diff options
Diffstat (limited to 'include/linux')
577 files changed, 19266 insertions, 11390 deletions
diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 268a4d91f54c..8b4e516bac00 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -10,6 +10,7 @@ #include <linux/errno.h> #include <linux/ioport.h> /* for struct resource */ +#include <linux/irqdomain.h> #include <linux/resource_ext.h> #include <linux/device.h> #include <linux/property.h> @@ -314,10 +315,19 @@ int acpi_isa_irq_to_gsi (unsigned isa_irq, u32 *gsi); void acpi_set_irq_model(enum acpi_irq_model_id model, struct fwnode_handle *fwnode); +struct irq_domain *acpi_irq_create_hierarchy(unsigned int flags, + unsigned int size, + struct fwnode_handle *fwnode, + const struct irq_domain_ops *ops, + void *host_data); + #ifdef CONFIG_X86_IO_APIC extern int acpi_get_override_irq(u32 gsi, int *trigger, int *polarity); #else -#define acpi_get_override_irq(gsi, trigger, polarity) (-1) +static inline int acpi_get_override_irq(u32 gsi, int *trigger, int *polarity) +{ + return -1; +} #endif /* * This function undoes the effect of one call to acpi_register_gsi(). @@ -367,6 +377,7 @@ extern acpi_status wmi_install_notify_handler(const char *guid, extern acpi_status wmi_remove_notify_handler(const char *guid); extern acpi_status wmi_get_event_data(u32 event, struct acpi_buffer *out); extern bool wmi_has_guid(const char *guid); +extern char *wmi_get_acpi_device_uid(const char *guid); #endif /* CONFIG_ACPI_WMI */ @@ -919,31 +930,25 @@ static inline int acpi_dev_pm_attach(struct device *dev, bool power_on) #endif #if defined(CONFIG_ACPI) && defined(CONFIG_PM_SLEEP) -int acpi_dev_suspend_late(struct device *dev); int acpi_subsys_prepare(struct device *dev); void acpi_subsys_complete(struct device *dev); int acpi_subsys_suspend_late(struct device *dev); int acpi_subsys_suspend_noirq(struct device *dev); -int acpi_subsys_resume_noirq(struct device *dev); -int acpi_subsys_resume_early(struct device *dev); int acpi_subsys_suspend(struct device *dev); int acpi_subsys_freeze(struct device *dev); -int acpi_subsys_freeze_late(struct device *dev); -int acpi_subsys_freeze_noirq(struct device *dev); -int acpi_subsys_thaw_noirq(struct device *dev); +int acpi_subsys_poweroff(struct device *dev); +void acpi_ec_mark_gpe_for_wake(void); +void acpi_ec_set_gpe_wake_mask(u8 action); #else -static inline int acpi_dev_resume_early(struct device *dev) { return 0; } static inline int acpi_subsys_prepare(struct device *dev) { return 0; } static inline void acpi_subsys_complete(struct device *dev) {} static inline int acpi_subsys_suspend_late(struct device *dev) { return 0; } static inline int acpi_subsys_suspend_noirq(struct device *dev) { return 0; } -static inline int acpi_subsys_resume_noirq(struct device *dev) { return 0; } -static inline int acpi_subsys_resume_early(struct device *dev) { return 0; } static inline int acpi_subsys_suspend(struct device *dev) { return 0; } static inline int acpi_subsys_freeze(struct device *dev) { return 0; } -static inline int acpi_subsys_freeze_late(struct device *dev) { return 0; } -static inline int acpi_subsys_freeze_noirq(struct device *dev) { return 0; } -static inline int acpi_subsys_thaw_noirq(struct device *dev) { return 0; } +static inline int acpi_subsys_poweroff(struct device *dev) { return 0; } +static inline void acpi_ec_mark_gpe_for_wake(void) {} +static inline void acpi_ec_set_gpe_wake_mask(u8 action) {} #endif #ifdef CONFIG_ACPI @@ -999,62 +1004,11 @@ void __acpi_handle_debug(struct _ddebug *descriptor, acpi_handle handle, const c #endif #endif -struct acpi_gpio_params { - unsigned int crs_entry_index; - unsigned int line_index; - bool active_low; -}; - -struct acpi_gpio_mapping { - const char *name; - const struct acpi_gpio_params *data; - unsigned int size; - -/* Ignore IoRestriction field */ -#define ACPI_GPIO_QUIRK_NO_IO_RESTRICTION BIT(0) -/* - * When ACPI GPIO mapping table is in use the index parameter inside it - * refers to the GPIO resource in _CRS method. That index has no - * distinction of actual type of the resource. When consumer wants to - * get GpioIo type explicitly, this quirk may be used. - */ -#define ACPI_GPIO_QUIRK_ONLY_GPIOIO BIT(1) - - unsigned int quirks; -}; - #if defined(CONFIG_ACPI) && defined(CONFIG_GPIOLIB) -int acpi_dev_add_driver_gpios(struct acpi_device *adev, - const struct acpi_gpio_mapping *gpios); - -static inline void acpi_dev_remove_driver_gpios(struct acpi_device *adev) -{ - if (adev) - adev->driver_gpios = NULL; -} - -int devm_acpi_dev_add_driver_gpios(struct device *dev, - const struct acpi_gpio_mapping *gpios); -void devm_acpi_dev_remove_driver_gpios(struct device *dev); - bool acpi_gpio_get_irq_resource(struct acpi_resource *ares, struct acpi_resource_gpio **agpio); int acpi_dev_gpio_irq_get(struct acpi_device *adev, int index); #else -static inline int acpi_dev_add_driver_gpios(struct acpi_device *adev, - const struct acpi_gpio_mapping *gpios) -{ - return -ENXIO; -} -static inline void acpi_dev_remove_driver_gpios(struct acpi_device *adev) {} - -static inline int devm_acpi_dev_add_driver_gpios(struct device *dev, - const struct acpi_gpio_mapping *gpios) -{ - return -ENXIO; -} -static inline void devm_acpi_dev_remove_driver_gpios(struct device *dev) {} - static inline bool acpi_gpio_get_irq_resource(struct acpi_resource *ares, struct acpi_resource_gpio **agpio) { @@ -1307,10 +1261,16 @@ static inline int lpit_read_residency_count_address(u64 *address) #endif #ifdef CONFIG_ACPI_PPTT +int acpi_pptt_cpu_is_thread(unsigned int cpu); int find_acpi_cpu_topology(unsigned int cpu, int level); int find_acpi_cpu_topology_package(unsigned int cpu); +int find_acpi_cpu_topology_hetero_id(unsigned int cpu); int find_acpi_cpu_cache_topology(unsigned int cpu, int level); #else +static inline int acpi_pptt_cpu_is_thread(unsigned int cpu) +{ + return -EINVAL; +} static inline int find_acpi_cpu_topology(unsigned int cpu, int level) { return -EINVAL; @@ -1319,6 +1279,10 @@ static inline int find_acpi_cpu_topology_package(unsigned int cpu) { return -EINVAL; } +static inline int find_acpi_cpu_topology_hetero_id(unsigned int cpu) +{ + return -EINVAL; +} static inline int find_acpi_cpu_cache_topology(unsigned int cpu, int level) { return -EINVAL; diff --git a/include/linux/alarmtimer.h b/include/linux/alarmtimer.h index 0760ca1cb009..74748e306f4b 100644 --- a/include/linux/alarmtimer.h +++ b/include/linux/alarmtimer.h @@ -5,7 +5,8 @@ #include <linux/time.h> #include <linux/hrtimer.h> #include <linux/timerqueue.h> -#include <linux/rtc.h> + +struct rtc_device; enum alarmtimer_type { ALARM_REALTIME, diff --git a/include/linux/amba/clcd-regs.h b/include/linux/amba/clcd-regs.h index 516a6fda83c5..421b0fa90d6a 100644 --- a/include/linux/amba/clcd-regs.h +++ b/include/linux/amba/clcd-regs.h @@ -42,6 +42,7 @@ #define TIM2_PCD_LO_MASK GENMASK(4, 0) #define TIM2_PCD_LO_BITS 5 #define TIM2_CLKSEL (1 << 5) +#define TIM2_ACB_MASK GENMASK(10, 6) #define TIM2_IVS (1 << 11) #define TIM2_IHS (1 << 12) #define TIM2_IPC (1 << 13) diff --git a/include/linux/amd-iommu.h b/include/linux/amd-iommu.h index 4a4d00646040..21e950e4ab62 100644 --- a/include/linux/amd-iommu.h +++ b/include/linux/amd-iommu.h @@ -184,6 +184,9 @@ extern int amd_iommu_register_ga_log_notifier(int (*notifier)(u32)); extern int amd_iommu_update_ga(int cpu, bool is_run, void *data); +extern int amd_iommu_activate_guest_mode(void *data); +extern int amd_iommu_deactivate_guest_mode(void *data); + #else /* defined(CONFIG_AMD_IOMMU) && defined(CONFIG_IRQ_REMAP) */ static inline int @@ -198,6 +201,15 @@ amd_iommu_update_ga(int cpu, bool is_run, void *data) return 0; } +static inline int amd_iommu_activate_guest_mode(void *data) +{ + return 0; +} + +static inline int amd_iommu_deactivate_guest_mode(void *data) +{ + return 0; +} #endif /* defined(CONFIG_AMD_IOMMU) && defined(CONFIG_IRQ_REMAP) */ #endif /* _ASM_X86_AMD_IOMMU_H */ diff --git a/include/linux/arch_topology.h b/include/linux/arch_topology.h index d9bdc1a7f4e7..42f2b5126094 100644 --- a/include/linux/arch_topology.h +++ b/include/linux/arch_topology.h @@ -18,7 +18,7 @@ DECLARE_PER_CPU(unsigned long, cpu_scale); struct sched_domain; static inline -unsigned long topology_get_cpu_scale(struct sched_domain *sd, int cpu) +unsigned long topology_get_cpu_scale(int cpu) { return per_cpu(cpu_scale, cpu); } @@ -33,4 +33,30 @@ unsigned long topology_get_freq_scale(int cpu) return per_cpu(freq_scale, cpu); } +struct cpu_topology { + int thread_id; + int core_id; + int package_id; + int llc_id; + cpumask_t thread_sibling; + cpumask_t core_sibling; + cpumask_t llc_sibling; +}; + +#ifdef CONFIG_GENERIC_ARCH_TOPOLOGY +extern struct cpu_topology cpu_topology[NR_CPUS]; + +#define topology_physical_package_id(cpu) (cpu_topology[cpu].package_id) +#define topology_core_id(cpu) (cpu_topology[cpu].core_id) +#define topology_core_cpumask(cpu) (&cpu_topology[cpu].core_sibling) +#define topology_sibling_cpumask(cpu) (&cpu_topology[cpu].thread_sibling) +#define topology_llc_cpumask(cpu) (&cpu_topology[cpu].llc_sibling) +void init_cpu_topology(void); +void store_cpu_topology(unsigned int cpuid); +const struct cpumask *cpu_coregroup_mask(int cpu); +void update_siblings_masks(unsigned int cpu); +void remove_cpu_topology(unsigned int cpuid); +void reset_cpu_topology(void); +#endif + #endif /* _LINUX_ARCH_TOPOLOGY_H_ */ diff --git a/include/linux/audit.h b/include/linux/audit.h index 3a4f2415bb7c..aee3dc9eb378 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h @@ -11,7 +11,6 @@ #include <linux/sched.h> #include <linux/ptrace.h> -#include <linux/namei.h> /* LOOKUP_* */ #include <uapi/linux/audit.h> #define AUDIT_INO_UNSET ((unsigned long)-1) @@ -182,6 +181,9 @@ static inline unsigned int audit_get_sessionid(struct task_struct *tsk) } extern u32 audit_enabled; + +extern int audit_signal_info(int sig, struct task_struct *t); + #else /* CONFIG_AUDIT */ static inline __printf(4, 5) void audit_log(struct audit_context *ctx, gfp_t gfp_mask, int type, @@ -235,6 +237,12 @@ static inline unsigned int audit_get_sessionid(struct task_struct *tsk) } #define audit_enabled AUDIT_OFF + +static inline int audit_signal_info(int sig, struct task_struct *t) +{ + return 0; +} + #endif /* CONFIG_AUDIT */ #ifdef CONFIG_AUDIT_COMPAT_GENERIC @@ -243,6 +251,10 @@ static inline unsigned int audit_get_sessionid(struct task_struct *tsk) #define audit_is_compat(arch) false #endif +#define AUDIT_INODE_PARENT 1 /* dentry represents the parent */ +#define AUDIT_INODE_HIDDEN 2 /* audit record should be hidden */ +#define AUDIT_INODE_NOEVAL 4 /* audit record incomplete */ + #ifdef CONFIG_AUDITSYSCALL #include <asm/syscall.h> /* for syscall_get_arch() */ @@ -256,9 +268,6 @@ extern void __audit_syscall_exit(int ret_success, long ret_value); extern struct filename *__audit_reusename(const __user char *uptr); extern void __audit_getname(struct filename *name); -#define AUDIT_INODE_PARENT 1 /* dentry represents the parent */ -#define AUDIT_INODE_HIDDEN 2 /* audit record should be hidden */ -#define AUDIT_INODE_NOEVAL 4 /* audit record incomplete */ extern void __audit_inode(struct filename *name, const struct dentry *dentry, unsigned int flags); extern void __audit_file(const struct file *); @@ -319,16 +328,9 @@ static inline void audit_getname(struct filename *name) } static inline void audit_inode(struct filename *name, const struct dentry *dentry, - unsigned int flags) { - if (unlikely(!audit_dummy_context())) { - unsigned int aflags = 0; - - if (flags & LOOKUP_PARENT) - aflags |= AUDIT_INODE_PARENT; - if (flags & LOOKUP_NO_EVAL) - aflags |= AUDIT_INODE_NOEVAL; + unsigned int aflags) { + if (unlikely(!audit_dummy_context())) __audit_inode(name, dentry, aflags); - } } static inline void audit_file(struct file *file) { @@ -552,7 +554,7 @@ static inline void __audit_inode_child(struct inode *parent, { } static inline void audit_inode(struct filename *name, const struct dentry *dentry, - unsigned int parent) + unsigned int aflags) { } static inline void audit_file(struct file *file) { diff --git a/include/linux/avf/virtchnl.h b/include/linux/avf/virtchnl.h index 191621ff7594..ca956b672ac0 100644 --- a/include/linux/avf/virtchnl.h +++ b/include/linux/avf/virtchnl.h @@ -61,12 +61,14 @@ enum virtchnl_status_code { #define VIRTCHNL_ERR_PARAM VIRTCHNL_STATUS_ERR_PARAM #define VIRTCHNL_STATUS_NOT_SUPPORTED VIRTCHNL_STATUS_ERR_NOT_SUPPORTED +#define VIRTCHNL_LINK_SPEED_2_5GB_SHIFT 0x0 #define VIRTCHNL_LINK_SPEED_100MB_SHIFT 0x1 #define VIRTCHNL_LINK_SPEED_1000MB_SHIFT 0x2 #define VIRTCHNL_LINK_SPEED_10GB_SHIFT 0x3 #define VIRTCHNL_LINK_SPEED_40GB_SHIFT 0x4 #define VIRTCHNL_LINK_SPEED_20GB_SHIFT 0x5 #define VIRTCHNL_LINK_SPEED_25GB_SHIFT 0x6 +#define VIRTCHNL_LINK_SPEED_5GB_SHIFT 0x7 enum virtchnl_link_speed { VIRTCHNL_LINK_SPEED_UNKNOWN = 0, @@ -76,6 +78,8 @@ enum virtchnl_link_speed { VIRTCHNL_LINK_SPEED_40GB = BIT(VIRTCHNL_LINK_SPEED_40GB_SHIFT), VIRTCHNL_LINK_SPEED_20GB = BIT(VIRTCHNL_LINK_SPEED_20GB_SHIFT), VIRTCHNL_LINK_SPEED_25GB = BIT(VIRTCHNL_LINK_SPEED_25GB_SHIFT), + VIRTCHNL_LINK_SPEED_2_5GB = BIT(VIRTCHNL_LINK_SPEED_2_5GB_SHIFT), + VIRTCHNL_LINK_SPEED_5GB = BIT(VIRTCHNL_LINK_SPEED_5GB_SHIFT), }; /* for hsplit_0 field of Rx HMC context */ diff --git a/include/linux/backing-dev-defs.h b/include/linux/backing-dev-defs.h index 07e02d6df5ad..4fc87dee005a 100644 --- a/include/linux/backing-dev-defs.h +++ b/include/linux/backing-dev-defs.h @@ -63,10 +63,31 @@ enum wb_reason { * so it has a mismatch name. */ WB_REASON_FORKER_THREAD, + WB_REASON_FOREIGN_FLUSH, WB_REASON_MAX, }; +struct wb_completion { + atomic_t cnt; + wait_queue_head_t *waitq; +}; + +#define __WB_COMPLETION_INIT(_waitq) \ + (struct wb_completion){ .cnt = ATOMIC_INIT(1), .waitq = (_waitq) } + +/* + * If one wants to wait for one or more wb_writeback_works, each work's + * ->done should be set to a wb_completion defined using the following + * macro. Once all work items are issued with wb_queue_work(), the caller + * can wait for the completion of all using wb_wait_for_completion(). Work + * items which are waited upon aren't freed automatically on completion. + */ +#define WB_COMPLETION_INIT(bdi) __WB_COMPLETION_INIT(&(bdi)->wb_waitq) + +#define DEFINE_WB_COMPLETION(cmpl, bdi) \ + struct wb_completion cmpl = WB_COMPLETION_INIT(bdi) + /* * For cgroup writeback, multiple wb's may map to the same blkcg. Those * wb's can operate mostly independently but should share the congested @@ -165,6 +186,8 @@ struct bdi_writeback { }; struct backing_dev_info { + u64 id; + struct rb_node rb_node; /* keyed by ->id */ struct list_head bdi_list; unsigned long ra_pages; /* max readahead in PAGE_SIZE units */ unsigned long io_pages; /* max allowed IO size */ @@ -203,7 +226,6 @@ struct backing_dev_info { #ifdef CONFIG_DEBUG_FS struct dentry *debug_dir; - struct dentry *debug_stats; #endif }; diff --git a/include/linux/backing-dev.h b/include/linux/backing-dev.h index f9b029180241..97967ce06de3 100644 --- a/include/linux/backing-dev.h +++ b/include/linux/backing-dev.h @@ -24,6 +24,7 @@ static inline struct backing_dev_info *bdi_get(struct backing_dev_info *bdi) return bdi; } +struct backing_dev_info *bdi_get_by_id(u64 id); void bdi_put(struct backing_dev_info *bdi); __printf(2, 3) @@ -44,10 +45,13 @@ void wb_start_background_writeback(struct bdi_writeback *wb); void wb_workfn(struct work_struct *work); void wb_wakeup_delayed(struct bdi_writeback *wb); +void wb_wait_for_completion(struct wb_completion *done); + extern spinlock_t bdi_lock; extern struct list_head bdi_list; extern struct workqueue_struct *bdi_wq; +extern struct workqueue_struct *bdi_async_bio_wq; static inline bool wb_has_dirty_io(struct bdi_writeback *wb) { @@ -226,6 +230,8 @@ static inline int bdi_sched_wait(void *word) struct bdi_writeback_congested * wb_congested_get_create(struct backing_dev_info *bdi, int blkcg_id, gfp_t gfp); void wb_congested_put(struct bdi_writeback_congested *congested); +struct bdi_writeback *wb_get_lookup(struct backing_dev_info *bdi, + struct cgroup_subsys_state *memcg_css); struct bdi_writeback *wb_get_create(struct backing_dev_info *bdi, struct cgroup_subsys_state *memcg_css, gfp_t gfp); diff --git a/include/linux/backlight.h b/include/linux/backlight.h index 0b5897446dca..c7d6b2e8c3b5 100644 --- a/include/linux/backlight.h +++ b/include/linux/backlight.h @@ -46,6 +46,12 @@ enum backlight_notification { BACKLIGHT_UNREGISTERED, }; +enum backlight_scale { + BACKLIGHT_SCALE_UNKNOWN = 0, + BACKLIGHT_SCALE_LINEAR, + BACKLIGHT_SCALE_NON_LINEAR, +}; + struct backlight_device; struct fb_info; @@ -80,6 +86,8 @@ struct backlight_properties { enum backlight_type type; /* Flags used to signal drivers of state changes */ unsigned int state; + /* Type of the brightness scale (linear, non-linear, ...) */ + enum backlight_scale scale; #define BL_CORE_SUSPENDED (1 << 0) /* backlight is suspended */ #define BL_CORE_FBBLANK (1 << 1) /* backlight is under an fb blank event */ diff --git a/include/linux/balloon_compaction.h b/include/linux/balloon_compaction.h index f31521dcb09a..338aa27e4773 100644 --- a/include/linux/balloon_compaction.h +++ b/include/linux/balloon_compaction.h @@ -64,6 +64,10 @@ extern struct page *balloon_page_alloc(void); extern void balloon_page_enqueue(struct balloon_dev_info *b_dev_info, struct page *page); extern struct page *balloon_page_dequeue(struct balloon_dev_info *b_dev_info); +extern size_t balloon_page_list_enqueue(struct balloon_dev_info *b_dev_info, + struct list_head *pages); +extern size_t balloon_page_list_dequeue(struct balloon_dev_info *b_dev_info, + struct list_head *pages, size_t n_req_pages); static inline void balloon_devinfo_init(struct balloon_dev_info *balloon) { diff --git a/include/linux/bio.h b/include/linux/bio.h index f87abaa898f0..3cdb84cdc488 100644 --- a/include/linux/bio.h +++ b/include/linux/bio.h @@ -102,9 +102,23 @@ static inline void *bio_data(struct bio *bio) return NULL; } -static inline bool bio_full(struct bio *bio) +/** + * bio_full - check if the bio is full + * @bio: bio to check + * @len: length of one segment to be added + * + * Return true if @bio is full and one segment with @len bytes can't be + * added to the bio, otherwise return false + */ +static inline bool bio_full(struct bio *bio, unsigned len) { - return bio->bi_vcnt >= bio->bi_max_vecs; + if (bio->bi_vcnt >= bio->bi_max_vecs) + return true; + + if (bio->bi_iter.bi_size > UINT_MAX - len) + return true; + + return false; } static inline bool bio_next_segment(const struct bio *bio, @@ -408,7 +422,6 @@ static inline void bio_wouldblock_error(struct bio *bio) } struct request_queue; -extern int bio_phys_segments(struct request_queue *, struct bio *); extern int submit_bio_wait(struct bio *bio); extern void bio_advance(struct bio *, unsigned); @@ -427,6 +440,7 @@ bool __bio_try_merge_page(struct bio *bio, struct page *page, void __bio_add_page(struct bio *bio, struct page *page, unsigned int len, unsigned int off); int bio_iov_iter_get_pages(struct bio *bio, struct iov_iter *iter); +void bio_release_pages(struct bio *bio, bool mark_dirty); struct rq_map_data; extern struct bio *bio_map_user_iov(struct request_queue *, struct iov_iter *, gfp_t); @@ -444,17 +458,6 @@ void generic_end_io_acct(struct request_queue *q, int op, struct hd_struct *part, unsigned long start_time); -#ifndef ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE -# error "You should define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE for your platform" -#endif -#if ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE -extern void bio_flush_dcache_pages(struct bio *bi); -#else -static inline void bio_flush_dcache_pages(struct bio *bi) -{ -} -#endif - extern void bio_copy_data_iter(struct bio *dst, struct bvec_iter *dst_iter, struct bio *src, struct bvec_iter *src_iter); extern void bio_copy_data(struct bio *dst, struct bio *src); diff --git a/include/linux/bitmap.h b/include/linux/bitmap.h index f58e97446abc..90528f12bdfa 100644 --- a/include/linux/bitmap.h +++ b/include/linux/bitmap.h @@ -120,6 +120,10 @@ extern int __bitmap_empty(const unsigned long *bitmap, unsigned int nbits); extern int __bitmap_full(const unsigned long *bitmap, unsigned int nbits); extern int __bitmap_equal(const unsigned long *bitmap1, const unsigned long *bitmap2, unsigned int nbits); +extern bool __pure __bitmap_or_equal(const unsigned long *src1, + const unsigned long *src2, + const unsigned long *src3, + unsigned int nbits); extern void __bitmap_complement(unsigned long *dst, const unsigned long *src, unsigned int nbits); extern void __bitmap_shift_right(unsigned long *dst, const unsigned long *src, @@ -321,6 +325,25 @@ static inline int bitmap_equal(const unsigned long *src1, return __bitmap_equal(src1, src2, nbits); } +/** + * bitmap_or_equal - Check whether the or of two bitnaps is equal to a third + * @src1: Pointer to bitmap 1 + * @src2: Pointer to bitmap 2 will be or'ed with bitmap 1 + * @src3: Pointer to bitmap 3. Compare to the result of *@src1 | *@src2 + * + * Returns: True if (*@src1 | *@src2) == *@src3, false otherwise + */ +static inline bool bitmap_or_equal(const unsigned long *src1, + const unsigned long *src2, + const unsigned long *src3, + unsigned int nbits) +{ + if (!small_const_nbits(nbits)) + return __bitmap_or_equal(src1, src2, src3, nbits); + + return !(((*src1 | *src2) ^ *src3) & BITMAP_LAST_WORD_MASK(nbits)); +} + static inline int bitmap_intersects(const unsigned long *src1, const unsigned long *src2, unsigned int nbits) { diff --git a/include/linux/bits.h b/include/linux/bits.h index 2b7b532c1d51..669d69441a62 100644 --- a/include/linux/bits.h +++ b/include/linux/bits.h @@ -1,13 +1,15 @@ /* SPDX-License-Identifier: GPL-2.0 */ #ifndef __LINUX_BITS_H #define __LINUX_BITS_H + +#include <linux/const.h> #include <asm/bitsperlong.h> -#define BIT(nr) (1UL << (nr)) -#define BIT_ULL(nr) (1ULL << (nr)) -#define BIT_MASK(nr) (1UL << ((nr) % BITS_PER_LONG)) +#define BIT(nr) (UL(1) << (nr)) +#define BIT_ULL(nr) (ULL(1) << (nr)) +#define BIT_MASK(nr) (UL(1) << ((nr) % BITS_PER_LONG)) #define BIT_WORD(nr) ((nr) / BITS_PER_LONG) -#define BIT_ULL_MASK(nr) (1ULL << ((nr) % BITS_PER_LONG_LONG)) +#define BIT_ULL_MASK(nr) (ULL(1) << ((nr) % BITS_PER_LONG_LONG)) #define BIT_ULL_WORD(nr) ((nr) / BITS_PER_LONG_LONG) #define BITS_PER_BYTE 8 @@ -17,10 +19,11 @@ * GENMASK_ULL(39, 21) gives us the 64bit vector 0x000000ffffe00000. */ #define GENMASK(h, l) \ - (((~0UL) - (1UL << (l)) + 1) & (~0UL >> (BITS_PER_LONG - 1 - (h)))) + (((~UL(0)) - (UL(1) << (l)) + 1) & \ + (~UL(0) >> (BITS_PER_LONG - 1 - (h)))) #define GENMASK_ULL(h, l) \ - (((~0ULL) - (1ULL << (l)) + 1) & \ - (~0ULL >> (BITS_PER_LONG_LONG - 1 - (h)))) + (((~ULL(0)) - (ULL(1) << (l)) + 1) & \ + (~ULL(0) >> (BITS_PER_LONG_LONG - 1 - (h)))) #endif /* __LINUX_BITS_H */ diff --git a/include/linux/blk-cgroup.h b/include/linux/blk-cgroup.h index 76c61318fda5..bed9e43f9426 100644 --- a/include/linux/blk-cgroup.h +++ b/include/linux/blk-cgroup.h @@ -63,19 +63,17 @@ struct blkcg { /* * blkg_[rw]stat->aux_cnt is excluded for local stats but included for - * recursive. Used to carry stats of dead children, and, for blkg_rwstat, - * to carry result values from read and sum operations. + * recursive. Used to carry stats of dead children. */ -struct blkg_stat { - struct percpu_counter cpu_cnt; - atomic64_t aux_cnt; -}; - struct blkg_rwstat { struct percpu_counter cpu_cnt[BLKG_RWSTAT_NR]; atomic64_t aux_cnt[BLKG_RWSTAT_NR]; }; +struct blkg_rwstat_sample { + u64 cnt[BLKG_RWSTAT_NR]; +}; + /* * A blkcg_gq (blkg) is association between a block cgroup (blkcg) and a * request_queue (q). This is used by blkcg policies which need to track @@ -134,20 +132,25 @@ struct blkcg_gq { struct blkg_policy_data *pd[BLKCG_MAX_POLS]; - struct rcu_head rcu_head; + spinlock_t async_bio_lock; + struct bio_list async_bios; + struct work_struct async_bio_work; atomic_t use_delay; atomic64_t delay_nsec; atomic64_t delay_start; u64 last_delay; int last_use; + + struct rcu_head rcu_head; }; typedef struct blkcg_policy_data *(blkcg_pol_alloc_cpd_fn)(gfp_t gfp); typedef void (blkcg_pol_init_cpd_fn)(struct blkcg_policy_data *cpd); typedef void (blkcg_pol_free_cpd_fn)(struct blkcg_policy_data *cpd); typedef void (blkcg_pol_bind_cpd_fn)(struct blkcg_policy_data *cpd); -typedef struct blkg_policy_data *(blkcg_pol_alloc_pd_fn)(gfp_t gfp, int node); +typedef struct blkg_policy_data *(blkcg_pol_alloc_pd_fn)(gfp_t gfp, + struct request_queue *q, struct blkcg *blkcg); typedef void (blkcg_pol_init_pd_fn)(struct blkg_policy_data *pd); typedef void (blkcg_pol_online_pd_fn)(struct blkg_policy_data *pd); typedef void (blkcg_pol_offline_pd_fn)(struct blkg_policy_data *pd); @@ -179,6 +182,7 @@ struct blkcg_policy { extern struct blkcg blkcg_root; extern struct cgroup_subsys_state * const blkcg_root_css; +extern bool blkcg_debug_stats; struct blkcg_gq *blkg_lookup_slowpath(struct blkcg *blkcg, struct request_queue *q, bool update_hint); @@ -198,6 +202,13 @@ int blkcg_activate_policy(struct request_queue *q, void blkcg_deactivate_policy(struct request_queue *q, const struct blkcg_policy *pol); +static inline u64 blkg_rwstat_read_counter(struct blkg_rwstat *rwstat, + unsigned int idx) +{ + return atomic64_read(&rwstat->aux_cnt[idx]) + + percpu_counter_sum_positive(&rwstat->cpu_cnt[idx]); +} + const char *blkg_dev_name(struct blkcg_gq *blkg); void blkcg_print_blkgs(struct seq_file *sf, struct blkcg *blkcg, u64 (*prfill)(struct seq_file *, @@ -206,8 +217,7 @@ void blkcg_print_blkgs(struct seq_file *sf, struct blkcg *blkcg, bool show_total); u64 __blkg_prfill_u64(struct seq_file *sf, struct blkg_policy_data *pd, u64 v); u64 __blkg_prfill_rwstat(struct seq_file *sf, struct blkg_policy_data *pd, - const struct blkg_rwstat *rwstat); -u64 blkg_prfill_stat(struct seq_file *sf, struct blkg_policy_data *pd, int off); + const struct blkg_rwstat_sample *rwstat); u64 blkg_prfill_rwstat(struct seq_file *sf, struct blkg_policy_data *pd, int off); int blkg_print_stat_bytes(struct seq_file *sf, void *v); @@ -215,10 +225,8 @@ int blkg_print_stat_ios(struct seq_file *sf, void *v); int blkg_print_stat_bytes_recursive(struct seq_file *sf, void *v); int blkg_print_stat_ios_recursive(struct seq_file *sf, void *v); -u64 blkg_stat_recursive_sum(struct blkcg_gq *blkg, - struct blkcg_policy *pol, int off); -struct blkg_rwstat blkg_rwstat_recursive_sum(struct blkcg_gq *blkg, - struct blkcg_policy *pol, int off); +void blkg_rwstat_recursive_sum(struct blkcg_gq *blkg, struct blkcg_policy *pol, + int off, struct blkg_rwstat_sample *sum); struct blkg_conf_ctx { struct gendisk *disk; @@ -226,6 +234,7 @@ struct blkg_conf_ctx { char *body; }; +struct gendisk *blkcg_conf_get_disk(char **inputp); int blkg_conf_prep(struct blkcg *blkcg, const struct blkcg_policy *pol, char *input, struct blkg_conf_ctx *ctx); void blkg_conf_finish(struct blkg_conf_ctx *ctx); @@ -368,7 +377,7 @@ static inline struct blkcg_gq *__blkg_lookup(struct blkcg *blkcg, * @q: request_queue of interest * * Lookup blkg for the @blkcg - @q pair. This function should be called - * under RCU read loc. + * under RCU read lock. */ static inline struct blkcg_gq *blkg_lookup(struct blkcg *blkcg, struct request_queue *q) @@ -569,69 +578,6 @@ static inline void blkg_put(struct blkcg_gq *blkg) if (((d_blkg) = __blkg_lookup(css_to_blkcg(pos_css), \ (p_blkg)->q, false))) -static inline int blkg_stat_init(struct blkg_stat *stat, gfp_t gfp) -{ - int ret; - - ret = percpu_counter_init(&stat->cpu_cnt, 0, gfp); - if (ret) - return ret; - - atomic64_set(&stat->aux_cnt, 0); - return 0; -} - -static inline void blkg_stat_exit(struct blkg_stat *stat) -{ - percpu_counter_destroy(&stat->cpu_cnt); -} - -/** - * blkg_stat_add - add a value to a blkg_stat - * @stat: target blkg_stat - * @val: value to add - * - * Add @val to @stat. The caller must ensure that IRQ on the same CPU - * don't re-enter this function for the same counter. - */ -static inline void blkg_stat_add(struct blkg_stat *stat, uint64_t val) -{ - percpu_counter_add_batch(&stat->cpu_cnt, val, BLKG_STAT_CPU_BATCH); -} - -/** - * blkg_stat_read - read the current value of a blkg_stat - * @stat: blkg_stat to read - */ -static inline uint64_t blkg_stat_read(struct blkg_stat *stat) -{ - return percpu_counter_sum_positive(&stat->cpu_cnt); -} - -/** - * blkg_stat_reset - reset a blkg_stat - * @stat: blkg_stat to reset - */ -static inline void blkg_stat_reset(struct blkg_stat *stat) -{ - percpu_counter_set(&stat->cpu_cnt, 0); - atomic64_set(&stat->aux_cnt, 0); -} - -/** - * blkg_stat_add_aux - add a blkg_stat into another's aux count - * @to: the destination blkg_stat - * @from: the source - * - * Add @from's count including the aux one to @to's aux count. - */ -static inline void blkg_stat_add_aux(struct blkg_stat *to, - struct blkg_stat *from) -{ - atomic64_add(blkg_stat_read(from) + atomic64_read(&from->aux_cnt), - &to->aux_cnt); -} - static inline int blkg_rwstat_init(struct blkg_rwstat *rwstat, gfp_t gfp) { int i, ret; @@ -693,15 +639,14 @@ static inline void blkg_rwstat_add(struct blkg_rwstat *rwstat, * * Read the current snapshot of @rwstat and return it in the aux counts. */ -static inline struct blkg_rwstat blkg_rwstat_read(struct blkg_rwstat *rwstat) +static inline void blkg_rwstat_read(struct blkg_rwstat *rwstat, + struct blkg_rwstat_sample *result) { - struct blkg_rwstat result; int i; for (i = 0; i < BLKG_RWSTAT_NR; i++) - atomic64_set(&result.aux_cnt[i], - percpu_counter_sum_positive(&rwstat->cpu_cnt[i])); - return result; + result->cnt[i] = + percpu_counter_sum_positive(&rwstat->cpu_cnt[i]); } /** @@ -714,10 +659,10 @@ static inline struct blkg_rwstat blkg_rwstat_read(struct blkg_rwstat *rwstat) */ static inline uint64_t blkg_rwstat_total(struct blkg_rwstat *rwstat) { - struct blkg_rwstat tmp = blkg_rwstat_read(rwstat); + struct blkg_rwstat_sample tmp = { }; - return atomic64_read(&tmp.aux_cnt[BLKG_RWSTAT_READ]) + - atomic64_read(&tmp.aux_cnt[BLKG_RWSTAT_WRITE]); + blkg_rwstat_read(rwstat, &tmp); + return tmp.cnt[BLKG_RWSTAT_READ] + tmp.cnt[BLKG_RWSTAT_WRITE]; } /** @@ -763,6 +708,15 @@ static inline bool blk_throtl_bio(struct request_queue *q, struct blkcg_gq *blkg struct bio *bio) { return false; } #endif +bool __blkcg_punt_bio_submit(struct bio *bio); + +static inline bool blkcg_punt_bio_submit(struct bio *bio) +{ + if (bio->bi_opf & REQ_CGROUP_PUNT) + return __blkcg_punt_bio_submit(bio); + else + return false; +} static inline void blkcg_bio_issue_init(struct bio *bio) { @@ -910,6 +864,7 @@ static inline char *blkg_path(struct blkcg_gq *blkg) { return NULL; } static inline void blkg_get(struct blkcg_gq *blkg) { } static inline void blkg_put(struct blkcg_gq *blkg) { } +static inline bool blkcg_punt_bio_submit(struct bio *bio) { return false; } static inline void blkcg_bio_issue_init(struct bio *bio) { } static inline bool blkcg_bio_issue_check(struct request_queue *q, struct bio *bio) { return true; } diff --git a/include/linux/blk-mq.h b/include/linux/blk-mq.h index 15d1aa53d96c..0bf056de5cc3 100644 --- a/include/linux/blk-mq.h +++ b/include/linux/blk-mq.h @@ -140,6 +140,7 @@ typedef int (poll_fn)(struct blk_mq_hw_ctx *); typedef int (map_queues_fn)(struct blk_mq_tag_set *set); typedef bool (busy_fn)(struct request_queue *); typedef void (complete_fn)(struct request *); +typedef void (cleanup_rq_fn)(struct request *); struct blk_mq_ops { @@ -201,6 +202,12 @@ struct blk_mq_ops { void (*initialize_rq_fn)(struct request *rq); /* + * Called before freeing one request which isn't completed yet, + * and usually for freeing the driver private data + */ + cleanup_rq_fn *cleanup_rq; + + /* * If set, returns whether or not this queue currently is busy */ busy_fn *busy; @@ -241,12 +248,12 @@ enum { struct request_queue *blk_mq_init_queue(struct blk_mq_tag_set *); struct request_queue *blk_mq_init_allocated_queue(struct blk_mq_tag_set *set, - struct request_queue *q); + struct request_queue *q, + bool elevator_init); struct request_queue *blk_mq_init_sq_queue(struct blk_mq_tag_set *set, const struct blk_mq_ops *ops, unsigned int queue_depth, unsigned int set_flags); -int blk_mq_register_dev(struct device *, struct request_queue *); void blk_mq_unregister_dev(struct device *, struct request_queue *); int blk_mq_alloc_tag_set(struct blk_mq_tag_set *set); @@ -296,6 +303,7 @@ static inline u16 blk_mq_unique_tag_to_tag(u32 unique_tag) int blk_mq_request_started(struct request *rq); +int blk_mq_request_completed(struct request *rq); void blk_mq_start_request(struct request *rq); void blk_mq_end_request(struct request *rq, blk_status_t error); void __blk_mq_end_request(struct request *rq, blk_status_t error); @@ -304,9 +312,8 @@ void blk_mq_requeue_request(struct request *rq, bool kick_requeue_list); void blk_mq_kick_requeue_list(struct request_queue *q); void blk_mq_delay_kick_requeue_list(struct request_queue *q, unsigned long msecs); bool blk_mq_complete_request(struct request *rq); -void blk_mq_complete_request_sync(struct request *rq); bool blk_mq_bio_list_merge(struct request_queue *q, struct list_head *list, - struct bio *bio); + struct bio *bio, unsigned int nr_segs); bool blk_mq_queue_stopped(struct request_queue *q); void blk_mq_stop_hw_queue(struct blk_mq_hw_ctx *hctx); void blk_mq_start_hw_queue(struct blk_mq_hw_ctx *hctx); @@ -321,6 +328,7 @@ bool blk_mq_run_hw_queue(struct blk_mq_hw_ctx *hctx, bool async); void blk_mq_run_hw_queues(struct request_queue *q, bool async); void blk_mq_tagset_busy_iter(struct blk_mq_tag_set *tagset, busy_tag_iter_fn *fn, void *priv); +void blk_mq_tagset_wait_completed_request(struct blk_mq_tag_set *tagset); void blk_mq_freeze_queue(struct request_queue *q); void blk_mq_unfreeze_queue(struct request_queue *q); void blk_freeze_queue_start(struct request_queue *q); @@ -366,4 +374,10 @@ static inline blk_qc_t request_to_qc_t(struct blk_mq_hw_ctx *hctx, BLK_QC_T_INTERNAL; } +static inline void blk_mq_cleanup_rq(struct request *rq) +{ + if (rq->q->mq_ops->cleanup_rq) + rq->q->mq_ops->cleanup_rq(rq); +} + #endif diff --git a/include/linux/blk_types.h b/include/linux/blk_types.h index 95202f80676c..d688b96d1d63 100644 --- a/include/linux/blk_types.h +++ b/include/linux/blk_types.h @@ -154,11 +154,6 @@ struct bio { blk_status_t bi_status; u8 bi_partno; - /* Number of segments in this BIO after - * physical address coalescing is performed. - */ - unsigned int bi_phys_segments; - struct bvec_iter bi_iter; atomic_t __bi_remaining; @@ -174,6 +169,9 @@ struct bio { */ struct blkcg_gq *bi_blkg; struct bio_issue bi_issue; +#ifdef CONFIG_BLK_CGROUP_IOCOST + u64 bi_iocost_cost; +#endif #endif union { #if defined(CONFIG_BLK_DEV_INTEGRITY) @@ -210,11 +208,11 @@ struct bio { */ enum { BIO_NO_PAGE_REF, /* don't put release vec pages */ - BIO_SEG_VALID, /* bi_phys_segments valid */ BIO_CLONED, /* doesn't own data */ BIO_BOUNCED, /* bio is a bounce bio */ BIO_USER_MAPPED, /* contains user pages */ BIO_NULL_MAPPED, /* contains invalid user pages */ + BIO_WORKINGSET, /* contains userspace workingset pages */ BIO_QUIET, /* Make BIO Quiet */ BIO_CHAIN, /* chained bio, ->bi_remaining in effect */ BIO_REFFED, /* bio has elevated ->bi_cnt */ @@ -288,6 +286,8 @@ enum req_opf { REQ_OP_ZONE_RESET = 6, /* write the same sector many times */ REQ_OP_WRITE_SAME = 7, + /* reset all the zone present on the device */ + REQ_OP_ZONE_RESET_ALL = 8, /* write the zero filled sector many times */ REQ_OP_WRITE_ZEROES = 9, @@ -317,6 +317,15 @@ enum req_flag_bits { __REQ_RAHEAD, /* read ahead, can fail anytime */ __REQ_BACKGROUND, /* background IO */ __REQ_NOWAIT, /* Don't wait if request will block */ + __REQ_NOWAIT_INLINE, /* Return would-block error inline */ + /* + * When a shared kthread needs to issue a bio for a cgroup, doing + * so synchronously can lead to priority inversions as the kthread + * can be trapped waiting for that cgroup. CGROUP_PUNT flag makes + * submit_bio() punt the actual issuing to a dedicated per-blkcg + * work item to avoid such priority inversions. + */ + __REQ_CGROUP_PUNT, /* command specific flags for REQ_OP_WRITE_ZEROES: */ __REQ_NOUNMAP, /* do not free blocks when zeroing */ @@ -343,6 +352,9 @@ enum req_flag_bits { #define REQ_RAHEAD (1ULL << __REQ_RAHEAD) #define REQ_BACKGROUND (1ULL << __REQ_BACKGROUND) #define REQ_NOWAIT (1ULL << __REQ_NOWAIT) +#define REQ_NOWAIT_INLINE (1ULL << __REQ_NOWAIT_INLINE) +#define REQ_CGROUP_PUNT (1ULL << __REQ_CGROUP_PUNT) + #define REQ_NOUNMAP (1ULL << __REQ_NOUNMAP) #define REQ_HIPRI (1ULL << __REQ_HIPRI) @@ -414,12 +426,13 @@ static inline int op_stat_group(unsigned int op) typedef unsigned int blk_qc_t; #define BLK_QC_T_NONE -1U +#define BLK_QC_T_EAGAIN -2U #define BLK_QC_T_SHIFT 16 #define BLK_QC_T_INTERNAL (1U << 31) static inline bool blk_qc_t_valid(blk_qc_t cookie) { - return cookie != BLK_QC_T_NONE; + return cookie != BLK_QC_T_NONE && cookie != BLK_QC_T_EAGAIN; } static inline unsigned int blk_qc_t_to_queue_num(blk_qc_t cookie) diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 592669bcc536..f3ea78b0c91c 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -137,11 +137,11 @@ struct request { unsigned int cmd_flags; /* op and common flags */ req_flags_t rq_flags; + int tag; int internal_tag; /* the following two fields are internal, NEVER access directly */ unsigned int __data_len; /* total data len */ - int tag; sector_t __sector; /* sector cursor */ struct bio *bio; @@ -194,7 +194,11 @@ struct request { struct gendisk *rq_disk; struct hd_struct *part; - /* Time that I/O was submitted to the kernel. */ +#ifdef CONFIG_BLK_RQ_ALLOC_TIME + /* Time that the first bio started allocating this request. */ + u64 alloc_time_ns; +#endif + /* Time that this request was allocated for this IO. */ u64 start_time_ns; /* Time that I/O was submitted to the device. */ u64 io_start_time_ns; @@ -202,9 +206,12 @@ struct request { #ifdef CONFIG_BLK_WBT unsigned short wbt_flags; #endif -#ifdef CONFIG_BLK_DEV_THROTTLING_LOW - unsigned short throtl_size; -#endif + /* + * rq sectors used for blk stats. It has the same value + * with blk_rq_sectors(rq), except that it never be zeroed + * by completion. + */ + unsigned short stats_sectors; /* * Number of scatter-gather DMA addr+len pairs after @@ -344,10 +351,15 @@ struct queue_limits { #ifdef CONFIG_BLK_DEV_ZONED +/* + * Maximum number of zones to report with a single report zones command. + */ +#define BLK_ZONED_REPORT_MAX_ZONES 8192U + extern unsigned int blkdev_nr_zones(struct block_device *bdev); extern int blkdev_report_zones(struct block_device *bdev, sector_t sector, struct blk_zone *zones, - unsigned int *nr_zones, gfp_t gfp_mask); + unsigned int *nr_zones); extern int blkdev_reset_zones(struct block_device *bdev, sector_t sectors, sector_t nr_sectors, gfp_t gfp_mask); extern int blk_revalidate_disk_zones(struct gendisk *disk); @@ -386,10 +398,6 @@ static inline int blkdev_reset_zones_ioctl(struct block_device *bdev, #endif /* CONFIG_BLK_DEV_ZONED */ struct request_queue { - /* - * Together with queue_head for cacheline sharing - */ - struct list_head queue_head; struct request *last_merge; struct elevator_queue *elevator; @@ -491,6 +499,8 @@ struct request_queue { struct queue_limits limits; + unsigned int required_elevator_features; + #ifdef CONFIG_BLK_DEV_ZONED /* * Zoned block device information for request dispatch control. @@ -534,6 +544,7 @@ struct request_queue { struct delayed_work requeue_work; struct mutex sysfs_lock; + struct mutex sysfs_dir_lock; /* * for reusing dead hctx instance in case of updating @@ -606,6 +617,8 @@ struct request_queue { #define QUEUE_FLAG_SCSI_PASSTHROUGH 23 /* queue supports SCSI commands */ #define QUEUE_FLAG_QUIESCED 24 /* queue has been quiesced */ #define QUEUE_FLAG_PCI_P2PDMA 25 /* device supports PCI p2p requests */ +#define QUEUE_FLAG_ZONE_RESETALL 26 /* supports Zone Reset All */ +#define QUEUE_FLAG_RQ_ALLOC_TIME 27 /* record rq->alloc_time_ns */ #define QUEUE_FLAG_MQ_DEFAULT ((1 << QUEUE_FLAG_IO_STAT) | \ (1 << QUEUE_FLAG_SAME_COMP)) @@ -625,6 +638,8 @@ bool blk_queue_flag_test_and_set(unsigned int flag, struct request_queue *q); #define blk_queue_io_stat(q) test_bit(QUEUE_FLAG_IO_STAT, &(q)->queue_flags) #define blk_queue_add_random(q) test_bit(QUEUE_FLAG_ADD_RANDOM, &(q)->queue_flags) #define blk_queue_discard(q) test_bit(QUEUE_FLAG_DISCARD, &(q)->queue_flags) +#define blk_queue_zone_resetall(q) \ + test_bit(QUEUE_FLAG_ZONE_RESETALL, &(q)->queue_flags) #define blk_queue_secure_erase(q) \ (test_bit(QUEUE_FLAG_SECERASE, &(q)->queue_flags)) #define blk_queue_dax(q) test_bit(QUEUE_FLAG_DAX, &(q)->queue_flags) @@ -632,6 +647,12 @@ bool blk_queue_flag_test_and_set(unsigned int flag, struct request_queue *q); test_bit(QUEUE_FLAG_SCSI_PASSTHROUGH, &(q)->queue_flags) #define blk_queue_pci_p2pdma(q) \ test_bit(QUEUE_FLAG_PCI_P2PDMA, &(q)->queue_flags) +#ifdef CONFIG_BLK_RQ_ALLOC_TIME +#define blk_queue_rq_alloc_time(q) \ + test_bit(QUEUE_FLAG_RQ_ALLOC_TIME, &(q)->queue_flags) +#else +#define blk_queue_rq_alloc_time(q) false +#endif #define blk_noretry_request(rq) \ ((rq)->cmd_flags & (REQ_FAILFAST_DEV|REQ_FAILFAST_TRANSPORT| \ @@ -639,6 +660,7 @@ bool blk_queue_flag_test_and_set(unsigned int flag, struct request_queue *q); #define blk_queue_quiesced(q) test_bit(QUEUE_FLAG_QUIESCED, &(q)->queue_flags) #define blk_queue_pm_only(q) atomic_read(&(q)->pm_only) #define blk_queue_fua(q) test_bit(QUEUE_FLAG_FUA, &(q)->queue_flags) +#define blk_queue_registered(q) test_bit(QUEUE_FLAG_REGISTERED, &(q)->queue_flags) extern void blk_set_pm_only(struct request_queue *q); extern void blk_clear_pm_only(struct request_queue *q); @@ -681,7 +703,7 @@ static inline bool blk_queue_is_zoned(struct request_queue *q) } } -static inline unsigned int blk_queue_zone_sectors(struct request_queue *q) +static inline sector_t blk_queue_zone_sectors(struct request_queue *q) { return blk_queue_is_zoned(q) ? q->limits.chunk_sectors : 0; } @@ -828,7 +850,6 @@ extern void blk_unregister_queue(struct gendisk *disk); extern blk_qc_t generic_make_request(struct bio *bio); extern blk_qc_t direct_make_request(struct bio *bio); extern void blk_rq_init(struct request_queue *q, struct request *rq); -extern void blk_init_request_from_bio(struct request *req, struct bio *bio); extern void blk_put_request(struct request *); extern struct request *blk_get_request(struct request_queue *, unsigned int op, blk_mq_req_flags_t flags); @@ -842,7 +863,6 @@ extern blk_status_t blk_insert_cloned_request(struct request_queue *q, struct request *rq); extern int blk_rq_append_bio(struct request *rq, struct bio **bio); extern void blk_queue_split(struct request_queue *, struct bio **); -extern void blk_recount_segments(struct request_queue *, struct bio *); extern int scsi_verify_blk_ioctl(struct block_device *, unsigned int); extern int scsi_cmd_blk_ioctl(struct block_device *, fmode_t, unsigned int, void __user *); @@ -867,6 +887,9 @@ extern void blk_execute_rq(struct request_queue *, struct gendisk *, extern void blk_execute_rq_nowait(struct request_queue *, struct gendisk *, struct request *, int, rq_end_io_fn *); +/* Helper to convert REQ_OP_XXX to its string format XXX */ +extern const char *blk_op_str(unsigned int op); + int blk_status_to_errno(blk_status_t status); blk_status_t errno_to_blk_status(int errno); @@ -897,6 +920,7 @@ static inline struct request_queue *bdev_get_queue(struct block_device *bdev) * blk_rq_err_bytes() : bytes left till the next error boundary * blk_rq_sectors() : sectors left in the entire request * blk_rq_cur_sectors() : sectors left in the current segment + * blk_rq_stats_sectors() : sectors of the entire request used for stats */ static inline sector_t blk_rq_pos(const struct request *rq) { @@ -925,6 +949,11 @@ static inline unsigned int blk_rq_cur_sectors(const struct request *rq) return blk_rq_cur_bytes(rq) >> SECTOR_SHIFT; } +static inline unsigned int blk_rq_stats_sectors(const struct request *rq) +{ + return rq->stats_sectors; +} + #ifdef CONFIG_BLK_DEV_ZONED static inline unsigned int blk_rq_zone_no(struct request *rq) { @@ -1026,21 +1055,9 @@ void blk_steal_bios(struct bio_list *list, struct request *rq); * * blk_update_request() completes given number of bytes and updates * the request without completing it. - * - * blk_end_request() and friends. __blk_end_request() must be called - * with the request queue spinlock acquired. - * - * Several drivers define their own end_request and call - * blk_end_request() for parts of the original function. - * This prevents code duplication in drivers. */ extern bool blk_update_request(struct request *rq, blk_status_t error, unsigned int nr_bytes); -extern void blk_end_request_all(struct request *rq, blk_status_t error); -extern bool __blk_end_request(struct request *rq, blk_status_t error, - unsigned int nr_bytes); -extern void __blk_end_request_all(struct request *rq, blk_status_t error); -extern bool __blk_end_request_cur(struct request *rq, blk_status_t error); extern void __blk_complete_request(struct request *); extern void blk_abort_request(struct request *); @@ -1091,6 +1108,10 @@ extern void blk_queue_dma_alignment(struct request_queue *, int); extern void blk_queue_update_dma_alignment(struct request_queue *, int); extern void blk_queue_rq_timeout(struct request_queue *, unsigned int); extern void blk_queue_write_cache(struct request_queue *q, bool enabled, bool fua); +extern void blk_queue_required_elevator_features(struct request_queue *q, + unsigned int features); +extern bool blk_queue_can_use_dma_map_merging(struct request_queue *q, + struct device *dev); /* * Number of physical segments as sent to the device. @@ -1238,42 +1259,42 @@ enum blk_default_limits { BLK_SEG_BOUNDARY_MASK = 0xFFFFFFFFUL, }; -static inline unsigned long queue_segment_boundary(struct request_queue *q) +static inline unsigned long queue_segment_boundary(const struct request_queue *q) { return q->limits.seg_boundary_mask; } -static inline unsigned long queue_virt_boundary(struct request_queue *q) +static inline unsigned long queue_virt_boundary(const struct request_queue *q) { return q->limits.virt_boundary_mask; } -static inline unsigned int queue_max_sectors(struct request_queue *q) +static inline unsigned int queue_max_sectors(const struct request_queue *q) { return q->limits.max_sectors; } -static inline unsigned int queue_max_hw_sectors(struct request_queue *q) +static inline unsigned int queue_max_hw_sectors(const struct request_queue *q) { return q->limits.max_hw_sectors; } -static inline unsigned short queue_max_segments(struct request_queue *q) +static inline unsigned short queue_max_segments(const struct request_queue *q) { return q->limits.max_segments; } -static inline unsigned short queue_max_discard_segments(struct request_queue *q) +static inline unsigned short queue_max_discard_segments(const struct request_queue *q) { return q->limits.max_discard_segments; } -static inline unsigned int queue_max_segment_size(struct request_queue *q) +static inline unsigned int queue_max_segment_size(const struct request_queue *q) { return q->limits.max_segment_size; } -static inline unsigned short queue_logical_block_size(struct request_queue *q) +static inline unsigned short queue_logical_block_size(const struct request_queue *q) { int retval = 512; @@ -1288,7 +1309,7 @@ static inline unsigned short bdev_logical_block_size(struct block_device *bdev) return queue_logical_block_size(bdev_get_queue(bdev)); } -static inline unsigned int queue_physical_block_size(struct request_queue *q) +static inline unsigned int queue_physical_block_size(const struct request_queue *q) { return q->limits.physical_block_size; } @@ -1298,7 +1319,7 @@ static inline unsigned int bdev_physical_block_size(struct block_device *bdev) return queue_physical_block_size(bdev_get_queue(bdev)); } -static inline unsigned int queue_io_min(struct request_queue *q) +static inline unsigned int queue_io_min(const struct request_queue *q) { return q->limits.io_min; } @@ -1308,7 +1329,7 @@ static inline int bdev_io_min(struct block_device *bdev) return queue_io_min(bdev_get_queue(bdev)); } -static inline unsigned int queue_io_opt(struct request_queue *q) +static inline unsigned int queue_io_opt(const struct request_queue *q) { return q->limits.io_opt; } @@ -1318,7 +1339,7 @@ static inline int bdev_io_opt(struct block_device *bdev) return queue_io_opt(bdev_get_queue(bdev)); } -static inline int queue_alignment_offset(struct request_queue *q) +static inline int queue_alignment_offset(const struct request_queue *q) { if (q->limits.misaligned) return -1; @@ -1348,7 +1369,7 @@ static inline int bdev_alignment_offset(struct block_device *bdev) return q->limits.alignment_offset; } -static inline int queue_discard_alignment(struct request_queue *q) +static inline int queue_discard_alignment(const struct request_queue *q) { if (q->limits.discard_misaligned) return -1; @@ -1429,7 +1450,7 @@ static inline bool bdev_is_zoned(struct block_device *bdev) return false; } -static inline unsigned int bdev_zone_sectors(struct block_device *bdev) +static inline sector_t bdev_zone_sectors(struct block_device *bdev) { struct request_queue *q = bdev_get_queue(bdev); @@ -1438,7 +1459,7 @@ static inline unsigned int bdev_zone_sectors(struct block_device *bdev) return 0; } -static inline int queue_dma_alignment(struct request_queue *q) +static inline int queue_dma_alignment(const struct request_queue *q) { return q ? q->dma_alignment : 511; } @@ -1503,10 +1524,14 @@ struct blk_integrity_iter { }; typedef blk_status_t (integrity_processing_fn) (struct blk_integrity_iter *); +typedef void (integrity_prepare_fn) (struct request *); +typedef void (integrity_complete_fn) (struct request *, unsigned int); struct blk_integrity_profile { integrity_processing_fn *generate_fn; integrity_processing_fn *verify_fn; + integrity_prepare_fn *prepare_fn; + integrity_complete_fn *complete_fn; const char *name; }; @@ -1549,7 +1574,7 @@ static inline void blk_queue_max_integrity_segments(struct request_queue *q, } static inline unsigned short -queue_max_integrity_segments(struct request_queue *q) +queue_max_integrity_segments(const struct request_queue *q) { return q->limits.max_integrity_segments; } @@ -1632,7 +1657,7 @@ static inline void blk_queue_max_integrity_segments(struct request_queue *q, unsigned int segs) { } -static inline unsigned short queue_max_integrity_segments(struct request_queue *q) +static inline unsigned short queue_max_integrity_segments(const struct request_queue *q) { return 0; } @@ -1684,8 +1709,7 @@ struct block_device_operations { /* this callback is with swap_lock and sometimes page table lock held */ void (*swap_slot_free_notify) (struct block_device *, unsigned long); int (*report_zones)(struct gendisk *, sector_t sector, - struct blk_zone *zones, unsigned int *nr_zones, - gfp_t gfp_mask); + struct blk_zone *zones, unsigned int *nr_zones); struct module *owner; const struct pr_ops *pr_ops; }; diff --git a/include/linux/bpf-cgroup.h b/include/linux/bpf-cgroup.h index a7f7a98ec39d..169fd25f6bc2 100644 --- a/include/linux/bpf-cgroup.h +++ b/include/linux/bpf-cgroup.h @@ -6,6 +6,7 @@ #include <linux/errno.h> #include <linux/jump_label.h> #include <linux/percpu.h> +#include <linux/percpu-refcount.h> #include <linux/rbtree.h> #include <uapi/linux/bpf.h> @@ -71,11 +72,17 @@ struct cgroup_bpf { u32 flags[MAX_BPF_ATTACH_TYPE]; /* temp storage for effective prog array used by prog_attach/detach */ - struct bpf_prog_array __rcu *inactive; + struct bpf_prog_array *inactive; + + /* reference counter used to detach bpf programs after cgroup removal */ + struct percpu_ref refcnt; + + /* cgroup_bpf is released using a work queue */ + struct work_struct release_work; }; -void cgroup_bpf_put(struct cgroup *cgrp); int cgroup_bpf_inherit(struct cgroup *cgrp); +void cgroup_bpf_offline(struct cgroup *cgrp); int __cgroup_bpf_attach(struct cgroup *cgrp, struct bpf_prog *prog, enum bpf_attach_type type, u32 flags); @@ -117,6 +124,14 @@ int __cgroup_bpf_run_filter_sysctl(struct ctl_table_header *head, loff_t *ppos, void **new_buf, enum bpf_attach_type type); +int __cgroup_bpf_run_filter_setsockopt(struct sock *sock, int *level, + int *optname, char __user *optval, + int *optlen, char **kernel_optval); +int __cgroup_bpf_run_filter_getsockopt(struct sock *sk, int level, + int optname, char __user *optval, + int __user *optlen, int max_optlen, + int retval); + static inline enum bpf_cgroup_storage_type cgroup_storage_type( struct bpf_map *map) { @@ -279,6 +294,38 @@ int bpf_percpu_cgroup_storage_update(struct bpf_map *map, void *key, __ret; \ }) +#define BPF_CGROUP_RUN_PROG_SETSOCKOPT(sock, level, optname, optval, optlen, \ + kernel_optval) \ +({ \ + int __ret = 0; \ + if (cgroup_bpf_enabled) \ + __ret = __cgroup_bpf_run_filter_setsockopt(sock, level, \ + optname, optval, \ + optlen, \ + kernel_optval); \ + __ret; \ +}) + +#define BPF_CGROUP_GETSOCKOPT_MAX_OPTLEN(optlen) \ +({ \ + int __ret = 0; \ + if (cgroup_bpf_enabled) \ + get_user(__ret, optlen); \ + __ret; \ +}) + +#define BPF_CGROUP_RUN_PROG_GETSOCKOPT(sock, level, optname, optval, optlen, \ + max_optlen, retval) \ +({ \ + int __ret = retval; \ + if (cgroup_bpf_enabled) \ + __ret = __cgroup_bpf_run_filter_getsockopt(sock, level, \ + optname, optval, \ + optlen, max_optlen, \ + retval); \ + __ret; \ +}) + int cgroup_bpf_prog_attach(const union bpf_attr *attr, enum bpf_prog_type ptype, struct bpf_prog *prog); int cgroup_bpf_prog_detach(const union bpf_attr *attr, @@ -289,8 +336,8 @@ int cgroup_bpf_prog_query(const union bpf_attr *attr, struct bpf_prog; struct cgroup_bpf {}; -static inline void cgroup_bpf_put(struct cgroup *cgrp) {} static inline int cgroup_bpf_inherit(struct cgroup *cgrp) { return 0; } +static inline void cgroup_bpf_offline(struct cgroup *cgrp) {} static inline int cgroup_bpf_prog_attach(const union bpf_attr *attr, enum bpf_prog_type ptype, @@ -350,6 +397,11 @@ static inline int bpf_percpu_cgroup_storage_update(struct bpf_map *map, #define BPF_CGROUP_RUN_PROG_SOCK_OPS(sock_ops) ({ 0; }) #define BPF_CGROUP_RUN_PROG_DEVICE_CGROUP(type,major,minor,access) ({ 0; }) #define BPF_CGROUP_RUN_PROG_SYSCTL(head,table,write,buf,count,pos,nbuf) ({ 0; }) +#define BPF_CGROUP_GETSOCKOPT_MAX_OPTLEN(optlen) ({ 0; }) +#define BPF_CGROUP_RUN_PROG_GETSOCKOPT(sock, level, optname, optval, \ + optlen, max_optlen, retval) ({ retval; }) +#define BPF_CGROUP_RUN_PROG_SETSOCKOPT(sock, level, optname, optval, optlen, \ + kernel_optval) ({ 0; }) #define for_each_cgroup_storage_type(stype) for (; false; ) diff --git a/include/linux/bpf.h b/include/linux/bpf.h index b92ef9f73e42..5b9d22338606 100644 --- a/include/linux/bpf.h +++ b/include/linux/bpf.h @@ -24,6 +24,9 @@ struct seq_file; struct btf; struct btf_type; +extern struct idr btf_idr; +extern spinlock_t btf_idr_lock; + /* map is generic key/value storage optionally accesible by eBPF programs */ struct bpf_map_ops { /* funcs callable from userspace (via syscall) */ @@ -63,6 +66,11 @@ struct bpf_map_ops { u64 imm, u32 *off); }; +struct bpf_map_memory { + u32 pages; + struct user_struct *user; +}; + struct bpf_map { /* The first two cachelines with read-mostly members of which some * are also accessed in fast-path (e.g. ops, max_entries). @@ -83,7 +91,7 @@ struct bpf_map { u32 btf_key_type_id; u32 btf_value_type_id; struct btf *btf; - u32 pages; + struct bpf_map_memory memory; bool unpriv_array; bool frozen; /* write-once */ /* 48 bytes hole */ @@ -91,8 +99,7 @@ struct bpf_map { /* The 3rd and 4th cacheline with misc members to avoid false sharing * particularly with refcounting. */ - struct user_struct *user ____cacheline_aligned; - atomic_t refcnt; + atomic_t refcnt ____cacheline_aligned; atomic_t usercnt; struct work_struct work; char name[BPF_OBJ_NAME_LEN]; @@ -273,6 +280,7 @@ enum bpf_reg_type { PTR_TO_TCP_SOCK, /* reg points to struct tcp_sock */ PTR_TO_TCP_SOCK_OR_NULL, /* reg points to struct tcp_sock or NULL */ PTR_TO_TP_BUFFER, /* reg points to a writable raw tp's buffer */ + PTR_TO_XDP_SOCK, /* reg points to struct xdp_sock */ }; /* The information passed from prog-specific *_is_valid_access @@ -367,6 +375,7 @@ struct bpf_prog_aux { u32 id; u32 func_cnt; /* used by non-func prog as the number of func progs */ u32 func_idx; /* 0 for non-func prog, the index in func array for func prog */ + bool verifier_zext; /* Zero extensions has been inserted by verifier. */ bool offload_requested; struct bpf_prog **func; void *jit_data; /* JIT specific data. arch dependent */ @@ -510,17 +519,18 @@ struct bpf_prog_array { }; struct bpf_prog_array *bpf_prog_array_alloc(u32 prog_cnt, gfp_t flags); -void bpf_prog_array_free(struct bpf_prog_array __rcu *progs); -int bpf_prog_array_length(struct bpf_prog_array __rcu *progs); -int bpf_prog_array_copy_to_user(struct bpf_prog_array __rcu *progs, +void bpf_prog_array_free(struct bpf_prog_array *progs); +int bpf_prog_array_length(struct bpf_prog_array *progs); +bool bpf_prog_array_is_empty(struct bpf_prog_array *array); +int bpf_prog_array_copy_to_user(struct bpf_prog_array *progs, __u32 __user *prog_ids, u32 cnt); -void bpf_prog_array_delete_safe(struct bpf_prog_array __rcu *progs, +void bpf_prog_array_delete_safe(struct bpf_prog_array *progs, struct bpf_prog *old_prog); -int bpf_prog_array_copy_info(struct bpf_prog_array __rcu *array, +int bpf_prog_array_copy_info(struct bpf_prog_array *array, u32 *prog_ids, u32 request_cnt, u32 *prog_cnt); -int bpf_prog_array_copy(struct bpf_prog_array __rcu *old_array, +int bpf_prog_array_copy(struct bpf_prog_array *old_array, struct bpf_prog *exclude_prog, struct bpf_prog *include_prog, struct bpf_prog_array **new_array); @@ -548,6 +558,56 @@ _out: \ _ret; \ }) +/* To be used by __cgroup_bpf_run_filter_skb for EGRESS BPF progs + * so BPF programs can request cwr for TCP packets. + * + * Current cgroup skb programs can only return 0 or 1 (0 to drop the + * packet. This macro changes the behavior so the low order bit + * indicates whether the packet should be dropped (0) or not (1) + * and the next bit is a congestion notification bit. This could be + * used by TCP to call tcp_enter_cwr() + * + * Hence, new allowed return values of CGROUP EGRESS BPF programs are: + * 0: drop packet + * 1: keep packet + * 2: drop packet and cn + * 3: keep packet and cn + * + * This macro then converts it to one of the NET_XMIT or an error + * code that is then interpreted as drop packet (and no cn): + * 0: NET_XMIT_SUCCESS skb should be transmitted + * 1: NET_XMIT_DROP skb should be dropped and cn + * 2: NET_XMIT_CN skb should be transmitted and cn + * 3: -EPERM skb should be dropped + */ +#define BPF_PROG_CGROUP_INET_EGRESS_RUN_ARRAY(array, ctx, func) \ + ({ \ + struct bpf_prog_array_item *_item; \ + struct bpf_prog *_prog; \ + struct bpf_prog_array *_array; \ + u32 ret; \ + u32 _ret = 1; \ + u32 _cn = 0; \ + preempt_disable(); \ + rcu_read_lock(); \ + _array = rcu_dereference(array); \ + _item = &_array->items[0]; \ + while ((_prog = READ_ONCE(_item->prog))) { \ + bpf_cgroup_storage_set(_item->cgroup_storage); \ + ret = func(_prog, ctx); \ + _ret &= (ret & 1); \ + _cn |= (ret & 2); \ + _item++; \ + } \ + rcu_read_unlock(); \ + preempt_enable(); \ + if (_ret) \ + _ret = (_cn ? NET_XMIT_CN : NET_XMIT_SUCCESS); \ + else \ + _ret = (_cn ? NET_XMIT_DROP : -EPERM); \ + _ret; \ + }) + #define BPF_PROG_RUN_ARRAY(array, ctx, func) \ __BPF_PROG_RUN_ARRAY(array, ctx, func, false) @@ -590,11 +650,16 @@ void bpf_map_free_id(struct bpf_map *map, bool do_idr_lock); struct bpf_map *bpf_map_get_with_uref(u32 ufd); struct bpf_map *__bpf_map_get(struct fd f); struct bpf_map * __must_check bpf_map_inc(struct bpf_map *map, bool uref); +struct bpf_map * __must_check bpf_map_inc_not_zero(struct bpf_map *map, + bool uref); void bpf_map_put_with_uref(struct bpf_map *map); void bpf_map_put(struct bpf_map *map); -int bpf_map_precharge_memlock(u32 pages); int bpf_map_charge_memlock(struct bpf_map *map, u32 pages); void bpf_map_uncharge_memlock(struct bpf_map *map, u32 pages); +int bpf_map_charge_init(struct bpf_map_memory *mem, size_t size); +void bpf_map_charge_finish(struct bpf_map_memory *mem); +void bpf_map_charge_move(struct bpf_map_memory *dst, + struct bpf_map_memory *src); void *bpf_map_area_alloc(size_t size, int numa_node); void bpf_map_area_free(void *base); void bpf_map_init_from_attr(struct bpf_map *map, union bpf_attr *attr); @@ -653,7 +718,7 @@ struct xdp_buff; struct sk_buff; struct bpf_dtab_netdev *__dev_map_lookup_elem(struct bpf_map *map, u32 key); -void __dev_map_insert_ctx(struct bpf_map *map, u32 index); +struct bpf_dtab_netdev *__dev_map_hash_lookup_elem(struct bpf_map *map, u32 key); void __dev_map_flush(struct bpf_map *map); int dev_map_enqueue(struct bpf_dtab_netdev *dst, struct xdp_buff *xdp, struct net_device *dev_rx); @@ -661,7 +726,6 @@ int dev_map_generic_redirect(struct bpf_dtab_netdev *dst, struct sk_buff *skb, struct bpf_prog *xdp_prog); struct bpf_cpu_map_entry *__cpu_map_lookup_elem(struct bpf_map *map, u32 key); -void __cpu_map_insert_ctx(struct bpf_map *map, u32 index); void __cpu_map_flush(struct bpf_map *map); int cpu_map_enqueue(struct bpf_cpu_map_entry *rcpu, struct xdp_buff *xdp, struct net_device *dev_rx); @@ -741,8 +805,10 @@ static inline struct net_device *__dev_map_lookup_elem(struct bpf_map *map, return NULL; } -static inline void __dev_map_insert_ctx(struct bpf_map *map, u32 index) +static inline struct net_device *__dev_map_hash_lookup_elem(struct bpf_map *map, + u32 key) { + return NULL; } static inline void __dev_map_flush(struct bpf_map *map) @@ -774,10 +840,6 @@ struct bpf_cpu_map_entry *__cpu_map_lookup_elem(struct bpf_map *map, u32 key) return NULL; } -static inline void __cpu_map_insert_ctx(struct bpf_map *map, u32 index) -{ -} - static inline void __cpu_map_flush(struct bpf_map *map) { } @@ -992,6 +1054,7 @@ extern const struct bpf_func_proto bpf_spin_unlock_proto; extern const struct bpf_func_proto bpf_get_local_storage_proto; extern const struct bpf_func_proto bpf_strtol_proto; extern const struct bpf_func_proto bpf_strtoul_proto; +extern const struct bpf_func_proto bpf_tcp_sock_proto; /* Shared helpers among cBPF and eBPF. */ void bpf_user_rnd_init_once(void); @@ -1040,6 +1103,15 @@ u32 bpf_tcp_sock_convert_ctx_access(enum bpf_access_type type, struct bpf_insn *insn_buf, struct bpf_prog *prog, u32 *target_size); + +bool bpf_xdp_sock_is_valid_access(int off, int size, enum bpf_access_type type, + struct bpf_insn_access_aux *info); + +u32 bpf_xdp_sock_convert_ctx_access(enum bpf_access_type type, + const struct bpf_insn *si, + struct bpf_insn *insn_buf, + struct bpf_prog *prog, + u32 *target_size); #else static inline bool bpf_tcp_sock_is_valid_access(int off, int size, enum bpf_access_type type, @@ -1056,6 +1128,21 @@ static inline u32 bpf_tcp_sock_convert_ctx_access(enum bpf_access_type type, { return 0; } +static inline bool bpf_xdp_sock_is_valid_access(int off, int size, + enum bpf_access_type type, + struct bpf_insn_access_aux *info) +{ + return false; +} + +static inline u32 bpf_xdp_sock_convert_ctx_access(enum bpf_access_type type, + const struct bpf_insn *si, + struct bpf_insn *insn_buf, + struct bpf_prog *prog, + u32 *target_size) +{ + return 0; +} #endif /* CONFIG_INET */ #endif /* _LINUX_BPF_H */ diff --git a/include/linux/bpf_types.h b/include/linux/bpf_types.h index 5a9975678d6f..36a9c2325176 100644 --- a/include/linux/bpf_types.h +++ b/include/linux/bpf_types.h @@ -30,6 +30,7 @@ BPF_PROG_TYPE(BPF_PROG_TYPE_RAW_TRACEPOINT_WRITABLE, raw_tracepoint_writable) #ifdef CONFIG_CGROUP_BPF BPF_PROG_TYPE(BPF_PROG_TYPE_CGROUP_DEVICE, cg_dev) BPF_PROG_TYPE(BPF_PROG_TYPE_CGROUP_SYSCTL, cg_sysctl) +BPF_PROG_TYPE(BPF_PROG_TYPE_CGROUP_SOCKOPT, cg_sockopt) #endif #ifdef CONFIG_BPF_LIRC_MODE2 BPF_PROG_TYPE(BPF_PROG_TYPE_LIRC_MODE2, lirc_mode2) @@ -61,6 +62,7 @@ BPF_MAP_TYPE(BPF_MAP_TYPE_ARRAY_OF_MAPS, array_of_maps_map_ops) BPF_MAP_TYPE(BPF_MAP_TYPE_HASH_OF_MAPS, htab_of_maps_map_ops) #ifdef CONFIG_NET BPF_MAP_TYPE(BPF_MAP_TYPE_DEVMAP, dev_map_ops) +BPF_MAP_TYPE(BPF_MAP_TYPE_DEVMAP_HASH, dev_map_hash_ops) BPF_MAP_TYPE(BPF_MAP_TYPE_SK_STORAGE, sk_storage_map_ops) #if defined(CONFIG_BPF_STREAM_PARSER) BPF_MAP_TYPE(BPF_MAP_TYPE_SOCKMAP, sock_map_ops) diff --git a/include/linux/bpf_verifier.h b/include/linux/bpf_verifier.h index 519aafabc40c..26a6d58ca78c 100644 --- a/include/linux/bpf_verifier.h +++ b/include/linux/bpf_verifier.h @@ -33,9 +33,11 @@ */ enum bpf_reg_liveness { REG_LIVE_NONE = 0, /* reg hasn't been read or written this branch */ - REG_LIVE_READ, /* reg was read, so we're sensitive to initial value */ - REG_LIVE_WRITTEN, /* reg was written first, screening off later reads */ - REG_LIVE_DONE = 4, /* liveness won't be updating this register anymore */ + REG_LIVE_READ32 = 0x1, /* reg was read, so we're sensitive to initial value */ + REG_LIVE_READ64 = 0x2, /* likewise, but full 64-bit content matters */ + REG_LIVE_READ = REG_LIVE_READ32 | REG_LIVE_READ64, + REG_LIVE_WRITTEN = 0x4, /* reg was written first, screening off later reads */ + REG_LIVE_DONE = 0x8, /* liveness won't be updating this register anymore */ }; struct bpf_reg_state { @@ -128,7 +130,14 @@ struct bpf_reg_state { * pointing to bpf_func_state. */ u32 frameno; + /* Tracks subreg definition. The stored value is the insn_idx of the + * writing insn. This is safe because subreg_def is used before any insn + * patching which only happens after main verification finished. + */ + s32 subreg_def; enum bpf_reg_liveness live; + /* if (!precise && SCALAR_VALUE) min/max/tnum don't affect safety */ + bool precise; }; enum bpf_stack_slot_type { @@ -180,13 +189,77 @@ struct bpf_func_state { struct bpf_stack_state *stack; }; +struct bpf_idx_pair { + u32 prev_idx; + u32 idx; +}; + #define MAX_CALL_FRAMES 8 struct bpf_verifier_state { /* call stack tracking */ struct bpf_func_state *frame[MAX_CALL_FRAMES]; + struct bpf_verifier_state *parent; + /* + * 'branches' field is the number of branches left to explore: + * 0 - all possible paths from this state reached bpf_exit or + * were safely pruned + * 1 - at least one path is being explored. + * This state hasn't reached bpf_exit + * 2 - at least two paths are being explored. + * This state is an immediate parent of two children. + * One is fallthrough branch with branches==1 and another + * state is pushed into stack (to be explored later) also with + * branches==1. The parent of this state has branches==1. + * The verifier state tree connected via 'parent' pointer looks like: + * 1 + * 1 + * 2 -> 1 (first 'if' pushed into stack) + * 1 + * 2 -> 1 (second 'if' pushed into stack) + * 1 + * 1 + * 1 bpf_exit. + * + * Once do_check() reaches bpf_exit, it calls update_branch_counts() + * and the verifier state tree will look: + * 1 + * 1 + * 2 -> 1 (first 'if' pushed into stack) + * 1 + * 1 -> 1 (second 'if' pushed into stack) + * 0 + * 0 + * 0 bpf_exit. + * After pop_stack() the do_check() will resume at second 'if'. + * + * If is_state_visited() sees a state with branches > 0 it means + * there is a loop. If such state is exactly equal to the current state + * it's an infinite loop. Note states_equal() checks for states + * equvalency, so two states being 'states_equal' does not mean + * infinite loop. The exact comparison is provided by + * states_maybe_looping() function. It's a stronger pre-check and + * much faster than states_equal(). + * + * This algorithm may not find all possible infinite loops or + * loop iteration count may be too high. + * In such cases BPF_COMPLEXITY_LIMIT_INSNS limit kicks in. + */ + u32 branches; + u32 insn_idx; u32 curframe; u32 active_spin_lock; bool speculative; + + /* first and last insn idx of this verifier state */ + u32 first_insn_idx; + u32 last_insn_idx; + /* jmp history recorded from first to last. + * backtracking is using it to go from last to first. + * For most states jmp_history_cnt is [0-3]. + * For loops can go up to ~40. + */ + struct bpf_idx_pair *jmp_history; + u32 jmp_history_cnt; }; #define bpf_get_spilled_reg(slot, frame) \ @@ -229,7 +302,9 @@ struct bpf_insn_aux_data { int ctx_field_size; /* the ctx field size for load insn, maybe 0 */ int sanitize_stack_off; /* stack slot to be cleared */ bool seen; /* this insn was processed by the verifier */ + bool zext_dst; /* this insn zero extends dst reg */ u8 alu_state; /* used in combination with alu_limit */ + bool prune_point; unsigned int orig_idx; /* original instruction index */ }; @@ -280,6 +355,7 @@ struct bpf_verifier_env { struct bpf_verifier_stack_elem *head; /* stack of verifier states to be processed */ int stack_size; /* number of states to be processed */ bool strict_alignment; /* perform strict pointer alignment checks */ + bool test_state_freq; /* test verifier with different pruning frequency */ struct bpf_verifier_state *cur_state; /* current verifier state */ struct bpf_verifier_state_list **explored_states; /* search pruning optimization */ struct bpf_verifier_state_list *free_list; @@ -299,7 +375,9 @@ struct bpf_verifier_env { } cfg; u32 subprog_cnt; /* number of instructions analyzed by the verifier */ - u32 insn_processed; + u32 prev_insn_processed, insn_processed; + /* number of jmps, calls, exits analyzed so far */ + u32 prev_jmps_processed, jmps_processed; /* total verification time */ u64 verification_time; /* maximum number of verifier states kept in 'branching' instructions */ diff --git a/include/linux/bug.h b/include/linux/bug.h index fe5916550da8..f639bd0122f3 100644 --- a/include/linux/bug.h +++ b/include/linux/bug.h @@ -47,6 +47,11 @@ void generic_bug_clear_once(void); #else /* !CONFIG_GENERIC_BUG */ +static inline void *find_bug(unsigned long bugaddr) +{ + return NULL; +} + static inline enum bug_trap_type report_bug(unsigned long bug_addr, struct pt_regs *regs) { diff --git a/include/linux/cacheinfo.h b/include/linux/cacheinfo.h index 70e19bc6cc9f..46b92cd61d0c 100644 --- a/include/linux/cacheinfo.h +++ b/include/linux/cacheinfo.h @@ -17,6 +17,8 @@ enum cache_type { CACHE_TYPE_UNIFIED = BIT(2), }; +extern unsigned int coherency_max_size; + /** * struct cacheinfo - represent a cache leaf node * @id: This cache's id. It is unique among caches with the same (type, level). diff --git a/include/linux/can/can-ml.h b/include/linux/can/can-ml.h new file mode 100644 index 000000000000..2f5d731ae251 --- /dev/null +++ b/include/linux/can/can-ml.h @@ -0,0 +1,68 @@ +/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ +/* Copyright (c) 2002-2007 Volkswagen Group Electronic Research + * Copyright (c) 2017 Pengutronix, Marc Kleine-Budde <kernel@pengutronix.de> + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Volkswagen nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * Alternatively, provided that this notice is retained in full, this + * software may be distributed under the terms of the GNU General + * Public License ("GPL") version 2, in which case the provisions of the + * GPL apply INSTEAD OF those given above. + * + * The provided data structures and external interfaces from this code + * are not restricted to be used by modules with a GPL compatible license. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + */ + +#ifndef CAN_ML_H +#define CAN_ML_H + +#include <linux/can.h> +#include <linux/list.h> + +#define CAN_SFF_RCV_ARRAY_SZ (1 << CAN_SFF_ID_BITS) +#define CAN_EFF_RCV_HASH_BITS 10 +#define CAN_EFF_RCV_ARRAY_SZ (1 << CAN_EFF_RCV_HASH_BITS) + +enum { RX_ERR, RX_ALL, RX_FIL, RX_INV, RX_MAX }; + +struct can_dev_rcv_lists { + struct hlist_head rx[RX_MAX]; + struct hlist_head rx_sff[CAN_SFF_RCV_ARRAY_SZ]; + struct hlist_head rx_eff[CAN_EFF_RCV_ARRAY_SZ]; + int entries; +}; + +struct can_ml_priv { + struct can_dev_rcv_lists dev_rcv_lists; +#ifdef CAN_J1939 + struct j1939_priv *j1939_priv; +#endif +}; + +#endif /* CAN_ML_H */ diff --git a/include/linux/can/core.h b/include/linux/can/core.h index 6099bc18bd0c..8339071ab08b 100644 --- a/include/linux/can/core.h +++ b/include/linux/can/core.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0 */ +/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ /* * linux/can/core.h * @@ -41,6 +41,14 @@ struct can_proto { struct proto *prot; }; +/* required_size + * macro to find the minimum size of a struct + * that includes a requested member + */ +#define CAN_REQUIRED_SIZE(struct_type, member) \ + (offsetof(typeof(struct_type), member) + \ + sizeof(((typeof(struct_type) *)(NULL))->member)) + /* function prototypes for the CAN networklayer core (af_can.c) */ extern int can_proto_register(const struct can_proto *cp); @@ -57,6 +65,5 @@ extern void can_rx_unregister(struct net *net, struct net_device *dev, void *data); extern int can_send(struct sk_buff *skb, int loop); -extern int can_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg); #endif /* !_CAN_CORE_H */ diff --git a/include/linux/can/dev.h b/include/linux/can/dev.h index f01623aef2f7..9b3c720a31b1 100644 --- a/include/linux/can/dev.h +++ b/include/linux/can/dev.h @@ -169,7 +169,8 @@ void can_change_state(struct net_device *dev, struct can_frame *cf, void can_put_echo_skb(struct sk_buff *skb, struct net_device *dev, unsigned int idx); -struct sk_buff *__can_get_echo_skb(struct net_device *dev, unsigned int idx, u8 *len_ptr); +struct sk_buff *__can_get_echo_skb(struct net_device *dev, unsigned int idx, + u8 *len_ptr); unsigned int can_get_echo_skb(struct net_device *dev, unsigned int idx); void can_free_echo_skb(struct net_device *dev, unsigned int idx); diff --git a/include/linux/can/platform/rcar_can.h b/include/linux/can/platform/rcar_can.h deleted file mode 100644 index a43dcd0cf79e..000000000000 --- a/include/linux/can/platform/rcar_can.h +++ /dev/null @@ -1,18 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef _CAN_PLATFORM_RCAR_CAN_H_ -#define _CAN_PLATFORM_RCAR_CAN_H_ - -#include <linux/types.h> - -/* Clock Select Register settings */ -enum CLKR { - CLKR_CLKP1 = 0, /* Peripheral clock (clkp1) */ - CLKR_CLKP2 = 1, /* Peripheral clock (clkp2) */ - CLKR_CLKEXT = 3 /* Externally input clock */ -}; - -struct rcar_can_platform_data { - enum CLKR clock_select; /* Clock source select */ -}; - -#endif /* !_CAN_PLATFORM_RCAR_CAN_H_ */ diff --git a/include/linux/can/rx-offload.h b/include/linux/can/rx-offload.h index 9daa1119ea42..01219f2902bf 100644 --- a/include/linux/can/rx-offload.h +++ b/include/linux/can/rx-offload.h @@ -15,7 +15,8 @@ struct can_rx_offload { struct net_device *dev; - unsigned int (*mailbox_read)(struct can_rx_offload *offload, struct can_frame *cf, + unsigned int (*mailbox_read)(struct can_rx_offload *offload, + struct can_frame *cf, u32 *timestamp, unsigned int mb); struct sk_buff_head skb_queue; @@ -29,9 +30,13 @@ struct can_rx_offload { bool inc; }; -int can_rx_offload_add_timestamp(struct net_device *dev, struct can_rx_offload *offload); -int can_rx_offload_add_fifo(struct net_device *dev, struct can_rx_offload *offload, unsigned int weight); -int can_rx_offload_irq_offload_timestamp(struct can_rx_offload *offload, u64 reg); +int can_rx_offload_add_timestamp(struct net_device *dev, + struct can_rx_offload *offload); +int can_rx_offload_add_fifo(struct net_device *dev, + struct can_rx_offload *offload, + unsigned int weight); +int can_rx_offload_irq_offload_timestamp(struct can_rx_offload *offload, + u64 reg); int can_rx_offload_irq_offload_fifo(struct can_rx_offload *offload); int can_rx_offload_queue_sorted(struct can_rx_offload *offload, struct sk_buff *skb, u32 timestamp); diff --git a/include/linux/can/skb.h b/include/linux/can/skb.h index b3379a97245c..a954def26c0d 100644 --- a/include/linux/can/skb.h +++ b/include/linux/can/skb.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0 */ +/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ /* * linux/can/skb.h * diff --git a/include/linux/ccp.h b/include/linux/ccp.h index 55cb455cfcb0..a5dfbaf2470d 100644 --- a/include/linux/ccp.h +++ b/include/linux/ccp.h @@ -170,6 +170,8 @@ struct ccp_aes_engine { enum ccp_aes_mode mode; enum ccp_aes_action action; + u32 authsize; + struct scatterlist *key; u32 key_len; /* In bytes */ diff --git a/include/linux/ceph/buffer.h b/include/linux/ceph/buffer.h index 5e58bb29b1a3..11cdc7c60480 100644 --- a/include/linux/ceph/buffer.h +++ b/include/linux/ceph/buffer.h @@ -30,7 +30,8 @@ static inline struct ceph_buffer *ceph_buffer_get(struct ceph_buffer *b) static inline void ceph_buffer_put(struct ceph_buffer *b) { - kref_put(&b->kref, ceph_buffer_release); + if (b) + kref_put(&b->kref, ceph_buffer_release); } extern int ceph_decode_buffer(struct ceph_buffer **b, void **p, void *end); diff --git a/include/linux/ceph/ceph_features.h b/include/linux/ceph/ceph_features.h index 65a38c4a02a1..39e6f4c57580 100644 --- a/include/linux/ceph/ceph_features.h +++ b/include/linux/ceph/ceph_features.h @@ -211,6 +211,7 @@ DEFINE_CEPH_FEATURE_DEPRECATED(63, 1, RESERVED_BROKEN, LUMINOUS) // client-facin CEPH_FEATURE_MON_STATEFUL_SUB | \ CEPH_FEATURE_CRUSH_TUNABLES5 | \ CEPH_FEATURE_NEW_OSDOPREPLY_ENCODING | \ + CEPH_FEATURE_MSG_ADDR2 | \ CEPH_FEATURE_CEPHX_V2) #define CEPH_FEATURES_REQUIRED_DEFAULT 0 diff --git a/include/linux/ceph/ceph_fs.h b/include/linux/ceph/ceph_fs.h index 3ac0feaf2b5e..cb21c5cf12c3 100644 --- a/include/linux/ceph/ceph_fs.h +++ b/include/linux/ceph/ceph_fs.h @@ -682,7 +682,7 @@ extern const char *ceph_cap_op_name(int op); /* flags field in client cap messages (version >= 10) */ #define CEPH_CLIENT_CAPS_SYNC (1<<0) #define CEPH_CLIENT_CAPS_NO_CAPSNAP (1<<1) -#define CEPH_CLIENT_CAPS_PENDING_CAPSNAP (1<<2); +#define CEPH_CLIENT_CAPS_PENDING_CAPSNAP (1<<2) /* * caps message, used for capability callbacks, acks, requests, etc. diff --git a/include/linux/ceph/cls_lock_client.h b/include/linux/ceph/cls_lock_client.h index bea6c77d2093..17bc7584d1fe 100644 --- a/include/linux/ceph/cls_lock_client.h +++ b/include/linux/ceph/cls_lock_client.h @@ -52,4 +52,7 @@ int ceph_cls_lock_info(struct ceph_osd_client *osdc, char *lock_name, u8 *type, char **tag, struct ceph_locker **lockers, u32 *num_lockers); +int ceph_cls_assert_locked(struct ceph_osd_request *req, int which, + char *lock_name, u8 type, char *cookie, char *tag); + #endif diff --git a/include/linux/ceph/debugfs.h b/include/linux/ceph/debugfs.h index fa5f9b7f5dbb..cf5e840eec71 100644 --- a/include/linux/ceph/debugfs.h +++ b/include/linux/ceph/debugfs.h @@ -19,9 +19,9 @@ static const struct file_operations name##_fops = { \ }; /* debugfs.c */ -extern int ceph_debugfs_init(void); +extern void ceph_debugfs_init(void); extern void ceph_debugfs_cleanup(void); -extern int ceph_debugfs_client_init(struct ceph_client *client); +extern void ceph_debugfs_client_init(struct ceph_client *client); extern void ceph_debugfs_client_cleanup(struct ceph_client *client); #endif diff --git a/include/linux/ceph/decode.h b/include/linux/ceph/decode.h index a6c2a48d42e0..450384fe487c 100644 --- a/include/linux/ceph/decode.h +++ b/include/linux/ceph/decode.h @@ -218,18 +218,27 @@ static inline void ceph_encode_timespec64(struct ceph_timespec *tv, /* * sockaddr_storage <-> ceph_sockaddr */ -static inline void ceph_encode_addr(struct ceph_entity_addr *a) +#define CEPH_ENTITY_ADDR_TYPE_NONE 0 +#define CEPH_ENTITY_ADDR_TYPE_LEGACY __cpu_to_le32(1) + +static inline void ceph_encode_banner_addr(struct ceph_entity_addr *a) { __be16 ss_family = htons(a->in_addr.ss_family); a->in_addr.ss_family = *(__u16 *)&ss_family; + + /* Banner addresses require TYPE_NONE */ + a->type = CEPH_ENTITY_ADDR_TYPE_NONE; } -static inline void ceph_decode_addr(struct ceph_entity_addr *a) +static inline void ceph_decode_banner_addr(struct ceph_entity_addr *a) { __be16 ss_family = *(__be16 *)&a->in_addr.ss_family; a->in_addr.ss_family = ntohs(ss_family); WARN_ON(a->in_addr.ss_family == 512); + a->type = CEPH_ENTITY_ADDR_TYPE_LEGACY; } +extern int ceph_decode_entity_addr(void **p, void *end, + struct ceph_entity_addr *addr); /* * encoders */ diff --git a/include/linux/ceph/libceph.h b/include/linux/ceph/libceph.h index 337d5049ff93..b9dbda1c26aa 100644 --- a/include/linux/ceph/libceph.h +++ b/include/linux/ceph/libceph.h @@ -84,11 +84,13 @@ struct ceph_options { #define CEPH_MSG_MAX_MIDDLE_LEN (16*1024*1024) /* - * Handle the largest possible rbd object in one message. + * The largest possible rbd data object is 32M. + * The largest possible rbd object map object is 64M. + * * There is no limit on the size of cephfs objects, but it has to obey * rsize and wsize mount options anyway. */ -#define CEPH_MSG_MAX_DATA_LEN (32*1024*1024) +#define CEPH_MSG_MAX_DATA_LEN (64*1024*1024) #define CEPH_AUTH_NAME_DEFAULT "guest" @@ -291,6 +293,7 @@ struct ceph_client *ceph_create_client(struct ceph_options *opt, void *private); struct ceph_entity_addr *ceph_client_addr(struct ceph_client *client); u64 ceph_client_gid(struct ceph_client *client); extern void ceph_destroy_client(struct ceph_client *client); +extern void ceph_reset_client_addr(struct ceph_client *client); extern int __ceph_open_session(struct ceph_client *client, unsigned long started); extern int ceph_open_session(struct ceph_client *client); @@ -299,10 +302,6 @@ int ceph_wait_for_latest_osdmap(struct ceph_client *client, /* pagevec.c */ extern void ceph_release_page_vector(struct page **pages, int num_pages); - -extern struct page **ceph_get_direct_page_vector(const void __user *data, - int num_pages, - bool write_page); extern void ceph_put_page_vector(struct page **pages, int num_pages, bool dirty); extern struct page **ceph_alloc_page_vector(int num_pages, gfp_t flags); diff --git a/include/linux/ceph/messenger.h b/include/linux/ceph/messenger.h index 23895d178149..c4458dc6a757 100644 --- a/include/linux/ceph/messenger.h +++ b/include/linux/ceph/messenger.h @@ -337,6 +337,7 @@ extern void ceph_msgr_flush(void); extern void ceph_messenger_init(struct ceph_messenger *msgr, struct ceph_entity_addr *myaddr); extern void ceph_messenger_fini(struct ceph_messenger *msgr); +extern void ceph_messenger_reset_nonce(struct ceph_messenger *msgr); extern void ceph_con_init(struct ceph_connection *con, void *private, const struct ceph_connection_operations *ops, diff --git a/include/linux/ceph/mon_client.h b/include/linux/ceph/mon_client.h index 3a4688af7455..dbb8a6959a73 100644 --- a/include/linux/ceph/mon_client.h +++ b/include/linux/ceph/mon_client.h @@ -104,12 +104,12 @@ struct ceph_mon_client { #endif }; -extern struct ceph_monmap *ceph_monmap_decode(void *p, void *end); extern int ceph_monmap_contains(struct ceph_monmap *m, struct ceph_entity_addr *addr); extern int ceph_monc_init(struct ceph_mon_client *monc, struct ceph_client *cl); extern void ceph_monc_stop(struct ceph_mon_client *monc); +extern void ceph_monc_reopen_session(struct ceph_mon_client *monc); enum { CEPH_SUB_MONMAP = 0, diff --git a/include/linux/ceph/osd_client.h b/include/linux/ceph/osd_client.h index 2294f963dab7..eaffbdddf89a 100644 --- a/include/linux/ceph/osd_client.h +++ b/include/linux/ceph/osd_client.h @@ -198,9 +198,9 @@ struct ceph_osd_request { bool r_mempool; struct completion r_completion; /* private to osd_client.c */ ceph_osdc_callback_t r_callback; - struct list_head r_unsafe_item; struct inode *r_inode; /* for use by callbacks */ + struct list_head r_private_item; /* ditto */ void *r_priv; /* ditto */ /* set by submitter */ @@ -381,6 +381,7 @@ extern void ceph_osdc_cleanup(void); extern int ceph_osdc_init(struct ceph_osd_client *osdc, struct ceph_client *client); extern void ceph_osdc_stop(struct ceph_osd_client *osdc); +extern void ceph_osdc_reopen_osds(struct ceph_osd_client *osdc); extern void ceph_osdc_handle_reply(struct ceph_osd_client *osdc, struct ceph_msg *msg); @@ -388,6 +389,15 @@ extern void ceph_osdc_handle_map(struct ceph_osd_client *osdc, struct ceph_msg *msg); void ceph_osdc_update_epoch_barrier(struct ceph_osd_client *osdc, u32 eb); void ceph_osdc_abort_requests(struct ceph_osd_client *osdc, int err); +void ceph_osdc_clear_abort_err(struct ceph_osd_client *osdc); + +#define osd_req_op_data(oreq, whch, typ, fld) \ +({ \ + struct ceph_osd_request *__oreq = (oreq); \ + unsigned int __whch = (whch); \ + BUG_ON(__whch >= __oreq->r_num_ops); \ + &__oreq->r_ops[__whch].typ.fld; \ +}) extern void osd_req_op_init(struct ceph_osd_request *osd_req, unsigned int which, u16 opcode, u32 flags); @@ -497,7 +507,7 @@ int ceph_osdc_call(struct ceph_osd_client *osdc, const char *class, const char *method, unsigned int flags, struct page *req_page, size_t req_len, - struct page *resp_page, size_t *resp_len); + struct page **resp_pages, size_t *resp_len); extern int ceph_osdc_readpages(struct ceph_osd_client *osdc, struct ceph_vino vino, diff --git a/include/linux/ceph/striper.h b/include/linux/ceph/striper.h index cbd0d24b7148..3486636c0e6e 100644 --- a/include/linux/ceph/striper.h +++ b/include/linux/ceph/striper.h @@ -66,4 +66,6 @@ int ceph_extent_to_file(struct ceph_file_layout *l, struct ceph_file_extent **file_extents, u32 *num_file_extents); +u64 ceph_get_num_objects(struct ceph_file_layout *l, u64 size); + #endif diff --git a/include/linux/cgroup-defs.h b/include/linux/cgroup-defs.h index b4e766e93f6e..430e219e3aba 100644 --- a/include/linux/cgroup-defs.h +++ b/include/linux/cgroup-defs.h @@ -624,7 +624,7 @@ struct cftype { /* * Control Group subsystem type. - * See Documentation/cgroup-v1/cgroups.txt for details + * See Documentation/admin-guide/cgroup-v1/cgroups.rst for details */ struct cgroup_subsys { struct cgroup_subsys_state *(*css_alloc)(struct cgroup_subsys_state *parent_css); diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h index 0297f930a56e..3ba3e6da13a6 100644 --- a/include/linux/cgroup.h +++ b/include/linux/cgroup.h @@ -131,6 +131,8 @@ void cgroup_free(struct task_struct *p); int cgroup_init_early(void); int cgroup_init(void); +int cgroup_parse_float(const char *input, unsigned dec_shift, s64 *v); + /* * Iteration helpers and macros. */ @@ -148,6 +150,7 @@ struct task_struct *cgroup_taskset_first(struct cgroup_taskset *tset, struct task_struct *cgroup_taskset_next(struct cgroup_taskset *tset, struct cgroup_subsys_state **dst_cssp); +void cgroup_enable_task_cg_lists(void); void css_task_iter_start(struct cgroup_subsys_state *css, unsigned int flags, struct css_task_iter *it); struct task_struct *css_task_iter_next(struct css_task_iter *it); @@ -697,6 +700,7 @@ void cgroup_path_from_kernfs_id(const union kernfs_node_id *id, struct cgroup_subsys_state; struct cgroup; +static inline void css_get(struct cgroup_subsys_state *css) {} static inline void css_put(struct cgroup_subsys_state *css) {} static inline int cgroup_attach_task_all(struct task_struct *from, struct task_struct *t) { return 0; } @@ -934,4 +938,22 @@ static inline bool cgroup_task_frozen(struct task_struct *task) #endif /* !CONFIG_CGROUPS */ +#ifdef CONFIG_CGROUP_BPF +static inline void cgroup_bpf_get(struct cgroup *cgrp) +{ + percpu_ref_get(&cgrp->bpf.refcnt); +} + +static inline void cgroup_bpf_put(struct cgroup *cgrp) +{ + percpu_ref_put(&cgrp->bpf.refcnt); +} + +#else /* CONFIG_CGROUP_BPF */ + +static inline void cgroup_bpf_get(struct cgroup *cgrp) {} +static inline void cgroup_bpf_put(struct cgroup *cgrp) {} + +#endif /* CONFIG_CGROUP_BPF */ + #endif /* _LINUX_CGROUP_H */ diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index bb6118f79784..2fdfe8061363 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h @@ -9,8 +9,6 @@ #include <linux/of.h> #include <linux/of_clk.h> -#ifdef CONFIG_COMMON_CLK - /* * flags used across common struct clk. these flags should only affect the * top-level framework. custom flags for dealing with hardware specifics @@ -301,7 +299,8 @@ struct clk_init_data { * into the clk API * * @init: pointer to struct clk_init_data that contains the init data shared - * with the common clock framework. + * with the common clock framework. This pointer will be set to NULL once + * a clk_register() variant is called on this clk_hw pointer. */ struct clk_hw { struct clk_core *core; @@ -807,11 +806,19 @@ void devm_clk_hw_unregister(struct device *dev, struct clk_hw *hw); /* helper functions */ const char *__clk_get_name(const struct clk *clk); const char *clk_hw_get_name(const struct clk_hw *hw); +#ifdef CONFIG_COMMON_CLK struct clk_hw *__clk_get_hw(struct clk *clk); +#else +static inline struct clk_hw *__clk_get_hw(struct clk *clk) +{ + return (struct clk_hw *)clk; +} +#endif unsigned int clk_hw_get_num_parents(const struct clk_hw *hw); struct clk_hw *clk_hw_get_parent(const struct clk_hw *hw); struct clk_hw *clk_hw_get_parent_by_index(const struct clk_hw *hw, unsigned int index); +int clk_hw_set_parent(struct clk_hw *hw, struct clk_hw *new_parent); unsigned int __clk_get_enable_count(struct clk *clk); unsigned long clk_hw_get_rate(const struct clk_hw *hw); unsigned long __clk_get_flags(struct clk *clk); @@ -867,8 +874,6 @@ static inline long divider_ro_round_rate(struct clk_hw *hw, unsigned long rate, */ unsigned long clk_hw_round_rate(struct clk_hw *hw, unsigned long rate); -struct of_device_id; - struct clk_onecell_data { struct clk **clks; unsigned int clk_num; @@ -879,8 +884,6 @@ struct clk_hw_onecell_data { struct clk_hw *hws[]; }; -extern struct of_device_id __clk_of_table; - #define CLK_OF_DECLARE(name, compat, fn) OF_DECLARE_1(clk, name, compat, fn) /* @@ -904,6 +907,40 @@ extern struct of_device_id __clk_of_table; .ops = _ops, \ }) +#define CLK_HW_INIT_HW(_name, _parent, _ops, _flags) \ + (&(struct clk_init_data) { \ + .flags = _flags, \ + .name = _name, \ + .parent_hws = (const struct clk_hw*[]) { _parent }, \ + .num_parents = 1, \ + .ops = _ops, \ + }) + +/* + * This macro is intended for drivers to be able to share the otherwise + * individual struct clk_hw[] compound literals created by the compiler + * when using CLK_HW_INIT_HW. It does NOT support multiple parents. + */ +#define CLK_HW_INIT_HWS(_name, _parent, _ops, _flags) \ + (&(struct clk_init_data) { \ + .flags = _flags, \ + .name = _name, \ + .parent_hws = _parent, \ + .num_parents = 1, \ + .ops = _ops, \ + }) + +#define CLK_HW_INIT_FW_NAME(_name, _parent, _ops, _flags) \ + (&(struct clk_init_data) { \ + .flags = _flags, \ + .name = _name, \ + .parent_data = (const struct clk_parent_data[]) { \ + { .fw_name = _parent }, \ + }, \ + .num_parents = 1, \ + .ops = _ops, \ + }) + #define CLK_HW_INIT_PARENTS(_name, _parents, _ops, _flags) \ (&(struct clk_init_data) { \ .flags = _flags, \ @@ -913,6 +950,24 @@ extern struct of_device_id __clk_of_table; .ops = _ops, \ }) +#define CLK_HW_INIT_PARENTS_HW(_name, _parents, _ops, _flags) \ + (&(struct clk_init_data) { \ + .flags = _flags, \ + .name = _name, \ + .parent_hws = _parents, \ + .num_parents = ARRAY_SIZE(_parents), \ + .ops = _ops, \ + }) + +#define CLK_HW_INIT_PARENTS_DATA(_name, _parents, _ops, _flags) \ + (&(struct clk_init_data) { \ + .flags = _flags, \ + .name = _name, \ + .parent_data = _parents, \ + .num_parents = ARRAY_SIZE(_parents), \ + .ops = _ops, \ + }) + #define CLK_HW_INIT_NO_PARENT(_name, _ops, _flags) \ (&(struct clk_init_data) { \ .flags = _flags, \ @@ -933,6 +988,43 @@ extern struct of_device_id __clk_of_table; _flags), \ } +#define CLK_FIXED_FACTOR_HW(_struct, _name, _parent, \ + _div, _mult, _flags) \ + struct clk_fixed_factor _struct = { \ + .div = _div, \ + .mult = _mult, \ + .hw.init = CLK_HW_INIT_HW(_name, \ + _parent, \ + &clk_fixed_factor_ops, \ + _flags), \ + } + +/* + * This macro allows the driver to reuse the _parent array for multiple + * fixed factor clk declarations. + */ +#define CLK_FIXED_FACTOR_HWS(_struct, _name, _parent, \ + _div, _mult, _flags) \ + struct clk_fixed_factor _struct = { \ + .div = _div, \ + .mult = _mult, \ + .hw.init = CLK_HW_INIT_HWS(_name, \ + _parent, \ + &clk_fixed_factor_ops, \ + _flags), \ + } + +#define CLK_FIXED_FACTOR_FW_NAME(_struct, _name, _parent, \ + _div, _mult, _flags) \ + struct clk_fixed_factor _struct = { \ + .div = _div, \ + .mult = _mult, \ + .hw.init = CLK_HW_INIT_FW_NAME(_name, \ + _parent, \ + &clk_fixed_factor_ops, \ + _flags), \ + } + #ifdef CONFIG_OF int of_clk_add_provider(struct device_node *np, struct clk *(*clk_src_get)(struct of_phandle_args *args, @@ -1019,5 +1111,4 @@ static inline int of_clk_detect_critical(struct device_node *np, int index, void clk_gate_restore_context(struct clk_hw *hw); -#endif /* CONFIG_COMMON_CLK */ #endif /* CLK_PROVIDER_H */ diff --git a/include/linux/clk.h b/include/linux/clk.h index c8e3325868bd..18b7b95a8253 100644 --- a/include/linux/clk.h +++ b/include/linux/clk.h @@ -239,7 +239,8 @@ static inline int clk_prepare(struct clk *clk) return 0; } -static inline int __must_check clk_bulk_prepare(int num_clks, struct clk_bulk_data *clks) +static inline int __must_check +clk_bulk_prepare(int num_clks, const struct clk_bulk_data *clks) { might_sleep(); return 0; @@ -263,7 +264,8 @@ static inline void clk_unprepare(struct clk *clk) { might_sleep(); } -static inline void clk_bulk_unprepare(int num_clks, struct clk_bulk_data *clks) +static inline void clk_bulk_unprepare(int num_clks, + const struct clk_bulk_data *clks) { might_sleep(); } @@ -329,6 +331,19 @@ int __must_check clk_bulk_get(struct device *dev, int num_clks, */ int __must_check clk_bulk_get_all(struct device *dev, struct clk_bulk_data **clks); + +/** + * clk_bulk_get_optional - lookup and obtain a number of references to clock producer + * @dev: device for clock "consumer" + * @num_clks: the number of clk_bulk_data + * @clks: the clk_bulk_data table of consumer + * + * Behaves the same as clk_bulk_get() except where there is no clock producer. + * In this case, instead of returning -ENOENT, the function returns 0 and + * NULL for a clk for which a clock producer could not be determined. + */ +int __must_check clk_bulk_get_optional(struct device *dev, int num_clks, + struct clk_bulk_data *clks); /** * devm_clk_bulk_get - managed get multiple clk consumers * @dev: device for clock "consumer" @@ -344,6 +359,29 @@ int __must_check clk_bulk_get_all(struct device *dev, int __must_check devm_clk_bulk_get(struct device *dev, int num_clks, struct clk_bulk_data *clks); /** + * devm_clk_bulk_get_optional - managed get multiple optional consumer clocks + * @dev: device for clock "consumer" + * @num_clks: the number of clk_bulk_data + * @clks: pointer to the clk_bulk_data table of consumer + * + * Behaves the same as devm_clk_bulk_get() except where there is no clock + * producer. In this case, instead of returning -ENOENT, the function returns + * NULL for given clk. It is assumed all clocks in clk_bulk_data are optional. + * + * Returns 0 if all clocks specified in clk_bulk_data table are obtained + * successfully or for any clk there was no clk provider available, otherwise + * returns valid IS_ERR() condition containing errno. + * The implementation uses @dev and @clk_bulk_data.id to determine the + * clock consumer, and thereby the clock producer. + * The clock returned is stored in each @clk_bulk_data.clk field. + * + * Drivers must assume that the clock source is not enabled. + * + * clk_bulk_get should not be called from within interrupt context. + */ +int __must_check devm_clk_bulk_get_optional(struct device *dev, int num_clks, + struct clk_bulk_data *clks); +/** * devm_clk_bulk_get_all - managed get multiple clk consumers * @dev: device for clock "consumer" * @clks: pointer to the clk_bulk_data table of consumer @@ -715,6 +753,12 @@ static inline int __must_check clk_bulk_get(struct device *dev, int num_clks, return 0; } +static inline int __must_check clk_bulk_get_optional(struct device *dev, + int num_clks, struct clk_bulk_data *clks) +{ + return 0; +} + static inline int __must_check clk_bulk_get_all(struct device *dev, struct clk_bulk_data **clks) { @@ -738,6 +782,12 @@ static inline int __must_check devm_clk_bulk_get(struct device *dev, int num_clk return 0; } +static inline int __must_check devm_clk_bulk_get_optional(struct device *dev, + int num_clks, struct clk_bulk_data *clks) +{ + return 0; +} + static inline int __must_check devm_clk_bulk_get_all(struct device *dev, struct clk_bulk_data **clks) { @@ -772,7 +822,8 @@ static inline int clk_enable(struct clk *clk) return 0; } -static inline int __must_check clk_bulk_enable(int num_clks, struct clk_bulk_data *clks) +static inline int __must_check clk_bulk_enable(int num_clks, + const struct clk_bulk_data *clks) { return 0; } @@ -781,7 +832,7 @@ static inline void clk_disable(struct clk *clk) {} static inline void clk_bulk_disable(int num_clks, - struct clk_bulk_data *clks) {} + const struct clk_bulk_data *clks) {} static inline unsigned long clk_get_rate(struct clk *clk) { @@ -870,8 +921,8 @@ static inline void clk_disable_unprepare(struct clk *clk) clk_unprepare(clk); } -static inline int __must_check clk_bulk_prepare_enable(int num_clks, - struct clk_bulk_data *clks) +static inline int __must_check +clk_bulk_prepare_enable(int num_clks, const struct clk_bulk_data *clks) { int ret; @@ -886,7 +937,7 @@ static inline int __must_check clk_bulk_prepare_enable(int num_clks, } static inline void clk_bulk_disable_unprepare(int num_clks, - struct clk_bulk_data *clks) + const struct clk_bulk_data *clks) { clk_bulk_disable(num_clks, clks); clk_bulk_unprepare(num_clks, clks); diff --git a/include/linux/clk/clk-conf.h b/include/linux/clk/clk-conf.h index 85f8cf9d1226..eae9652c70cd 100644 --- a/include/linux/clk/clk-conf.h +++ b/include/linux/clk/clk-conf.h @@ -4,6 +4,9 @@ * Sylwester Nawrocki <s.nawrocki@samsung.com> */ +#ifndef __CLK_CONF_H +#define __CLK_CONF_H + #include <linux/types.h> struct device_node; @@ -17,3 +20,5 @@ static inline int of_clk_set_defaults(struct device_node *node, return 0; } #endif + +#endif /* __CLK_CONF_H */ diff --git a/include/linux/coda.h b/include/linux/coda.h index d30209b9cef8..0ca0c83fdb1c 100644 --- a/include/linux/coda.h +++ b/include/linux/coda.h @@ -58,8 +58,7 @@ Mellon the rights to redistribute these changes without encumbrance. #ifndef _CODA_HEADER_ #define _CODA_HEADER_ -#if defined(__linux__) typedef unsigned long long u_quad_t; -#endif + #include <uapi/linux/coda.h> #endif diff --git a/include/linux/coda_psdev.h b/include/linux/coda_psdev.h deleted file mode 100644 index 15170954aa2b..000000000000 --- a/include/linux/coda_psdev.h +++ /dev/null @@ -1,72 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef __CODA_PSDEV_H -#define __CODA_PSDEV_H - -#include <linux/backing-dev.h> -#include <linux/mutex.h> -#include <uapi/linux/coda_psdev.h> - -struct kstatfs; - -/* communication pending/processing queues */ -struct venus_comm { - u_long vc_seq; - wait_queue_head_t vc_waitq; /* Venus wait queue */ - struct list_head vc_pending; - struct list_head vc_processing; - int vc_inuse; - struct super_block *vc_sb; - struct mutex vc_mutex; -}; - - -static inline struct venus_comm *coda_vcp(struct super_block *sb) -{ - return (struct venus_comm *)((sb)->s_fs_info); -} - -/* upcalls */ -int venus_rootfid(struct super_block *sb, struct CodaFid *fidp); -int venus_getattr(struct super_block *sb, struct CodaFid *fid, - struct coda_vattr *attr); -int venus_setattr(struct super_block *, struct CodaFid *, struct coda_vattr *); -int venus_lookup(struct super_block *sb, struct CodaFid *fid, - const char *name, int length, int *type, - struct CodaFid *resfid); -int venus_close(struct super_block *sb, struct CodaFid *fid, int flags, - kuid_t uid); -int venus_open(struct super_block *sb, struct CodaFid *fid, int flags, - struct file **f); -int venus_mkdir(struct super_block *sb, struct CodaFid *dirfid, - const char *name, int length, - struct CodaFid *newfid, struct coda_vattr *attrs); -int venus_create(struct super_block *sb, struct CodaFid *dirfid, - const char *name, int length, int excl, int mode, - struct CodaFid *newfid, struct coda_vattr *attrs) ; -int venus_rmdir(struct super_block *sb, struct CodaFid *dirfid, - const char *name, int length); -int venus_remove(struct super_block *sb, struct CodaFid *dirfid, - const char *name, int length); -int venus_readlink(struct super_block *sb, struct CodaFid *fid, - char *buffer, int *length); -int venus_rename(struct super_block *, struct CodaFid *new_fid, - struct CodaFid *old_fid, size_t old_length, - size_t new_length, const char *old_name, - const char *new_name); -int venus_link(struct super_block *sb, struct CodaFid *fid, - struct CodaFid *dirfid, const char *name, int len ); -int venus_symlink(struct super_block *sb, struct CodaFid *fid, - const char *name, int len, const char *symname, int symlen); -int venus_access(struct super_block *sb, struct CodaFid *fid, int mask); -int venus_pioctl(struct super_block *sb, struct CodaFid *fid, - unsigned int cmd, struct PioctlData *data); -int coda_downcall(struct venus_comm *vcp, int opcode, union outputArgs *out); -int venus_fsync(struct super_block *sb, struct CodaFid *fid); -int venus_statfs(struct dentry *dentry, struct kstatfs *sfs); - -/* - * Statistics - */ - -extern struct venus_comm coda_comms[]; -#endif diff --git a/include/linux/compaction.h b/include/linux/compaction.h index 9569e7c786d3..4b898cdbdf05 100644 --- a/include/linux/compaction.h +++ b/include/linux/compaction.h @@ -129,11 +129,8 @@ static inline bool compaction_failed(enum compact_result result) return false; } -/* - * Compaction has backed off for some reason. It might be throttling or - * lock contention. Retrying is still worthwhile. - */ -static inline bool compaction_withdrawn(enum compact_result result) +/* Compaction needs reclaim to be performed first, so it can continue. */ +static inline bool compaction_needs_reclaim(enum compact_result result) { /* * Compaction backed off due to watermark checks for order-0 @@ -142,6 +139,16 @@ static inline bool compaction_withdrawn(enum compact_result result) if (result == COMPACT_SKIPPED) return true; + return false; +} + +/* + * Compaction has backed off for some reason after doing some work or none + * at all. It might be throttling or lock contention. Retrying might be still + * worthwhile, but with a higher priority if allowed. + */ +static inline bool compaction_withdrawn(enum compact_result result) +{ /* * If compaction is deferred for high-order allocations, it is * because sync compaction recently failed. If this is the case @@ -207,6 +214,11 @@ static inline bool compaction_failed(enum compact_result result) return false; } +static inline bool compaction_needs_reclaim(enum compact_result result) +{ + return false; +} + static inline bool compaction_withdrawn(enum compact_result result) { return true; diff --git a/include/linux/compat.h b/include/linux/compat.h index ebddcb6cfcf8..16dafd9f4b86 100644 --- a/include/linux/compat.h +++ b/include/linux/compat.h @@ -138,8 +138,7 @@ typedef struct { compat_sigset_word sig[_COMPAT_NSIG_WORDS]; } compat_sigset_t; -int set_compat_user_sigmask(const compat_sigset_t __user *usigmask, - sigset_t *set, sigset_t *oldset, +int set_compat_user_sigmask(const compat_sigset_t __user *umask, size_t sigsetsize); struct compat_sigaction { diff --git a/include/linux/compiler-gcc.h b/include/linux/compiler-gcc.h index e8579412ad21..d7ee4c6bad48 100644 --- a/include/linux/compiler-gcc.h +++ b/include/linux/compiler-gcc.h @@ -170,3 +170,5 @@ #else #define __diag_GCC_8(s) #endif + +#define __no_fgcse __attribute__((optimize("-fno-gcse"))) diff --git a/include/linux/compiler.h b/include/linux/compiler.h index 8aaf7cd026b0..5e88e7e33abe 100644 --- a/include/linux/compiler.h +++ b/include/linux/compiler.h @@ -24,7 +24,7 @@ void ftrace_likely_update(struct ftrace_likely_data *f, int val, long ______r; \ static struct ftrace_likely_data \ __aligned(4) \ - __section("_ftrace_annotated_branch") \ + __section(_ftrace_annotated_branch) \ ______f = { \ .data.func = __func__, \ .data.file = __FILE__, \ @@ -60,7 +60,7 @@ void ftrace_likely_update(struct ftrace_likely_data *f, int val, #define __trace_if_value(cond) ({ \ static struct ftrace_branch_data \ __aligned(4) \ - __section("_ftrace_branch") \ + __section(_ftrace_branch) \ __if_trace = { \ .func = __func__, \ .file = __FILE__, \ @@ -116,9 +116,14 @@ void ftrace_likely_update(struct ftrace_likely_data *f, int val, ".pushsection .discard.unreachable\n\t" \ ".long 999b - .\n\t" \ ".popsection\n\t" + +/* Annotate a C jump table to allow objtool to follow the code flow */ +#define __annotate_jump_table __section(.rodata..c_jump_table) + #else #define annotate_reachable() #define annotate_unreachable() +#define __annotate_jump_table #endif #ifndef ASM_UNREACHABLE @@ -293,7 +298,7 @@ unsigned long read_word_at_a_time(const void *addr) * visible to the compiler. */ #define __ADDRESSABLE(sym) \ - static void * __section(".discard.addressable") __used \ + static void * __section(.discard.addressable) __used \ __PASTE(__addressable_##sym, __LINE__) = (void *)&sym; /** diff --git a/include/linux/compiler_types.h b/include/linux/compiler_types.h index 19e58b9138a0..72393a8c1a6c 100644 --- a/include/linux/compiler_types.h +++ b/include/linux/compiler_types.h @@ -112,6 +112,8 @@ struct ftrace_likely_data { #if defined(CC_USING_HOTPATCH) #define notrace __attribute__((hotpatch(0, 0))) +#elif defined(CC_USING_PATCHABLE_FUNCTION_ENTRY) +#define notrace __attribute__((patchable_function_entry(0, 0))) #else #define notrace __attribute__((__no_instrument_function__)) #endif @@ -128,10 +130,6 @@ struct ftrace_likely_data { /* * Force always-inline if the user requests it so via the .config. - * GCC does not warn about unused static inline functions for - * -Wunused-function. This turns out to avoid the need for complex #ifdef - * directives. Suppress the warning in clang as well by using "unused" - * function attribute, which is redundant but not harmful for gcc. * Prefer gnu_inline, so that extern inline functions do not emit an * externally visible function. This makes extern inline behave as per gnu89 * semantics rather than c99. This prevents multiple symbol definition errors @@ -142,14 +140,35 @@ struct ftrace_likely_data { */ #if !defined(CONFIG_OPTIMIZE_INLINING) #define inline inline __attribute__((__always_inline__)) __gnu_inline \ - __maybe_unused notrace + __inline_maybe_unused notrace #else #define inline inline __gnu_inline \ - __maybe_unused notrace + __inline_maybe_unused notrace #endif +/* + * gcc provides both __inline__ and __inline as alternate spellings of + * the inline keyword, though the latter is undocumented. New kernel + * code should only use the inline spelling, but some existing code + * uses __inline__. Since we #define inline above, to ensure + * __inline__ has the same semantics, we need this #define. + * + * However, the spelling __inline is strictly reserved for referring + * to the bare keyword. + */ #define __inline__ inline -#define __inline inline + +/* + * GCC does not warn about unused static inline functions for -Wunused-function. + * Suppress the warning in clang as well by using __maybe_unused, but enable it + * for W=1 build. This will allow clang to find unused functions. Remove the + * __inline_maybe_unused entirely after fixing most of -Wunused-function warnings. + */ +#ifdef KBUILD_EXTRA_WARN1 +#define __inline_maybe_unused +#else +#define __inline_maybe_unused __maybe_unused +#endif /* * Rather then using noinline to prevent stack consumption, use @@ -187,6 +206,16 @@ struct ftrace_likely_data { #define asm_volatile_goto(x...) asm goto(x) #endif +#ifdef CONFIG_CC_HAS_ASM_INLINE +#define asm_inline asm __inline +#else +#define asm_inline asm +#endif + +#ifndef __no_fgcse +# define __no_fgcse +#endif + /* Are two types/vars the same type (ignoring qualifiers)? */ #define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b)) diff --git a/include/linux/concap.h b/include/linux/concap.h deleted file mode 100644 index 977acb3d1fb2..000000000000 --- a/include/linux/concap.h +++ /dev/null @@ -1,112 +0,0 @@ -/* $Id: concap.h,v 1.3.2.2 2004/01/12 23:08:35 keil Exp $ - * - * Copyright 1997 by Henner Eisen <eis@baty.hanse.de> - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - */ - -#ifndef _LINUX_CONCAP_H -#define _LINUX_CONCAP_H - -#include <linux/skbuff.h> -#include <linux/netdevice.h> - -/* Stuff to support encapsulation protocols genericly. The encapsulation - protocol is processed at the uppermost layer of the network interface. - - Based on a ideas developed in a 'synchronous device' thread in the - linux-x25 mailing list contributed by Alan Cox, Thomasz Motylewski - and Jonathan Naylor. - - For more documetation on this refer to Documentation/isdn/README.concap -*/ - -struct concap_proto_ops; -struct concap_device_ops; - -/* this manages all data needed by the encapsulation protocol - */ -struct concap_proto{ - struct net_device *net_dev; /* net device using our service */ - struct concap_device_ops *dops; /* callbacks provided by device */ - struct concap_proto_ops *pops; /* callbacks provided by us */ - spinlock_t lock; - int flags; - void *proto_data; /* protocol specific private data, to - be accessed via *pops methods only*/ - /* - : - whatever - : - */ -}; - -/* Operations to be supported by the net device. Called by the encapsulation - * protocol entity. No receive method is offered because the encapsulation - * protocol directly calls netif_rx(). - */ -struct concap_device_ops{ - - /* to request data is submitted by device*/ - int (*data_req)(struct concap_proto *, struct sk_buff *); - - /* Control methods must be set to NULL by devices which do not - support connection control.*/ - /* to request a connection is set up */ - int (*connect_req)(struct concap_proto *); - - /* to request a connection is released */ - int (*disconn_req)(struct concap_proto *); -}; - -/* Operations to be supported by the encapsulation protocol. Called by - * device driver. - */ -struct concap_proto_ops{ - - /* create a new encapsulation protocol instance of same type */ - struct concap_proto * (*proto_new) (void); - - /* delete encapsulation protocol instance and free all its resources. - cprot may no loger be referenced after calling this */ - void (*proto_del)(struct concap_proto *cprot); - - /* initialize the protocol's data. To be called at interface startup - or when the device driver resets the interface. All services of the - encapsulation protocol may be used after this*/ - int (*restart)(struct concap_proto *cprot, - struct net_device *ndev, - struct concap_device_ops *dops); - - /* inactivate an encapsulation protocol instance. The encapsulation - protocol may not call any *dops methods after this. */ - int (*close)(struct concap_proto *cprot); - - /* process a frame handed down to us by upper layer */ - int (*encap_and_xmit)(struct concap_proto *cprot, struct sk_buff *skb); - - /* to be called for each data entity received from lower layer*/ - int (*data_ind)(struct concap_proto *cprot, struct sk_buff *skb); - - /* to be called when a connection was set up/down. - Protocols that don't process these primitives might fill in - dummy methods here */ - int (*connect_ind)(struct concap_proto *cprot); - int (*disconn_ind)(struct concap_proto *cprot); - /* - Some network device support functions, like net_header(), rebuild_header(), - and others, that depend solely on the encapsulation protocol, might - be provided here, too. The net device would just fill them in its - corresponding fields when it is opened. - */ -}; - -/* dummy restart/close/connect/reset/disconn methods - */ -extern int concap_nop(struct concap_proto *cprot); - -/* dummy submit method - */ -extern int concap_drop_skb(struct concap_proto *cprot, struct sk_buff *skb); -#endif diff --git a/include/linux/connector.h b/include/linux/connector.h index 1d72ef76f24f..cb732643471b 100644 --- a/include/linux/connector.h +++ b/include/linux/connector.h @@ -50,15 +50,75 @@ struct cn_dev { u32 seq, groups; struct sock *nls; - void (*input) (struct sk_buff *skb); struct cn_queue_dev *cbdev; }; +/** + * cn_add_callback() - Registers new callback with connector core. + * + * @id: unique connector's user identifier. + * It must be registered in connector.h for legal + * in-kernel users. + * @name: connector's callback symbolic name. + * @callback: connector's callback. + * parameters are %cn_msg and the sender's credentials + */ int cn_add_callback(struct cb_id *id, const char *name, void (*callback)(struct cn_msg *, struct netlink_skb_parms *)); -void cn_del_callback(struct cb_id *); +/** + * cn_del_callback() - Unregisters new callback with connector core. + * + * @id: unique connector's user identifier. + */ +void cn_del_callback(struct cb_id *id); + + +/** + * cn_netlink_send_mult - Sends message to the specified groups. + * + * @msg: message header(with attached data). + * @len: Number of @msg to be sent. + * @portid: destination port. + * If non-zero the message will be sent to the given port, + * which should be set to the original sender. + * @group: destination group. + * If @portid and @group is zero, then appropriate group will + * be searched through all registered connector users, and + * message will be delivered to the group which was created + * for user with the same ID as in @msg. + * If @group is not zero, then message will be delivered + * to the specified group. + * @gfp_mask: GFP mask. + * + * It can be safely called from softirq context, but may silently + * fail under strong memory pressure. + * + * If there are no listeners for given group %-ESRCH can be returned. + */ int cn_netlink_send_mult(struct cn_msg *msg, u16 len, u32 portid, u32 group, gfp_t gfp_mask); + +/** + * cn_netlink_send_mult - Sends message to the specified groups. + * + * @msg: message header(with attached data). + * @portid: destination port. + * If non-zero the message will be sent to the given port, + * which should be set to the original sender. + * @group: destination group. + * If @portid and @group is zero, then appropriate group will + * be searched through all registered connector users, and + * message will be delivered to the group which was created + * for user with the same ID as in @msg. + * If @group is not zero, then message will be delivered + * to the specified group. + * @gfp_mask: GFP mask. + * + * It can be safely called from softirq context, but may silently + * fail under strong memory pressure. + * + * If there are no listeners for given group %-ESRCH can be returned. + */ int cn_netlink_send(struct cn_msg *msg, u32 portid, u32 group, gfp_t gfp_mask); int cn_queue_add_callback(struct cn_queue_dev *dev, const char *name, diff --git a/include/linux/console_struct.h b/include/linux/console_struct.h index ed798e114663..24d4c16e3ae0 100644 --- a/include/linux/console_struct.h +++ b/include/linux/console_struct.h @@ -168,9 +168,6 @@ extern void vc_SAK(struct work_struct *work); #define CUR_DEFAULT CUR_UNDERLINE -static inline bool con_is_visible(const struct vc_data *vc) -{ - return *vc->vc_display_fg == vc; -} +bool con_is_visible(const struct vc_data *vc); #endif /* _LINUX_CONSOLE_STRUCT_H */ diff --git a/include/linux/container.h b/include/linux/container.h index 0cc2ee91905c..2566a1baa736 100644 --- a/include/linux/container.h +++ b/include/linux/container.h @@ -6,6 +6,9 @@ * Author: Rafael J. Wysocki <rafael.j.wysocki@intel.com> */ +#ifndef _LINUX_CONTAINER_H +#define _LINUX_CONTAINER_H + #include <linux/device.h> /* drivers/base/power/container.c */ @@ -20,3 +23,5 @@ static inline struct container_dev *to_container_dev(struct device *dev) { return container_of(dev, struct container_dev, dev); } + +#endif /* _LINUX_CONTAINER_H */ diff --git a/include/linux/coresight.h b/include/linux/coresight.h index 62a520df8add..a2b68823717b 100644 --- a/include/linux/coresight.h +++ b/include/linux/coresight.h @@ -91,15 +91,11 @@ union coresight_dev_subtype { /** * struct coresight_platform_data - data harvested from the DT specification - * @cpu: the CPU a source belongs to. Only applicable for ETM/PTMs. - * @name: name of the component as shown under sysfs. * @nr_inport: number of input ports for this component. * @nr_outport: number of output ports for this component. * @conns: Array of nr_outport connections from this component */ struct coresight_platform_data { - int cpu; - const char *name; int nr_inport; int nr_outport; struct coresight_connection *conns; @@ -110,11 +106,12 @@ struct coresight_platform_data { * @type: as defined by @coresight_dev_type. * @subtype: as defined by @coresight_dev_subtype. * @ops: generic operations for this component, as defined - by @coresight_ops. + * by @coresight_ops. * @pdata: platform data collected from DT. * @dev: The device entity associated to this component. * @groups: operations specific to this component. These will end up - in the component's sysfs sub-directory. + * in the component's sysfs sub-directory. + * @name: name for the coresight device, also shown under sysfs. */ struct coresight_desc { enum coresight_dev_type type; @@ -123,28 +120,27 @@ struct coresight_desc { struct coresight_platform_data *pdata; struct device *dev; const struct attribute_group **groups; + const char *name; }; /** * struct coresight_connection - representation of a single connection * @outport: a connection's output port number. - * @chid_name: remote component's name. * @child_port: remote component's port number @output is connected to. + * @chid_fwnode: remote component's fwnode handle. * @child_dev: a @coresight_device representation of the component connected to @outport. */ struct coresight_connection { int outport; - const char *child_name; int child_port; + struct fwnode_handle *child_fwnode; struct coresight_device *child_dev; }; /** * struct coresight_device - representation of a device as used by the framework - * @conns: array of coresight_connections associated to this component. - * @nr_inport: number of input port associated to this component. - * @nr_outport: number of output port associated to this component. + * @pdata: Platform data with device connections associated to this device. * @type: as defined by @coresight_dev_type. * @subtype: as defined by @coresight_dev_subtype. * @ops: generic operations for this component, as defined @@ -159,9 +155,7 @@ struct coresight_connection { * @ea: Device attribute for sink representation under PMU directory. */ struct coresight_device { - struct coresight_connection *conns; - int nr_inport; - int nr_outport; + struct coresight_platform_data *pdata; enum coresight_dev_type type; union coresight_dev_subtype subtype; const struct coresight_ops *ops; @@ -174,6 +168,28 @@ struct coresight_device { struct dev_ext_attribute *ea; }; +/* + * coresight_dev_list - Mapping for devices to "name" index for device + * names. + * + * @nr_idx: Number of entries already allocated. + * @pfx: Prefix pattern for device name. + * @fwnode_list: Array of fwnode_handles associated with each allocated + * index, upto nr_idx entries. + */ +struct coresight_dev_list { + int nr_idx; + const char *pfx; + struct fwnode_handle **fwnode_list; +}; + +#define DEFINE_CORESIGHT_DEVLIST(var, dev_pfx) \ +static struct coresight_dev_list (var) = { \ + .pfx = dev_pfx, \ + .nr_idx = 0, \ + .fwnode_list = NULL, \ +} + #define to_coresight_device(d) container_of(d, struct coresight_device, dev) #define source_ops(csdev) csdev->ops->source_ops @@ -267,7 +283,8 @@ extern int coresight_claim_device_unlocked(void __iomem *base); extern void coresight_disclaim_device(void __iomem *base); extern void coresight_disclaim_device_unlocked(void __iomem *base); - +extern char *coresight_alloc_device_name(struct coresight_dev_list *devs, + struct device *dev); #else static inline struct coresight_device * coresight_register(struct coresight_desc *desc) { return NULL; } @@ -292,16 +309,8 @@ static inline void coresight_disclaim_device_unlocked(void __iomem *base) {} #endif -#ifdef CONFIG_OF -extern int of_coresight_get_cpu(const struct device_node *node); -extern struct coresight_platform_data * -of_get_coresight_platform_data(struct device *dev, - const struct device_node *node); -#else -static inline int of_coresight_get_cpu(const struct device_node *node) -{ return 0; } -static inline struct coresight_platform_data *of_get_coresight_platform_data( - struct device *dev, const struct device_node *node) { return NULL; } -#endif +extern int coresight_get_cpu(struct device *dev); + +struct coresight_platform_data *coresight_get_platform_data(struct device *dev); #endif diff --git a/include/linux/cpu.h b/include/linux/cpu.h index fcb1386bb0d4..d0633ebdaa9c 100644 --- a/include/linux/cpu.h +++ b/include/linux/cpu.h @@ -179,7 +179,7 @@ void arch_cpu_idle_dead(void); int cpu_report_state(int cpu); int cpu_check_up_prepare(int cpu); void cpu_set_state_online(int cpu); -void play_idle(unsigned long duration_ms); +void play_idle(unsigned long duration_us); #ifdef CONFIG_HOTPLUG_CPU bool cpu_wait_death(unsigned int cpu, int seconds); @@ -201,12 +201,14 @@ enum cpuhp_smt_control { extern enum cpuhp_smt_control cpu_smt_control; extern void cpu_smt_disable(bool force); extern void cpu_smt_check_topology(void); +extern bool cpu_smt_possible(void); extern int cpuhp_smt_enable(void); extern int cpuhp_smt_disable(enum cpuhp_smt_control ctrlval); #else # define cpu_smt_control (CPU_SMT_NOT_IMPLEMENTED) static inline void cpu_smt_disable(bool force) { } static inline void cpu_smt_check_topology(void) { } +static inline bool cpu_smt_possible(void) { return false; } static inline int cpuhp_smt_enable(void) { return 0; } static inline int cpuhp_smt_disable(enum cpuhp_smt_control ctrlval) { return 0; } #endif diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h index 32a1733014f5..c57e88e85c41 100644 --- a/include/linux/cpufreq.h +++ b/include/linux/cpufreq.h @@ -47,11 +47,6 @@ struct cpufreq_cpuinfo { unsigned int transition_latency; }; -struct cpufreq_user_policy { - unsigned int min; /* in kHz */ - unsigned int max; /* in kHz */ -}; - struct cpufreq_policy { /* CPUs sharing clock, require sw coordination */ cpumask_var_t cpus; /* Online CPUs only */ @@ -81,7 +76,8 @@ struct cpufreq_policy { struct work_struct update; /* if update_policy() needs to be * called, but you're in IRQ context */ - struct cpufreq_user_policy user_policy; + struct dev_pm_qos_request *min_freq_req; + struct dev_pm_qos_request *max_freq_req; struct cpufreq_frequency_table *freq_table; enum cpufreq_table_sorting freq_table_sorted; @@ -144,6 +140,9 @@ struct cpufreq_policy { /* Pointer to the cooling device if used for thermal mitigation */ struct thermal_cooling_device *cdev; + + struct notifier_block nb_min; + struct notifier_block nb_max; }; struct cpufreq_freqs { @@ -201,6 +200,7 @@ void cpufreq_cpu_release(struct cpufreq_policy *policy); int cpufreq_get_policy(struct cpufreq_policy *policy, unsigned int cpu); int cpufreq_set_policy(struct cpufreq_policy *policy, struct cpufreq_policy *new_policy); +void refresh_frequency_limits(struct cpufreq_policy *policy); void cpufreq_update_policy(unsigned int cpu); void cpufreq_update_limits(unsigned int cpu); bool have_governor_per_policy(void); @@ -406,6 +406,12 @@ int cpufreq_unregister_driver(struct cpufreq_driver *driver_data); const char *cpufreq_get_current_driver(void); void *cpufreq_get_driver_data(void); +static inline int cpufreq_thermal_control_enabled(struct cpufreq_driver *drv) +{ + return IS_ENABLED(CONFIG_CPU_THERMAL) && + (drv->flags & CPUFREQ_IS_COOLING_DEV); +} + static inline void cpufreq_verify_within_limits(struct cpufreq_policy *policy, unsigned int min, unsigned int max) { @@ -450,8 +456,8 @@ static inline void cpufreq_resume(void) {} #define CPUFREQ_POSTCHANGE (1) /* Policy Notifiers */ -#define CPUFREQ_ADJUST (0) -#define CPUFREQ_NOTIFY (1) +#define CPUFREQ_CREATE_POLICY (0) +#define CPUFREQ_REMOVE_POLICY (1) #ifdef CONFIG_CPU_FREQ int cpufreq_register_notifier(struct notifier_block *nb, unsigned int list); @@ -986,7 +992,7 @@ extern struct freq_attr *cpufreq_generic_attr[]; int cpufreq_table_validate_and_sort(struct cpufreq_policy *policy); unsigned int cpufreq_generic_get(unsigned int cpu); -int cpufreq_generic_init(struct cpufreq_policy *policy, +void cpufreq_generic_init(struct cpufreq_policy *policy, struct cpufreq_frequency_table *table, unsigned int transition_latency); #endif /* _LINUX_CPUFREQ_H */ diff --git a/include/linux/cpuhotplug.h b/include/linux/cpuhotplug.h index 5c6062206760..068793a619ca 100644 --- a/include/linux/cpuhotplug.h +++ b/include/linux/cpuhotplug.h @@ -116,10 +116,10 @@ enum cpuhp_state { CPUHP_AP_PERF_ARM_ACPI_STARTING, CPUHP_AP_PERF_ARM_STARTING, CPUHP_AP_ARM_L2X0_STARTING, + CPUHP_AP_EXYNOS4_MCT_TIMER_STARTING, CPUHP_AP_ARM_ARCH_TIMER_STARTING, CPUHP_AP_ARM_GLOBAL_TIMER_STARTING, CPUHP_AP_JCORE_TIMER_STARTING, - CPUHP_AP_EXYNOS4_MCT_TIMER_STARTING, CPUHP_AP_ARM_TWD_STARTING, CPUHP_AP_QCOM_TIMER_STARTING, CPUHP_AP_TEGRA_TIMER_STARTING, @@ -176,6 +176,7 @@ enum cpuhp_state { CPUHP_AP_WATCHDOG_ONLINE, CPUHP_AP_WORKQUEUE_ONLINE, CPUHP_AP_RCUTREE_ONLINE, + CPUHP_AP_BASE_CACHEINFO_ONLINE, CPUHP_AP_ONLINE_DYN, CPUHP_AP_ONLINE_DYN_END = CPUHP_AP_ONLINE_DYN + 30, CPUHP_AP_X86_HPET_ONLINE, diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h index bb9a0db89f1a..4b6b5bea8f79 100644 --- a/include/linux/cpuidle.h +++ b/include/linux/cpuidle.h @@ -85,7 +85,9 @@ struct cpuidle_device { unsigned int cpu; ktime_t next_hrtimer; + int last_state_idx; int last_residency; + u64 poll_limit_ns; struct cpuidle_state_usage states_usage[CPUIDLE_STATE_MAX]; struct cpuidle_state_kobj *kobjs[CPUIDLE_STATE_MAX]; struct cpuidle_driver_kobj *kobj_driver; @@ -119,6 +121,9 @@ struct cpuidle_driver { /* the driver handles the cpus in cpumask */ struct cpumask *cpumask; + + /* preferred governor to switch at register time */ + const char *governor; }; #ifdef CONFIG_CPU_IDLE @@ -132,6 +137,8 @@ extern int cpuidle_select(struct cpuidle_driver *drv, extern int cpuidle_enter(struct cpuidle_driver *drv, struct cpuidle_device *dev, int index); extern void cpuidle_reflect(struct cpuidle_device *dev, int index); +extern u64 cpuidle_poll_time(struct cpuidle_driver *drv, + struct cpuidle_device *dev); extern int cpuidle_register_driver(struct cpuidle_driver *drv); extern struct cpuidle_driver *cpuidle_get_driver(void); @@ -166,6 +173,9 @@ static inline int cpuidle_enter(struct cpuidle_driver *drv, struct cpuidle_device *dev, int index) {return -ENODEV; } static inline void cpuidle_reflect(struct cpuidle_device *dev, int index) { } +static inline u64 cpuidle_poll_time(struct cpuidle_driver *drv, + struct cpuidle_device *dev) +{return 0; } static inline int cpuidle_register_driver(struct cpuidle_driver *drv) {return -ENODEV; } static inline struct cpuidle_driver *cpuidle_get_driver(void) {return NULL; } @@ -256,7 +266,10 @@ static inline int cpuidle_register_governor(struct cpuidle_governor *gov) {return 0;} #endif -#define __CPU_PM_CPU_IDLE_ENTER(low_level_idle_enter, idx, is_retention) \ +#define __CPU_PM_CPU_IDLE_ENTER(low_level_idle_enter, \ + idx, \ + state, \ + is_retention) \ ({ \ int __ret = 0; \ \ @@ -268,7 +281,7 @@ static inline int cpuidle_register_governor(struct cpuidle_governor *gov) if (!is_retention) \ __ret = cpu_pm_enter(); \ if (!__ret) { \ - __ret = low_level_idle_enter(idx); \ + __ret = low_level_idle_enter(state); \ if (!is_retention) \ cpu_pm_exit(); \ } \ @@ -277,9 +290,15 @@ static inline int cpuidle_register_governor(struct cpuidle_governor *gov) }) #define CPU_PM_CPU_IDLE_ENTER(low_level_idle_enter, idx) \ - __CPU_PM_CPU_IDLE_ENTER(low_level_idle_enter, idx, 0) + __CPU_PM_CPU_IDLE_ENTER(low_level_idle_enter, idx, idx, 0) #define CPU_PM_CPU_IDLE_ENTER_RETENTION(low_level_idle_enter, idx) \ - __CPU_PM_CPU_IDLE_ENTER(low_level_idle_enter, idx, 1) + __CPU_PM_CPU_IDLE_ENTER(low_level_idle_enter, idx, idx, 1) + +#define CPU_PM_CPU_IDLE_ENTER_PARAM(low_level_idle_enter, idx, state) \ + __CPU_PM_CPU_IDLE_ENTER(low_level_idle_enter, idx, state, 0) + +#define CPU_PM_CPU_IDLE_ENTER_RETENTION_PARAM(low_level_idle_enter, idx, state) \ + __CPU_PM_CPU_IDLE_ENTER(low_level_idle_enter, idx, state, 1) #endif /* _LINUX_CPUIDLE_H */ diff --git a/include/linux/cpuidle_haltpoll.h b/include/linux/cpuidle_haltpoll.h new file mode 100644 index 000000000000..d50c1e0411a2 --- /dev/null +++ b/include/linux/cpuidle_haltpoll.h @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _CPUIDLE_HALTPOLL_H +#define _CPUIDLE_HALTPOLL_H + +#ifdef CONFIG_ARCH_CPUIDLE_HALTPOLL +#include <asm/cpuidle_haltpoll.h> +#else +static inline void arch_haltpoll_enable(unsigned int cpu) +{ +} + +static inline void arch_haltpoll_disable(unsigned int cpu) +{ +} +#endif +#endif diff --git a/include/linux/cpumask.h b/include/linux/cpumask.h index 21755471b1c3..78a73eba64dd 100644 --- a/include/linux/cpumask.h +++ b/include/linux/cpumask.h @@ -10,6 +10,7 @@ #include <linux/kernel.h> #include <linux/threads.h> #include <linux/bitmap.h> +#include <linux/atomic.h> #include <linux/bug.h> /* Don't assign or return these: may not be this big! */ @@ -95,8 +96,21 @@ extern struct cpumask __cpu_active_mask; #define cpu_present_mask ((const struct cpumask *)&__cpu_present_mask) #define cpu_active_mask ((const struct cpumask *)&__cpu_active_mask) +extern atomic_t __num_online_cpus; + #if NR_CPUS > 1 -#define num_online_cpus() cpumask_weight(cpu_online_mask) +/** + * num_online_cpus() - Read the number of online CPUs + * + * Despite the fact that __num_online_cpus is of type atomic_t, this + * interface gives only a momentary snapshot and is not protected against + * concurrent CPU hotplug operations unless invoked from a cpuhp_lock held + * region. + */ +static inline unsigned int num_online_cpus(void) +{ + return atomic_read(&__num_online_cpus); +} #define num_possible_cpus() cpumask_weight(cpu_possible_mask) #define num_present_cpus() cpumask_weight(cpu_present_mask) #define num_active_cpus() cpumask_weight(cpu_active_mask) @@ -115,6 +129,8 @@ extern struct cpumask __cpu_active_mask; #define cpu_active(cpu) ((cpu) == 0) #endif +extern cpumask_t cpus_booted_once_mask; + static inline void cpu_max_bits_warn(unsigned int cpu, unsigned int bits) { #ifdef CONFIG_DEBUG_PER_CPU_MAPS @@ -184,8 +200,8 @@ static inline unsigned int cpumask_local_spread(unsigned int i, int node) for ((cpu) = 0; (cpu) < 1; (cpu)++, (void)mask) #define for_each_cpu_wrap(cpu, mask, start) \ for ((cpu) = 0; (cpu) < 1; (cpu)++, (void)mask, (void)(start)) -#define for_each_cpu_and(cpu, mask, and) \ - for ((cpu) = 0; (cpu) < 1; (cpu)++, (void)mask, (void)and) +#define for_each_cpu_and(cpu, mask1, mask2) \ + for ((cpu) = 0; (cpu) < 1; (cpu)++, (void)mask1, (void)mask2) #else /** * cpumask_first - get the first cpu in a cpumask @@ -274,20 +290,20 @@ extern int cpumask_next_wrap(int n, const struct cpumask *mask, int start, bool /** * for_each_cpu_and - iterate over every cpu in both masks * @cpu: the (optionally unsigned) integer iterator - * @mask: the first cpumask pointer - * @and: the second cpumask pointer + * @mask1: the first cpumask pointer + * @mask2: the second cpumask pointer * * This saves a temporary CPU mask in many places. It is equivalent to: * struct cpumask tmp; - * cpumask_and(&tmp, &mask, &and); + * cpumask_and(&tmp, &mask1, &mask2); * for_each_cpu(cpu, &tmp) * ... * * After the loop, cpu is >= nr_cpu_ids. */ -#define for_each_cpu_and(cpu, mask, and) \ +#define for_each_cpu_and(cpu, mask1, mask2) \ for ((cpu) = -1; \ - (cpu) = cpumask_next_and((cpu), (mask), (and)), \ + (cpu) = cpumask_next_and((cpu), (mask1), (mask2)), \ (cpu) < nr_cpu_ids;) #endif /* SMP */ @@ -474,6 +490,20 @@ static inline bool cpumask_equal(const struct cpumask *src1p, } /** + * cpumask_or_equal - *src1p | *src2p == *src3p + * @src1p: the first input + * @src2p: the second input + * @src3p: the third input + */ +static inline bool cpumask_or_equal(const struct cpumask *src1p, + const struct cpumask *src2p, + const struct cpumask *src3p) +{ + return bitmap_or_equal(cpumask_bits(src1p), cpumask_bits(src2p), + cpumask_bits(src3p), nr_cpumask_bits); +} + +/** * cpumask_intersects - (*src1p & *src2p) != 0 * @src1p: the first input * @src2p: the second input @@ -805,14 +835,7 @@ set_cpu_present(unsigned int cpu, bool present) cpumask_clear_cpu(cpu, &__cpu_present_mask); } -static inline void -set_cpu_online(unsigned int cpu, bool online) -{ - if (online) - cpumask_set_cpu(cpu, &__cpu_online_mask); - else - cpumask_clear_cpu(cpu, &__cpu_online_mask); -} +void set_cpu_online(unsigned int cpu, bool online); static inline void set_cpu_active(unsigned int cpu, bool active) diff --git a/include/linux/cpuset.h b/include/linux/cpuset.h index 934633a05d20..04c20de66afc 100644 --- a/include/linux/cpuset.h +++ b/include/linux/cpuset.h @@ -40,14 +40,14 @@ static inline bool cpusets_enabled(void) static inline void cpuset_inc(void) { - static_branch_inc(&cpusets_pre_enable_key); - static_branch_inc(&cpusets_enabled_key); + static_branch_inc_cpuslocked(&cpusets_pre_enable_key); + static_branch_inc_cpuslocked(&cpusets_enabled_key); } static inline void cpuset_dec(void) { - static_branch_dec(&cpusets_enabled_key); - static_branch_dec(&cpusets_pre_enable_key); + static_branch_dec_cpuslocked(&cpusets_enabled_key); + static_branch_dec_cpuslocked(&cpusets_pre_enable_key); } extern int cpuset_init(void); @@ -55,6 +55,8 @@ extern void cpuset_init_smp(void); extern void cpuset_force_rebuild(void); extern void cpuset_update_active_cpus(void); extern void cpuset_wait_for_hotplug(void); +extern void cpuset_read_lock(void); +extern void cpuset_read_unlock(void); extern void cpuset_cpus_allowed(struct task_struct *p, struct cpumask *mask); extern void cpuset_cpus_allowed_fallback(struct task_struct *p); extern nodemask_t cpuset_mems_allowed(struct task_struct *p); @@ -176,6 +178,9 @@ static inline void cpuset_update_active_cpus(void) static inline void cpuset_wait_for_hotplug(void) { } +static inline void cpuset_read_lock(void) { } +static inline void cpuset_read_unlock(void) { } + static inline void cpuset_cpus_allowed(struct task_struct *p, struct cpumask *mask) { diff --git a/include/linux/crash_dump.h b/include/linux/crash_dump.h index f774c5eb9e3c..4664fc1871de 100644 --- a/include/linux/crash_dump.h +++ b/include/linux/crash_dump.h @@ -115,4 +115,18 @@ static inline int vmcore_add_device_dump(struct vmcoredd_data *data) return -EOPNOTSUPP; } #endif /* CONFIG_PROC_VMCORE_DEVICE_DUMP */ + +#ifdef CONFIG_PROC_VMCORE +ssize_t read_from_oldmem(char *buf, size_t count, + u64 *ppos, int userbuf, + bool encrypted); +#else +static inline ssize_t read_from_oldmem(char *buf, size_t count, + u64 *ppos, int userbuf, + bool encrypted) +{ + return -EOPNOTSUPP; +} +#endif /* CONFIG_PROC_VMCORE */ + #endif /* LINUX_CRASHDUMP_H */ diff --git a/include/linux/cred.h b/include/linux/cred.h index 7eb43a038330..18639c069263 100644 --- a/include/linux/cred.h +++ b/include/linux/cred.h @@ -145,7 +145,11 @@ struct cred { struct user_struct *user; /* real user ID subscription */ struct user_namespace *user_ns; /* user_ns the caps and keyrings are relative to. */ struct group_info *group_info; /* supplementary groups for euid/fsgid */ - struct rcu_head rcu; /* RCU deletion hook */ + /* RCU deletion */ + union { + int non_rcu; /* Can we skip RCU deletion? */ + struct rcu_head rcu; /* RCU deletion hook */ + }; } __randomize_layout; extern void __put_cred(struct cred *); @@ -246,6 +250,7 @@ static inline const struct cred *get_cred(const struct cred *cred) if (!cred) return cred; validate_creds(cred); + nonconst_cred->non_rcu = 0; return get_new_cred(nonconst_cred); } @@ -257,6 +262,7 @@ static inline const struct cred *get_cred_rcu(const struct cred *cred) if (!atomic_inc_not_zero(&nonconst_cred->usage)) return NULL; validate_creds(cred); + nonconst_cred->non_rcu = 0; return cred; } @@ -380,7 +386,6 @@ static inline void put_cred(const struct cred *_cred) #define current_fsgid() (current_cred_xxx(fsgid)) #define current_cap() (current_cred_xxx(cap_effective)) #define current_user() (current_cred_xxx(user)) -#define current_security() (current_cred_xxx(security)) extern struct user_namespace init_user_ns; #ifdef CONFIG_USER_NS diff --git a/include/linux/crypto.h b/include/linux/crypto.h index 9cf8f3ce0e50..19ea3a371d7b 100644 --- a/include/linux/crypto.h +++ b/include/linux/crypto.h @@ -49,7 +49,6 @@ #define CRYPTO_ALG_TYPE_SCOMPRESS 0x0000000b #define CRYPTO_ALG_TYPE_RNG 0x0000000c #define CRYPTO_ALG_TYPE_AKCIPHER 0x0000000d -#define CRYPTO_ALG_TYPE_DIGEST 0x0000000e #define CRYPTO_ALG_TYPE_HASH 0x0000000e #define CRYPTO_ALG_TYPE_SHASH 0x0000000e #define CRYPTO_ALG_TYPE_AHASH 0x0000000f @@ -323,6 +322,17 @@ struct cipher_alg { void (*cia_decrypt)(struct crypto_tfm *tfm, u8 *dst, const u8 *src); }; +/** + * struct compress_alg - compression/decompression algorithm + * @coa_compress: Compress a buffer of specified length, storing the resulting + * data in the specified buffer. Return the length of the + * compressed data in dlen. + * @coa_decompress: Decompress the source buffer, storing the uncompressed + * data in the specified buffer. The length of the data is + * returned in dlen. + * + * All fields are mandatory. + */ struct compress_alg { int (*coa_compress)(struct crypto_tfm *tfm, const u8 *src, unsigned int slen, u8 *dst, unsigned int *dlen); diff --git a/include/linux/dax.h b/include/linux/dax.h index becaea5f4488..9bd8528bd305 100644 --- a/include/linux/dax.h +++ b/include/linux/dax.h @@ -7,6 +7,9 @@ #include <linux/radix-tree.h> #include <asm/pgtable.h> +/* Flag for synchronous flush */ +#define DAXDEV_F_SYNC (1UL << 0) + typedef unsigned long dax_entry_t; struct iomap_ops; @@ -38,18 +41,40 @@ extern struct attribute_group dax_attribute_group; #if IS_ENABLED(CONFIG_DAX) struct dax_device *dax_get_by_host(const char *host); struct dax_device *alloc_dax(void *private, const char *host, - const struct dax_operations *ops); + const struct dax_operations *ops, unsigned long flags); void put_dax(struct dax_device *dax_dev); void kill_dax(struct dax_device *dax_dev); void dax_write_cache(struct dax_device *dax_dev, bool wc); bool dax_write_cache_enabled(struct dax_device *dax_dev); +bool __dax_synchronous(struct dax_device *dax_dev); +static inline bool dax_synchronous(struct dax_device *dax_dev) +{ + return __dax_synchronous(dax_dev); +} +void __set_dax_synchronous(struct dax_device *dax_dev); +static inline void set_dax_synchronous(struct dax_device *dax_dev) +{ + __set_dax_synchronous(dax_dev); +} +/* + * Check if given mapping is supported by the file / underlying device. + */ +static inline bool daxdev_mapping_supported(struct vm_area_struct *vma, + struct dax_device *dax_dev) +{ + if (!(vma->vm_flags & VM_SYNC)) + return true; + if (!IS_DAX(file_inode(vma->vm_file))) + return false; + return dax_synchronous(dax_dev); +} #else static inline struct dax_device *dax_get_by_host(const char *host) { return NULL; } static inline struct dax_device *alloc_dax(void *private, const char *host, - const struct dax_operations *ops) + const struct dax_operations *ops, unsigned long flags) { /* * Callers should check IS_ENABLED(CONFIG_DAX) to know if this @@ -70,6 +95,18 @@ static inline bool dax_write_cache_enabled(struct dax_device *dax_dev) { return false; } +static inline bool dax_synchronous(struct dax_device *dax_dev) +{ + return true; +} +static inline void set_dax_synchronous(struct dax_device *dax_dev) +{ +} +static inline bool daxdev_mapping_supported(struct vm_area_struct *vma, + struct dax_device *dax_dev) +{ + return !(vma->vm_flags & VM_SYNC); +} #endif struct writeback_control; diff --git a/include/linux/dcache.h b/include/linux/dcache.h index f14e587c5d5d..10090f11ab95 100644 --- a/include/linux/dcache.h +++ b/include/linux/dcache.h @@ -151,9 +151,9 @@ struct dentry_operations { /* * Locking rules for dentry_operations callbacks are to be found in - * Documentation/filesystems/Locking. Keep it updated! + * Documentation/filesystems/locking.rst. Keep it updated! * - * FUrther descriptions are found in Documentation/filesystems/vfs.txt. + * FUrther descriptions are found in Documentation/filesystems/vfs.rst. * Keep it updated too! */ @@ -291,7 +291,6 @@ static inline unsigned d_count(const struct dentry *dentry) */ extern __printf(4, 5) char *dynamic_dname(struct dentry *, char *, int, const char *, ...); -extern char *simple_dname(struct dentry *, char *, int); extern char *__d_path(const struct path *, const struct path *, char *, int); extern char *d_absolute_path(const struct path *, char *, int); @@ -568,7 +567,7 @@ static inline struct dentry *d_backing_dentry(struct dentry *upper) * If dentry is on a union/overlay, then return the underlying, real dentry. * Otherwise return the dentry itself. * - * See also: Documentation/filesystems/vfs.txt + * See also: Documentation/filesystems/vfs.rst */ static inline struct dentry *d_real(struct dentry *dentry, const struct inode *inode) diff --git a/include/linux/debugfs.h b/include/linux/debugfs.h index 3b0ba54cc4d5..58424eb3b329 100644 --- a/include/linux/debugfs.h +++ b/include/linux/debugfs.h @@ -133,9 +133,8 @@ struct dentry *debugfs_create_regset32(const char *name, umode_t mode, void debugfs_print_regs32(struct seq_file *s, const struct debugfs_reg32 *regs, int nregs, void __iomem *base, char *prefix); -struct dentry *debugfs_create_u32_array(const char *name, umode_t mode, - struct dentry *parent, - u32 *array, u32 elements); +void debugfs_create_u32_array(const char *name, umode_t mode, + struct dentry *parent, u32 *array, u32 elements); struct dentry *debugfs_create_devm_seqfile(struct device *dev, const char *name, struct dentry *parent, @@ -353,11 +352,10 @@ static inline bool debugfs_initialized(void) return false; } -static inline struct dentry *debugfs_create_u32_array(const char *name, umode_t mode, - struct dentry *parent, - u32 *array, u32 elements) +static inline void debugfs_create_u32_array(const char *name, umode_t mode, + struct dentry *parent, u32 *array, + u32 elements) { - return ERR_PTR(-ENODEV); } static inline struct dentry *debugfs_create_devm_seqfile(struct device *dev, diff --git a/include/linux/devfreq-event.h b/include/linux/devfreq-event.h index 29fc0dd735ae..f14f17f8cb7f 100644 --- a/include/linux/devfreq-event.h +++ b/include/linux/devfreq-event.h @@ -78,14 +78,20 @@ struct devfreq_event_ops { * struct devfreq_event_desc - the descriptor of devfreq-event device * * @name : the name of devfreq-event device. + * @event_type : the type of the event determined and used by driver * @driver_data : the private data for devfreq-event driver. * @ops : the operation to control devfreq-event device. * * Each devfreq-event device is described with a this structure. * This structure contains the various data for devfreq-event device. + * The event_type describes what is going to be counted in the register. + * It might choose to count e.g. read requests, write data in bytes, etc. + * The full supported list of types is present in specyfic header in: + * include/dt-bindings/pmu/. */ struct devfreq_event_desc { const char *name; + u32 event_type; void *driver_data; const struct devfreq_event_ops *ops; diff --git a/include/linux/device-mapper.h b/include/linux/device-mapper.h index e1f51d607cc5..399ad8632356 100644 --- a/include/linux/device-mapper.h +++ b/include/linux/device-mapper.h @@ -95,8 +95,7 @@ typedef int (*dm_prepare_ioctl_fn) (struct dm_target *ti, struct block_device ** typedef int (*dm_report_zones_fn) (struct dm_target *ti, sector_t sector, struct blk_zone *zones, - unsigned int *nr_zones, - gfp_t gfp_mask); + unsigned int *nr_zones); /* * These iteration functions are typically used to check (and combine) @@ -530,29 +529,20 @@ void *dm_vcalloc(unsigned long nmemb, unsigned long elem_size); *---------------------------------------------------------------*/ #define DM_NAME "device-mapper" -#define DM_RATELIMIT(pr_func, fmt, ...) \ -do { \ - static DEFINE_RATELIMIT_STATE(rs, DEFAULT_RATELIMIT_INTERVAL, \ - DEFAULT_RATELIMIT_BURST); \ - \ - if (__ratelimit(&rs)) \ - pr_func(DM_FMT(fmt), ##__VA_ARGS__); \ -} while (0) - #define DM_FMT(fmt) DM_NAME ": " DM_MSG_PREFIX ": " fmt "\n" #define DMCRIT(fmt, ...) pr_crit(DM_FMT(fmt), ##__VA_ARGS__) #define DMERR(fmt, ...) pr_err(DM_FMT(fmt), ##__VA_ARGS__) -#define DMERR_LIMIT(fmt, ...) DM_RATELIMIT(pr_err, fmt, ##__VA_ARGS__) +#define DMERR_LIMIT(fmt, ...) pr_err_ratelimited(DM_FMT(fmt), ##__VA_ARGS__) #define DMWARN(fmt, ...) pr_warn(DM_FMT(fmt), ##__VA_ARGS__) -#define DMWARN_LIMIT(fmt, ...) DM_RATELIMIT(pr_warn, fmt, ##__VA_ARGS__) +#define DMWARN_LIMIT(fmt, ...) pr_warn_ratelimited(DM_FMT(fmt), ##__VA_ARGS__) #define DMINFO(fmt, ...) pr_info(DM_FMT(fmt), ##__VA_ARGS__) -#define DMINFO_LIMIT(fmt, ...) DM_RATELIMIT(pr_info, fmt, ##__VA_ARGS__) +#define DMINFO_LIMIT(fmt, ...) pr_info_ratelimited(DM_FMT(fmt), ##__VA_ARGS__) #ifdef CONFIG_DM_DEBUG #define DMDEBUG(fmt, ...) printk(KERN_DEBUG DM_FMT(fmt), ##__VA_ARGS__) -#define DMDEBUG_LIMIT(fmt, ...) DM_RATELIMIT(pr_debug, fmt, ##__VA_ARGS__) +#define DMDEBUG_LIMIT(fmt, ...) pr_debug_ratelimited(DM_FMT(fmt), ##__VA_ARGS__) #else #define DMDEBUG(fmt, ...) no_printk(fmt, ##__VA_ARGS__) #define DMDEBUG_LIMIT(fmt, ...) no_printk(fmt, ##__VA_ARGS__) diff --git a/include/linux/device.h b/include/linux/device.h index 4a295e324ac5..297239a08bb7 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -6,7 +6,7 @@ * Copyright (c) 2004-2009 Greg Kroah-Hartman <gregkh@suse.de> * Copyright (c) 2008-2009 Novell Inc. * - * See Documentation/driver-model/ for more information. + * See Documentation/driver-api/driver-model/ for more information. */ #ifndef _DEVICE_H_ @@ -42,6 +42,7 @@ struct iommu_ops; struct iommu_group; struct iommu_fwspec; struct dev_pin_info; +struct iommu_param; struct bus_attribute { struct attribute attr; @@ -163,14 +164,102 @@ void subsys_dev_iter_init(struct subsys_dev_iter *iter, struct device *subsys_dev_iter_next(struct subsys_dev_iter *iter); void subsys_dev_iter_exit(struct subsys_dev_iter *iter); +int device_match_name(struct device *dev, const void *name); +int device_match_of_node(struct device *dev, const void *np); +int device_match_fwnode(struct device *dev, const void *fwnode); +int device_match_devt(struct device *dev, const void *pdevt); +int device_match_acpi_dev(struct device *dev, const void *adev); +int device_match_any(struct device *dev, const void *unused); + int bus_for_each_dev(struct bus_type *bus, struct device *start, void *data, int (*fn)(struct device *dev, void *data)); struct device *bus_find_device(struct bus_type *bus, struct device *start, - void *data, - int (*match)(struct device *dev, void *data)); -struct device *bus_find_device_by_name(struct bus_type *bus, - struct device *start, - const char *name); + const void *data, + int (*match)(struct device *dev, const void *data)); +/** + * bus_find_device_by_name - device iterator for locating a particular device + * of a specific name. + * @bus: bus type + * @start: Device to begin with + * @name: name of the device to match + */ +static inline struct device *bus_find_device_by_name(struct bus_type *bus, + struct device *start, + const char *name) +{ + return bus_find_device(bus, start, name, device_match_name); +} + +/** + * bus_find_device_by_of_node : device iterator for locating a particular device + * matching the of_node. + * @bus: bus type + * @np: of_node of the device to match. + */ +static inline struct device * +bus_find_device_by_of_node(struct bus_type *bus, const struct device_node *np) +{ + return bus_find_device(bus, NULL, np, device_match_of_node); +} + +/** + * bus_find_device_by_fwnode : device iterator for locating a particular device + * matching the fwnode. + * @bus: bus type + * @fwnode: fwnode of the device to match. + */ +static inline struct device * +bus_find_device_by_fwnode(struct bus_type *bus, const struct fwnode_handle *fwnode) +{ + return bus_find_device(bus, NULL, fwnode, device_match_fwnode); +} + +/** + * bus_find_device_by_devt : device iterator for locating a particular device + * matching the device type. + * @bus: bus type + * @devt: device type of the device to match. + */ +static inline struct device *bus_find_device_by_devt(struct bus_type *bus, + dev_t devt) +{ + return bus_find_device(bus, NULL, &devt, device_match_devt); +} + +/** + * bus_find_next_device - Find the next device after a given device in a + * given bus. + * @bus: bus type + * @cur: device to begin the search with. + */ +static inline struct device * +bus_find_next_device(struct bus_type *bus,struct device *cur) +{ + return bus_find_device(bus, cur, NULL, device_match_any); +} + +#ifdef CONFIG_ACPI +struct acpi_device; + +/** + * bus_find_device_by_acpi_dev : device iterator for locating a particular device + * matching the ACPI COMPANION device. + * @bus: bus type + * @adev: ACPI COMPANION device to match. + */ +static inline struct device * +bus_find_device_by_acpi_dev(struct bus_type *bus, const struct acpi_device *adev) +{ + return bus_find_device(bus, NULL, adev, device_match_acpi_dev); +} +#else +static inline struct device * +bus_find_device_by_acpi_dev(struct bus_type *bus, const void *adev) +{ + return NULL; +} +#endif + struct device *subsys_find_device_by_id(struct bus_type *bus, unsigned int id, struct device *hint); int bus_for_each_drv(struct bus_type *bus, struct device_driver *start, @@ -259,6 +348,8 @@ enum probe_type { * @resume: Called to bring a device from sleep mode. * @groups: Default attributes that get created by the driver core * automatically. + * @dev_groups: Additional attributes attached to device instance once the + * it is bound to the driver. * @pm: Power management operations of the device which matched * this driver. * @coredump: Called when sysfs entry is written to. The device driver @@ -293,6 +384,7 @@ struct device_driver { int (*suspend) (struct device *dev, pm_message_t state); int (*resume) (struct device *dev); const struct attribute_group **groups; + const struct attribute_group **dev_groups; const struct dev_pm_ops *pm; void (*coredump) (struct device *dev); @@ -336,11 +428,89 @@ extern int __must_check driver_for_each_device(struct device_driver *drv, int (*fn)(struct device *dev, void *)); struct device *driver_find_device(struct device_driver *drv, - struct device *start, void *data, - int (*match)(struct device *dev, void *data)); + struct device *start, const void *data, + int (*match)(struct device *dev, const void *data)); + +/** + * driver_find_device_by_name - device iterator for locating a particular device + * of a specific name. + * @drv: the driver we're iterating + * @name: name of the device to match + */ +static inline struct device *driver_find_device_by_name(struct device_driver *drv, + const char *name) +{ + return driver_find_device(drv, NULL, name, device_match_name); +} + +/** + * driver_find_device_by_of_node- device iterator for locating a particular device + * by of_node pointer. + * @drv: the driver we're iterating + * @np: of_node pointer to match. + */ +static inline struct device * +driver_find_device_by_of_node(struct device_driver *drv, + const struct device_node *np) +{ + return driver_find_device(drv, NULL, np, device_match_of_node); +} + +/** + * driver_find_device_by_fwnode- device iterator for locating a particular device + * by fwnode pointer. + * @drv: the driver we're iterating + * @fwnode: fwnode pointer to match. + */ +static inline struct device * +driver_find_device_by_fwnode(struct device_driver *drv, + const struct fwnode_handle *fwnode) +{ + return driver_find_device(drv, NULL, fwnode, device_match_fwnode); +} + +/** + * driver_find_device_by_devt- device iterator for locating a particular device + * by devt. + * @drv: the driver we're iterating + * @devt: devt pointer to match. + */ +static inline struct device *driver_find_device_by_devt(struct device_driver *drv, + dev_t devt) +{ + return driver_find_device(drv, NULL, &devt, device_match_devt); +} + +static inline struct device *driver_find_next_device(struct device_driver *drv, + struct device *start) +{ + return driver_find_device(drv, start, NULL, device_match_any); +} + +#ifdef CONFIG_ACPI +/** + * driver_find_device_by_acpi_dev : device iterator for locating a particular + * device matching the ACPI_COMPANION device. + * @drv: the driver we're iterating + * @adev: ACPI_COMPANION device to match. + */ +static inline struct device * +driver_find_device_by_acpi_dev(struct device_driver *drv, + const struct acpi_device *adev) +{ + return driver_find_device(drv, NULL, adev, device_match_acpi_dev); +} +#else +static inline struct device * +driver_find_device_by_acpi_dev(struct device_driver *drv, const void *adev) +{ + return NULL; +} +#endif void driver_deferred_probe_add(struct device *dev); int driver_deferred_probe_check_state(struct device *dev); +int driver_deferred_probe_check_state_continue(struct device *dev); /** * struct subsys_interface - interfaces to device functions @@ -467,6 +637,76 @@ extern struct device *class_find_device(struct class *class, struct device *start, const void *data, int (*match)(struct device *, const void *)); +/** + * class_find_device_by_name - device iterator for locating a particular device + * of a specific name. + * @class: class type + * @name: name of the device to match + */ +static inline struct device *class_find_device_by_name(struct class *class, + const char *name) +{ + return class_find_device(class, NULL, name, device_match_name); +} + +/** + * class_find_device_by_of_node : device iterator for locating a particular device + * matching the of_node. + * @class: class type + * @np: of_node of the device to match. + */ +static inline struct device * +class_find_device_by_of_node(struct class *class, const struct device_node *np) +{ + return class_find_device(class, NULL, np, device_match_of_node); +} + +/** + * class_find_device_by_fwnode : device iterator for locating a particular device + * matching the fwnode. + * @class: class type + * @fwnode: fwnode of the device to match. + */ +static inline struct device * +class_find_device_by_fwnode(struct class *class, + const struct fwnode_handle *fwnode) +{ + return class_find_device(class, NULL, fwnode, device_match_fwnode); +} + +/** + * class_find_device_by_devt : device iterator for locating a particular device + * matching the device type. + * @class: class type + * @devt: device type of the device to match. + */ +static inline struct device *class_find_device_by_devt(struct class *class, + dev_t devt) +{ + return class_find_device(class, NULL, &devt, device_match_devt); +} + +#ifdef CONFIG_ACPI +struct acpi_device; +/** + * class_find_device_by_acpi_dev : device iterator for locating a particular + * device matching the ACPI_COMPANION device. + * @class: class type + * @adev: ACPI_COMPANION device to match. + */ +static inline struct device * +class_find_device_by_acpi_dev(struct class *class, const struct acpi_device *adev) +{ + return class_find_device(class, NULL, adev, device_match_acpi_dev); +} +#else +static inline struct device * +class_find_device_by_acpi_dev(struct class *class, const void *adev) +{ + return NULL; +} +#endif + struct class_attribute { struct attribute attr; ssize_t (*show)(struct class *class, struct class_attribute *attr, @@ -774,10 +1014,14 @@ struct device_connection { struct list_head list; }; +typedef void *(*devcon_match_fn_t)(struct device_connection *con, int ep, + void *data); + +void *fwnode_connection_find_match(struct fwnode_handle *fwnode, + const char *con_id, void *data, + devcon_match_fn_t match); void *device_connection_find_match(struct device *dev, const char *con_id, - void *data, - void *(*match)(struct device_connection *con, - int ep, void *data)); + void *data, devcon_match_fn_t match); struct device *device_connection_find(struct device *dev, const char *con_id); @@ -829,12 +1073,13 @@ enum device_link_state { /* * Device link flags. * - * STATELESS: The core won't track the presence of supplier/consumer drivers. + * STATELESS: The core will not remove this link automatically. * AUTOREMOVE_CONSUMER: Remove the link automatically on consumer driver unbind. * PM_RUNTIME: If set, the runtime PM framework will use this link. * RPM_ACTIVE: Run pm_runtime_get_sync() on the supplier during link creation. * AUTOREMOVE_SUPPLIER: Remove the link automatically on supplier driver unbind. * AUTOPROBE_CONSUMER: Probe consumer driver automatically after supplier binds. + * MANAGED: The core tracks presence of supplier/consumer drivers (internal). */ #define DL_FLAG_STATELESS BIT(0) #define DL_FLAG_AUTOREMOVE_CONSUMER BIT(1) @@ -842,6 +1087,7 @@ enum device_link_state { #define DL_FLAG_RPM_ACTIVE BIT(3) #define DL_FLAG_AUTOREMOVE_SUPPLIER BIT(4) #define DL_FLAG_AUTOPROBE_CONSUMER BIT(5) +#define DL_FLAG_MANAGED BIT(6) /** * struct device_link - Device link representation. @@ -911,6 +1157,8 @@ struct dev_links_info { * This identifies the device type and carries type-specific * information. * @mutex: Mutex to synchronize calls to its driver. + * @lockdep_mutex: An optional debug lock that a subsystem can use as a + * peer lock to gain localized lockdep coverage of the device_lock. * @bus: Type of bus device is on. * @driver: Which driver has allocated this * @platform_data: Platform data specific to the device. @@ -961,6 +1209,7 @@ struct dev_links_info { * device (i.e. the bus driver that discovered the device). * @iommu_group: IOMMU group the device belongs to. * @iommu_fwspec: IOMMU-specific properties supplied by firmware. + * @iommu_param: Per device generic IOMMU runtime data * * @offline_disabled: If set, the device is permanently online. * @offline: Set after successful invocation of bus type's .offline(). @@ -993,6 +1242,9 @@ struct device { core doesn't touch it */ void *driver_data; /* Driver data, set and get with dev_set_drvdata/dev_get_drvdata */ +#ifdef CONFIG_PROVE_LOCKING + struct mutex lockdep_mutex; +#endif struct mutex mutex; /* mutex to synchronize calls to * its driver. */ @@ -1054,6 +1306,7 @@ struct device { void (*release)(struct device *dev); struct iommu_group *iommu_group; struct iommu_fwspec *iommu_fwspec; + struct iommu_param *iommu_param; bool offline_disabled:1; bool offline:1; @@ -1252,6 +1505,8 @@ extern int device_for_each_child_reverse(struct device *dev, void *data, int (*fn)(struct device *dev, void *data)); extern struct device *device_find_child(struct device *dev, void *data, int (*match)(struct device *dev, void *data)); +extern struct device *device_find_child_by_name(struct device *parent, + const char *name); extern int device_rename(struct device *dev, const char *new_name); extern int device_move(struct device *dev, struct device *new_parent, enum dpm_order dpm_order); @@ -1375,6 +1630,7 @@ extern int (*platform_notify_remove)(struct device *dev); */ extern struct device *get_device(struct device *dev); extern void put_device(struct device *dev); +extern bool kill_device(struct device *dev); #ifdef CONFIG_DEVTMPFS extern int devtmpfs_create_node(struct device *dev); diff --git a/include/linux/dim.h b/include/linux/dim.h new file mode 100644 index 000000000000..9fa4b3f88c39 --- /dev/null +++ b/include/linux/dim.h @@ -0,0 +1,333 @@ +/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */ +/* Copyright (c) 2019 Mellanox Technologies. */ + +#ifndef DIM_H +#define DIM_H + +#include <linux/module.h> + +/** + * Number of events between DIM iterations. + * Causes a moderation of the algorithm run. + */ +#define DIM_NEVENTS 64 + +/** + * Is a difference between values justifies taking an action. + * We consider 10% difference as significant. + */ +#define IS_SIGNIFICANT_DIFF(val, ref) \ + (((100UL * abs((val) - (ref))) / (ref)) > 10) + +/** + * Calculate the gap between two values. + * Take wrap-around and variable size into consideration. + */ +#define BIT_GAP(bits, end, start) ((((end) - (start)) + BIT_ULL(bits)) \ + & (BIT_ULL(bits) - 1)) + +/** + * Structure for CQ moderation values. + * Used for communications between DIM and its consumer. + * + * @usec: CQ timer suggestion (by DIM) + * @pkts: CQ packet counter suggestion (by DIM) + * @cq_period_mode: CQ priod count mode (from CQE/EQE) + */ +struct dim_cq_moder { + u16 usec; + u16 pkts; + u16 comps; + u8 cq_period_mode; +}; + +/** + * Structure for DIM sample data. + * Used for communications between DIM and its consumer. + * + * @time: Sample timestamp + * @pkt_ctr: Number of packets + * @byte_ctr: Number of bytes + * @event_ctr: Number of events + */ +struct dim_sample { + ktime_t time; + u32 pkt_ctr; + u32 byte_ctr; + u16 event_ctr; + u32 comp_ctr; +}; + +/** + * Structure for DIM stats. + * Used for holding current measured rates. + * + * @ppms: Packets per msec + * @bpms: Bytes per msec + * @epms: Events per msec + */ +struct dim_stats { + int ppms; /* packets per msec */ + int bpms; /* bytes per msec */ + int epms; /* events per msec */ + int cpms; /* completions per msec */ + int cpe_ratio; /* ratio of completions to events */ +}; + +/** + * Main structure for dynamic interrupt moderation (DIM). + * Used for holding all information about a specific DIM instance. + * + * @state: Algorithm state (see below) + * @prev_stats: Measured rates from previous iteration (for comparison) + * @start_sample: Sampled data at start of current iteration + * @work: Work to perform on action required + * @priv: A pointer to the struct that points to dim + * @profile_ix: Current moderation profile + * @mode: CQ period count mode + * @tune_state: Algorithm tuning state (see below) + * @steps_right: Number of steps taken towards higher moderation + * @steps_left: Number of steps taken towards lower moderation + * @tired: Parking depth counter + */ +struct dim { + u8 state; + struct dim_stats prev_stats; + struct dim_sample start_sample; + struct dim_sample measuring_sample; + struct work_struct work; + void *priv; + u8 profile_ix; + u8 mode; + u8 tune_state; + u8 steps_right; + u8 steps_left; + u8 tired; +}; + +/** + * enum dim_cq_period_mode + * + * These are the modes for CQ period count. + * + * @DIM_CQ_PERIOD_MODE_START_FROM_EQE: Start counting from EQE + * @DIM_CQ_PERIOD_MODE_START_FROM_CQE: Start counting from CQE (implies timer reset) + * @DIM_CQ_PERIOD_NUM_MODES: Number of modes + */ +enum { + DIM_CQ_PERIOD_MODE_START_FROM_EQE = 0x0, + DIM_CQ_PERIOD_MODE_START_FROM_CQE = 0x1, + DIM_CQ_PERIOD_NUM_MODES +}; + +/** + * enum dim_state + * + * These are the DIM algorithm states. + * These will determine if the algorithm is in a valid state to start an iteration. + * + * @DIM_START_MEASURE: This is the first iteration (also after applying a new profile) + * @DIM_MEASURE_IN_PROGRESS: Algorithm is already in progress - check if + * need to perform an action + * @DIM_APPLY_NEW_PROFILE: DIM consumer is currently applying a profile - no need to measure + */ +enum { + DIM_START_MEASURE, + DIM_MEASURE_IN_PROGRESS, + DIM_APPLY_NEW_PROFILE, +}; + +/** + * enum dim_tune_state + * + * These are the DIM algorithm tune states. + * These will determine which action the algorithm should perform. + * + * @DIM_PARKING_ON_TOP: Algorithm found a local top point - exit on significant difference + * @DIM_PARKING_TIRED: Algorithm found a deep top point - don't exit if tired > 0 + * @DIM_GOING_RIGHT: Algorithm is currently trying higher moderation levels + * @DIM_GOING_LEFT: Algorithm is currently trying lower moderation levels + */ +enum { + DIM_PARKING_ON_TOP, + DIM_PARKING_TIRED, + DIM_GOING_RIGHT, + DIM_GOING_LEFT, +}; + +/** + * enum dim_stats_state + * + * These are the DIM algorithm statistics states. + * These will determine the verdict of current iteration. + * + * @DIM_STATS_WORSE: Current iteration shows worse performance than before + * @DIM_STATS_WORSE: Current iteration shows same performance than before + * @DIM_STATS_WORSE: Current iteration shows better performance than before + */ +enum { + DIM_STATS_WORSE, + DIM_STATS_SAME, + DIM_STATS_BETTER, +}; + +/** + * enum dim_step_result + * + * These are the DIM algorithm step results. + * These describe the result of a step. + * + * @DIM_STEPPED: Performed a regular step + * @DIM_TOO_TIRED: Same kind of step was done multiple times - should go to + * tired parking + * @DIM_ON_EDGE: Stepped to the most left/right profile + */ +enum { + DIM_STEPPED, + DIM_TOO_TIRED, + DIM_ON_EDGE, +}; + +/** + * dim_on_top - check if current state is a good place to stop (top location) + * @dim: DIM context + * + * Check if current profile is a good place to park at. + * This will result in reducing the DIM checks frequency as we assume we + * shouldn't probably change profiles, unless traffic pattern wasn't changed. + */ +bool dim_on_top(struct dim *dim); + +/** + * dim_turn - change profile alterning direction + * @dim: DIM context + * + * Go left if we were going right and vice-versa. + * Do nothing if currently parking. + */ +void dim_turn(struct dim *dim); + +/** + * dim_park_on_top - enter a parking state on a top location + * @dim: DIM context + * + * Enter parking state. + * Clear all movement history. + */ +void dim_park_on_top(struct dim *dim); + +/** + * dim_park_tired - enter a tired parking state + * @dim: DIM context + * + * Enter parking state. + * Clear all movement history and cause DIM checks frequency to reduce. + */ +void dim_park_tired(struct dim *dim); + +/** + * dim_calc_stats - calculate the difference between two samples + * @start: start sample + * @end: end sample + * @curr_stats: delta between samples + * + * Calculate the delta between two samples (in data rates). + * Takes into consideration counter wrap-around. + */ +void dim_calc_stats(struct dim_sample *start, struct dim_sample *end, + struct dim_stats *curr_stats); + +/** + * dim_update_sample - set a sample's fields with give values + * @event_ctr: number of events to set + * @packets: number of packets to set + * @bytes: number of bytes to set + * @s: DIM sample + */ +static inline void +dim_update_sample(u16 event_ctr, u64 packets, u64 bytes, struct dim_sample *s) +{ + s->time = ktime_get(); + s->pkt_ctr = packets; + s->byte_ctr = bytes; + s->event_ctr = event_ctr; +} + +/** + * dim_update_sample_with_comps - set a sample's fields with given + * values including the completion parameter + * @event_ctr: number of events to set + * @packets: number of packets to set + * @bytes: number of bytes to set + * @comps: number of completions to set + * @s: DIM sample + */ +static inline void +dim_update_sample_with_comps(u16 event_ctr, u64 packets, u64 bytes, u64 comps, + struct dim_sample *s) +{ + dim_update_sample(event_ctr, packets, bytes, s); + s->comp_ctr = comps; +} + +/* Net DIM */ + +/** + * net_dim_get_rx_moderation - provide a CQ moderation object for the given RX profile + * @cq_period_mode: CQ period mode + * @ix: Profile index + */ +struct dim_cq_moder net_dim_get_rx_moderation(u8 cq_period_mode, int ix); + +/** + * net_dim_get_def_rx_moderation - provide the default RX moderation + * @cq_period_mode: CQ period mode + */ +struct dim_cq_moder net_dim_get_def_rx_moderation(u8 cq_period_mode); + +/** + * net_dim_get_tx_moderation - provide a CQ moderation object for the given TX profile + * @cq_period_mode: CQ period mode + * @ix: Profile index + */ +struct dim_cq_moder net_dim_get_tx_moderation(u8 cq_period_mode, int ix); + +/** + * net_dim_get_def_tx_moderation - provide the default TX moderation + * @cq_period_mode: CQ period mode + */ +struct dim_cq_moder net_dim_get_def_tx_moderation(u8 cq_period_mode); + +/** + * net_dim - main DIM algorithm entry point + * @dim: DIM instance information + * @end_sample: Current data measurement + * + * Called by the consumer. + * This is the main logic of the algorithm, where data is processed in order to decide on next + * required action. + */ +void net_dim(struct dim *dim, struct dim_sample end_sample); + +/* RDMA DIM */ + +/* + * RDMA DIM profile: + * profile size must be of RDMA_DIM_PARAMS_NUM_PROFILES. + */ +#define RDMA_DIM_PARAMS_NUM_PROFILES 9 +#define RDMA_DIM_START_PROFILE 0 + +/** + * rdma_dim - Runs the adaptive moderation. + * @dim: The moderation struct. + * @completions: The number of completions collected in this round. + * + * Each call to rdma_dim takes the latest amount of completions that + * have been collected and counts them as a new event. + * Once enough events have been collected the algorithm decides a new + * moderation level. + */ +void rdma_dim(struct dim *dim, u64 completions); + +#endif /* DIM_H */ diff --git a/include/linux/dma-buf.h b/include/linux/dma-buf.h index 9b84114f74ce..ec212cb27fdc 100644 --- a/include/linux/dma-buf.h +++ b/include/linux/dma-buf.h @@ -28,19 +28,21 @@ struct dma_buf_attachment; /** * struct dma_buf_ops - operations possible on struct dma_buf - * @map_atomic: [optional] maps a page from the buffer into kernel address - * space, users may not block until the subsequent unmap call. - * This callback must not sleep. - * @unmap_atomic: [optional] unmaps a atomically mapped page from the buffer. - * This Callback must not sleep. - * @map: [optional] maps a page from the buffer into kernel address space. - * @unmap: [optional] unmaps a page from the buffer. * @vmap: [optional] creates a virtual mapping for the buffer into kernel * address space. Same restrictions as for vmap and friends apply. * @vunmap: [optional] unmaps a vmap from the buffer */ struct dma_buf_ops { /** + * @cache_sgt_mapping: + * + * If true the framework will cache the first mapping made for each + * attachment. This avoids creating mappings for attachments multiple + * times. + */ + bool cache_sgt_mapping; + + /** * @attach: * * This is called from dma_buf_attach() to make sure that a given @@ -194,8 +196,6 @@ struct dma_buf_ops { * to be restarted. */ int (*end_cpu_access)(struct dma_buf *, enum dma_data_direction); - void *(*map)(struct dma_buf *, unsigned long); - void (*unmap)(struct dma_buf *, unsigned long, void *); /** * @mmap: @@ -234,6 +234,31 @@ struct dma_buf_ops { */ int (*mmap)(struct dma_buf *, struct vm_area_struct *vma); + /** + * @map: + * + * Maps a page from the buffer into kernel address space. The page is + * specified by offset into the buffer in PAGE_SIZE units. + * + * This callback is optional. + * + * Returns: + * + * Virtual address pointer where requested page can be accessed. NULL + * on error or when this function is unimplemented by the exporter. + */ + void *(*map)(struct dma_buf *, unsigned long); + + /** + * @unmap: + * + * Unmaps a page from the buffer. Page offset and address pointer should + * be the same as the one passed to and returned by matching call to map. + * + * This callback is optional. + */ + void (*unmap)(struct dma_buf *, unsigned long, void *); + void *(*vmap)(struct dma_buf *); void (*vunmap)(struct dma_buf *, void *vaddr); }; @@ -244,10 +269,12 @@ struct dma_buf_ops { * @file: file pointer used for sharing buffers across, and for refcounting. * @attachments: list of dma_buf_attachment that denotes all devices attached. * @ops: dma_buf_ops associated with this buffer object. - * @lock: used internally to serialize list manipulation, attach/detach and vmap/unmap + * @lock: used internally to serialize list manipulation, attach/detach and + * vmap/unmap, and accesses to name * @vmapping_counter: used internally to refcnt the vmaps * @vmap_ptr: the current vmap ptr if vmapping_counter > 0 * @exp_name: name of the exporter; useful for debugging. + * @name: userspace-provided name; useful for accounting and debugging. * @owner: pointer to exporter module; used for refcounting when exporter is a * kernel module. * @list_node: node for dma_buf accounting and debugging. @@ -275,10 +302,11 @@ struct dma_buf { unsigned vmapping_counter; void *vmap_ptr; const char *exp_name; + const char *name; struct module *owner; struct list_head list_node; void *priv; - struct reservation_object *resv; + struct dma_resv *resv; /* poll support */ wait_queue_head_t poll; @@ -296,6 +324,8 @@ struct dma_buf { * @dmabuf: buffer for this attachment. * @dev: device attached to the buffer. * @node: list of dma_buf_attachment. + * @sgt: cached mapping. + * @dir: direction of cached mapping. * @priv: exporter specific attachment data. * * This structure holds the attachment information between the dma_buf buffer @@ -311,6 +341,8 @@ struct dma_buf_attachment { struct dma_buf *dmabuf; struct device *dev; struct list_head node; + struct sg_table *sgt; + enum dma_data_direction dir; void *priv; }; @@ -333,7 +365,7 @@ struct dma_buf_export_info { const struct dma_buf_ops *ops; size_t size; int flags; - struct reservation_object *resv; + struct dma_resv *resv; void *priv; }; diff --git a/include/linux/dma-contiguous.h b/include/linux/dma-contiguous.h index 6665fa03c0d1..03f8e98e3bcc 100644 --- a/include/linux/dma-contiguous.h +++ b/include/linux/dma-contiguous.h @@ -50,6 +50,7 @@ #ifdef __KERNEL__ #include <linux/device.h> +#include <linux/mm.h> struct cma; struct page; @@ -111,6 +112,8 @@ struct page *dma_alloc_from_contiguous(struct device *dev, size_t count, unsigned int order, bool no_warn); bool dma_release_from_contiguous(struct device *dev, struct page *pages, int count); +struct page *dma_alloc_contiguous(struct device *dev, size_t size, gfp_t gfp); +void dma_free_contiguous(struct device *dev, struct page *page, size_t size); #else @@ -153,6 +156,19 @@ bool dma_release_from_contiguous(struct device *dev, struct page *pages, return false; } +/* Use fallback alloc() and free() when CONFIG_DMA_CMA=n */ +static inline struct page *dma_alloc_contiguous(struct device *dev, size_t size, + gfp_t gfp) +{ + return NULL; +} + +static inline void dma_free_contiguous(struct device *dev, struct page *page, + size_t size) +{ + __free_pages(page, get_order(size)); +} + #endif #endif diff --git a/include/linux/dma-direct.h b/include/linux/dma-direct.h index b7338702592a..adf993a3bd58 100644 --- a/include/linux/dma-direct.h +++ b/include/linux/dma-direct.h @@ -32,6 +32,15 @@ static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size) } #endif /* !CONFIG_ARCH_HAS_PHYS_TO_DMA */ +#ifdef CONFIG_ARCH_HAS_FORCE_DMA_UNENCRYPTED +bool force_dma_unencrypted(struct device *dev); +#else +static inline bool force_dma_unencrypted(struct device *dev) +{ + return false; +} +#endif /* CONFIG_ARCH_HAS_FORCE_DMA_UNENCRYPTED */ + /* * If memory encryption is supported, phys_to_dma will set the memory encryption * bit in the DMA address, and dma_to_phys will clear it. The raw __phys_to_dma diff --git a/include/linux/dma-fence.h b/include/linux/dma-fence.h index 05d29dbc7e62..3347c54f3a87 100644 --- a/include/linux/dma-fence.h +++ b/include/linux/dma-fence.h @@ -63,15 +63,35 @@ struct dma_fence_cb; * been completed, or never called at all. */ struct dma_fence { - struct kref refcount; - const struct dma_fence_ops *ops; - struct rcu_head rcu; - struct list_head cb_list; spinlock_t *lock; + const struct dma_fence_ops *ops; + /* + * We clear the callback list on kref_put so that by the time we + * release the fence it is unused. No one should be adding to the + * cb_list that they don't themselves hold a reference for. + * + * The lifetime of the timestamp is similarly tied to both the + * rcu freelist and the cb_list. The timestamp is only set upon + * signaling while simultaneously notifying the cb_list. Ergo, we + * only use either the cb_list of timestamp. Upon destruction, + * neither are accessible, and so we can use the rcu. This means + * that the cb_list is *only* valid until the signal bit is set, + * and to read either you *must* hold a reference to the fence, + * and not just the rcu_read_lock. + * + * Listed in chronological order. + */ + union { + struct list_head cb_list; + /* @cb_list replaced by @timestamp on dma_fence_signal() */ + ktime_t timestamp; + /* @timestamp replaced by @rcu on dma_fence_release() */ + struct rcu_head rcu; + }; u64 context; u64 seqno; unsigned long flags; - ktime_t timestamp; + struct kref refcount; int error; }; @@ -273,7 +293,7 @@ static inline struct dma_fence *dma_fence_get(struct dma_fence *fence) } /** - * dma_fence_get_rcu - get a fence from a reservation_object_list with + * dma_fence_get_rcu - get a fence from a dma_resv_list with * rcu read lock * @fence: fence to increase refcount of * @@ -297,7 +317,7 @@ static inline struct dma_fence *dma_fence_get_rcu(struct dma_fence *fence) * so long as the caller is using RCU on the pointer to the fence. * * An alternative mechanism is to employ a seqlock to protect a bunch of - * fences, such as used by struct reservation_object. When using a seqlock, + * fences, such as used by struct dma_resv. When using a seqlock, * the seqlock must be taken before and checked after a reference to the * fence is acquired (as shown here). * diff --git a/include/linux/dma-iommu.h b/include/linux/dma-iommu.h index 37258c8b2063..2112f21f73d8 100644 --- a/include/linux/dma-iommu.h +++ b/include/linux/dma-iommu.h @@ -5,59 +5,21 @@ #ifndef __DMA_IOMMU_H #define __DMA_IOMMU_H -#ifdef __KERNEL__ +#include <linux/errno.h> #include <linux/types.h> -#include <asm/errno.h> #ifdef CONFIG_IOMMU_DMA #include <linux/dma-mapping.h> #include <linux/iommu.h> #include <linux/msi.h> -int iommu_dma_init(void); - /* Domain management interface for IOMMU drivers */ int iommu_get_dma_cookie(struct iommu_domain *domain); int iommu_get_msi_cookie(struct iommu_domain *domain, dma_addr_t base); void iommu_put_dma_cookie(struct iommu_domain *domain); /* Setup call for arch DMA mapping code */ -int iommu_dma_init_domain(struct iommu_domain *domain, dma_addr_t base, - u64 size, struct device *dev); - -/* General helpers for DMA-API <-> IOMMU-API interaction */ -int dma_info_to_prot(enum dma_data_direction dir, bool coherent, - unsigned long attrs); - -/* - * These implement the bulk of the relevant DMA mapping callbacks, but require - * the arch code to take care of attributes and cache maintenance - */ -struct page **iommu_dma_alloc(struct device *dev, size_t size, gfp_t gfp, - unsigned long attrs, int prot, dma_addr_t *handle, - void (*flush_page)(struct device *, const void *, phys_addr_t)); -void iommu_dma_free(struct device *dev, struct page **pages, size_t size, - dma_addr_t *handle); - -int iommu_dma_mmap(struct page **pages, size_t size, struct vm_area_struct *vma); - -dma_addr_t iommu_dma_map_page(struct device *dev, struct page *page, - unsigned long offset, size_t size, int prot); -int iommu_dma_map_sg(struct device *dev, struct scatterlist *sg, - int nents, int prot); - -/* - * Arch code with no special attribute handling may use these - * directly as DMA mapping callbacks for simplicity - */ -void iommu_dma_unmap_page(struct device *dev, dma_addr_t handle, size_t size, - enum dma_data_direction dir, unsigned long attrs); -void iommu_dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nents, - enum dma_data_direction dir, unsigned long attrs); -dma_addr_t iommu_dma_map_resource(struct device *dev, phys_addr_t phys, - size_t size, enum dma_data_direction dir, unsigned long attrs); -void iommu_dma_unmap_resource(struct device *dev, dma_addr_t handle, - size_t size, enum dma_data_direction dir, unsigned long attrs); +void iommu_setup_dma_ops(struct device *dev, u64 dma_base, u64 size); /* The DMA API isn't _quite_ the whole story, though... */ /* @@ -75,16 +37,16 @@ void iommu_dma_compose_msi_msg(struct msi_desc *desc, void iommu_dma_get_resv_regions(struct device *dev, struct list_head *list); -#else +#else /* CONFIG_IOMMU_DMA */ struct iommu_domain; struct msi_desc; struct msi_msg; struct device; -static inline int iommu_dma_init(void) +static inline void iommu_setup_dma_ops(struct device *dev, u64 dma_base, + u64 size) { - return 0; } static inline int iommu_get_dma_cookie(struct iommu_domain *domain) @@ -117,5 +79,4 @@ static inline void iommu_dma_get_resv_regions(struct device *dev, struct list_he } #endif /* CONFIG_IOMMU_DMA */ -#endif /* __KERNEL__ */ #endif /* __DMA_IOMMU_H */ diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h index 6309a721394b..4a1c4fca475a 100644 --- a/include/linux/dma-mapping.h +++ b/include/linux/dma-mapping.h @@ -131,6 +131,7 @@ struct dma_map_ops { int (*dma_supported)(struct device *dev, u64 mask); u64 (*get_required_mask)(struct device *dev); size_t (*max_mapping_size)(struct device *dev); + unsigned long (*get_merge_boundary)(struct device *dev); }; #define DMA_MAPPING_ERROR (~(dma_addr_t)0) @@ -149,11 +150,6 @@ static inline int valid_dma_direction(int dma_direction) (dma_direction == DMA_FROM_DEVICE)); } -static inline int is_device_dma_capable(struct device *dev) -{ - return dev->dma_mask != NULL && *dev->dma_mask != DMA_MASK_NONE; -} - #ifdef CONFIG_DMA_DECLARE_COHERENT /* * These three functions are only for dma allocator. @@ -462,11 +458,13 @@ int dma_get_sgtable_attrs(struct device *dev, struct sg_table *sgt, int dma_mmap_attrs(struct device *dev, struct vm_area_struct *vma, void *cpu_addr, dma_addr_t dma_addr, size_t size, unsigned long attrs); +bool dma_can_mmap(struct device *dev); int dma_supported(struct device *dev, u64 mask); int dma_set_mask(struct device *dev, u64 mask); int dma_set_coherent_mask(struct device *dev, u64 mask); u64 dma_get_required_mask(struct device *dev); size_t dma_max_mapping_size(struct device *dev); +unsigned long dma_get_merge_boundary(struct device *dev); #else /* CONFIG_HAS_DMA */ static inline dma_addr_t dma_map_page_attrs(struct device *dev, struct page *page, size_t offset, size_t size, @@ -552,6 +550,10 @@ static inline int dma_mmap_attrs(struct device *dev, struct vm_area_struct *vma, { return -ENXIO; } +static inline bool dma_can_mmap(struct device *dev) +{ + return false; +} static inline int dma_supported(struct device *dev, u64 mask) { return 0; @@ -572,6 +574,10 @@ static inline size_t dma_max_mapping_size(struct device *dev) { return 0; } +static inline unsigned long dma_get_merge_boundary(struct device *dev) +{ + return 0; +} #endif /* CONFIG_HAS_DMA */ static inline dma_addr_t dma_map_single_attrs(struct device *dev, void *ptr, @@ -615,16 +621,14 @@ extern int dma_common_mmap(struct device *dev, struct vm_area_struct *vma, void *cpu_addr, dma_addr_t dma_addr, size_t size, unsigned long attrs); +struct page **dma_common_find_pages(void *cpu_addr); void *dma_common_contiguous_remap(struct page *page, size_t size, - unsigned long vm_flags, pgprot_t prot, const void *caller); void *dma_common_pages_remap(struct page **pages, size_t size, - unsigned long vm_flags, pgprot_t prot, - const void *caller); -void dma_common_free_remap(void *cpu_addr, size_t size, unsigned long vm_flags); + pgprot_t prot, const void *caller); +void dma_common_free_remap(void *cpu_addr, size_t size); -int __init dma_atomic_pool_init(gfp_t gfp, pgprot_t prot); bool dma_in_atomic_pool(void *start, size_t size); void *dma_alloc_from_pool(size_t size, struct page **ret_page, gfp_t flags); bool dma_free_from_pool(void *start, size_t size); @@ -679,6 +683,20 @@ static inline int dma_coerce_mask_and_coherent(struct device *dev, u64 mask) return dma_set_mask_and_coherent(dev, mask); } +/** + * dma_addressing_limited - return if the device is addressing limited + * @dev: device to check + * + * Return %true if the devices DMA mask is too small to address all memory in + * the system, else %false. Lack of addressing bits is the prime reason for + * bounce buffering, but might not be the only one. + */ +static inline bool dma_addressing_limited(struct device *dev) +{ + return min_not_zero(dma_get_mask(dev), dev->bus_dma_mask) < + dma_get_required_mask(dev); +} + #ifdef CONFIG_ARCH_HAS_SETUP_DMA_OPS void arch_setup_dma_ops(struct device *dev, u64 dma_base, u64 size, const struct iommu_ops *iommu, bool coherent); @@ -729,13 +747,6 @@ static inline int dma_set_seg_boundary(struct device *dev, unsigned long mask) return -EIO; } -#ifndef dma_max_pfn -static inline unsigned long dma_max_pfn(struct device *dev) -{ - return (*dev->dma_mask >> PAGE_SHIFT) + dev->dma_pfn_offset; -} -#endif - static inline int dma_get_cache_alignment(void) { #ifdef ARCH_DMA_MINALIGN @@ -747,7 +758,6 @@ static inline int dma_get_cache_alignment(void) #ifdef CONFIG_DMA_DECLARE_COHERENT int dma_declare_coherent_memory(struct device *dev, phys_addr_t phys_addr, dma_addr_t device_addr, size_t size); -void dma_release_declared_memory(struct device *dev); #else static inline int dma_declare_coherent_memory(struct device *dev, phys_addr_t phys_addr, @@ -755,11 +765,6 @@ dma_declare_coherent_memory(struct device *dev, phys_addr_t phys_addr, { return -ENOSYS; } - -static inline void -dma_release_declared_memory(struct device *dev) -{ -} #endif /* CONFIG_DMA_DECLARE_COHERENT */ static inline void *dmam_alloc_coherent(struct device *dev, size_t size, @@ -779,9 +784,6 @@ static inline void *dma_alloc_wc(struct device *dev, size_t size, return dma_alloc_attrs(dev, size, dma_addr, gfp, attrs); } -#ifndef dma_alloc_writecombine -#define dma_alloc_writecombine dma_alloc_wc -#endif static inline void dma_free_wc(struct device *dev, size_t size, void *cpu_addr, dma_addr_t dma_addr) @@ -789,9 +791,6 @@ static inline void dma_free_wc(struct device *dev, size_t size, return dma_free_attrs(dev, size, cpu_addr, dma_addr, DMA_ATTR_WRITE_COMBINE); } -#ifndef dma_free_writecombine -#define dma_free_writecombine dma_free_wc -#endif static inline int dma_mmap_wc(struct device *dev, struct vm_area_struct *vma, @@ -801,9 +800,6 @@ static inline int dma_mmap_wc(struct device *dev, return dma_mmap_attrs(dev, vma, cpu_addr, dma_addr, size, DMA_ATTR_WRITE_COMBINE); } -#ifndef dma_mmap_writecombine -#define dma_mmap_writecombine dma_mmap_wc -#endif #ifdef CONFIG_NEED_DMA_MAP_STATE #define DEFINE_DMA_UNMAP_ADDR(ADDR_NAME) dma_addr_t ADDR_NAME diff --git a/include/linux/dma-noncoherent.h b/include/linux/dma-noncoherent.h index 9741767e400f..dd3de6d88fc0 100644 --- a/include/linux/dma-noncoherent.h +++ b/include/linux/dma-noncoherent.h @@ -3,6 +3,7 @@ #define _LINUX_DMA_NONCOHERENT_H 1 #include <linux/dma-mapping.h> +#include <asm/pgtable.h> #ifdef CONFIG_ARCH_HAS_DMA_COHERENCE_H #include <asm/dma-coherence.h> @@ -20,6 +21,22 @@ static inline bool dev_is_dma_coherent(struct device *dev) } #endif /* CONFIG_ARCH_HAS_DMA_COHERENCE_H */ +/* + * Check if an allocation needs to be marked uncached to be coherent. + */ +static __always_inline bool dma_alloc_need_uncached(struct device *dev, + unsigned long attrs) +{ + if (dev_is_dma_coherent(dev)) + return false; + if (attrs & DMA_ATTR_NO_KERNEL_MAPPING) + return false; + if (IS_ENABLED(CONFIG_DMA_NONCOHERENT_CACHE_SYNC) && + (attrs & DMA_ATTR_NON_CONSISTENT)) + return false; + return true; +} + void *arch_dma_alloc(struct device *dev, size_t size, dma_addr_t *dma_handle, gfp_t gfp, unsigned long attrs); void arch_dma_free(struct device *dev, size_t size, void *cpu_addr, @@ -27,13 +44,26 @@ void arch_dma_free(struct device *dev, size_t size, void *cpu_addr, long arch_dma_coherent_to_pfn(struct device *dev, void *cpu_addr, dma_addr_t dma_addr); -#ifdef CONFIG_ARCH_HAS_DMA_MMAP_PGPROT -pgprot_t arch_dma_mmap_pgprot(struct device *dev, pgprot_t prot, - unsigned long attrs); -#else -# define arch_dma_mmap_pgprot(dev, prot, attrs) pgprot_noncached(prot) +#ifdef CONFIG_MMU +/* + * Page protection so that devices that can't snoop CPU caches can use the + * memory coherently. We default to pgprot_noncached which is usually used + * for ioremap as a safe bet, but architectures can override this with less + * strict semantics if possible. + */ +#ifndef pgprot_dmacoherent +#define pgprot_dmacoherent(prot) pgprot_noncached(prot) #endif +pgprot_t dma_pgprot(struct device *dev, pgprot_t prot, unsigned long attrs); +#else +static inline pgprot_t dma_pgprot(struct device *dev, pgprot_t prot, + unsigned long attrs) +{ + return prot; /* no protection bits supported without page tables */ +} +#endif /* CONFIG_MMU */ + #ifdef CONFIG_DMA_NONCOHERENT_CACHE_SYNC void arch_dma_cache_sync(struct device *dev, void *vaddr, size_t size, enum dma_data_direction direction); @@ -80,4 +110,7 @@ static inline void arch_dma_prep_coherent(struct page *page, size_t size) } #endif /* CONFIG_ARCH_HAS_DMA_PREP_COHERENT */ +void *uncached_kernel_address(void *addr); +void *cached_kernel_address(void *addr); + #endif /* _LINUX_DMA_NONCOHERENT_H */ diff --git a/include/linux/reservation.h b/include/linux/dma-resv.h index ee750765cc94..ee50d10f052b 100644 --- a/include/linux/reservation.h +++ b/include/linux/dma-resv.h @@ -50,98 +50,52 @@ extern struct lock_class_key reservation_seqcount_class; extern const char reservation_seqcount_string[]; /** - * struct reservation_object_list - a list of shared fences + * struct dma_resv_list - a list of shared fences * @rcu: for internal use * @shared_count: table of shared fences * @shared_max: for growing shared fence table * @shared: shared fence table */ -struct reservation_object_list { +struct dma_resv_list { struct rcu_head rcu; u32 shared_count, shared_max; struct dma_fence __rcu *shared[]; }; /** - * struct reservation_object - a reservation object manages fences for a buffer + * struct dma_resv - a reservation object manages fences for a buffer * @lock: update side lock * @seq: sequence count for managing RCU read-side synchronization * @fence_excl: the exclusive fence, if there is one currently * @fence: list of current shared fences */ -struct reservation_object { +struct dma_resv { struct ww_mutex lock; seqcount_t seq; struct dma_fence __rcu *fence_excl; - struct reservation_object_list __rcu *fence; + struct dma_resv_list __rcu *fence; }; -#define reservation_object_held(obj) lockdep_is_held(&(obj)->lock.base) -#define reservation_object_assert_held(obj) \ - lockdep_assert_held(&(obj)->lock.base) +#define dma_resv_held(obj) lockdep_is_held(&(obj)->lock.base) +#define dma_resv_assert_held(obj) lockdep_assert_held(&(obj)->lock.base) /** - * reservation_object_init - initialize a reservation object - * @obj: the reservation object - */ -static inline void -reservation_object_init(struct reservation_object *obj) -{ - ww_mutex_init(&obj->lock, &reservation_ww_class); - - __seqcount_init(&obj->seq, reservation_seqcount_string, &reservation_seqcount_class); - RCU_INIT_POINTER(obj->fence, NULL); - RCU_INIT_POINTER(obj->fence_excl, NULL); -} - -/** - * reservation_object_fini - destroys a reservation object - * @obj: the reservation object - */ -static inline void -reservation_object_fini(struct reservation_object *obj) -{ - int i; - struct reservation_object_list *fobj; - struct dma_fence *excl; - - /* - * This object should be dead and all references must have - * been released to it, so no need to be protected with rcu. - */ - excl = rcu_dereference_protected(obj->fence_excl, 1); - if (excl) - dma_fence_put(excl); - - fobj = rcu_dereference_protected(obj->fence, 1); - if (fobj) { - for (i = 0; i < fobj->shared_count; ++i) - dma_fence_put(rcu_dereference_protected(fobj->shared[i], 1)); - - kfree(fobj); - } - - ww_mutex_destroy(&obj->lock); -} - -/** - * reservation_object_get_list - get the reservation object's + * dma_resv_get_list - get the reservation object's * shared fence list, with update-side lock held * @obj: the reservation object * * Returns the shared fence list. Does NOT take references to * the fence. The obj->lock must be held. */ -static inline struct reservation_object_list * -reservation_object_get_list(struct reservation_object *obj) +static inline struct dma_resv_list *dma_resv_get_list(struct dma_resv *obj) { return rcu_dereference_protected(obj->fence, - reservation_object_held(obj)); + dma_resv_held(obj)); } /** - * reservation_object_lock - lock the reservation object + * dma_resv_lock - lock the reservation object * @obj: the reservation object * @ctx: the locking context * @@ -155,15 +109,14 @@ reservation_object_get_list(struct reservation_object *obj) * is detected. See ww_mutex_lock() and ww_acquire_init(). A reservation * object may be locked by itself by passing NULL as @ctx. */ -static inline int -reservation_object_lock(struct reservation_object *obj, - struct ww_acquire_ctx *ctx) +static inline int dma_resv_lock(struct dma_resv *obj, + struct ww_acquire_ctx *ctx) { return ww_mutex_lock(&obj->lock, ctx); } /** - * reservation_object_lock_interruptible - lock the reservation object + * dma_resv_lock_interruptible - lock the reservation object * @obj: the reservation object * @ctx: the locking context * @@ -177,16 +130,45 @@ reservation_object_lock(struct reservation_object *obj, * is detected. See ww_mutex_lock() and ww_acquire_init(). A reservation * object may be locked by itself by passing NULL as @ctx. */ -static inline int -reservation_object_lock_interruptible(struct reservation_object *obj, - struct ww_acquire_ctx *ctx) +static inline int dma_resv_lock_interruptible(struct dma_resv *obj, + struct ww_acquire_ctx *ctx) { return ww_mutex_lock_interruptible(&obj->lock, ctx); } +/** + * dma_resv_lock_slow - slowpath lock the reservation object + * @obj: the reservation object + * @ctx: the locking context + * + * Acquires the reservation object after a die case. This function + * will sleep until the lock becomes available. See dma_resv_lock() as + * well. + */ +static inline void dma_resv_lock_slow(struct dma_resv *obj, + struct ww_acquire_ctx *ctx) +{ + ww_mutex_lock_slow(&obj->lock, ctx); +} /** - * reservation_object_trylock - trylock the reservation object + * dma_resv_lock_slow_interruptible - slowpath lock the reservation + * object, interruptible + * @obj: the reservation object + * @ctx: the locking context + * + * Acquires the reservation object interruptible after a die case. This function + * will sleep until the lock becomes available. See + * dma_resv_lock_interruptible() as well. + */ +static inline int dma_resv_lock_slow_interruptible(struct dma_resv *obj, + struct ww_acquire_ctx *ctx) +{ + return ww_mutex_lock_slow_interruptible(&obj->lock, ctx); +} + +/** + * dma_resv_trylock - trylock the reservation object * @obj: the reservation object * * Tries to lock the reservation object for exclusive access and modification. @@ -199,31 +181,55 @@ reservation_object_lock_interruptible(struct reservation_object *obj, * * Returns true if the lock was acquired, false otherwise. */ -static inline bool __must_check -reservation_object_trylock(struct reservation_object *obj) +static inline bool __must_check dma_resv_trylock(struct dma_resv *obj) { return ww_mutex_trylock(&obj->lock); } /** - * reservation_object_unlock - unlock the reservation object + * dma_resv_is_locked - is the reservation object locked + * @obj: the reservation object + * + * Returns true if the mutex is locked, false if unlocked. + */ +static inline bool dma_resv_is_locked(struct dma_resv *obj) +{ + return ww_mutex_is_locked(&obj->lock); +} + +/** + * dma_resv_locking_ctx - returns the context used to lock the object + * @obj: the reservation object + * + * Returns the context used to lock a reservation object or NULL if no context + * was used or the object is not locked at all. + */ +static inline struct ww_acquire_ctx *dma_resv_locking_ctx(struct dma_resv *obj) +{ + return READ_ONCE(obj->lock.ctx); +} + +/** + * dma_resv_unlock - unlock the reservation object * @obj: the reservation object * * Unlocks the reservation object following exclusive access. */ -static inline void -reservation_object_unlock(struct reservation_object *obj) +static inline void dma_resv_unlock(struct dma_resv *obj) { #ifdef CONFIG_DEBUG_MUTEXES /* Test shared fence slot reservation */ - if (obj->fence) - obj->fence->shared_max = obj->fence->shared_count; + if (rcu_access_pointer(obj->fence)) { + struct dma_resv_list *fence = dma_resv_get_list(obj); + + fence->shared_max = fence->shared_count; + } #endif ww_mutex_unlock(&obj->lock); } /** - * reservation_object_get_excl - get the reservation object's + * dma_resv_get_excl - get the reservation object's * exclusive fence, with update-side lock held * @obj: the reservation object * @@ -235,14 +241,14 @@ reservation_object_unlock(struct reservation_object *obj) * The exclusive fence or NULL */ static inline struct dma_fence * -reservation_object_get_excl(struct reservation_object *obj) +dma_resv_get_excl(struct dma_resv *obj) { return rcu_dereference_protected(obj->fence_excl, - reservation_object_held(obj)); + dma_resv_held(obj)); } /** - * reservation_object_get_excl_rcu - get the reservation object's + * dma_resv_get_excl_rcu - get the reservation object's * exclusive fence, without lock held. * @obj: the reservation object * @@ -253,7 +259,7 @@ reservation_object_get_excl(struct reservation_object *obj) * The exclusive fence or NULL if none */ static inline struct dma_fence * -reservation_object_get_excl_rcu(struct reservation_object *obj) +dma_resv_get_excl_rcu(struct dma_resv *obj) { struct dma_fence *fence; @@ -267,27 +273,23 @@ reservation_object_get_excl_rcu(struct reservation_object *obj) return fence; } -int reservation_object_reserve_shared(struct reservation_object *obj, - unsigned int num_fences); -void reservation_object_add_shared_fence(struct reservation_object *obj, - struct dma_fence *fence); +void dma_resv_init(struct dma_resv *obj); +void dma_resv_fini(struct dma_resv *obj); +int dma_resv_reserve_shared(struct dma_resv *obj, unsigned int num_fences); +void dma_resv_add_shared_fence(struct dma_resv *obj, struct dma_fence *fence); -void reservation_object_add_excl_fence(struct reservation_object *obj, - struct dma_fence *fence); +void dma_resv_add_excl_fence(struct dma_resv *obj, struct dma_fence *fence); -int reservation_object_get_fences_rcu(struct reservation_object *obj, - struct dma_fence **pfence_excl, - unsigned *pshared_count, - struct dma_fence ***pshared); +int dma_resv_get_fences_rcu(struct dma_resv *obj, + struct dma_fence **pfence_excl, + unsigned *pshared_count, + struct dma_fence ***pshared); -int reservation_object_copy_fences(struct reservation_object *dst, - struct reservation_object *src); +int dma_resv_copy_fences(struct dma_resv *dst, struct dma_resv *src); -long reservation_object_wait_timeout_rcu(struct reservation_object *obj, - bool wait_all, bool intr, - unsigned long timeout); +long dma_resv_wait_timeout_rcu(struct dma_resv *obj, bool wait_all, bool intr, + unsigned long timeout); -bool reservation_object_test_signaled_rcu(struct reservation_object *obj, - bool test_all); +bool dma_resv_test_signaled_rcu(struct dma_resv *obj, bool test_all); #endif /* _LINUX_RESERVATION_H */ diff --git a/include/linux/dma/edma.h b/include/linux/dma/edma.h new file mode 100644 index 000000000000..cab6e18773da --- /dev/null +++ b/include/linux/dma/edma.h @@ -0,0 +1,47 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2018-2019 Synopsys, Inc. and/or its affiliates. + * Synopsys DesignWare eDMA core driver + * + * Author: Gustavo Pimentel <gustavo.pimentel@synopsys.com> + */ + +#ifndef _DW_EDMA_H +#define _DW_EDMA_H + +#include <linux/device.h> +#include <linux/dmaengine.h> + +struct dw_edma; + +/** + * struct dw_edma_chip - representation of DesignWare eDMA controller hardware + * @dev: struct device of the eDMA controller + * @id: instance ID + * @irq: irq line + * @dw: struct dw_edma that is filed by dw_edma_probe() + */ +struct dw_edma_chip { + struct device *dev; + int id; + int irq; + struct dw_edma *dw; +}; + +/* Export to the platform drivers */ +#if IS_ENABLED(CONFIG_DW_EDMA) +int dw_edma_probe(struct dw_edma_chip *chip); +int dw_edma_remove(struct dw_edma_chip *chip); +#else +static inline int dw_edma_probe(struct dw_edma_chip *chip) +{ + return -ENODEV; +} + +static inline int dw_edma_remove(struct dw_edma_chip *chip) +{ + return 0; +} +#endif /* CONFIG_DW_EDMA */ + +#endif /* _DW_EDMA_H */ diff --git a/include/linux/dma/mxs-dma.h b/include/linux/dma/mxs-dma.h new file mode 100644 index 000000000000..069d9f5a609e --- /dev/null +++ b/include/linux/dma/mxs-dma.h @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _MXS_DMA_H_ +#define _MXS_DMA_H_ + +#include <linux/dmaengine.h> + +#define MXS_DMA_CTRL_WAIT4END BIT(31) +#define MXS_DMA_CTRL_WAIT4RDY BIT(30) + +/* + * The mxs dmaengine can do PIO transfers. We pass a pointer to the PIO words + * in the second argument to dmaengine_prep_slave_sg when the direction is + * set to DMA_TRANS_NONE. To make this clear and to prevent users from doing + * the error prone casting we have this wrapper function + */ +static inline struct dma_async_tx_descriptor *mxs_dmaengine_prep_pio( + struct dma_chan *chan, u32 *pio, unsigned int npio, + enum dma_transfer_direction dir, unsigned long flags) +{ + return dmaengine_prep_slave_sg(chan, (struct scatterlist *)pio, npio, + dir, flags); +} + +#endif /* _MXS_DMA_H_ */ diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h index c952f987ee57..8fcdee1c0cf9 100644 --- a/include/linux/dmaengine.h +++ b/include/linux/dmaengine.h @@ -1302,7 +1302,8 @@ enum dma_status dma_sync_wait(struct dma_chan *chan, dma_cookie_t cookie); enum dma_status dma_wait_for_async_tx(struct dma_async_tx_descriptor *tx); void dma_issue_pending_all(void); struct dma_chan *__dma_request_channel(const dma_cap_mask_t *mask, - dma_filter_fn fn, void *fn_param); + dma_filter_fn fn, void *fn_param, + struct device_node *np); struct dma_chan *dma_request_slave_channel(struct device *dev, const char *name); struct dma_chan *dma_request_chan(struct device *dev, const char *name); @@ -1327,7 +1328,9 @@ static inline void dma_issue_pending_all(void) { } static inline struct dma_chan *__dma_request_channel(const dma_cap_mask_t *mask, - dma_filter_fn fn, void *fn_param) + dma_filter_fn fn, + void *fn_param, + struct device_node *np) { return NULL; } @@ -1399,7 +1402,8 @@ void dma_async_device_unregister(struct dma_device *device); void dma_run_dependencies(struct dma_async_tx_descriptor *tx); struct dma_chan *dma_get_slave_channel(struct dma_chan *chan); struct dma_chan *dma_get_any_slave_channel(struct dma_device *device); -#define dma_request_channel(mask, x, y) __dma_request_channel(&(mask), x, y) +#define dma_request_channel(mask, x, y) \ + __dma_request_channel(&(mask), x, y, NULL) #define dma_request_slave_channel_compat(mask, x, y, dev, name) \ __dma_request_slave_channel_compat(&(mask), x, y, dev, name) @@ -1417,6 +1421,6 @@ static inline struct dma_chan if (!fn || !fn_param) return NULL; - return __dma_request_channel(mask, fn, fn_param); + return __dma_request_channel(mask, fn, fn_param, NULL); } #endif /* DMAENGINE_H */ diff --git a/include/linux/dmar.h b/include/linux/dmar.h index 28813c6f44b6..a7cf3599d9a1 100644 --- a/include/linux/dmar.h +++ b/include/linux/dmar.h @@ -92,12 +92,14 @@ static inline bool dmar_rcu_check(void) #define dmar_rcu_dereference(p) rcu_dereference_check((p), dmar_rcu_check()) -#define for_each_dev_scope(a, c, p, d) \ - for ((p) = 0; ((d) = (p) < (c) ? dmar_rcu_dereference((a)[(p)].dev) : \ - NULL, (p) < (c)); (p)++) - -#define for_each_active_dev_scope(a, c, p, d) \ - for_each_dev_scope((a), (c), (p), (d)) if (!(d)) { continue; } else +#define for_each_dev_scope(devs, cnt, i, tmp) \ + for ((i) = 0; ((tmp) = (i) < (cnt) ? \ + dmar_rcu_dereference((devs)[(i)].dev) : NULL, (i) < (cnt)); \ + (i)++) + +#define for_each_active_dev_scope(devs, cnt, i, tmp) \ + for_each_dev_scope((devs), (cnt), (i), (tmp)) \ + if (!(tmp)) { continue; } else extern int dmar_table_init(void); extern int dmar_dev_scope_init(void); diff --git a/include/linux/dns_resolver.h b/include/linux/dns_resolver.h index f2b3ae22e6b7..976cbbdb2832 100644 --- a/include/linux/dns_resolver.h +++ b/include/linux/dns_resolver.h @@ -26,7 +26,8 @@ #include <uapi/linux/dns_resolver.h> -extern int dns_query(const char *type, const char *name, size_t namelen, +struct net; +extern int dns_query(struct net *net, const char *type, const char *name, size_t namelen, const char *options, char **_result, time64_t *_expiry, bool invalidate); diff --git a/include/linux/dsa/8021q.h b/include/linux/dsa/8021q.h index 3911e0586478..0aa803c451a3 100644 --- a/include/linux/dsa/8021q.h +++ b/include/linux/dsa/8021q.h @@ -20,9 +20,6 @@ int dsa_port_setup_8021q_tagging(struct dsa_switch *ds, int index, struct sk_buff *dsa_8021q_xmit(struct sk_buff *skb, struct net_device *netdev, u16 tpid, u16 tci); -struct sk_buff *dsa_8021q_rcv(struct sk_buff *skb, struct net_device *netdev, - struct packet_type *pt, u16 *tpid, u16 *tci); - u16 dsa_8021q_tx_vid(struct dsa_switch *ds, int port); u16 dsa_8021q_rx_vid(struct dsa_switch *ds, int port); @@ -31,6 +28,8 @@ int dsa_8021q_rx_switch_id(u16 vid); int dsa_8021q_rx_source_port(u16 vid); +struct sk_buff *dsa_8021q_remove_header(struct sk_buff *skb); + #else int dsa_port_setup_8021q_tagging(struct dsa_switch *ds, int index, @@ -45,12 +44,6 @@ struct sk_buff *dsa_8021q_xmit(struct sk_buff *skb, struct net_device *netdev, return NULL; } -struct sk_buff *dsa_8021q_rcv(struct sk_buff *skb, struct net_device *netdev, - struct packet_type *pt, u16 *tpid, u16 *tci) -{ - return NULL; -} - u16 dsa_8021q_tx_vid(struct dsa_switch *ds, int port) { return 0; @@ -71,6 +64,11 @@ int dsa_8021q_rx_source_port(u16 vid) return 0; } +struct sk_buff *dsa_8021q_remove_header(struct sk_buff *skb) +{ + return NULL; +} + #endif /* IS_ENABLED(CONFIG_NET_DSA_TAG_8021Q) */ #endif /* _NET_DSA_8021Q_H */ diff --git a/include/linux/dsa/sja1105.h b/include/linux/dsa/sja1105.h index e46e18c47d41..79435cfc20eb 100644 --- a/include/linux/dsa/sja1105.h +++ b/include/linux/dsa/sja1105.h @@ -12,6 +12,7 @@ #include <net/dsa.h> #define ETH_P_SJA1105 ETH_P_DSA_8021Q +#define ETH_P_SJA1105_META 0x0008 /* IEEE 802.3 Annex 57A: Slow Protocols PDUs (01:80:C2:xx:xx:xx) */ #define SJA1105_LINKLOCAL_FILTER_A 0x0180C2000000ull @@ -20,8 +21,41 @@ #define SJA1105_LINKLOCAL_FILTER_B 0x011B19000000ull #define SJA1105_LINKLOCAL_FILTER_B_MASK 0xFFFFFF000000ull +/* Source and Destination MAC of follow-up meta frames. + * Whereas the choice of SMAC only affects the unique identification of the + * switch as sender of meta frames, the DMAC must be an address that is present + * in the DSA master port's multicast MAC filter. + * 01-80-C2-00-00-0E is a good choice for this, as all profiles of IEEE 1588 + * over L2 use this address for some purpose already. + */ +#define SJA1105_META_SMAC 0x222222222222ull +#define SJA1105_META_DMAC 0x0180C200000Eull + +/* Global tagger data: each struct sja1105_port has a reference to + * the structure defined in struct sja1105_private. + */ +struct sja1105_tagger_data { + struct sk_buff_head skb_rxtstamp_queue; + struct work_struct rxtstamp_work; + struct sk_buff *stampable_skb; + /* Protects concurrent access to the meta state machine + * from taggers running on multiple ports on SMP systems + */ + spinlock_t meta_lock; + bool hwts_rx_en; +}; + +struct sja1105_skb_cb { + u32 meta_tstamp; +}; + +#define SJA1105_SKB_CB(skb) \ + ((struct sja1105_skb_cb *)DSA_SKB_CB_PRIV(skb)) + struct sja1105_port { + struct sja1105_tagger_data *data; struct dsa_port *dp; + bool hwts_tx_en; int mgmt_slot; }; diff --git a/include/linux/edac.h b/include/linux/edac.h index 342dabda9c7e..c19483b90079 100644 --- a/include/linux/edac.h +++ b/include/linux/edac.h @@ -440,7 +440,7 @@ struct dimm_info { char label[EDAC_MC_LABEL_LEN + 1]; /* DIMM label on motherboard */ /* Memory location data */ - unsigned location[EDAC_MAX_LAYERS]; + unsigned int location[EDAC_MAX_LAYERS]; struct mem_ctl_info *mci; /* the parent */ @@ -451,7 +451,7 @@ struct dimm_info { u32 nr_pages; /* number of pages on this dimm */ - unsigned csrow, cschannel; /* Points to the old API data */ + unsigned int csrow, cschannel; /* Points to the old API data */ u16 smbios_handle; /* Handle for SMBIOS type 17 */ }; @@ -597,7 +597,7 @@ struct mem_ctl_info { unsigned long page); int mc_idx; struct csrow_info **csrows; - unsigned nr_csrows, num_cschannel; + unsigned int nr_csrows, num_cschannel; /* * Memory Controller hierarchy @@ -608,14 +608,14 @@ struct mem_ctl_info { * of the recent drivers enumerate memories per DIMM, instead. * When the memory controller is per rank, csbased is true. */ - unsigned n_layers; + unsigned int n_layers; struct edac_mc_layer *layers; bool csbased; /* * DIMM info. Will eventually remove the entire csrows_info some day */ - unsigned tot_dimms; + unsigned int tot_dimms; struct dimm_info **dimms; /* diff --git a/include/linux/edma.h b/include/linux/edma.h deleted file mode 100644 index a1307e7827e8..000000000000 --- a/include/linux/edma.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * TI EDMA DMA engine driver - * - * Copyright 2012 Texas Instruments - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation version 2. - * - * This program is distributed "as is" WITHOUT ANY WARRANTY of any - * kind, whether express or implied; without even the implied warranty - * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ -#ifndef __LINUX_EDMA_H -#define __LINUX_EDMA_H - -struct dma_chan; - -#if defined(CONFIG_TI_EDMA) || defined(CONFIG_TI_EDMA_MODULE) -bool edma_filter_fn(struct dma_chan *, void *); -#else -static inline bool edma_filter_fn(struct dma_chan *chan, void *param) -{ - return false; -} -#endif - -#endif diff --git a/include/linux/efi.h b/include/linux/efi.h index 6ebc2098cfe1..bd3837022307 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h @@ -689,8 +689,12 @@ void efi_native_runtime_setup(void); #define LINUX_EFI_LOADER_ENTRY_GUID EFI_GUID(0x4a67b082, 0x0a4c, 0x41cf, 0xb6, 0xc7, 0x44, 0x0b, 0x29, 0xbb, 0x8c, 0x4f) #define LINUX_EFI_RANDOM_SEED_TABLE_GUID EFI_GUID(0x1ce1e5bc, 0x7ceb, 0x42f2, 0x81, 0xe5, 0x8a, 0xad, 0xf1, 0x80, 0xf5, 0x7b) #define LINUX_EFI_TPM_EVENT_LOG_GUID EFI_GUID(0xb7799cb0, 0xeca2, 0x4943, 0x96, 0x67, 0x1f, 0xae, 0x07, 0xb7, 0x47, 0xfa) +#define LINUX_EFI_TPM_FINAL_LOG_GUID EFI_GUID(0x1e2ed096, 0x30e2, 0x4254, 0xbd, 0x89, 0x86, 0x3b, 0xbe, 0xf8, 0x23, 0x25) #define LINUX_EFI_MEMRESERVE_TABLE_GUID EFI_GUID(0x888eb0c6, 0x8ede, 0x4ff5, 0xa8, 0xf0, 0x9a, 0xee, 0x5c, 0xb9, 0x77, 0xc2) +/* OEM GUIDs */ +#define DELLEMC_EFI_RCI2_TABLE_GUID EFI_GUID(0x2d9f28a2, 0xa886, 0x456a, 0x97, 0xa8, 0xf1, 0x1e, 0xf2, 0x4f, 0xf4, 0x55) + typedef struct { efi_guid_t guid; u64 table; @@ -983,11 +987,9 @@ extern struct efi { unsigned long acpi20; /* ACPI table (ACPI 2.0) */ unsigned long smbios; /* SMBIOS table (32 bit entry point) */ unsigned long smbios3; /* SMBIOS table (64 bit entry point) */ - unsigned long sal_systab; /* SAL system table */ unsigned long boot_info; /* boot info table */ unsigned long hcdp; /* HCDP table */ unsigned long uga; /* UGA table */ - unsigned long uv_systab; /* UV system table */ unsigned long fw_vendor; /* fw_vendor */ unsigned long runtime; /* runtime table */ unsigned long config_table; /* config tables */ @@ -996,6 +998,7 @@ extern struct efi { unsigned long mem_attr_table; /* memory attributes table */ unsigned long rng_seed; /* UEFI firmware random seed */ unsigned long tpm_log; /* TPM2 Event Log table */ + unsigned long tpm_final_log; /* TPM2 Final Events Log table */ unsigned long mem_reserve; /* Linux EFI memreserve table */ efi_get_time_t *get_time; efi_set_time_t *set_time; @@ -1209,8 +1212,6 @@ static inline bool efi_enabled(int feature) return test_bit(feature, &efi.flags) != 0; } extern void efi_reboot(enum reboot_mode reboot_mode, const char *__unused); - -extern bool efi_is_table_address(unsigned long phys_addr); #else static inline bool efi_enabled(int feature) { @@ -1224,11 +1225,6 @@ efi_capsule_pending(int *reset_type) { return false; } - -static inline bool efi_is_table_address(unsigned long phys_addr) -{ - return false; -} #endif extern int efi_status_to_err(efi_status_t status); @@ -1706,12 +1702,22 @@ struct linux_efi_random_seed { struct linux_efi_tpm_eventlog { u32 size; + u32 final_events_preboot_size; u8 version; u8 log[]; }; extern int efi_tpm_eventlog_init(void); +struct efi_tcg2_final_events_table { + u64 version; + u64 nr_events; + u8 events[]; +}; +extern int efi_tpm_final_log_size; + +extern unsigned long rci2_table_phys; + /* * efi_runtime_service() function identifiers. * "NONE" is used by efi_recover_from_page_fault() to check if the page diff --git a/include/linux/elevator.h b/include/linux/elevator.h index 6e8bc53740f0..901bda352dcb 100644 --- a/include/linux/elevator.h +++ b/include/linux/elevator.h @@ -34,7 +34,7 @@ struct elevator_mq_ops { void (*depth_updated)(struct blk_mq_hw_ctx *); bool (*allow_merge)(struct request_queue *, struct request *, struct bio *); - bool (*bio_merge)(struct blk_mq_hw_ctx *, struct bio *); + bool (*bio_merge)(struct blk_mq_hw_ctx *, struct bio *, unsigned int); int (*request_merge)(struct request_queue *q, struct request **, struct bio *); void (*request_merged)(struct request_queue *, struct request *, enum elv_merge); void (*requests_merged)(struct request_queue *, struct request *, struct request *); @@ -45,7 +45,6 @@ struct elevator_mq_ops { struct request *(*dispatch_request)(struct blk_mq_hw_ctx *); bool (*has_work)(struct blk_mq_hw_ctx *); void (*completed_request)(struct request *, u64); - void (*started_request)(struct request *); void (*requeue_request)(struct request *); struct request *(*former_request)(struct request_queue *, struct request *); struct request *(*next_request)(struct request_queue *, struct request *); @@ -75,8 +74,9 @@ struct elevator_type size_t icq_size; /* see iocontext.h */ size_t icq_align; /* ditto */ struct elv_fs_entry *elevator_attrs; - char elevator_name[ELV_NAME_MAX]; + const char *elevator_name; const char *elevator_alias; + const unsigned int elevator_features; struct module *elevator_owner; #ifdef CONFIG_BLK_DEBUG_FS const struct blk_mq_debugfs_attr *queue_debugfs_attrs; @@ -160,20 +160,18 @@ extern struct request *elv_rb_find(struct rb_root *, sector_t); #define ELEVATOR_INSERT_FLUSH 5 #define ELEVATOR_INSERT_SORT_MERGE 6 -/* - * return values from elevator_may_queue_fn - */ -enum { - ELV_MQUEUE_MAY, - ELV_MQUEUE_NO, - ELV_MQUEUE_MUST, -}; - #define rq_end_sector(rq) (blk_rq_pos(rq) + blk_rq_sectors(rq)) #define rb_entry_rq(node) rb_entry((node), struct request, rb_node) #define rq_entry_fifo(ptr) list_entry((ptr), struct request, queuelist) #define rq_fifo_clear(rq) list_del_init(&(rq)->queuelist) +/* + * Elevator features. + */ + +/* Supports zoned block devices sequential write constraint */ +#define ELEVATOR_F_ZBD_SEQ_WRITE (1U << 0) + #endif /* CONFIG_BLOCK */ #endif diff --git a/include/linux/energy_model.h b/include/linux/energy_model.h index aa027f7bcb3e..73f8c3cb9588 100644 --- a/include/linux/energy_model.h +++ b/include/linux/energy_model.h @@ -89,7 +89,7 @@ static inline unsigned long em_pd_energy(struct em_perf_domain *pd, * like schedutil. */ cpu = cpumask_first(to_cpumask(pd->cpus)); - scale_cpu = arch_scale_cpu_capacity(NULL, cpu); + scale_cpu = arch_scale_cpu_capacity(cpu); cs = &pd->table[pd->nr_cap_states - 1]; freq = map_util_freq(max_util, cs->frequency, scale_cpu); diff --git a/include/linux/error-injection.h b/include/linux/error-injection.h index 280c61ecbf20..635a95caf29f 100644 --- a/include/linux/error-injection.h +++ b/include/linux/error-injection.h @@ -2,16 +2,16 @@ #ifndef _LINUX_ERROR_INJECTION_H #define _LINUX_ERROR_INJECTION_H -#ifdef CONFIG_FUNCTION_ERROR_INJECTION +#include <linux/compiler.h> +#include <asm-generic/error-injection.h> -#include <asm/error-injection.h> +#ifdef CONFIG_FUNCTION_ERROR_INJECTION extern bool within_error_injection_list(unsigned long addr); extern int get_injectable_error_type(unsigned long addr); #else /* !CONFIG_FUNCTION_ERROR_INJECTION */ -#include <asm-generic/error-injection.h> static inline bool within_error_injection_list(unsigned long addr) { return false; diff --git a/include/linux/export.h b/include/linux/export.h index fd8711ed9ac4..95f55b7f83a0 100644 --- a/include/linux/export.h +++ b/include/linux/export.h @@ -18,9 +18,8 @@ extern struct module __this_module; #define THIS_MODULE ((struct module *)0) #endif -#ifdef CONFIG_MODULES +#define NS_SEPARATOR "." -#if defined(__KERNEL__) && !defined(__GENKSYMS__) #ifdef CONFIG_MODVERSIONS /* Mark the CRC weak since genksyms apparently decides not to * generate a checksums for some symbols */ @@ -29,13 +28,13 @@ extern struct module __this_module; asm(" .section \"___kcrctab" sec "+" #sym "\", \"a\" \n" \ " .weak __crc_" #sym " \n" \ " .long __crc_" #sym " - . \n" \ - " .previous \n"); + " .previous \n") #else #define __CRC_SYMBOL(sym, sec) \ asm(" .section \"___kcrctab" sec "+" #sym "\", \"a\" \n" \ " .weak __crc_" #sym " \n" \ " .long __crc_" #sym " \n" \ - " .previous \n"); + " .previous \n") #endif #else #define __CRC_SYMBOL(sym, sec) @@ -49,47 +48,89 @@ extern struct module __this_module; * absolute relocations that require runtime processing on relocatable * kernels. */ +#define __KSYMTAB_ENTRY_NS(sym, sec, ns) \ + __ADDRESSABLE(sym) \ + asm(" .section \"___ksymtab" sec "+" #sym "\", \"a\" \n" \ + " .balign 4 \n" \ + "__ksymtab_" #sym NS_SEPARATOR #ns ": \n" \ + " .long " #sym "- . \n" \ + " .long __kstrtab_" #sym "- . \n" \ + " .long __kstrtab_ns_" #sym "- . \n" \ + " .previous \n") + #define __KSYMTAB_ENTRY(sym, sec) \ __ADDRESSABLE(sym) \ asm(" .section \"___ksymtab" sec "+" #sym "\", \"a\" \n" \ - " .balign 8 \n" \ + " .balign 4 \n" \ "__ksymtab_" #sym ": \n" \ " .long " #sym "- . \n" \ " .long __kstrtab_" #sym "- . \n" \ + " .long 0 \n" \ " .previous \n") struct kernel_symbol { int value_offset; int name_offset; + int namespace_offset; }; #else +#define __KSYMTAB_ENTRY_NS(sym, sec, ns) \ + static const struct kernel_symbol __ksymtab_##sym##__##ns \ + asm("__ksymtab_" #sym NS_SEPARATOR #ns) \ + __attribute__((section("___ksymtab" sec "+" #sym), used)) \ + __aligned(sizeof(void *)) \ + = { (unsigned long)&sym, __kstrtab_##sym, __kstrtab_ns_##sym } + #define __KSYMTAB_ENTRY(sym, sec) \ static const struct kernel_symbol __ksymtab_##sym \ + asm("__ksymtab_" #sym) \ __attribute__((section("___ksymtab" sec "+" #sym), used)) \ - = { (unsigned long)&sym, __kstrtab_##sym } + __aligned(sizeof(void *)) \ + = { (unsigned long)&sym, __kstrtab_##sym, NULL } struct kernel_symbol { unsigned long value; const char *name; + const char *namespace; }; #endif -/* For every exported symbol, place a struct in the __ksymtab section */ -#define ___EXPORT_SYMBOL(sym, sec) \ +#ifdef __GENKSYMS__ + +#define ___EXPORT_SYMBOL(sym,sec) __GENKSYMS_EXPORT_SYMBOL(sym) +#define ___EXPORT_SYMBOL_NS(sym,sec,ns) __GENKSYMS_EXPORT_SYMBOL(sym) + +#else + +#define ___export_symbol_common(sym, sec) \ extern typeof(sym) sym; \ - __CRC_SYMBOL(sym, sec) \ + __CRC_SYMBOL(sym, sec); \ static const char __kstrtab_##sym[] \ __attribute__((section("__ksymtab_strings"), used, aligned(1))) \ - = #sym; \ + = #sym \ + +/* For every exported symbol, place a struct in the __ksymtab section */ +#define ___EXPORT_SYMBOL_NS(sym, sec, ns) \ + ___export_symbol_common(sym, sec); \ + static const char __kstrtab_ns_##sym[] \ + __attribute__((section("__ksymtab_strings"), used, aligned(1))) \ + = #ns; \ + __KSYMTAB_ENTRY_NS(sym, sec, ns) + +#define ___EXPORT_SYMBOL(sym, sec) \ + ___export_symbol_common(sym, sec); \ __KSYMTAB_ENTRY(sym, sec) -#if defined(__DISABLE_EXPORTS) +#endif + +#if !defined(CONFIG_MODULES) || defined(__DISABLE_EXPORTS) /* * Allow symbol exports to be disabled completely so that C code may * be reused in other execution contexts such as the UEFI stub or the * decompressor. */ +#define __EXPORT_SYMBOL_NS(sym, sec, ns) #define __EXPORT_SYMBOL(sym, sec) #elif defined(CONFIG_TRIM_UNUSED_KSYMS) @@ -116,38 +157,43 @@ struct kernel_symbol { #define __cond_export_sym_1(sym, sec) ___EXPORT_SYMBOL(sym, sec) #define __cond_export_sym_0(sym, sec) /* nothing */ +#define __EXPORT_SYMBOL_NS(sym, sec, ns) \ + __ksym_marker(sym); \ + __cond_export_ns_sym(sym, sec, ns, __is_defined(__KSYM_##sym)) +#define __cond_export_ns_sym(sym, sec, ns, conf) \ + ___cond_export_ns_sym(sym, sec, ns, conf) +#define ___cond_export_ns_sym(sym, sec, ns, enabled) \ + __cond_export_ns_sym_##enabled(sym, sec, ns) +#define __cond_export_ns_sym_1(sym, sec, ns) ___EXPORT_SYMBOL_NS(sym, sec, ns) +#define __cond_export_ns_sym_0(sym, sec, ns) /* nothing */ + #else -#define __EXPORT_SYMBOL ___EXPORT_SYMBOL -#endif -#define EXPORT_SYMBOL(sym) \ - __EXPORT_SYMBOL(sym, "") +#define __EXPORT_SYMBOL_NS(sym,sec,ns) ___EXPORT_SYMBOL_NS(sym,sec,ns) +#define __EXPORT_SYMBOL(sym,sec) ___EXPORT_SYMBOL(sym,sec) -#define EXPORT_SYMBOL_GPL(sym) \ - __EXPORT_SYMBOL(sym, "_gpl") +#endif /* CONFIG_MODULES */ -#define EXPORT_SYMBOL_GPL_FUTURE(sym) \ - __EXPORT_SYMBOL(sym, "_gpl_future") +#ifdef DEFAULT_SYMBOL_NAMESPACE +#undef __EXPORT_SYMBOL +#define __EXPORT_SYMBOL(sym, sec) \ + __EXPORT_SYMBOL_NS(sym, sec, DEFAULT_SYMBOL_NAMESPACE) +#endif + +#define EXPORT_SYMBOL(sym) __EXPORT_SYMBOL(sym, "") +#define EXPORT_SYMBOL_GPL(sym) __EXPORT_SYMBOL(sym, "_gpl") +#define EXPORT_SYMBOL_GPL_FUTURE(sym) __EXPORT_SYMBOL(sym, "_gpl_future") +#define EXPORT_SYMBOL_NS(sym, ns) __EXPORT_SYMBOL_NS(sym, "", ns) +#define EXPORT_SYMBOL_NS_GPL(sym, ns) __EXPORT_SYMBOL_NS(sym, "_gpl", ns) #ifdef CONFIG_UNUSED_SYMBOLS -#define EXPORT_UNUSED_SYMBOL(sym) __EXPORT_SYMBOL(sym, "_unused") -#define EXPORT_UNUSED_SYMBOL_GPL(sym) __EXPORT_SYMBOL(sym, "_unused_gpl") +#define EXPORT_UNUSED_SYMBOL(sym) __EXPORT_SYMBOL(sym, "_unused") +#define EXPORT_UNUSED_SYMBOL_GPL(sym) __EXPORT_SYMBOL(sym, "_unused_gpl") #else #define EXPORT_UNUSED_SYMBOL(sym) #define EXPORT_UNUSED_SYMBOL_GPL(sym) #endif -#endif /* __GENKSYMS__ */ - -#else /* !CONFIG_MODULES... */ - -#define EXPORT_SYMBOL(sym) -#define EXPORT_SYMBOL_GPL(sym) -#define EXPORT_SYMBOL_GPL_FUTURE(sym) -#define EXPORT_UNUSED_SYMBOL(sym) -#define EXPORT_UNUSED_SYMBOL_GPL(sym) - -#endif /* CONFIG_MODULES */ #endif /* !__ASSEMBLY__ */ #endif /* _LINUX_EXPORT_H */ diff --git a/include/linux/exportfs.h b/include/linux/exportfs.h index 0d3037419bc7..cf6571fc9c01 100644 --- a/include/linux/exportfs.h +++ b/include/linux/exportfs.h @@ -139,7 +139,7 @@ struct fid { * @get_parent: find the parent of a given directory * @commit_metadata: commit metadata changes to stable storage * - * See Documentation/filesystems/nfs/Exporting for details on how to use + * See Documentation/filesystems/nfs/exporting.rst for details on how to use * this interface correctly. * * encode_fh: diff --git a/include/linux/extable.h b/include/linux/extable.h index 41c5b3a25f67..81ecfaa83ad3 100644 --- a/include/linux/extable.h +++ b/include/linux/extable.h @@ -19,6 +19,8 @@ void trim_init_extable(struct module *m); /* Given an address, look for it in the exception tables */ const struct exception_table_entry *search_exception_tables(unsigned long add); +const struct exception_table_entry * +search_kernel_exception_table(unsigned long addr); #ifdef CONFIG_MODULES /* For extable.c to search modules' exception tables. */ diff --git a/include/linux/f2fs_fs.h b/include/linux/f2fs_fs.h index 65559900d4d7..284738996028 100644 --- a/include/linux/f2fs_fs.h +++ b/include/linux/f2fs_fs.h @@ -36,11 +36,17 @@ #define F2FS_MAX_QUOTAS 3 +#define F2FS_ENC_UTF8_12_1 1 +#define F2FS_ENC_STRICT_MODE_FL (1 << 0) +#define f2fs_has_strict_mode(sbi) \ + (sbi->s_encoding_flags & F2FS_ENC_STRICT_MODE_FL) + #define F2FS_IO_SIZE(sbi) (1 << F2FS_OPTION(sbi).write_io_size_bits) /* Blocks */ #define F2FS_IO_SIZE_KB(sbi) (1 << (F2FS_OPTION(sbi).write_io_size_bits + 2)) /* KB */ #define F2FS_IO_SIZE_BYTES(sbi) (1 << (F2FS_OPTION(sbi).write_io_size_bits + 12)) /* B */ #define F2FS_IO_SIZE_BITS(sbi) (F2FS_OPTION(sbi).write_io_size_bits) /* power of 2 */ #define F2FS_IO_SIZE_MASK(sbi) (F2FS_IO_SIZE(sbi) - 1) +#define F2FS_IO_ALIGNED(sbi) (F2FS_IO_SIZE(sbi) > 1) /* This flag is used by node and meta inodes, and by recovery */ #define GFP_F2FS_ZERO (GFP_NOFS | __GFP_ZERO) @@ -109,7 +115,9 @@ struct f2fs_super_block { struct f2fs_device devs[MAX_DEVICES]; /* device list */ __le32 qf_ino[F2FS_MAX_QUOTAS]; /* quota inode numbers */ __u8 hot_ext_count; /* # of hot file extension */ - __u8 reserved[310]; /* valid reserved region */ + __le16 s_encoding; /* Filename charset encoding */ + __le16 s_encoding_flags; /* Filename charset encoding flags */ + __u8 reserved[306]; /* valid reserved region */ __le32 crc; /* checksum of superblock */ } __packed; diff --git a/include/linux/fault-inject.h b/include/linux/fault-inject.h index 7e6c77740413..e525f6957c49 100644 --- a/include/linux/fault-inject.h +++ b/include/linux/fault-inject.h @@ -11,7 +11,7 @@ /* * For explanation of the elements of this struct, see - * Documentation/fault-injection/fault-injection.txt + * Documentation/fault-injection/fault-injection.rst */ struct fault_attr { unsigned long probability; diff --git a/include/linux/fb.h b/include/linux/fb.h index f52ef0ad6781..756706b666a1 100644 --- a/include/linux/fb.h +++ b/include/linux/fb.h @@ -126,43 +126,15 @@ struct fb_cursor_user { /* The resolution of the passed in fb_info about to change */ #define FB_EVENT_MODE_CHANGE 0x01 -/* The display on this fb_info is being suspended, no access to the - * framebuffer is allowed any more after that call returns - */ -#define FB_EVENT_SUSPEND 0x02 -/* The display on this fb_info was resumed, you can restore the display - * if you own it - */ -#define FB_EVENT_RESUME 0x03 -/* An entry from the modelist was removed */ -#define FB_EVENT_MODE_DELETE 0x04 -/* A driver registered itself */ + +#ifdef CONFIG_GUMSTIX_AM200EPD +/* only used by mach-pxa/am200epd.c */ #define FB_EVENT_FB_REGISTERED 0x05 -/* A driver unregistered itself */ #define FB_EVENT_FB_UNREGISTERED 0x06 -/* CONSOLE-SPECIFIC: get console to framebuffer mapping */ -#define FB_EVENT_GET_CONSOLE_MAP 0x07 -/* CONSOLE-SPECIFIC: set console to framebuffer mapping */ -#define FB_EVENT_SET_CONSOLE_MAP 0x08 -/* A hardware display blank change occurred */ +#endif + +/* A display blank is requested */ #define FB_EVENT_BLANK 0x09 -/* Private modelist is to be replaced */ -#define FB_EVENT_NEW_MODELIST 0x0A -/* The resolution of the passed in fb_info about to change and - all vc's should be changed */ -#define FB_EVENT_MODE_CHANGE_ALL 0x0B -/* A software display blank change occurred */ -#define FB_EVENT_CONBLANK 0x0C -/* Get drawing requirements */ -#define FB_EVENT_GET_REQ 0x0D -/* Unbind from the console if possible */ -#define FB_EVENT_FB_UNBIND 0x0E -/* CONSOLE-SPECIFIC: remap all consoles to new fb - for vga_switcheroo */ -#define FB_EVENT_REMAP_ALL_CONSOLE 0x0F -/* A hardware display blank early change occurred */ -#define FB_EARLY_EVENT_BLANK 0x10 -/* A hardware display blank revert early change occurred */ -#define FB_R_EARLY_EVENT_BLANK 0x11 struct fb_event { struct fb_info *info; @@ -633,8 +605,8 @@ extern ssize_t fb_sys_write(struct fb_info *info, const char __user *buf, /* drivers/video/fbmem.c */ extern int register_framebuffer(struct fb_info *fb_info); -extern int unregister_framebuffer(struct fb_info *fb_info); -extern int unlink_framebuffer(struct fb_info *fb_info); +extern void unregister_framebuffer(struct fb_info *fb_info); +extern void unlink_framebuffer(struct fb_info *fb_info); extern int remove_conflicting_pci_framebuffers(struct pci_dev *pdev, int res_id, const char *name); extern int remove_conflicting_framebuffers(struct apertures_struct *a, @@ -660,7 +632,10 @@ extern struct class *fb_class; for (i = 0; i < FB_MAX; i++) \ if (!registered_fb[i]) {} else -extern int lock_fb_info(struct fb_info *info); +static inline void lock_fb_info(struct fb_info *info) +{ + mutex_lock(&info->lock); +} static inline void unlock_fb_info(struct fb_info *info) { @@ -742,8 +717,6 @@ extern int fb_parse_edid(unsigned char *edid, struct fb_var_screeninfo *var); extern const unsigned char *fb_firmware_edid(struct device *device); extern void fb_edid_to_monspecs(unsigned char *edid, struct fb_monspecs *specs); -extern void fb_edid_add_monspecs(unsigned char *edid, - struct fb_monspecs *specs); extern void fb_destroy_modedb(struct fb_videomode *modedb); extern int fb_find_mode_cvt(struct fb_videomode *mode, int margins, int rb); extern unsigned char *fb_ddc_read(struct i2c_adapter *adapter); @@ -817,7 +790,6 @@ struct dmt_videomode { extern const char *fb_mode_option; extern const struct fb_videomode vesa_modes[]; -extern const struct fb_videomode cea_modes[65]; extern const struct dmt_videomode dmt_modes[]; struct fb_modelist { diff --git a/include/linux/fbcon.h b/include/linux/fbcon.h index f68a7db14165..ff5596dd30f8 100644 --- a/include/linux/fbcon.h +++ b/include/linux/fbcon.h @@ -4,9 +4,39 @@ #ifdef CONFIG_FRAMEBUFFER_CONSOLE void __init fb_console_init(void); void __exit fb_console_exit(void); +int fbcon_fb_registered(struct fb_info *info); +void fbcon_fb_unregistered(struct fb_info *info); +void fbcon_fb_unbind(struct fb_info *info); +void fbcon_suspended(struct fb_info *info); +void fbcon_resumed(struct fb_info *info); +int fbcon_mode_deleted(struct fb_info *info, + struct fb_videomode *mode); +void fbcon_new_modelist(struct fb_info *info); +void fbcon_get_requirement(struct fb_info *info, + struct fb_blit_caps *caps); +void fbcon_fb_blanked(struct fb_info *info, int blank); +void fbcon_update_vcs(struct fb_info *info, bool all); +void fbcon_remap_all(struct fb_info *info); +int fbcon_set_con2fb_map_ioctl(void __user *argp); +int fbcon_get_con2fb_map_ioctl(void __user *argp); #else static inline void fb_console_init(void) {} static inline void fb_console_exit(void) {} +static inline int fbcon_fb_registered(struct fb_info *info) { return 0; } +static inline void fbcon_fb_unregistered(struct fb_info *info) {} +static inline void fbcon_fb_unbind(struct fb_info *info) {} +static inline void fbcon_suspended(struct fb_info *info) {} +static inline void fbcon_resumed(struct fb_info *info) {} +static inline int fbcon_mode_deleted(struct fb_info *info, + struct fb_videomode *mode) { return 0; } +static inline void fbcon_new_modelist(struct fb_info *info) {} +static inline void fbcon_get_requirement(struct fb_info *info, + struct fb_blit_caps *caps) {} +static inline void fbcon_fb_blanked(struct fb_info *info, int blank) {} +static inline void fbcon_update_vcs(struct fb_info *info, bool all) {} +static inline void fbcon_remap_all(struct fb_info *info) {} +static inline int fbcon_set_con2fb_map_ioctl(void __user *argp) { return 0; } +static inline int fbcon_get_con2fb_map_ioctl(void __user *argp) { return 0; } #endif #endif /* _LINUX_FBCON_H */ diff --git a/include/linux/filter.h b/include/linux/filter.h index 7148bab96943..2ce57645f3cd 100644 --- a/include/linux/filter.h +++ b/include/linux/filter.h @@ -24,6 +24,7 @@ #include <net/sch_generic.h> +#include <asm/byteorder.h> #include <uapi/linux/filter.h> #include <uapi/linux/bpf.h> @@ -160,6 +161,20 @@ struct ctl_table_header; .off = 0, \ .imm = IMM }) +/* Special form of mov32, used for doing explicit zero extension on dst. */ +#define BPF_ZEXT_REG(DST) \ + ((struct bpf_insn) { \ + .code = BPF_ALU | BPF_MOV | BPF_X, \ + .dst_reg = DST, \ + .src_reg = DST, \ + .off = 0, \ + .imm = 1 }) + +static inline bool insn_is_zext(const struct bpf_insn *insn) +{ + return insn->code == (BPF_ALU | BPF_MOV | BPF_X) && insn->imm == 1; +} + /* BPF_LD_IMM64 macro encodes single 'load 64-bit immediate' insn */ #define BPF_LD_IMM64(DST, IMM) \ BPF_LD_IMM64_RAW(DST, 0, IMM) @@ -512,7 +527,8 @@ struct bpf_prog { blinded:1, /* Was blinded */ is_func:1, /* program is a bpf function */ kprobe_override:1, /* Do we override a kprobe? */ - has_callchain_buf:1; /* callchain buffer allocated? */ + has_callchain_buf:1, /* callchain buffer allocated? */ + enforce_expected_attach_type:1; /* Enforce expected_attach_type checking at attach time */ enum bpf_prog_type type; /* Type of BPF program */ enum bpf_attach_type expected_attach_type; /* For some prog types */ u32 len; /* Number of filter blocks */ @@ -563,8 +579,9 @@ struct bpf_skb_data_end { }; struct bpf_redirect_info { - u32 ifindex; u32 flags; + u32 tgt_index; + void *tgt_value; struct bpf_map *map; struct bpf_map *map_to_flush; u32 kern_flags; @@ -731,6 +748,24 @@ bpf_ctx_narrow_access_ok(u32 off, u32 size, u32 size_default) return size <= size_default && (size & (size - 1)) == 0; } +static inline u8 +bpf_ctx_narrow_access_offset(u32 off, u32 size, u32 size_default) +{ + u8 access_off = off & (size_default - 1); + +#ifdef __LITTLE_ENDIAN + return access_off; +#else + return size_default - (access_off + size); +#endif +} + +#define bpf_ctx_wide_access_ok(off, size, type, field) \ + (size == sizeof(__u64) && \ + off >= offsetof(type, field) && \ + off + sizeof(__u64) <= offsetofend(type, field) && \ + off % sizeof(__u64) == 0) + #define bpf_classic_proglen(fprog) (fprog->len * sizeof(fprog->filter[0])) static inline void bpf_prog_lock_ro(struct bpf_prog *fp) @@ -811,6 +846,7 @@ u64 __bpf_call_base(u64 r1, u64 r2, u64 r3, u64 r4, u64 r5); struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog); void bpf_jit_compile(struct bpf_prog *prog); +bool bpf_jit_needs_zext(void); bool bpf_helper_changes_pkt_data(void *func); static inline bool bpf_dump_raw_ok(void) @@ -1183,4 +1219,14 @@ struct bpf_sysctl_kern { u64 tmp_reg; }; +struct bpf_sockopt_kern { + struct sock *sk; + u8 *optval; + u8 *optval_end; + s32 level; + s32 optname; + s32 optlen; + s32 retval; +}; + #endif /* __LINUX_FILTER_H__ */ diff --git a/include/linux/fips.h b/include/linux/fips.h index afeeece92302..c6961e932fef 100644 --- a/include/linux/fips.h +++ b/include/linux/fips.h @@ -4,8 +4,15 @@ #ifdef CONFIG_CRYPTO_FIPS extern int fips_enabled; +extern struct atomic_notifier_head fips_fail_notif_chain; + +void fips_fail_notify(void); + #else #define fips_enabled 0 + +static inline void fips_fail_notify(void) {} + #endif #endif diff --git a/include/linux/firmware/imx/dsp.h b/include/linux/firmware/imx/dsp.h new file mode 100644 index 000000000000..7562099c9e46 --- /dev/null +++ b/include/linux/firmware/imx/dsp.h @@ -0,0 +1,67 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright 2019 NXP + * + * Header file for the DSP IPC implementation + */ + +#ifndef _IMX_DSP_IPC_H +#define _IMX_DSP_IPC_H + +#include <linux/device.h> +#include <linux/types.h> +#include <linux/mailbox_client.h> + +#define DSP_MU_CHAN_NUM 4 + +struct imx_dsp_chan { + struct imx_dsp_ipc *ipc; + struct mbox_client cl; + struct mbox_chan *ch; + char *name; + int idx; +}; + +struct imx_dsp_ops { + void (*handle_reply)(struct imx_dsp_ipc *ipc); + void (*handle_request)(struct imx_dsp_ipc *ipc); +}; + +struct imx_dsp_ipc { + /* Host <-> DSP communication uses 2 txdb and 2 rxdb channels */ + struct imx_dsp_chan chans[DSP_MU_CHAN_NUM]; + struct device *dev; + struct imx_dsp_ops *ops; + void *private_data; +}; + +static inline void imx_dsp_set_data(struct imx_dsp_ipc *ipc, void *data) +{ + if (!ipc) + return; + + ipc->private_data = data; +} + +static inline void *imx_dsp_get_data(struct imx_dsp_ipc *ipc) +{ + if (!ipc) + return NULL; + + return ipc->private_data; +} + +#if IS_ENABLED(CONFIG_IMX_DSP) + +int imx_dsp_ring_doorbell(struct imx_dsp_ipc *dsp, unsigned int chan_idx); + +#else + +static inline int imx_dsp_ring_doorbell(struct imx_dsp_ipc *ipc, + unsigned int chan_idx) +{ + return -ENOTSUPP; +} + +#endif +#endif /* _IMX_DSP_IPC_H */ diff --git a/include/linux/firmware/intel/stratix10-smc.h b/include/linux/firmware/intel/stratix10-smc.h index 01684d935580..013ae4819deb 100644 --- a/include/linux/firmware/intel/stratix10-smc.h +++ b/include/linux/firmware/intel/stratix10-smc.h @@ -210,7 +210,7 @@ INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_FPGA_CONFIG_COMPLETED_WRITE) #define INTEL_SIP_SMC_FPGA_CONFIG_LOOPBACK \ INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_FPGA_CONFIG_LOOPBACK) -/* +/** * Request INTEL_SIP_SMC_REG_READ * * Read a protected register at EL3 @@ -229,7 +229,7 @@ INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_FPGA_CONFIG_COMPLETED_WRITE) #define INTEL_SIP_SMC_REG_READ \ INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_REG_READ) -/* +/** * Request INTEL_SIP_SMC_REG_WRITE * * Write a protected register at EL3 @@ -248,7 +248,7 @@ INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_FPGA_CONFIG_COMPLETED_WRITE) #define INTEL_SIP_SMC_REG_WRITE \ INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_REG_WRITE) -/* +/** * Request INTEL_SIP_SMC_FUNCID_REG_UPDATE * * Update one or more bits in a protected register at EL3 using a @@ -269,7 +269,7 @@ INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_FPGA_CONFIG_COMPLETED_WRITE) #define INTEL_SIP_SMC_REG_UPDATE \ INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_REG_UPDATE) -/* +/** * Request INTEL_SIP_SMC_RSU_STATUS * * Request remote status update boot log, call is synchronous. @@ -292,7 +292,7 @@ INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_FPGA_CONFIG_COMPLETED_WRITE) #define INTEL_SIP_SMC_RSU_STATUS \ INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_RSU_STATUS) -/* +/** * Request INTEL_SIP_SMC_RSU_UPDATE * * Request to set the offset of the bitstream to boot after reboot, call @@ -310,7 +310,7 @@ INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_FPGA_CONFIG_COMPLETED_WRITE) #define INTEL_SIP_SMC_RSU_UPDATE \ INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_RSU_UPDATE) -/* +/** * Request INTEL_SIP_SMC_ECC_DBE * * Sync call used by service driver at EL1 to alert EL3 that a Double @@ -329,3 +329,42 @@ INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_FPGA_CONFIG_COMPLETED_WRITE) INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_ECC_DBE) #endif + +/** + * Request INTEL_SIP_SMC_RSU_NOTIFY + * + * Sync call used by service driver at EL1 to report hard processor + * system execution stage to firmware + * + * Call register usage: + * a0 INTEL_SIP_SMC_RSU_NOTIFY + * a1 32bit value representing hard processor system execution stage + * a2-7 not used + * + * Return status + * a0 INTEL_SIP_SMC_STATUS_OK + */ +#define INTEL_SIP_SMC_FUNCID_RSU_NOTIFY 14 +#define INTEL_SIP_SMC_RSU_NOTIFY \ + INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_RSU_NOTIFY) + +/** + * Request INTEL_SIP_SMC_RSU_RETRY_COUNTER + * + * Sync call used by service driver at EL1 to query RSU retry counter + * + * Call register usage: + * a0 INTEL_SIP_SMC_RSU_RETRY_COUNTER + * a1-7 not used + * + * Return status + * a0 INTEL_SIP_SMC_STATUS_OK + * a1 the retry counter + * + * Or + * + * a0 INTEL_SIP_SMC_RSU_ERROR + */ +#define INTEL_SIP_SMC_FUNCID_RSU_RETRY_COUNTER 15 +#define INTEL_SIP_SMC_RSU_RETRY_COUNTER \ + INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_RSU_RETRY_COUNTER) diff --git a/include/linux/firmware/intel/stratix10-svc-client.h b/include/linux/firmware/intel/stratix10-svc-client.h index e521f172a47a..b6c4302a39e0 100644 --- a/include/linux/firmware/intel/stratix10-svc-client.h +++ b/include/linux/firmware/intel/stratix10-svc-client.h @@ -95,6 +95,13 @@ struct stratix10_svc_chan; * * @COMMAND_RSU_UPDATE: set the offset of the bitstream to boot after reboot, * return status is SVC_STATUS_RSU_OK or SVC_STATUS_RSU_ERROR + * + * @COMMAND_RSU_NOTIFY: report the status of hard processor system + * software to firmware, return status is SVC_STATUS_RSU_OK or + * SVC_STATUS_RSU_ERROR + * + * @COMMAND_RSU_RETRY: query firmware for the current image's retry counter, + * return status is SVC_STATUS_RSU_OK or SVC_STATUS_RSU_ERROR */ enum stratix10_svc_command_code { COMMAND_NOOP = 0, @@ -103,7 +110,9 @@ enum stratix10_svc_command_code { COMMAND_RECONFIG_DATA_CLAIM, COMMAND_RECONFIG_STATUS, COMMAND_RSU_STATUS, - COMMAND_RSU_UPDATE + COMMAND_RSU_UPDATE, + COMMAND_RSU_NOTIFY, + COMMAND_RSU_RETRY, }; /** diff --git a/include/linux/firmware/xlnx-zynqmp.h b/include/linux/firmware/xlnx-zynqmp.h index 1262ea6a1f4b..778abbbc7d94 100644 --- a/include/linux/firmware/xlnx-zynqmp.h +++ b/include/linux/firmware/xlnx-zynqmp.h @@ -46,7 +46,6 @@ #define ZYNQMP_PM_CAPABILITY_ACCESS 0x1U #define ZYNQMP_PM_CAPABILITY_CONTEXT 0x2U #define ZYNQMP_PM_CAPABILITY_WAKEUP 0x4U -#define ZYNQMP_PM_CAPABILITY_POWER 0x8U /* * Firmware FPGA Manager flags diff --git a/include/linux/flat.h b/include/linux/flat.h index 569b67d64d5c..83977c0ce3de 100644 --- a/include/linux/flat.h +++ b/include/linux/flat.h @@ -10,8 +10,41 @@ #ifndef _LINUX_FLAT_H #define _LINUX_FLAT_H -#include <uapi/linux/flat.h> -#include <asm/flat.h> +#define FLAT_VERSION 0x00000004L + +/* + * To make everything easier to port and manage cross platform + * development, all fields are in network byte order. + */ + +struct flat_hdr { + char magic[4]; + __be32 rev; /* version (as above) */ + __be32 entry; /* Offset of first executable instruction + with text segment from beginning of file */ + __be32 data_start; /* Offset of data segment from beginning of + file */ + __be32 data_end; /* Offset of end of data segment from beginning + of file */ + __be32 bss_end; /* Offset of end of bss segment from beginning + of file */ + + /* (It is assumed that data_end through bss_end forms the bss segment.) */ + + __be32 stack_size; /* Size of stack, in bytes */ + __be32 reloc_start; /* Offset of relocation records from beginning of + file */ + __be32 reloc_count; /* Number of relocation records */ + __be32 flags; + __be32 build_date; /* When the program/library was built */ + __u32 filler[5]; /* Reservered, set to zero */ +}; + +#define FLAT_FLAG_RAM 0x0001 /* load program entirely into RAM */ +#define FLAT_FLAG_GOTPIC 0x0002 /* program is PIC with GOT */ +#define FLAT_FLAG_GZIP 0x0004 /* all but the header is compressed */ +#define FLAT_FLAG_GZDATA 0x0008 /* only data/relocs are compressed (for XIP) */ +#define FLAT_FLAG_KTRACE 0x0010 /* output useful kernel trace for debugging */ /* * While it would be nice to keep this header clean, users of older @@ -22,28 +55,21 @@ * with the format above, except to fix bugs with old format support. */ -#include <asm/byteorder.h> - #define OLD_FLAT_VERSION 0x00000002L #define OLD_FLAT_RELOC_TYPE_TEXT 0 #define OLD_FLAT_RELOC_TYPE_DATA 1 #define OLD_FLAT_RELOC_TYPE_BSS 2 typedef union { - unsigned long value; + u32 value; struct { -# if defined(mc68000) && !defined(CONFIG_COLDFIRE) - signed long offset : 30; - unsigned long type : 2; -# define OLD_FLAT_FLAG_RAM 0x1 /* load program entirely into RAM */ +#if defined(__LITTLE_ENDIAN_BITFIELD) || \ + (defined(mc68000) && !defined(CONFIG_COLDFIRE)) + s32 offset : 30; + u32 type : 2; # elif defined(__BIG_ENDIAN_BITFIELD) - unsigned long type : 2; - signed long offset : 30; -# define OLD_FLAT_FLAG_RAM 0x1 /* load program entirely into RAM */ -# elif defined(__LITTLE_ENDIAN_BITFIELD) - signed long offset : 30; - unsigned long type : 2; -# define OLD_FLAT_FLAG_RAM 0x1 /* load program entirely into RAM */ + u32 type : 2; + s32 offset : 30; # else # error "Unknown bitfield order for flat files." # endif diff --git a/include/linux/fmc-sdb.h b/include/linux/fmc-sdb.h deleted file mode 100644 index bec899f0867c..000000000000 --- a/include/linux/fmc-sdb.h +++ /dev/null @@ -1,39 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * This file is separate from sdb.h, because I want that one to remain - * unchanged (as far as possible) from the official sdb distribution - * - * This file and associated functionality are a playground for me to - * understand stuff which will later be implemented in more generic places. - */ -#include <linux/sdb.h> - -/* This is the union of all currently defined types */ -union sdb_record { - struct sdb_interconnect ic; - struct sdb_device dev; - struct sdb_bridge bridge; - struct sdb_integration integr; - struct sdb_empty empty; - struct sdb_synthesis synthesis; - struct sdb_repo_url repo_url; -}; - -struct fmc_device; - -/* Every sdb table is turned into this structure */ -struct sdb_array { - int len; - int level; - unsigned long baseaddr; - struct fmc_device *fmc; /* the device that hosts it */ - struct sdb_array *parent; /* NULL at root */ - union sdb_record *record; /* copies of the struct */ - struct sdb_array **subtree; /* only valid for bridge items */ -}; - -extern int fmc_scan_sdb_tree(struct fmc_device *fmc, unsigned long address); -extern void fmc_show_sdb_tree(const struct fmc_device *fmc); -extern signed long fmc_find_sdb_device(struct sdb_array *tree, uint64_t vendor, - uint32_t device, unsigned long *sz); -extern int fmc_free_sdb_tree(struct fmc_device *fmc); diff --git a/include/linux/fmc.h b/include/linux/fmc.h deleted file mode 100644 index b355f3806f3f..000000000000 --- a/include/linux/fmc.h +++ /dev/null @@ -1,269 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* - * Copyright (C) 2012 CERN (www.cern.ch) - * Author: Alessandro Rubini <rubini@gnudd.com> - * - * This work is part of the White Rabbit project, a research effort led - * by CERN, the European Institute for Nuclear Research. - */ -#ifndef __LINUX_FMC_H__ -#define __LINUX_FMC_H__ -#include <linux/types.h> -#include <linux/moduleparam.h> -#include <linux/device.h> -#include <linux/list.h> -#include <linux/interrupt.h> -#include <linux/io.h> - -struct fmc_device; -struct fmc_driver; - -/* - * This bus abstraction is developed separately from drivers, so we need - * to check the version of the data structures we receive. - */ - -#define FMC_MAJOR 3 -#define FMC_MINOR 0 -#define FMC_VERSION ((FMC_MAJOR << 16) | FMC_MINOR) -#define __FMC_MAJOR(x) ((x) >> 16) -#define __FMC_MINOR(x) ((x) & 0xffff) - -/* - * The device identification, as defined by the IPMI FRU (Field Replaceable - * Unit) includes four different strings to describe the device. Here we - * only match the "Board Manufacturer" and the "Board Product Name", - * ignoring the "Board Serial Number" and "Board Part Number". All 4 are - * expected to be strings, so they are treated as zero-terminated C strings. - * Unspecified string (NULL) means "any", so if both are unspecified this - * is a catch-all driver. So null entries are allowed and we use array - * and length. This is unlike pci and usb that use null-terminated arrays - */ -struct fmc_fru_id { - char *manufacturer; - char *product_name; -}; - -/* - * If the FPGA is already programmed (think Etherbone or the second - * SVEC slot), we can match on SDB devices in the memory image. This - * match uses an array of devices that must all be present, and the - * match is based on vendor and device only. Further checks are expected - * to happen in the probe function. Zero means "any" and catch-all is allowed. - */ -struct fmc_sdb_one_id { - uint64_t vendor; - uint32_t device; -}; -struct fmc_sdb_id { - struct fmc_sdb_one_id *cores; - int cores_nr; -}; - -struct fmc_device_id { - struct fmc_fru_id *fru_id; - int fru_id_nr; - struct fmc_sdb_id *sdb_id; - int sdb_id_nr; -}; - -/* This sizes the module_param_array used by generic module parameters */ -#define FMC_MAX_CARDS 32 - -/* The driver is a pretty simple thing */ -struct fmc_driver { - unsigned long version; - struct device_driver driver; - int (*probe)(struct fmc_device *); - int (*remove)(struct fmc_device *); - const struct fmc_device_id id_table; - /* What follows is for generic module parameters */ - int busid_n; - int busid_val[FMC_MAX_CARDS]; - int gw_n; - char *gw_val[FMC_MAX_CARDS]; -}; -#define to_fmc_driver(x) container_of((x), struct fmc_driver, driver) - -/* These are the generic parameters, that drivers may instantiate */ -#define FMC_PARAM_BUSID(_d) \ - module_param_array_named(busid, _d.busid_val, int, &_d.busid_n, 0444) -#define FMC_PARAM_GATEWARE(_d) \ - module_param_array_named(gateware, _d.gw_val, charp, &_d.gw_n, 0444) - -/* - * Drivers may need to configure gpio pins in the carrier. To read input - * (a very uncommon operation, and definitely not in the hot paths), just - * configure one gpio only and get 0 or 1 as retval of the config method - */ -struct fmc_gpio { - char *carrier_name; /* name or NULL for virtual pins */ - int gpio; - int _gpio; /* internal use by the carrier */ - int mode; /* GPIOF_DIR_OUT etc, from <linux/gpio.h> */ - int irqmode; /* IRQF_TRIGGER_LOW and so on */ -}; - -/* The numbering of gpio pins allows access to raw pins or virtual roles */ -#define FMC_GPIO_RAW(x) (x) /* 4096 of them */ -#define __FMC_GPIO_IS_RAW(x) ((x) < 0x1000) -#define FMC_GPIO_IRQ(x) ((x) + 0x1000) /* 256 of them */ -#define FMC_GPIO_LED(x) ((x) + 0x1100) /* 256 of them */ -#define FMC_GPIO_KEY(x) ((x) + 0x1200) /* 256 of them */ -#define FMC_GPIO_TP(x) ((x) + 0x1300) /* 256 of them */ -#define FMC_GPIO_USER(x) ((x) + 0x1400) /* 256 of them */ -/* We may add SCL and SDA, or other roles if the need arises */ - -/* GPIOF_DIR_IN etc are missing before 3.0. copy from <linux/gpio.h> */ -#ifndef GPIOF_DIR_IN -# define GPIOF_DIR_OUT (0 << 0) -# define GPIOF_DIR_IN (1 << 0) -# define GPIOF_INIT_LOW (0 << 1) -# define GPIOF_INIT_HIGH (1 << 1) -#endif - -/* - * The operations are offered by each carrier and should make driver - * design completely independent of the carrier. Named GPIO pins may be - * the exception. - */ -struct fmc_operations { - uint32_t (*read32)(struct fmc_device *fmc, int offset); - void (*write32)(struct fmc_device *fmc, uint32_t value, int offset); - int (*validate)(struct fmc_device *fmc, struct fmc_driver *drv); - int (*reprogram_raw)(struct fmc_device *f, struct fmc_driver *d, - void *gw, unsigned long len); - int (*reprogram)(struct fmc_device *f, struct fmc_driver *d, char *gw); - int (*irq_request)(struct fmc_device *fmc, irq_handler_t h, - char *name, int flags); - void (*irq_ack)(struct fmc_device *fmc); - int (*irq_free)(struct fmc_device *fmc); - int (*gpio_config)(struct fmc_device *fmc, struct fmc_gpio *gpio, - int ngpio); - int (*read_ee)(struct fmc_device *fmc, int pos, void *d, int l); - int (*write_ee)(struct fmc_device *fmc, int pos, const void *d, int l); -}; - -/* Prefer this helper rather than calling of fmc->reprogram directly */ -int fmc_reprogram_raw(struct fmc_device *fmc, struct fmc_driver *d, - void *gw, unsigned long len, int sdb_entry); -extern int fmc_reprogram(struct fmc_device *f, struct fmc_driver *d, char *gw, - int sdb_entry); - -/* - * The device reports all information needed to access hw. - * - * If we have eeprom_len and not contents, the core reads it. - * Then, parsing of identifiers is done by the core which fills fmc_fru_id.. - * Similarly a device that must be matched based on SDB cores must - * fill the entry point and the core will scan the bus (FIXME: sdb match) - */ -struct fmc_device { - unsigned long version; - unsigned long flags; - struct module *owner; /* char device must pin it */ - struct fmc_fru_id id; /* for EEPROM-based match */ - struct fmc_operations *op; /* carrier-provided */ - int irq; /* according to host bus. 0 == none */ - int eeprom_len; /* Usually 8kB, may be less */ - int eeprom_addr; /* 0x50, 0x52 etc */ - uint8_t *eeprom; /* Full contents or leading part */ - char *carrier_name; /* "SPEC" or similar, for special use */ - void *carrier_data; /* "struct spec *" or equivalent */ - __iomem void *fpga_base; /* May be NULL (Etherbone) */ - __iomem void *slot_base; /* Set by the driver */ - struct fmc_device **devarray; /* Allocated by the bus */ - int slot_id; /* Index in the slot array */ - int nr_slots; /* Number of slots in this carrier */ - unsigned long memlen; /* Used for the char device */ - struct device dev; /* For Linux use */ - struct device *hwdev; /* The underlying hardware device */ - unsigned long sdbfs_entry; - struct sdb_array *sdb; - uint32_t device_id; /* Filled by the device */ - char *mezzanine_name; /* Defaults to ``fmc'' */ - void *mezzanine_data; - - struct dentry *dbg_dir; - struct dentry *dbg_sdb_dump; -}; -#define to_fmc_device(x) container_of((x), struct fmc_device, dev) - -#define FMC_DEVICE_HAS_GOLDEN 1 -#define FMC_DEVICE_HAS_CUSTOM 2 -#define FMC_DEVICE_NO_MEZZANINE 4 -#define FMC_DEVICE_MATCH_SDB 8 /* fmc-core must scan sdb in fpga */ - -/* - * If fpga_base can be used, the carrier offers no readl/writel methods, and - * this expands to a single, fast, I/O access. - */ -static inline uint32_t fmc_readl(struct fmc_device *fmc, int offset) -{ - if (unlikely(fmc->op->read32)) - return fmc->op->read32(fmc, offset); - return readl(fmc->fpga_base + offset); -} -static inline void fmc_writel(struct fmc_device *fmc, uint32_t val, int off) -{ - if (unlikely(fmc->op->write32)) - fmc->op->write32(fmc, val, off); - else - writel(val, fmc->fpga_base + off); -} - -/* pci-like naming */ -static inline void *fmc_get_drvdata(const struct fmc_device *fmc) -{ - return dev_get_drvdata(&fmc->dev); -} - -static inline void fmc_set_drvdata(struct fmc_device *fmc, void *data) -{ - dev_set_drvdata(&fmc->dev, data); -} - -struct fmc_gateware { - void *bitstream; - unsigned long len; -}; - -/* The 5 access points */ -extern int fmc_driver_register(struct fmc_driver *drv); -extern void fmc_driver_unregister(struct fmc_driver *drv); -extern int fmc_device_register(struct fmc_device *tdev); -extern int fmc_device_register_gw(struct fmc_device *tdev, - struct fmc_gateware *gw); -extern void fmc_device_unregister(struct fmc_device *tdev); - -/* Three more for device sets, all driven by the same FPGA */ -extern int fmc_device_register_n(struct fmc_device **devs, int n); -extern int fmc_device_register_n_gw(struct fmc_device **devs, int n, - struct fmc_gateware *gw); -extern void fmc_device_unregister_n(struct fmc_device **devs, int n); - -/* Internal cross-calls between files; not exported to other modules */ -extern int fmc_match(struct device *dev, struct device_driver *drv); -extern int fmc_fill_id_info(struct fmc_device *fmc); -extern void fmc_free_id_info(struct fmc_device *fmc); -extern void fmc_dump_eeprom(const struct fmc_device *fmc); - -/* helpers for FMC operations */ -extern int fmc_irq_request(struct fmc_device *fmc, irq_handler_t h, - char *name, int flags); -extern void fmc_irq_free(struct fmc_device *fmc); -extern void fmc_irq_ack(struct fmc_device *fmc); -extern int fmc_validate(struct fmc_device *fmc, struct fmc_driver *drv); -extern int fmc_gpio_config(struct fmc_device *fmc, struct fmc_gpio *gpio, - int ngpio); -extern int fmc_read_ee(struct fmc_device *fmc, int pos, void *d, int l); -extern int fmc_write_ee(struct fmc_device *fmc, int pos, const void *d, int l); - -/* helpers for FMC operations */ -extern int fmc_irq_request(struct fmc_device *fmc, irq_handler_t h, - char *name, int flags); -extern void fmc_irq_free(struct fmc_device *fmc); -extern void fmc_irq_ack(struct fmc_device *fmc); -extern int fmc_validate(struct fmc_device *fmc, struct fmc_driver *drv); - -#endif /* __LINUX_FMC_H__ */ diff --git a/include/linux/fpga/adi-axi-common.h b/include/linux/fpga/adi-axi-common.h new file mode 100644 index 000000000000..7fc95d5c95bb --- /dev/null +++ b/include/linux/fpga/adi-axi-common.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Analog Devices AXI common registers & definitions + * + * Copyright 2019 Analog Devices Inc. + * + * https://wiki.analog.com/resources/fpga/docs/axi_ip + * https://wiki.analog.com/resources/fpga/docs/hdl/regmap + */ + +#ifndef ADI_AXI_COMMON_H_ +#define ADI_AXI_COMMON_H_ + +#define ADI_AXI_REG_VERSION 0x0000 + +#define ADI_AXI_PCORE_VER(major, minor, patch) \ + (((major) << 16) | ((minor) << 8) | (patch)) + +#endif /* ADI_AXI_COMMON_H_ */ diff --git a/include/linux/fpga/altera-pr-ip-core.h b/include/linux/fpga/altera-pr-ip-core.h index 7d4664730d60..0b08ac20ab16 100644 --- a/include/linux/fpga/altera-pr-ip-core.h +++ b/include/linux/fpga/altera-pr-ip-core.h @@ -13,6 +13,6 @@ #include <linux/io.h> int alt_pr_register(struct device *dev, void __iomem *reg_base); -int alt_pr_unregister(struct device *dev); +void alt_pr_unregister(struct device *dev); #endif /* _ALT_PR_IP_CORE_H */ diff --git a/include/linux/fs.h b/include/linux/fs.h index f7fdfe93e25d..e0d909d35763 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -64,6 +64,8 @@ struct workqueue_struct; struct iov_iter; struct fscrypt_info; struct fscrypt_operations; +struct fsverity_info; +struct fsverity_operations; struct fs_context; struct fs_parameter_description; @@ -427,6 +429,7 @@ int pagecache_write_end(struct file *, struct address_space *mapping, * @i_pages: Cached pages. * @gfp_mask: Memory allocation flags to use for allocating pages. * @i_mmap_writable: Number of VM_SHARED mappings. + * @nr_thps: Number of THPs in the pagecache (non-shmem only). * @i_mmap: Tree of private and shared mappings. * @i_mmap_rwsem: Protects @i_mmap and @i_mmap_writable. * @nrpages: Number of page entries, protected by the i_pages lock. @@ -444,6 +447,10 @@ struct address_space { struct xarray i_pages; gfp_t gfp_mask; atomic_t i_mmap_writable; +#ifdef CONFIG_READ_ONLY_THP_FOR_FS + /* number of thp, only for non-shmem files */ + atomic_t nr_thps; +#endif struct rb_root_cached i_mmap; struct rw_semaphore i_mmap_rwsem; unsigned long nrpages; @@ -694,7 +701,7 @@ struct inode { atomic_t i_count; atomic_t i_dio_count; atomic_t i_writecount; -#ifdef CONFIG_IMA +#if defined(CONFIG_IMA) || defined(CONFIG_FILE_LOCKING) atomic_t i_readcount; /* struct files open RO */ #endif union { @@ -723,9 +730,15 @@ struct inode { struct fscrypt_info *i_crypt_info; #endif +#ifdef CONFIG_FS_VERITY + struct fsverity_info *i_verity_info; +#endif + void *i_private; /* fs or device private pointer */ } __randomize_layout; +struct timespec64 timestamp_truncate(struct timespec64 t, struct inode *inode); + static inline unsigned int i_blocksize(const struct inode *node) { return (1 << node->i_blkbits); @@ -1019,8 +1032,6 @@ struct file_lock_operations { }; struct lock_manager_operations { - int (*lm_compare_owner)(struct file_lock *, struct file_lock *); - unsigned long (*lm_owner_key)(struct file_lock *); fl_owner_t (*lm_get_owner)(fl_owner_t); void (*lm_put_owner)(fl_owner_t); void (*lm_notify)(struct file_lock *); /* unblock callback */ @@ -1157,6 +1168,11 @@ extern void lease_get_mtime(struct inode *, struct timespec64 *time); extern int generic_setlease(struct file *, long, struct file_lock **, void **priv); extern int vfs_setlease(struct file *, long, struct file_lock **, void **); extern int lease_modify(struct file_lock *, int, struct list_head *); + +struct notifier_block; +extern int lease_register_notifier(struct notifier_block *); +extern void lease_unregister_notifier(struct notifier_block *); + struct files_struct; extern void show_fd_locks(struct seq_file *f, struct file *filp, struct files_struct *files); @@ -1429,6 +1445,10 @@ struct super_block { const struct xattr_handler **s_xattr; #ifdef CONFIG_FS_ENCRYPTION const struct fscrypt_operations *s_cop; + struct key *s_master_keys; /* master crypto keys in use */ +#endif +#ifdef CONFIG_FS_VERITY + const struct fsverity_operations *s_vop; #endif struct hlist_bl_head s_roots; /* alternate root dentries for NFS */ struct list_head s_mounts; /* list of mounts; _not_ for fs use */ @@ -1450,6 +1470,9 @@ struct super_block { /* Granularity of c/m/atime in ns (cannot be worse than a second) */ u32 s_time_gran; + /* Time limits for c/m/atime in seconds */ + time64_t s_time_min; + time64_t s_time_max; #ifdef CONFIG_FSNOTIFY __u32 s_fsnotify_mask; struct fsnotify_mark_connector __rcu *s_fsnotify_marks; @@ -1769,7 +1792,7 @@ struct block_device_operations; /* * These flags control the behavior of the remap_file_range function pointer. * If it is called with len == 0 that means "remap to end of source file". - * See Documentation/filesystems/vfs.txt for more details about this call. + * See Documentation/filesystems/vfs.rst for more details about this call. * * REMAP_FILE_DEDUP: only remap if contents identical (i.e. deduplicate) * REMAP_FILE_CAN_SHORTEN: caller can handle a shortened request @@ -1889,6 +1912,9 @@ extern ssize_t vfs_readv(struct file *, const struct iovec __user *, unsigned long, loff_t *, rwf_t); extern ssize_t vfs_copy_file_range(struct file *, loff_t , struct file *, loff_t, size_t, unsigned int); +extern ssize_t generic_copy_file_range(struct file *file_in, loff_t pos_in, + struct file *file_out, loff_t pos_out, + size_t len, unsigned int flags); extern int generic_remap_file_range_prep(struct file *file_in, loff_t pos_in, struct file *file_out, loff_t pos_out, loff_t *count, @@ -1964,6 +1990,7 @@ struct super_operations { #endif #define S_ENCRYPTED 16384 /* Encrypted file (using fs/crypto/) */ #define S_CASEFOLD 32768 /* Casefolded file */ +#define S_VERITY 65536 /* Verity file (using fs/verity/) */ /* * Note that nosuid etc flags are inode-specific: setting some file-system @@ -2005,6 +2032,7 @@ static inline bool sb_rdonly(const struct super_block *sb) { return sb->s_flags #define IS_DAX(inode) ((inode)->i_flags & S_DAX) #define IS_ENCRYPTED(inode) ((inode)->i_flags & S_ENCRYPTED) #define IS_CASEFOLDED(inode) ((inode)->i_flags & S_CASEFOLD) +#define IS_VERITY(inode) ((inode)->i_flags & S_VERITY) #define IS_WHITEOUT(inode) (S_ISCHR(inode->i_mode) && \ (inode)->i_rdev == WHITEOUT_DEV) @@ -2174,6 +2202,8 @@ static inline void file_accessed(struct file *file) touch_atime(&file->f_path); } +extern int file_modified(struct file *file); + int sync_inode(struct inode *inode, struct writeback_control *wbc); int sync_inode_metadata(struct inode *inode, int wait); @@ -2184,6 +2214,7 @@ struct file_system_type { #define FS_BINARY_MOUNTDATA 2 #define FS_HAS_SUBTYPE 4 #define FS_USERNS_MOUNT 8 /* Can be mounted by userns root */ +#define FS_DISALLOW_NOTIFY_PERM 16 /* Disable fanotify permission events */ #define FS_RENAME_DOES_D_MOVE 32768 /* FS will handle d_move() during rename() internally. */ int (*init_fs_context)(struct fs_context *); const struct fs_parameter_description *parameters; @@ -2206,9 +2237,6 @@ struct file_system_type { #define MODULE_ALIAS_FS(NAME) MODULE_ALIAS("fs-" NAME) -extern struct dentry *mount_ns(struct file_system_type *fs_type, - int flags, void *data, void *ns, struct user_namespace *user_ns, - int (*fill_super)(struct super_block *, void *, int)); #ifdef CONFIG_BLOCK extern struct dentry *mount_bdev(struct file_system_type *fs_type, int flags, const char *dev_name, void *data, @@ -2248,28 +2276,10 @@ void free_anon_bdev(dev_t); struct super_block *sget_fc(struct fs_context *fc, int (*test)(struct super_block *, struct fs_context *), int (*set)(struct super_block *, struct fs_context *)); -struct super_block *sget_userns(struct file_system_type *type, - int (*test)(struct super_block *,void *), - int (*set)(struct super_block *,void *), - int flags, struct user_namespace *user_ns, - void *data); struct super_block *sget(struct file_system_type *type, int (*test)(struct super_block *,void *), int (*set)(struct super_block *,void *), int flags, void *data); -extern struct dentry *mount_pseudo_xattr(struct file_system_type *, char *, - const struct super_operations *ops, - const struct xattr_handler **xattr, - const struct dentry_operations *dops, - unsigned long); - -static inline struct dentry * -mount_pseudo(struct file_system_type *fs_type, char *name, - const struct super_operations *ops, - const struct dentry_operations *dops, unsigned long magic) -{ - return mount_pseudo_xattr(fs_type, name, ops, NULL, dops, magic); -} /* Alas, no aliases. Too much hassle with bringing module.h everywhere */ #define fops_get(fops) \ @@ -2615,6 +2625,12 @@ extern struct block_device *blkdev_get_by_path(const char *path, fmode_t mode, void *holder); extern struct block_device *blkdev_get_by_dev(dev_t dev, fmode_t mode, void *holder); +extern struct block_device *bd_start_claiming(struct block_device *bdev, + void *holder); +extern void bd_finish_claiming(struct block_device *bdev, + struct block_device *whole, void *holder); +extern void bd_abort_claiming(struct block_device *bdev, + struct block_device *whole, void *holder); extern void blkdev_put(struct block_device *bdev, fmode_t mode); extern int __blkdev_reread_part(struct block_device *bdev); extern int blkdev_reread_part(struct block_device *bdev); @@ -2712,6 +2728,8 @@ extern int filemap_flush(struct address_space *); extern int filemap_fdatawait_keep_errors(struct address_space *mapping); extern int filemap_fdatawait_range(struct address_space *, loff_t lstart, loff_t lend); +extern int filemap_fdatawait_range_keep_errors(struct address_space *mapping, + loff_t start_byte, loff_t end_byte); static inline int filemap_fdatawait(struct address_space *mapping) { @@ -2790,6 +2808,33 @@ static inline errseq_t filemap_sample_wb_err(struct address_space *mapping) return errseq_sample(&mapping->wb_err); } +static inline int filemap_nr_thps(struct address_space *mapping) +{ +#ifdef CONFIG_READ_ONLY_THP_FOR_FS + return atomic_read(&mapping->nr_thps); +#else + return 0; +#endif +} + +static inline void filemap_nr_thps_inc(struct address_space *mapping) +{ +#ifdef CONFIG_READ_ONLY_THP_FOR_FS + atomic_inc(&mapping->nr_thps); +#else + WARN_ON_ONCE(1); +#endif +} + +static inline void filemap_nr_thps_dec(struct address_space *mapping) +{ +#ifdef CONFIG_READ_ONLY_THP_FOR_FS + atomic_dec(&mapping->nr_thps); +#else + WARN_ON_ONCE(1); +#endif +} + extern int vfs_fsync_range(struct file *file, loff_t start, loff_t end, int datasync); extern int vfs_fsync(struct file *file, int datasync); @@ -2890,7 +2935,7 @@ static inline bool inode_is_open_for_write(const struct inode *inode) return atomic_read(&inode->i_writecount) > 0; } -#ifdef CONFIG_IMA +#if defined(CONFIG_IMA) || defined(CONFIG_FILE_LOCKING) static inline void i_readcount_dec(struct inode *inode) { BUG_ON(!atomic_read(&inode->i_readcount)); @@ -3046,6 +3091,10 @@ extern ssize_t generic_write_checks(struct kiocb *, struct iov_iter *); extern int generic_remap_checks(struct file *file_in, loff_t pos_in, struct file *file_out, loff_t pos_out, loff_t *count, unsigned int remap_flags); +extern int generic_file_rw_checks(struct file *file_in, struct file *file_out); +extern int generic_copy_file_checks(struct file *file_in, loff_t pos_in, + struct file *file_out, loff_t pos_out, + size_t *count, unsigned int flags); extern ssize_t generic_file_read_iter(struct kiocb *, struct iov_iter *); extern ssize_t __generic_file_write_iter(struct kiocb *, struct iov_iter *); extern ssize_t generic_file_write_iter(struct kiocb *, struct iov_iter *); @@ -3536,6 +3585,8 @@ extern void inode_nohighmem(struct inode *inode); /* mm/fadvise.c */ extern int vfs_fadvise(struct file *file, loff_t offset, loff_t len, int advice); +extern int generic_fadvise(struct file *file, loff_t offset, loff_t len, + int advice); #if defined(CONFIG_IO_URING) extern struct sock *io_uring_get_socket(struct file *file); @@ -3546,4 +3597,27 @@ static inline struct sock *io_uring_get_socket(struct file *file) } #endif +int vfs_ioc_setflags_prepare(struct inode *inode, unsigned int oldflags, + unsigned int flags); + +int vfs_ioc_fssetxattr_check(struct inode *inode, const struct fsxattr *old_fa, + struct fsxattr *fa); + +static inline void simple_fill_fsxattr(struct fsxattr *fa, __u32 xflags) +{ + memset(fa, 0, sizeof(*fa)); + fa->fsx_xflags = xflags; +} + +/* + * Flush file data before changing attributes. Caller must hold any locks + * required to prevent further writes to this file until we're done setting + * flags. + */ +static inline int inode_drain_writes(struct inode *inode) +{ + inode_dio_wait(inode); + return filemap_write_and_wait(inode->i_mapping); +} + #endif /* _LINUX_FS_H */ diff --git a/include/linux/fs_context.h b/include/linux/fs_context.h index d476ff0c10df..e5c14e2c53d3 100644 --- a/include/linux/fs_context.h +++ b/include/linux/fs_context.h @@ -81,24 +81,25 @@ struct fs_parameter { * Superblock creation fills in ->root whereas reconfiguration begins with this * already set. * - * See Documentation/filesystems/mounting.txt + * See Documentation/filesystems/mount_api.txt */ struct fs_context { const struct fs_context_operations *ops; struct mutex uapi_mutex; /* Userspace access mutex */ struct file_system_type *fs_type; void *fs_private; /* The filesystem's context */ + void *sget_key; struct dentry *root; /* The root and superblock */ struct user_namespace *user_ns; /* The user namespace for this mount */ struct net *net_ns; /* The network namespace for this mount */ const struct cred *cred; /* The mounter's credentials */ struct fc_log *log; /* Logging buffer */ const char *source; /* The source name (eg. dev path) */ - const char *subtype; /* The subtype to set on the superblock */ void *security; /* Linux S&M options */ void *s_fs_info; /* Proposed s_fs_info */ unsigned int sb_flags; /* Proposed superblock flags (SB_*) */ unsigned int sb_flags_mask; /* Superblock flags that were changed */ + unsigned int s_iflags; /* OR'd with sb->s_iflags */ unsigned int lsm_flags; /* Information flags from the fs to the LSM */ enum fs_context_purpose purpose:8; enum fs_context_phase phase:8; /* The phase the context is in */ @@ -135,10 +136,11 @@ extern int vfs_get_tree(struct fs_context *fc); extern void put_fs_context(struct fs_context *fc); /* - * sget() wrapper to be called from the ->get_tree() op. + * sget() wrappers to be called from the ->get_tree() op. */ enum vfs_get_super_keying { vfs_get_single_super, /* Only one such superblock may exist */ + vfs_get_single_reconf_super, /* As above, but reconfigure if it exists */ vfs_get_keyed_super, /* Superblocks with different s_fs_info keys may exist */ vfs_get_independent_super, /* Multiple independent superblocks may exist */ }; @@ -147,6 +149,24 @@ extern int vfs_get_super(struct fs_context *fc, int (*fill_super)(struct super_block *sb, struct fs_context *fc)); +extern int get_tree_nodev(struct fs_context *fc, + int (*fill_super)(struct super_block *sb, + struct fs_context *fc)); +extern int get_tree_single(struct fs_context *fc, + int (*fill_super)(struct super_block *sb, + struct fs_context *fc)); +extern int get_tree_single_reconf(struct fs_context *fc, + int (*fill_super)(struct super_block *sb, + struct fs_context *fc)); +extern int get_tree_keyed(struct fs_context *fc, + int (*fill_super)(struct super_block *sb, + struct fs_context *fc), + void *key); + +extern int get_tree_bdev(struct fs_context *fc, + int (*fill_super)(struct super_block *sb, + struct fs_context *fc)); + extern const struct file_operations fscontext_fops; /* diff --git a/include/linux/fs_pin.h b/include/linux/fs_pin.h index 7cab74d66f85..bdd09fd2520c 100644 --- a/include/linux/fs_pin.h +++ b/include/linux/fs_pin.h @@ -20,6 +20,5 @@ static inline void init_fs_pin(struct fs_pin *p, void (*kill)(struct fs_pin *)) } void pin_remove(struct fs_pin *); -void pin_insert_group(struct fs_pin *, struct vfsmount *, struct hlist_head *); void pin_insert(struct fs_pin *, struct vfsmount *); void pin_kill(struct fs_pin *); diff --git a/include/linux/fscrypt.h b/include/linux/fscrypt.h index f7680ef1abd2..f622f7460ed8 100644 --- a/include/linux/fscrypt.h +++ b/include/linux/fscrypt.h @@ -16,6 +16,7 @@ #include <linux/fs.h> #include <linux/mm.h> #include <linux/slab.h> +#include <uapi/linux/fscrypt.h> #define FS_CRYPTO_BLOCK_SIZE 16 @@ -42,7 +43,7 @@ struct fscrypt_name { #define fname_len(p) ((p)->disk_name.len) /* Maximum value for the third parameter of fscrypt_operations.set_context(). */ -#define FSCRYPT_SET_CONTEXT_MAX_SIZE 28 +#define FSCRYPT_SET_CONTEXT_MAX_SIZE 40 #ifdef CONFIG_FS_ENCRYPTION /* @@ -63,16 +64,13 @@ struct fscrypt_operations { unsigned int max_namelen; }; +/* Decryption work */ struct fscrypt_ctx { union { struct { - struct page *bounce_page; /* Ciphertext page */ - struct page *control_page; /* Original page */ - } w; - struct { struct bio *bio; struct work_struct work; - } r; + }; struct list_head free_list; /* Free list */ }; u8 flags; /* Flags */ @@ -106,29 +104,54 @@ static inline void fscrypt_handle_d_move(struct dentry *dentry) extern void fscrypt_enqueue_decrypt_work(struct work_struct *); extern struct fscrypt_ctx *fscrypt_get_ctx(gfp_t); extern void fscrypt_release_ctx(struct fscrypt_ctx *); -extern struct page *fscrypt_encrypt_page(const struct inode *, struct page *, - unsigned int, unsigned int, - u64, gfp_t); -extern int fscrypt_decrypt_page(const struct inode *, struct page *, unsigned int, - unsigned int, u64); -static inline struct page *fscrypt_control_page(struct page *page) +extern struct page *fscrypt_encrypt_pagecache_blocks(struct page *page, + unsigned int len, + unsigned int offs, + gfp_t gfp_flags); +extern int fscrypt_encrypt_block_inplace(const struct inode *inode, + struct page *page, unsigned int len, + unsigned int offs, u64 lblk_num, + gfp_t gfp_flags); + +extern int fscrypt_decrypt_pagecache_blocks(struct page *page, unsigned int len, + unsigned int offs); +extern int fscrypt_decrypt_block_inplace(const struct inode *inode, + struct page *page, unsigned int len, + unsigned int offs, u64 lblk_num); + +static inline bool fscrypt_is_bounce_page(struct page *page) +{ + return page->mapping == NULL; +} + +static inline struct page *fscrypt_pagecache_page(struct page *bounce_page) { - return ((struct fscrypt_ctx *)page_private(page))->w.control_page; + return (struct page *)page_private(bounce_page); } -extern void fscrypt_restore_control_page(struct page *); +extern void fscrypt_free_bounce_page(struct page *bounce_page); /* policy.c */ extern int fscrypt_ioctl_set_policy(struct file *, const void __user *); extern int fscrypt_ioctl_get_policy(struct file *, void __user *); +extern int fscrypt_ioctl_get_policy_ex(struct file *, void __user *); extern int fscrypt_has_permitted_context(struct inode *, struct inode *); extern int fscrypt_inherit_context(struct inode *, struct inode *, void *, bool); -/* keyinfo.c */ +/* keyring.c */ +extern void fscrypt_sb_free(struct super_block *sb); +extern int fscrypt_ioctl_add_key(struct file *filp, void __user *arg); +extern int fscrypt_ioctl_remove_key(struct file *filp, void __user *arg); +extern int fscrypt_ioctl_remove_key_all_users(struct file *filp, + void __user *arg); +extern int fscrypt_ioctl_get_key_status(struct file *filp, void __user *arg); + +/* keysetup.c */ extern int fscrypt_get_encryption_info(struct inode *); extern void fscrypt_put_encryption_info(struct inode *); extern void fscrypt_free_inode(struct inode *); +extern int fscrypt_drop_inode(struct inode *inode); /* fname.c */ extern int fscrypt_setup_filename(struct inode *, const struct qstr *, @@ -223,7 +246,6 @@ static inline bool fscrypt_match_name(const struct fscrypt_name *fname, extern void fscrypt_decrypt_bio(struct bio *); extern void fscrypt_enqueue_decrypt_bio(struct fscrypt_ctx *ctx, struct bio *bio); -extern void fscrypt_pullback_bio_page(struct page **, bool); extern int fscrypt_zeroout_range(const struct inode *, pgoff_t, sector_t, unsigned int); @@ -283,32 +305,51 @@ static inline void fscrypt_release_ctx(struct fscrypt_ctx *ctx) return; } -static inline struct page *fscrypt_encrypt_page(const struct inode *inode, +static inline struct page *fscrypt_encrypt_pagecache_blocks(struct page *page, + unsigned int len, + unsigned int offs, + gfp_t gfp_flags) +{ + return ERR_PTR(-EOPNOTSUPP); +} + +static inline int fscrypt_encrypt_block_inplace(const struct inode *inode, struct page *page, unsigned int len, - unsigned int offs, - u64 lblk_num, gfp_t gfp_flags) + unsigned int offs, u64 lblk_num, + gfp_t gfp_flags) { - return ERR_PTR(-EOPNOTSUPP); + return -EOPNOTSUPP; +} + +static inline int fscrypt_decrypt_pagecache_blocks(struct page *page, + unsigned int len, + unsigned int offs) +{ + return -EOPNOTSUPP; } -static inline int fscrypt_decrypt_page(const struct inode *inode, - struct page *page, - unsigned int len, unsigned int offs, - u64 lblk_num) +static inline int fscrypt_decrypt_block_inplace(const struct inode *inode, + struct page *page, + unsigned int len, + unsigned int offs, u64 lblk_num) { return -EOPNOTSUPP; } -static inline struct page *fscrypt_control_page(struct page *page) +static inline bool fscrypt_is_bounce_page(struct page *page) +{ + return false; +} + +static inline struct page *fscrypt_pagecache_page(struct page *bounce_page) { WARN_ON_ONCE(1); return ERR_PTR(-EINVAL); } -static inline void fscrypt_restore_control_page(struct page *page) +static inline void fscrypt_free_bounce_page(struct page *bounce_page) { - return; } /* policy.c */ @@ -323,6 +364,12 @@ static inline int fscrypt_ioctl_get_policy(struct file *filp, void __user *arg) return -EOPNOTSUPP; } +static inline int fscrypt_ioctl_get_policy_ex(struct file *filp, + void __user *arg) +{ + return -EOPNOTSUPP; +} + static inline int fscrypt_has_permitted_context(struct inode *parent, struct inode *child) { @@ -336,7 +383,34 @@ static inline int fscrypt_inherit_context(struct inode *parent, return -EOPNOTSUPP; } -/* keyinfo.c */ +/* keyring.c */ +static inline void fscrypt_sb_free(struct super_block *sb) +{ +} + +static inline int fscrypt_ioctl_add_key(struct file *filp, void __user *arg) +{ + return -EOPNOTSUPP; +} + +static inline int fscrypt_ioctl_remove_key(struct file *filp, void __user *arg) +{ + return -EOPNOTSUPP; +} + +static inline int fscrypt_ioctl_remove_key_all_users(struct file *filp, + void __user *arg) +{ + return -EOPNOTSUPP; +} + +static inline int fscrypt_ioctl_get_key_status(struct file *filp, + void __user *arg) +{ + return -EOPNOTSUPP; +} + +/* keysetup.c */ static inline int fscrypt_get_encryption_info(struct inode *inode) { return -EOPNOTSUPP; @@ -351,6 +425,11 @@ static inline void fscrypt_free_inode(struct inode *inode) { } +static inline int fscrypt_drop_inode(struct inode *inode) +{ + return 0; +} + /* fname.c */ static inline int fscrypt_setup_filename(struct inode *dir, const struct qstr *iname, @@ -410,11 +489,6 @@ static inline void fscrypt_enqueue_decrypt_bio(struct fscrypt_ctx *ctx, { } -static inline void fscrypt_pullback_bio_page(struct page **page, bool restore) -{ - return; -} - static inline int fscrypt_zeroout_range(const struct inode *inode, pgoff_t lblk, sector_t pblk, unsigned int len) { @@ -692,4 +766,15 @@ static inline int fscrypt_encrypt_symlink(struct inode *inode, return 0; } +/* If *pagep is a bounce page, free it and set *pagep to the pagecache page */ +static inline void fscrypt_finalize_bounce_page(struct page **pagep) +{ + struct page *page = *pagep; + + if (fscrypt_is_bounce_page(page)) { + *pagep = fscrypt_pagecache_page(page); + fscrypt_free_bounce_page(page); + } +} + #endif /* _LINUX_FSCRYPT_H */ diff --git a/include/linux/fsl_devices.h b/include/linux/fsl_devices.h index cb2b46f57af3..5d231ce8709b 100644 --- a/include/linux/fsl_devices.h +++ b/include/linux/fsl_devices.h @@ -98,6 +98,7 @@ struct fsl_usb2_platform_data { unsigned has_fsl_erratum_14:1; unsigned has_fsl_erratum_a005275:1; unsigned has_fsl_erratum_a005697:1; + unsigned has_fsl_erratum_a006918:1; unsigned check_phy_clk_valid:1; /* register save area for suspend/resume */ diff --git a/include/linux/fsnotify.h b/include/linux/fsnotify.h index 94972e8eb6d1..a2d5d175d3c1 100644 --- a/include/linux/fsnotify.h +++ b/include/linux/fsnotify.h @@ -189,6 +189,19 @@ static inline void fsnotify_link(struct inode *dir, struct inode *inode, struct } /* + * fsnotify_unlink - 'name' was unlinked + * + * Caller must make sure that dentry->d_name is stable. + */ +static inline void fsnotify_unlink(struct inode *dir, struct dentry *dentry) +{ + /* Expected to be called before d_delete() */ + WARN_ON_ONCE(d_is_negative(dentry)); + + fsnotify_dirent(dir, dentry, FS_DELETE); +} + +/* * fsnotify_mkdir - directory 'name' was created */ static inline void fsnotify_mkdir(struct inode *inode, struct dentry *dentry) @@ -199,6 +212,19 @@ static inline void fsnotify_mkdir(struct inode *inode, struct dentry *dentry) } /* + * fsnotify_rmdir - directory 'name' was removed + * + * Caller must make sure that dentry->d_name is stable. + */ +static inline void fsnotify_rmdir(struct inode *dir, struct dentry *dentry) +{ + /* Expected to be called before d_delete() */ + WARN_ON_ONCE(d_is_negative(dentry)); + + fsnotify_dirent(dir, dentry, FS_DELETE | FS_ISDIR); +} + +/* * fsnotify_access - file was read */ static inline void fsnotify_access(struct file *file) diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h index d4844cad2c2b..1915bdba2fad 100644 --- a/include/linux/fsnotify_backend.h +++ b/include/linux/fsnotify_backend.h @@ -357,7 +357,6 @@ extern int __fsnotify_parent(const struct path *path, struct dentry *dentry, __u extern void __fsnotify_inode_delete(struct inode *inode); extern void __fsnotify_vfsmount_delete(struct vfsmount *mnt); extern void fsnotify_sb_delete(struct super_block *sb); -extern void fsnotify_nameremove(struct dentry *dentry, int isdir); extern u32 fsnotify_get_cookie(void); static inline int fsnotify_inode_watches_children(struct inode *inode) @@ -476,6 +475,8 @@ extern void fsnotify_destroy_mark(struct fsnotify_mark *mark, extern void fsnotify_detach_mark(struct fsnotify_mark *mark); /* free mark */ extern void fsnotify_free_mark(struct fsnotify_mark *mark); +/* Wait until all marks queued for destruction are destroyed */ +extern void fsnotify_wait_marks_destroyed(void); /* run all the marks in a group, and clear all of the marks attached to given object type */ extern void fsnotify_clear_marks_by_group(struct fsnotify_group *group, unsigned int type); /* run all the marks in a group, and clear all of the vfsmount marks */ @@ -527,9 +528,6 @@ static inline void __fsnotify_vfsmount_delete(struct vfsmount *mnt) static inline void fsnotify_sb_delete(struct super_block *sb) {} -static inline void fsnotify_nameremove(struct dentry *dentry, int isdir) -{} - static inline void fsnotify_update_flags(struct dentry *dentry) {} diff --git a/include/linux/fsverity.h b/include/linux/fsverity.h new file mode 100644 index 000000000000..3b6b8ccebe7d --- /dev/null +++ b/include/linux/fsverity.h @@ -0,0 +1,211 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * fs-verity: read-only file-based authenticity protection + * + * This header declares the interface between the fs/verity/ support layer and + * filesystems that support fs-verity. + * + * Copyright 2019 Google LLC + */ + +#ifndef _LINUX_FSVERITY_H +#define _LINUX_FSVERITY_H + +#include <linux/fs.h> +#include <uapi/linux/fsverity.h> + +/* Verity operations for filesystems */ +struct fsverity_operations { + + /** + * Begin enabling verity on the given file. + * + * @filp: a readonly file descriptor for the file + * + * The filesystem must do any needed filesystem-specific preparations + * for enabling verity, e.g. evicting inline data. It also must return + * -EBUSY if verity is already being enabled on the given file. + * + * i_rwsem is held for write. + * + * Return: 0 on success, -errno on failure + */ + int (*begin_enable_verity)(struct file *filp); + + /** + * End enabling verity on the given file. + * + * @filp: a readonly file descriptor for the file + * @desc: the verity descriptor to write, or NULL on failure + * @desc_size: size of verity descriptor, or 0 on failure + * @merkle_tree_size: total bytes the Merkle tree took up + * + * If desc == NULL, then enabling verity failed and the filesystem only + * must do any necessary cleanups. Else, it must also store the given + * verity descriptor to a fs-specific location associated with the inode + * and do any fs-specific actions needed to mark the inode as a verity + * inode, e.g. setting a bit in the on-disk inode. The filesystem is + * also responsible for setting the S_VERITY flag in the VFS inode. + * + * i_rwsem is held for write, but it may have been dropped between + * ->begin_enable_verity() and ->end_enable_verity(). + * + * Return: 0 on success, -errno on failure + */ + int (*end_enable_verity)(struct file *filp, const void *desc, + size_t desc_size, u64 merkle_tree_size); + + /** + * Get the verity descriptor of the given inode. + * + * @inode: an inode with the S_VERITY flag set + * @buf: buffer in which to place the verity descriptor + * @bufsize: size of @buf, or 0 to retrieve the size only + * + * If bufsize == 0, then the size of the verity descriptor is returned. + * Otherwise the verity descriptor is written to 'buf' and its actual + * size is returned; -ERANGE is returned if it's too large. This may be + * called by multiple processes concurrently on the same inode. + * + * Return: the size on success, -errno on failure + */ + int (*get_verity_descriptor)(struct inode *inode, void *buf, + size_t bufsize); + + /** + * Read a Merkle tree page of the given inode. + * + * @inode: the inode + * @index: 0-based index of the page within the Merkle tree + * + * This can be called at any time on an open verity file, as well as + * between ->begin_enable_verity() and ->end_enable_verity(). It may be + * called by multiple processes concurrently, even with the same page. + * + * Note that this must retrieve a *page*, not necessarily a *block*. + * + * Return: the page on success, ERR_PTR() on failure + */ + struct page *(*read_merkle_tree_page)(struct inode *inode, + pgoff_t index); + + /** + * Write a Merkle tree block to the given inode. + * + * @inode: the inode for which the Merkle tree is being built + * @buf: block to write + * @index: 0-based index of the block within the Merkle tree + * @log_blocksize: log base 2 of the Merkle tree block size + * + * This is only called between ->begin_enable_verity() and + * ->end_enable_verity(). + * + * Return: 0 on success, -errno on failure + */ + int (*write_merkle_tree_block)(struct inode *inode, const void *buf, + u64 index, int log_blocksize); +}; + +#ifdef CONFIG_FS_VERITY + +static inline struct fsverity_info *fsverity_get_info(const struct inode *inode) +{ + /* pairs with the cmpxchg() in fsverity_set_info() */ + return READ_ONCE(inode->i_verity_info); +} + +/* enable.c */ + +extern int fsverity_ioctl_enable(struct file *filp, const void __user *arg); + +/* measure.c */ + +extern int fsverity_ioctl_measure(struct file *filp, void __user *arg); + +/* open.c */ + +extern int fsverity_file_open(struct inode *inode, struct file *filp); +extern int fsverity_prepare_setattr(struct dentry *dentry, struct iattr *attr); +extern void fsverity_cleanup_inode(struct inode *inode); + +/* verify.c */ + +extern bool fsverity_verify_page(struct page *page); +extern void fsverity_verify_bio(struct bio *bio); +extern void fsverity_enqueue_verify_work(struct work_struct *work); + +#else /* !CONFIG_FS_VERITY */ + +static inline struct fsverity_info *fsverity_get_info(const struct inode *inode) +{ + return NULL; +} + +/* enable.c */ + +static inline int fsverity_ioctl_enable(struct file *filp, + const void __user *arg) +{ + return -EOPNOTSUPP; +} + +/* measure.c */ + +static inline int fsverity_ioctl_measure(struct file *filp, void __user *arg) +{ + return -EOPNOTSUPP; +} + +/* open.c */ + +static inline int fsverity_file_open(struct inode *inode, struct file *filp) +{ + return IS_VERITY(inode) ? -EOPNOTSUPP : 0; +} + +static inline int fsverity_prepare_setattr(struct dentry *dentry, + struct iattr *attr) +{ + return IS_VERITY(d_inode(dentry)) ? -EOPNOTSUPP : 0; +} + +static inline void fsverity_cleanup_inode(struct inode *inode) +{ +} + +/* verify.c */ + +static inline bool fsverity_verify_page(struct page *page) +{ + WARN_ON(1); + return false; +} + +static inline void fsverity_verify_bio(struct bio *bio) +{ + WARN_ON(1); +} + +static inline void fsverity_enqueue_verify_work(struct work_struct *work) +{ + WARN_ON(1); +} + +#endif /* !CONFIG_FS_VERITY */ + +/** + * fsverity_active() - do reads from the inode need to go through fs-verity? + * + * This checks whether ->i_verity_info has been set. + * + * Filesystems call this from ->readpages() to check whether the pages need to + * be verified or not. Don't use IS_VERITY() for this purpose; it's subject to + * a race condition where the file is being read concurrently with + * FS_IOC_ENABLE_VERITY completing. (S_VERITY is set before ->i_verity_info.) + */ +static inline bool fsverity_active(const struct inode *inode) +{ + return fsverity_get_info(inode) != NULL; +} + +#endif /* _LINUX_FSVERITY_H */ diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h index 25e2995d4a4c..8a8cb3c401b2 100644 --- a/include/linux/ftrace.h +++ b/include/linux/ftrace.h @@ -427,8 +427,8 @@ struct dyn_ftrace *ftrace_rec_iter_record(struct ftrace_rec_iter *iter); iter = ftrace_rec_iter_next(iter)) -int ftrace_update_record(struct dyn_ftrace *rec, int enable); -int ftrace_test_record(struct dyn_ftrace *rec, int enable); +int ftrace_update_record(struct dyn_ftrace *rec, bool enable); +int ftrace_test_record(struct dyn_ftrace *rec, bool enable); void ftrace_run_stop_machine(int command); unsigned long ftrace_location(unsigned long ip); unsigned long ftrace_location_range(unsigned long start, unsigned long end); diff --git a/include/linux/fwnode.h b/include/linux/fwnode.h index a11c8c56c78b..ababd6bc82f3 100644 --- a/include/linux/fwnode.h +++ b/include/linux/fwnode.h @@ -110,10 +110,11 @@ struct fwnode_operations { (fwnode ? (fwnode_has_op(fwnode, op) ? \ (fwnode)->ops->op(fwnode, ## __VA_ARGS__) : -ENXIO) : \ -EINVAL) -#define fwnode_call_bool_op(fwnode, op, ...) \ - (fwnode ? (fwnode_has_op(fwnode, op) ? \ - (fwnode)->ops->op(fwnode, ## __VA_ARGS__) : false) : \ - false) + +#define fwnode_call_bool_op(fwnode, op, ...) \ + (fwnode_has_op(fwnode, op) ? \ + (fwnode)->ops->op(fwnode, ## __VA_ARGS__) : false) + #define fwnode_call_ptr_op(fwnode, op, ...) \ (fwnode_has_op(fwnode, op) ? \ (fwnode)->ops->op(fwnode, ## __VA_ARGS__) : NULL) diff --git a/include/linux/genalloc.h b/include/linux/genalloc.h index 205f62b8d291..4bd583bd6934 100644 --- a/include/linux/genalloc.h +++ b/include/linux/genalloc.h @@ -155,6 +155,15 @@ static inline unsigned long gen_pool_alloc(struct gen_pool *pool, size_t size) extern void *gen_pool_dma_alloc(struct gen_pool *pool, size_t size, dma_addr_t *dma); +extern void *gen_pool_dma_alloc_algo(struct gen_pool *pool, size_t size, + dma_addr_t *dma, genpool_algo_t algo, void *data); +extern void *gen_pool_dma_alloc_align(struct gen_pool *pool, size_t size, + dma_addr_t *dma, int align); +extern void *gen_pool_dma_zalloc(struct gen_pool *pool, size_t size, dma_addr_t *dma); +extern void *gen_pool_dma_zalloc_algo(struct gen_pool *pool, size_t size, + dma_addr_t *dma, genpool_algo_t algo, void *data); +extern void *gen_pool_dma_zalloc_align(struct gen_pool *pool, size_t size, + dma_addr_t *dma, int align); extern void gen_pool_free_owner(struct gen_pool *pool, unsigned long addr, size_t size, void **owner); static inline void gen_pool_free(struct gen_pool *pool, unsigned long addr, diff --git a/include/linux/gfp.h b/include/linux/gfp.h index fb07b503dc45..f33881688f42 100644 --- a/include/linux/gfp.h +++ b/include/linux/gfp.h @@ -510,22 +510,18 @@ alloc_pages(gfp_t gfp_mask, unsigned int order) } extern struct page *alloc_pages_vma(gfp_t gfp_mask, int order, struct vm_area_struct *vma, unsigned long addr, - int node, bool hugepage); -#define alloc_hugepage_vma(gfp_mask, vma, addr, order) \ - alloc_pages_vma(gfp_mask, order, vma, addr, numa_node_id(), true) + int node); #else #define alloc_pages(gfp_mask, order) \ alloc_pages_node(numa_node_id(), gfp_mask, order) -#define alloc_pages_vma(gfp_mask, order, vma, addr, node, false)\ - alloc_pages(gfp_mask, order) -#define alloc_hugepage_vma(gfp_mask, vma, addr, order) \ +#define alloc_pages_vma(gfp_mask, order, vma, addr, node)\ alloc_pages(gfp_mask, order) #endif #define alloc_page(gfp_mask) alloc_pages(gfp_mask, 0) #define alloc_page_vma(gfp_mask, vma, addr) \ - alloc_pages_vma(gfp_mask, 0, vma, addr, numa_node_id(), false) + alloc_pages_vma(gfp_mask, 0, vma, addr, numa_node_id()) #define alloc_page_vma_node(gfp_mask, vma, addr, node) \ - alloc_pages_vma(gfp_mask, 0, vma, addr, node, false) + alloc_pages_vma(gfp_mask, 0, vma, addr, node) extern unsigned long __get_free_pages(gfp_t gfp_mask, unsigned int order); extern unsigned long get_zeroed_page(gfp_t gfp_mask); diff --git a/include/linux/gpio.h b/include/linux/gpio.h index 39745b8bdd65..2157717c2136 100644 --- a/include/linux/gpio.h +++ b/include/linux/gpio.h @@ -106,6 +106,7 @@ void devm_gpio_free(struct device *dev, unsigned int gpio); struct device; struct gpio_chip; +struct pinctrl_dev; static inline bool gpio_is_valid(int number) { @@ -220,19 +221,6 @@ static inline int gpio_to_irq(unsigned gpio) return -EINVAL; } -static inline int gpiochip_lock_as_irq(struct gpio_chip *chip, - unsigned int offset) -{ - WARN_ON(1); - return -EINVAL; -} - -static inline void gpiochip_unlock_as_irq(struct gpio_chip *chip, - unsigned int offset) -{ - WARN_ON(1); -} - static inline int irq_to_gpio(unsigned irq) { /* irq can never have been returned from gpio_to_irq() */ @@ -240,30 +228,6 @@ static inline int irq_to_gpio(unsigned irq) return -EINVAL; } -static inline int -gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name, - unsigned int gpio_offset, unsigned int pin_offset, - unsigned int npins) -{ - WARN_ON(1); - return -EINVAL; -} - -static inline int -gpiochip_add_pingroup_range(struct gpio_chip *chip, - struct pinctrl_dev *pctldev, - unsigned int gpio_offset, const char *pin_group) -{ - WARN_ON(1); - return -EINVAL; -} - -static inline void -gpiochip_remove_pin_ranges(struct gpio_chip *chip) -{ - WARN_ON(1); -} - static inline int devm_gpio_request(struct device *dev, unsigned gpio, const char *label) { diff --git a/include/linux/gpio/consumer.h b/include/linux/gpio/consumer.h index 9ddcf50a3c59..b70af921c614 100644 --- a/include/linux/gpio/consumer.h +++ b/include/linux/gpio/consumer.h @@ -170,18 +170,8 @@ struct gpio_desc *gpio_to_desc(unsigned gpio); int desc_to_gpio(const struct gpio_desc *desc); /* Child properties interface */ -struct device_node; struct fwnode_handle; -struct gpio_desc *gpiod_get_from_of_node(struct device_node *node, - const char *propname, int index, - enum gpiod_flags dflags, - const char *label); -struct gpio_desc *devm_gpiod_get_from_of_node(struct device *dev, - struct device_node *node, - const char *propname, int index, - enum gpiod_flags dflags, - const char *label); struct gpio_desc *fwnode_get_named_gpiod(struct fwnode_handle *fwnode, const char *propname, int index, enum gpiod_flags dflags, @@ -247,7 +237,7 @@ static inline void gpiod_put(struct gpio_desc *desc) might_sleep(); /* GPIO can never have been requested */ - WARN_ON(1); + WARN_ON(desc); } static inline void devm_gpiod_unhinge(struct device *dev, @@ -256,7 +246,7 @@ static inline void devm_gpiod_unhinge(struct device *dev, might_sleep(); /* GPIO can never have been requested */ - WARN_ON(1); + WARN_ON(desc); } static inline void gpiod_put_array(struct gpio_descs *descs) @@ -264,7 +254,7 @@ static inline void gpiod_put_array(struct gpio_descs *descs) might_sleep(); /* GPIO can never have been requested */ - WARN_ON(1); + WARN_ON(descs); } static inline struct gpio_desc *__must_check @@ -317,7 +307,7 @@ static inline void devm_gpiod_put(struct device *dev, struct gpio_desc *desc) might_sleep(); /* GPIO can never have been requested */ - WARN_ON(1); + WARN_ON(desc); } static inline void devm_gpiod_put_array(struct device *dev, @@ -326,32 +316,32 @@ static inline void devm_gpiod_put_array(struct device *dev, might_sleep(); /* GPIO can never have been requested */ - WARN_ON(1); + WARN_ON(descs); } static inline int gpiod_get_direction(const struct gpio_desc *desc) { /* GPIO can never have been requested */ - WARN_ON(1); + WARN_ON(desc); return -ENOSYS; } static inline int gpiod_direction_input(struct gpio_desc *desc) { /* GPIO can never have been requested */ - WARN_ON(1); + WARN_ON(desc); return -ENOSYS; } static inline int gpiod_direction_output(struct gpio_desc *desc, int value) { /* GPIO can never have been requested */ - WARN_ON(1); + WARN_ON(desc); return -ENOSYS; } static inline int gpiod_direction_output_raw(struct gpio_desc *desc, int value) { /* GPIO can never have been requested */ - WARN_ON(1); + WARN_ON(desc); return -ENOSYS; } @@ -359,7 +349,7 @@ static inline int gpiod_direction_output_raw(struct gpio_desc *desc, int value) static inline int gpiod_get_value(const struct gpio_desc *desc) { /* GPIO can never have been requested */ - WARN_ON(1); + WARN_ON(desc); return 0; } static inline int gpiod_get_array_value(unsigned int array_size, @@ -368,13 +358,13 @@ static inline int gpiod_get_array_value(unsigned int array_size, unsigned long *value_bitmap) { /* GPIO can never have been requested */ - WARN_ON(1); + WARN_ON(desc_array); return 0; } static inline void gpiod_set_value(struct gpio_desc *desc, int value) { /* GPIO can never have been requested */ - WARN_ON(1); + WARN_ON(desc); } static inline int gpiod_set_array_value(unsigned int array_size, struct gpio_desc **desc_array, @@ -382,13 +372,13 @@ static inline int gpiod_set_array_value(unsigned int array_size, unsigned long *value_bitmap) { /* GPIO can never have been requested */ - WARN_ON(1); + WARN_ON(desc_array); return 0; } static inline int gpiod_get_raw_value(const struct gpio_desc *desc) { /* GPIO can never have been requested */ - WARN_ON(1); + WARN_ON(desc); return 0; } static inline int gpiod_get_raw_array_value(unsigned int array_size, @@ -397,13 +387,13 @@ static inline int gpiod_get_raw_array_value(unsigned int array_size, unsigned long *value_bitmap) { /* GPIO can never have been requested */ - WARN_ON(1); + WARN_ON(desc_array); return 0; } static inline void gpiod_set_raw_value(struct gpio_desc *desc, int value) { /* GPIO can never have been requested */ - WARN_ON(1); + WARN_ON(desc); } static inline int gpiod_set_raw_array_value(unsigned int array_size, struct gpio_desc **desc_array, @@ -411,14 +401,14 @@ static inline int gpiod_set_raw_array_value(unsigned int array_size, unsigned long *value_bitmap) { /* GPIO can never have been requested */ - WARN_ON(1); + WARN_ON(desc_array); return 0; } static inline int gpiod_get_value_cansleep(const struct gpio_desc *desc) { /* GPIO can never have been requested */ - WARN_ON(1); + WARN_ON(desc); return 0; } static inline int gpiod_get_array_value_cansleep(unsigned int array_size, @@ -427,13 +417,13 @@ static inline int gpiod_get_array_value_cansleep(unsigned int array_size, unsigned long *value_bitmap) { /* GPIO can never have been requested */ - WARN_ON(1); + WARN_ON(desc_array); return 0; } static inline void gpiod_set_value_cansleep(struct gpio_desc *desc, int value) { /* GPIO can never have been requested */ - WARN_ON(1); + WARN_ON(desc); } static inline int gpiod_set_array_value_cansleep(unsigned int array_size, struct gpio_desc **desc_array, @@ -441,13 +431,13 @@ static inline int gpiod_set_array_value_cansleep(unsigned int array_size, unsigned long *value_bitmap) { /* GPIO can never have been requested */ - WARN_ON(1); + WARN_ON(desc_array); return 0; } static inline int gpiod_get_raw_value_cansleep(const struct gpio_desc *desc) { /* GPIO can never have been requested */ - WARN_ON(1); + WARN_ON(desc); return 0; } static inline int gpiod_get_raw_array_value_cansleep(unsigned int array_size, @@ -456,14 +446,14 @@ static inline int gpiod_get_raw_array_value_cansleep(unsigned int array_size, unsigned long *value_bitmap) { /* GPIO can never have been requested */ - WARN_ON(1); + WARN_ON(desc_array); return 0; } static inline void gpiod_set_raw_value_cansleep(struct gpio_desc *desc, int value) { /* GPIO can never have been requested */ - WARN_ON(1); + WARN_ON(desc); } static inline int gpiod_set_raw_array_value_cansleep(unsigned int array_size, struct gpio_desc **desc_array, @@ -471,41 +461,41 @@ static inline int gpiod_set_raw_array_value_cansleep(unsigned int array_size, unsigned long *value_bitmap) { /* GPIO can never have been requested */ - WARN_ON(1); + WARN_ON(desc_array); return 0; } static inline int gpiod_set_debounce(struct gpio_desc *desc, unsigned debounce) { /* GPIO can never have been requested */ - WARN_ON(1); + WARN_ON(desc); return -ENOSYS; } static inline int gpiod_set_transitory(struct gpio_desc *desc, bool transitory) { /* GPIO can never have been requested */ - WARN_ON(1); + WARN_ON(desc); return -ENOSYS; } static inline int gpiod_is_active_low(const struct gpio_desc *desc) { /* GPIO can never have been requested */ - WARN_ON(1); + WARN_ON(desc); return 0; } static inline int gpiod_cansleep(const struct gpio_desc *desc) { /* GPIO can never have been requested */ - WARN_ON(1); + WARN_ON(desc); return 0; } static inline int gpiod_to_irq(const struct gpio_desc *desc) { /* GPIO can never have been requested */ - WARN_ON(1); + WARN_ON(desc); return -EINVAL; } @@ -513,7 +503,7 @@ static inline int gpiod_set_consumer_name(struct gpio_desc *desc, const char *name) { /* GPIO can never have been requested */ - WARN_ON(1); + WARN_ON(desc); return -EINVAL; } @@ -525,34 +515,14 @@ static inline struct gpio_desc *gpio_to_desc(unsigned gpio) static inline int desc_to_gpio(const struct gpio_desc *desc) { /* GPIO can never have been requested */ - WARN_ON(1); + WARN_ON(desc); return -EINVAL; } /* Child properties interface */ -struct device_node; struct fwnode_handle; static inline -struct gpio_desc *gpiod_get_from_of_node(struct device_node *node, - const char *propname, int index, - enum gpiod_flags dflags, - const char *label) -{ - return ERR_PTR(-ENOSYS); -} - -static inline -struct gpio_desc *devm_gpiod_get_from_of_node(struct device *dev, - struct device_node *node, - const char *propname, int index, - enum gpiod_flags dflags, - const char *label) -{ - return ERR_PTR(-ENOSYS); -} - -static inline struct gpio_desc *fwnode_get_named_gpiod(struct fwnode_handle *fwnode, const char *propname, int index, enum gpiod_flags dflags, @@ -584,6 +554,111 @@ struct gpio_desc *devm_fwnode_get_gpiod_from_child(struct device *dev, flags, label); } +#if IS_ENABLED(CONFIG_GPIOLIB) && IS_ENABLED(CONFIG_OF_GPIO) +struct device_node; + +struct gpio_desc *gpiod_get_from_of_node(struct device_node *node, + const char *propname, int index, + enum gpiod_flags dflags, + const char *label); + +#else /* CONFIG_GPIOLIB && CONFIG_OF_GPIO */ + +struct device_node; + +static inline +struct gpio_desc *gpiod_get_from_of_node(struct device_node *node, + const char *propname, int index, + enum gpiod_flags dflags, + const char *label) +{ + return ERR_PTR(-ENOSYS); +} + +#endif /* CONFIG_GPIOLIB && CONFIG_OF_GPIO */ + +#ifdef CONFIG_GPIOLIB +struct device_node; + +struct gpio_desc *devm_gpiod_get_from_of_node(struct device *dev, + struct device_node *node, + const char *propname, int index, + enum gpiod_flags dflags, + const char *label); + +#else /* CONFIG_GPIOLIB */ + +struct device_node; + +static inline +struct gpio_desc *devm_gpiod_get_from_of_node(struct device *dev, + struct device_node *node, + const char *propname, int index, + enum gpiod_flags dflags, + const char *label) +{ + return ERR_PTR(-ENOSYS); +} + +#endif /* CONFIG_GPIOLIB */ + +struct acpi_gpio_params { + unsigned int crs_entry_index; + unsigned int line_index; + bool active_low; +}; + +struct acpi_gpio_mapping { + const char *name; + const struct acpi_gpio_params *data; + unsigned int size; + +/* Ignore IoRestriction field */ +#define ACPI_GPIO_QUIRK_NO_IO_RESTRICTION BIT(0) +/* + * When ACPI GPIO mapping table is in use the index parameter inside it + * refers to the GPIO resource in _CRS method. That index has no + * distinction of actual type of the resource. When consumer wants to + * get GpioIo type explicitly, this quirk may be used. + */ +#define ACPI_GPIO_QUIRK_ONLY_GPIOIO BIT(1) + + unsigned int quirks; +}; + +#if IS_ENABLED(CONFIG_GPIOLIB) && IS_ENABLED(CONFIG_ACPI) + +struct acpi_device; + +int acpi_dev_add_driver_gpios(struct acpi_device *adev, + const struct acpi_gpio_mapping *gpios); +void acpi_dev_remove_driver_gpios(struct acpi_device *adev); + +int devm_acpi_dev_add_driver_gpios(struct device *dev, + const struct acpi_gpio_mapping *gpios); +void devm_acpi_dev_remove_driver_gpios(struct device *dev); + +#else /* CONFIG_GPIOLIB && CONFIG_ACPI */ + +struct acpi_device; + +static inline int acpi_dev_add_driver_gpios(struct acpi_device *adev, + const struct acpi_gpio_mapping *gpios) +{ + return -ENXIO; +} +static inline void acpi_dev_remove_driver_gpios(struct acpi_device *adev) {} + +static inline int devm_acpi_dev_add_driver_gpios(struct device *dev, + const struct acpi_gpio_mapping *gpios) +{ + return -ENXIO; +} +static inline void devm_acpi_dev_remove_driver_gpios(struct device *dev) {} + +#endif /* CONFIG_GPIOLIB && CONFIG_ACPI */ + + #if IS_ENABLED(CONFIG_GPIOLIB) && IS_ENABLED(CONFIG_GPIO_SYSFS) int gpiod_export(struct gpio_desc *desc, bool direction_may_change); diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h index a1d273c96016..f8245d67f070 100644 --- a/include/linux/gpio/driver.h +++ b/include/linux/gpio/driver.h @@ -18,10 +18,10 @@ struct seq_file; struct gpio_device; struct module; enum gpiod_flags; +enum gpio_lookup_flags; -#ifdef CONFIG_GPIOLIB +struct gpio_chip; -#ifdef CONFIG_GPIOLIB_IRQCHIP /** * struct gpio_irq_chip - GPIO interrupt controller */ @@ -48,6 +48,84 @@ struct gpio_irq_chip { */ const struct irq_domain_ops *domain_ops; +#ifdef CONFIG_IRQ_DOMAIN_HIERARCHY + /** + * @fwnode: + * + * Firmware node corresponding to this gpiochip/irqchip, necessary + * for hierarchical irqdomain support. + */ + struct fwnode_handle *fwnode; + + /** + * @parent_domain: + * + * If non-NULL, will be set as the parent of this GPIO interrupt + * controller's IRQ domain to establish a hierarchical interrupt + * domain. The presence of this will activate the hierarchical + * interrupt support. + */ + struct irq_domain *parent_domain; + + /** + * @child_to_parent_hwirq: + * + * This callback translates a child hardware IRQ offset to a parent + * hardware IRQ offset on a hierarchical interrupt chip. The child + * hardware IRQs correspond to the GPIO index 0..ngpio-1 (see the + * ngpio field of struct gpio_chip) and the corresponding parent + * hardware IRQ and type (such as IRQ_TYPE_*) shall be returned by + * the driver. The driver can calculate this from an offset or using + * a lookup table or whatever method is best for this chip. Return + * 0 on successful translation in the driver. + * + * If some ranges of hardware IRQs do not have a corresponding parent + * HWIRQ, return -EINVAL, but also make sure to fill in @valid_mask and + * @need_valid_mask to make these GPIO lines unavailable for + * translation. + */ + int (*child_to_parent_hwirq)(struct gpio_chip *chip, + unsigned int child_hwirq, + unsigned int child_type, + unsigned int *parent_hwirq, + unsigned int *parent_type); + + /** + * @populate_parent_fwspec: + * + * This optional callback populates the &struct irq_fwspec for the + * parent's IRQ domain. If this is not specified, then + * &gpiochip_populate_parent_fwspec_twocell will be used. A four-cell + * variant named &gpiochip_populate_parent_fwspec_fourcell is also + * available. + */ + void (*populate_parent_fwspec)(struct gpio_chip *chip, + struct irq_fwspec *fwspec, + unsigned int parent_hwirq, + unsigned int parent_type); + + /** + * @child_offset_to_irq: + * + * This optional callback is used to translate the child's GPIO line + * offset on the GPIO chip to an IRQ number for the GPIO to_irq() + * callback. If this is not specified, then a default callback will be + * provided that returns the line offset. + */ + unsigned int (*child_offset_to_irq)(struct gpio_chip *chip, + unsigned int pin); + + /** + * @child_irq_domain_ops: + * + * The IRQ domain operations that will be used for this GPIO IRQ + * chip. If no operations are provided, then default callbacks will + * be populated to setup the IRQ hierarchy. Some drivers need to + * supply their own translate function. + */ + struct irq_domain_ops child_irq_domain_ops; +#endif + /** * @handler: * @@ -102,13 +180,6 @@ struct gpio_irq_chip { unsigned int num_parents; /** - * @parent_irq: - * - * For use by gpiochip_set_cascaded_irqchip() - */ - unsigned int parent_irq; - - /** * @parents: * * A list of interrupt parents of a GPIO chip. This is owned by the @@ -131,11 +202,17 @@ struct gpio_irq_chip { bool threaded; /** - * @need_valid_mask: - * - * If set core allocates @valid_mask with all bits set to one. + * @init_valid_mask: optional routine to initialize @valid_mask, to be + * used if not all GPIO lines are valid interrupts. Sometimes some + * lines just cannot fire interrupts, and this routine, when defined, + * is passed a bitmap in "valid_mask" and it will have ngpios + * bits from 0..(ngpios-1) set to "1" as in valid. The callback can + * then directly set some bits to "0" if they cannot be used for + * interrupts. */ - bool need_valid_mask; + void (*init_valid_mask)(struct gpio_chip *chip, + unsigned long *valid_mask, + unsigned int ngpios); /** * @valid_mask: @@ -167,7 +244,6 @@ struct gpio_irq_chip { */ void (*irq_disable)(struct irq_data *data); }; -#endif /** * struct gpio_chip - abstract a GPIO controller @@ -200,6 +276,8 @@ struct gpio_irq_chip { * @dbg_show: optional routine to show contents in debugfs; default code * will be used when this is omitted, but custom code can show extra * state (such as pullup/pulldown configuration). + * @init_valid_mask: optional routine to initialize @valid_mask, to be used if + * not all GPIOs are valid. * @base: identifies the first GPIO number handled by this chip; * or, if negative during registration, requests dynamic ID allocation. * DEPRECATION: providing anything non-negative and nailing the base @@ -286,7 +364,9 @@ struct gpio_chip { void (*dbg_show)(struct seq_file *s, struct gpio_chip *chip); - int (*init_valid_mask)(struct gpio_chip *chip); + int (*init_valid_mask)(struct gpio_chip *chip, + unsigned long *valid_mask, + unsigned int ngpios); int base; u16 ngpio; @@ -307,7 +387,7 @@ struct gpio_chip { spinlock_t bgpio_lock; unsigned long bgpio_data; unsigned long bgpio_dir; -#endif +#endif /* CONFIG_GPIO_GENERIC */ #ifdef CONFIG_GPIOLIB_IRQCHIP /* @@ -322,16 +402,7 @@ struct gpio_chip { * used to handle IRQs for most practical cases. */ struct gpio_irq_chip irq; -#endif - - /** - * @need_valid_mask: - * - * If set core allocates @valid_mask with all its values initialized - * with init_valid_mask() or set to one if init_valid_mask() is not - * defined - */ - bool need_valid_mask; +#endif /* CONFIG_GPIOLIB_IRQCHIP */ /** * @valid_mask: @@ -369,7 +440,7 @@ struct gpio_chip { */ int (*of_xlate)(struct gpio_chip *gc, const struct of_phandle_args *gpiospec, u32 *flags); -#endif +#endif /* CONFIG_OF_GPIO */ }; extern const char *gpiochip_is_requested(struct gpio_chip *chip, @@ -412,7 +483,7 @@ extern int gpiochip_add_data_with_key(struct gpio_chip *chip, void *data, }) #else #define gpiochip_add_data(chip, data) gpiochip_add_data_with_key(chip, data, NULL, NULL) -#endif +#endif /* CONFIG_LOCKDEP */ static inline int gpiochip_add(struct gpio_chip *chip) { @@ -425,9 +496,6 @@ extern int devm_gpiochip_add_data(struct device *dev, struct gpio_chip *chip, extern struct gpio_chip *gpiochip_find(void *data, int (*match)(struct gpio_chip *chip, void *data)); -/* lock/unlock as IRQ */ -int gpiochip_lock_as_irq(struct gpio_chip *chip, unsigned int offset); -void gpiochip_unlock_as_irq(struct gpio_chip *chip, unsigned int offset); bool gpiochip_line_is_irq(struct gpio_chip *chip, unsigned int offset); int gpiochip_reqres_irq(struct gpio_chip *chip, unsigned int offset); void gpiochip_relres_irq(struct gpio_chip *chip, unsigned int offset); @@ -445,15 +513,40 @@ bool gpiochip_line_is_valid(const struct gpio_chip *chip, unsigned int offset); /* get driver data */ void *gpiochip_get_data(struct gpio_chip *chip); -struct gpio_chip *gpiod_to_chip(const struct gpio_desc *desc); - struct bgpio_pdata { const char *label; int base; int ngpio; }; -#if IS_ENABLED(CONFIG_GPIO_GENERIC) +#ifdef CONFIG_IRQ_DOMAIN_HIERARCHY + +void gpiochip_populate_parent_fwspec_twocell(struct gpio_chip *chip, + struct irq_fwspec *fwspec, + unsigned int parent_hwirq, + unsigned int parent_type); +void gpiochip_populate_parent_fwspec_fourcell(struct gpio_chip *chip, + struct irq_fwspec *fwspec, + unsigned int parent_hwirq, + unsigned int parent_type); + +#else + +static inline void gpiochip_populate_parent_fwspec_twocell(struct gpio_chip *chip, + struct irq_fwspec *fwspec, + unsigned int parent_hwirq, + unsigned int parent_type) +{ +} + +static inline void gpiochip_populate_parent_fwspec_fourcell(struct gpio_chip *chip, + struct irq_fwspec *fwspec, + unsigned int parent_hwirq, + unsigned int parent_type) +{ +} + +#endif /* CONFIG_IRQ_DOMAIN_HIERARCHY */ int bgpio_init(struct gpio_chip *gc, struct device *dev, unsigned long sz, void __iomem *dat, void __iomem *set, @@ -467,10 +560,6 @@ int bgpio_init(struct gpio_chip *gc, struct device *dev, #define BGPIOF_READ_OUTPUT_REG_SET BIT(4) /* reg_set stores output value */ #define BGPIOF_NO_OUTPUT BIT(5) /* only input */ -#endif - -#ifdef CONFIG_GPIOLIB_IRQCHIP - int gpiochip_irq_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hwirq); void gpiochip_irq_unmap(struct irq_domain *d, unsigned int irq); @@ -537,7 +626,7 @@ static inline int gpiochip_irqchip_add_nested(struct gpio_chip *gpiochip, handler, type, true, &lock_key, &request_key); } -#else +#else /* ! CONFIG_LOCKDEP */ static inline int gpiochip_irqchip_add(struct gpio_chip *gpiochip, struct irq_chip *irqchip, unsigned int first_irq, @@ -559,15 +648,11 @@ static inline int gpiochip_irqchip_add_nested(struct gpio_chip *gpiochip, } #endif /* CONFIG_LOCKDEP */ -#endif /* CONFIG_GPIOLIB_IRQCHIP */ - int gpiochip_generic_request(struct gpio_chip *chip, unsigned offset); void gpiochip_generic_free(struct gpio_chip *chip, unsigned offset); int gpiochip_generic_config(struct gpio_chip *chip, unsigned offset, unsigned long config); -#ifdef CONFIG_PINCTRL - /** * struct gpio_pin_range - pin range controlled by a gpio chip * @node: list for maintaining set of pin ranges, used internally @@ -580,6 +665,8 @@ struct gpio_pin_range { struct pinctrl_gpio_range range; }; +#ifdef CONFIG_PINCTRL + int gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name, unsigned int gpio_offset, unsigned int pin_offset, unsigned int npins); @@ -588,7 +675,7 @@ int gpiochip_add_pingroup_range(struct gpio_chip *chip, unsigned int gpio_offset, const char *pin_group); void gpiochip_remove_pin_ranges(struct gpio_chip *chip); -#else +#else /* ! CONFIG_PINCTRL */ static inline int gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name, @@ -614,12 +701,22 @@ gpiochip_remove_pin_ranges(struct gpio_chip *chip) struct gpio_desc *gpiochip_request_own_desc(struct gpio_chip *chip, u16 hwnum, const char *label, - enum gpiod_flags flags); + enum gpio_lookup_flags lflags, + enum gpiod_flags dflags); void gpiochip_free_own_desc(struct gpio_desc *desc); void devprop_gpiochip_set_names(struct gpio_chip *chip, const struct fwnode_handle *fwnode); +#ifdef CONFIG_GPIOLIB + +/* lock/unlock as IRQ */ +int gpiochip_lock_as_irq(struct gpio_chip *chip, unsigned int offset); +void gpiochip_unlock_as_irq(struct gpio_chip *chip, unsigned int offset); + + +struct gpio_chip *gpiod_to_chip(const struct gpio_desc *desc); + #else /* CONFIG_GPIOLIB */ static inline struct gpio_chip *gpiod_to_chip(const struct gpio_desc *desc) @@ -629,6 +726,18 @@ static inline struct gpio_chip *gpiod_to_chip(const struct gpio_desc *desc) return ERR_PTR(-ENODEV); } +static inline int gpiochip_lock_as_irq(struct gpio_chip *chip, + unsigned int offset) +{ + WARN_ON(1); + return -EINVAL; +} + +static inline void gpiochip_unlock_as_irq(struct gpio_chip *chip, + unsigned int offset) +{ + WARN_ON(1); +} #endif /* CONFIG_GPIOLIB */ -#endif +#endif /* __LINUX_GPIO_DRIVER_H */ diff --git a/include/linux/gpio/gpio-reg.h b/include/linux/gpio/gpio-reg.h index 5c6efd394cb0..39b888c40b39 100644 --- a/include/linux/gpio/gpio-reg.h +++ b/include/linux/gpio/gpio-reg.h @@ -11,4 +11,4 @@ struct gpio_chip *gpio_reg_init(struct device *dev, void __iomem *reg, int gpio_reg_resume(struct gpio_chip *gc); -#endif +#endif /* GPIO_REG_H */ diff --git a/include/linux/gpio/machine.h b/include/linux/gpio/machine.h index 35f299d1f6a7..1ebe5be05d5f 100644 --- a/include/linux/gpio/machine.h +++ b/include/linux/gpio/machine.h @@ -97,7 +97,7 @@ void gpiod_add_lookup_table(struct gpiod_lookup_table *table); void gpiod_add_lookup_tables(struct gpiod_lookup_table **tables, size_t n); void gpiod_remove_lookup_table(struct gpiod_lookup_table *table); void gpiod_add_hogs(struct gpiod_hog *hogs); -#else +#else /* ! CONFIG_GPIOLIB */ static inline void gpiod_add_lookup_table(struct gpiod_lookup_table *table) {} static inline @@ -105,6 +105,6 @@ void gpiod_add_lookup_tables(struct gpiod_lookup_table **tables, size_t n) {} static inline void gpiod_remove_lookup_table(struct gpiod_lookup_table *table) {} static inline void gpiod_add_hogs(struct gpiod_hog *hogs) {} -#endif +#endif /* CONFIG_GPIOLIB */ #endif /* __LINUX_GPIO_MACHINE_H */ diff --git a/include/linux/greybus.h b/include/linux/greybus.h new file mode 100644 index 000000000000..18c0fb958b74 --- /dev/null +++ b/include/linux/greybus.h @@ -0,0 +1,152 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Greybus driver and device API + * + * Copyright 2014-2015 Google Inc. + * Copyright 2014-2015 Linaro Ltd. + */ + +#ifndef __LINUX_GREYBUS_H +#define __LINUX_GREYBUS_H + +#ifdef __KERNEL__ + +#include <linux/kernel.h> +#include <linux/types.h> +#include <linux/list.h> +#include <linux/slab.h> +#include <linux/device.h> +#include <linux/module.h> +#include <linux/pm_runtime.h> +#include <linux/idr.h> + +#include <linux/greybus/greybus_id.h> +#include <linux/greybus/greybus_manifest.h> +#include <linux/greybus/greybus_protocols.h> +#include <linux/greybus/manifest.h> +#include <linux/greybus/hd.h> +#include <linux/greybus/svc.h> +#include <linux/greybus/control.h> +#include <linux/greybus/module.h> +#include <linux/greybus/interface.h> +#include <linux/greybus/bundle.h> +#include <linux/greybus/connection.h> +#include <linux/greybus/operation.h> + +/* Matches up with the Greybus Protocol specification document */ +#define GREYBUS_VERSION_MAJOR 0x00 +#define GREYBUS_VERSION_MINOR 0x01 + +#define GREYBUS_ID_MATCH_DEVICE \ + (GREYBUS_ID_MATCH_VENDOR | GREYBUS_ID_MATCH_PRODUCT) + +#define GREYBUS_DEVICE(v, p) \ + .match_flags = GREYBUS_ID_MATCH_DEVICE, \ + .vendor = (v), \ + .product = (p), + +#define GREYBUS_DEVICE_CLASS(c) \ + .match_flags = GREYBUS_ID_MATCH_CLASS, \ + .class = (c), + +/* Maximum number of CPorts */ +#define CPORT_ID_MAX 4095 /* UniPro max id is 4095 */ +#define CPORT_ID_BAD U16_MAX + +struct greybus_driver { + const char *name; + + int (*probe)(struct gb_bundle *bundle, + const struct greybus_bundle_id *id); + void (*disconnect)(struct gb_bundle *bundle); + + const struct greybus_bundle_id *id_table; + + struct device_driver driver; +}; +#define to_greybus_driver(d) container_of(d, struct greybus_driver, driver) + +static inline void greybus_set_drvdata(struct gb_bundle *bundle, void *data) +{ + dev_set_drvdata(&bundle->dev, data); +} + +static inline void *greybus_get_drvdata(struct gb_bundle *bundle) +{ + return dev_get_drvdata(&bundle->dev); +} + +/* Don't call these directly, use the module_greybus_driver() macro instead */ +int greybus_register_driver(struct greybus_driver *driver, + struct module *module, const char *mod_name); +void greybus_deregister_driver(struct greybus_driver *driver); + +/* define to get proper THIS_MODULE and KBUILD_MODNAME values */ +#define greybus_register(driver) \ + greybus_register_driver(driver, THIS_MODULE, KBUILD_MODNAME) +#define greybus_deregister(driver) \ + greybus_deregister_driver(driver) + +/** + * module_greybus_driver() - Helper macro for registering a Greybus driver + * @__greybus_driver: greybus_driver structure + * + * Helper macro for Greybus drivers to set up proper module init / exit + * functions. Replaces module_init() and module_exit() and keeps people from + * printing pointless things to the kernel log when their driver is loaded. + */ +#define module_greybus_driver(__greybus_driver) \ + module_driver(__greybus_driver, greybus_register, greybus_deregister) + +int greybus_disabled(void); + +void gb_debugfs_init(void); +void gb_debugfs_cleanup(void); +struct dentry *gb_debugfs_get(void); + +extern struct bus_type greybus_bus_type; + +extern struct device_type greybus_hd_type; +extern struct device_type greybus_module_type; +extern struct device_type greybus_interface_type; +extern struct device_type greybus_control_type; +extern struct device_type greybus_bundle_type; +extern struct device_type greybus_svc_type; + +static inline int is_gb_host_device(const struct device *dev) +{ + return dev->type == &greybus_hd_type; +} + +static inline int is_gb_module(const struct device *dev) +{ + return dev->type == &greybus_module_type; +} + +static inline int is_gb_interface(const struct device *dev) +{ + return dev->type == &greybus_interface_type; +} + +static inline int is_gb_control(const struct device *dev) +{ + return dev->type == &greybus_control_type; +} + +static inline int is_gb_bundle(const struct device *dev) +{ + return dev->type == &greybus_bundle_type; +} + +static inline int is_gb_svc(const struct device *dev) +{ + return dev->type == &greybus_svc_type; +} + +static inline bool cport_id_valid(struct gb_host_device *hd, u16 cport_id) +{ + return cport_id != CPORT_ID_BAD && cport_id < hd->num_cports; +} + +#endif /* __KERNEL__ */ +#endif /* __LINUX_GREYBUS_H */ diff --git a/include/linux/greybus/bundle.h b/include/linux/greybus/bundle.h new file mode 100644 index 000000000000..df8d88424cb7 --- /dev/null +++ b/include/linux/greybus/bundle.h @@ -0,0 +1,92 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Greybus bundles + * + * Copyright 2014 Google Inc. + * Copyright 2014 Linaro Ltd. + */ + +#ifndef __BUNDLE_H +#define __BUNDLE_H + +#include <linux/types.h> +#include <linux/list.h> +#include <linux/pm_runtime.h> +#include <linux/device.h> + +#define BUNDLE_ID_NONE U8_MAX + +/* Greybus "public" definitions" */ +struct gb_bundle { + struct device dev; + struct gb_interface *intf; + + u8 id; + u8 class; + u8 class_major; + u8 class_minor; + + size_t num_cports; + struct greybus_descriptor_cport *cport_desc; + + struct list_head connections; + u8 *state; + + struct list_head links; /* interface->bundles */ +}; +#define to_gb_bundle(d) container_of(d, struct gb_bundle, dev) + +/* Greybus "private" definitions" */ +struct gb_bundle *gb_bundle_create(struct gb_interface *intf, u8 bundle_id, + u8 class); +int gb_bundle_add(struct gb_bundle *bundle); +void gb_bundle_destroy(struct gb_bundle *bundle); + +/* Bundle Runtime PM wrappers */ +#ifdef CONFIG_PM +static inline int gb_pm_runtime_get_sync(struct gb_bundle *bundle) +{ + int retval; + + retval = pm_runtime_get_sync(&bundle->dev); + if (retval < 0) { + dev_err(&bundle->dev, + "pm_runtime_get_sync failed: %d\n", retval); + pm_runtime_put_noidle(&bundle->dev); + return retval; + } + + return 0; +} + +static inline int gb_pm_runtime_put_autosuspend(struct gb_bundle *bundle) +{ + int retval; + + pm_runtime_mark_last_busy(&bundle->dev); + retval = pm_runtime_put_autosuspend(&bundle->dev); + + return retval; +} + +static inline void gb_pm_runtime_get_noresume(struct gb_bundle *bundle) +{ + pm_runtime_get_noresume(&bundle->dev); +} + +static inline void gb_pm_runtime_put_noidle(struct gb_bundle *bundle) +{ + pm_runtime_put_noidle(&bundle->dev); +} + +#else +static inline int gb_pm_runtime_get_sync(struct gb_bundle *bundle) +{ return 0; } +static inline int gb_pm_runtime_put_autosuspend(struct gb_bundle *bundle) +{ return 0; } + +static inline void gb_pm_runtime_get_noresume(struct gb_bundle *bundle) {} +static inline void gb_pm_runtime_put_noidle(struct gb_bundle *bundle) {} +#endif + +#endif /* __BUNDLE_H */ diff --git a/include/linux/greybus/connection.h b/include/linux/greybus/connection.h new file mode 100644 index 000000000000..d59b7fc1de3e --- /dev/null +++ b/include/linux/greybus/connection.h @@ -0,0 +1,131 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Greybus connections + * + * Copyright 2014 Google Inc. + * Copyright 2014 Linaro Ltd. + */ + +#ifndef __CONNECTION_H +#define __CONNECTION_H + +#include <linux/bits.h> +#include <linux/list.h> +#include <linux/kfifo.h> +#include <linux/kref.h> +#include <linux/workqueue.h> + +#define GB_CONNECTION_FLAG_CSD BIT(0) +#define GB_CONNECTION_FLAG_NO_FLOWCTRL BIT(1) +#define GB_CONNECTION_FLAG_OFFLOADED BIT(2) +#define GB_CONNECTION_FLAG_CDSI1 BIT(3) +#define GB_CONNECTION_FLAG_CONTROL BIT(4) +#define GB_CONNECTION_FLAG_HIGH_PRIO BIT(5) + +#define GB_CONNECTION_FLAG_CORE_MASK GB_CONNECTION_FLAG_CONTROL + +enum gb_connection_state { + GB_CONNECTION_STATE_DISABLED = 0, + GB_CONNECTION_STATE_ENABLED_TX = 1, + GB_CONNECTION_STATE_ENABLED = 2, + GB_CONNECTION_STATE_DISCONNECTING = 3, +}; + +struct gb_operation; + +typedef int (*gb_request_handler_t)(struct gb_operation *); + +struct gb_connection { + struct gb_host_device *hd; + struct gb_interface *intf; + struct gb_bundle *bundle; + struct kref kref; + u16 hd_cport_id; + u16 intf_cport_id; + + struct list_head hd_links; + struct list_head bundle_links; + + gb_request_handler_t handler; + unsigned long flags; + + struct mutex mutex; + spinlock_t lock; + enum gb_connection_state state; + struct list_head operations; + + char name[16]; + struct workqueue_struct *wq; + + atomic_t op_cycle; + + void *private; + + bool mode_switch; +}; + +struct gb_connection *gb_connection_create_static(struct gb_host_device *hd, + u16 hd_cport_id, gb_request_handler_t handler); +struct gb_connection *gb_connection_create_control(struct gb_interface *intf); +struct gb_connection *gb_connection_create(struct gb_bundle *bundle, + u16 cport_id, gb_request_handler_t handler); +struct gb_connection *gb_connection_create_flags(struct gb_bundle *bundle, + u16 cport_id, gb_request_handler_t handler, + unsigned long flags); +struct gb_connection *gb_connection_create_offloaded(struct gb_bundle *bundle, + u16 cport_id, unsigned long flags); +void gb_connection_destroy(struct gb_connection *connection); + +static inline bool gb_connection_is_static(struct gb_connection *connection) +{ + return !connection->intf; +} + +int gb_connection_enable(struct gb_connection *connection); +int gb_connection_enable_tx(struct gb_connection *connection); +void gb_connection_disable_rx(struct gb_connection *connection); +void gb_connection_disable(struct gb_connection *connection); +void gb_connection_disable_forced(struct gb_connection *connection); + +void gb_connection_mode_switch_prepare(struct gb_connection *connection); +void gb_connection_mode_switch_complete(struct gb_connection *connection); + +void greybus_data_rcvd(struct gb_host_device *hd, u16 cport_id, + u8 *data, size_t length); + +void gb_connection_latency_tag_enable(struct gb_connection *connection); +void gb_connection_latency_tag_disable(struct gb_connection *connection); + +static inline bool gb_connection_e2efc_enabled(struct gb_connection *connection) +{ + return !(connection->flags & GB_CONNECTION_FLAG_CSD); +} + +static inline bool +gb_connection_flow_control_disabled(struct gb_connection *connection) +{ + return connection->flags & GB_CONNECTION_FLAG_NO_FLOWCTRL; +} + +static inline bool gb_connection_is_offloaded(struct gb_connection *connection) +{ + return connection->flags & GB_CONNECTION_FLAG_OFFLOADED; +} + +static inline bool gb_connection_is_control(struct gb_connection *connection) +{ + return connection->flags & GB_CONNECTION_FLAG_CONTROL; +} + +static inline void *gb_connection_get_data(struct gb_connection *connection) +{ + return connection->private; +} + +static inline void gb_connection_set_data(struct gb_connection *connection, + void *data) +{ + connection->private = data; +} + +#endif /* __CONNECTION_H */ diff --git a/include/linux/greybus/control.h b/include/linux/greybus/control.h new file mode 100644 index 000000000000..da11fe871653 --- /dev/null +++ b/include/linux/greybus/control.h @@ -0,0 +1,60 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Greybus CPort control protocol + * + * Copyright 2015 Google Inc. + * Copyright 2015 Linaro Ltd. + */ + +#ifndef __CONTROL_H +#define __CONTROL_H + +#include <linux/types.h> +#include <linux/device.h> + +struct gb_control { + struct device dev; + struct gb_interface *intf; + + struct gb_connection *connection; + + u8 protocol_major; + u8 protocol_minor; + + bool has_bundle_activate; + bool has_bundle_version; + + char *vendor_string; + char *product_string; +}; +#define to_gb_control(d) container_of(d, struct gb_control, dev) + +struct gb_control *gb_control_create(struct gb_interface *intf); +int gb_control_enable(struct gb_control *control); +void gb_control_disable(struct gb_control *control); +int gb_control_suspend(struct gb_control *control); +int gb_control_resume(struct gb_control *control); +int gb_control_add(struct gb_control *control); +void gb_control_del(struct gb_control *control); +struct gb_control *gb_control_get(struct gb_control *control); +void gb_control_put(struct gb_control *control); + +int gb_control_get_bundle_versions(struct gb_control *control); +int gb_control_connected_operation(struct gb_control *control, u16 cport_id); +int gb_control_disconnected_operation(struct gb_control *control, u16 cport_id); +int gb_control_disconnecting_operation(struct gb_control *control, + u16 cport_id); +int gb_control_mode_switch_operation(struct gb_control *control); +void gb_control_mode_switch_prepare(struct gb_control *control); +void gb_control_mode_switch_complete(struct gb_control *control); +int gb_control_get_manifest_size_operation(struct gb_interface *intf); +int gb_control_get_manifest_operation(struct gb_interface *intf, void *manifest, + size_t size); +int gb_control_bundle_suspend(struct gb_control *control, u8 bundle_id); +int gb_control_bundle_resume(struct gb_control *control, u8 bundle_id); +int gb_control_bundle_deactivate(struct gb_control *control, u8 bundle_id); +int gb_control_bundle_activate(struct gb_control *control, u8 bundle_id); +int gb_control_interface_suspend_prepare(struct gb_control *control); +int gb_control_interface_deactivate_prepare(struct gb_control *control); +int gb_control_interface_hibernate_abort(struct gb_control *control); +#endif /* __CONTROL_H */ diff --git a/include/linux/greybus/greybus_id.h b/include/linux/greybus/greybus_id.h new file mode 100644 index 000000000000..f4c8440093e4 --- /dev/null +++ b/include/linux/greybus/greybus_id.h @@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* FIXME + * move this to include/linux/mod_devicetable.h when merging + */ + +#ifndef __LINUX_GREYBUS_ID_H +#define __LINUX_GREYBUS_ID_H + +#include <linux/types.h> +#include <linux/mod_devicetable.h> + + +struct greybus_bundle_id { + __u16 match_flags; + __u32 vendor; + __u32 product; + __u8 class; + + kernel_ulong_t driver_info __aligned(sizeof(kernel_ulong_t)); +}; + +/* Used to match the greybus_bundle_id */ +#define GREYBUS_ID_MATCH_VENDOR BIT(0) +#define GREYBUS_ID_MATCH_PRODUCT BIT(1) +#define GREYBUS_ID_MATCH_CLASS BIT(2) + +#endif /* __LINUX_GREYBUS_ID_H */ diff --git a/include/linux/greybus/greybus_manifest.h b/include/linux/greybus/greybus_manifest.h new file mode 100644 index 000000000000..6e62fe478712 --- /dev/null +++ b/include/linux/greybus/greybus_manifest.h @@ -0,0 +1,181 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Greybus manifest definition + * + * See "Greybus Application Protocol" document (version 0.1) for + * details on these values and structures. + * + * Copyright 2014-2015 Google Inc. + * Copyright 2014-2015 Linaro Ltd. + * + * Released under the GPLv2 and BSD licenses. + */ + +#ifndef __GREYBUS_MANIFEST_H +#define __GREYBUS_MANIFEST_H + +#include <linux/bits.h> +#include <linux/types.h> + +enum greybus_descriptor_type { + GREYBUS_TYPE_INVALID = 0x00, + GREYBUS_TYPE_INTERFACE = 0x01, + GREYBUS_TYPE_STRING = 0x02, + GREYBUS_TYPE_BUNDLE = 0x03, + GREYBUS_TYPE_CPORT = 0x04, +}; + +enum greybus_protocol { + GREYBUS_PROTOCOL_CONTROL = 0x00, + /* 0x01 is unused */ + GREYBUS_PROTOCOL_GPIO = 0x02, + GREYBUS_PROTOCOL_I2C = 0x03, + GREYBUS_PROTOCOL_UART = 0x04, + GREYBUS_PROTOCOL_HID = 0x05, + GREYBUS_PROTOCOL_USB = 0x06, + GREYBUS_PROTOCOL_SDIO = 0x07, + GREYBUS_PROTOCOL_POWER_SUPPLY = 0x08, + GREYBUS_PROTOCOL_PWM = 0x09, + /* 0x0a is unused */ + GREYBUS_PROTOCOL_SPI = 0x0b, + GREYBUS_PROTOCOL_DISPLAY = 0x0c, + GREYBUS_PROTOCOL_CAMERA_MGMT = 0x0d, + GREYBUS_PROTOCOL_SENSOR = 0x0e, + GREYBUS_PROTOCOL_LIGHTS = 0x0f, + GREYBUS_PROTOCOL_VIBRATOR = 0x10, + GREYBUS_PROTOCOL_LOOPBACK = 0x11, + GREYBUS_PROTOCOL_AUDIO_MGMT = 0x12, + GREYBUS_PROTOCOL_AUDIO_DATA = 0x13, + GREYBUS_PROTOCOL_SVC = 0x14, + GREYBUS_PROTOCOL_BOOTROM = 0x15, + GREYBUS_PROTOCOL_CAMERA_DATA = 0x16, + GREYBUS_PROTOCOL_FW_DOWNLOAD = 0x17, + GREYBUS_PROTOCOL_FW_MANAGEMENT = 0x18, + GREYBUS_PROTOCOL_AUTHENTICATION = 0x19, + GREYBUS_PROTOCOL_LOG = 0x1a, + /* ... */ + GREYBUS_PROTOCOL_RAW = 0xfe, + GREYBUS_PROTOCOL_VENDOR = 0xff, +}; + +enum greybus_class_type { + GREYBUS_CLASS_CONTROL = 0x00, + /* 0x01 is unused */ + /* 0x02 is unused */ + /* 0x03 is unused */ + /* 0x04 is unused */ + GREYBUS_CLASS_HID = 0x05, + /* 0x06 is unused */ + /* 0x07 is unused */ + GREYBUS_CLASS_POWER_SUPPLY = 0x08, + /* 0x09 is unused */ + GREYBUS_CLASS_BRIDGED_PHY = 0x0a, + /* 0x0b is unused */ + GREYBUS_CLASS_DISPLAY = 0x0c, + GREYBUS_CLASS_CAMERA = 0x0d, + GREYBUS_CLASS_SENSOR = 0x0e, + GREYBUS_CLASS_LIGHTS = 0x0f, + GREYBUS_CLASS_VIBRATOR = 0x10, + GREYBUS_CLASS_LOOPBACK = 0x11, + GREYBUS_CLASS_AUDIO = 0x12, + /* 0x13 is unused */ + /* 0x14 is unused */ + GREYBUS_CLASS_BOOTROM = 0x15, + GREYBUS_CLASS_FW_MANAGEMENT = 0x16, + GREYBUS_CLASS_LOG = 0x17, + /* ... */ + GREYBUS_CLASS_RAW = 0xfe, + GREYBUS_CLASS_VENDOR = 0xff, +}; + +enum { + GREYBUS_INTERFACE_FEATURE_TIMESYNC = BIT(0), +}; + +/* + * The string in a string descriptor is not NUL-terminated. The + * size of the descriptor will be rounded up to a multiple of 4 + * bytes, by padding the string with 0x00 bytes if necessary. + */ +struct greybus_descriptor_string { + __u8 length; + __u8 id; + __u8 string[0]; +} __packed; + +/* + * An interface descriptor describes information about an interface as a whole, + * *not* the functions within it. + */ +struct greybus_descriptor_interface { + __u8 vendor_stringid; + __u8 product_stringid; + __u8 features; + __u8 pad; +} __packed; + +/* + * An bundle descriptor defines an identification number and a class for + * each bundle. + * + * @id: Uniquely identifies a bundle within a interface, its sole purpose is to + * allow CPort descriptors to specify which bundle they are associated with. + * The first bundle will have id 0, second will have 1 and so on. + * + * The largest CPort id associated with an bundle (defined by a + * CPort descriptor in the manifest) is used to determine how to + * encode the device id and module number in UniPro packets + * that use the bundle. + * + * @class: It is used by kernel to know the functionality provided by the + * bundle and will be matched against drivers functinality while probing greybus + * driver. It should contain one of the values defined in + * 'enum greybus_class_type'. + * + */ +struct greybus_descriptor_bundle { + __u8 id; /* interface-relative id (0..) */ + __u8 class; + __u8 pad[2]; +} __packed; + +/* + * A CPort descriptor indicates the id of the bundle within the + * module it's associated with, along with the CPort id used to + * address the CPort. The protocol id defines the format of messages + * exchanged using the CPort. + */ +struct greybus_descriptor_cport { + __le16 id; + __u8 bundle; + __u8 protocol_id; /* enum greybus_protocol */ +} __packed; + +struct greybus_descriptor_header { + __le16 size; + __u8 type; /* enum greybus_descriptor_type */ + __u8 pad; +} __packed; + +struct greybus_descriptor { + struct greybus_descriptor_header header; + union { + struct greybus_descriptor_string string; + struct greybus_descriptor_interface interface; + struct greybus_descriptor_bundle bundle; + struct greybus_descriptor_cport cport; + }; +} __packed; + +struct greybus_manifest_header { + __le16 size; + __u8 version_major; + __u8 version_minor; +} __packed; + +struct greybus_manifest { + struct greybus_manifest_header header; + struct greybus_descriptor descriptors[0]; +} __packed; + +#endif /* __GREYBUS_MANIFEST_H */ diff --git a/include/linux/greybus/greybus_protocols.h b/include/linux/greybus/greybus_protocols.h new file mode 100644 index 000000000000..dfbc6c39a74b --- /dev/null +++ b/include/linux/greybus/greybus_protocols.h @@ -0,0 +1,2178 @@ +/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ +/* + * Copyright(c) 2014 - 2015 Google Inc. All rights reserved. + * Copyright(c) 2014 - 2015 Linaro Ltd. All rights reserved. + */ + +#ifndef __GREYBUS_PROTOCOLS_H +#define __GREYBUS_PROTOCOLS_H + +#include <linux/types.h> + +/* Fixed IDs for control/svc protocols */ + +/* SVC switch-port device ids */ +#define GB_SVC_DEVICE_ID_SVC 0 +#define GB_SVC_DEVICE_ID_AP 1 +#define GB_SVC_DEVICE_ID_MIN 2 +#define GB_SVC_DEVICE_ID_MAX 31 + +#define GB_SVC_CPORT_ID 0 +#define GB_CONTROL_BUNDLE_ID 0 +#define GB_CONTROL_CPORT_ID 0 + + +/* + * All operation messages (both requests and responses) begin with + * a header that encodes the size of the message (header included). + * This header also contains a unique identifier, that associates a + * response message with its operation. The header contains an + * operation type field, whose interpretation is dependent on what + * type of protocol is used over the connection. The high bit + * (0x80) of the operation type field is used to indicate whether + * the message is a request (clear) or a response (set). + * + * Response messages include an additional result byte, which + * communicates the result of the corresponding request. A zero + * result value means the operation completed successfully. Any + * other value indicates an error; in this case, the payload of the + * response message (if any) is ignored. The result byte must be + * zero in the header for a request message. + * + * The wire format for all numeric fields in the header is little + * endian. Any operation-specific data begins immediately after the + * header. + */ +struct gb_operation_msg_hdr { + __le16 size; /* Size in bytes of header + payload */ + __le16 operation_id; /* Operation unique id */ + __u8 type; /* E.g GB_I2C_TYPE_* or GB_GPIO_TYPE_* */ + __u8 result; /* Result of request (in responses only) */ + __u8 pad[2]; /* must be zero (ignore when read) */ +} __packed; + + +/* Generic request types */ +#define GB_REQUEST_TYPE_CPORT_SHUTDOWN 0x00 +#define GB_REQUEST_TYPE_INVALID 0x7f + +struct gb_cport_shutdown_request { + __u8 phase; +} __packed; + + +/* Control Protocol */ + +/* Greybus control request types */ +#define GB_CONTROL_TYPE_VERSION 0x01 +#define GB_CONTROL_TYPE_PROBE_AP 0x02 +#define GB_CONTROL_TYPE_GET_MANIFEST_SIZE 0x03 +#define GB_CONTROL_TYPE_GET_MANIFEST 0x04 +#define GB_CONTROL_TYPE_CONNECTED 0x05 +#define GB_CONTROL_TYPE_DISCONNECTED 0x06 +#define GB_CONTROL_TYPE_TIMESYNC_ENABLE 0x07 +#define GB_CONTROL_TYPE_TIMESYNC_DISABLE 0x08 +#define GB_CONTROL_TYPE_TIMESYNC_AUTHORITATIVE 0x09 +/* Unused 0x0a */ +#define GB_CONTROL_TYPE_BUNDLE_VERSION 0x0b +#define GB_CONTROL_TYPE_DISCONNECTING 0x0c +#define GB_CONTROL_TYPE_TIMESYNC_GET_LAST_EVENT 0x0d +#define GB_CONTROL_TYPE_MODE_SWITCH 0x0e +#define GB_CONTROL_TYPE_BUNDLE_SUSPEND 0x0f +#define GB_CONTROL_TYPE_BUNDLE_RESUME 0x10 +#define GB_CONTROL_TYPE_BUNDLE_DEACTIVATE 0x11 +#define GB_CONTROL_TYPE_BUNDLE_ACTIVATE 0x12 +#define GB_CONTROL_TYPE_INTF_SUSPEND_PREPARE 0x13 +#define GB_CONTROL_TYPE_INTF_DEACTIVATE_PREPARE 0x14 +#define GB_CONTROL_TYPE_INTF_HIBERNATE_ABORT 0x15 + +struct gb_control_version_request { + __u8 major; + __u8 minor; +} __packed; + +struct gb_control_version_response { + __u8 major; + __u8 minor; +} __packed; + +struct gb_control_bundle_version_request { + __u8 bundle_id; +} __packed; + +struct gb_control_bundle_version_response { + __u8 major; + __u8 minor; +} __packed; + +/* Control protocol manifest get size request has no payload*/ +struct gb_control_get_manifest_size_response { + __le16 size; +} __packed; + +/* Control protocol manifest get request has no payload */ +struct gb_control_get_manifest_response { + __u8 data[0]; +} __packed; + +/* Control protocol [dis]connected request */ +struct gb_control_connected_request { + __le16 cport_id; +} __packed; + +struct gb_control_disconnecting_request { + __le16 cport_id; +} __packed; +/* disconnecting response has no payload */ + +struct gb_control_disconnected_request { + __le16 cport_id; +} __packed; +/* Control protocol [dis]connected response has no payload */ + +/* + * All Bundle power management operations use the same request and response + * layout and status codes. + */ + +#define GB_CONTROL_BUNDLE_PM_OK 0x00 +#define GB_CONTROL_BUNDLE_PM_INVAL 0x01 +#define GB_CONTROL_BUNDLE_PM_BUSY 0x02 +#define GB_CONTROL_BUNDLE_PM_FAIL 0x03 +#define GB_CONTROL_BUNDLE_PM_NA 0x04 + +struct gb_control_bundle_pm_request { + __u8 bundle_id; +} __packed; + +struct gb_control_bundle_pm_response { + __u8 status; +} __packed; + +/* + * Interface Suspend Prepare and Deactivate Prepare operations use the same + * response layout and error codes. Define a single response structure and reuse + * it. Both operations have no payload. + */ + +#define GB_CONTROL_INTF_PM_OK 0x00 +#define GB_CONTROL_INTF_PM_BUSY 0x01 +#define GB_CONTROL_INTF_PM_NA 0x02 + +struct gb_control_intf_pm_response { + __u8 status; +} __packed; + +/* APBridge protocol */ + +/* request APB1 log */ +#define GB_APB_REQUEST_LOG 0x02 + +/* request to map a cport to bulk in and bulk out endpoints */ +#define GB_APB_REQUEST_EP_MAPPING 0x03 + +/* request to get the number of cports available */ +#define GB_APB_REQUEST_CPORT_COUNT 0x04 + +/* request to reset a cport state */ +#define GB_APB_REQUEST_RESET_CPORT 0x05 + +/* request to time the latency of messages on a given cport */ +#define GB_APB_REQUEST_LATENCY_TAG_EN 0x06 +#define GB_APB_REQUEST_LATENCY_TAG_DIS 0x07 + +/* request to control the CSI transmitter */ +#define GB_APB_REQUEST_CSI_TX_CONTROL 0x08 + +/* request to control audio streaming */ +#define GB_APB_REQUEST_AUDIO_CONTROL 0x09 + +/* TimeSync requests */ +#define GB_APB_REQUEST_TIMESYNC_ENABLE 0x0d +#define GB_APB_REQUEST_TIMESYNC_DISABLE 0x0e +#define GB_APB_REQUEST_TIMESYNC_AUTHORITATIVE 0x0f +#define GB_APB_REQUEST_TIMESYNC_GET_LAST_EVENT 0x10 + +/* requests to set Greybus CPort flags */ +#define GB_APB_REQUEST_CPORT_FLAGS 0x11 + +/* ARPC request */ +#define GB_APB_REQUEST_ARPC_RUN 0x12 + +struct gb_apb_request_cport_flags { + __le32 flags; +#define GB_APB_CPORT_FLAG_CONTROL 0x01 +#define GB_APB_CPORT_FLAG_HIGH_PRIO 0x02 +} __packed; + + +/* Firmware Download Protocol */ + +/* Request Types */ +#define GB_FW_DOWNLOAD_TYPE_FIND_FIRMWARE 0x01 +#define GB_FW_DOWNLOAD_TYPE_FETCH_FIRMWARE 0x02 +#define GB_FW_DOWNLOAD_TYPE_RELEASE_FIRMWARE 0x03 + +#define GB_FIRMWARE_TAG_MAX_SIZE 10 + +/* firmware download find firmware request/response */ +struct gb_fw_download_find_firmware_request { + __u8 firmware_tag[GB_FIRMWARE_TAG_MAX_SIZE]; +} __packed; + +struct gb_fw_download_find_firmware_response { + __u8 firmware_id; + __le32 size; +} __packed; + +/* firmware download fetch firmware request/response */ +struct gb_fw_download_fetch_firmware_request { + __u8 firmware_id; + __le32 offset; + __le32 size; +} __packed; + +struct gb_fw_download_fetch_firmware_response { + __u8 data[0]; +} __packed; + +/* firmware download release firmware request */ +struct gb_fw_download_release_firmware_request { + __u8 firmware_id; +} __packed; +/* firmware download release firmware response has no payload */ + + +/* Firmware Management Protocol */ + +/* Request Types */ +#define GB_FW_MGMT_TYPE_INTERFACE_FW_VERSION 0x01 +#define GB_FW_MGMT_TYPE_LOAD_AND_VALIDATE_FW 0x02 +#define GB_FW_MGMT_TYPE_LOADED_FW 0x03 +#define GB_FW_MGMT_TYPE_BACKEND_FW_VERSION 0x04 +#define GB_FW_MGMT_TYPE_BACKEND_FW_UPDATE 0x05 +#define GB_FW_MGMT_TYPE_BACKEND_FW_UPDATED 0x06 + +#define GB_FW_LOAD_METHOD_UNIPRO 0x01 +#define GB_FW_LOAD_METHOD_INTERNAL 0x02 + +#define GB_FW_LOAD_STATUS_FAILED 0x00 +#define GB_FW_LOAD_STATUS_UNVALIDATED 0x01 +#define GB_FW_LOAD_STATUS_VALIDATED 0x02 +#define GB_FW_LOAD_STATUS_VALIDATION_FAILED 0x03 + +#define GB_FW_BACKEND_FW_STATUS_SUCCESS 0x01 +#define GB_FW_BACKEND_FW_STATUS_FAIL_FIND 0x02 +#define GB_FW_BACKEND_FW_STATUS_FAIL_FETCH 0x03 +#define GB_FW_BACKEND_FW_STATUS_FAIL_WRITE 0x04 +#define GB_FW_BACKEND_FW_STATUS_INT 0x05 +#define GB_FW_BACKEND_FW_STATUS_RETRY 0x06 +#define GB_FW_BACKEND_FW_STATUS_NOT_SUPPORTED 0x07 + +#define GB_FW_BACKEND_VERSION_STATUS_SUCCESS 0x01 +#define GB_FW_BACKEND_VERSION_STATUS_NOT_AVAILABLE 0x02 +#define GB_FW_BACKEND_VERSION_STATUS_NOT_SUPPORTED 0x03 +#define GB_FW_BACKEND_VERSION_STATUS_RETRY 0x04 +#define GB_FW_BACKEND_VERSION_STATUS_FAIL_INT 0x05 + +/* firmware management interface firmware version request has no payload */ +struct gb_fw_mgmt_interface_fw_version_response { + __u8 firmware_tag[GB_FIRMWARE_TAG_MAX_SIZE]; + __le16 major; + __le16 minor; +} __packed; + +/* firmware management load and validate firmware request/response */ +struct gb_fw_mgmt_load_and_validate_fw_request { + __u8 request_id; + __u8 load_method; + __u8 firmware_tag[GB_FIRMWARE_TAG_MAX_SIZE]; +} __packed; +/* firmware management load and validate firmware response has no payload*/ + +/* firmware management loaded firmware request */ +struct gb_fw_mgmt_loaded_fw_request { + __u8 request_id; + __u8 status; + __le16 major; + __le16 minor; +} __packed; +/* firmware management loaded firmware response has no payload */ + +/* firmware management backend firmware version request/response */ +struct gb_fw_mgmt_backend_fw_version_request { + __u8 firmware_tag[GB_FIRMWARE_TAG_MAX_SIZE]; +} __packed; + +struct gb_fw_mgmt_backend_fw_version_response { + __le16 major; + __le16 minor; + __u8 status; +} __packed; + +/* firmware management backend firmware update request */ +struct gb_fw_mgmt_backend_fw_update_request { + __u8 request_id; + __u8 firmware_tag[GB_FIRMWARE_TAG_MAX_SIZE]; +} __packed; +/* firmware management backend firmware update response has no payload */ + +/* firmware management backend firmware updated request */ +struct gb_fw_mgmt_backend_fw_updated_request { + __u8 request_id; + __u8 status; +} __packed; +/* firmware management backend firmware updated response has no payload */ + + +/* Component Authentication Protocol (CAP) */ + +/* Request Types */ +#define GB_CAP_TYPE_GET_ENDPOINT_UID 0x01 +#define GB_CAP_TYPE_GET_IMS_CERTIFICATE 0x02 +#define GB_CAP_TYPE_AUTHENTICATE 0x03 + +/* CAP get endpoint uid request has no payload */ +struct gb_cap_get_endpoint_uid_response { + __u8 uid[8]; +} __packed; + +/* CAP get endpoint ims certificate request/response */ +struct gb_cap_get_ims_certificate_request { + __le32 certificate_class; + __le32 certificate_id; +} __packed; + +struct gb_cap_get_ims_certificate_response { + __u8 result_code; + __u8 certificate[0]; +} __packed; + +/* CAP authenticate request/response */ +struct gb_cap_authenticate_request { + __le32 auth_type; + __u8 uid[8]; + __u8 challenge[32]; +} __packed; + +struct gb_cap_authenticate_response { + __u8 result_code; + __u8 response[64]; + __u8 signature[0]; +} __packed; + + +/* Bootrom Protocol */ + +/* Version of the Greybus bootrom protocol we support */ +#define GB_BOOTROM_VERSION_MAJOR 0x00 +#define GB_BOOTROM_VERSION_MINOR 0x01 + +/* Greybus bootrom request types */ +#define GB_BOOTROM_TYPE_VERSION 0x01 +#define GB_BOOTROM_TYPE_FIRMWARE_SIZE 0x02 +#define GB_BOOTROM_TYPE_GET_FIRMWARE 0x03 +#define GB_BOOTROM_TYPE_READY_TO_BOOT 0x04 +#define GB_BOOTROM_TYPE_AP_READY 0x05 /* Request with no-payload */ +#define GB_BOOTROM_TYPE_GET_VID_PID 0x06 /* Request with no-payload */ + +/* Greybus bootrom boot stages */ +#define GB_BOOTROM_BOOT_STAGE_ONE 0x01 /* Reserved for the boot ROM */ +#define GB_BOOTROM_BOOT_STAGE_TWO 0x02 /* Bootrom package to be loaded by the boot ROM */ +#define GB_BOOTROM_BOOT_STAGE_THREE 0x03 /* Module personality package loaded by Stage 2 firmware */ + +/* Greybus bootrom ready to boot status */ +#define GB_BOOTROM_BOOT_STATUS_INVALID 0x00 /* Firmware blob could not be validated */ +#define GB_BOOTROM_BOOT_STATUS_INSECURE 0x01 /* Firmware blob is valid but insecure */ +#define GB_BOOTROM_BOOT_STATUS_SECURE 0x02 /* Firmware blob is valid and secure */ + +/* Max bootrom data fetch size in bytes */ +#define GB_BOOTROM_FETCH_MAX 2000 + +struct gb_bootrom_version_request { + __u8 major; + __u8 minor; +} __packed; + +struct gb_bootrom_version_response { + __u8 major; + __u8 minor; +} __packed; + +/* Bootrom protocol firmware size request/response */ +struct gb_bootrom_firmware_size_request { + __u8 stage; +} __packed; + +struct gb_bootrom_firmware_size_response { + __le32 size; +} __packed; + +/* Bootrom protocol get firmware request/response */ +struct gb_bootrom_get_firmware_request { + __le32 offset; + __le32 size; +} __packed; + +struct gb_bootrom_get_firmware_response { + __u8 data[0]; +} __packed; + +/* Bootrom protocol Ready to boot request */ +struct gb_bootrom_ready_to_boot_request { + __u8 status; +} __packed; +/* Bootrom protocol Ready to boot response has no payload */ + +/* Bootrom protocol get VID/PID request has no payload */ +struct gb_bootrom_get_vid_pid_response { + __le32 vendor_id; + __le32 product_id; +} __packed; + + +/* Power Supply */ + +/* Greybus power supply request types */ +#define GB_POWER_SUPPLY_TYPE_GET_SUPPLIES 0x02 +#define GB_POWER_SUPPLY_TYPE_GET_DESCRIPTION 0x03 +#define GB_POWER_SUPPLY_TYPE_GET_PROP_DESCRIPTORS 0x04 +#define GB_POWER_SUPPLY_TYPE_GET_PROPERTY 0x05 +#define GB_POWER_SUPPLY_TYPE_SET_PROPERTY 0x06 +#define GB_POWER_SUPPLY_TYPE_EVENT 0x07 + +/* Greybus power supply battery technologies types */ +#define GB_POWER_SUPPLY_TECH_UNKNOWN 0x0000 +#define GB_POWER_SUPPLY_TECH_NiMH 0x0001 +#define GB_POWER_SUPPLY_TECH_LION 0x0002 +#define GB_POWER_SUPPLY_TECH_LIPO 0x0003 +#define GB_POWER_SUPPLY_TECH_LiFe 0x0004 +#define GB_POWER_SUPPLY_TECH_NiCd 0x0005 +#define GB_POWER_SUPPLY_TECH_LiMn 0x0006 + +/* Greybus power supply types */ +#define GB_POWER_SUPPLY_UNKNOWN_TYPE 0x0000 +#define GB_POWER_SUPPLY_BATTERY_TYPE 0x0001 +#define GB_POWER_SUPPLY_UPS_TYPE 0x0002 +#define GB_POWER_SUPPLY_MAINS_TYPE 0x0003 +#define GB_POWER_SUPPLY_USB_TYPE 0x0004 +#define GB_POWER_SUPPLY_USB_DCP_TYPE 0x0005 +#define GB_POWER_SUPPLY_USB_CDP_TYPE 0x0006 +#define GB_POWER_SUPPLY_USB_ACA_TYPE 0x0007 + +/* Greybus power supply health values */ +#define GB_POWER_SUPPLY_HEALTH_UNKNOWN 0x0000 +#define GB_POWER_SUPPLY_HEALTH_GOOD 0x0001 +#define GB_POWER_SUPPLY_HEALTH_OVERHEAT 0x0002 +#define GB_POWER_SUPPLY_HEALTH_DEAD 0x0003 +#define GB_POWER_SUPPLY_HEALTH_OVERVOLTAGE 0x0004 +#define GB_POWER_SUPPLY_HEALTH_UNSPEC_FAILURE 0x0005 +#define GB_POWER_SUPPLY_HEALTH_COLD 0x0006 +#define GB_POWER_SUPPLY_HEALTH_WATCHDOG_TIMER_EXPIRE 0x0007 +#define GB_POWER_SUPPLY_HEALTH_SAFETY_TIMER_EXPIRE 0x0008 + +/* Greybus power supply status values */ +#define GB_POWER_SUPPLY_STATUS_UNKNOWN 0x0000 +#define GB_POWER_SUPPLY_STATUS_CHARGING 0x0001 +#define GB_POWER_SUPPLY_STATUS_DISCHARGING 0x0002 +#define GB_POWER_SUPPLY_STATUS_NOT_CHARGING 0x0003 +#define GB_POWER_SUPPLY_STATUS_FULL 0x0004 + +/* Greybus power supply capacity level values */ +#define GB_POWER_SUPPLY_CAPACITY_LEVEL_UNKNOWN 0x0000 +#define GB_POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL 0x0001 +#define GB_POWER_SUPPLY_CAPACITY_LEVEL_LOW 0x0002 +#define GB_POWER_SUPPLY_CAPACITY_LEVEL_NORMAL 0x0003 +#define GB_POWER_SUPPLY_CAPACITY_LEVEL_HIGH 0x0004 +#define GB_POWER_SUPPLY_CAPACITY_LEVEL_FULL 0x0005 + +/* Greybus power supply scope values */ +#define GB_POWER_SUPPLY_SCOPE_UNKNOWN 0x0000 +#define GB_POWER_SUPPLY_SCOPE_SYSTEM 0x0001 +#define GB_POWER_SUPPLY_SCOPE_DEVICE 0x0002 + +struct gb_power_supply_get_supplies_response { + __u8 supplies_count; +} __packed; + +struct gb_power_supply_get_description_request { + __u8 psy_id; +} __packed; + +struct gb_power_supply_get_description_response { + __u8 manufacturer[32]; + __u8 model[32]; + __u8 serial_number[32]; + __le16 type; + __u8 properties_count; +} __packed; + +struct gb_power_supply_props_desc { + __u8 property; +#define GB_POWER_SUPPLY_PROP_STATUS 0x00 +#define GB_POWER_SUPPLY_PROP_CHARGE_TYPE 0x01 +#define GB_POWER_SUPPLY_PROP_HEALTH 0x02 +#define GB_POWER_SUPPLY_PROP_PRESENT 0x03 +#define GB_POWER_SUPPLY_PROP_ONLINE 0x04 +#define GB_POWER_SUPPLY_PROP_AUTHENTIC 0x05 +#define GB_POWER_SUPPLY_PROP_TECHNOLOGY 0x06 +#define GB_POWER_SUPPLY_PROP_CYCLE_COUNT 0x07 +#define GB_POWER_SUPPLY_PROP_VOLTAGE_MAX 0x08 +#define GB_POWER_SUPPLY_PROP_VOLTAGE_MIN 0x09 +#define GB_POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN 0x0A +#define GB_POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN 0x0B +#define GB_POWER_SUPPLY_PROP_VOLTAGE_NOW 0x0C +#define GB_POWER_SUPPLY_PROP_VOLTAGE_AVG 0x0D +#define GB_POWER_SUPPLY_PROP_VOLTAGE_OCV 0x0E +#define GB_POWER_SUPPLY_PROP_VOLTAGE_BOOT 0x0F +#define GB_POWER_SUPPLY_PROP_CURRENT_MAX 0x10 +#define GB_POWER_SUPPLY_PROP_CURRENT_NOW 0x11 +#define GB_POWER_SUPPLY_PROP_CURRENT_AVG 0x12 +#define GB_POWER_SUPPLY_PROP_CURRENT_BOOT 0x13 +#define GB_POWER_SUPPLY_PROP_POWER_NOW 0x14 +#define GB_POWER_SUPPLY_PROP_POWER_AVG 0x15 +#define GB_POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN 0x16 +#define GB_POWER_SUPPLY_PROP_CHARGE_EMPTY_DESIGN 0x17 +#define GB_POWER_SUPPLY_PROP_CHARGE_FULL 0x18 +#define GB_POWER_SUPPLY_PROP_CHARGE_EMPTY 0x19 +#define GB_POWER_SUPPLY_PROP_CHARGE_NOW 0x1A +#define GB_POWER_SUPPLY_PROP_CHARGE_AVG 0x1B +#define GB_POWER_SUPPLY_PROP_CHARGE_COUNTER 0x1C +#define GB_POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT 0x1D +#define GB_POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX 0x1E +#define GB_POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE 0x1F +#define GB_POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX 0x20 +#define GB_POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT 0x21 +#define GB_POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT_MAX 0x22 +#define GB_POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT 0x23 +#define GB_POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN 0x24 +#define GB_POWER_SUPPLY_PROP_ENERGY_EMPTY_DESIGN 0x25 +#define GB_POWER_SUPPLY_PROP_ENERGY_FULL 0x26 +#define GB_POWER_SUPPLY_PROP_ENERGY_EMPTY 0x27 +#define GB_POWER_SUPPLY_PROP_ENERGY_NOW 0x28 +#define GB_POWER_SUPPLY_PROP_ENERGY_AVG 0x29 +#define GB_POWER_SUPPLY_PROP_CAPACITY 0x2A +#define GB_POWER_SUPPLY_PROP_CAPACITY_ALERT_MIN 0x2B +#define GB_POWER_SUPPLY_PROP_CAPACITY_ALERT_MAX 0x2C +#define GB_POWER_SUPPLY_PROP_CAPACITY_LEVEL 0x2D +#define GB_POWER_SUPPLY_PROP_TEMP 0x2E +#define GB_POWER_SUPPLY_PROP_TEMP_MAX 0x2F +#define GB_POWER_SUPPLY_PROP_TEMP_MIN 0x30 +#define GB_POWER_SUPPLY_PROP_TEMP_ALERT_MIN 0x31 +#define GB_POWER_SUPPLY_PROP_TEMP_ALERT_MAX 0x32 +#define GB_POWER_SUPPLY_PROP_TEMP_AMBIENT 0x33 +#define GB_POWER_SUPPLY_PROP_TEMP_AMBIENT_ALERT_MIN 0x34 +#define GB_POWER_SUPPLY_PROP_TEMP_AMBIENT_ALERT_MAX 0x35 +#define GB_POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW 0x36 +#define GB_POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG 0x37 +#define GB_POWER_SUPPLY_PROP_TIME_TO_FULL_NOW 0x38 +#define GB_POWER_SUPPLY_PROP_TIME_TO_FULL_AVG 0x39 +#define GB_POWER_SUPPLY_PROP_TYPE 0x3A +#define GB_POWER_SUPPLY_PROP_SCOPE 0x3B +#define GB_POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT 0x3C +#define GB_POWER_SUPPLY_PROP_CALIBRATE 0x3D + __u8 is_writeable; +} __packed; + +struct gb_power_supply_get_property_descriptors_request { + __u8 psy_id; +} __packed; + +struct gb_power_supply_get_property_descriptors_response { + __u8 properties_count; + struct gb_power_supply_props_desc props[]; +} __packed; + +struct gb_power_supply_get_property_request { + __u8 psy_id; + __u8 property; +} __packed; + +struct gb_power_supply_get_property_response { + __le32 prop_val; +}; + +struct gb_power_supply_set_property_request { + __u8 psy_id; + __u8 property; + __le32 prop_val; +} __packed; + +struct gb_power_supply_event_request { + __u8 psy_id; + __u8 event; +#define GB_POWER_SUPPLY_UPDATE 0x01 +} __packed; + + +/* HID */ + +/* Greybus HID operation types */ +#define GB_HID_TYPE_GET_DESC 0x02 +#define GB_HID_TYPE_GET_REPORT_DESC 0x03 +#define GB_HID_TYPE_PWR_ON 0x04 +#define GB_HID_TYPE_PWR_OFF 0x05 +#define GB_HID_TYPE_GET_REPORT 0x06 +#define GB_HID_TYPE_SET_REPORT 0x07 +#define GB_HID_TYPE_IRQ_EVENT 0x08 + +/* Report type */ +#define GB_HID_INPUT_REPORT 0 +#define GB_HID_OUTPUT_REPORT 1 +#define GB_HID_FEATURE_REPORT 2 + +/* Different request/response structures */ +/* HID get descriptor response */ +struct gb_hid_desc_response { + __u8 bLength; + __le16 wReportDescLength; + __le16 bcdHID; + __le16 wProductID; + __le16 wVendorID; + __u8 bCountryCode; +} __packed; + +/* HID get report request/response */ +struct gb_hid_get_report_request { + __u8 report_type; + __u8 report_id; +} __packed; + +/* HID set report request */ +struct gb_hid_set_report_request { + __u8 report_type; + __u8 report_id; + __u8 report[0]; +} __packed; + +/* HID input report request, via interrupt pipe */ +struct gb_hid_input_report_request { + __u8 report[0]; +} __packed; + + +/* I2C */ + +/* Greybus i2c request types */ +#define GB_I2C_TYPE_FUNCTIONALITY 0x02 +#define GB_I2C_TYPE_TRANSFER 0x05 + +/* functionality request has no payload */ +struct gb_i2c_functionality_response { + __le32 functionality; +} __packed; + +/* + * Outgoing data immediately follows the op count and ops array. + * The data for each write (master -> slave) op in the array is sent + * in order, with no (e.g. pad) bytes separating them. + * + * Short reads cause the entire transfer request to fail So response + * payload consists only of bytes read, and the number of bytes is + * exactly what was specified in the corresponding op. Like + * outgoing data, the incoming data is in order and contiguous. + */ +struct gb_i2c_transfer_op { + __le16 addr; + __le16 flags; + __le16 size; +} __packed; + +struct gb_i2c_transfer_request { + __le16 op_count; + struct gb_i2c_transfer_op ops[0]; /* op_count of these */ +} __packed; +struct gb_i2c_transfer_response { + __u8 data[0]; /* inbound data */ +} __packed; + + +/* GPIO */ + +/* Greybus GPIO request types */ +#define GB_GPIO_TYPE_LINE_COUNT 0x02 +#define GB_GPIO_TYPE_ACTIVATE 0x03 +#define GB_GPIO_TYPE_DEACTIVATE 0x04 +#define GB_GPIO_TYPE_GET_DIRECTION 0x05 +#define GB_GPIO_TYPE_DIRECTION_IN 0x06 +#define GB_GPIO_TYPE_DIRECTION_OUT 0x07 +#define GB_GPIO_TYPE_GET_VALUE 0x08 +#define GB_GPIO_TYPE_SET_VALUE 0x09 +#define GB_GPIO_TYPE_SET_DEBOUNCE 0x0a +#define GB_GPIO_TYPE_IRQ_TYPE 0x0b +#define GB_GPIO_TYPE_IRQ_MASK 0x0c +#define GB_GPIO_TYPE_IRQ_UNMASK 0x0d +#define GB_GPIO_TYPE_IRQ_EVENT 0x0e + +#define GB_GPIO_IRQ_TYPE_NONE 0x00 +#define GB_GPIO_IRQ_TYPE_EDGE_RISING 0x01 +#define GB_GPIO_IRQ_TYPE_EDGE_FALLING 0x02 +#define GB_GPIO_IRQ_TYPE_EDGE_BOTH 0x03 +#define GB_GPIO_IRQ_TYPE_LEVEL_HIGH 0x04 +#define GB_GPIO_IRQ_TYPE_LEVEL_LOW 0x08 + +/* line count request has no payload */ +struct gb_gpio_line_count_response { + __u8 count; +} __packed; + +struct gb_gpio_activate_request { + __u8 which; +} __packed; +/* activate response has no payload */ + +struct gb_gpio_deactivate_request { + __u8 which; +} __packed; +/* deactivate response has no payload */ + +struct gb_gpio_get_direction_request { + __u8 which; +} __packed; +struct gb_gpio_get_direction_response { + __u8 direction; +} __packed; + +struct gb_gpio_direction_in_request { + __u8 which; +} __packed; +/* direction in response has no payload */ + +struct gb_gpio_direction_out_request { + __u8 which; + __u8 value; +} __packed; +/* direction out response has no payload */ + +struct gb_gpio_get_value_request { + __u8 which; +} __packed; +struct gb_gpio_get_value_response { + __u8 value; +} __packed; + +struct gb_gpio_set_value_request { + __u8 which; + __u8 value; +} __packed; +/* set value response has no payload */ + +struct gb_gpio_set_debounce_request { + __u8 which; + __le16 usec; +} __packed; +/* debounce response has no payload */ + +struct gb_gpio_irq_type_request { + __u8 which; + __u8 type; +} __packed; +/* irq type response has no payload */ + +struct gb_gpio_irq_mask_request { + __u8 which; +} __packed; +/* irq mask response has no payload */ + +struct gb_gpio_irq_unmask_request { + __u8 which; +} __packed; +/* irq unmask response has no payload */ + +/* irq event requests originate on another module and are handled on the AP */ +struct gb_gpio_irq_event_request { + __u8 which; +} __packed; +/* irq event has no response */ + + +/* PWM */ + +/* Greybus PWM operation types */ +#define GB_PWM_TYPE_PWM_COUNT 0x02 +#define GB_PWM_TYPE_ACTIVATE 0x03 +#define GB_PWM_TYPE_DEACTIVATE 0x04 +#define GB_PWM_TYPE_CONFIG 0x05 +#define GB_PWM_TYPE_POLARITY 0x06 +#define GB_PWM_TYPE_ENABLE 0x07 +#define GB_PWM_TYPE_DISABLE 0x08 + +/* pwm count request has no payload */ +struct gb_pwm_count_response { + __u8 count; +} __packed; + +struct gb_pwm_activate_request { + __u8 which; +} __packed; + +struct gb_pwm_deactivate_request { + __u8 which; +} __packed; + +struct gb_pwm_config_request { + __u8 which; + __le32 duty; + __le32 period; +} __packed; + +struct gb_pwm_polarity_request { + __u8 which; + __u8 polarity; +} __packed; + +struct gb_pwm_enable_request { + __u8 which; +} __packed; + +struct gb_pwm_disable_request { + __u8 which; +} __packed; + +/* SPI */ + +/* Should match up with modes in linux/spi/spi.h */ +#define GB_SPI_MODE_CPHA 0x01 /* clock phase */ +#define GB_SPI_MODE_CPOL 0x02 /* clock polarity */ +#define GB_SPI_MODE_MODE_0 (0 | 0) /* (original MicroWire) */ +#define GB_SPI_MODE_MODE_1 (0 | GB_SPI_MODE_CPHA) +#define GB_SPI_MODE_MODE_2 (GB_SPI_MODE_CPOL | 0) +#define GB_SPI_MODE_MODE_3 (GB_SPI_MODE_CPOL | GB_SPI_MODE_CPHA) +#define GB_SPI_MODE_CS_HIGH 0x04 /* chipselect active high? */ +#define GB_SPI_MODE_LSB_FIRST 0x08 /* per-word bits-on-wire */ +#define GB_SPI_MODE_3WIRE 0x10 /* SI/SO signals shared */ +#define GB_SPI_MODE_LOOP 0x20 /* loopback mode */ +#define GB_SPI_MODE_NO_CS 0x40 /* 1 dev/bus, no chipselect */ +#define GB_SPI_MODE_READY 0x80 /* slave pulls low to pause */ + +/* Should match up with flags in linux/spi/spi.h */ +#define GB_SPI_FLAG_HALF_DUPLEX BIT(0) /* can't do full duplex */ +#define GB_SPI_FLAG_NO_RX BIT(1) /* can't do buffer read */ +#define GB_SPI_FLAG_NO_TX BIT(2) /* can't do buffer write */ + +/* Greybus spi operation types */ +#define GB_SPI_TYPE_MASTER_CONFIG 0x02 +#define GB_SPI_TYPE_DEVICE_CONFIG 0x03 +#define GB_SPI_TYPE_TRANSFER 0x04 + +/* mode request has no payload */ +struct gb_spi_master_config_response { + __le32 bits_per_word_mask; + __le32 min_speed_hz; + __le32 max_speed_hz; + __le16 mode; + __le16 flags; + __u8 num_chipselect; +} __packed; + +struct gb_spi_device_config_request { + __u8 chip_select; +} __packed; + +struct gb_spi_device_config_response { + __le16 mode; + __u8 bits_per_word; + __le32 max_speed_hz; + __u8 device_type; +#define GB_SPI_SPI_DEV 0x00 +#define GB_SPI_SPI_NOR 0x01 +#define GB_SPI_SPI_MODALIAS 0x02 + __u8 name[32]; +} __packed; + +/** + * struct gb_spi_transfer - a read/write buffer pair + * @speed_hz: Select a speed other than the device default for this transfer. If + * 0 the default (from @spi_device) is used. + * @len: size of rx and tx buffers (in bytes) + * @delay_usecs: microseconds to delay after this transfer before (optionally) + * changing the chipselect status, then starting the next transfer or + * completing this spi_message. + * @cs_change: affects chipselect after this transfer completes + * @bits_per_word: select a bits_per_word other than the device default for this + * transfer. If 0 the default (from @spi_device) is used. + */ +struct gb_spi_transfer { + __le32 speed_hz; + __le32 len; + __le16 delay_usecs; + __u8 cs_change; + __u8 bits_per_word; + __u8 xfer_flags; +#define GB_SPI_XFER_READ 0x01 +#define GB_SPI_XFER_WRITE 0x02 +#define GB_SPI_XFER_INPROGRESS 0x04 +} __packed; + +struct gb_spi_transfer_request { + __u8 chip_select; /* of the spi device */ + __u8 mode; /* of the spi device */ + __le16 count; + struct gb_spi_transfer transfers[0]; /* count of these */ +} __packed; + +struct gb_spi_transfer_response { + __u8 data[0]; /* inbound data */ +} __packed; + +/* Version of the Greybus SVC protocol we support */ +#define GB_SVC_VERSION_MAJOR 0x00 +#define GB_SVC_VERSION_MINOR 0x01 + +/* Greybus SVC request types */ +#define GB_SVC_TYPE_PROTOCOL_VERSION 0x01 +#define GB_SVC_TYPE_SVC_HELLO 0x02 +#define GB_SVC_TYPE_INTF_DEVICE_ID 0x03 +#define GB_SVC_TYPE_INTF_RESET 0x06 +#define GB_SVC_TYPE_CONN_CREATE 0x07 +#define GB_SVC_TYPE_CONN_DESTROY 0x08 +#define GB_SVC_TYPE_DME_PEER_GET 0x09 +#define GB_SVC_TYPE_DME_PEER_SET 0x0a +#define GB_SVC_TYPE_ROUTE_CREATE 0x0b +#define GB_SVC_TYPE_ROUTE_DESTROY 0x0c +#define GB_SVC_TYPE_TIMESYNC_ENABLE 0x0d +#define GB_SVC_TYPE_TIMESYNC_DISABLE 0x0e +#define GB_SVC_TYPE_TIMESYNC_AUTHORITATIVE 0x0f +#define GB_SVC_TYPE_INTF_SET_PWRM 0x10 +#define GB_SVC_TYPE_INTF_EJECT 0x11 +#define GB_SVC_TYPE_PING 0x13 +#define GB_SVC_TYPE_PWRMON_RAIL_COUNT_GET 0x14 +#define GB_SVC_TYPE_PWRMON_RAIL_NAMES_GET 0x15 +#define GB_SVC_TYPE_PWRMON_SAMPLE_GET 0x16 +#define GB_SVC_TYPE_PWRMON_INTF_SAMPLE_GET 0x17 +#define GB_SVC_TYPE_TIMESYNC_WAKE_PINS_ACQUIRE 0x18 +#define GB_SVC_TYPE_TIMESYNC_WAKE_PINS_RELEASE 0x19 +#define GB_SVC_TYPE_TIMESYNC_PING 0x1a +#define GB_SVC_TYPE_MODULE_INSERTED 0x1f +#define GB_SVC_TYPE_MODULE_REMOVED 0x20 +#define GB_SVC_TYPE_INTF_VSYS_ENABLE 0x21 +#define GB_SVC_TYPE_INTF_VSYS_DISABLE 0x22 +#define GB_SVC_TYPE_INTF_REFCLK_ENABLE 0x23 +#define GB_SVC_TYPE_INTF_REFCLK_DISABLE 0x24 +#define GB_SVC_TYPE_INTF_UNIPRO_ENABLE 0x25 +#define GB_SVC_TYPE_INTF_UNIPRO_DISABLE 0x26 +#define GB_SVC_TYPE_INTF_ACTIVATE 0x27 +#define GB_SVC_TYPE_INTF_RESUME 0x28 +#define GB_SVC_TYPE_INTF_MAILBOX_EVENT 0x29 +#define GB_SVC_TYPE_INTF_OOPS 0x2a + +/* Greybus SVC protocol status values */ +#define GB_SVC_OP_SUCCESS 0x00 +#define GB_SVC_OP_UNKNOWN_ERROR 0x01 +#define GB_SVC_INTF_NOT_DETECTED 0x02 +#define GB_SVC_INTF_NO_UPRO_LINK 0x03 +#define GB_SVC_INTF_UPRO_NOT_DOWN 0x04 +#define GB_SVC_INTF_UPRO_NOT_HIBERNATED 0x05 +#define GB_SVC_INTF_NO_V_SYS 0x06 +#define GB_SVC_INTF_V_CHG 0x07 +#define GB_SVC_INTF_WAKE_BUSY 0x08 +#define GB_SVC_INTF_NO_REFCLK 0x09 +#define GB_SVC_INTF_RELEASING 0x0a +#define GB_SVC_INTF_NO_ORDER 0x0b +#define GB_SVC_INTF_MBOX_SET 0x0c +#define GB_SVC_INTF_BAD_MBOX 0x0d +#define GB_SVC_INTF_OP_TIMEOUT 0x0e +#define GB_SVC_PWRMON_OP_NOT_PRESENT 0x0f + +struct gb_svc_version_request { + __u8 major; + __u8 minor; +} __packed; + +struct gb_svc_version_response { + __u8 major; + __u8 minor; +} __packed; + +/* SVC protocol hello request */ +struct gb_svc_hello_request { + __le16 endo_id; + __u8 interface_id; +} __packed; +/* hello response has no payload */ + +struct gb_svc_intf_device_id_request { + __u8 intf_id; + __u8 device_id; +} __packed; +/* device id response has no payload */ + +struct gb_svc_intf_reset_request { + __u8 intf_id; +} __packed; +/* interface reset response has no payload */ + +struct gb_svc_intf_eject_request { + __u8 intf_id; +} __packed; +/* interface eject response has no payload */ + +struct gb_svc_conn_create_request { + __u8 intf1_id; + __le16 cport1_id; + __u8 intf2_id; + __le16 cport2_id; + __u8 tc; + __u8 flags; +} __packed; +/* connection create response has no payload */ + +struct gb_svc_conn_destroy_request { + __u8 intf1_id; + __le16 cport1_id; + __u8 intf2_id; + __le16 cport2_id; +} __packed; +/* connection destroy response has no payload */ + +struct gb_svc_dme_peer_get_request { + __u8 intf_id; + __le16 attr; + __le16 selector; +} __packed; + +struct gb_svc_dme_peer_get_response { + __le16 result_code; + __le32 attr_value; +} __packed; + +struct gb_svc_dme_peer_set_request { + __u8 intf_id; + __le16 attr; + __le16 selector; + __le32 value; +} __packed; + +struct gb_svc_dme_peer_set_response { + __le16 result_code; +} __packed; + +/* Greybus init-status values, currently retrieved using DME peer gets. */ +#define GB_INIT_SPI_BOOT_STARTED 0x02 +#define GB_INIT_TRUSTED_SPI_BOOT_FINISHED 0x03 +#define GB_INIT_UNTRUSTED_SPI_BOOT_FINISHED 0x04 +#define GB_INIT_BOOTROM_UNIPRO_BOOT_STARTED 0x06 +#define GB_INIT_BOOTROM_FALLBACK_UNIPRO_BOOT_STARTED 0x09 +#define GB_INIT_S2_LOADER_BOOT_STARTED 0x0D + +struct gb_svc_route_create_request { + __u8 intf1_id; + __u8 dev1_id; + __u8 intf2_id; + __u8 dev2_id; +} __packed; +/* route create response has no payload */ + +struct gb_svc_route_destroy_request { + __u8 intf1_id; + __u8 intf2_id; +} __packed; +/* route destroy response has no payload */ + +/* used for svc_intf_vsys_{enable,disable} */ +struct gb_svc_intf_vsys_request { + __u8 intf_id; +} __packed; + +struct gb_svc_intf_vsys_response { + __u8 result_code; +#define GB_SVC_INTF_VSYS_OK 0x00 + /* 0x01 is reserved */ +#define GB_SVC_INTF_VSYS_FAIL 0x02 +} __packed; + +/* used for svc_intf_refclk_{enable,disable} */ +struct gb_svc_intf_refclk_request { + __u8 intf_id; +} __packed; + +struct gb_svc_intf_refclk_response { + __u8 result_code; +#define GB_SVC_INTF_REFCLK_OK 0x00 + /* 0x01 is reserved */ +#define GB_SVC_INTF_REFCLK_FAIL 0x02 +} __packed; + +/* used for svc_intf_unipro_{enable,disable} */ +struct gb_svc_intf_unipro_request { + __u8 intf_id; +} __packed; + +struct gb_svc_intf_unipro_response { + __u8 result_code; +#define GB_SVC_INTF_UNIPRO_OK 0x00 + /* 0x01 is reserved */ +#define GB_SVC_INTF_UNIPRO_FAIL 0x02 +#define GB_SVC_INTF_UNIPRO_NOT_OFF 0x03 +} __packed; + +#define GB_SVC_UNIPRO_FAST_MODE 0x01 +#define GB_SVC_UNIPRO_SLOW_MODE 0x02 +#define GB_SVC_UNIPRO_FAST_AUTO_MODE 0x04 +#define GB_SVC_UNIPRO_SLOW_AUTO_MODE 0x05 +#define GB_SVC_UNIPRO_MODE_UNCHANGED 0x07 +#define GB_SVC_UNIPRO_HIBERNATE_MODE 0x11 +#define GB_SVC_UNIPRO_OFF_MODE 0x12 + +#define GB_SVC_SMALL_AMPLITUDE 0x01 +#define GB_SVC_LARGE_AMPLITUDE 0x02 + +#define GB_SVC_NO_DE_EMPHASIS 0x00 +#define GB_SVC_SMALL_DE_EMPHASIS 0x01 +#define GB_SVC_LARGE_DE_EMPHASIS 0x02 + +#define GB_SVC_PWRM_RXTERMINATION 0x01 +#define GB_SVC_PWRM_TXTERMINATION 0x02 +#define GB_SVC_PWRM_LINE_RESET 0x04 +#define GB_SVC_PWRM_SCRAMBLING 0x20 + +#define GB_SVC_PWRM_QUIRK_HSSER 0x00000001 + +#define GB_SVC_UNIPRO_HS_SERIES_A 0x01 +#define GB_SVC_UNIPRO_HS_SERIES_B 0x02 + +#define GB_SVC_SETPWRM_PWR_OK 0x00 +#define GB_SVC_SETPWRM_PWR_LOCAL 0x01 +#define GB_SVC_SETPWRM_PWR_REMOTE 0x02 +#define GB_SVC_SETPWRM_PWR_BUSY 0x03 +#define GB_SVC_SETPWRM_PWR_ERROR_CAP 0x04 +#define GB_SVC_SETPWRM_PWR_FATAL_ERROR 0x05 + +struct gb_svc_l2_timer_cfg { + __le16 tsb_fc0_protection_timeout; + __le16 tsb_tc0_replay_timeout; + __le16 tsb_afc0_req_timeout; + __le16 tsb_fc1_protection_timeout; + __le16 tsb_tc1_replay_timeout; + __le16 tsb_afc1_req_timeout; + __le16 reserved_for_tc2[3]; + __le16 reserved_for_tc3[3]; +} __packed; + +struct gb_svc_intf_set_pwrm_request { + __u8 intf_id; + __u8 hs_series; + __u8 tx_mode; + __u8 tx_gear; + __u8 tx_nlanes; + __u8 tx_amplitude; + __u8 tx_hs_equalizer; + __u8 rx_mode; + __u8 rx_gear; + __u8 rx_nlanes; + __u8 flags; + __le32 quirks; + struct gb_svc_l2_timer_cfg local_l2timerdata, remote_l2timerdata; +} __packed; + +struct gb_svc_intf_set_pwrm_response { + __u8 result_code; +} __packed; + +struct gb_svc_key_event_request { + __le16 key_code; +#define GB_KEYCODE_ARA 0x00 + + __u8 key_event; +#define GB_SVC_KEY_RELEASED 0x00 +#define GB_SVC_KEY_PRESSED 0x01 +} __packed; + +#define GB_SVC_PWRMON_MAX_RAIL_COUNT 254 + +struct gb_svc_pwrmon_rail_count_get_response { + __u8 rail_count; +} __packed; + +#define GB_SVC_PWRMON_RAIL_NAME_BUFSIZE 32 + +struct gb_svc_pwrmon_rail_names_get_response { + __u8 status; + __u8 name[0][GB_SVC_PWRMON_RAIL_NAME_BUFSIZE]; +} __packed; + +#define GB_SVC_PWRMON_TYPE_CURR 0x01 +#define GB_SVC_PWRMON_TYPE_VOL 0x02 +#define GB_SVC_PWRMON_TYPE_PWR 0x03 + +#define GB_SVC_PWRMON_GET_SAMPLE_OK 0x00 +#define GB_SVC_PWRMON_GET_SAMPLE_INVAL 0x01 +#define GB_SVC_PWRMON_GET_SAMPLE_NOSUPP 0x02 +#define GB_SVC_PWRMON_GET_SAMPLE_HWERR 0x03 + +struct gb_svc_pwrmon_sample_get_request { + __u8 rail_id; + __u8 measurement_type; +} __packed; + +struct gb_svc_pwrmon_sample_get_response { + __u8 result; + __le32 measurement; +} __packed; + +struct gb_svc_pwrmon_intf_sample_get_request { + __u8 intf_id; + __u8 measurement_type; +} __packed; + +struct gb_svc_pwrmon_intf_sample_get_response { + __u8 result; + __le32 measurement; +} __packed; + +#define GB_SVC_MODULE_INSERTED_FLAG_NO_PRIMARY 0x0001 + +struct gb_svc_module_inserted_request { + __u8 primary_intf_id; + __u8 intf_count; + __le16 flags; +} __packed; +/* module_inserted response has no payload */ + +struct gb_svc_module_removed_request { + __u8 primary_intf_id; +} __packed; +/* module_removed response has no payload */ + +struct gb_svc_intf_activate_request { + __u8 intf_id; +} __packed; + +#define GB_SVC_INTF_TYPE_UNKNOWN 0x00 +#define GB_SVC_INTF_TYPE_DUMMY 0x01 +#define GB_SVC_INTF_TYPE_UNIPRO 0x02 +#define GB_SVC_INTF_TYPE_GREYBUS 0x03 + +struct gb_svc_intf_activate_response { + __u8 status; + __u8 intf_type; +} __packed; + +struct gb_svc_intf_resume_request { + __u8 intf_id; +} __packed; + +struct gb_svc_intf_resume_response { + __u8 status; +} __packed; + +#define GB_SVC_INTF_MAILBOX_NONE 0x00 +#define GB_SVC_INTF_MAILBOX_AP 0x01 +#define GB_SVC_INTF_MAILBOX_GREYBUS 0x02 + +struct gb_svc_intf_mailbox_event_request { + __u8 intf_id; + __le16 result_code; + __le32 mailbox; +} __packed; +/* intf_mailbox_event response has no payload */ + +struct gb_svc_intf_oops_request { + __u8 intf_id; + __u8 reason; +} __packed; +/* intf_oops response has no payload */ + + +/* RAW */ + +/* Greybus raw request types */ +#define GB_RAW_TYPE_SEND 0x02 + +struct gb_raw_send_request { + __le32 len; + __u8 data[0]; +} __packed; + + +/* UART */ + +/* Greybus UART operation types */ +#define GB_UART_TYPE_SEND_DATA 0x02 +#define GB_UART_TYPE_RECEIVE_DATA 0x03 /* Unsolicited data */ +#define GB_UART_TYPE_SET_LINE_CODING 0x04 +#define GB_UART_TYPE_SET_CONTROL_LINE_STATE 0x05 +#define GB_UART_TYPE_SEND_BREAK 0x06 +#define GB_UART_TYPE_SERIAL_STATE 0x07 /* Unsolicited data */ +#define GB_UART_TYPE_RECEIVE_CREDITS 0x08 +#define GB_UART_TYPE_FLUSH_FIFOS 0x09 + +/* Represents data from AP -> Module */ +struct gb_uart_send_data_request { + __le16 size; + __u8 data[0]; +} __packed; + +/* recv-data-request flags */ +#define GB_UART_RECV_FLAG_FRAMING 0x01 /* Framing error */ +#define GB_UART_RECV_FLAG_PARITY 0x02 /* Parity error */ +#define GB_UART_RECV_FLAG_OVERRUN 0x04 /* Overrun error */ +#define GB_UART_RECV_FLAG_BREAK 0x08 /* Break */ + +/* Represents data from Module -> AP */ +struct gb_uart_recv_data_request { + __le16 size; + __u8 flags; + __u8 data[0]; +} __packed; + +struct gb_uart_receive_credits_request { + __le16 count; +} __packed; + +struct gb_uart_set_line_coding_request { + __le32 rate; + __u8 format; +#define GB_SERIAL_1_STOP_BITS 0 +#define GB_SERIAL_1_5_STOP_BITS 1 +#define GB_SERIAL_2_STOP_BITS 2 + + __u8 parity; +#define GB_SERIAL_NO_PARITY 0 +#define GB_SERIAL_ODD_PARITY 1 +#define GB_SERIAL_EVEN_PARITY 2 +#define GB_SERIAL_MARK_PARITY 3 +#define GB_SERIAL_SPACE_PARITY 4 + + __u8 data_bits; + + __u8 flow_control; +#define GB_SERIAL_AUTO_RTSCTS_EN 0x1 +} __packed; + +/* output control lines */ +#define GB_UART_CTRL_DTR 0x01 +#define GB_UART_CTRL_RTS 0x02 + +struct gb_uart_set_control_line_state_request { + __u8 control; +} __packed; + +struct gb_uart_set_break_request { + __u8 state; +} __packed; + +/* input control lines and line errors */ +#define GB_UART_CTRL_DCD 0x01 +#define GB_UART_CTRL_DSR 0x02 +#define GB_UART_CTRL_RI 0x04 + +struct gb_uart_serial_state_request { + __u8 control; +} __packed; + +struct gb_uart_serial_flush_request { + __u8 flags; +#define GB_SERIAL_FLAG_FLUSH_TRANSMITTER 0x01 +#define GB_SERIAL_FLAG_FLUSH_RECEIVER 0x02 +} __packed; + +/* Loopback */ + +/* Greybus loopback request types */ +#define GB_LOOPBACK_TYPE_PING 0x02 +#define GB_LOOPBACK_TYPE_TRANSFER 0x03 +#define GB_LOOPBACK_TYPE_SINK 0x04 + +/* + * Loopback request/response header format should be identical + * to simplify bandwidth and data movement analysis. + */ +struct gb_loopback_transfer_request { + __le32 len; + __le32 reserved0; + __le32 reserved1; + __u8 data[0]; +} __packed; + +struct gb_loopback_transfer_response { + __le32 len; + __le32 reserved0; + __le32 reserved1; + __u8 data[0]; +} __packed; + +/* SDIO */ +/* Greybus SDIO operation types */ +#define GB_SDIO_TYPE_GET_CAPABILITIES 0x02 +#define GB_SDIO_TYPE_SET_IOS 0x03 +#define GB_SDIO_TYPE_COMMAND 0x04 +#define GB_SDIO_TYPE_TRANSFER 0x05 +#define GB_SDIO_TYPE_EVENT 0x06 + +/* get caps response: request has no payload */ +struct gb_sdio_get_caps_response { + __le32 caps; +#define GB_SDIO_CAP_NONREMOVABLE 0x00000001 +#define GB_SDIO_CAP_4_BIT_DATA 0x00000002 +#define GB_SDIO_CAP_8_BIT_DATA 0x00000004 +#define GB_SDIO_CAP_MMC_HS 0x00000008 +#define GB_SDIO_CAP_SD_HS 0x00000010 +#define GB_SDIO_CAP_ERASE 0x00000020 +#define GB_SDIO_CAP_1_2V_DDR 0x00000040 +#define GB_SDIO_CAP_1_8V_DDR 0x00000080 +#define GB_SDIO_CAP_POWER_OFF_CARD 0x00000100 +#define GB_SDIO_CAP_UHS_SDR12 0x00000200 +#define GB_SDIO_CAP_UHS_SDR25 0x00000400 +#define GB_SDIO_CAP_UHS_SDR50 0x00000800 +#define GB_SDIO_CAP_UHS_SDR104 0x00001000 +#define GB_SDIO_CAP_UHS_DDR50 0x00002000 +#define GB_SDIO_CAP_DRIVER_TYPE_A 0x00004000 +#define GB_SDIO_CAP_DRIVER_TYPE_C 0x00008000 +#define GB_SDIO_CAP_DRIVER_TYPE_D 0x00010000 +#define GB_SDIO_CAP_HS200_1_2V 0x00020000 +#define GB_SDIO_CAP_HS200_1_8V 0x00040000 +#define GB_SDIO_CAP_HS400_1_2V 0x00080000 +#define GB_SDIO_CAP_HS400_1_8V 0x00100000 + + /* see possible values below at vdd */ + __le32 ocr; + __le32 f_min; + __le32 f_max; + __le16 max_blk_count; + __le16 max_blk_size; +} __packed; + +/* set ios request: response has no payload */ +struct gb_sdio_set_ios_request { + __le32 clock; + __le32 vdd; +#define GB_SDIO_VDD_165_195 0x00000001 +#define GB_SDIO_VDD_20_21 0x00000002 +#define GB_SDIO_VDD_21_22 0x00000004 +#define GB_SDIO_VDD_22_23 0x00000008 +#define GB_SDIO_VDD_23_24 0x00000010 +#define GB_SDIO_VDD_24_25 0x00000020 +#define GB_SDIO_VDD_25_26 0x00000040 +#define GB_SDIO_VDD_26_27 0x00000080 +#define GB_SDIO_VDD_27_28 0x00000100 +#define GB_SDIO_VDD_28_29 0x00000200 +#define GB_SDIO_VDD_29_30 0x00000400 +#define GB_SDIO_VDD_30_31 0x00000800 +#define GB_SDIO_VDD_31_32 0x00001000 +#define GB_SDIO_VDD_32_33 0x00002000 +#define GB_SDIO_VDD_33_34 0x00004000 +#define GB_SDIO_VDD_34_35 0x00008000 +#define GB_SDIO_VDD_35_36 0x00010000 + + __u8 bus_mode; +#define GB_SDIO_BUSMODE_OPENDRAIN 0x00 +#define GB_SDIO_BUSMODE_PUSHPULL 0x01 + + __u8 power_mode; +#define GB_SDIO_POWER_OFF 0x00 +#define GB_SDIO_POWER_UP 0x01 +#define GB_SDIO_POWER_ON 0x02 +#define GB_SDIO_POWER_UNDEFINED 0x03 + + __u8 bus_width; +#define GB_SDIO_BUS_WIDTH_1 0x00 +#define GB_SDIO_BUS_WIDTH_4 0x02 +#define GB_SDIO_BUS_WIDTH_8 0x03 + + __u8 timing; +#define GB_SDIO_TIMING_LEGACY 0x00 +#define GB_SDIO_TIMING_MMC_HS 0x01 +#define GB_SDIO_TIMING_SD_HS 0x02 +#define GB_SDIO_TIMING_UHS_SDR12 0x03 +#define GB_SDIO_TIMING_UHS_SDR25 0x04 +#define GB_SDIO_TIMING_UHS_SDR50 0x05 +#define GB_SDIO_TIMING_UHS_SDR104 0x06 +#define GB_SDIO_TIMING_UHS_DDR50 0x07 +#define GB_SDIO_TIMING_MMC_DDR52 0x08 +#define GB_SDIO_TIMING_MMC_HS200 0x09 +#define GB_SDIO_TIMING_MMC_HS400 0x0A + + __u8 signal_voltage; +#define GB_SDIO_SIGNAL_VOLTAGE_330 0x00 +#define GB_SDIO_SIGNAL_VOLTAGE_180 0x01 +#define GB_SDIO_SIGNAL_VOLTAGE_120 0x02 + + __u8 drv_type; +#define GB_SDIO_SET_DRIVER_TYPE_B 0x00 +#define GB_SDIO_SET_DRIVER_TYPE_A 0x01 +#define GB_SDIO_SET_DRIVER_TYPE_C 0x02 +#define GB_SDIO_SET_DRIVER_TYPE_D 0x03 +} __packed; + +/* command request */ +struct gb_sdio_command_request { + __u8 cmd; + __u8 cmd_flags; +#define GB_SDIO_RSP_NONE 0x00 +#define GB_SDIO_RSP_PRESENT 0x01 +#define GB_SDIO_RSP_136 0x02 +#define GB_SDIO_RSP_CRC 0x04 +#define GB_SDIO_RSP_BUSY 0x08 +#define GB_SDIO_RSP_OPCODE 0x10 + + __u8 cmd_type; +#define GB_SDIO_CMD_AC 0x00 +#define GB_SDIO_CMD_ADTC 0x01 +#define GB_SDIO_CMD_BC 0x02 +#define GB_SDIO_CMD_BCR 0x03 + + __le32 cmd_arg; + __le16 data_blocks; + __le16 data_blksz; +} __packed; + +struct gb_sdio_command_response { + __le32 resp[4]; +} __packed; + +/* transfer request */ +struct gb_sdio_transfer_request { + __u8 data_flags; +#define GB_SDIO_DATA_WRITE 0x01 +#define GB_SDIO_DATA_READ 0x02 +#define GB_SDIO_DATA_STREAM 0x04 + + __le16 data_blocks; + __le16 data_blksz; + __u8 data[0]; +} __packed; + +struct gb_sdio_transfer_response { + __le16 data_blocks; + __le16 data_blksz; + __u8 data[0]; +} __packed; + +/* event request: generated by module and is defined as unidirectional */ +struct gb_sdio_event_request { + __u8 event; +#define GB_SDIO_CARD_INSERTED 0x01 +#define GB_SDIO_CARD_REMOVED 0x02 +#define GB_SDIO_WP 0x04 +} __packed; + +/* Camera */ + +/* Greybus Camera request types */ +#define GB_CAMERA_TYPE_CAPABILITIES 0x02 +#define GB_CAMERA_TYPE_CONFIGURE_STREAMS 0x03 +#define GB_CAMERA_TYPE_CAPTURE 0x04 +#define GB_CAMERA_TYPE_FLUSH 0x05 +#define GB_CAMERA_TYPE_METADATA 0x06 + +#define GB_CAMERA_MAX_STREAMS 4 +#define GB_CAMERA_MAX_SETTINGS_SIZE 8192 + +/* Greybus Camera Configure Streams request payload */ +struct gb_camera_stream_config_request { + __le16 width; + __le16 height; + __le16 format; + __le16 padding; +} __packed; + +struct gb_camera_configure_streams_request { + __u8 num_streams; + __u8 flags; +#define GB_CAMERA_CONFIGURE_STREAMS_TEST_ONLY 0x01 + __le16 padding; + struct gb_camera_stream_config_request config[0]; +} __packed; + +/* Greybus Camera Configure Streams response payload */ +struct gb_camera_stream_config_response { + __le16 width; + __le16 height; + __le16 format; + __u8 virtual_channel; + __u8 data_type[2]; + __le16 max_pkt_size; + __u8 padding; + __le32 max_size; +} __packed; + +struct gb_camera_configure_streams_response { + __u8 num_streams; +#define GB_CAMERA_CONFIGURE_STREAMS_ADJUSTED 0x01 + __u8 flags; + __u8 padding[2]; + __le32 data_rate; + struct gb_camera_stream_config_response config[0]; +}; + +/* Greybus Camera Capture request payload - response has no payload */ +struct gb_camera_capture_request { + __le32 request_id; + __u8 streams; + __u8 padding; + __le16 num_frames; + __u8 settings[0]; +} __packed; + +/* Greybus Camera Flush response payload - request has no payload */ +struct gb_camera_flush_response { + __le32 request_id; +} __packed; + +/* Greybus Camera Metadata request payload - operation has no response */ +struct gb_camera_metadata_request { + __le32 request_id; + __le16 frame_number; + __u8 stream; + __u8 padding; + __u8 metadata[0]; +} __packed; + +/* Lights */ + +/* Greybus Lights request types */ +#define GB_LIGHTS_TYPE_GET_LIGHTS 0x02 +#define GB_LIGHTS_TYPE_GET_LIGHT_CONFIG 0x03 +#define GB_LIGHTS_TYPE_GET_CHANNEL_CONFIG 0x04 +#define GB_LIGHTS_TYPE_GET_CHANNEL_FLASH_CONFIG 0x05 +#define GB_LIGHTS_TYPE_SET_BRIGHTNESS 0x06 +#define GB_LIGHTS_TYPE_SET_BLINK 0x07 +#define GB_LIGHTS_TYPE_SET_COLOR 0x08 +#define GB_LIGHTS_TYPE_SET_FADE 0x09 +#define GB_LIGHTS_TYPE_EVENT 0x0A +#define GB_LIGHTS_TYPE_SET_FLASH_INTENSITY 0x0B +#define GB_LIGHTS_TYPE_SET_FLASH_STROBE 0x0C +#define GB_LIGHTS_TYPE_SET_FLASH_TIMEOUT 0x0D +#define GB_LIGHTS_TYPE_GET_FLASH_FAULT 0x0E + +/* Greybus Light modes */ + +/* + * if you add any specific mode below, update also the + * GB_CHANNEL_MODE_DEFINED_RANGE value accordingly + */ +#define GB_CHANNEL_MODE_NONE 0x00000000 +#define GB_CHANNEL_MODE_BATTERY 0x00000001 +#define GB_CHANNEL_MODE_POWER 0x00000002 +#define GB_CHANNEL_MODE_WIRELESS 0x00000004 +#define GB_CHANNEL_MODE_BLUETOOTH 0x00000008 +#define GB_CHANNEL_MODE_KEYBOARD 0x00000010 +#define GB_CHANNEL_MODE_BUTTONS 0x00000020 +#define GB_CHANNEL_MODE_NOTIFICATION 0x00000040 +#define GB_CHANNEL_MODE_ATTENTION 0x00000080 +#define GB_CHANNEL_MODE_FLASH 0x00000100 +#define GB_CHANNEL_MODE_TORCH 0x00000200 +#define GB_CHANNEL_MODE_INDICATOR 0x00000400 + +/* Lights Mode valid bit values */ +#define GB_CHANNEL_MODE_DEFINED_RANGE 0x000004FF +#define GB_CHANNEL_MODE_VENDOR_RANGE 0x00F00000 + +/* Greybus Light Channels Flags */ +#define GB_LIGHT_CHANNEL_MULTICOLOR 0x00000001 +#define GB_LIGHT_CHANNEL_FADER 0x00000002 +#define GB_LIGHT_CHANNEL_BLINK 0x00000004 + +/* get count of lights in module */ +struct gb_lights_get_lights_response { + __u8 lights_count; +} __packed; + +/* light config request payload */ +struct gb_lights_get_light_config_request { + __u8 id; +} __packed; + +/* light config response payload */ +struct gb_lights_get_light_config_response { + __u8 channel_count; + __u8 name[32]; +} __packed; + +/* channel config request payload */ +struct gb_lights_get_channel_config_request { + __u8 light_id; + __u8 channel_id; +} __packed; + +/* channel flash config request payload */ +struct gb_lights_get_channel_flash_config_request { + __u8 light_id; + __u8 channel_id; +} __packed; + +/* channel config response payload */ +struct gb_lights_get_channel_config_response { + __u8 max_brightness; + __le32 flags; + __le32 color; + __u8 color_name[32]; + __le32 mode; + __u8 mode_name[32]; +} __packed; + +/* channel flash config response payload */ +struct gb_lights_get_channel_flash_config_response { + __le32 intensity_min_uA; + __le32 intensity_max_uA; + __le32 intensity_step_uA; + __le32 timeout_min_us; + __le32 timeout_max_us; + __le32 timeout_step_us; +} __packed; + +/* blink request payload: response have no payload */ +struct gb_lights_blink_request { + __u8 light_id; + __u8 channel_id; + __le16 time_on_ms; + __le16 time_off_ms; +} __packed; + +/* set brightness request payload: response have no payload */ +struct gb_lights_set_brightness_request { + __u8 light_id; + __u8 channel_id; + __u8 brightness; +} __packed; + +/* set color request payload: response have no payload */ +struct gb_lights_set_color_request { + __u8 light_id; + __u8 channel_id; + __le32 color; +} __packed; + +/* set fade request payload: response have no payload */ +struct gb_lights_set_fade_request { + __u8 light_id; + __u8 channel_id; + __u8 fade_in; + __u8 fade_out; +} __packed; + +/* event request: generated by module */ +struct gb_lights_event_request { + __u8 light_id; + __u8 event; +#define GB_LIGHTS_LIGHT_CONFIG 0x01 +} __packed; + +/* set flash intensity request payload: response have no payload */ +struct gb_lights_set_flash_intensity_request { + __u8 light_id; + __u8 channel_id; + __le32 intensity_uA; +} __packed; + +/* set flash strobe state request payload: response have no payload */ +struct gb_lights_set_flash_strobe_request { + __u8 light_id; + __u8 channel_id; + __u8 state; +} __packed; + +/* set flash timeout request payload: response have no payload */ +struct gb_lights_set_flash_timeout_request { + __u8 light_id; + __u8 channel_id; + __le32 timeout_us; +} __packed; + +/* get flash fault request payload */ +struct gb_lights_get_flash_fault_request { + __u8 light_id; + __u8 channel_id; +} __packed; + +/* get flash fault response payload */ +struct gb_lights_get_flash_fault_response { + __le32 fault; +#define GB_LIGHTS_FLASH_FAULT_OVER_VOLTAGE 0x00000000 +#define GB_LIGHTS_FLASH_FAULT_TIMEOUT 0x00000001 +#define GB_LIGHTS_FLASH_FAULT_OVER_TEMPERATURE 0x00000002 +#define GB_LIGHTS_FLASH_FAULT_SHORT_CIRCUIT 0x00000004 +#define GB_LIGHTS_FLASH_FAULT_OVER_CURRENT 0x00000008 +#define GB_LIGHTS_FLASH_FAULT_INDICATOR 0x00000010 +#define GB_LIGHTS_FLASH_FAULT_UNDER_VOLTAGE 0x00000020 +#define GB_LIGHTS_FLASH_FAULT_INPUT_VOLTAGE 0x00000040 +#define GB_LIGHTS_FLASH_FAULT_LED_OVER_TEMPERATURE 0x00000080 +} __packed; + +/* Audio */ + +#define GB_AUDIO_TYPE_GET_TOPOLOGY_SIZE 0x02 +#define GB_AUDIO_TYPE_GET_TOPOLOGY 0x03 +#define GB_AUDIO_TYPE_GET_CONTROL 0x04 +#define GB_AUDIO_TYPE_SET_CONTROL 0x05 +#define GB_AUDIO_TYPE_ENABLE_WIDGET 0x06 +#define GB_AUDIO_TYPE_DISABLE_WIDGET 0x07 +#define GB_AUDIO_TYPE_GET_PCM 0x08 +#define GB_AUDIO_TYPE_SET_PCM 0x09 +#define GB_AUDIO_TYPE_SET_TX_DATA_SIZE 0x0a + /* 0x0b unused */ +#define GB_AUDIO_TYPE_ACTIVATE_TX 0x0c +#define GB_AUDIO_TYPE_DEACTIVATE_TX 0x0d +#define GB_AUDIO_TYPE_SET_RX_DATA_SIZE 0x0e + /* 0x0f unused */ +#define GB_AUDIO_TYPE_ACTIVATE_RX 0x10 +#define GB_AUDIO_TYPE_DEACTIVATE_RX 0x11 +#define GB_AUDIO_TYPE_JACK_EVENT 0x12 +#define GB_AUDIO_TYPE_BUTTON_EVENT 0x13 +#define GB_AUDIO_TYPE_STREAMING_EVENT 0x14 +#define GB_AUDIO_TYPE_SEND_DATA 0x15 + +/* Module must be able to buffer 10ms of audio data, minimum */ +#define GB_AUDIO_SAMPLE_BUFFER_MIN_US 10000 + +#define GB_AUDIO_PCM_NAME_MAX 32 +#define AUDIO_DAI_NAME_MAX 32 +#define AUDIO_CONTROL_NAME_MAX 32 +#define AUDIO_CTL_ELEM_NAME_MAX 44 +#define AUDIO_ENUM_NAME_MAX 64 +#define AUDIO_WIDGET_NAME_MAX 32 + +/* See SNDRV_PCM_FMTBIT_* in Linux source */ +#define GB_AUDIO_PCM_FMT_S8 BIT(0) +#define GB_AUDIO_PCM_FMT_U8 BIT(1) +#define GB_AUDIO_PCM_FMT_S16_LE BIT(2) +#define GB_AUDIO_PCM_FMT_S16_BE BIT(3) +#define GB_AUDIO_PCM_FMT_U16_LE BIT(4) +#define GB_AUDIO_PCM_FMT_U16_BE BIT(5) +#define GB_AUDIO_PCM_FMT_S24_LE BIT(6) +#define GB_AUDIO_PCM_FMT_S24_BE BIT(7) +#define GB_AUDIO_PCM_FMT_U24_LE BIT(8) +#define GB_AUDIO_PCM_FMT_U24_BE BIT(9) +#define GB_AUDIO_PCM_FMT_S32_LE BIT(10) +#define GB_AUDIO_PCM_FMT_S32_BE BIT(11) +#define GB_AUDIO_PCM_FMT_U32_LE BIT(12) +#define GB_AUDIO_PCM_FMT_U32_BE BIT(13) + +/* See SNDRV_PCM_RATE_* in Linux source */ +#define GB_AUDIO_PCM_RATE_5512 BIT(0) +#define GB_AUDIO_PCM_RATE_8000 BIT(1) +#define GB_AUDIO_PCM_RATE_11025 BIT(2) +#define GB_AUDIO_PCM_RATE_16000 BIT(3) +#define GB_AUDIO_PCM_RATE_22050 BIT(4) +#define GB_AUDIO_PCM_RATE_32000 BIT(5) +#define GB_AUDIO_PCM_RATE_44100 BIT(6) +#define GB_AUDIO_PCM_RATE_48000 BIT(7) +#define GB_AUDIO_PCM_RATE_64000 BIT(8) +#define GB_AUDIO_PCM_RATE_88200 BIT(9) +#define GB_AUDIO_PCM_RATE_96000 BIT(10) +#define GB_AUDIO_PCM_RATE_176400 BIT(11) +#define GB_AUDIO_PCM_RATE_192000 BIT(12) + +#define GB_AUDIO_STREAM_TYPE_CAPTURE 0x1 +#define GB_AUDIO_STREAM_TYPE_PLAYBACK 0x2 + +#define GB_AUDIO_CTL_ELEM_ACCESS_READ BIT(0) +#define GB_AUDIO_CTL_ELEM_ACCESS_WRITE BIT(1) + +/* See SNDRV_CTL_ELEM_TYPE_* in Linux source */ +#define GB_AUDIO_CTL_ELEM_TYPE_BOOLEAN 0x01 +#define GB_AUDIO_CTL_ELEM_TYPE_INTEGER 0x02 +#define GB_AUDIO_CTL_ELEM_TYPE_ENUMERATED 0x03 +#define GB_AUDIO_CTL_ELEM_TYPE_INTEGER64 0x06 + +/* See SNDRV_CTL_ELEM_IFACE_* in Linux source */ +#define GB_AUDIO_CTL_ELEM_IFACE_CARD 0x00 +#define GB_AUDIO_CTL_ELEM_IFACE_HWDEP 0x01 +#define GB_AUDIO_CTL_ELEM_IFACE_MIXER 0x02 +#define GB_AUDIO_CTL_ELEM_IFACE_PCM 0x03 +#define GB_AUDIO_CTL_ELEM_IFACE_RAWMIDI 0x04 +#define GB_AUDIO_CTL_ELEM_IFACE_TIMER 0x05 +#define GB_AUDIO_CTL_ELEM_IFACE_SEQUENCER 0x06 + +/* SNDRV_CTL_ELEM_ACCESS_* in Linux source */ +#define GB_AUDIO_ACCESS_READ BIT(0) +#define GB_AUDIO_ACCESS_WRITE BIT(1) +#define GB_AUDIO_ACCESS_VOLATILE BIT(2) +#define GB_AUDIO_ACCESS_TIMESTAMP BIT(3) +#define GB_AUDIO_ACCESS_TLV_READ BIT(4) +#define GB_AUDIO_ACCESS_TLV_WRITE BIT(5) +#define GB_AUDIO_ACCESS_TLV_COMMAND BIT(6) +#define GB_AUDIO_ACCESS_INACTIVE BIT(7) +#define GB_AUDIO_ACCESS_LOCK BIT(8) +#define GB_AUDIO_ACCESS_OWNER BIT(9) + +/* enum snd_soc_dapm_type */ +#define GB_AUDIO_WIDGET_TYPE_INPUT 0x0 +#define GB_AUDIO_WIDGET_TYPE_OUTPUT 0x1 +#define GB_AUDIO_WIDGET_TYPE_MUX 0x2 +#define GB_AUDIO_WIDGET_TYPE_VIRT_MUX 0x3 +#define GB_AUDIO_WIDGET_TYPE_VALUE_MUX 0x4 +#define GB_AUDIO_WIDGET_TYPE_MIXER 0x5 +#define GB_AUDIO_WIDGET_TYPE_MIXER_NAMED_CTL 0x6 +#define GB_AUDIO_WIDGET_TYPE_PGA 0x7 +#define GB_AUDIO_WIDGET_TYPE_OUT_DRV 0x8 +#define GB_AUDIO_WIDGET_TYPE_ADC 0x9 +#define GB_AUDIO_WIDGET_TYPE_DAC 0xa +#define GB_AUDIO_WIDGET_TYPE_MICBIAS 0xb +#define GB_AUDIO_WIDGET_TYPE_MIC 0xc +#define GB_AUDIO_WIDGET_TYPE_HP 0xd +#define GB_AUDIO_WIDGET_TYPE_SPK 0xe +#define GB_AUDIO_WIDGET_TYPE_LINE 0xf +#define GB_AUDIO_WIDGET_TYPE_SWITCH 0x10 +#define GB_AUDIO_WIDGET_TYPE_VMID 0x11 +#define GB_AUDIO_WIDGET_TYPE_PRE 0x12 +#define GB_AUDIO_WIDGET_TYPE_POST 0x13 +#define GB_AUDIO_WIDGET_TYPE_SUPPLY 0x14 +#define GB_AUDIO_WIDGET_TYPE_REGULATOR_SUPPLY 0x15 +#define GB_AUDIO_WIDGET_TYPE_CLOCK_SUPPLY 0x16 +#define GB_AUDIO_WIDGET_TYPE_AIF_IN 0x17 +#define GB_AUDIO_WIDGET_TYPE_AIF_OUT 0x18 +#define GB_AUDIO_WIDGET_TYPE_SIGGEN 0x19 +#define GB_AUDIO_WIDGET_TYPE_DAI_IN 0x1a +#define GB_AUDIO_WIDGET_TYPE_DAI_OUT 0x1b +#define GB_AUDIO_WIDGET_TYPE_DAI_LINK 0x1c + +#define GB_AUDIO_WIDGET_STATE_DISABLED 0x01 +#define GB_AUDIO_WIDGET_STATE_ENAABLED 0x02 + +#define GB_AUDIO_JACK_EVENT_INSERTION 0x1 +#define GB_AUDIO_JACK_EVENT_REMOVAL 0x2 + +#define GB_AUDIO_BUTTON_EVENT_PRESS 0x1 +#define GB_AUDIO_BUTTON_EVENT_RELEASE 0x2 + +#define GB_AUDIO_STREAMING_EVENT_UNSPECIFIED 0x1 +#define GB_AUDIO_STREAMING_EVENT_HALT 0x2 +#define GB_AUDIO_STREAMING_EVENT_INTERNAL_ERROR 0x3 +#define GB_AUDIO_STREAMING_EVENT_PROTOCOL_ERROR 0x4 +#define GB_AUDIO_STREAMING_EVENT_FAILURE 0x5 +#define GB_AUDIO_STREAMING_EVENT_UNDERRUN 0x6 +#define GB_AUDIO_STREAMING_EVENT_OVERRUN 0x7 +#define GB_AUDIO_STREAMING_EVENT_CLOCKING 0x8 +#define GB_AUDIO_STREAMING_EVENT_DATA_LEN 0x9 + +#define GB_AUDIO_INVALID_INDEX 0xff + +/* enum snd_jack_types */ +#define GB_AUDIO_JACK_HEADPHONE 0x0000001 +#define GB_AUDIO_JACK_MICROPHONE 0x0000002 +#define GB_AUDIO_JACK_HEADSET (GB_AUDIO_JACK_HEADPHONE | \ + GB_AUDIO_JACK_MICROPHONE) +#define GB_AUDIO_JACK_LINEOUT 0x0000004 +#define GB_AUDIO_JACK_MECHANICAL 0x0000008 +#define GB_AUDIO_JACK_VIDEOOUT 0x0000010 +#define GB_AUDIO_JACK_AVOUT (GB_AUDIO_JACK_LINEOUT | \ + GB_AUDIO_JACK_VIDEOOUT) +#define GB_AUDIO_JACK_LINEIN 0x0000020 +#define GB_AUDIO_JACK_OC_HPHL 0x0000040 +#define GB_AUDIO_JACK_OC_HPHR 0x0000080 +#define GB_AUDIO_JACK_MICROPHONE2 0x0000200 +#define GB_AUDIO_JACK_ANC_HEADPHONE (GB_AUDIO_JACK_HEADPHONE | \ + GB_AUDIO_JACK_MICROPHONE | \ + GB_AUDIO_JACK_MICROPHONE2) +/* Kept separate from switches to facilitate implementation */ +#define GB_AUDIO_JACK_BTN_0 0x4000000 +#define GB_AUDIO_JACK_BTN_1 0x2000000 +#define GB_AUDIO_JACK_BTN_2 0x1000000 +#define GB_AUDIO_JACK_BTN_3 0x0800000 + +struct gb_audio_pcm { + __u8 stream_name[GB_AUDIO_PCM_NAME_MAX]; + __le32 formats; /* GB_AUDIO_PCM_FMT_* */ + __le32 rates; /* GB_AUDIO_PCM_RATE_* */ + __u8 chan_min; + __u8 chan_max; + __u8 sig_bits; /* number of bits of content */ +} __packed; + +struct gb_audio_dai { + __u8 name[AUDIO_DAI_NAME_MAX]; + __le16 data_cport; + struct gb_audio_pcm capture; + struct gb_audio_pcm playback; +} __packed; + +struct gb_audio_integer { + __le32 min; + __le32 max; + __le32 step; +} __packed; + +struct gb_audio_integer64 { + __le64 min; + __le64 max; + __le64 step; +} __packed; + +struct gb_audio_enumerated { + __le32 items; + __le16 names_length; + __u8 names[0]; +} __packed; + +struct gb_audio_ctl_elem_info { /* See snd_ctl_elem_info in Linux source */ + __u8 type; /* GB_AUDIO_CTL_ELEM_TYPE_* */ + __le16 dimen[4]; + union { + struct gb_audio_integer integer; + struct gb_audio_integer64 integer64; + struct gb_audio_enumerated enumerated; + } value; +} __packed; + +struct gb_audio_ctl_elem_value { /* See snd_ctl_elem_value in Linux source */ + __le64 timestamp; /* XXX needed? */ + union { + __le32 integer_value[2]; /* consider CTL_DOUBLE_xxx */ + __le64 integer64_value[2]; + __le32 enumerated_item[2]; + } value; +} __packed; + +struct gb_audio_control { + __u8 name[AUDIO_CONTROL_NAME_MAX]; + __u8 id; /* 0-63 */ + __u8 iface; /* GB_AUDIO_IFACE_* */ + __le16 data_cport; + __le32 access; /* GB_AUDIO_ACCESS_* */ + __u8 count; /* count of same elements */ + __u8 count_values; /* count of values, max=2 for CTL_DOUBLE_xxx */ + struct gb_audio_ctl_elem_info info; +} __packed; + +struct gb_audio_widget { + __u8 name[AUDIO_WIDGET_NAME_MAX]; + __u8 sname[AUDIO_WIDGET_NAME_MAX]; + __u8 id; + __u8 type; /* GB_AUDIO_WIDGET_TYPE_* */ + __u8 state; /* GB_AUDIO_WIDGET_STATE_* */ + __u8 ncontrols; + struct gb_audio_control ctl[0]; /* 'ncontrols' entries */ +} __packed; + +struct gb_audio_route { + __u8 source_id; /* widget id */ + __u8 destination_id; /* widget id */ + __u8 control_id; /* 0-63 */ + __u8 index; /* Selection within the control */ +} __packed; + +struct gb_audio_topology { + __u8 num_dais; + __u8 num_controls; + __u8 num_widgets; + __u8 num_routes; + __le32 size_dais; + __le32 size_controls; + __le32 size_widgets; + __le32 size_routes; + __le32 jack_type; + /* + * struct gb_audio_dai dai[num_dais]; + * struct gb_audio_control controls[num_controls]; + * struct gb_audio_widget widgets[num_widgets]; + * struct gb_audio_route routes[num_routes]; + */ + __u8 data[0]; +} __packed; + +struct gb_audio_get_topology_size_response { + __le16 size; +} __packed; + +struct gb_audio_get_topology_response { + struct gb_audio_topology topology; +} __packed; + +struct gb_audio_get_control_request { + __u8 control_id; + __u8 index; +} __packed; + +struct gb_audio_get_control_response { + struct gb_audio_ctl_elem_value value; +} __packed; + +struct gb_audio_set_control_request { + __u8 control_id; + __u8 index; + struct gb_audio_ctl_elem_value value; +} __packed; + +struct gb_audio_enable_widget_request { + __u8 widget_id; +} __packed; + +struct gb_audio_disable_widget_request { + __u8 widget_id; +} __packed; + +struct gb_audio_get_pcm_request { + __le16 data_cport; +} __packed; + +struct gb_audio_get_pcm_response { + __le32 format; + __le32 rate; + __u8 channels; + __u8 sig_bits; +} __packed; + +struct gb_audio_set_pcm_request { + __le16 data_cport; + __le32 format; + __le32 rate; + __u8 channels; + __u8 sig_bits; +} __packed; + +struct gb_audio_set_tx_data_size_request { + __le16 data_cport; + __le16 size; +} __packed; + +struct gb_audio_activate_tx_request { + __le16 data_cport; +} __packed; + +struct gb_audio_deactivate_tx_request { + __le16 data_cport; +} __packed; + +struct gb_audio_set_rx_data_size_request { + __le16 data_cport; + __le16 size; +} __packed; + +struct gb_audio_activate_rx_request { + __le16 data_cport; +} __packed; + +struct gb_audio_deactivate_rx_request { + __le16 data_cport; +} __packed; + +struct gb_audio_jack_event_request { + __u8 widget_id; + __u8 jack_attribute; + __u8 event; +} __packed; + +struct gb_audio_button_event_request { + __u8 widget_id; + __u8 button_id; + __u8 event; +} __packed; + +struct gb_audio_streaming_event_request { + __le16 data_cport; + __u8 event; +} __packed; + +struct gb_audio_send_data_request { + __le64 timestamp; + __u8 data[0]; +} __packed; + + +/* Log */ + +/* operations */ +#define GB_LOG_TYPE_SEND_LOG 0x02 + +/* length */ +#define GB_LOG_MAX_LEN 1024 + +struct gb_log_send_log_request { + __le16 len; + __u8 msg[0]; +} __packed; + +#endif /* __GREYBUS_PROTOCOLS_H */ + diff --git a/include/linux/greybus/hd.h b/include/linux/greybus/hd.h new file mode 100644 index 000000000000..d3faf0c1a569 --- /dev/null +++ b/include/linux/greybus/hd.h @@ -0,0 +1,85 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Greybus Host Device + * + * Copyright 2014-2015 Google Inc. + * Copyright 2014-2015 Linaro Ltd. + */ + +#ifndef __HD_H +#define __HD_H + +#include <linux/types.h> +#include <linux/device.h> + +struct gb_host_device; +struct gb_message; + +struct gb_hd_driver { + size_t hd_priv_size; + + int (*cport_allocate)(struct gb_host_device *hd, int cport_id, + unsigned long flags); + void (*cport_release)(struct gb_host_device *hd, u16 cport_id); + int (*cport_enable)(struct gb_host_device *hd, u16 cport_id, + unsigned long flags); + int (*cport_disable)(struct gb_host_device *hd, u16 cport_id); + int (*cport_connected)(struct gb_host_device *hd, u16 cport_id); + int (*cport_flush)(struct gb_host_device *hd, u16 cport_id); + int (*cport_shutdown)(struct gb_host_device *hd, u16 cport_id, + u8 phase, unsigned int timeout); + int (*cport_quiesce)(struct gb_host_device *hd, u16 cport_id, + size_t peer_space, unsigned int timeout); + int (*cport_clear)(struct gb_host_device *hd, u16 cport_id); + + int (*message_send)(struct gb_host_device *hd, u16 dest_cport_id, + struct gb_message *message, gfp_t gfp_mask); + void (*message_cancel)(struct gb_message *message); + int (*latency_tag_enable)(struct gb_host_device *hd, u16 cport_id); + int (*latency_tag_disable)(struct gb_host_device *hd, u16 cport_id); + int (*output)(struct gb_host_device *hd, void *req, u16 size, u8 cmd, + bool async); +}; + +struct gb_host_device { + struct device dev; + int bus_id; + const struct gb_hd_driver *driver; + + struct list_head modules; + struct list_head connections; + struct ida cport_id_map; + + /* Number of CPorts supported by the UniPro IP */ + size_t num_cports; + + /* Host device buffer constraints */ + size_t buffer_size_max; + + struct gb_svc *svc; + /* Private data for the host driver */ + unsigned long hd_priv[0] __aligned(sizeof(s64)); +}; +#define to_gb_host_device(d) container_of(d, struct gb_host_device, dev) + +int gb_hd_cport_reserve(struct gb_host_device *hd, u16 cport_id); +void gb_hd_cport_release_reserved(struct gb_host_device *hd, u16 cport_id); +int gb_hd_cport_allocate(struct gb_host_device *hd, int cport_id, + unsigned long flags); +void gb_hd_cport_release(struct gb_host_device *hd, u16 cport_id); + +struct gb_host_device *gb_hd_create(struct gb_hd_driver *driver, + struct device *parent, + size_t buffer_size_max, + size_t num_cports); +int gb_hd_add(struct gb_host_device *hd); +void gb_hd_del(struct gb_host_device *hd); +void gb_hd_shutdown(struct gb_host_device *hd); +void gb_hd_put(struct gb_host_device *hd); +int gb_hd_output(struct gb_host_device *hd, void *req, u16 size, u8 cmd, + bool in_irq); + +int gb_hd_init(void); +void gb_hd_exit(void); + +#endif /* __HD_H */ diff --git a/include/linux/greybus/interface.h b/include/linux/greybus/interface.h new file mode 100644 index 000000000000..ce4def881e6f --- /dev/null +++ b/include/linux/greybus/interface.h @@ -0,0 +1,85 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Greybus Interface Block code + * + * Copyright 2014 Google Inc. + * Copyright 2014 Linaro Ltd. + */ + +#ifndef __INTERFACE_H +#define __INTERFACE_H + +#include <linux/types.h> +#include <linux/device.h> + +enum gb_interface_type { + GB_INTERFACE_TYPE_INVALID = 0, + GB_INTERFACE_TYPE_UNKNOWN, + GB_INTERFACE_TYPE_DUMMY, + GB_INTERFACE_TYPE_UNIPRO, + GB_INTERFACE_TYPE_GREYBUS, +}; + +#define GB_INTERFACE_QUIRK_NO_CPORT_FEATURES BIT(0) +#define GB_INTERFACE_QUIRK_NO_INIT_STATUS BIT(1) +#define GB_INTERFACE_QUIRK_NO_GMP_IDS BIT(2) +#define GB_INTERFACE_QUIRK_FORCED_DISABLE BIT(3) +#define GB_INTERFACE_QUIRK_LEGACY_MODE_SWITCH BIT(4) +#define GB_INTERFACE_QUIRK_NO_BUNDLE_ACTIVATE BIT(5) +#define GB_INTERFACE_QUIRK_NO_PM BIT(6) + +struct gb_interface { + struct device dev; + struct gb_control *control; + + struct list_head bundles; + struct list_head module_node; + struct list_head manifest_descs; + u8 interface_id; /* Physical location within the Endo */ + u8 device_id; + u8 features; /* Feature flags set in the manifest */ + + enum gb_interface_type type; + + u32 ddbl1_manufacturer_id; + u32 ddbl1_product_id; + u32 vendor_id; + u32 product_id; + u64 serial_number; + + struct gb_host_device *hd; + struct gb_module *module; + + unsigned long quirks; + + struct mutex mutex; + + bool disconnected; + + bool ejected; + bool removed; + bool active; + bool enabled; + bool mode_switch; + bool dme_read; + + struct work_struct mode_switch_work; + struct completion mode_switch_completion; +}; +#define to_gb_interface(d) container_of(d, struct gb_interface, dev) + +struct gb_interface *gb_interface_create(struct gb_module *module, + u8 interface_id); +int gb_interface_activate(struct gb_interface *intf); +void gb_interface_deactivate(struct gb_interface *intf); +int gb_interface_enable(struct gb_interface *intf); +void gb_interface_disable(struct gb_interface *intf); +int gb_interface_add(struct gb_interface *intf); +void gb_interface_del(struct gb_interface *intf); +void gb_interface_put(struct gb_interface *intf); +void gb_interface_mailbox_event(struct gb_interface *intf, u16 result, + u32 mailbox); + +int gb_interface_request_mode_switch(struct gb_interface *intf); + +#endif /* __INTERFACE_H */ diff --git a/include/linux/greybus/manifest.h b/include/linux/greybus/manifest.h new file mode 100644 index 000000000000..830301b7a8bc --- /dev/null +++ b/include/linux/greybus/manifest.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Greybus manifest parsing + * + * Copyright 2014 Google Inc. + * Copyright 2014 Linaro Ltd. + */ + +#ifndef __MANIFEST_H +#define __MANIFEST_H + +#include <linux/types.h> + +struct gb_interface; +bool gb_manifest_parse(struct gb_interface *intf, void *data, size_t size); + +#endif /* __MANIFEST_H */ diff --git a/include/linux/greybus/module.h b/include/linux/greybus/module.h new file mode 100644 index 000000000000..47b839af145d --- /dev/null +++ b/include/linux/greybus/module.h @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Greybus Module code + * + * Copyright 2016 Google Inc. + * Copyright 2016 Linaro Ltd. + */ + +#ifndef __MODULE_H +#define __MODULE_H + +#include <linux/types.h> +#include <linux/device.h> + +struct gb_module { + struct device dev; + struct gb_host_device *hd; + + struct list_head hd_node; + + u8 module_id; + size_t num_interfaces; + + bool disconnected; + + struct gb_interface *interfaces[0]; +}; +#define to_gb_module(d) container_of(d, struct gb_module, dev) + +struct gb_module *gb_module_create(struct gb_host_device *hd, u8 module_id, + size_t num_interfaces); +int gb_module_add(struct gb_module *module); +void gb_module_del(struct gb_module *module); +void gb_module_put(struct gb_module *module); + +#endif /* __MODULE_H */ diff --git a/include/linux/greybus/operation.h b/include/linux/greybus/operation.h new file mode 100644 index 000000000000..cb8e4ef45222 --- /dev/null +++ b/include/linux/greybus/operation.h @@ -0,0 +1,229 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Greybus operations + * + * Copyright 2014 Google Inc. + * Copyright 2014 Linaro Ltd. + */ + +#ifndef __OPERATION_H +#define __OPERATION_H + +#include <linux/completion.h> +#include <linux/kref.h> +#include <linux/timer.h> +#include <linux/types.h> +#include <linux/workqueue.h> + +struct gb_host_device; +struct gb_operation; + +/* The default amount of time a request is given to complete */ +#define GB_OPERATION_TIMEOUT_DEFAULT 1000 /* milliseconds */ + +/* + * The top bit of the type in an operation message header indicates + * whether the message is a request (bit clear) or response (bit set) + */ +#define GB_MESSAGE_TYPE_RESPONSE ((u8)0x80) + +enum gb_operation_result { + GB_OP_SUCCESS = 0x00, + GB_OP_INTERRUPTED = 0x01, + GB_OP_TIMEOUT = 0x02, + GB_OP_NO_MEMORY = 0x03, + GB_OP_PROTOCOL_BAD = 0x04, + GB_OP_OVERFLOW = 0x05, + GB_OP_INVALID = 0x06, + GB_OP_RETRY = 0x07, + GB_OP_NONEXISTENT = 0x08, + GB_OP_UNKNOWN_ERROR = 0xfe, + GB_OP_MALFUNCTION = 0xff, +}; + +#define GB_OPERATION_MESSAGE_SIZE_MIN sizeof(struct gb_operation_msg_hdr) +#define GB_OPERATION_MESSAGE_SIZE_MAX U16_MAX + +/* + * Protocol code should only examine the payload and payload_size fields, and + * host-controller drivers may use the hcpriv field. All other fields are + * intended to be private to the operations core code. + */ +struct gb_message { + struct gb_operation *operation; + struct gb_operation_msg_hdr *header; + + void *payload; + size_t payload_size; + + void *buffer; + + void *hcpriv; +}; + +#define GB_OPERATION_FLAG_INCOMING BIT(0) +#define GB_OPERATION_FLAG_UNIDIRECTIONAL BIT(1) +#define GB_OPERATION_FLAG_SHORT_RESPONSE BIT(2) +#define GB_OPERATION_FLAG_CORE BIT(3) + +#define GB_OPERATION_FLAG_USER_MASK (GB_OPERATION_FLAG_SHORT_RESPONSE | \ + GB_OPERATION_FLAG_UNIDIRECTIONAL) + +/* + * A Greybus operation is a remote procedure call performed over a + * connection between two UniPro interfaces. + * + * Every operation consists of a request message sent to the other + * end of the connection coupled with a reply message returned to + * the sender. Every operation has a type, whose interpretation is + * dependent on the protocol associated with the connection. + * + * Only four things in an operation structure are intended to be + * directly usable by protocol handlers: the operation's connection + * pointer; the operation type; the request message payload (and + * size); and the response message payload (and size). Note that a + * message with a 0-byte payload has a null message payload pointer. + * + * In addition, every operation has a result, which is an errno + * value. Protocol handlers access the operation result using + * gb_operation_result(). + */ +typedef void (*gb_operation_callback)(struct gb_operation *); +struct gb_operation { + struct gb_connection *connection; + struct gb_message *request; + struct gb_message *response; + + unsigned long flags; + u8 type; + u16 id; + int errno; /* Operation result */ + + struct work_struct work; + gb_operation_callback callback; + struct completion completion; + struct timer_list timer; + + struct kref kref; + atomic_t waiters; + + int active; + struct list_head links; /* connection->operations */ + + void *private; +}; + +static inline bool +gb_operation_is_incoming(struct gb_operation *operation) +{ + return operation->flags & GB_OPERATION_FLAG_INCOMING; +} + +static inline bool +gb_operation_is_unidirectional(struct gb_operation *operation) +{ + return operation->flags & GB_OPERATION_FLAG_UNIDIRECTIONAL; +} + +static inline bool +gb_operation_short_response_allowed(struct gb_operation *operation) +{ + return operation->flags & GB_OPERATION_FLAG_SHORT_RESPONSE; +} + +static inline bool gb_operation_is_core(struct gb_operation *operation) +{ + return operation->flags & GB_OPERATION_FLAG_CORE; +} + +void gb_connection_recv(struct gb_connection *connection, + void *data, size_t size); + +int gb_operation_result(struct gb_operation *operation); + +size_t gb_operation_get_payload_size_max(struct gb_connection *connection); +struct gb_operation * +gb_operation_create_flags(struct gb_connection *connection, + u8 type, size_t request_size, + size_t response_size, unsigned long flags, + gfp_t gfp); + +static inline struct gb_operation * +gb_operation_create(struct gb_connection *connection, + u8 type, size_t request_size, + size_t response_size, gfp_t gfp) +{ + return gb_operation_create_flags(connection, type, request_size, + response_size, 0, gfp); +} + +struct gb_operation * +gb_operation_create_core(struct gb_connection *connection, + u8 type, size_t request_size, + size_t response_size, unsigned long flags, + gfp_t gfp); + +void gb_operation_get(struct gb_operation *operation); +void gb_operation_put(struct gb_operation *operation); + +bool gb_operation_response_alloc(struct gb_operation *operation, + size_t response_size, gfp_t gfp); + +int gb_operation_request_send(struct gb_operation *operation, + gb_operation_callback callback, + unsigned int timeout, + gfp_t gfp); +int gb_operation_request_send_sync_timeout(struct gb_operation *operation, + unsigned int timeout); +static inline int +gb_operation_request_send_sync(struct gb_operation *operation) +{ + return gb_operation_request_send_sync_timeout(operation, + GB_OPERATION_TIMEOUT_DEFAULT); +} + +void gb_operation_cancel(struct gb_operation *operation, int errno); +void gb_operation_cancel_incoming(struct gb_operation *operation, int errno); + +void greybus_message_sent(struct gb_host_device *hd, + struct gb_message *message, int status); + +int gb_operation_sync_timeout(struct gb_connection *connection, int type, + void *request, int request_size, + void *response, int response_size, + unsigned int timeout); +int gb_operation_unidirectional_timeout(struct gb_connection *connection, + int type, void *request, int request_size, + unsigned int timeout); + +static inline int gb_operation_sync(struct gb_connection *connection, int type, + void *request, int request_size, + void *response, int response_size) +{ + return gb_operation_sync_timeout(connection, type, + request, request_size, response, response_size, + GB_OPERATION_TIMEOUT_DEFAULT); +} + +static inline int gb_operation_unidirectional(struct gb_connection *connection, + int type, void *request, int request_size) +{ + return gb_operation_unidirectional_timeout(connection, type, + request, request_size, GB_OPERATION_TIMEOUT_DEFAULT); +} + +static inline void *gb_operation_get_data(struct gb_operation *operation) +{ + return operation->private; +} + +static inline void gb_operation_set_data(struct gb_operation *operation, + void *data) +{ + operation->private = data; +} + +int gb_operation_init(void); +void gb_operation_exit(void); + +#endif /* !__OPERATION_H */ diff --git a/include/linux/greybus/svc.h b/include/linux/greybus/svc.h new file mode 100644 index 000000000000..5afaf5f06856 --- /dev/null +++ b/include/linux/greybus/svc.h @@ -0,0 +1,106 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Greybus SVC code + * + * Copyright 2015 Google Inc. + * Copyright 2015 Linaro Ltd. + */ + +#ifndef __SVC_H +#define __SVC_H + +#include <linux/types.h> +#include <linux/device.h> + +struct gb_svc_l2_timer_cfg; + +#define GB_SVC_CPORT_FLAG_E2EFC BIT(0) +#define GB_SVC_CPORT_FLAG_CSD_N BIT(1) +#define GB_SVC_CPORT_FLAG_CSV_N BIT(2) + +enum gb_svc_state { + GB_SVC_STATE_RESET, + GB_SVC_STATE_PROTOCOL_VERSION, + GB_SVC_STATE_SVC_HELLO, +}; + +enum gb_svc_watchdog_bite { + GB_SVC_WATCHDOG_BITE_RESET_UNIPRO = 0, + GB_SVC_WATCHDOG_BITE_PANIC_KERNEL, +}; + +struct gb_svc_watchdog; + +struct svc_debugfs_pwrmon_rail { + u8 id; + struct gb_svc *svc; +}; + +struct gb_svc { + struct device dev; + + struct gb_host_device *hd; + struct gb_connection *connection; + enum gb_svc_state state; + struct ida device_id_map; + struct workqueue_struct *wq; + + u16 endo_id; + u8 ap_intf_id; + + u8 protocol_major; + u8 protocol_minor; + + struct gb_svc_watchdog *watchdog; + enum gb_svc_watchdog_bite action; + + struct dentry *debugfs_dentry; + struct svc_debugfs_pwrmon_rail *pwrmon_rails; +}; +#define to_gb_svc(d) container_of(d, struct gb_svc, dev) + +struct gb_svc *gb_svc_create(struct gb_host_device *hd); +int gb_svc_add(struct gb_svc *svc); +void gb_svc_del(struct gb_svc *svc); +void gb_svc_put(struct gb_svc *svc); + +int gb_svc_pwrmon_intf_sample_get(struct gb_svc *svc, u8 intf_id, + u8 measurement_type, u32 *value); +int gb_svc_intf_device_id(struct gb_svc *svc, u8 intf_id, u8 device_id); +int gb_svc_route_create(struct gb_svc *svc, u8 intf1_id, u8 dev1_id, + u8 intf2_id, u8 dev2_id); +void gb_svc_route_destroy(struct gb_svc *svc, u8 intf1_id, u8 intf2_id); +int gb_svc_connection_create(struct gb_svc *svc, u8 intf1_id, u16 cport1_id, + u8 intf2_id, u16 cport2_id, u8 cport_flags); +void gb_svc_connection_destroy(struct gb_svc *svc, u8 intf1_id, u16 cport1_id, + u8 intf2_id, u16 cport2_id); +int gb_svc_intf_eject(struct gb_svc *svc, u8 intf_id); +int gb_svc_intf_vsys_set(struct gb_svc *svc, u8 intf_id, bool enable); +int gb_svc_intf_refclk_set(struct gb_svc *svc, u8 intf_id, bool enable); +int gb_svc_intf_unipro_set(struct gb_svc *svc, u8 intf_id, bool enable); +int gb_svc_intf_activate(struct gb_svc *svc, u8 intf_id, u8 *intf_type); +int gb_svc_intf_resume(struct gb_svc *svc, u8 intf_id); + +int gb_svc_dme_peer_get(struct gb_svc *svc, u8 intf_id, u16 attr, u16 selector, + u32 *value); +int gb_svc_dme_peer_set(struct gb_svc *svc, u8 intf_id, u16 attr, u16 selector, + u32 value); +int gb_svc_intf_set_power_mode(struct gb_svc *svc, u8 intf_id, u8 hs_series, + u8 tx_mode, u8 tx_gear, u8 tx_nlanes, + u8 tx_amplitude, u8 tx_hs_equalizer, + u8 rx_mode, u8 rx_gear, u8 rx_nlanes, + u8 flags, u32 quirks, + struct gb_svc_l2_timer_cfg *local, + struct gb_svc_l2_timer_cfg *remote); +int gb_svc_intf_set_power_mode_hibernate(struct gb_svc *svc, u8 intf_id); +int gb_svc_ping(struct gb_svc *svc); +int gb_svc_watchdog_create(struct gb_svc *svc); +void gb_svc_watchdog_destroy(struct gb_svc *svc); +bool gb_svc_watchdog_enabled(struct gb_svc *svc); +int gb_svc_watchdog_enable(struct gb_svc *svc); +int gb_svc_watchdog_disable(struct gb_svc *svc); + +int gb_svc_protocol_init(void); +void gb_svc_protocol_exit(void); + +#endif /* __SVC_H */ diff --git a/include/linux/hdmi.h b/include/linux/hdmi.h index 927ad6451105..9918a6c910c5 100644 --- a/include/linux/hdmi.h +++ b/include/linux/hdmi.h @@ -47,6 +47,7 @@ enum hdmi_infoframe_type { HDMI_INFOFRAME_TYPE_AVI = 0x82, HDMI_INFOFRAME_TYPE_SPD = 0x83, HDMI_INFOFRAME_TYPE_AUDIO = 0x84, + HDMI_INFOFRAME_TYPE_DRM = 0x87, }; #define HDMI_IEEE_OUI 0x000c03 @@ -55,6 +56,7 @@ enum hdmi_infoframe_type { #define HDMI_AVI_INFOFRAME_SIZE 13 #define HDMI_SPD_INFOFRAME_SIZE 25 #define HDMI_AUDIO_INFOFRAME_SIZE 10 +#define HDMI_DRM_INFOFRAME_SIZE 26 #define HDMI_INFOFRAME_SIZE(type) \ (HDMI_INFOFRAME_HEADER_SIZE + HDMI_ ## type ## _INFOFRAME_SIZE) @@ -152,6 +154,17 @@ enum hdmi_content_type { HDMI_CONTENT_TYPE_GAME, }; +enum hdmi_metadata_type { + HDMI_STATIC_METADATA_TYPE1 = 1, +}; + +enum hdmi_eotf { + HDMI_EOTF_TRADITIONAL_GAMMA_SDR, + HDMI_EOTF_TRADITIONAL_GAMMA_HDR, + HDMI_EOTF_SMPTE_ST2084, + HDMI_EOTF_BT_2100_HLG, +}; + struct hdmi_avi_infoframe { enum hdmi_infoframe_type type; unsigned char version; @@ -175,12 +188,37 @@ struct hdmi_avi_infoframe { unsigned short right_bar; }; +/* DRM Infoframe as per CTA 861.G spec */ +struct hdmi_drm_infoframe { + enum hdmi_infoframe_type type; + unsigned char version; + unsigned char length; + enum hdmi_eotf eotf; + enum hdmi_metadata_type metadata_type; + struct { + u16 x, y; + } display_primaries[3]; + struct { + u16 x, y; + } white_point; + u16 max_display_mastering_luminance; + u16 min_display_mastering_luminance; + u16 max_cll; + u16 max_fall; +}; + int hdmi_avi_infoframe_init(struct hdmi_avi_infoframe *frame); ssize_t hdmi_avi_infoframe_pack(struct hdmi_avi_infoframe *frame, void *buffer, size_t size); ssize_t hdmi_avi_infoframe_pack_only(const struct hdmi_avi_infoframe *frame, void *buffer, size_t size); int hdmi_avi_infoframe_check(struct hdmi_avi_infoframe *frame); +int hdmi_drm_infoframe_init(struct hdmi_drm_infoframe *frame); +ssize_t hdmi_drm_infoframe_pack(struct hdmi_drm_infoframe *frame, void *buffer, + size_t size); +ssize_t hdmi_drm_infoframe_pack_only(const struct hdmi_drm_infoframe *frame, + void *buffer, size_t size); +int hdmi_drm_infoframe_check(struct hdmi_drm_infoframe *frame); enum hdmi_spd_sdi { HDMI_SPD_SDI_UNKNOWN, @@ -320,6 +358,33 @@ struct hdmi_vendor_infoframe { unsigned int s3d_ext_data; }; +/* HDR Metadata as per 861.G spec */ +struct hdr_static_metadata { + __u8 eotf; + __u8 metadata_type; + __u16 max_cll; + __u16 max_fall; + __u16 min_cll; +}; + +/** + * struct hdr_sink_metadata - HDR sink metadata + * + * Metadata Information read from Sink's EDID + */ +struct hdr_sink_metadata { + /** + * @metadata_type: Static_Metadata_Descriptor_ID. + */ + __u32 metadata_type; + /** + * @hdmi_type1: HDR Metadata Infoframe. + */ + union { + struct hdr_static_metadata hdmi_type1; + }; +}; + int hdmi_vendor_infoframe_init(struct hdmi_vendor_infoframe *frame); ssize_t hdmi_vendor_infoframe_pack(struct hdmi_vendor_infoframe *frame, void *buffer, size_t size); @@ -344,6 +409,7 @@ union hdmi_vendor_any_infoframe { * @spd: spd infoframe * @vendor: union of all vendor infoframes * @audio: audio infoframe + * @drm: Dynamic Range and Mastering infoframe * * This is used by the generic pack function. This works since all infoframes * have the same header which also indicates which type of infoframe should be @@ -355,6 +421,7 @@ union hdmi_infoframe { struct hdmi_spd_infoframe spd; union hdmi_vendor_any_infoframe vendor; struct hdmi_audio_infoframe audio; + struct hdmi_drm_infoframe drm; }; ssize_t hdmi_infoframe_pack(union hdmi_infoframe *frame, void *buffer, diff --git a/include/linux/hid.h b/include/linux/hid.h index d770ab1a0479..cd41f209043f 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h @@ -1154,29 +1154,32 @@ int hid_pidff_init(struct hid_device *hid); #define hid_pidff_init NULL #endif -#define dbg_hid(format, arg...) \ +#define dbg_hid(fmt, ...) \ do { \ if (hid_debug) \ - printk(KERN_DEBUG "%s: " format, __FILE__, ##arg); \ + printk(KERN_DEBUG "%s: " fmt, __FILE__, ##__VA_ARGS__); \ } while (0) -#define hid_printk(level, hid, fmt, arg...) \ - dev_printk(level, &(hid)->dev, fmt, ##arg) -#define hid_emerg(hid, fmt, arg...) \ - dev_emerg(&(hid)->dev, fmt, ##arg) -#define hid_crit(hid, fmt, arg...) \ - dev_crit(&(hid)->dev, fmt, ##arg) -#define hid_alert(hid, fmt, arg...) \ - dev_alert(&(hid)->dev, fmt, ##arg) -#define hid_err(hid, fmt, arg...) \ - dev_err(&(hid)->dev, fmt, ##arg) -#define hid_notice(hid, fmt, arg...) \ - dev_notice(&(hid)->dev, fmt, ##arg) -#define hid_warn(hid, fmt, arg...) \ - dev_warn(&(hid)->dev, fmt, ##arg) -#define hid_info(hid, fmt, arg...) \ - dev_info(&(hid)->dev, fmt, ##arg) -#define hid_dbg(hid, fmt, arg...) \ - dev_dbg(&(hid)->dev, fmt, ##arg) +#define hid_err(hid, fmt, ...) \ + dev_err(&(hid)->dev, fmt, ##__VA_ARGS__) +#define hid_notice(hid, fmt, ...) \ + dev_notice(&(hid)->dev, fmt, ##__VA_ARGS__) +#define hid_warn(hid, fmt, ...) \ + dev_warn(&(hid)->dev, fmt, ##__VA_ARGS__) +#define hid_info(hid, fmt, ...) \ + dev_info(&(hid)->dev, fmt, ##__VA_ARGS__) +#define hid_dbg(hid, fmt, ...) \ + dev_dbg(&(hid)->dev, fmt, ##__VA_ARGS__) + +#define hid_err_once(hid, fmt, ...) \ + dev_err_once(&(hid)->dev, fmt, ##__VA_ARGS__) +#define hid_notice_once(hid, fmt, ...) \ + dev_notice_once(&(hid)->dev, fmt, ##__VA_ARGS__) +#define hid_warn_once(hid, fmt, ...) \ + dev_warn_once(&(hid)->dev, fmt, ##__VA_ARGS__) +#define hid_info_once(hid, fmt, ...) \ + dev_info_once(&(hid)->dev, fmt, ##__VA_ARGS__) +#define hid_dbg_once(hid, fmt, ...) \ + dev_dbg_once(&(hid)->dev, fmt, ##__VA_ARGS__) #endif diff --git a/include/linux/hmm.h b/include/linux/hmm.h index 044a36d7c3f8..3fec513b9c00 100644 --- a/include/linux/hmm.h +++ b/include/linux/hmm.h @@ -21,8 +21,8 @@ * * HMM address space mirroring API: * - * Use HMM address space mirroring if you want to mirror range of the CPU page - * table of a process into a device page table. Here, "mirror" means "keep + * Use HMM address space mirroring if you want to mirror a range of the CPU + * page tables of a process into a device page table. Here, "mirror" means "keep * synchronized". Prerequisites: the device must provide the ability to write- * protect its page tables (at PAGE_SIZE granularity), and must be able to * recover from the resulting potential page faults. @@ -62,7 +62,7 @@ #include <linux/kconfig.h> #include <asm/pgtable.h> -#if IS_ENABLED(CONFIG_HMM) +#ifdef CONFIG_HMM_MIRROR #include <linux/device.h> #include <linux/migrate.h> @@ -82,19 +82,15 @@ * @mirrors_sem: read/write semaphore protecting the mirrors list * @wq: wait queue for user waiting on a range invalidation * @notifiers: count of active mmu notifiers - * @dead: is the mm dead ? */ struct hmm { - struct mm_struct *mm; - struct kref kref; - struct mutex lock; + struct mmu_notifier mmu_notifier; + spinlock_t ranges_lock; struct list_head ranges; struct list_head mirrors; - struct mmu_notifier mmu_notifier; struct rw_semaphore mirrors_sem; wait_queue_head_t wq; long notifiers; - bool dead; }; /* @@ -105,10 +101,11 @@ struct hmm { * HMM_PFN_WRITE: CPU page table has write permission set * HMM_PFN_DEVICE_PRIVATE: private device memory (ZONE_DEVICE) * - * The driver provide a flags array, if driver valid bit for an entry is bit - * 3 ie (entry & (1 << 3)) is true if entry is valid then driver must provide + * The driver provides a flags array for mapping page protections to device + * PTE bits. If the driver valid bit for an entry is bit 3, + * i.e., (entry & (1 << 3)), then the driver must provide * an array in hmm_range.flags with hmm_range.flags[HMM_PFN_VALID] == 1 << 3. - * Same logic apply to all flags. This is same idea as vm_page_prot in vma + * Same logic apply to all flags. This is the same idea as vm_page_prot in vma * except that this is per device driver rather than per architecture. */ enum hmm_pfn_flag_e { @@ -129,13 +126,13 @@ enum hmm_pfn_flag_e { * be mirrored by a device, because the entry will never have HMM_PFN_VALID * set and the pfn value is undefined. * - * Driver provide entry value for none entry, error entry and special entry, - * driver can alias (ie use same value for error and special for instance). It - * should not alias none and error or special. + * Driver provides values for none entry, error entry, and special entry. + * Driver can alias (i.e., use same value) error and special, but + * it should not alias none with error or special. * * HMM pfn value returned by hmm_vma_get_pfns() or hmm_vma_fault() will be: * hmm_range.values[HMM_PFN_ERROR] if CPU page table entry is poisonous, - * hmm_range.values[HMM_PFN_NONE] if there is no CPU page table + * hmm_range.values[HMM_PFN_NONE] if there is no CPU page table entry, * hmm_range.values[HMM_PFN_SPECIAL] if CPU page table entry is a special one */ enum hmm_pfn_value_e { @@ -163,7 +160,6 @@ enum hmm_pfn_value_e { */ struct hmm_range { struct hmm *hmm; - struct vm_area_struct *vma; struct list_head list; unsigned long start; unsigned long end; @@ -172,57 +168,27 @@ struct hmm_range { const uint64_t *values; uint64_t default_flags; uint64_t pfn_flags_mask; - uint8_t page_shift; uint8_t pfn_shift; bool valid; }; /* - * hmm_range_page_shift() - return the page shift for the range - * @range: range being queried - * Returns: page shift (page size = 1 << page shift) for the range - */ -static inline unsigned hmm_range_page_shift(const struct hmm_range *range) -{ - return range->page_shift; -} - -/* - * hmm_range_page_size() - return the page size for the range - * @range: range being queried - * Returns: page size for the range in bytes - */ -static inline unsigned long hmm_range_page_size(const struct hmm_range *range) -{ - return 1UL << hmm_range_page_shift(range); -} - -/* * hmm_range_wait_until_valid() - wait for range to be valid * @range: range affected by invalidation to wait on * @timeout: time out for wait in ms (ie abort wait after that period of time) - * Returns: true if the range is valid, false otherwise. + * Return: true if the range is valid, false otherwise. */ static inline bool hmm_range_wait_until_valid(struct hmm_range *range, unsigned long timeout) { - /* Check if mm is dead ? */ - if (range->hmm == NULL || range->hmm->dead || range->hmm->mm == NULL) { - range->valid = false; - return false; - } - if (range->valid) - return true; - wait_event_timeout(range->hmm->wq, range->valid || range->hmm->dead, - msecs_to_jiffies(timeout)); - /* Return current valid status just in case we get lucky */ - return range->valid; + return wait_event_timeout(range->hmm->wq, range->valid, + msecs_to_jiffies(timeout)) != 0; } /* * hmm_range_valid() - test if a range is valid or not * @range: range - * Returns: true if the range is valid, false otherwise. + * Return: true if the range is valid, false otherwise. */ static inline bool hmm_range_valid(struct hmm_range *range) { @@ -233,7 +199,7 @@ static inline bool hmm_range_valid(struct hmm_range *range) * hmm_device_entry_to_page() - return struct page pointed to by a device entry * @range: range use to decode device entry value * @entry: device entry value to get corresponding struct page from - * Returns: struct page pointer if entry is a valid, NULL otherwise + * Return: struct page pointer if entry is a valid, NULL otherwise * * If the device entry is valid (ie valid flag set) then return the struct page * matching the entry value. Otherwise return NULL. @@ -256,7 +222,7 @@ static inline struct page *hmm_device_entry_to_page(const struct hmm_range *rang * hmm_device_entry_to_pfn() - return pfn value store in a device entry * @range: range use to decode device entry value * @entry: device entry to extract pfn from - * Returns: pfn value if device entry is valid, -1UL otherwise + * Return: pfn value if device entry is valid, -1UL otherwise */ static inline unsigned long hmm_device_entry_to_pfn(const struct hmm_range *range, uint64_t pfn) @@ -276,7 +242,7 @@ hmm_device_entry_to_pfn(const struct hmm_range *range, uint64_t pfn) * hmm_device_entry_from_page() - create a valid device entry for a page * @range: range use to encode HMM pfn value * @page: page for which to create the device entry - * Returns: valid device entry for the page + * Return: valid device entry for the page */ static inline uint64_t hmm_device_entry_from_page(const struct hmm_range *range, struct page *page) @@ -289,7 +255,7 @@ static inline uint64_t hmm_device_entry_from_page(const struct hmm_range *range, * hmm_device_entry_from_pfn() - create a valid device entry value from pfn * @range: range use to encode HMM pfn value * @pfn: pfn value for which to create the device entry - * Returns: valid device entry for the pfn + * Return: valid device entry for the pfn */ static inline uint64_t hmm_device_entry_from_pfn(const struct hmm_range *range, unsigned long pfn) @@ -299,43 +265,6 @@ static inline uint64_t hmm_device_entry_from_pfn(const struct hmm_range *range, } /* - * Old API: - * hmm_pfn_to_page() - * hmm_pfn_to_pfn() - * hmm_pfn_from_page() - * hmm_pfn_from_pfn() - * - * This are the OLD API please use new API, it is here to avoid cross-tree - * merge painfullness ie we convert things to new API in stages. - */ -static inline struct page *hmm_pfn_to_page(const struct hmm_range *range, - uint64_t pfn) -{ - return hmm_device_entry_to_page(range, pfn); -} - -static inline unsigned long hmm_pfn_to_pfn(const struct hmm_range *range, - uint64_t pfn) -{ - return hmm_device_entry_to_pfn(range, pfn); -} - -static inline uint64_t hmm_pfn_from_page(const struct hmm_range *range, - struct page *page) -{ - return hmm_device_entry_from_page(range, page); -} - -static inline uint64_t hmm_pfn_from_pfn(const struct hmm_range *range, - unsigned long pfn) -{ - return hmm_device_entry_from_pfn(range, pfn); -} - - - -#if IS_ENABLED(CONFIG_HMM_MIRROR) -/* * Mirroring: how to synchronize device page table with CPU page table. * * A device driver that is participating in HMM mirroring must always @@ -386,29 +315,6 @@ static inline uint64_t hmm_pfn_from_pfn(const struct hmm_range *range, struct hmm_mirror; /* - * enum hmm_update_event - type of update - * @HMM_UPDATE_INVALIDATE: invalidate range (no indication as to why) - */ -enum hmm_update_event { - HMM_UPDATE_INVALIDATE, -}; - -/* - * struct hmm_update - HMM update informations for callback - * - * @start: virtual start address of the range to update - * @end: virtual end address of the range to update - * @event: event triggering the update (what is happening) - * @blockable: can the callback block/sleep ? - */ -struct hmm_update { - unsigned long start; - unsigned long end; - enum hmm_update_event event; - bool blockable; -}; - -/* * struct hmm_mirror_ops - HMM mirror device operations callback * * @update: callback to update range on a device @@ -418,18 +324,19 @@ struct hmm_mirror_ops { * * @mirror: pointer to struct hmm_mirror * - * This is called when the mm_struct is being released. - * The callback should make sure no references to the mirror occur - * after the callback returns. + * This is called when the mm_struct is being released. The callback + * must ensure that all access to any pages obtained from this mirror + * is halted before the callback returns. All future access should + * fault. */ void (*release)(struct hmm_mirror *mirror); /* sync_cpu_device_pagetables() - synchronize page tables * * @mirror: pointer to struct hmm_mirror - * @update: update informations (see struct hmm_update) - * Returns: -EAGAIN if update.blockable false and callback need to - * block, 0 otherwise. + * @update: update information (see struct mmu_notifier_range) + * Return: -EAGAIN if mmu_notifier_range_blockable(update) is false + * and callback needs to block, 0 otherwise. * * This callback ultimately originates from mmu_notifiers when the CPU * page table is updated. The device driver must update its page table @@ -440,8 +347,9 @@ struct hmm_mirror_ops { * page tables are completely updated (TLBs flushed, etc); this is a * synchronous call. */ - int (*sync_cpu_device_pagetables)(struct hmm_mirror *mirror, - const struct hmm_update *update); + int (*sync_cpu_device_pagetables)( + struct hmm_mirror *mirror, + const struct mmu_notifier_range *update); }; /* @@ -465,47 +373,26 @@ int hmm_mirror_register(struct hmm_mirror *mirror, struct mm_struct *mm); void hmm_mirror_unregister(struct hmm_mirror *mirror); /* - * hmm_mirror_mm_is_alive() - test if mm is still alive - * @mirror: the HMM mm mirror for which we want to lock the mmap_sem - * Returns: false if the mm is dead, true otherwise - * - * This is an optimization it will not accurately always return -EINVAL if the - * mm is dead ie there can be false negative (process is being kill but HMM is - * not yet inform of that). It is only intented to be use to optimize out case - * where driver is about to do something time consuming and it would be better - * to skip it if the mm is dead. + * Please see Documentation/vm/hmm.rst for how to use the range API. */ -static inline bool hmm_mirror_mm_is_alive(struct hmm_mirror *mirror) -{ - struct mm_struct *mm; +int hmm_range_register(struct hmm_range *range, struct hmm_mirror *mirror); +void hmm_range_unregister(struct hmm_range *range); - if (!mirror || !mirror->hmm) - return false; - mm = READ_ONCE(mirror->hmm->mm); - if (mirror->hmm->dead || !mm) - return false; +/* + * Retry fault if non-blocking, drop mmap_sem and return -EAGAIN in that case. + */ +#define HMM_FAULT_ALLOW_RETRY (1 << 0) - return true; -} +/* Don't fault in missing PTEs, just snapshot the current state. */ +#define HMM_FAULT_SNAPSHOT (1 << 1) +long hmm_range_fault(struct hmm_range *range, unsigned int flags); -/* - * Please see Documentation/vm/hmm.rst for how to use the range API. - */ -int hmm_range_register(struct hmm_range *range, - struct mm_struct *mm, - unsigned long start, - unsigned long end, - unsigned page_shift); -void hmm_range_unregister(struct hmm_range *range); -long hmm_range_snapshot(struct hmm_range *range); -long hmm_range_fault(struct hmm_range *range, bool block); long hmm_range_dma_map(struct hmm_range *range, struct device *device, dma_addr_t *daddrs, - bool block); + unsigned int flags); long hmm_range_dma_unmap(struct hmm_range *range, - struct vm_area_struct *vma, struct device *device, dma_addr_t *daddrs, bool dirty); @@ -519,262 +406,6 @@ long hmm_range_dma_unmap(struct hmm_range *range, */ #define HMM_RANGE_DEFAULT_TIMEOUT 1000 -/* This is a temporary helper to avoid merge conflict between trees. */ -static inline bool hmm_vma_range_done(struct hmm_range *range) -{ - bool ret = hmm_range_valid(range); - - hmm_range_unregister(range); - return ret; -} - -/* This is a temporary helper to avoid merge conflict between trees. */ -static inline int hmm_vma_fault(struct hmm_range *range, bool block) -{ - long ret; - - /* - * With the old API the driver must set each individual entries with - * the requested flags (valid, write, ...). So here we set the mask to - * keep intact the entries provided by the driver and zero out the - * default_flags. - */ - range->default_flags = 0; - range->pfn_flags_mask = -1UL; - - ret = hmm_range_register(range, range->vma->vm_mm, - range->start, range->end, - PAGE_SHIFT); - if (ret) - return (int)ret; - - if (!hmm_range_wait_until_valid(range, HMM_RANGE_DEFAULT_TIMEOUT)) { - /* - * The mmap_sem was taken by driver we release it here and - * returns -EAGAIN which correspond to mmap_sem have been - * drop in the old API. - */ - up_read(&range->vma->vm_mm->mmap_sem); - return -EAGAIN; - } - - ret = hmm_range_fault(range, block); - if (ret <= 0) { - if (ret == -EBUSY || !ret) { - /* Same as above drop mmap_sem to match old API. */ - up_read(&range->vma->vm_mm->mmap_sem); - ret = -EBUSY; - } else if (ret == -EAGAIN) - ret = -EBUSY; - hmm_range_unregister(range); - return ret; - } - return 0; -} - -/* Below are for HMM internal use only! Not to be used by device driver! */ -void hmm_mm_destroy(struct mm_struct *mm); - -static inline void hmm_mm_init(struct mm_struct *mm) -{ - mm->hmm = NULL; -} -#else /* IS_ENABLED(CONFIG_HMM_MIRROR) */ -static inline void hmm_mm_destroy(struct mm_struct *mm) {} -static inline void hmm_mm_init(struct mm_struct *mm) {} #endif /* IS_ENABLED(CONFIG_HMM_MIRROR) */ -#if IS_ENABLED(CONFIG_DEVICE_PRIVATE) || IS_ENABLED(CONFIG_DEVICE_PUBLIC) -struct hmm_devmem; - -struct page *hmm_vma_alloc_locked_page(struct vm_area_struct *vma, - unsigned long addr); - -/* - * struct hmm_devmem_ops - callback for ZONE_DEVICE memory events - * - * @free: call when refcount on page reach 1 and thus is no longer use - * @fault: call when there is a page fault to unaddressable memory - * - * Both callback happens from page_free() and page_fault() callback of struct - * dev_pagemap respectively. See include/linux/memremap.h for more details on - * those. - * - * The hmm_devmem_ops callback are just here to provide a coherent and - * uniq API to device driver and device driver should not register their - * own page_free() or page_fault() but rely on the hmm_devmem_ops call- - * back. - */ -struct hmm_devmem_ops { - /* - * free() - free a device page - * @devmem: device memory structure (see struct hmm_devmem) - * @page: pointer to struct page being freed - * - * Call back occurs whenever a device page refcount reach 1 which - * means that no one is holding any reference on the page anymore - * (ZONE_DEVICE page have an elevated refcount of 1 as default so - * that they are not release to the general page allocator). - * - * Note that callback has exclusive ownership of the page (as no - * one is holding any reference). - */ - void (*free)(struct hmm_devmem *devmem, struct page *page); - /* - * fault() - CPU page fault or get user page (GUP) - * @devmem: device memory structure (see struct hmm_devmem) - * @vma: virtual memory area containing the virtual address - * @addr: virtual address that faulted or for which there is a GUP - * @page: pointer to struct page backing virtual address (unreliable) - * @flags: FAULT_FLAG_* (see include/linux/mm.h) - * @pmdp: page middle directory - * Returns: VM_FAULT_MINOR/MAJOR on success or one of VM_FAULT_ERROR - * on error - * - * The callback occurs whenever there is a CPU page fault or GUP on a - * virtual address. This means that the device driver must migrate the - * page back to regular memory (CPU accessible). - * - * The device driver is free to migrate more than one page from the - * fault() callback as an optimization. However if device decide to - * migrate more than one page it must always priotirize the faulting - * address over the others. - * - * The struct page pointer is only given as an hint to allow quick - * lookup of internal device driver data. A concurrent migration - * might have already free that page and the virtual address might - * not longer be back by it. So it should not be modified by the - * callback. - * - * Note that mmap semaphore is held in read mode at least when this - * callback occurs, hence the vma is valid upon callback entry. - */ - vm_fault_t (*fault)(struct hmm_devmem *devmem, - struct vm_area_struct *vma, - unsigned long addr, - const struct page *page, - unsigned int flags, - pmd_t *pmdp); -}; - -/* - * struct hmm_devmem - track device memory - * - * @completion: completion object for device memory - * @pfn_first: first pfn for this resource (set by hmm_devmem_add()) - * @pfn_last: last pfn for this resource (set by hmm_devmem_add()) - * @resource: IO resource reserved for this chunk of memory - * @pagemap: device page map for that chunk - * @device: device to bind resource to - * @ops: memory operations callback - * @ref: per CPU refcount - * @page_fault: callback when CPU fault on an unaddressable device page - * - * This an helper structure for device drivers that do not wish to implement - * the gory details related to hotplugging new memoy and allocating struct - * pages. - * - * Device drivers can directly use ZONE_DEVICE memory on their own if they - * wish to do so. - * - * The page_fault() callback must migrate page back, from device memory to - * system memory, so that the CPU can access it. This might fail for various - * reasons (device issues, device have been unplugged, ...). When such error - * conditions happen, the page_fault() callback must return VM_FAULT_SIGBUS and - * set the CPU page table entry to "poisoned". - * - * Note that because memory cgroup charges are transferred to the device memory, - * this should never fail due to memory restrictions. However, allocation - * of a regular system page might still fail because we are out of memory. If - * that happens, the page_fault() callback must return VM_FAULT_OOM. - * - * The page_fault() callback can also try to migrate back multiple pages in one - * chunk, as an optimization. It must, however, prioritize the faulting address - * over all the others. - */ -typedef vm_fault_t (*dev_page_fault_t)(struct vm_area_struct *vma, - unsigned long addr, - const struct page *page, - unsigned int flags, - pmd_t *pmdp); - -struct hmm_devmem { - struct completion completion; - unsigned long pfn_first; - unsigned long pfn_last; - struct resource *resource; - struct device *device; - struct dev_pagemap pagemap; - const struct hmm_devmem_ops *ops; - struct percpu_ref ref; - dev_page_fault_t page_fault; -}; - -/* - * To add (hotplug) device memory, HMM assumes that there is no real resource - * that reserves a range in the physical address space (this is intended to be - * use by unaddressable device memory). It will reserve a physical range big - * enough and allocate struct page for it. - * - * The device driver can wrap the hmm_devmem struct inside a private device - * driver struct. - */ -struct hmm_devmem *hmm_devmem_add(const struct hmm_devmem_ops *ops, - struct device *device, - unsigned long size); -struct hmm_devmem *hmm_devmem_add_resource(const struct hmm_devmem_ops *ops, - struct device *device, - struct resource *res); - -/* - * hmm_devmem_page_set_drvdata - set per-page driver data field - * - * @page: pointer to struct page - * @data: driver data value to set - * - * Because page can not be on lru we have an unsigned long that driver can use - * to store a per page field. This just a simple helper to do that. - */ -static inline void hmm_devmem_page_set_drvdata(struct page *page, - unsigned long data) -{ - page->hmm_data = data; -} - -/* - * hmm_devmem_page_get_drvdata - get per page driver data field - * - * @page: pointer to struct page - * Return: driver data value - */ -static inline unsigned long hmm_devmem_page_get_drvdata(const struct page *page) -{ - return page->hmm_data; -} - - -/* - * struct hmm_device - fake device to hang device memory onto - * - * @device: device struct - * @minor: device minor number - */ -struct hmm_device { - struct device device; - unsigned int minor; -}; - -/* - * A device driver that wants to handle multiple devices memory through a - * single fake device can use hmm_device to do so. This is purely a helper and - * it is not strictly needed, in order to make use of any HMM functionality. - */ -struct hmm_device *hmm_device_new(void *drvdata); -void hmm_device_put(struct hmm_device *hmm_device); -#endif /* CONFIG_DEVICE_PRIVATE || CONFIG_DEVICE_PUBLIC */ -#else /* IS_ENABLED(CONFIG_HMM) */ -static inline void hmm_mm_destroy(struct mm_struct *mm) {} -static inline void hmm_mm_init(struct mm_struct *mm) {} -#endif /* IS_ENABLED(CONFIG_HMM) */ - #endif /* LINUX_HMM_H */ diff --git a/include/linux/host1x.h b/include/linux/host1x.h index cfff30b9a62e..e6eea45e1154 100644 --- a/include/linux/host1x.h +++ b/include/linux/host1x.h @@ -297,6 +297,8 @@ struct host1x_device { struct list_head clients; bool registered; + + struct device_dma_parameters dma_parms; }; static inline struct host1x_device *to_host1x_device(struct device *dev) diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h index 2e8957eac4d4..1b9a51a1bccb 100644 --- a/include/linux/hrtimer.h +++ b/include/linux/hrtimer.h @@ -12,8 +12,8 @@ #ifndef _LINUX_HRTIMER_H #define _LINUX_HRTIMER_H +#include <linux/hrtimer_defs.h> #include <linux/rbtree.h> -#include <linux/ktime.h> #include <linux/init.h> #include <linux/list.h> #include <linux/percpu.h> @@ -32,12 +32,15 @@ struct hrtimer_cpu_base; * when starting the timer) * HRTIMER_MODE_SOFT - Timer callback function will be executed in * soft irq context + * HRTIMER_MODE_HARD - Timer callback function will be executed in + * hard irq context even on PREEMPT_RT. */ enum hrtimer_mode { HRTIMER_MODE_ABS = 0x00, HRTIMER_MODE_REL = 0x01, HRTIMER_MODE_PINNED = 0x02, HRTIMER_MODE_SOFT = 0x04, + HRTIMER_MODE_HARD = 0x08, HRTIMER_MODE_ABS_PINNED = HRTIMER_MODE_ABS | HRTIMER_MODE_PINNED, HRTIMER_MODE_REL_PINNED = HRTIMER_MODE_REL | HRTIMER_MODE_PINNED, @@ -48,6 +51,11 @@ enum hrtimer_mode { HRTIMER_MODE_ABS_PINNED_SOFT = HRTIMER_MODE_ABS_PINNED | HRTIMER_MODE_SOFT, HRTIMER_MODE_REL_PINNED_SOFT = HRTIMER_MODE_REL_PINNED | HRTIMER_MODE_SOFT, + HRTIMER_MODE_ABS_HARD = HRTIMER_MODE_ABS | HRTIMER_MODE_HARD, + HRTIMER_MODE_REL_HARD = HRTIMER_MODE_REL | HRTIMER_MODE_HARD, + + HRTIMER_MODE_ABS_PINNED_HARD = HRTIMER_MODE_ABS_PINNED | HRTIMER_MODE_HARD, + HRTIMER_MODE_REL_PINNED_HARD = HRTIMER_MODE_REL_PINNED | HRTIMER_MODE_HARD, }; /* @@ -101,6 +109,8 @@ enum hrtimer_restart { * @state: state information (See bit values above) * @is_rel: Set if the timer was armed relative * @is_soft: Set if hrtimer will be expired in soft interrupt context. + * @is_hard: Set if hrtimer will be expired in hard interrupt context + * even on RT. * * The hrtimer structure must be initialized by hrtimer_init() */ @@ -112,6 +122,7 @@ struct hrtimer { u8 state; u8 is_rel; u8 is_soft; + u8 is_hard; }; /** @@ -183,6 +194,10 @@ enum hrtimer_base_type { * @nr_retries: Total number of hrtimer interrupt retries * @nr_hangs: Total number of hrtimer interrupt hangs * @max_hang_time: Maximum time spent in hrtimer_interrupt + * @softirq_expiry_lock: Lock which is taken while softirq based hrtimer are + * expired + * @timer_waiters: A hrtimer_cancel() invocation waits for the timer + * callback to finish. * @expires_next: absolute time of the next event, is required for remote * hrtimer enqueue; it is the total first expiry time (hard * and soft hrtimer are taken into account) @@ -210,6 +225,10 @@ struct hrtimer_cpu_base { unsigned short nr_hangs; unsigned int max_hang_time; #endif +#ifdef CONFIG_PREEMPT_RT + spinlock_t softirq_expiry_lock; + atomic_t timer_waiters; +#endif ktime_t expires_next; struct hrtimer *next_timer; ktime_t softirq_expires_next; @@ -298,26 +317,12 @@ struct clock_event_device; extern void hrtimer_interrupt(struct clock_event_device *dev); -/* - * The resolution of the clocks. The resolution value is returned in - * the clock_getres() system call to give application programmers an - * idea of the (in)accuracy of timers. Timer values are rounded up to - * this resolution values. - */ -# define HIGH_RES_NSEC 1 -# define KTIME_HIGH_RES (HIGH_RES_NSEC) -# define MONOTONIC_RES_NSEC HIGH_RES_NSEC -# define KTIME_MONOTONIC_RES KTIME_HIGH_RES - extern void clock_was_set_delayed(void); extern unsigned int hrtimer_resolution; #else -# define MONOTONIC_RES_NSEC LOW_RES_NSEC -# define KTIME_MONOTONIC_RES KTIME_LOW_RES - #define hrtimer_resolution (unsigned int)LOW_RES_NSEC static inline void clock_was_set_delayed(void) { } @@ -355,16 +360,29 @@ extern void hrtimers_resume(void); DECLARE_PER_CPU(struct tick_device, tick_cpu_device); +#ifdef CONFIG_PREEMPT_RT +void hrtimer_cancel_wait_running(const struct hrtimer *timer); +#else +static inline void hrtimer_cancel_wait_running(struct hrtimer *timer) +{ + cpu_relax(); +} +#endif /* Exported timer functions: */ /* Initialize timers: */ extern void hrtimer_init(struct hrtimer *timer, clockid_t which_clock, enum hrtimer_mode mode); +extern void hrtimer_init_sleeper(struct hrtimer_sleeper *sl, clockid_t clock_id, + enum hrtimer_mode mode); #ifdef CONFIG_DEBUG_OBJECTS_TIMERS extern void hrtimer_init_on_stack(struct hrtimer *timer, clockid_t which_clock, enum hrtimer_mode mode); +extern void hrtimer_init_sleeper_on_stack(struct hrtimer_sleeper *sl, + clockid_t clock_id, + enum hrtimer_mode mode); extern void destroy_hrtimer_on_stack(struct hrtimer *timer); #else @@ -374,6 +392,14 @@ static inline void hrtimer_init_on_stack(struct hrtimer *timer, { hrtimer_init(timer, which_clock, mode); } + +static inline void hrtimer_init_sleeper_on_stack(struct hrtimer_sleeper *sl, + clockid_t clock_id, + enum hrtimer_mode mode) +{ + hrtimer_init_sleeper(sl, clock_id, mode); +} + static inline void destroy_hrtimer_on_stack(struct hrtimer *timer) { } #endif @@ -409,6 +435,9 @@ static inline void hrtimer_start_expires(struct hrtimer *timer, hrtimer_start_range_ns(timer, soft, delta, mode); } +void hrtimer_sleeper_start_expires(struct hrtimer_sleeper *sl, + enum hrtimer_mode mode); + static inline void hrtimer_restart(struct hrtimer *timer) { hrtimer_start_expires(timer, HRTIMER_MODE_ABS); @@ -477,11 +506,8 @@ extern long hrtimer_nanosleep(const struct timespec64 *rqtp, const enum hrtimer_mode mode, const clockid_t clockid); -extern void hrtimer_init_sleeper(struct hrtimer_sleeper *sl, - struct task_struct *tsk); - extern int schedule_hrtimeout_range(ktime_t *expires, u64 delta, - const enum hrtimer_mode mode); + const enum hrtimer_mode mode); extern int schedule_hrtimeout_range_clock(ktime_t *expires, u64 delta, const enum hrtimer_mode mode, diff --git a/include/linux/hrtimer_defs.h b/include/linux/hrtimer_defs.h new file mode 100644 index 000000000000..2d3e3c5fb946 --- /dev/null +++ b/include/linux/hrtimer_defs.h @@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _LINUX_HRTIMER_DEFS_H +#define _LINUX_HRTIMER_DEFS_H + +#include <linux/ktime.h> + +#ifdef CONFIG_HIGH_RES_TIMERS + +/* + * The resolution of the clocks. The resolution value is returned in + * the clock_getres() system call to give application programmers an + * idea of the (in)accuracy of timers. Timer values are rounded up to + * this resolution values. + */ +# define HIGH_RES_NSEC 1 +# define KTIME_HIGH_RES (HIGH_RES_NSEC) +# define MONOTONIC_RES_NSEC HIGH_RES_NSEC +# define KTIME_MONOTONIC_RES KTIME_HIGH_RES + +#else + +# define MONOTONIC_RES_NSEC LOW_RES_NSEC +# define KTIME_MONOTONIC_RES KTIME_LOW_RES + +#endif + +#endif diff --git a/include/linux/huge_mm.h b/include/linux/huge_mm.h index 7cd5c150c21d..61c9ffd89b05 100644 --- a/include/linux/huge_mm.h +++ b/include/linux/huge_mm.h @@ -121,6 +121,23 @@ static inline bool __transparent_hugepage_enabled(struct vm_area_struct *vma) bool transparent_hugepage_enabled(struct vm_area_struct *vma); +#define HPAGE_CACHE_INDEX_MASK (HPAGE_PMD_NR - 1) + +static inline bool transhuge_vma_suitable(struct vm_area_struct *vma, + unsigned long haddr) +{ + /* Don't have to check pgoff for anonymous vma */ + if (!vma_is_anonymous(vma)) { + if (((vma->vm_start >> PAGE_SHIFT) & HPAGE_CACHE_INDEX_MASK) != + (vma->vm_pgoff & HPAGE_CACHE_INDEX_MASK)) + return false; + } + + if (haddr < vma->vm_start || haddr + HPAGE_PMD_SIZE > vma->vm_end) + return false; + return true; +} + #define transparent_hugepage_use_zero_page() \ (transparent_hugepage_flags & \ (1<<TRANSPARENT_HUGEPAGE_USE_ZERO_PAGE_FLAG)) @@ -250,6 +267,15 @@ static inline bool thp_migration_supported(void) return IS_ENABLED(CONFIG_ARCH_ENABLE_THP_MIGRATION); } +static inline struct list_head *page_deferred_list(struct page *page) +{ + /* + * Global or memcg deferred list in the second tail pages is + * occupied by compound_head. + */ + return &page[2].deferred_list; +} + #else /* CONFIG_TRANSPARENT_HUGEPAGE */ #define HPAGE_PMD_SHIFT ({ BUILD_BUG(); 0; }) #define HPAGE_PMD_MASK ({ BUILD_BUG(); 0; }) @@ -271,6 +297,12 @@ static inline bool transparent_hugepage_enabled(struct vm_area_struct *vma) return false; } +static inline bool transhuge_vma_suitable(struct vm_area_struct *vma, + unsigned long haddr) +{ + return false; +} + static inline void prep_transhuge_page(struct page *page) {} #define transparent_hugepage_flags 0UL diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h index edf476c8cfb9..53fc34f930d0 100644 --- a/include/linux/hugetlb.h +++ b/include/linux/hugetlb.h @@ -16,29 +16,11 @@ struct user_struct; struct mmu_gather; #ifndef is_hugepd -/* - * Some architectures requires a hugepage directory format that is - * required to support multiple hugepage sizes. For example - * a4fe3ce76 "powerpc/mm: Allow more flexible layouts for hugepage pagetables" - * introduced the same on powerpc. This allows for a more flexible hugepage - * pagetable layout. - */ typedef struct { unsigned long pd; } hugepd_t; #define is_hugepd(hugepd) (0) #define __hugepd(x) ((hugepd_t) { (x) }) -static inline int gup_huge_pd(hugepd_t hugepd, unsigned long addr, - unsigned pdshift, unsigned long end, - int write, struct page **pages, int *nr) -{ - return 0; -} -#else -extern int gup_huge_pd(hugepd_t hugepd, unsigned long addr, - unsigned pdshift, unsigned long end, - int write, struct page **pages, int *nr); #endif - #ifdef CONFIG_HUGETLB_PAGE #include <linux/mempolicy.h> @@ -472,7 +454,7 @@ static inline pte_t arch_make_huge_pte(pte_t entry, struct vm_area_struct *vma, static inline struct hstate *page_hstate(struct page *page) { VM_BUG_ON_PAGE(!PageHuge(page), page); - return size_to_hstate(PAGE_SIZE << compound_order(page)); + return size_to_hstate(page_size(page)); } static inline unsigned hstate_index_to_shift(unsigned index) @@ -608,22 +590,92 @@ static inline void huge_ptep_modify_prot_commit(struct vm_area_struct *vma, #else /* CONFIG_HUGETLB_PAGE */ struct hstate {}; -#define alloc_huge_page(v, a, r) NULL -#define alloc_huge_page_node(h, nid) NULL -#define alloc_huge_page_nodemask(h, preferred_nid, nmask) NULL -#define alloc_huge_page_vma(h, vma, address) NULL -#define alloc_bootmem_huge_page(h) NULL -#define hstate_file(f) NULL -#define hstate_sizelog(s) NULL -#define hstate_vma(v) NULL -#define hstate_inode(i) NULL -#define page_hstate(page) NULL -#define huge_page_size(h) PAGE_SIZE -#define huge_page_mask(h) PAGE_MASK -#define vma_kernel_pagesize(v) PAGE_SIZE -#define vma_mmu_pagesize(v) PAGE_SIZE -#define huge_page_order(h) 0 -#define huge_page_shift(h) PAGE_SHIFT + +static inline struct page *alloc_huge_page(struct vm_area_struct *vma, + unsigned long addr, + int avoid_reserve) +{ + return NULL; +} + +static inline struct page *alloc_huge_page_node(struct hstate *h, int nid) +{ + return NULL; +} + +static inline struct page * +alloc_huge_page_nodemask(struct hstate *h, int preferred_nid, nodemask_t *nmask) +{ + return NULL; +} + +static inline struct page *alloc_huge_page_vma(struct hstate *h, + struct vm_area_struct *vma, + unsigned long address) +{ + return NULL; +} + +static inline int __alloc_bootmem_huge_page(struct hstate *h) +{ + return 0; +} + +static inline struct hstate *hstate_file(struct file *f) +{ + return NULL; +} + +static inline struct hstate *hstate_sizelog(int page_size_log) +{ + return NULL; +} + +static inline struct hstate *hstate_vma(struct vm_area_struct *vma) +{ + return NULL; +} + +static inline struct hstate *hstate_inode(struct inode *i) +{ + return NULL; +} + +static inline struct hstate *page_hstate(struct page *page) +{ + return NULL; +} + +static inline unsigned long huge_page_size(struct hstate *h) +{ + return PAGE_SIZE; +} + +static inline unsigned long huge_page_mask(struct hstate *h) +{ + return PAGE_MASK; +} + +static inline unsigned long vma_kernel_pagesize(struct vm_area_struct *vma) +{ + return PAGE_SIZE; +} + +static inline unsigned long vma_mmu_pagesize(struct vm_area_struct *vma) +{ + return PAGE_SIZE; +} + +static inline unsigned int huge_page_order(struct hstate *h) +{ + return 0; +} + +static inline unsigned int huge_page_shift(struct hstate *h) +{ + return PAGE_SHIFT; +} + static inline bool hstate_is_gigantic(struct hstate *h) { return false; diff --git a/include/linux/hw_random.h b/include/linux/hw_random.h index c0b93e0ff0c0..8e6dd908da21 100644 --- a/include/linux/hw_random.h +++ b/include/linux/hw_random.h @@ -1,7 +1,7 @@ /* Hardware Random Number Generator - Please read Documentation/hw_random.txt for details on use. + Please read Documentation/admin-guide/hw_random.rst for details on use. ---------------------------------------------------------- This software may be used and distributed according to the terms diff --git a/include/linux/hwspinlock.h b/include/linux/hwspinlock.h index 0afe693be5f4..bfe7c1f1ac6d 100644 --- a/include/linux/hwspinlock.h +++ b/include/linux/hwspinlock.h @@ -14,9 +14,10 @@ #include <linux/sched.h> /* hwspinlock mode argument */ -#define HWLOCK_IRQSTATE 0x01 /* Disable interrupts, save state */ -#define HWLOCK_IRQ 0x02 /* Disable interrupts, don't save state */ -#define HWLOCK_RAW 0x03 +#define HWLOCK_IRQSTATE 0x01 /* Disable interrupts, save state */ +#define HWLOCK_IRQ 0x02 /* Disable interrupts, don't save state */ +#define HWLOCK_RAW 0x03 +#define HWLOCK_IN_ATOMIC 0x04 /* Called while in atomic context */ struct device; struct device_node; @@ -223,6 +224,23 @@ static inline int hwspin_trylock_raw(struct hwspinlock *hwlock) } /** + * hwspin_trylock_in_atomic() - attempt to lock a specific hwspinlock + * @hwlock: an hwspinlock which we want to trylock + * + * This function attempts to lock an hwspinlock, and will immediately fail + * if the hwspinlock is already taken. + * + * This function shall be called only from an atomic context. + * + * Returns 0 if we successfully locked the hwspinlock, -EBUSY if + * the hwspinlock was already taken, and -EINVAL if @hwlock is invalid. + */ +static inline int hwspin_trylock_in_atomic(struct hwspinlock *hwlock) +{ + return __hwspin_trylock(hwlock, HWLOCK_IN_ATOMIC, NULL); +} + +/** * hwspin_trylock() - attempt to lock a specific hwspinlock * @hwlock: an hwspinlock which we want to trylock * @@ -313,6 +331,28 @@ int hwspin_lock_timeout_raw(struct hwspinlock *hwlock, unsigned int to) } /** + * hwspin_lock_timeout_in_atomic() - lock an hwspinlock with timeout limit + * @hwlock: the hwspinlock to be locked + * @to: timeout value in msecs + * + * This function locks the underlying @hwlock. If the @hwlock + * is already taken, the function will busy loop waiting for it to + * be released, but give up when @timeout msecs have elapsed. + * + * This function shall be called only from an atomic context and the timeout + * value shall not exceed a few msecs. + * + * Returns 0 when the @hwlock was successfully taken, and an appropriate + * error code otherwise (most notably an -ETIMEDOUT if the @hwlock is still + * busy after @timeout msecs). The function will never sleep. + */ +static inline +int hwspin_lock_timeout_in_atomic(struct hwspinlock *hwlock, unsigned int to) +{ + return __hwspin_lock_timeout(hwlock, to, HWLOCK_IN_ATOMIC, NULL); +} + +/** * hwspin_lock_timeout() - lock an hwspinlock with timeout limit * @hwlock: the hwspinlock to be locked * @to: timeout value in msecs @@ -387,6 +427,21 @@ static inline void hwspin_unlock_raw(struct hwspinlock *hwlock) } /** + * hwspin_unlock_in_atomic() - unlock hwspinlock + * @hwlock: a previously-acquired hwspinlock which we want to unlock + * + * This function will unlock a specific hwspinlock. + * + * @hwlock must be already locked (e.g. by hwspin_trylock()) before calling + * this function: it is a bug to call unlock on a @hwlock that is already + * unlocked. + */ +static inline void hwspin_unlock_in_atomic(struct hwspinlock *hwlock) +{ + __hwspin_unlock(hwlock, HWLOCK_IN_ATOMIC, NULL); +} + +/** * hwspin_unlock() - unlock hwspinlock * @hwlock: a previously-acquired hwspinlock which we want to unlock * diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h index 6256cc34c4a6..b4a017093b69 100644 --- a/include/linux/hyperv.h +++ b/include/linux/hyperv.h @@ -245,7 +245,10 @@ struct vmbus_channel_offer { } pipe; } u; /* - * The sub_channel_index is defined in win8. + * The sub_channel_index is defined in Win8: a value of zero means a + * primary channel and a value of non-zero means a sub-channel. + * + * Before Win8, the field is reserved, meaning it's always zero. */ u16 sub_channel_index; u16 reserved3; @@ -423,6 +426,9 @@ enum vmbus_channel_message_type { CHANNELMSG_COUNT }; +/* Hyper-V supports about 2048 channels, and the RELIDs start with 1. */ +#define INVALID_RELID U32_MAX + struct vmbus_channel_message_header { enum vmbus_channel_message_type msgtype; u32 padding; @@ -934,6 +940,11 @@ static inline bool is_hvsock_channel(const struct vmbus_channel *c) VMBUS_CHANNEL_TLNPI_PROVIDER_OFFER); } +static inline bool is_sub_channel(const struct vmbus_channel *c) +{ + return c->offermsg.offer.sub_channel_index != 0; +} + static inline void set_channel_affinity_state(struct vmbus_channel *c, enum hv_numa_policy policy) { @@ -1149,6 +1160,9 @@ struct hv_driver { int (*remove)(struct hv_device *); void (*shutdown)(struct hv_device *); + int (*suspend)(struct hv_device *); + int (*resume)(struct hv_device *); + }; /* Base device object */ @@ -1578,4 +1592,33 @@ hv_pkt_iter_next(struct vmbus_channel *channel, for (pkt = hv_pkt_iter_first(channel); pkt; \ pkt = hv_pkt_iter_next(channel, pkt)) +/* + * Interface for passing data between SR-IOV PF and VF drivers. The VF driver + * sends requests to read and write blocks. Each block must be 128 bytes or + * smaller. Optionally, the VF driver can register a callback function which + * will be invoked when the host says that one or more of the first 64 block + * IDs is "invalid" which means that the VF driver should reread them. + */ +#define HV_CONFIG_BLOCK_SIZE_MAX 128 + +int hyperv_read_cfg_blk(struct pci_dev *dev, void *buf, unsigned int buf_len, + unsigned int block_id, unsigned int *bytes_returned); +int hyperv_write_cfg_blk(struct pci_dev *dev, void *buf, unsigned int len, + unsigned int block_id); +int hyperv_reg_block_invalidate(struct pci_dev *dev, void *context, + void (*block_invalidate)(void *context, + u64 block_mask)); + +struct hyperv_pci_block_ops { + int (*read_block)(struct pci_dev *dev, void *buf, unsigned int buf_len, + unsigned int block_id, unsigned int *bytes_returned); + int (*write_block)(struct pci_dev *dev, void *buf, unsigned int len, + unsigned int block_id); + int (*reg_blk_invalidate)(struct pci_dev *dev, void *context, + void (*block_invalidate)(void *context, + u64 block_mask)); +}; + +extern struct hyperv_pci_block_ops hvpci_block_ops; + #endif /* _HYPERV_H */ diff --git a/include/linux/i2c.h b/include/linux/i2c.h index 1308126fc384..1361637c369d 100644 --- a/include/linux/i2c.h +++ b/include/linux/i2c.h @@ -1,19 +1,16 @@ /* SPDX-License-Identifier: GPL-2.0-or-later */ -/* ------------------------------------------------------------------------- */ -/* */ -/* i2c.h - definitions for the i2c-bus interface */ -/* */ -/* ------------------------------------------------------------------------- */ -/* Copyright (C) 1995-2000 Simon G. Vogl - +/* + * i2c.h - definitions for the Linux i2c bus interface + * Copyright (C) 1995-2000 Simon G. Vogl + * Copyright (C) 2013-2019 Wolfram Sang <wsa@the-dreams.de> + * + * With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and + * Frodo Looijaard <frodol@dds.nl> */ -/* ------------------------------------------------------------------------- */ - -/* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and - Frodo Looijaard <frodol@dds.nl> */ #ifndef _LINUX_I2C_H #define _LINUX_I2C_H +#include <linux/acpi.h> /* for acpi_handle */ #include <linux/mod_devicetable.h> #include <linux/device.h> /* for struct device */ #include <linux/sched.h> /* for completion */ @@ -39,7 +36,8 @@ struct i2c_device_identity; union i2c_smbus_data; struct i2c_board_info; enum i2c_slave_event; -typedef int (*i2c_slave_cb_t)(struct i2c_client *, enum i2c_slave_event, u8 *); +typedef int (*i2c_slave_cb_t)(struct i2c_client *client, + enum i2c_slave_event event, u8 *val); struct module; struct property_entry; @@ -256,16 +254,16 @@ struct i2c_driver { unsigned int class; /* Standard driver model interfaces */ - int (*probe)(struct i2c_client *, const struct i2c_device_id *); - int (*remove)(struct i2c_client *); + int (*probe)(struct i2c_client *client, const struct i2c_device_id *id); + int (*remove)(struct i2c_client *client); /* New driver model interface to aid the seamless removal of the * current probe()'s, more commonly unused than used second parameter. */ - int (*probe_new)(struct i2c_client *); + int (*probe_new)(struct i2c_client *client); /* driver model interfaces that don't relate to enumeration */ - void (*shutdown)(struct i2c_client *); + void (*shutdown)(struct i2c_client *client); /* Alert callback, for example for the SMBus alert protocol. * The format and meaning of the data value depends on the protocol. @@ -274,7 +272,7 @@ struct i2c_driver { * For the SMBus Host Notify protocol, the data corresponds to the * 16-bit payload data reported by the slave device acting as master. */ - void (*alert)(struct i2c_client *, enum i2c_alert_protocol protocol, + void (*alert)(struct i2c_client *client, enum i2c_alert_protocol protocol, unsigned int data); /* a ioctl like command that can be used to perform specific functions @@ -286,7 +284,7 @@ struct i2c_driver { const struct i2c_device_id *id_table; /* Device detection callback for automatic device creation */ - int (*detect)(struct i2c_client *, struct i2c_board_info *); + int (*detect)(struct i2c_client *client, struct i2c_board_info *info); const unsigned short *address_list; struct list_head clients; @@ -296,8 +294,7 @@ struct i2c_driver { /** * struct i2c_client - represent an I2C slave device - * @flags: I2C_CLIENT_TEN indicates the device uses a ten bit chip address; - * I2C_CLIENT_PEC indicates it uses SMBus Packet Error Checking + * @flags: see I2C_CLIENT_* for possible flags * @addr: Address used on the I2C bus connected to the parent adapter. * @name: Indicates the type of the device, usually a chip name that's * generic enough to hide second-sourcing and compatible revisions. @@ -315,6 +312,15 @@ struct i2c_driver { */ struct i2c_client { unsigned short flags; /* div., see below */ +#define I2C_CLIENT_PEC 0x04 /* Use Packet Error Checking */ +#define I2C_CLIENT_TEN 0x10 /* we have a ten bit chip address */ + /* Must equal I2C_M_TEN below */ +#define I2C_CLIENT_SLAVE 0x20 /* we are the slave */ +#define I2C_CLIENT_HOST_NOTIFY 0x40 /* We want to use I2C host notify */ +#define I2C_CLIENT_WAKE 0x80 /* for board_info; true iff can wake */ +#define I2C_CLIENT_SCCB 0x9000 /* Use Omnivision SCCB protocol */ + /* Must match I2C_M_STOP|IGNORE_NAK */ + unsigned short addr; /* chip address - NOTE: 7bit */ /* addresses are stored in the */ /* _LOWER_ 7 bits */ @@ -436,6 +442,9 @@ struct i2c_board_info { extern struct i2c_client * i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info); +extern struct i2c_client * +i2c_new_client_device(struct i2c_adapter *adap, struct i2c_board_info const *info); + /* If you don't know the exact address of an I2C device, use this variant * instead, which can probe for device presence in a list of possible * addresses. The "probe" callback function is optional. If it is provided, @@ -446,10 +455,10 @@ extern struct i2c_client * i2c_new_probed_device(struct i2c_adapter *adap, struct i2c_board_info *info, unsigned short const *addr_list, - int (*probe)(struct i2c_adapter *, unsigned short addr)); + int (*probe)(struct i2c_adapter *adap, unsigned short addr)); /* Common custom probe functions */ -extern int i2c_probe_func_quick_read(struct i2c_adapter *, unsigned short addr); +extern int i2c_probe_func_quick_read(struct i2c_adapter *adap, unsigned short addr); /* For devices that use several addresses, use i2c_new_dummy() to make * client handles for the extra addresses. @@ -458,14 +467,17 @@ extern struct i2c_client * i2c_new_dummy(struct i2c_adapter *adap, u16 address); extern struct i2c_client * +i2c_new_dummy_device(struct i2c_adapter *adapter, u16 address); + +extern struct i2c_client * devm_i2c_new_dummy_device(struct device *dev, struct i2c_adapter *adap, u16 address); extern struct i2c_client * -i2c_new_secondary_device(struct i2c_client *client, +i2c_new_ancillary_device(struct i2c_client *client, const char *name, u16 default_addr); -extern void i2c_unregister_device(struct i2c_client *); +extern void i2c_unregister_device(struct i2c_client *client); #endif /* I2C */ /* Mainboard arch_initcall() code should register all its I2C devices. @@ -509,7 +521,7 @@ i2c_register_board_info(int busnum, struct i2c_board_info const *info, * * The return codes from the @master_xfer{_atomic} fields should indicate the * type of error code that occurred during the transfer, as documented in the - * Kernel Documentation file Documentation/i2c/fault-codes. + * Kernel Documentation file Documentation/i2c/fault-codes.rst. */ struct i2c_algorithm { /* @@ -550,9 +562,9 @@ struct i2c_algorithm { * The main operations are wrapped by i2c_lock_bus and i2c_unlock_bus. */ struct i2c_lock_operations { - void (*lock_bus)(struct i2c_adapter *, unsigned int flags); - int (*trylock_bus)(struct i2c_adapter *, unsigned int flags); - void (*unlock_bus)(struct i2c_adapter *, unsigned int flags); + void (*lock_bus)(struct i2c_adapter *adapter, unsigned int flags); + int (*trylock_bus)(struct i2c_adapter *adapter, unsigned int flags); + void (*unlock_bus)(struct i2c_adapter *adapter, unsigned int flags); }; /** @@ -702,14 +714,14 @@ struct i2c_adapter { }; #define to_i2c_adapter(d) container_of(d, struct i2c_adapter, dev) -static inline void *i2c_get_adapdata(const struct i2c_adapter *dev) +static inline void *i2c_get_adapdata(const struct i2c_adapter *adap) { - return dev_get_drvdata(&dev->dev); + return dev_get_drvdata(&adap->dev); } -static inline void i2c_set_adapdata(struct i2c_adapter *dev, void *data) +static inline void i2c_set_adapdata(struct i2c_adapter *adap, void *data) { - dev_set_drvdata(&dev->dev, data); + dev_set_drvdata(&adap->dev, data); } static inline struct i2c_adapter * @@ -725,7 +737,7 @@ i2c_parent_is_i2c_adapter(const struct i2c_adapter *adapter) return NULL; } -int i2c_for_each_dev(void *data, int (*fn)(struct device *, void *)); +int i2c_for_each_dev(void *data, int (*fn)(struct device *dev, void *data)); /* Adapter locking functions, exported for shared pin cases */ #define I2C_LOCK_ROOT_ADAPTER BIT(0) @@ -801,16 +813,6 @@ static inline void i2c_mark_adapter_resumed(struct i2c_adapter *adap) i2c_unlock_bus(adap, I2C_LOCK_ROOT_ADAPTER); } -/*flags for the client struct: */ -#define I2C_CLIENT_PEC 0x04 /* Use Packet Error Checking */ -#define I2C_CLIENT_TEN 0x10 /* we have a ten bit chip address */ - /* Must equal I2C_M_TEN below */ -#define I2C_CLIENT_SLAVE 0x20 /* we are the slave */ -#define I2C_CLIENT_HOST_NOTIFY 0x40 /* We want to use I2C host notify */ -#define I2C_CLIENT_WAKE 0x80 /* for board_info; true iff can wake */ -#define I2C_CLIENT_SCCB 0x9000 /* Use Omnivision SCCB protocol */ - /* Must match I2C_M_STOP|IGNORE_NAK */ - /* i2c adapter classes (bitmask) */ #define I2C_CLASS_HWMON (1<<0) /* lm_sensors, ... */ #define I2C_CLASS_DDC (1<<3) /* DDC bus on graphics adapters */ @@ -831,12 +833,12 @@ static inline void i2c_mark_adapter_resumed(struct i2c_adapter *adap) /* administration... */ #if IS_ENABLED(CONFIG_I2C) -extern int i2c_add_adapter(struct i2c_adapter *); -extern void i2c_del_adapter(struct i2c_adapter *); -extern int i2c_add_numbered_adapter(struct i2c_adapter *); +extern int i2c_add_adapter(struct i2c_adapter *adap); +extern void i2c_del_adapter(struct i2c_adapter *adap); +extern int i2c_add_numbered_adapter(struct i2c_adapter *adap); -extern int i2c_register_driver(struct module *, struct i2c_driver *); -extern void i2c_del_driver(struct i2c_driver *); +extern int i2c_register_driver(struct module *owner, struct i2c_driver *driver); +extern void i2c_del_driver(struct i2c_driver *driver); /* use a define to avoid include chaining to get THIS_MODULE */ #define i2c_add_driver(driver) \ @@ -981,6 +983,7 @@ bool i2c_acpi_get_i2c_resource(struct acpi_resource *ares, u32 i2c_acpi_find_bus_speed(struct device *dev); struct i2c_client *i2c_acpi_new_device(struct device *dev, int index, struct i2c_board_info *info); +struct i2c_adapter *i2c_acpi_find_adapter_by_handle(acpi_handle handle); #else static inline bool i2c_acpi_get_i2c_resource(struct acpi_resource *ares, struct acpi_resource_i2c_serialbus **i2c) @@ -996,6 +999,10 @@ static inline struct i2c_client *i2c_acpi_new_device(struct device *dev, { return NULL; } +static inline struct i2c_adapter *i2c_acpi_find_adapter_by_handle(acpi_handle handle) +{ + return NULL; +} #endif /* CONFIG_ACPI */ #endif /* _LINUX_I2C_H */ diff --git a/include/linux/i3c/device.h b/include/linux/i3c/device.h index 5ecb055fd375..de102e4418ab 100644 --- a/include/linux/i3c/device.h +++ b/include/linux/i3c/device.h @@ -188,6 +188,10 @@ static inline struct i3c_driver *drv_to_i3cdrv(struct device_driver *drv) struct device *i3cdev_to_dev(struct i3c_device *i3cdev); struct i3c_device *dev_to_i3cdev(struct device *dev); +const struct i3c_device_id * +i3c_device_match_id(struct i3c_device *i3cdev, + const struct i3c_device_id *id_table); + static inline void i3cdev_set_drvdata(struct i3c_device *i3cdev, void *data) { diff --git a/include/linux/i3c/master.h b/include/linux/i3c/master.h index f13fd8b1dd79..9cb39d901cd5 100644 --- a/include/linux/i3c/master.h +++ b/include/linux/i3c/master.h @@ -48,7 +48,7 @@ struct i3c_i2c_dev_desc { #define I3C_LVR_I2C_INDEX(x) ((x) << 5) #define I3C_LVR_I2C_FM_MODE BIT(4) -#define I2C_MAX_ADDR GENMASK(9, 0) +#define I2C_MAX_ADDR GENMASK(6, 0) /** * struct i2c_dev_boardinfo - I2C device board information @@ -71,6 +71,9 @@ struct i2c_dev_boardinfo { * @common: common part of the I2C device descriptor * @boardinfo: pointer to the boardinfo attached to this I2C device * @dev: I2C device object registered to the I2C framework + * @addr: I2C device address + * @lvr: LVR (Legacy Virtual Register) needed by the I3C core to know about + * the I2C device limitations * * Each I2C device connected on the bus will have an i2c_dev_desc. * This object is created by the core and later attached to the controller @@ -84,6 +87,8 @@ struct i2c_dev_desc { struct i3c_i2c_dev_desc common; const struct i2c_dev_boardinfo *boardinfo; struct i2c_client *dev; + u16 addr; + u8 lvr; }; /** @@ -250,12 +255,17 @@ struct i3c_device { * the bus. The only impact in this mode is that the * high SCL pulse has to stay below 50ns to trick I2C * devices when transmitting I3C frames + * @I3C_BUS_MODE_MIXED_LIMITED: I2C devices without 50ns spike filter are + * present on the bus. However they allow + * compliance up to the maximum SDR SCL clock + * frequency. * @I3C_BUS_MODE_MIXED_SLOW: I2C devices without 50ns spike filter are present * on the bus */ enum i3c_bus_mode { I3C_BUS_MODE_PURE, I3C_BUS_MODE_MIXED_FAST, + I3C_BUS_MODE_MIXED_LIMITED, I3C_BUS_MODE_MIXED_SLOW, }; @@ -390,8 +400,6 @@ struct i3c_bus { * and i2c_put_dma_safe_msg_buf() helpers provided by the I2C * framework. * This method is mandatory. - * @i2c_funcs: expose the supported I2C functionalities. - * This method is mandatory. * @request_ibi: attach an IBI handler to an I3C device. This implies defining * an IBI handler and the constraints of the IBI (maximum payload * length and number of pre-allocated slots). @@ -437,7 +445,6 @@ struct i3c_master_controller_ops { void (*detach_i2c_dev)(struct i2c_dev_desc *dev); int (*i2c_xfers)(struct i2c_dev_desc *dev, const struct i2c_msg *xfers, int nxfers); - u32 (*i2c_funcs)(struct i3c_master_controller *master); int (*request_ibi)(struct i3c_dev_desc *dev, const struct i3c_ibi_setup *req); void (*free_ibi)(struct i3c_dev_desc *dev); diff --git a/include/linux/ide.h b/include/linux/ide.h index 971cf76a78a0..46b771d6999e 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -253,9 +253,9 @@ static inline void ide_std_init_ports(struct ide_hw *hw, * Special Driver Flags */ enum { - IDE_SFLAG_SET_GEOMETRY = (1 << 0), - IDE_SFLAG_RECALIBRATE = (1 << 1), - IDE_SFLAG_SET_MULTMODE = (1 << 2), + IDE_SFLAG_SET_GEOMETRY = BIT(0), + IDE_SFLAG_RECALIBRATE = BIT(1), + IDE_SFLAG_SET_MULTMODE = BIT(2), }; /* @@ -267,13 +267,13 @@ typedef enum { } ide_startstop_t; enum { - IDE_VALID_ERROR = (1 << 1), + IDE_VALID_ERROR = BIT(1), IDE_VALID_FEATURE = IDE_VALID_ERROR, - IDE_VALID_NSECT = (1 << 2), - IDE_VALID_LBAL = (1 << 3), - IDE_VALID_LBAM = (1 << 4), - IDE_VALID_LBAH = (1 << 5), - IDE_VALID_DEVICE = (1 << 6), + IDE_VALID_NSECT = BIT(2), + IDE_VALID_LBAL = BIT(3), + IDE_VALID_LBAM = BIT(4), + IDE_VALID_LBAH = BIT(5), + IDE_VALID_DEVICE = BIT(6), IDE_VALID_LBA = IDE_VALID_LBAL | IDE_VALID_LBAM | IDE_VALID_LBAH, @@ -289,24 +289,24 @@ enum { }; enum { - IDE_TFLAG_LBA48 = (1 << 0), - IDE_TFLAG_WRITE = (1 << 1), - IDE_TFLAG_CUSTOM_HANDLER = (1 << 2), - IDE_TFLAG_DMA_PIO_FALLBACK = (1 << 3), + IDE_TFLAG_LBA48 = BIT(0), + IDE_TFLAG_WRITE = BIT(1), + IDE_TFLAG_CUSTOM_HANDLER = BIT(2), + IDE_TFLAG_DMA_PIO_FALLBACK = BIT(3), /* force 16-bit I/O operations */ - IDE_TFLAG_IO_16BIT = (1 << 4), + IDE_TFLAG_IO_16BIT = BIT(4), /* struct ide_cmd was allocated using kmalloc() */ - IDE_TFLAG_DYN = (1 << 5), - IDE_TFLAG_FS = (1 << 6), - IDE_TFLAG_MULTI_PIO = (1 << 7), - IDE_TFLAG_SET_XFER = (1 << 8), + IDE_TFLAG_DYN = BIT(5), + IDE_TFLAG_FS = BIT(6), + IDE_TFLAG_MULTI_PIO = BIT(7), + IDE_TFLAG_SET_XFER = BIT(8), }; enum { - IDE_FTFLAG_FLAGGED = (1 << 0), - IDE_FTFLAG_SET_IN_FLAGS = (1 << 1), - IDE_FTFLAG_OUT_DATA = (1 << 2), - IDE_FTFLAG_IN_DATA = (1 << 3), + IDE_FTFLAG_FLAGGED = BIT(0), + IDE_FTFLAG_SET_IN_FLAGS = BIT(1), + IDE_FTFLAG_OUT_DATA = BIT(2), + IDE_FTFLAG_IN_DATA = BIT(3), }; struct ide_taskfile { @@ -357,13 +357,13 @@ struct ide_cmd { /* ATAPI packet command flags */ enum { /* set when an error is considered normal - no retry (ide-tape) */ - PC_FLAG_ABORT = (1 << 0), - PC_FLAG_SUPPRESS_ERROR = (1 << 1), - PC_FLAG_WAIT_FOR_DSC = (1 << 2), - PC_FLAG_DMA_OK = (1 << 3), - PC_FLAG_DMA_IN_PROGRESS = (1 << 4), - PC_FLAG_DMA_ERROR = (1 << 5), - PC_FLAG_WRITING = (1 << 6), + PC_FLAG_ABORT = BIT(0), + PC_FLAG_SUPPRESS_ERROR = BIT(1), + PC_FLAG_WAIT_FOR_DSC = BIT(2), + PC_FLAG_DMA_OK = BIT(3), + PC_FLAG_DMA_IN_PROGRESS = BIT(4), + PC_FLAG_DMA_ERROR = BIT(5), + PC_FLAG_WRITING = BIT(6), }; #define ATAPI_WAIT_PC (60 * HZ) @@ -417,111 +417,111 @@ struct ide_disk_ops { /* ATAPI device flags */ enum { - IDE_AFLAG_DRQ_INTERRUPT = (1 << 0), + IDE_AFLAG_DRQ_INTERRUPT = BIT(0), /* ide-cd */ /* Drive cannot eject the disc. */ - IDE_AFLAG_NO_EJECT = (1 << 1), + IDE_AFLAG_NO_EJECT = BIT(1), /* Drive is a pre ATAPI 1.2 drive. */ - IDE_AFLAG_PRE_ATAPI12 = (1 << 2), + IDE_AFLAG_PRE_ATAPI12 = BIT(2), /* TOC addresses are in BCD. */ - IDE_AFLAG_TOCADDR_AS_BCD = (1 << 3), + IDE_AFLAG_TOCADDR_AS_BCD = BIT(3), /* TOC track numbers are in BCD. */ - IDE_AFLAG_TOCTRACKS_AS_BCD = (1 << 4), + IDE_AFLAG_TOCTRACKS_AS_BCD = BIT(4), /* Saved TOC information is current. */ - IDE_AFLAG_TOC_VALID = (1 << 6), + IDE_AFLAG_TOC_VALID = BIT(6), /* We think that the drive door is locked. */ - IDE_AFLAG_DOOR_LOCKED = (1 << 7), + IDE_AFLAG_DOOR_LOCKED = BIT(7), /* SET_CD_SPEED command is unsupported. */ - IDE_AFLAG_NO_SPEED_SELECT = (1 << 8), - IDE_AFLAG_VERTOS_300_SSD = (1 << 9), - IDE_AFLAG_VERTOS_600_ESD = (1 << 10), - IDE_AFLAG_SANYO_3CD = (1 << 11), - IDE_AFLAG_FULL_CAPS_PAGE = (1 << 12), - IDE_AFLAG_PLAY_AUDIO_OK = (1 << 13), - IDE_AFLAG_LE_SPEED_FIELDS = (1 << 14), + IDE_AFLAG_NO_SPEED_SELECT = BIT(8), + IDE_AFLAG_VERTOS_300_SSD = BIT(9), + IDE_AFLAG_VERTOS_600_ESD = BIT(10), + IDE_AFLAG_SANYO_3CD = BIT(11), + IDE_AFLAG_FULL_CAPS_PAGE = BIT(12), + IDE_AFLAG_PLAY_AUDIO_OK = BIT(13), + IDE_AFLAG_LE_SPEED_FIELDS = BIT(14), /* ide-floppy */ /* Avoid commands not supported in Clik drive */ - IDE_AFLAG_CLIK_DRIVE = (1 << 15), + IDE_AFLAG_CLIK_DRIVE = BIT(15), /* Requires BH algorithm for packets */ - IDE_AFLAG_ZIP_DRIVE = (1 << 16), + IDE_AFLAG_ZIP_DRIVE = BIT(16), /* Supports format progress report */ - IDE_AFLAG_SRFP = (1 << 17), + IDE_AFLAG_SRFP = BIT(17), /* ide-tape */ - IDE_AFLAG_IGNORE_DSC = (1 << 18), + IDE_AFLAG_IGNORE_DSC = BIT(18), /* 0 When the tape position is unknown */ - IDE_AFLAG_ADDRESS_VALID = (1 << 19), + IDE_AFLAG_ADDRESS_VALID = BIT(19), /* Device already opened */ - IDE_AFLAG_BUSY = (1 << 20), + IDE_AFLAG_BUSY = BIT(20), /* Attempt to auto-detect the current user block size */ - IDE_AFLAG_DETECT_BS = (1 << 21), + IDE_AFLAG_DETECT_BS = BIT(21), /* Currently on a filemark */ - IDE_AFLAG_FILEMARK = (1 << 22), + IDE_AFLAG_FILEMARK = BIT(22), /* 0 = no tape is loaded, so we don't rewind after ejecting */ - IDE_AFLAG_MEDIUM_PRESENT = (1 << 23), + IDE_AFLAG_MEDIUM_PRESENT = BIT(23), - IDE_AFLAG_NO_AUTOCLOSE = (1 << 24), + IDE_AFLAG_NO_AUTOCLOSE = BIT(24), }; /* device flags */ enum { /* restore settings after device reset */ - IDE_DFLAG_KEEP_SETTINGS = (1 << 0), + IDE_DFLAG_KEEP_SETTINGS = BIT(0), /* device is using DMA for read/write */ - IDE_DFLAG_USING_DMA = (1 << 1), + IDE_DFLAG_USING_DMA = BIT(1), /* okay to unmask other IRQs */ - IDE_DFLAG_UNMASK = (1 << 2), + IDE_DFLAG_UNMASK = BIT(2), /* don't attempt flushes */ - IDE_DFLAG_NOFLUSH = (1 << 3), + IDE_DFLAG_NOFLUSH = BIT(3), /* DSC overlap */ - IDE_DFLAG_DSC_OVERLAP = (1 << 4), + IDE_DFLAG_DSC_OVERLAP = BIT(4), /* give potential excess bandwidth */ - IDE_DFLAG_NICE1 = (1 << 5), + IDE_DFLAG_NICE1 = BIT(5), /* device is physically present */ - IDE_DFLAG_PRESENT = (1 << 6), + IDE_DFLAG_PRESENT = BIT(6), /* disable Host Protected Area */ - IDE_DFLAG_NOHPA = (1 << 7), + IDE_DFLAG_NOHPA = BIT(7), /* id read from device (synthetic if not set) */ - IDE_DFLAG_ID_READ = (1 << 8), - IDE_DFLAG_NOPROBE = (1 << 9), + IDE_DFLAG_ID_READ = BIT(8), + IDE_DFLAG_NOPROBE = BIT(9), /* need to do check_media_change() */ - IDE_DFLAG_REMOVABLE = (1 << 10), + IDE_DFLAG_REMOVABLE = BIT(10), /* needed for removable devices */ - IDE_DFLAG_ATTACH = (1 << 11), - IDE_DFLAG_FORCED_GEOM = (1 << 12), + IDE_DFLAG_ATTACH = BIT(11), + IDE_DFLAG_FORCED_GEOM = BIT(12), /* disallow setting unmask bit */ - IDE_DFLAG_NO_UNMASK = (1 << 13), + IDE_DFLAG_NO_UNMASK = BIT(13), /* disallow enabling 32-bit I/O */ - IDE_DFLAG_NO_IO_32BIT = (1 << 14), + IDE_DFLAG_NO_IO_32BIT = BIT(14), /* for removable only: door lock/unlock works */ - IDE_DFLAG_DOORLOCKING = (1 << 15), + IDE_DFLAG_DOORLOCKING = BIT(15), /* disallow DMA */ - IDE_DFLAG_NODMA = (1 << 16), + IDE_DFLAG_NODMA = BIT(16), /* powermanagement told us not to do anything, so sleep nicely */ - IDE_DFLAG_BLOCKED = (1 << 17), + IDE_DFLAG_BLOCKED = BIT(17), /* sleeping & sleep field valid */ - IDE_DFLAG_SLEEPING = (1 << 18), - IDE_DFLAG_POST_RESET = (1 << 19), - IDE_DFLAG_UDMA33_WARNED = (1 << 20), - IDE_DFLAG_LBA48 = (1 << 21), + IDE_DFLAG_SLEEPING = BIT(18), + IDE_DFLAG_POST_RESET = BIT(19), + IDE_DFLAG_UDMA33_WARNED = BIT(20), + IDE_DFLAG_LBA48 = BIT(21), /* status of write cache */ - IDE_DFLAG_WCACHE = (1 << 22), + IDE_DFLAG_WCACHE = BIT(22), /* used for ignoring ATA_DF */ - IDE_DFLAG_NOWERR = (1 << 23), + IDE_DFLAG_NOWERR = BIT(23), /* retrying in PIO */ - IDE_DFLAG_DMA_PIO_RETRY = (1 << 24), - IDE_DFLAG_LBA = (1 << 25), + IDE_DFLAG_DMA_PIO_RETRY = BIT(24), + IDE_DFLAG_LBA = BIT(25), /* don't unload heads */ - IDE_DFLAG_NO_UNLOAD = (1 << 26), + IDE_DFLAG_NO_UNLOAD = BIT(26), /* heads unloaded, please don't reset port */ - IDE_DFLAG_PARKED = (1 << 27), - IDE_DFLAG_MEDIA_CHANGED = (1 << 28), + IDE_DFLAG_PARKED = BIT(27), + IDE_DFLAG_MEDIA_CHANGED = BIT(28), /* write protect */ - IDE_DFLAG_WP = (1 << 29), - IDE_DFLAG_FORMAT_IN_PROGRESS = (1 << 30), - IDE_DFLAG_NIEN_QUIRK = (1 << 31), + IDE_DFLAG_WP = BIT(29), + IDE_DFLAG_FORMAT_IN_PROGRESS = BIT(30), + IDE_DFLAG_NIEN_QUIRK = BIT(31), }; struct ide_drive_s { @@ -709,7 +709,7 @@ struct ide_dma_ops { }; enum { - IDE_PFLAG_PROBING = (1 << 0), + IDE_PFLAG_PROBING = BIT(0), }; struct ide_host; @@ -862,7 +862,7 @@ extern struct mutex ide_setting_mtx; * configurable drive settings */ -#define DS_SYNC (1 << 0) +#define DS_SYNC BIT(0) struct ide_devset { int (*get)(ide_drive_t *); @@ -1000,15 +1000,15 @@ static inline void ide_proc_unregister_driver(ide_drive_t *drive, enum { /* enter/exit functions */ - IDE_DBG_FUNC = (1 << 0), + IDE_DBG_FUNC = BIT(0), /* sense key/asc handling */ - IDE_DBG_SENSE = (1 << 1), + IDE_DBG_SENSE = BIT(1), /* packet commands handling */ - IDE_DBG_PC = (1 << 2), + IDE_DBG_PC = BIT(2), /* request handling */ - IDE_DBG_RQ = (1 << 3), + IDE_DBG_RQ = BIT(3), /* driver probing/setup */ - IDE_DBG_PROBE = (1 << 4), + IDE_DBG_PROBE = BIT(4), }; /* DRV_NAME has to be defined in the driver before using the macro below */ @@ -1171,10 +1171,10 @@ ssize_t ide_park_store(struct device *dev, struct device_attribute *attr, * the tail of our block device request queue and wait for their completion. */ enum { - REQ_IDETAPE_PC1 = (1 << 0), /* packet command (first stage) */ - REQ_IDETAPE_PC2 = (1 << 1), /* packet command (second stage) */ - REQ_IDETAPE_READ = (1 << 2), - REQ_IDETAPE_WRITE = (1 << 3), + REQ_IDETAPE_PC1 = BIT(0), /* packet command (first stage) */ + REQ_IDETAPE_PC2 = BIT(1), /* packet command (second stage) */ + REQ_IDETAPE_READ = BIT(2), + REQ_IDETAPE_WRITE = BIT(3), }; int ide_queue_pc_tail(ide_drive_t *, struct gendisk *, struct ide_atapi_pc *, @@ -1264,71 +1264,71 @@ struct ide_pci_enablebit { enum { /* Uses ISA control ports not PCI ones. */ - IDE_HFLAG_ISA_PORTS = (1 << 0), + IDE_HFLAG_ISA_PORTS = BIT(0), /* single port device */ - IDE_HFLAG_SINGLE = (1 << 1), + IDE_HFLAG_SINGLE = BIT(1), /* don't use legacy PIO blacklist */ - IDE_HFLAG_PIO_NO_BLACKLIST = (1 << 2), + IDE_HFLAG_PIO_NO_BLACKLIST = BIT(2), /* set for the second port of QD65xx */ - IDE_HFLAG_QD_2ND_PORT = (1 << 3), + IDE_HFLAG_QD_2ND_PORT = BIT(3), /* use PIO8/9 for prefetch off/on */ - IDE_HFLAG_ABUSE_PREFETCH = (1 << 4), + IDE_HFLAG_ABUSE_PREFETCH = BIT(4), /* use PIO6/7 for fast-devsel off/on */ - IDE_HFLAG_ABUSE_FAST_DEVSEL = (1 << 5), + IDE_HFLAG_ABUSE_FAST_DEVSEL = BIT(5), /* use 100-102 and 200-202 PIO values to set DMA modes */ - IDE_HFLAG_ABUSE_DMA_MODES = (1 << 6), + IDE_HFLAG_ABUSE_DMA_MODES = BIT(6), /* * keep DMA setting when programming PIO mode, may be used only * for hosts which have separate PIO and DMA timings (ie. PMAC) */ - IDE_HFLAG_SET_PIO_MODE_KEEP_DMA = (1 << 7), + IDE_HFLAG_SET_PIO_MODE_KEEP_DMA = BIT(7), /* program host for the transfer mode after programming device */ - IDE_HFLAG_POST_SET_MODE = (1 << 8), + IDE_HFLAG_POST_SET_MODE = BIT(8), /* don't program host/device for the transfer mode ("smart" hosts) */ - IDE_HFLAG_NO_SET_MODE = (1 << 9), + IDE_HFLAG_NO_SET_MODE = BIT(9), /* trust BIOS for programming chipset/device for DMA */ - IDE_HFLAG_TRUST_BIOS_FOR_DMA = (1 << 10), + IDE_HFLAG_TRUST_BIOS_FOR_DMA = BIT(10), /* host is CS5510/CS5520 */ - IDE_HFLAG_CS5520 = (1 << 11), + IDE_HFLAG_CS5520 = BIT(11), /* ATAPI DMA is unsupported */ - IDE_HFLAG_NO_ATAPI_DMA = (1 << 12), + IDE_HFLAG_NO_ATAPI_DMA = BIT(12), /* set if host is a "non-bootable" controller */ - IDE_HFLAG_NON_BOOTABLE = (1 << 13), + IDE_HFLAG_NON_BOOTABLE = BIT(13), /* host doesn't support DMA */ - IDE_HFLAG_NO_DMA = (1 << 14), + IDE_HFLAG_NO_DMA = BIT(14), /* check if host is PCI IDE device before allowing DMA */ - IDE_HFLAG_NO_AUTODMA = (1 << 15), + IDE_HFLAG_NO_AUTODMA = BIT(15), /* host uses MMIO */ - IDE_HFLAG_MMIO = (1 << 16), + IDE_HFLAG_MMIO = BIT(16), /* no LBA48 */ - IDE_HFLAG_NO_LBA48 = (1 << 17), + IDE_HFLAG_NO_LBA48 = BIT(17), /* no LBA48 DMA */ - IDE_HFLAG_NO_LBA48_DMA = (1 << 18), + IDE_HFLAG_NO_LBA48_DMA = BIT(18), /* data FIFO is cleared by an error */ - IDE_HFLAG_ERROR_STOPS_FIFO = (1 << 19), + IDE_HFLAG_ERROR_STOPS_FIFO = BIT(19), /* serialize ports */ - IDE_HFLAG_SERIALIZE = (1 << 20), + IDE_HFLAG_SERIALIZE = BIT(20), /* host is DTC2278 */ - IDE_HFLAG_DTC2278 = (1 << 21), + IDE_HFLAG_DTC2278 = BIT(21), /* 4 devices on a single set of I/O ports */ - IDE_HFLAG_4DRIVES = (1 << 22), + IDE_HFLAG_4DRIVES = BIT(22), /* host is TRM290 */ - IDE_HFLAG_TRM290 = (1 << 23), + IDE_HFLAG_TRM290 = BIT(23), /* use 32-bit I/O ops */ - IDE_HFLAG_IO_32BIT = (1 << 24), + IDE_HFLAG_IO_32BIT = BIT(24), /* unmask IRQs */ - IDE_HFLAG_UNMASK_IRQS = (1 << 25), - IDE_HFLAG_BROKEN_ALTSTATUS = (1 << 26), + IDE_HFLAG_UNMASK_IRQS = BIT(25), + IDE_HFLAG_BROKEN_ALTSTATUS = BIT(26), /* serialize ports if DMA is possible (for sl82c105) */ - IDE_HFLAG_SERIALIZE_DMA = (1 << 27), + IDE_HFLAG_SERIALIZE_DMA = BIT(27), /* force host out of "simplex" mode */ - IDE_HFLAG_CLEAR_SIMPLEX = (1 << 28), + IDE_HFLAG_CLEAR_SIMPLEX = BIT(28), /* DSC overlap is unsupported */ - IDE_HFLAG_NO_DSC = (1 << 29), + IDE_HFLAG_NO_DSC = BIT(29), /* never use 32-bit I/O ops */ - IDE_HFLAG_NO_IO_32BIT = (1 << 30), + IDE_HFLAG_NO_IO_32BIT = BIT(30), /* never unmask IRQs */ - IDE_HFLAG_NO_UNMASK_IRQS = (1 << 31), + IDE_HFLAG_NO_UNMASK_IRQS = BIT(31), }; #ifdef CONFIG_BLK_DEV_OFFBOARD @@ -1536,16 +1536,16 @@ struct ide_timing { }; enum { - IDE_TIMING_SETUP = (1 << 0), - IDE_TIMING_ACT8B = (1 << 1), - IDE_TIMING_REC8B = (1 << 2), - IDE_TIMING_CYC8B = (1 << 3), + IDE_TIMING_SETUP = BIT(0), + IDE_TIMING_ACT8B = BIT(1), + IDE_TIMING_REC8B = BIT(2), + IDE_TIMING_CYC8B = BIT(3), IDE_TIMING_8BIT = IDE_TIMING_ACT8B | IDE_TIMING_REC8B | IDE_TIMING_CYC8B, - IDE_TIMING_ACTIVE = (1 << 4), - IDE_TIMING_RECOVER = (1 << 5), - IDE_TIMING_CYCLE = (1 << 6), - IDE_TIMING_UDMA = (1 << 7), + IDE_TIMING_ACTIVE = BIT(4), + IDE_TIMING_RECOVER = BIT(5), + IDE_TIMING_CYCLE = BIT(6), + IDE_TIMING_UDMA = BIT(7), IDE_TIMING_ALL = IDE_TIMING_SETUP | IDE_TIMING_8BIT | IDE_TIMING_ACTIVE | IDE_TIMING_RECOVER | IDE_TIMING_CYCLE | IDE_TIMING_UDMA, diff --git a/include/linux/idle_inject.h b/include/linux/idle_inject.h index bdc0293fb6cb..a445cd1a36c5 100644 --- a/include/linux/idle_inject.h +++ b/include/linux/idle_inject.h @@ -20,10 +20,10 @@ int idle_inject_start(struct idle_inject_device *ii_dev); void idle_inject_stop(struct idle_inject_device *ii_dev); void idle_inject_set_duration(struct idle_inject_device *ii_dev, - unsigned int run_duration_ms, - unsigned int idle_duration_ms); + unsigned int run_duration_us, + unsigned int idle_duration_us); void idle_inject_get_duration(struct idle_inject_device *ii_dev, - unsigned int *run_duration_ms, - unsigned int *idle_duration_ms); + unsigned int *run_duration_us, + unsigned int *idle_duration_us); #endif /* __IDLE_INJECT_H__ */ diff --git a/include/linux/idr.h b/include/linux/idr.h index ee7abae143d3..4ec8986e5dfb 100644 --- a/include/linux/idr.h +++ b/include/linux/idr.h @@ -191,14 +191,17 @@ static inline void idr_preload_end(void) * idr_for_each_entry_ul() - Iterate over an IDR's elements of a given type. * @idr: IDR handle. * @entry: The type * to use as cursor. + * @tmp: A temporary placeholder for ID. * @id: Entry ID. * * @entry and @id do not need to be initialized before the loop, and * after normal termination @entry is left with the value NULL. This * is convenient for a "not found" value. */ -#define idr_for_each_entry_ul(idr, entry, id) \ - for (id = 0; ((entry) = idr_get_next_ul(idr, &(id))) != NULL; ++id) +#define idr_for_each_entry_ul(idr, entry, tmp, id) \ + for (tmp = 0, id = 0; \ + tmp <= id && ((entry) = idr_get_next_ul(idr, &(id))) != NULL; \ + tmp = id, ++id) /** * idr_for_each_entry_continue() - Continue iteration over an IDR's elements of a given type @@ -213,6 +216,20 @@ static inline void idr_preload_end(void) entry; \ ++id, (entry) = idr_get_next((idr), &(id))) +/** + * idr_for_each_entry_continue_ul() - Continue iteration over an IDR's elements of a given type + * @idr: IDR handle. + * @entry: The type * to use as a cursor. + * @tmp: A temporary placeholder for ID. + * @id: Entry ID. + * + * Continue to iterate over entries, continuing after the current position. + */ +#define idr_for_each_entry_continue_ul(idr, entry, tmp, id) \ + for (tmp = id; \ + tmp <= id && ((entry) = idr_get_next_ul(idr, &(id))) != NULL; \ + tmp = id, ++id) + /* * IDA - ID Allocator, use when translation from id to pointer isn't necessary. */ diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h index 42690007d612..7d3f2ced92d1 100644 --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h @@ -881,6 +881,14 @@ struct ieee80211_tpc_report_ie { u8 link_margin; } __packed; +#define IEEE80211_ADDBA_EXT_FRAG_LEVEL_MASK GENMASK(2, 1) +#define IEEE80211_ADDBA_EXT_FRAG_LEVEL_SHIFT 1 +#define IEEE80211_ADDBA_EXT_NO_FRAG BIT(0) + +struct ieee80211_addba_ext_ie { + u8 data; +} __packed; + struct ieee80211_mgmt { __le16 frame_control; __le16 duration; @@ -973,6 +981,8 @@ struct ieee80211_mgmt { __le16 capab; __le16 timeout; __le16 start_seq_num; + /* followed by BA Extension */ + u8 variable[0]; } __packed addba_req; struct{ u8 action_code; @@ -1626,6 +1636,18 @@ struct ieee80211_he_operation { } __packed; /** + * struct ieee80211_he_spr - HE spatial reuse element + * + * This structure is the "HE spatial reuse element" element as + * described in P802.11ax_D4.0 section 9.4.2.241 + */ +struct ieee80211_he_spr { + u8 he_sr_control; + /* Optional 0 to 19 bytes: depends on @he_sr_control */ + u8 optional[0]; +} __packed; + +/** * struct ieee80211_he_mu_edca_param_ac_rec - MU AC Parameter Record field * * This structure is the "MU AC Parameter Record" fields as @@ -2033,8 +2055,8 @@ ieee80211_he_ppe_size(u8 ppe_thres_hdr, const u8 *phy_cap_info) * ieee80211_he_oper_size - calculate 802.11ax HE Operations IE size * @he_oper_ie: byte data of the He Operations IE, stating from the the byte * after the ext ID byte. It is assumed that he_oper_ie has at least - * sizeof(struct ieee80211_he_operation) bytes, checked already in - * ieee802_11_parse_elems_crc() + * sizeof(struct ieee80211_he_operation) bytes, the caller must have + * validated this. * @return the actual size of the IE data (not including header), or 0 on error */ static inline u8 @@ -2063,6 +2085,42 @@ ieee80211_he_oper_size(const u8 *he_oper_ie) return oper_len; } +/* HE Spatial Reuse defines */ +#define IEEE80211_HE_SPR_NON_SRG_OFFSET_PRESENT 0x4 +#define IEEE80211_HE_SPR_SRG_INFORMATION_PRESENT 0x8 + +/* + * ieee80211_he_spr_size - calculate 802.11ax HE Spatial Reuse IE size + * @he_spr_ie: byte data of the He Spatial Reuse IE, stating from the the byte + * after the ext ID byte. It is assumed that he_spr_ie has at least + * sizeof(struct ieee80211_he_spr) bytes, the caller must have validated + * this + * @return the actual size of the IE data (not including header), or 0 on error + */ +static inline u8 +ieee80211_he_spr_size(const u8 *he_spr_ie) +{ + struct ieee80211_he_spr *he_spr = (void *)he_spr_ie; + u8 spr_len = sizeof(struct ieee80211_he_spr); + u32 he_spr_params; + + /* Make sure the input is not NULL */ + if (!he_spr_ie) + return 0; + + /* Calc required length */ + he_spr_params = le32_to_cpu(he_spr->he_sr_control); + if (he_spr_params & IEEE80211_HE_SPR_NON_SRG_OFFSET_PRESENT) + spr_len++; + if (he_spr_params & IEEE80211_HE_SPR_SRG_INFORMATION_PRESENT) + spr_len += 18; + + /* Add the first byte (extension ID) to the total length */ + spr_len++; + + return spr_len; +} + /* Authentication algorithms */ #define WLAN_AUTH_OPEN 0 #define WLAN_AUTH_SHARED_KEY 1 @@ -2485,6 +2543,7 @@ enum ieee80211_eid_ext { WLAN_EID_EXT_HE_OPERATION = 36, WLAN_EID_EXT_UORA = 37, WLAN_EID_EXT_HE_MU_EDCA = 38, + WLAN_EID_EXT_HE_SPR = 39, WLAN_EID_EXT_MAX_CHANNEL_SWITCH_TIME = 52, WLAN_EID_EXT_MULTIPLE_BSSID_CONFIGURATION = 55, WLAN_EID_EXT_NON_INHERITANCE = 56, @@ -2609,6 +2668,7 @@ enum ieee80211_key_len { #define FILS_ERP_MAX_RRK_LEN 64 #define PMK_MAX_LEN 64 +#define SAE_PASSWORD_MAX_LEN 128 /* Public action codes (IEEE Std 802.11-2016, 9.6.8.1, Table 9-307) */ enum ieee80211_pub_actioncode { @@ -2709,6 +2769,13 @@ enum ieee80211_tdls_actioncode { #define WLAN_EXT_CAPA10_TWT_REQUESTER_SUPPORT BIT(5) #define WLAN_EXT_CAPA10_TWT_RESPONDER_SUPPORT BIT(6) +/* + * When set, indicates that the AP is able to tolerate 26-tone RU UL + * OFDMA transmissions using HE TB PPDU from OBSS (not falsely classify the + * 26-tone RU UL OFDMA transmissions as radar pulses). + */ +#define WLAN_EXT_CAPA10_OBSS_NARROW_BW_RU_TOLERANCE_SUPPORT BIT(7) + /* Defines support for enhanced multi-bssid advertisement*/ #define WLAN_EXT_CAPA11_EMA_SUPPORT BIT(1) diff --git a/include/linux/if_bridge.h b/include/linux/if_bridge.h index f3fab5d0ea97..9e57c4411734 100644 --- a/include/linux/if_bridge.h +++ b/include/linux/if_bridge.h @@ -88,6 +88,8 @@ static inline bool br_multicast_router(const struct net_device *dev) #if IS_ENABLED(CONFIG_BRIDGE) && IS_ENABLED(CONFIG_BRIDGE_VLAN_FILTERING) bool br_vlan_enabled(const struct net_device *dev); int br_vlan_get_pvid(const struct net_device *dev, u16 *p_pvid); +int br_vlan_get_pvid_rcu(const struct net_device *dev, u16 *p_pvid); +int br_vlan_get_proto(const struct net_device *dev, u16 *p_proto); int br_vlan_get_info(const struct net_device *dev, u16 vid, struct bridge_vlan_info *p_vinfo); #else @@ -101,6 +103,16 @@ static inline int br_vlan_get_pvid(const struct net_device *dev, u16 *p_pvid) return -EINVAL; } +static inline int br_vlan_get_proto(const struct net_device *dev, u16 *p_proto) +{ + return -EINVAL; +} + +static inline int br_vlan_get_pvid_rcu(const struct net_device *dev, u16 *p_pvid) +{ + return -EINVAL; +} + static inline int br_vlan_get_info(const struct net_device *dev, u16 vid, struct bridge_vlan_info *p_vinfo) { diff --git a/include/linux/if_pppox.h b/include/linux/if_pppox.h index 8b728750a625..69e813bcb947 100644 --- a/include/linux/if_pppox.h +++ b/include/linux/if_pppox.h @@ -80,6 +80,9 @@ extern int register_pppox_proto(int proto_num, const struct pppox_proto *pp); extern void unregister_pppox_proto(int proto_num); extern void pppox_unbind_sock(struct sock *sk);/* delete ppp-channel binding */ extern int pppox_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg); +extern int pppox_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg); + +#define PPPOEIOCSFWD32 _IOW(0xB1 ,0, compat_size_t) /* PPPoX socket states */ enum { diff --git a/include/linux/if_rmnet.h b/include/linux/if_rmnet.h new file mode 100644 index 000000000000..9661416a9bb4 --- /dev/null +++ b/include/linux/if_rmnet.h @@ -0,0 +1,55 @@ +/* SPDX-License-Identifier: GPL-2.0-only + * Copyright (c) 2013-2019, The Linux Foundation. All rights reserved. + */ + +#ifndef _LINUX_IF_RMNET_H_ +#define _LINUX_IF_RMNET_H_ + +struct rmnet_map_header { +#if defined(__LITTLE_ENDIAN_BITFIELD) + u8 pad_len:6; + u8 reserved_bit:1; + u8 cd_bit:1; +#elif defined (__BIG_ENDIAN_BITFIELD) + u8 cd_bit:1; + u8 reserved_bit:1; + u8 pad_len:6; +#else +#error "Please fix <asm/byteorder.h>" +#endif + u8 mux_id; + __be16 pkt_len; +} __aligned(1); + +struct rmnet_map_dl_csum_trailer { + u8 reserved1; +#if defined(__LITTLE_ENDIAN_BITFIELD) + u8 valid:1; + u8 reserved2:7; +#elif defined (__BIG_ENDIAN_BITFIELD) + u8 reserved2:7; + u8 valid:1; +#else +#error "Please fix <asm/byteorder.h>" +#endif + u16 csum_start_offset; + u16 csum_length; + __be16 csum_value; +} __aligned(1); + +struct rmnet_map_ul_csum_header { + __be16 csum_start_offset; +#if defined(__LITTLE_ENDIAN_BITFIELD) + u16 csum_insert_offset:14; + u16 udp_ind:1; + u16 csum_enabled:1; +#elif defined (__BIG_ENDIAN_BITFIELD) + u16 csum_enabled:1; + u16 udp_ind:1; + u16 csum_insert_offset:14; +#else +#error "Please fix <asm/byteorder.h>" +#endif +} __aligned(1); + +#endif /* !(_LINUX_IF_RMNET_H_) */ diff --git a/include/linux/if_tap.h b/include/linux/if_tap.h index 8e66866c11be..915a187cfabd 100644 --- a/include/linux/if_tap.h +++ b/include/linux/if_tap.h @@ -62,7 +62,6 @@ struct tap_dev { struct tap_queue { struct sock sk; struct socket sock; - struct socket_wq wq; int vnet_hdr_sz; struct tap_dev __rcu *tap; struct file *file; diff --git a/include/linux/igmp.h b/include/linux/igmp.h index 9cbbd1baaf85..463047d0190b 100644 --- a/include/linux/igmp.h +++ b/include/linux/igmp.h @@ -60,8 +60,8 @@ struct ip_mc_socklist { struct ip_sf_list { struct ip_sf_list *sf_next; - __be32 sf_inaddr; unsigned long sf_count[2]; /* include/exclude counts */ + __be32 sf_inaddr; unsigned char sf_gsresp; /* include in g & s response? */ unsigned char sf_oldin; /* change state */ unsigned char sf_crcount; /* retrans. left to send */ diff --git a/include/linux/iio/common/cros_ec_sensors_core.h b/include/linux/iio/common/cros_ec_sensors_core.h index 0c636b9fe8d7..bb331e6356a9 100644 --- a/include/linux/iio/common/cros_ec_sensors_core.h +++ b/include/linux/iio/common/cros_ec_sensors_core.h @@ -10,7 +10,8 @@ #include <linux/iio/iio.h> #include <linux/irqreturn.h> -#include <linux/mfd/cros_ec.h> +#include <linux/platform_data/cros_ec_commands.h> +#include <linux/platform_data/cros_ec_proto.h> enum { CROS_EC_SENSOR_X, @@ -62,14 +63,20 @@ struct cros_ec_sensors_core_state { enum motionsensor_type type; enum motionsensor_location loc; - s16 calib[CROS_EC_SENSOR_MAX_AXIS]; - + struct calib_data { + s16 offset; + u16 scale; + } calib[CROS_EC_SENSOR_MAX_AXIS]; + s8 sign[CROS_EC_SENSOR_MAX_AXIS]; u8 samples[CROS_EC_SAMPLE_SIZE]; int (*read_ec_sensors_data)(struct iio_dev *indio_dev, unsigned long scan_mask, s16 *data); int curr_sampl_freq; + + /* Table of known available frequencies : 0, Min and Max in mHz */ + int frequencies[3]; }; /** @@ -151,6 +158,24 @@ int cros_ec_sensors_core_read(struct cros_ec_sensors_core_state *st, int *val, int *val2, long mask); /** + * cros_ec_sensors_core_read_avail() - get available values + * @indio_dev: pointer to state information for device + * @chan: channel specification structure table + * @vals: list of available values + * @type: type of data returned + * @length: number of data returned in the array + * @mask: specifies which values to be requested + * + * Return: an error code, IIO_AVAIL_RANGE or IIO_AVAIL_LIST + */ +int cros_ec_sensors_core_read_avail(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + const int **vals, + int *type, + int *length, + long mask); + +/** * cros_ec_sensors_core_write() - function to write a value to the sensor * @st: pointer to state information for device * @chan: channel specification structure table diff --git a/include/linux/iio/common/st_sensors.h b/include/linux/iio/common/st_sensors.h index 2948ac99e2da..686be532f4cb 100644 --- a/include/linux/iio/common/st_sensors.h +++ b/include/linux/iio/common/st_sensors.h @@ -16,11 +16,16 @@ #include <linux/iio/trigger.h> #include <linux/bitops.h> #include <linux/regulator/consumer.h> +#include <linux/regmap.h> #include <linux/platform_data/st_sensors_pdata.h> -#define ST_SENSORS_TX_MAX_LENGTH 2 -#define ST_SENSORS_RX_MAX_LENGTH 6 +/* + * Buffer size max case: 2bytes per channel, 3 channels in total + + * 8bytes timestamp channel (s64) + */ +#define ST_SENSORS_MAX_BUFFER_SIZE (ALIGN(2 * 3, sizeof(s64)) + \ + sizeof(s64)) #define ST_SENSORS_ODR_LIST_MAX 10 #define ST_SENSORS_FULLSCALE_AVL_MAX 10 @@ -170,36 +175,6 @@ struct st_sensor_data_ready_irq { }; /** - * struct st_sensor_transfer_buffer - ST sensor device I/O buffer - * @buf_lock: Mutex to protect rx and tx buffers. - * @tx_buf: Buffer used by SPI transfer function to send data to the sensors. - * This buffer is used to avoid DMA not-aligned issue. - * @rx_buf: Buffer used by SPI transfer to receive data from sensors. - * This buffer is used to avoid DMA not-aligned issue. - */ -struct st_sensor_transfer_buffer { - struct mutex buf_lock; - u8 rx_buf[ST_SENSORS_RX_MAX_LENGTH]; - u8 tx_buf[ST_SENSORS_TX_MAX_LENGTH] ____cacheline_aligned; -}; - -/** - * struct st_sensor_transfer_function - ST sensor device I/O function - * @read_byte: Function used to read one byte. - * @write_byte: Function used to write one byte. - * @read_multiple_byte: Function used to read multiple byte. - */ -struct st_sensor_transfer_function { - int (*read_byte) (struct st_sensor_transfer_buffer *tb, - struct device *dev, u8 reg_addr, u8 *res_byte); - int (*write_byte) (struct st_sensor_transfer_buffer *tb, - struct device *dev, u8 reg_addr, u8 data); - int (*read_multiple_byte) (struct st_sensor_transfer_buffer *tb, - struct device *dev, u8 reg_addr, int len, u8 *data, - bool multiread_bit); -}; - -/** * struct st_sensor_settings - ST specific sensor settings * @wai: Contents of WhoAmI register. * @wai_addr: The address of WhoAmI register. @@ -242,19 +217,17 @@ struct st_sensor_settings { * @current_fullscale: Maximum range of measure by the sensor. * @vdd: Pointer to sensor's Vdd power supply * @vdd_io: Pointer to sensor's Vdd-IO power supply + * @regmap: Pointer to specific sensor regmap configuration. * @enabled: Status of the sensor (false->off, true->on). - * @multiread_bit: Use or not particular bit for [I2C/SPI] multiread. - * @buffer_data: Data used by buffer part. * @odr: Output data rate of the sensor [Hz]. * num_data_channels: Number of data channels used in buffer. * @drdy_int_pin: Redirect DRDY on pin 1 (1) or pin 2 (2). * @int_pin_open_drain: Set the interrupt/DRDY to open drain. - * @get_irq_data_ready: Function to get the IRQ used for data ready signal. - * @tf: Transfer function structure used by I/O operations. - * @tb: Transfer buffers and mutex used by I/O operations. + * @irq: the IRQ number. * @edge_irq: the IRQ triggers on edges and need special handling. * @hw_irq_trigger: if we're using the hardware interrupt on the sensor. * @hw_timestamp: Latest timestamp from the interrupt handler, when in use. + * @buffer_data: Data used by buffer part. */ struct st_sensor_data { struct device *dev; @@ -264,26 +237,22 @@ struct st_sensor_data { struct st_sensor_fullscale_avl *current_fullscale; struct regulator *vdd; struct regulator *vdd_io; + struct regmap *regmap; bool enabled; - bool multiread_bit; - - char *buffer_data; unsigned int odr; unsigned int num_data_channels; u8 drdy_int_pin; bool int_pin_open_drain; - - unsigned int (*get_irq_data_ready) (struct iio_dev *indio_dev); - - const struct st_sensor_transfer_function *tf; - struct st_sensor_transfer_buffer tb; + int irq; bool edge_irq; bool hw_irq_trigger; s64 hw_timestamp; + + char buffer_data[ST_SENSORS_MAX_BUFFER_SIZE] ____cacheline_aligned; }; #ifdef CONFIG_IIO_BUFFER @@ -334,8 +303,11 @@ int st_sensors_set_fullscale_by_gain(struct iio_dev *indio_dev, int scale); int st_sensors_read_info_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *ch, int *val); -int st_sensors_check_device_support(struct iio_dev *indio_dev, - int num_sensors_list, const struct st_sensor_settings *sensor_settings); +int st_sensors_get_settings_index(const char *name, + const struct st_sensor_settings *list, + const int list_length); + +int st_sensors_verify_id(struct iio_dev *indio_dev); ssize_t st_sensors_sysfs_sampling_frequency_avail(struct device *dev, struct device_attribute *attr, char *buf); diff --git a/include/linux/iio/common/st_sensors_i2c.h b/include/linux/iio/common/st_sensors_i2c.h index 5ada89944698..01e424e2af4f 100644 --- a/include/linux/iio/common/st_sensors_i2c.h +++ b/include/linux/iio/common/st_sensors_i2c.h @@ -14,8 +14,8 @@ #include <linux/iio/common/st_sensors.h> #include <linux/of.h> -void st_sensors_i2c_configure(struct iio_dev *indio_dev, - struct i2c_client *client, struct st_sensor_data *sdata); +int st_sensors_i2c_configure(struct iio_dev *indio_dev, + struct i2c_client *client); #ifdef CONFIG_ACPI int st_sensors_match_acpi_device(struct device *dev); diff --git a/include/linux/iio/common/st_sensors_spi.h b/include/linux/iio/common/st_sensors_spi.h index 6020f7167859..90b25f087f06 100644 --- a/include/linux/iio/common/st_sensors_spi.h +++ b/include/linux/iio/common/st_sensors_spi.h @@ -13,7 +13,7 @@ #include <linux/spi/spi.h> #include <linux/iio/common/st_sensors.h> -void st_sensors_spi_configure(struct iio_dev *indio_dev, - struct spi_device *spi, struct st_sensor_data *sdata); +int st_sensors_spi_configure(struct iio_dev *indio_dev, + struct spi_device *spi); #endif /* ST_SENSORS_SPI_H */ diff --git a/include/linux/iio/imu/adis.h b/include/linux/iio/imu/adis.h index 3428d06b2f44..4c53815bb729 100644 --- a/include/linux/iio/imu/adis.h +++ b/include/linux/iio/imu/adis.h @@ -26,6 +26,7 @@ struct adis_burst; * struct adis_data - ADIS chip variant specific data * @read_delay: SPI delay for read operations in us * @write_delay: SPI delay for write operations in us + * @cs_change_delay: SPI delay between CS changes in us * @glob_cmd_reg: Register address of the GLOB_CMD register * @msc_ctrl_reg: Register address of the MSC_CTRL register * @diag_stat_reg: Register address of the DIAG_STAT register @@ -35,6 +36,7 @@ struct adis_burst; struct adis_data { unsigned int read_delay; unsigned int write_delay; + unsigned int cs_change_delay; unsigned int glob_cmd_reg; unsigned int msc_ctrl_reg; diff --git a/include/linux/ima.h b/include/linux/ima.h index 8e2f324fb901..1c37f17f7203 100644 --- a/include/linux/ima.h +++ b/include/linux/ima.h @@ -23,6 +23,7 @@ extern int ima_read_file(struct file *file, enum kernel_read_file_id id); extern int ima_post_read_file(struct file *file, void *buf, loff_t size, enum kernel_read_file_id id); extern void ima_post_path_mknod(struct dentry *dentry); +extern void ima_kexec_cmdline(const void *buf, int size); #ifdef CONFIG_IMA_KEXEC extern void ima_add_kexec_buffer(struct kimage *image); @@ -89,6 +90,7 @@ static inline void ima_post_path_mknod(struct dentry *dentry) return; } +static inline void ima_kexec_cmdline(const void *buf, int size) {} #endif /* CONFIG_IMA */ #ifndef CONFIG_IMA_KEXEC diff --git a/include/linux/in.h b/include/linux/in.h index 4d2fedfb753a..1873ef642605 100644 --- a/include/linux/in.h +++ b/include/linux/in.h @@ -63,7 +63,7 @@ static inline bool ipv4_is_all_snoopers(__be32 addr) static inline bool ipv4_is_zeronet(__be32 addr) { - return (addr & htonl(0xff000000)) == htonl(0x00000000); + return (addr == 0); } /* Special-Use IPv4 Addresses (RFC3330) */ diff --git a/include/linux/inetdevice.h b/include/linux/inetdevice.h index 367dc2a0f84a..3515ca64e638 100644 --- a/include/linux/inetdevice.h +++ b/include/linux/inetdevice.h @@ -26,7 +26,7 @@ struct in_device { struct net_device *dev; refcount_t refcnt; int dead; - struct in_ifaddr *ifa_list; /* IP ifaddr chain */ + struct in_ifaddr __rcu *ifa_list;/* IP ifaddr chain */ struct ip_mc_list __rcu *mc_list; /* IP multicast filter chain */ struct ip_mc_list __rcu * __rcu *mc_hash; @@ -136,7 +136,7 @@ static inline void ipv4_devconf_setall(struct in_device *in_dev) struct in_ifaddr { struct hlist_node hash; - struct in_ifaddr *ifa_next; + struct in_ifaddr __rcu *ifa_next; struct in_device *ifa_dev; struct rcu_head rcu_head; __be32 ifa_local; @@ -186,7 +186,7 @@ __be32 inet_confirm_addr(struct net *net, struct in_device *in_dev, __be32 dst, struct in_ifaddr *inet_ifa_byprefix(struct in_device *in_dev, __be32 prefix, __be32 mask); struct in_ifaddr *inet_lookup_ifaddr_rcu(struct net *net, __be32 addr); -static __inline__ bool inet_ifa_match(__be32 addr, struct in_ifaddr *ifa) +static inline bool inet_ifa_match(__be32 addr, const struct in_ifaddr *ifa) { return !((addr^ifa->ifa_address)&ifa->ifa_mask); } @@ -206,14 +206,13 @@ static __inline__ bool bad_mask(__be32 mask, __be32 addr) return false; } -#define for_primary_ifa(in_dev) { struct in_ifaddr *ifa; \ - for (ifa = (in_dev)->ifa_list; ifa && !(ifa->ifa_flags&IFA_F_SECONDARY); ifa = ifa->ifa_next) +#define in_dev_for_each_ifa_rtnl(ifa, in_dev) \ + for (ifa = rtnl_dereference((in_dev)->ifa_list); ifa; \ + ifa = rtnl_dereference(ifa->ifa_next)) -#define for_ifa(in_dev) { struct in_ifaddr *ifa; \ - for (ifa = (in_dev)->ifa_list; ifa; ifa = ifa->ifa_next) - - -#define endfor_ifa(in_dev) } +#define in_dev_for_each_ifa_rcu(ifa, in_dev) \ + for (ifa = rcu_dereference((in_dev)->ifa_list); ifa; \ + ifa = rcu_dereference(ifa->ifa_next)) static inline struct in_device *__in_dev_get_rcu(const struct net_device *dev) { diff --git a/include/linux/init.h b/include/linux/init.h index 5255069f5a9f..212fc9e2f691 100644 --- a/include/linux/init.h +++ b/include/linux/init.h @@ -137,6 +137,8 @@ extern initcall_entry_t __con_initcall_start[], __con_initcall_end[]; /* Used for contructor calls. */ typedef void (*ctor_fn_t)(void); +struct file_system_type; + /* Defined in init/main.c */ extern int do_one_initcall(initcall_t fn); extern char __initdata boot_command_line[]; @@ -146,7 +148,8 @@ extern unsigned int reset_devices; /* used by init/main.c */ void setup_arch(char **); void prepare_namespace(void); -int __init init_rootfs(void); +void __init init_rootfs(void); +extern struct file_system_type rootfs_fs_type; #if defined(CONFIG_STRICT_KERNEL_RWX) || defined(CONFIG_STRICT_MODULE_RWX) extern bool rodata_enabled; diff --git a/include/linux/init_task.h b/include/linux/init_task.h index 6049baa5b8bc..2c620d7ac432 100644 --- a/include/linux/init_task.h +++ b/include/linux/init_task.h @@ -36,17 +36,6 @@ extern struct cred init_cred; #define INIT_PREV_CPUTIME(x) #endif -#ifdef CONFIG_POSIX_TIMERS -#define INIT_CPU_TIMERS(s) \ - .cpu_timers = { \ - LIST_HEAD_INIT(s.cpu_timers[0]), \ - LIST_HEAD_INIT(s.cpu_timers[1]), \ - LIST_HEAD_INIT(s.cpu_timers[2]), \ - }, -#else -#define INIT_CPU_TIMERS(s) -#endif - #define INIT_TASK_COMM "swapper" /* Attach to the init_task data structure for proper alignment */ diff --git a/include/linux/input.h b/include/linux/input.h index 510e78558c10..94f277cd806a 100644 --- a/include/linux/input.h +++ b/include/linux/input.h @@ -21,6 +21,8 @@ #include <linux/timer.h> #include <linux/mod_devicetable.h> +struct input_dev_poller; + /** * struct input_value - input value representation * @type: type of value (EV_KEY, EV_ABS, etc) @@ -33,6 +35,13 @@ struct input_value { __s32 value; }; +enum input_clock_type { + INPUT_CLK_REAL = 0, + INPUT_CLK_MONO, + INPUT_CLK_BOOT, + INPUT_CLK_MAX +}; + /** * struct input_dev - represents an input device * @name: name of the device @@ -64,6 +73,8 @@ struct input_value { * not sleep * @ff: force feedback structure associated with the device if device * supports force feedback effects + * @poller: poller structure associated with the device if device is + * set up to use polling mode * @repeat_key: stores key code of the last key pressed; used to implement * software autorepeat * @timer: timer for software autorepeat @@ -114,6 +125,8 @@ struct input_value { * @vals: array of values queued in the current frame * @devres_managed: indicates that devices is managed with devres framework * and needs not be explicitly unregistered or freed. + * @timestamp: storage for a timestamp set by input_set_timestamp called + * by a driver */ struct input_dev { const char *name; @@ -147,6 +160,8 @@ struct input_dev { struct ff_device *ff; + struct input_dev_poller *poller; + unsigned int repeat_key; struct timer_list timer; @@ -184,6 +199,8 @@ struct input_dev { struct input_value *vals; bool devres_managed; + + ktime_t timestamp[INPUT_CLK_MAX]; }; #define to_input_dev(d) container_of(d, struct input_dev, dev) @@ -361,6 +378,12 @@ void input_unregister_device(struct input_dev *); void input_reset_device(struct input_dev *); +int input_setup_polling(struct input_dev *dev, + void (*poll_fn)(struct input_dev *dev)); +void input_set_poll_interval(struct input_dev *dev, unsigned int interval); +void input_set_min_poll_interval(struct input_dev *dev, unsigned int interval); +void input_set_max_poll_interval(struct input_dev *dev, unsigned int interval); + int __must_check input_register_handler(struct input_handler *); void input_unregister_handler(struct input_handler *); @@ -382,6 +405,9 @@ void input_close_device(struct input_handle *); int input_flush_device(struct input_handle *handle, struct file *file); +void input_set_timestamp(struct input_dev *dev, ktime_t timestamp); +ktime_t *input_get_timestamp(struct input_dev *dev); + void input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value); void input_inject_event(struct input_handle *handle, unsigned int type, unsigned int code, int value); diff --git a/include/linux/input/bu21013.h b/include/linux/input/bu21013.h deleted file mode 100644 index 7e5b7e978e8a..000000000000 --- a/include/linux/input/bu21013.h +++ /dev/null @@ -1,34 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Copyright (C) ST-Ericsson SA 2010 - * Author: Naveen Kumar G <naveen.gaddipati@stericsson.com> for ST-Ericsson - */ - -#ifndef _BU21013_H -#define _BU21013_H - -/** - * struct bu21013_platform_device - Handle the platform data - * @touch_x_max: touch x max - * @touch_y_max: touch y max - * @cs_pin: chip select pin - * @touch_pin: touch gpio pin - * @ext_clk: external clock flag - * @x_flip: x flip flag - * @y_flip: y flip flag - * @wakeup: wakeup flag - * - * This is used to handle the platform data - */ -struct bu21013_platform_device { - int touch_x_max; - int touch_y_max; - unsigned int cs_pin; - unsigned int touch_pin; - bool ext_clk; - bool x_flip; - bool y_flip; - bool wakeup; -}; - -#endif diff --git a/include/linux/input/elan-i2c-ids.h b/include/linux/input/elan-i2c-ids.h new file mode 100644 index 000000000000..1ecb6b45812c --- /dev/null +++ b/include/linux/input/elan-i2c-ids.h @@ -0,0 +1,76 @@ +/* + * Elan I2C/SMBus Touchpad device whitelist + * + * Copyright (c) 2013 ELAN Microelectronics Corp. + * + * Author: Ã¦ç¶ (Duson Lin) <dusonlin@emc.com.tw> + * Author: KT Liao <kt.liao@emc.com.tw> + * Version: 1.6.3 + * + * Based on cyapa driver: + * copyright (c) 2011-2012 Cypress Semiconductor, Inc. + * copyright (c) 2011-2012 Google, Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + * + * Trademarks are the property of their respective owners. + */ + +#ifndef __ELAN_I2C_IDS_H +#define __ELAN_I2C_IDS_H + +#include <linux/mod_devicetable.h> + +static const struct acpi_device_id elan_acpi_id[] = { + { "ELAN0000", 0 }, + { "ELAN0100", 0 }, + { "ELAN0600", 0 }, + { "ELAN0601", 0 }, + { "ELAN0602", 0 }, + { "ELAN0603", 0 }, + { "ELAN0604", 0 }, + { "ELAN0605", 0 }, + { "ELAN0606", 0 }, + { "ELAN0607", 0 }, + { "ELAN0608", 0 }, + { "ELAN0609", 0 }, + { "ELAN060B", 0 }, + { "ELAN060C", 0 }, + { "ELAN060F", 0 }, + { "ELAN0610", 0 }, + { "ELAN0611", 0 }, + { "ELAN0612", 0 }, + { "ELAN0615", 0 }, + { "ELAN0616", 0 }, + { "ELAN0617", 0 }, + { "ELAN0618", 0 }, + { "ELAN0619", 0 }, + { "ELAN061A", 0 }, +/* { "ELAN061B", 0 }, not working on the Lenovo Legion Y7000 */ + { "ELAN061C", 0 }, + { "ELAN061D", 0 }, + { "ELAN061E", 0 }, + { "ELAN061F", 0 }, + { "ELAN0620", 0 }, + { "ELAN0621", 0 }, + { "ELAN0622", 0 }, + { "ELAN0623", 0 }, + { "ELAN0624", 0 }, + { "ELAN0625", 0 }, + { "ELAN0626", 0 }, + { "ELAN0627", 0 }, + { "ELAN0628", 0 }, + { "ELAN0629", 0 }, + { "ELAN062A", 0 }, + { "ELAN062B", 0 }, + { "ELAN062C", 0 }, + { "ELAN062D", 0 }, + { "ELAN0631", 0 }, + { "ELAN0632", 0 }, + { "ELAN1000", 0 }, + { } +}; + +#endif /* __ELAN_I2C_IDS_H */ diff --git a/include/linux/intel-iommu.h b/include/linux/intel-iommu.h index 6a8dd4af0147..ed11ef594378 100644 --- a/include/linux/intel-iommu.h +++ b/include/linux/intel-iommu.h @@ -272,6 +272,8 @@ #define dma_frcd_type(d) ((d >> 30) & 1) #define dma_frcd_fault_reason(c) (c & 0xff) #define dma_frcd_source_id(c) (c & 0xffff) +#define dma_frcd_pasid_value(c) (((c) >> 8) & 0xfffff) +#define dma_frcd_pasid_present(c) (((c) >> 31) & 1) /* low 64 bit */ #define dma_frcd_page_addr(d) (d & (((u64)-1) << PAGE_SHIFT)) @@ -346,7 +348,6 @@ enum { #define QI_PC_PASID_SEL (QI_PC_TYPE | QI_PC_GRAN(1)) #define QI_EIOTLB_ADDR(addr) ((u64)(addr) & VTD_PAGE_MASK) -#define QI_EIOTLB_GL(gl) (((u64)gl) << 7) #define QI_EIOTLB_IH(ih) (((u64)ih) << 6) #define QI_EIOTLB_AM(am) (((u64)am)) #define QI_EIOTLB_PASID(pasid) (((u64)pasid) << 32) @@ -378,8 +379,6 @@ enum { #define QI_RESP_INVALID 0x1 #define QI_RESP_FAILURE 0xf -#define QI_GRAN_ALL_ALL 0 -#define QI_GRAN_NONG_ALL 1 #define QI_GRAN_NONG_PASID 2 #define QI_GRAN_PSI_PASID 3 @@ -435,6 +434,12 @@ enum { #define VTD_FLAG_TRANS_PRE_ENABLED (1 << 0) #define VTD_FLAG_IRQ_REMAP_PRE_ENABLED (1 << 1) +extern int intel_iommu_sm; + +#define sm_supported(iommu) (intel_iommu_sm && ecap_smts((iommu)->ecap)) +#define pasid_supported(iommu) (sm_supported(iommu) && \ + ecap_pasid((iommu)->ecap)) + struct pasid_entry; struct pasid_state_entry; struct page_req_dsc; @@ -642,7 +647,6 @@ extern int qi_submit_sync(struct qi_desc *desc, struct intel_iommu *iommu); extern int dmar_ir_support(void); -struct dmar_domain *get_valid_domain_for_dev(struct device *dev); void *alloc_pgtable_page(int node); void free_pgtable_page(void *vaddr); struct intel_iommu *domain_get_iommu(struct dmar_domain *domain); diff --git a/include/linux/intel-svm.h b/include/linux/intel-svm.h index 54ffcc6a322e..94f047a8a845 100644 --- a/include/linux/intel-svm.h +++ b/include/linux/intel-svm.h @@ -49,7 +49,7 @@ struct svm_dev_ops { /** * intel_svm_bind_mm() - Bind the current process to a PASID - * @dev: Device to be granted acccess + * @dev: Device to be granted access * @pasid: Address for allocated PASID * @flags: Flags. Later for requesting supervisor mode, etc. * @ops: Callbacks to device driver diff --git a/include/linux/intel_rapl.h b/include/linux/intel_rapl.h new file mode 100644 index 000000000000..efb3ce892c20 --- /dev/null +++ b/include/linux/intel_rapl.h @@ -0,0 +1,155 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Data types and headers for RAPL support + * + * Copyright (C) 2019 Intel Corporation. + * + * Author: Zhang Rui <rui.zhang@intel.com> + */ + +#ifndef __INTEL_RAPL_H__ +#define __INTEL_RAPL_H__ + +#include <linux/types.h> +#include <linux/powercap.h> +#include <linux/cpuhotplug.h> + +enum rapl_domain_type { + RAPL_DOMAIN_PACKAGE, /* entire package/socket */ + RAPL_DOMAIN_PP0, /* core power plane */ + RAPL_DOMAIN_PP1, /* graphics uncore */ + RAPL_DOMAIN_DRAM, /* DRAM control_type */ + RAPL_DOMAIN_PLATFORM, /* PSys control_type */ + RAPL_DOMAIN_MAX, +}; + +enum rapl_domain_reg_id { + RAPL_DOMAIN_REG_LIMIT, + RAPL_DOMAIN_REG_STATUS, + RAPL_DOMAIN_REG_PERF, + RAPL_DOMAIN_REG_POLICY, + RAPL_DOMAIN_REG_INFO, + RAPL_DOMAIN_REG_MAX, +}; + +struct rapl_package; + +enum rapl_primitives { + ENERGY_COUNTER, + POWER_LIMIT1, + POWER_LIMIT2, + FW_LOCK, + + PL1_ENABLE, /* power limit 1, aka long term */ + PL1_CLAMP, /* allow frequency to go below OS request */ + PL2_ENABLE, /* power limit 2, aka short term, instantaneous */ + PL2_CLAMP, + + TIME_WINDOW1, /* long term */ + TIME_WINDOW2, /* short term */ + THERMAL_SPEC_POWER, + MAX_POWER, + + MIN_POWER, + MAX_TIME_WINDOW, + THROTTLED_TIME, + PRIORITY_LEVEL, + + /* below are not raw primitive data */ + AVERAGE_POWER, + NR_RAPL_PRIMITIVES, +}; + +struct rapl_domain_data { + u64 primitives[NR_RAPL_PRIMITIVES]; + unsigned long timestamp; +}; + +#define NR_POWER_LIMITS (2) +struct rapl_power_limit { + struct powercap_zone_constraint *constraint; + int prim_id; /* primitive ID used to enable */ + struct rapl_domain *domain; + const char *name; + u64 last_power_limit; +}; + +struct rapl_package; + +struct rapl_domain { + const char *name; + enum rapl_domain_type id; + u64 regs[RAPL_DOMAIN_REG_MAX]; + struct powercap_zone power_zone; + struct rapl_domain_data rdd; + struct rapl_power_limit rpl[NR_POWER_LIMITS]; + u64 attr_map; /* track capabilities */ + unsigned int state; + unsigned int domain_energy_unit; + struct rapl_package *rp; +}; + +struct reg_action { + u64 reg; + u64 mask; + u64 value; + int err; +}; + +/** + * struct rapl_if_priv: private data for different RAPL interfaces + * @control_type: Each RAPL interface must have its own powercap + * control type. + * @platform_rapl_domain: Optional. Some RAPL interface may have platform + * level RAPL control. + * @pcap_rapl_online: CPU hotplug state for each RAPL interface. + * @reg_unit: Register for getting energy/power/time unit. + * @regs: Register sets for different RAPL Domains. + * @limits: Number of power limits supported by each domain. + * @read_raw: Callback for reading RAPL interface specific + * registers. + * @write_raw: Callback for writing RAPL interface specific + * registers. + */ +struct rapl_if_priv { + struct powercap_control_type *control_type; + struct rapl_domain *platform_rapl_domain; + enum cpuhp_state pcap_rapl_online; + u64 reg_unit; + u64 regs[RAPL_DOMAIN_MAX][RAPL_DOMAIN_REG_MAX]; + int limits[RAPL_DOMAIN_MAX]; + int (*read_raw)(int cpu, struct reg_action *ra); + int (*write_raw)(int cpu, struct reg_action *ra); +}; + +/* maximum rapl package domain name: package-%d-die-%d */ +#define PACKAGE_DOMAIN_NAME_LENGTH 30 + +struct rapl_package { + unsigned int id; /* logical die id, equals physical 1-die systems */ + unsigned int nr_domains; + unsigned long domain_map; /* bit map of active domains */ + unsigned int power_unit; + unsigned int energy_unit; + unsigned int time_unit; + struct rapl_domain *domains; /* array of domains, sized at runtime */ + struct powercap_zone *power_zone; /* keep track of parent zone */ + unsigned long power_limit_irq; /* keep track of package power limit + * notify interrupt enable status. + */ + struct list_head plist; + int lead_cpu; /* one active cpu per package for access */ + /* Track active cpus */ + struct cpumask cpumask; + char name[PACKAGE_DOMAIN_NAME_LENGTH]; + struct rapl_if_priv *priv; +}; + +struct rapl_package *rapl_find_package_domain(int cpu, struct rapl_if_priv *priv); +struct rapl_package *rapl_add_package(int cpu, struct rapl_if_priv *priv); +void rapl_remove_package(struct rapl_package *rp); + +int rapl_add_platform_domain(struct rapl_if_priv *priv); +void rapl_remove_platform_domain(struct rapl_if_priv *priv); + +#endif /* __INTEL_RAPL_H__ */ diff --git a/include/linux/intel_th.h b/include/linux/intel_th.h new file mode 100644 index 000000000000..9b7f4c22499c --- /dev/null +++ b/include/linux/intel_th.h @@ -0,0 +1,79 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Intel(R) Trace Hub data structures for implementing buffer sinks. + * + * Copyright (C) 2019 Intel Corporation. + */ + +#ifndef _INTEL_TH_H_ +#define _INTEL_TH_H_ + +#include <linux/scatterlist.h> + +/* MSC operating modes (MSC_MODE) */ +enum { + MSC_MODE_SINGLE = 0, + MSC_MODE_MULTI, + MSC_MODE_EXI, + MSC_MODE_DEBUG, +}; + +struct msu_buffer { + const char *name; + /* + * ->assign() called when buffer 'mode' is set to this driver + * (aka mode_store()) + * @device: struct device * of the msc + * @mode: allows the driver to set HW mode (see the enum above) + * Returns: a pointer to a private structure associated with this + * msc or NULL in case of error. This private structure + * will then be passed into all other callbacks. + */ + void *(*assign)(struct device *dev, int *mode); + /* ->unassign(): some other mode is selected, clean up */ + void (*unassign)(void *priv); + /* + * ->alloc_window(): allocate memory for the window of a given + * size + * @sgt: pointer to sg_table, can be overridden by the buffer + * driver, or kept intact + * Returns: number of sg table entries <= number of pages; + * 0 is treated as an allocation failure. + */ + int (*alloc_window)(void *priv, struct sg_table **sgt, + size_t size); + void (*free_window)(void *priv, struct sg_table *sgt); + /* ->activate(): trace has started */ + void (*activate)(void *priv); + /* ->deactivate(): trace is about to stop */ + void (*deactivate)(void *priv); + /* + * ->ready(): window @sgt is filled up to the last block OR + * tracing is stopped by the user; this window contains + * @bytes data. The window in question transitions into + * the "LOCKED" state, indicating that it can't be used + * by hardware. To clear this state and make the window + * available to the hardware again, call + * intel_th_msc_window_unlock(). + */ + int (*ready)(void *priv, struct sg_table *sgt, size_t bytes); +}; + +int intel_th_msu_buffer_register(const struct msu_buffer *mbuf, + struct module *owner); +void intel_th_msu_buffer_unregister(const struct msu_buffer *mbuf); +void intel_th_msc_window_unlock(struct device *dev, struct sg_table *sgt); + +#define module_intel_th_msu_buffer(__buffer) \ +static int __init __buffer##_init(void) \ +{ \ + return intel_th_msu_buffer_register(&(__buffer), THIS_MODULE); \ +} \ +module_init(__buffer##_init); \ +static void __exit __buffer##_exit(void) \ +{ \ + intel_th_msu_buffer_unregister(&(__buffer)); \ +} \ +module_exit(__buffer##_exit); + +#endif /* _INTEL_TH_H_ */ diff --git a/include/linux/interconnect-provider.h b/include/linux/interconnect-provider.h index 63caccadc2db..b16f9effa555 100644 --- a/include/linux/interconnect-provider.h +++ b/include/linux/interconnect-provider.h @@ -36,6 +36,8 @@ struct icc_node *of_icc_xlate_onecell(struct of_phandle_args *spec, * @nodes: internal list of the interconnect provider nodes * @set: pointer to device specific set operation function * @aggregate: pointer to device specific aggregate operation function + * @pre_aggregate: pointer to device specific function that is called + * before the aggregation begins (optional) * @xlate: provider-specific callback for mapping nodes from phandle arguments * @dev: the device this interconnect provider belongs to * @users: count of active users @@ -45,8 +47,9 @@ struct icc_provider { struct list_head provider_list; struct list_head nodes; int (*set)(struct icc_node *src, struct icc_node *dst); - int (*aggregate)(struct icc_node *node, u32 avg_bw, u32 peak_bw, - u32 *agg_avg, u32 *agg_peak); + int (*aggregate)(struct icc_node *node, u32 tag, u32 avg_bw, + u32 peak_bw, u32 *agg_avg, u32 *agg_peak); + void (*pre_aggregate)(struct icc_node *node); struct icc_node* (*xlate)(struct of_phandle_args *spec, void *data); struct device *dev; int users; diff --git a/include/linux/interconnect.h b/include/linux/interconnect.h index dc25864755ba..d70a914cba11 100644 --- a/include/linux/interconnect.h +++ b/include/linux/interconnect.h @@ -30,6 +30,7 @@ struct icc_path *icc_get(struct device *dev, const int src_id, struct icc_path *of_icc_get(struct device *dev, const char *name); void icc_put(struct icc_path *path); int icc_set_bw(struct icc_path *path, u32 avg_bw, u32 peak_bw); +void icc_set_tag(struct icc_path *path, u32 tag); #else @@ -54,6 +55,10 @@ static inline int icc_set_bw(struct icc_path *path, u32 avg_bw, u32 peak_bw) return 0; } +static inline void icc_set_tag(struct icc_path *path, u32 tag) +{ +} + #endif /* CONFIG_INTERCONNECT */ #endif /* __LINUX_INTERCONNECT_H */ diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h index c7eef32e7739..89fc59dab57d 100644 --- a/include/linux/interrupt.h +++ b/include/linux/interrupt.h @@ -52,7 +52,7 @@ * irq line disabled until the threaded handler has been run. * IRQF_NO_SUSPEND - Do not disable this IRQ during suspend. Does not guarantee * that this interrupt will wake the system from a suspended - * state. See Documentation/power/suspend-and-interrupts.txt + * state. See Documentation/power/suspend-and-interrupts.rst * IRQF_FORCE_RESUME - Force enable it on resume even if IRQF_NO_SUSPEND is set * IRQF_NO_THREAD - Interrupt cannot be threaded * IRQF_EARLY_RESUME - Resume IRQ early during syscore instead of at device @@ -238,6 +238,7 @@ extern void teardown_percpu_nmi(unsigned int irq); /* The following three functions are for the core kernel use only. */ extern void suspend_device_irqs(void); extern void resume_device_irqs(void); +extern void rearm_wake_irq(unsigned int irq); /** * struct irq_affinity_notify - context for notification of IRQ affinity changes @@ -472,7 +473,11 @@ extern int irq_set_irqchip_state(unsigned int irq, enum irqchip_irq_state which, bool state); #ifdef CONFIG_IRQ_FORCED_THREADING +# ifdef CONFIG_PREEMPT_RT +# define force_irqthreads (true) +# else extern bool force_irqthreads; +# endif #else #define force_irqthreads (0) #endif diff --git a/include/linux/interval_tree_generic.h b/include/linux/interval_tree_generic.h index 855476145fe1..aaa8a0767aa3 100644 --- a/include/linux/interval_tree_generic.h +++ b/include/linux/interval_tree_generic.h @@ -30,26 +30,8 @@ \ /* Callbacks for augmented rbtree insert and remove */ \ \ -static inline ITTYPE ITPREFIX ## _compute_subtree_last(ITSTRUCT *node) \ -{ \ - ITTYPE max = ITLAST(node), subtree_last; \ - if (node->ITRB.rb_left) { \ - subtree_last = rb_entry(node->ITRB.rb_left, \ - ITSTRUCT, ITRB)->ITSUBTREE; \ - if (max < subtree_last) \ - max = subtree_last; \ - } \ - if (node->ITRB.rb_right) { \ - subtree_last = rb_entry(node->ITRB.rb_right, \ - ITSTRUCT, ITRB)->ITSUBTREE; \ - if (max < subtree_last) \ - max = subtree_last; \ - } \ - return max; \ -} \ - \ -RB_DECLARE_CALLBACKS(static, ITPREFIX ## _augment, ITSTRUCT, ITRB, \ - ITTYPE, ITSUBTREE, ITPREFIX ## _compute_subtree_last) \ +RB_DECLARE_CALLBACKS_MAX(static, ITPREFIX ## _augment, \ + ITSTRUCT, ITRB, ITTYPE, ITSUBTREE, ITLAST) \ \ /* Insert / remove interval nodes from the tree */ \ \ diff --git a/include/linux/io-pgtable.h b/include/linux/io-pgtable.h index 76969a564831..ec7a13405f10 100644 --- a/include/linux/io-pgtable.h +++ b/include/linux/io-pgtable.h @@ -1,7 +1,9 @@ /* SPDX-License-Identifier: GPL-2.0 */ #ifndef __IO_PGTABLE_H #define __IO_PGTABLE_H + #include <linux/bitops.h> +#include <linux/iommu.h> /* * Public API for use by IOMMU drivers @@ -17,22 +19,31 @@ enum io_pgtable_fmt { }; /** - * struct iommu_gather_ops - IOMMU callbacks for TLB and page table management. + * struct iommu_flush_ops - IOMMU callbacks for TLB and page table management. * - * @tlb_flush_all: Synchronously invalidate the entire TLB context. - * @tlb_add_flush: Queue up a TLB invalidation for a virtual address range. - * @tlb_sync: Ensure any queued TLB invalidation has taken effect, and - * any corresponding page table updates are visible to the - * IOMMU. + * @tlb_flush_all: Synchronously invalidate the entire TLB context. + * @tlb_flush_walk: Synchronously invalidate all intermediate TLB state + * (sometimes referred to as the "walk cache") for a virtual + * address range. + * @tlb_flush_leaf: Synchronously invalidate all leaf TLB state for a virtual + * address range. + * @tlb_add_page: Optional callback to queue up leaf TLB invalidation for a + * single page. IOMMUs that cannot batch TLB invalidation + * operations efficiently will typically issue them here, but + * others may decide to update the iommu_iotlb_gather structure + * and defer the invalidation until iommu_tlb_sync() instead. * * Note that these can all be called in atomic context and must therefore * not block. */ -struct iommu_gather_ops { +struct iommu_flush_ops { void (*tlb_flush_all)(void *cookie); - void (*tlb_add_flush)(unsigned long iova, size_t size, size_t granule, - bool leaf, void *cookie); - void (*tlb_sync)(void *cookie); + void (*tlb_flush_walk)(unsigned long iova, size_t size, size_t granule, + void *cookie); + void (*tlb_flush_leaf)(unsigned long iova, size_t size, size_t granule, + void *cookie); + void (*tlb_add_page)(struct iommu_iotlb_gather *gather, + unsigned long iova, size_t granule, void *cookie); }; /** @@ -44,6 +55,8 @@ struct iommu_gather_ops { * tables. * @ias: Input address (iova) size, in bits. * @oas: Output address (paddr) size, in bits. + * @coherent_walk A flag to indicate whether or not page table walks made + * by the IOMMU are coherent with the CPU caches. * @tlb: TLB management callbacks for this set of tables. * @iommu_dev: The device representing the DMA configuration for the * page table walker. @@ -63,15 +76,9 @@ struct io_pgtable_cfg { * (unmapped) entries but the hardware might do so anyway, perform * TLB maintenance when mapping as well as when unmapping. * - * IO_PGTABLE_QUIRK_ARM_MTK_4GB: (ARM v7s format) Set bit 9 in all - * PTEs, for Mediatek IOMMUs which treat it as a 33rd address bit - * when the SoC is in "4GB mode" and they can only access the high - * remap of DRAM (0x1_00000000 to 0x1_ffffffff). - * - * IO_PGTABLE_QUIRK_NO_DMA: Guarantees that the tables will only ever - * be accessed by a fully cache-coherent IOMMU or CPU (e.g. for a - * software-emulated IOMMU), such that pagetable updates need not - * be treated as explicit DMA data. + * IO_PGTABLE_QUIRK_ARM_MTK_EXT: (ARM v7s format) MediaTek IOMMUs extend + * to support up to 34 bits PA where the bit32 and bit33 are + * encoded in the bit9 and bit4 of the PTE respectively. * * IO_PGTABLE_QUIRK_NON_STRICT: Skip issuing synchronous leaf TLBIs * on unmap, for DMA domains using the flush queue mechanism for @@ -80,14 +87,14 @@ struct io_pgtable_cfg { #define IO_PGTABLE_QUIRK_ARM_NS BIT(0) #define IO_PGTABLE_QUIRK_NO_PERMS BIT(1) #define IO_PGTABLE_QUIRK_TLBI_ON_MAP BIT(2) - #define IO_PGTABLE_QUIRK_ARM_MTK_4GB BIT(3) - #define IO_PGTABLE_QUIRK_NO_DMA BIT(4) - #define IO_PGTABLE_QUIRK_NON_STRICT BIT(5) + #define IO_PGTABLE_QUIRK_ARM_MTK_EXT BIT(3) + #define IO_PGTABLE_QUIRK_NON_STRICT BIT(4) unsigned long quirks; unsigned long pgsize_bitmap; unsigned int ias; unsigned int oas; - const struct iommu_gather_ops *tlb; + bool coherent_walk; + const struct iommu_flush_ops *tlb; struct device *iommu_dev; /* Low-level data specific to the table format */ @@ -131,7 +138,7 @@ struct io_pgtable_ops { int (*map)(struct io_pgtable_ops *ops, unsigned long iova, phys_addr_t paddr, size_t size, int prot); size_t (*unmap)(struct io_pgtable_ops *ops, unsigned long iova, - size_t size); + size_t size, struct iommu_iotlb_gather *gather); phys_addr_t (*iova_to_phys)(struct io_pgtable_ops *ops, unsigned long iova); }; @@ -187,15 +194,27 @@ static inline void io_pgtable_tlb_flush_all(struct io_pgtable *iop) iop->cfg.tlb->tlb_flush_all(iop->cookie); } -static inline void io_pgtable_tlb_add_flush(struct io_pgtable *iop, - unsigned long iova, size_t size, size_t granule, bool leaf) +static inline void +io_pgtable_tlb_flush_walk(struct io_pgtable *iop, unsigned long iova, + size_t size, size_t granule) +{ + iop->cfg.tlb->tlb_flush_walk(iova, size, granule, iop->cookie); +} + +static inline void +io_pgtable_tlb_flush_leaf(struct io_pgtable *iop, unsigned long iova, + size_t size, size_t granule) { - iop->cfg.tlb->tlb_add_flush(iova, size, granule, leaf, iop->cookie); + iop->cfg.tlb->tlb_flush_leaf(iova, size, granule, iop->cookie); } -static inline void io_pgtable_tlb_sync(struct io_pgtable *iop) +static inline void +io_pgtable_tlb_add_page(struct io_pgtable *iop, + struct iommu_iotlb_gather * gather, unsigned long iova, + size_t granule) { - iop->cfg.tlb->tlb_sync(iop->cookie); + if (iop->cfg.tlb->tlb_add_page) + iop->cfg.tlb->tlb_add_page(gather, iova, granule, iop->cookie); } /** diff --git a/include/linux/io.h b/include/linux/io.h index 9876e5801a9d..accac822336a 100644 --- a/include/linux/io.h +++ b/include/linux/io.h @@ -33,6 +33,7 @@ static inline int ioremap_page_range(unsigned long addr, unsigned long end, #ifdef CONFIG_HAVE_ARCH_HUGE_VMAP void __init ioremap_huge_init(void); +int arch_ioremap_p4d_supported(void); int arch_ioremap_pud_supported(void); int arch_ioremap_pmd_supported(void); #else diff --git a/include/linux/ioc4.h b/include/linux/ioc4.h deleted file mode 100644 index 51e2b9fb6372..000000000000 --- a/include/linux/ioc4.h +++ /dev/null @@ -1,184 +0,0 @@ -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * Copyright (c) 2005 Silicon Graphics, Inc. All Rights Reserved. - */ - -#ifndef _LINUX_IOC4_H -#define _LINUX_IOC4_H - -#include <linux/interrupt.h> - -/*************** - * Definitions * - ***************/ - -/* Miscellaneous values inherent to hardware */ - -#define IOC4_EXTINT_COUNT_DIVISOR 520 /* PCI clocks per COUNT tick */ - -/*********************************** - * Structures needed by subdrivers * - ***********************************/ - -/* This structure fully describes the IOC4 miscellaneous registers which - * appear at bar[0]+0x00000 through bar[0]+0x0005c. The corresponding - * PCI resource is managed by the main IOC4 driver because it contains - * registers of interest to many different IOC4 subdrivers. - */ -struct ioc4_misc_regs { - /* Miscellaneous IOC4 registers */ - union ioc4_pci_err_addr_l { - uint32_t raw; - struct { - uint32_t valid:1; /* Address captured */ - uint32_t master_id:4; /* Unit causing error - * 0/1: Serial port 0 TX/RX - * 2/3: Serial port 1 TX/RX - * 4/5: Serial port 2 TX/RX - * 6/7: Serial port 3 TX/RX - * 8: ATA/ATAPI - * 9-15: Undefined - */ - uint32_t mul_err:1; /* Multiple errors occurred */ - uint32_t addr:26; /* Bits 31-6 of error addr */ - } fields; - } pci_err_addr_l; - uint32_t pci_err_addr_h; /* Bits 63-32 of error addr */ - union ioc4_sio_int { - uint32_t raw; - struct { - uint8_t tx_mt:1; /* TX ring buffer empty */ - uint8_t rx_full:1; /* RX ring buffer full */ - uint8_t rx_high:1; /* RX high-water exceeded */ - uint8_t rx_timer:1; /* RX timer has triggered */ - uint8_t delta_dcd:1; /* DELTA_DCD seen */ - uint8_t delta_cts:1; /* DELTA_CTS seen */ - uint8_t intr_pass:1; /* Interrupt pass-through */ - uint8_t tx_explicit:1; /* TX, MCW, or delay complete */ - } fields[4]; - } sio_ir; /* Serial interrupt state */ - union ioc4_other_int { - uint32_t raw; - struct { - uint32_t ata_int:1; /* ATA port passthru */ - uint32_t ata_memerr:1; /* ATA halted by mem error */ - uint32_t memerr:4; /* Serial halted by mem err */ - uint32_t kbd_int:1; /* kbd/mouse intr asserted */ - uint32_t reserved:16; /* zero */ - uint32_t rt_int:1; /* INT_OUT section latch */ - uint32_t gen_int:8; /* Intr. from generic pins */ - } fields; - } other_ir; /* Other interrupt state */ - union ioc4_sio_int sio_ies; /* Serial interrupt enable set */ - union ioc4_other_int other_ies; /* Other interrupt enable set */ - union ioc4_sio_int sio_iec; /* Serial interrupt enable clear */ - union ioc4_other_int other_iec; /* Other interrupt enable clear */ - union ioc4_sio_cr { - uint32_t raw; - struct { - uint32_t cmd_pulse:4; /* Bytebus strobe width */ - uint32_t arb_diag:3; /* PCI bus requester */ - uint32_t sio_diag_idle:1; /* Active ser req? */ - uint32_t ata_diag_idle:1; /* Active ATA req? */ - uint32_t ata_diag_active:1; /* ATA req is winner */ - uint32_t reserved:22; /* zero */ - } fields; - } sio_cr; - uint32_t unused1; - union ioc4_int_out { - uint32_t raw; - struct { - uint32_t count:16; /* Period control */ - uint32_t mode:3; /* Output signal shape */ - uint32_t reserved:11; /* zero */ - uint32_t diag:1; /* Timebase control */ - uint32_t int_out:1; /* Current value */ - } fields; - } int_out; /* External interrupt output control */ - uint32_t unused2; - union ioc4_gpcr { - uint32_t raw; - struct { - uint32_t dir:8; /* Pin direction */ - uint32_t edge:8; /* Edge/level mode */ - uint32_t reserved1:4; /* zero */ - uint32_t int_out_en:1; /* INT_OUT enable */ - uint32_t reserved2:11; /* zero */ - } fields; - } gpcr_s; /* Generic PIO control set */ - union ioc4_gpcr gpcr_c; /* Generic PIO control clear */ - union ioc4_gpdr { - uint32_t raw; - struct { - uint32_t gen_pin:8; /* State of pins */ - uint32_t reserved:24; - } fields; - } gpdr; /* Generic PIO data */ - uint32_t unused3; - union ioc4_gppr { - uint32_t raw; - struct { - uint32_t gen_pin:1; /* Single pin state */ - uint32_t reserved:31; - } fields; - } gppr[8]; /* Generic PIO pins */ -}; - -/* Masks for GPCR DIR pins */ -#define IOC4_GPCR_DIR_0 0x01 /* External interrupt output */ -#define IOC4_GPCR_DIR_1 0x02 /* External interrupt input */ -#define IOC4_GPCR_DIR_2 0x04 -#define IOC4_GPCR_DIR_3 0x08 /* Keyboard/mouse presence */ -#define IOC4_GPCR_DIR_4 0x10 /* Ser. port 0 xcvr select (0=232, 1=422) */ -#define IOC4_GPCR_DIR_5 0x20 /* Ser. port 1 xcvr select (0=232, 1=422) */ -#define IOC4_GPCR_DIR_6 0x40 /* Ser. port 2 xcvr select (0=232, 1=422) */ -#define IOC4_GPCR_DIR_7 0x80 /* Ser. port 3 xcvr select (0=232, 1=422) */ - -/* Masks for GPCR EDGE pins */ -#define IOC4_GPCR_EDGE_0 0x01 -#define IOC4_GPCR_EDGE_1 0x02 /* External interrupt input */ -#define IOC4_GPCR_EDGE_2 0x04 -#define IOC4_GPCR_EDGE_3 0x08 -#define IOC4_GPCR_EDGE_4 0x10 -#define IOC4_GPCR_EDGE_5 0x20 -#define IOC4_GPCR_EDGE_6 0x40 -#define IOC4_GPCR_EDGE_7 0x80 - -#define IOC4_VARIANT_IO9 0x0900 -#define IOC4_VARIANT_PCI_RT 0x0901 -#define IOC4_VARIANT_IO10 0x1000 - -/* One of these per IOC4 */ -struct ioc4_driver_data { - struct list_head idd_list; - unsigned long idd_bar0; - struct pci_dev *idd_pdev; - const struct pci_device_id *idd_pci_id; - struct ioc4_misc_regs __iomem *idd_misc_regs; - unsigned long count_period; - void *idd_serial_data; - unsigned int idd_variant; -}; - -/* One per submodule */ -struct ioc4_submodule { - struct list_head is_list; - char *is_name; - struct module *is_owner; - int (*is_probe) (struct ioc4_driver_data *); - int (*is_remove) (struct ioc4_driver_data *); -}; - -#define IOC4_NUM_CARDS 8 /* max cards per partition */ - -/********************************** - * Functions needed by submodules * - **********************************/ - -extern int ioc4_register_submodule(struct ioc4_submodule *); -extern void ioc4_unregister_submodule(struct ioc4_submodule *); - -#endif /* _LINUX_IOC4_H */ diff --git a/include/linux/iomap.h b/include/linux/iomap.h index 2103b94cb1bf..7aa5d6117936 100644 --- a/include/linux/iomap.h +++ b/include/linux/iomap.h @@ -7,6 +7,7 @@ #include <linux/mm.h> #include <linux/types.h> #include <linux/mm_types.h> +#include <linux/blkdev.h> struct address_space; struct fiemap_extent_info; @@ -35,6 +36,7 @@ struct vm_fault; #define IOMAP_F_NEW 0x01 /* blocks have been newly allocated */ #define IOMAP_F_DIRTY 0x02 /* uncommitted metadata */ #define IOMAP_F_BUFFER_HEAD 0x04 /* file system requires buffer heads */ +#define IOMAP_F_SIZE_CHANGED 0x08 /* file size has changed */ /* * Flags that only need to be reported for IOMAP_REPORT requests: @@ -68,6 +70,12 @@ struct iomap { const struct iomap_page_ops *page_ops; }; +static inline sector_t +iomap_sector(struct iomap *iomap, loff_t pos) +{ + return (iomap->addr + pos - iomap->offset) >> SECTOR_SHIFT; +} + /* * When a filesystem sets page_ops in an iomap mapping it returns, page_prepare * and page_done will be called for each page written to. This only applies to @@ -115,6 +123,16 @@ struct iomap_ops { }; /* + * Main iomap iterator function. + */ +typedef loff_t (*iomap_actor_t)(struct inode *inode, loff_t pos, loff_t len, + void *data, struct iomap *iomap); + +loff_t iomap_apply(struct inode *inode, loff_t pos, loff_t length, + unsigned flags, const struct iomap_ops *ops, void *data, + iomap_actor_t actor); + +/* * Structure allocate for each page when block size < PAGE_SIZE to track * sub-page uptodate status and I/O completions. */ @@ -170,10 +188,14 @@ sector_t iomap_bmap(struct address_space *mapping, sector_t bno, */ #define IOMAP_DIO_UNWRITTEN (1 << 0) /* covers unwritten extent(s) */ #define IOMAP_DIO_COW (1 << 1) /* covers COW extent(s) */ -typedef int (iomap_dio_end_io_t)(struct kiocb *iocb, ssize_t ret, - unsigned flags); + +struct iomap_dio_ops { + int (*end_io)(struct kiocb *iocb, ssize_t size, int error, + unsigned flags); +}; + ssize_t iomap_dio_rw(struct kiocb *iocb, struct iov_iter *iter, - const struct iomap_ops *ops, iomap_dio_end_io_t end_io); + const struct iomap_ops *ops, const struct iomap_dio_ops *dops); int iomap_dio_iopoll(struct kiocb *kiocb, bool spin); #ifdef CONFIG_SWAP diff --git a/include/linux/iommu.h b/include/linux/iommu.h index e552c3b63f6f..29bac5345563 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h @@ -13,6 +13,7 @@ #include <linux/errno.h> #include <linux/err.h> #include <linux/of.h> +#include <uapi/linux/iommu.h> #define IOMMU_READ (1 << 0) #define IOMMU_WRITE (1 << 1) @@ -29,6 +30,12 @@ * if the IOMMU page table format is equivalent. */ #define IOMMU_PRIV (1 << 5) +/* + * Non-coherent masters on few Qualcomm SoCs can use this page protection flag + * to set correct cacheability attributes to use an outer level of cache - + * last level cache, aka system cache. + */ +#define IOMMU_QCOM_SYS_CACHE (1 << 6) struct iommu_ops; struct iommu_group; @@ -37,6 +44,7 @@ struct device; struct iommu_domain; struct notifier_block; struct iommu_sva; +struct iommu_fault_event; /* iommu fault flags */ #define IOMMU_FAULT_READ 0x0 @@ -46,6 +54,7 @@ typedef int (*iommu_fault_handler_t)(struct iommu_domain *, struct device *, unsigned long, int, void *); typedef int (*iommu_mm_exit_handler_t)(struct device *dev, struct iommu_sva *, void *); +typedef int (*iommu_dev_fault_handler_t)(struct iommu_fault *, void *); struct iommu_domain_geometry { dma_addr_t aperture_start; /* First address that can be mapped */ @@ -123,6 +132,12 @@ enum iommu_attr { enum iommu_resv_type { /* Memory regions which must be mapped 1:1 at all times */ IOMMU_RESV_DIRECT, + /* + * Memory regions which are advertised to be 1:1 but are + * commonly considered relaxable in some conditions, + * for instance in device assignment use case (USB, Graphics) + */ + IOMMU_RESV_DIRECT_RELAXABLE, /* Arbitrary "never map this or give it to a device" address ranges */ IOMMU_RESV_RESERVED, /* Hardware MSI region (untranslated) */ @@ -177,6 +192,23 @@ struct iommu_sva_ops { #ifdef CONFIG_IOMMU_API /** + * struct iommu_iotlb_gather - Range information for a pending IOTLB flush + * + * @start: IOVA representing the start of the range to be flushed + * @end: IOVA representing the end of the range to be flushed (exclusive) + * @pgsize: The interval at which to perform the flush + * + * This structure is intended to be updated by multiple calls to the + * ->unmap() function in struct iommu_ops before eventually being passed + * into ->iotlb_sync(). + */ +struct iommu_iotlb_gather { + unsigned long start; + unsigned long end; + size_t pgsize; +}; + +/** * struct iommu_ops - iommu ops and capabilities * @capable: check capability * @domain_alloc: allocate iommu domain @@ -186,7 +218,6 @@ struct iommu_sva_ops { * @map: map a physically contiguous memory region to an iommu domain * @unmap: unmap a physically contiguous memory region from an iommu domain * @flush_iotlb_all: Synchronously flush all hardware TLBs for this domain - * @iotlb_range_add: Add a given iova range to the flush queue for this domain * @iotlb_sync_map: Sync mappings created recently using @map to the hardware * @iotlb_sync: Flush all queued ranges from the hardware TLBs and empty flush * queue @@ -212,6 +243,7 @@ struct iommu_sva_ops { * @sva_bind: Bind process address space to device * @sva_unbind: Unbind process address space from device * @sva_get_pasid: Get PASID associated to a SVA handle + * @page_response: handle page request response * @pgsize_bitmap: bitmap of all possible supported page sizes */ struct iommu_ops { @@ -226,12 +258,11 @@ struct iommu_ops { int (*map)(struct iommu_domain *domain, unsigned long iova, phys_addr_t paddr, size_t size, int prot); size_t (*unmap)(struct iommu_domain *domain, unsigned long iova, - size_t size); + size_t size, struct iommu_iotlb_gather *iotlb_gather); void (*flush_iotlb_all)(struct iommu_domain *domain); - void (*iotlb_range_add)(struct iommu_domain *domain, - unsigned long iova, size_t size); void (*iotlb_sync_map)(struct iommu_domain *domain); - void (*iotlb_sync)(struct iommu_domain *domain); + void (*iotlb_sync)(struct iommu_domain *domain, + struct iommu_iotlb_gather *iotlb_gather); phys_addr_t (*iova_to_phys)(struct iommu_domain *domain, dma_addr_t iova); int (*add_device)(struct device *dev); void (*remove_device)(struct device *dev); @@ -272,6 +303,10 @@ struct iommu_ops { void (*sva_unbind)(struct iommu_sva *handle); int (*sva_get_pasid)(struct iommu_sva *handle); + int (*page_response)(struct device *dev, + struct iommu_fault_event *evt, + struct iommu_page_response *msg); + unsigned long pgsize_bitmap; }; @@ -289,6 +324,48 @@ struct iommu_device { struct device *dev; }; +/** + * struct iommu_fault_event - Generic fault event + * + * Can represent recoverable faults such as a page requests or + * unrecoverable faults such as DMA or IRQ remapping faults. + * + * @fault: fault descriptor + * @list: pending fault event list, used for tracking responses + */ +struct iommu_fault_event { + struct iommu_fault fault; + struct list_head list; +}; + +/** + * struct iommu_fault_param - per-device IOMMU fault data + * @handler: Callback function to handle IOMMU faults at device level + * @data: handler private data + * @faults: holds the pending faults which needs response + * @lock: protect pending faults list + */ +struct iommu_fault_param { + iommu_dev_fault_handler_t handler; + void *data; + struct list_head faults; + struct mutex lock; +}; + +/** + * struct iommu_param - collection of per-device IOMMU data + * + * @fault_param: IOMMU detected device fault reporting data + * + * TODO: migrate other per device data pointers under iommu_dev_data, e.g. + * struct iommu_group *iommu_group; + * struct iommu_fwspec *iommu_fwspec; + */ +struct iommu_param { + struct mutex lock; + struct iommu_fault_param *fault_param; +}; + int iommu_device_register(struct iommu_device *iommu); void iommu_device_unregister(struct iommu_device *iommu); int iommu_device_sysfs_add(struct iommu_device *iommu, @@ -316,6 +393,13 @@ static inline struct iommu_device *dev_to_iommu_device(struct device *dev) return (struct iommu_device *)dev_get_drvdata(dev); } +static inline void iommu_iotlb_gather_init(struct iommu_iotlb_gather *gather) +{ + *gather = (struct iommu_iotlb_gather) { + .start = ULONG_MAX, + }; +} + #define IOMMU_GROUP_NOTIFY_ADD_DEVICE 1 /* Device added */ #define IOMMU_GROUP_NOTIFY_DEL_DEVICE 2 /* Pre Device removed */ #define IOMMU_GROUP_NOTIFY_BIND_DRIVER 3 /* Pre Driver bind */ @@ -340,7 +424,8 @@ extern int iommu_map(struct iommu_domain *domain, unsigned long iova, extern size_t iommu_unmap(struct iommu_domain *domain, unsigned long iova, size_t size); extern size_t iommu_unmap_fast(struct iommu_domain *domain, - unsigned long iova, size_t size); + unsigned long iova, size_t size, + struct iommu_iotlb_gather *iotlb_gather); extern size_t iommu_map_sg(struct iommu_domain *domain, unsigned long iova, struct scatterlist *sg,unsigned int nents, int prot); extern phys_addr_t iommu_iova_to_phys(struct iommu_domain *domain, dma_addr_t iova); @@ -350,6 +435,10 @@ extern void iommu_set_fault_handler(struct iommu_domain *domain, extern void iommu_get_resv_regions(struct device *dev, struct list_head *list); extern void iommu_put_resv_regions(struct device *dev, struct list_head *list); extern int iommu_request_dm_for_dev(struct device *dev); +extern int iommu_request_dma_domain_for_dev(struct device *dev); +extern void iommu_set_default_passthrough(bool cmd_line); +extern void iommu_set_default_translated(bool cmd_line); +extern bool iommu_default_passthrough(void); extern struct iommu_resv_region * iommu_alloc_resv_region(phys_addr_t start, size_t length, int prot, enum iommu_resv_type type); @@ -378,6 +467,17 @@ extern int iommu_group_register_notifier(struct iommu_group *group, struct notifier_block *nb); extern int iommu_group_unregister_notifier(struct iommu_group *group, struct notifier_block *nb); +extern int iommu_register_device_fault_handler(struct device *dev, + iommu_dev_fault_handler_t handler, + void *data); + +extern int iommu_unregister_device_fault_handler(struct device *dev); + +extern int iommu_report_device_fault(struct device *dev, + struct iommu_fault_event *evt); +extern int iommu_page_response(struct device *dev, + struct iommu_page_response *msg); + extern int iommu_group_id(struct iommu_group *group); extern struct iommu_group *iommu_group_get_for_dev(struct device *dev); extern struct iommu_domain *iommu_group_default_domain(struct iommu_group *); @@ -402,17 +502,38 @@ static inline void iommu_flush_tlb_all(struct iommu_domain *domain) domain->ops->flush_iotlb_all(domain); } -static inline void iommu_tlb_range_add(struct iommu_domain *domain, - unsigned long iova, size_t size) +static inline void iommu_tlb_sync(struct iommu_domain *domain, + struct iommu_iotlb_gather *iotlb_gather) { - if (domain->ops->iotlb_range_add) - domain->ops->iotlb_range_add(domain, iova, size); + if (domain->ops->iotlb_sync) + domain->ops->iotlb_sync(domain, iotlb_gather); + + iommu_iotlb_gather_init(iotlb_gather); } -static inline void iommu_tlb_sync(struct iommu_domain *domain) +static inline void iommu_iotlb_gather_add_page(struct iommu_domain *domain, + struct iommu_iotlb_gather *gather, + unsigned long iova, size_t size) { - if (domain->ops->iotlb_sync) - domain->ops->iotlb_sync(domain); + unsigned long start = iova, end = start + size; + + /* + * If the new page is disjoint from the current range or is mapped at + * a different granularity, then sync the TLB so that the gather + * structure can be rewritten. + */ + if (gather->pgsize != size || + end < gather->start || start > gather->end) { + if (gather->pgsize) + iommu_tlb_sync(domain, gather); + gather->pgsize = size; + } + + if (gather->end < end) + gather->end = end; + + if (gather->start > start) + gather->start = start; } /* PCI device grouping function */ @@ -492,6 +613,8 @@ struct iommu_ops {}; struct iommu_group {}; struct iommu_fwspec {}; struct iommu_device {}; +struct iommu_fault_param {}; +struct iommu_iotlb_gather {}; static inline bool iommu_present(struct bus_type *bus) { @@ -546,7 +669,8 @@ static inline size_t iommu_unmap(struct iommu_domain *domain, } static inline size_t iommu_unmap_fast(struct iommu_domain *domain, - unsigned long iova, int gfp_order) + unsigned long iova, int gfp_order, + struct iommu_iotlb_gather *iotlb_gather) { return 0; } @@ -562,12 +686,8 @@ static inline void iommu_flush_tlb_all(struct iommu_domain *domain) { } -static inline void iommu_tlb_range_add(struct iommu_domain *domain, - unsigned long iova, size_t size) -{ -} - -static inline void iommu_tlb_sync(struct iommu_domain *domain) +static inline void iommu_tlb_sync(struct iommu_domain *domain, + struct iommu_iotlb_gather *iotlb_gather) { } @@ -614,6 +734,24 @@ static inline int iommu_request_dm_for_dev(struct device *dev) return -ENODEV; } +static inline int iommu_request_dma_domain_for_dev(struct device *dev) +{ + return -ENODEV; +} + +static inline void iommu_set_default_passthrough(bool cmd_line) +{ +} + +static inline void iommu_set_default_translated(bool cmd_line) +{ +} + +static inline bool iommu_default_passthrough(void) +{ + return true; +} + static inline int iommu_attach_group(struct iommu_domain *domain, struct iommu_group *group) { @@ -685,6 +823,31 @@ static inline int iommu_group_unregister_notifier(struct iommu_group *group, return 0; } +static inline +int iommu_register_device_fault_handler(struct device *dev, + iommu_dev_fault_handler_t handler, + void *data) +{ + return -ENODEV; +} + +static inline int iommu_unregister_device_fault_handler(struct device *dev) +{ + return 0; +} + +static inline +int iommu_report_device_fault(struct device *dev, struct iommu_fault_event *evt) +{ + return -ENODEV; +} + +static inline int iommu_page_response(struct device *dev, + struct iommu_page_response *msg) +{ + return -ENODEV; +} + static inline int iommu_group_id(struct iommu_group *group) { return -ENODEV; @@ -722,6 +885,16 @@ static inline struct iommu_device *dev_to_iommu_device(struct device *dev) return NULL; } +static inline void iommu_iotlb_gather_init(struct iommu_iotlb_gather *gather) +{ +} + +static inline void iommu_iotlb_gather_add_page(struct iommu_domain *domain, + struct iommu_iotlb_gather *gather, + unsigned long iova, size_t size) +{ +} + static inline void iommu_device_unregister(struct iommu_device *iommu) { } diff --git a/include/linux/iopoll.h b/include/linux/iopoll.h index 3908353deec6..35e15dfd4155 100644 --- a/include/linux/iopoll.h +++ b/include/linux/iopoll.h @@ -21,7 +21,7 @@ * @cond: Break condition (usually involving @val) * @sleep_us: Maximum time to sleep between reads in us (0 * tight-loops). Should be less than ~20ms since usleep_range - * is used (see Documentation/timers/timers-howto.txt). + * is used (see Documentation/timers/timers-howto.rst). * @timeout_us: Timeout in us, 0 means never timeout * * Returns 0 on success and -ETIMEDOUT upon a timeout. In either @@ -60,7 +60,7 @@ * @cond: Break condition (usually involving @val) * @delay_us: Time to udelay between reads in us (0 tight-loops). Should * be less than ~10us since udelay is used (see - * Documentation/timers/timers-howto.txt). + * Documentation/timers/timers-howto.rst). * @timeout_us: Timeout in us, 0 means never timeout * * Returns 0 on success and -ETIMEDOUT upon a timeout. In either diff --git a/include/linux/ioport.h b/include/linux/ioport.h index da0ebaec25f0..7bddddfc76d6 100644 --- a/include/linux/ioport.h +++ b/include/linux/ioport.h @@ -12,6 +12,7 @@ #ifndef __ASSEMBLY__ #include <linux/compiler.h> #include <linux/types.h> +#include <linux/bits.h> /* * Resources are tree-like, allowing * nesting etc.. @@ -132,7 +133,15 @@ enum { IORES_DESC_PERSISTENT_MEMORY = 4, IORES_DESC_PERSISTENT_MEMORY_LEGACY = 5, IORES_DESC_DEVICE_PRIVATE_MEMORY = 6, - IORES_DESC_DEVICE_PUBLIC_MEMORY = 7, + IORES_DESC_RESERVED = 7, +}; + +/* + * Flags controlling ioremap() behavior. + */ +enum { + IORES_MAP_SYSTEM_RAM = BIT(0), + IORES_MAP_ENCRYPTED = BIT(1), }; /* helpers to define resources */ @@ -286,6 +295,10 @@ static inline bool resource_overlaps(struct resource *r1, struct resource *r2) return (r1->start <= r2->end && r1->end >= r2->start); } +struct resource *devm_request_free_mem_region(struct device *dev, + struct resource *base, unsigned long size); +struct resource *request_free_mem_region(struct resource *base, + unsigned long size, const char *name); #endif /* __ASSEMBLY__ */ #endif /* _LINUX_IOPORT_H */ diff --git a/include/linux/iova.h b/include/linux/iova.h index 781b96ac706f..a0637abffee8 100644 --- a/include/linux/iova.h +++ b/include/linux/iova.h @@ -155,6 +155,7 @@ struct iova *reserve_iova(struct iova_domain *iovad, unsigned long pfn_lo, void copy_reserved_iova(struct iova_domain *from, struct iova_domain *to); void init_iova_domain(struct iova_domain *iovad, unsigned long granule, unsigned long start_pfn); +bool has_iova_flush_queue(struct iova_domain *iovad); int init_iova_flush_queue(struct iova_domain *iovad, iova_flush_cb flush_cb, iova_entry_dtor entry_dtor); struct iova *find_iova(struct iova_domain *iovad, unsigned long pfn); @@ -235,6 +236,11 @@ static inline void init_iova_domain(struct iova_domain *iovad, { } +static inline bool has_iova_flush_queue(struct iova_domain *iovad) +{ + return false; +} + static inline int init_iova_flush_queue(struct iova_domain *iovad, iova_flush_cb flush_cb, iova_entry_dtor entry_dtor) diff --git a/include/linux/irqchip/arm-gic-common.h b/include/linux/irqchip/arm-gic-common.h index 626283858563..b9850f5f1906 100644 --- a/include/linux/irqchip/arm-gic-common.h +++ b/include/linux/irqchip/arm-gic-common.h @@ -36,4 +36,9 @@ struct gic_kvm_info { const struct gic_kvm_info *gic_get_kvm_info(void); +struct irq_domain; +struct fwnode_handle; +int gicv2m_init(struct fwnode_handle *parent_handle, + struct irq_domain *parent); + #endif /* __LINUX_IRQCHIP_ARM_GIC_COMMON_H */ diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h index 67c4b9806d43..5cc10cf7cb3e 100644 --- a/include/linux/irqchip/arm-gic-v3.h +++ b/include/linux/irqchip/arm-gic-v3.h @@ -30,10 +30,22 @@ #define GICD_ICFGR 0x0C00 #define GICD_IGRPMODR 0x0D00 #define GICD_NSACR 0x0E00 +#define GICD_IGROUPRnE 0x1000 +#define GICD_ISENABLERnE 0x1200 +#define GICD_ICENABLERnE 0x1400 +#define GICD_ISPENDRnE 0x1600 +#define GICD_ICPENDRnE 0x1800 +#define GICD_ISACTIVERnE 0x1A00 +#define GICD_ICACTIVERnE 0x1C00 +#define GICD_IPRIORITYRnE 0x2000 +#define GICD_ICFGRnE 0x3000 #define GICD_IROUTER 0x6000 +#define GICD_IROUTERnE 0x8000 #define GICD_IDREGS 0xFFD0 #define GICD_PIDR2 0xFFE8 +#define ESPI_BASE_INTID 4096 + /* * Those registers are actually from GICv2, but the spec demands that they * are implemented as RES0 if ARE is 1 (which we do in KVM's emulated GICv3). @@ -69,10 +81,13 @@ #define GICD_TYPER_RSS (1U << 26) #define GICD_TYPER_LPIS (1U << 17) #define GICD_TYPER_MBIS (1U << 16) +#define GICD_TYPER_ESPI (1U << 8) #define GICD_TYPER_ID_BITS(typer) ((((typer) >> 19) & 0x1f) + 1) #define GICD_TYPER_NUM_LPIS(typer) ((((typer) >> 11) & 0x1f) + 1) -#define GICD_TYPER_IRQS(typer) ((((typer) & 0x1f) + 1) * 32) +#define GICD_TYPER_SPIS(typer) ((((typer) & 0x1f) + 1) * 32) +#define GICD_TYPER_ESPIS(typer) \ + (((typer) & GICD_TYPER_ESPI) ? GICD_TYPER_SPIS((typer) >> 27) : 0) #define GICD_IROUTER_SPI_MODE_ONE (0U << 31) #define GICD_IROUTER_SPI_MODE_ANY (1U << 31) @@ -109,6 +124,18 @@ #define GICR_TYPER_CPU_NUMBER(r) (((r) >> 8) & 0xffff) +#define EPPI_BASE_INTID 1056 + +#define GICR_TYPER_NR_PPIS(r) \ + ({ \ + unsigned int __ppinum = ((r) >> 27) & 0x1f; \ + unsigned int __nr_ppis = 16; \ + if (__ppinum == 1 || __ppinum == 2) \ + __nr_ppis += __ppinum * 32; \ + \ + __nr_ppis; \ + }) + #define GICR_WAKER_ProcessorSleep (1U << 1) #define GICR_WAKER_ChildrenAsleep (1U << 2) @@ -469,6 +496,7 @@ #define ICC_CTLR_EL1_A3V_SHIFT 15 #define ICC_CTLR_EL1_A3V_MASK (0x1 << ICC_CTLR_EL1_A3V_SHIFT) #define ICC_CTLR_EL1_RSS (0x1 << 18) +#define ICC_CTLR_EL1_ExtRange (0x1 << 19) #define ICC_PMR_EL1_SHIFT 0 #define ICC_PMR_EL1_MASK (0xff << ICC_PMR_EL1_SHIFT) #define ICC_BPR0_EL1_SHIFT 0 diff --git a/include/linux/irqchip/arm-gic.h b/include/linux/irqchip/arm-gic.h index 316087da1d09..5686711b0f40 100644 --- a/include/linux/irqchip/arm-gic.h +++ b/include/linux/irqchip/arm-gic.h @@ -157,9 +157,6 @@ int gic_of_init_child(struct device *dev, struct gic_chip_data **gic, int irq); */ void gic_init(void __iomem *dist , void __iomem *cpu); -int gicv2m_init(struct fwnode_handle *parent_handle, - struct irq_domain *parent); - void gic_send_sgi(unsigned int cpu_id, unsigned int irq); int gic_get_cpu_id(unsigned int cpu); void gic_migrate_target(unsigned int new_cpu_id); diff --git a/include/linux/irqchip/irq-partition-percpu.h b/include/linux/irqchip/irq-partition-percpu.h index a783ddb58444..2f6ae7551748 100644 --- a/include/linux/irqchip/irq-partition-percpu.h +++ b/include/linux/irqchip/irq-partition-percpu.h @@ -4,6 +4,9 @@ * Author: Marc Zyngier <marc.zyngier@arm.com> */ +#ifndef __LINUX_IRQCHIP_IRQ_PARTITION_PERCPU_H +#define __LINUX_IRQCHIP_IRQ_PARTITION_PERCPU_H + #include <linux/fwnode.h> #include <linux/cpumask.h> #include <linux/irqdomain.h> @@ -46,3 +49,5 @@ struct irq_domain *partition_get_domain(struct partition_desc *dsc) return NULL; } #endif + +#endif /* __LINUX_IRQCHIP_IRQ_PARTITION_PERCPU_H */ diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h index 07ec8b390161..583e7abd07f9 100644 --- a/include/linux/irqdomain.h +++ b/include/linux/irqdomain.h @@ -220,7 +220,7 @@ static inline struct device_node *irq_domain_get_of_node(struct irq_domain *d) #ifdef CONFIG_IRQ_DOMAIN struct fwnode_handle *__irq_domain_alloc_fwnode(unsigned int type, int id, - const char *name, void *data); + const char *name, phys_addr_t *pa); enum { IRQCHIP_FWNODE_REAL, @@ -241,9 +241,9 @@ struct fwnode_handle *irq_domain_alloc_named_id_fwnode(const char *name, int id) NULL); } -static inline struct fwnode_handle *irq_domain_alloc_fwnode(void *data) +static inline struct fwnode_handle *irq_domain_alloc_fwnode(phys_addr_t *pa) { - return __irq_domain_alloc_fwnode(IRQCHIP_FWNODE_REAL, 0, NULL, data); + return __irq_domain_alloc_fwnode(IRQCHIP_FWNODE_REAL, 0, NULL, pa); } void irq_domain_free_fwnode(struct fwnode_handle *fwnode); diff --git a/include/linux/isdn.h b/include/linux/isdn.h deleted file mode 100644 index df97c8444f5d..000000000000 --- a/include/linux/isdn.h +++ /dev/null @@ -1,473 +0,0 @@ -/* $Id: isdn.h,v 1.125.2.3 2004/02/10 01:07:14 keil Exp $ - * - * Main header for the Linux ISDN subsystem (linklevel). - * - * Copyright 1994,95,96 by Fritz Elfert (fritz@isdn4linux.de) - * Copyright 1995,96 by Thinking Objects Software GmbH Wuerzburg - * Copyright 1995,96 by Michael Hipp (Michael.Hipp@student.uni-tuebingen.de) - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - * - */ -#ifndef __ISDN_H__ -#define __ISDN_H__ - - -#include <linux/errno.h> -#include <linux/fs.h> -#include <linux/major.h> -#include <asm/io.h> -#include <linux/kernel.h> -#include <linux/signal.h> -#include <linux/slab.h> -#include <linux/timer.h> -#include <linux/wait.h> -#include <linux/tty.h> -#include <linux/tty_flip.h> -#include <linux/serial_reg.h> -#include <linux/fcntl.h> -#include <linux/types.h> -#include <linux/interrupt.h> -#include <linux/ip.h> -#include <linux/in.h> -#include <linux/netdevice.h> -#include <linux/etherdevice.h> -#include <linux/skbuff.h> -#include <linux/tcp.h> -#include <linux/mutex.h> -#include <uapi/linux/isdn.h> - -#define ISDN_TTY_MAJOR 43 -#define ISDN_TTYAUX_MAJOR 44 -#define ISDN_MAJOR 45 - -/* The minor-devicenumbers for Channel 0 and 1 are used as arguments for - * physical Channel-Mapping, so they MUST NOT be changed without changing - * the correspondent code in isdn.c - */ - -#define ISDN_MINOR_B 0 -#define ISDN_MINOR_BMAX (ISDN_MAX_CHANNELS-1) -#define ISDN_MINOR_CTRL 64 -#define ISDN_MINOR_CTRLMAX (64 + (ISDN_MAX_CHANNELS-1)) -#define ISDN_MINOR_PPP 128 -#define ISDN_MINOR_PPPMAX (128 + (ISDN_MAX_CHANNELS-1)) -#define ISDN_MINOR_STATUS 255 - -#ifdef CONFIG_ISDN_PPP - -#ifdef CONFIG_ISDN_PPP_VJ -# include <net/slhc_vj.h> -#endif - -#include <linux/ppp_defs.h> -#include <linux/ppp-ioctl.h> - -#include <linux/isdn_ppp.h> -#endif - -#ifdef CONFIG_ISDN_X25 -# include <linux/concap.h> -#endif - -#include <linux/isdnif.h> - -#define ISDN_DRVIOCTL_MASK 0x7f /* Mask for Device-ioctl */ - -/* Until now unused */ -#define ISDN_SERVICE_VOICE 1 -#define ISDN_SERVICE_AB 1<<1 -#define ISDN_SERVICE_X21 1<<2 -#define ISDN_SERVICE_G4 1<<3 -#define ISDN_SERVICE_BTX 1<<4 -#define ISDN_SERVICE_DFUE 1<<5 -#define ISDN_SERVICE_X25 1<<6 -#define ISDN_SERVICE_TTX 1<<7 -#define ISDN_SERVICE_MIXED 1<<8 -#define ISDN_SERVICE_FW 1<<9 -#define ISDN_SERVICE_GTEL 1<<10 -#define ISDN_SERVICE_BTXN 1<<11 -#define ISDN_SERVICE_BTEL 1<<12 - -/* Macros checking plain usage */ -#define USG_NONE(x) ((x & ISDN_USAGE_MASK)==ISDN_USAGE_NONE) -#define USG_RAW(x) ((x & ISDN_USAGE_MASK)==ISDN_USAGE_RAW) -#define USG_MODEM(x) ((x & ISDN_USAGE_MASK)==ISDN_USAGE_MODEM) -#define USG_VOICE(x) ((x & ISDN_USAGE_MASK)==ISDN_USAGE_VOICE) -#define USG_NET(x) ((x & ISDN_USAGE_MASK)==ISDN_USAGE_NET) -#define USG_FAX(x) ((x & ISDN_USAGE_MASK)==ISDN_USAGE_FAX) -#define USG_OUTGOING(x) ((x & ISDN_USAGE_OUTGOING)==ISDN_USAGE_OUTGOING) -#define USG_MODEMORVOICE(x) (((x & ISDN_USAGE_MASK)==ISDN_USAGE_MODEM) || \ - ((x & ISDN_USAGE_MASK)==ISDN_USAGE_VOICE) ) - -/* Timer-delays and scheduling-flags */ -#define ISDN_TIMER_RES 4 /* Main Timer-Resolution */ -#define ISDN_TIMER_02SEC (HZ/ISDN_TIMER_RES/5) /* Slow-Timer1 .2 sec */ -#define ISDN_TIMER_1SEC (HZ/ISDN_TIMER_RES) /* Slow-Timer2 1 sec */ -#define ISDN_TIMER_RINGING 5 /* tty RINGs = ISDN_TIMER_1SEC * this factor */ -#define ISDN_TIMER_KEEPINT 10 /* Cisco-Keepalive = ISDN_TIMER_1SEC * this factor */ -#define ISDN_TIMER_MODEMREAD 1 -#define ISDN_TIMER_MODEMPLUS 2 -#define ISDN_TIMER_MODEMRING 4 -#define ISDN_TIMER_MODEMXMIT 8 -#define ISDN_TIMER_NETDIAL 16 -#define ISDN_TIMER_NETHANGUP 32 -#define ISDN_TIMER_CARRIER 256 /* Wait for Carrier */ -#define ISDN_TIMER_FAST (ISDN_TIMER_MODEMREAD | ISDN_TIMER_MODEMPLUS | \ - ISDN_TIMER_MODEMXMIT) -#define ISDN_TIMER_SLOW (ISDN_TIMER_MODEMRING | ISDN_TIMER_NETHANGUP | \ - ISDN_TIMER_NETDIAL | ISDN_TIMER_CARRIER) - -/* Timeout-Values for isdn_net_dial() */ -#define ISDN_TIMER_DTIMEOUT10 (10*HZ/(ISDN_TIMER_02SEC*(ISDN_TIMER_RES+1))) -#define ISDN_TIMER_DTIMEOUT15 (15*HZ/(ISDN_TIMER_02SEC*(ISDN_TIMER_RES+1))) -#define ISDN_TIMER_DTIMEOUT60 (60*HZ/(ISDN_TIMER_02SEC*(ISDN_TIMER_RES+1))) - -/* GLOBAL_FLAGS */ -#define ISDN_GLOBAL_STOPPED 1 - -/*=================== Start of ip-over-ISDN stuff =========================*/ - -/* Feature- and status-flags for a net-interface */ -#define ISDN_NET_CONNECTED 0x01 /* Bound to ISDN-Channel */ -#define ISDN_NET_SECURE 0x02 /* Accept calls from phonelist only */ -#define ISDN_NET_CALLBACK 0x04 /* activate callback */ -#define ISDN_NET_CBHUP 0x08 /* hangup before callback */ -#define ISDN_NET_CBOUT 0x10 /* remote machine does callback */ - -#define ISDN_NET_MAGIC 0x49344C02 /* for paranoia-checking */ - -/* Phone-list-element */ -typedef struct { - void *next; - char num[ISDN_MSNLEN]; -} isdn_net_phone; - -/* - Principles when extending structures for generic encapsulation protocol - ("concap") support: - - Stuff which is hardware specific (here i4l-specific) goes in - the netdev -> local structure (here: isdn_net_local) - - Stuff which is encapsulation protocol specific goes in the structure - which holds the linux device structure (here: isdn_net_device) -*/ - -/* Local interface-data */ -typedef struct isdn_net_local_s { - ulong magic; - struct net_device_stats stats; /* Ethernet Statistics */ - int isdn_device; /* Index to isdn-device */ - int isdn_channel; /* Index to isdn-channel */ - int ppp_slot; /* PPPD device slot number */ - int pre_device; /* Preselected isdn-device */ - int pre_channel; /* Preselected isdn-channel */ - int exclusive; /* If non-zero idx to reserved chan.*/ - int flags; /* Connection-flags */ - int dialretry; /* Counter for Dialout-retries */ - int dialmax; /* Max. Number of Dial-retries */ - int cbdelay; /* Delay before Callback starts */ - int dtimer; /* Timeout-counter for dialing */ - char msn[ISDN_MSNLEN]; /* MSNs/EAZs for this interface */ - u_char cbhup; /* Flag: Reject Call before Callback*/ - u_char dialstate; /* State for dialing */ - u_char p_encap; /* Packet encapsulation */ - /* 0 = Ethernet over ISDN */ - /* 1 = RAW-IP */ - /* 2 = IP with type field */ - u_char l2_proto; /* Layer-2-protocol */ - /* See ISDN_PROTO_L2..-constants in */ - /* isdnif.h */ - /* 0 = X75/LAPB with I-Frames */ - /* 1 = X75/LAPB with UI-Frames */ - /* 2 = X75/LAPB with BUI-Frames */ - /* 3 = HDLC */ - u_char l3_proto; /* Layer-3-protocol */ - /* See ISDN_PROTO_L3..-constants in */ - /* isdnif.h */ - /* 0 = Transparent */ - int huptimer; /* Timeout-counter for auto-hangup */ - int charge; /* Counter for charging units */ - ulong chargetime; /* Timer for Charging info */ - int hupflags; /* Flags for charge-unit-hangup: */ - /* bit0: chargeint is invalid */ - /* bit1: Getting charge-interval */ - /* bit2: Do charge-unit-hangup */ - /* bit3: Do hangup even on incoming */ - int outgoing; /* Flag: outgoing call */ - int onhtime; /* Time to keep link up */ - int chargeint; /* Interval between charge-infos */ - int onum; /* Flag: at least 1 outgoing number */ - int cps; /* current speed of this interface */ - int transcount; /* byte-counter for cps-calculation */ - int sqfull; /* Flag: netdev-queue overloaded */ - ulong sqfull_stamp; /* Start-Time of overload */ - ulong slavedelay; /* Dynamic bundling delaytime */ - int triggercps; /* BogoCPS needed for trigger slave */ - isdn_net_phone *phone[2]; /* List of remote-phonenumbers */ - /* phone[0] = Incoming Numbers */ - /* phone[1] = Outgoing Numbers */ - isdn_net_phone *dial; /* Pointer to dialed number */ - struct net_device *master; /* Ptr to Master device for slaves */ - struct net_device *slave; /* Ptr to Slave device for masters */ - struct isdn_net_local_s *next; /* Ptr to next link in bundle */ - struct isdn_net_local_s *last; /* Ptr to last link in bundle */ - struct isdn_net_dev_s *netdev; /* Ptr to netdev */ - struct sk_buff_head super_tx_queue; /* List of supervisory frames to */ - /* be transmitted asap */ - atomic_t frame_cnt; /* number of frames currently */ - /* queued in HL driver */ - /* Ptr to orig. hard_header_cache */ - spinlock_t xmit_lock; /* used to protect the xmit path of */ - /* a particular channel (including */ - /* the frame_cnt */ - - int pppbind; /* ippp device for bindings */ - int dialtimeout; /* How long shall we try on dialing? (jiffies) */ - int dialwait; /* How long shall we wait after failed attempt? (jiffies) */ - ulong dialstarted; /* jiffies of first dialing-attempt */ - ulong dialwait_timer; /* jiffies of earliest next dialing-attempt */ - int huptimeout; /* How long will the connection be up? (seconds) */ -#ifdef CONFIG_ISDN_X25 - struct concap_device_ops *dops; /* callbacks used by encapsulator */ -#endif - /* use an own struct for that in later versions */ - ulong cisco_myseq; /* Local keepalive seq. for Cisco */ - ulong cisco_mineseen; /* returned keepalive seq. from remote */ - ulong cisco_yourseq; /* Remote keepalive seq. for Cisco */ - int cisco_keepalive_period; /* keepalive period */ - ulong cisco_last_slarp_in; /* jiffie of last keepalive packet we received */ - char cisco_line_state; /* state of line according to keepalive packets */ - char cisco_debserint; /* debugging flag of cisco hdlc with slarp */ - struct timer_list cisco_timer; - struct work_struct tqueue; -} isdn_net_local; - -/* the interface itself */ -typedef struct isdn_net_dev_s { - isdn_net_local *local; - isdn_net_local *queue; /* circular list of all bundled - channels, which are currently - online */ - spinlock_t queue_lock; /* lock to protect queue */ - void *next; /* Pointer to next isdn-interface */ - struct net_device *dev; /* interface to upper levels */ -#ifdef CONFIG_ISDN_PPP - ippp_bundle * pb; /* pointer to the common bundle structure - * with the per-bundle data */ -#endif -#ifdef CONFIG_ISDN_X25 - struct concap_proto *cprot; /* connection oriented encapsulation protocol */ -#endif - -} isdn_net_dev; - -/*===================== End of ip-over-ISDN stuff ===========================*/ - -/*======================= Start of ISDN-tty stuff ===========================*/ - -#define ISDN_ASYNC_MAGIC 0x49344C01 /* for paranoia-checking */ -#define ISDN_SERIAL_XMIT_SIZE 1024 /* Default bufsize for write */ -#define ISDN_SERIAL_XMIT_MAX 4000 /* Maximum bufsize for write */ - -#ifdef CONFIG_ISDN_AUDIO -/* For using sk_buffs with audio we need some private variables - * within each sk_buff. For this purpose, we declare a struct here, - * and put it always at the private skb->cb data array. A few macros help - * accessing the variables. - */ -typedef struct _isdn_audio_data { - unsigned short dle_count; - unsigned char lock; -} isdn_audio_data_t; - -#define ISDN_AUDIO_SKB_DLECOUNT(skb) (((isdn_audio_data_t *)&skb->cb[0])->dle_count) -#define ISDN_AUDIO_SKB_LOCK(skb) (((isdn_audio_data_t *)&skb->cb[0])->lock) -#endif - -/* Private data of AT-command-interpreter */ -typedef struct atemu { - u_char profile[ISDN_MODEM_NUMREG]; /* Modem-Regs. Profile 0 */ - u_char mdmreg[ISDN_MODEM_NUMREG]; /* Modem-Registers */ - char pmsn[ISDN_MSNLEN]; /* EAZ/MSNs Profile 0 */ - char msn[ISDN_MSNLEN]; /* EAZ/MSN */ - char plmsn[ISDN_LMSNLEN]; /* Listening MSNs Profile 0 */ - char lmsn[ISDN_LMSNLEN]; /* Listening MSNs */ - char cpn[ISDN_MSNLEN]; /* CalledPartyNumber on incoming call */ - char connmsg[ISDN_CMSGLEN]; /* CONNECT-Msg from HL-Driver */ -#ifdef CONFIG_ISDN_AUDIO - u_char vpar[10]; /* Voice-parameters */ - int lastDLE; /* Flag for voice-coding: DLE seen */ -#endif - int mdmcmdl; /* Length of Modem-Commandbuffer */ - int pluscount; /* Counter for +++ sequence */ - u_long lastplus; /* Timestamp of last + */ - int carrierwait; /* Seconds of carrier waiting */ - char mdmcmd[255]; /* Modem-Commandbuffer */ - unsigned int charge; /* Charge units of current connection */ -} atemu; - -/* Private data (similar to async_struct in <linux/serial.h>) */ -typedef struct modem_info { - int magic; - struct tty_port port; - int x_char; /* xon/xoff character */ - int mcr; /* Modem control register */ - int msr; /* Modem status register */ - int lsr; /* Line status register */ - int line; - int online; /* 1 = B-Channel is up, drop data */ - /* 2 = B-Channel is up, deliver d.*/ - int dialing; /* Dial in progress or ATA */ - int closing; - int rcvsched; /* Receive needs schedule */ - int isdn_driver; /* Index to isdn-driver */ - int isdn_channel; /* Index to isdn-channel */ - int drv_index; /* Index to dev->usage */ - int ncarrier; /* Flag: schedule NO CARRIER */ - unsigned char last_cause[8]; /* Last cause message */ - unsigned char last_num[ISDN_MSNLEN]; - /* Last phone-number */ - unsigned char last_l2; /* Last layer-2 protocol */ - unsigned char last_si; /* Last service */ - unsigned char last_lhup; /* Last hangup local? */ - unsigned char last_dir; /* Last direction (in or out) */ - struct timer_list nc_timer; /* Timer for delayed NO CARRIER */ - int send_outstanding;/* # of outstanding send-requests */ - int xmit_size; /* max. # of chars in xmit_buf */ - int xmit_count; /* # of chars in xmit_buf */ - struct sk_buff_head xmit_queue; /* transmit queue */ - atomic_t xmit_lock; /* Semaphore for isdn_tty_write */ -#ifdef CONFIG_ISDN_AUDIO - int vonline; /* Voice-channel status */ - /* Bit 0 = recording */ - /* Bit 1 = playback */ - /* Bit 2 = playback, DLE-ETX seen */ - struct sk_buff_head dtmf_queue; /* queue for dtmf results */ - void *adpcms; /* state for adpcm decompression */ - void *adpcmr; /* state for adpcm compression */ - void *dtmf_state; /* state for dtmf decoder */ - void *silence_state; /* state for silence detection */ -#endif -#ifdef CONFIG_ISDN_TTY_FAX - struct T30_s *fax; /* T30 Fax Group 3 data/interface */ - int faxonline; /* Fax-channel status */ -#endif - atemu emu; /* AT-emulator data */ - spinlock_t readlock; -} modem_info; - -#define ISDN_MODEM_WINSIZE 8 - -/* Description of one ISDN-tty */ -typedef struct _isdn_modem { - int refcount; /* Number of opens */ - struct tty_driver *tty_modem; /* tty-device */ - struct tty_struct *modem_table[ISDN_MAX_CHANNELS]; /* ?? copied from Orig */ - struct ktermios *modem_termios[ISDN_MAX_CHANNELS]; - struct ktermios *modem_termios_locked[ISDN_MAX_CHANNELS]; - modem_info info[ISDN_MAX_CHANNELS]; /* Private data */ -} isdn_modem_t; - -/*======================= End of ISDN-tty stuff ============================*/ - -/*======================== Start of V.110 stuff ============================*/ -#define V110_BUFSIZE 1024 - -typedef struct { - int nbytes; /* 1 Matrixbyte -> nbytes in stream */ - int nbits; /* Number of used bits in streambyte */ - unsigned char key; /* Bitmask in stream eg. 11 (nbits=2) */ - int decodelen; /* Amount of data in decodebuf */ - int SyncInit; /* Number of sync frames to send */ - unsigned char *OnlineFrame; /* Precalculated V110 idle frame */ - unsigned char *OfflineFrame; /* Precalculated V110 sync Frame */ - int framelen; /* Length of frames */ - int skbuser; /* Number of unacked userdata skbs */ - int skbidle; /* Number of unacked idle/sync skbs */ - int introducer; /* Local vars for decoder */ - int dbit; - unsigned char b; - int skbres; /* space to reserve in outgoing skb */ - int maxsize; /* maxbufsize of lowlevel driver */ - unsigned char *encodebuf; /* temporary buffer for encoding */ - unsigned char decodebuf[V110_BUFSIZE]; /* incomplete V110 matrices */ -} isdn_v110_stream; - -/*========================= End of V.110 stuff =============================*/ - -/*======================= Start of general stuff ===========================*/ - -typedef struct { - char *next; - char *private; -} infostruct; - -#define DRV_FLAG_RUNNING 1 -#define DRV_FLAG_REJBUS 2 -#define DRV_FLAG_LOADED 4 - -/* Description of hardware-level-driver */ -typedef struct _isdn_driver { - ulong online; /* Channel-Online flags */ - ulong flags; /* Misc driver Flags */ - int locks; /* Number of locks for this driver */ - int channels; /* Number of channels */ - wait_queue_head_t st_waitq; /* Wait-Queue for status-read's */ - int maxbufsize; /* Maximum Buffersize supported */ - unsigned long pktcount; /* Until now: unused */ - int stavail; /* Chars avail on Status-device */ - isdn_if *interface; /* Interface to driver */ - int *rcverr; /* Error-counters for B-Ch.-receive */ - int *rcvcount; /* Byte-counters for B-Ch.-receive */ -#ifdef CONFIG_ISDN_AUDIO - unsigned long DLEflag; /* Flags: Insert DLE at next read */ -#endif - struct sk_buff_head *rpqueue; /* Pointers to start of Rcv-Queue */ - wait_queue_head_t *rcv_waitq; /* Wait-Queues for B-Channel-Reads */ - wait_queue_head_t *snd_waitq; /* Wait-Queue for B-Channel-Send's */ - char msn2eaz[10][ISDN_MSNLEN]; /* Mapping-Table MSN->EAZ */ -} isdn_driver_t; - -/* Main driver-data */ -typedef struct isdn_devt { - struct module *owner; - spinlock_t lock; - unsigned short flags; /* Bitmapped Flags: */ - int drivers; /* Current number of drivers */ - int channels; /* Current number of channels */ - int net_verbose; /* Verbose-Flag */ - int modempoll; /* Flag: tty-read active */ - spinlock_t timerlock; - int tflags; /* Timer-Flags: */ - /* see ISDN_TIMER_..defines */ - int global_flags; - infostruct *infochain; /* List of open info-devs. */ - wait_queue_head_t info_waitq; /* Wait-Queue for isdninfo */ - struct timer_list timer; /* Misc.-function Timer */ - int chanmap[ISDN_MAX_CHANNELS]; /* Map minor->device-channel */ - int drvmap[ISDN_MAX_CHANNELS]; /* Map minor->driver-index */ - int usage[ISDN_MAX_CHANNELS]; /* Used by tty/ip/voice */ - char num[ISDN_MAX_CHANNELS][ISDN_MSNLEN]; - /* Remote number of active ch.*/ - int m_idx[ISDN_MAX_CHANNELS]; /* Index for mdm.... */ - isdn_driver_t *drv[ISDN_MAX_DRIVERS]; /* Array of drivers */ - isdn_net_dev *netdev; /* Linked list of net-if's */ - char drvid[ISDN_MAX_DRIVERS][20];/* Driver-ID */ - struct task_struct *profd; /* For iprofd */ - isdn_modem_t mdm; /* tty-driver-data */ - isdn_net_dev *rx_netdev[ISDN_MAX_CHANNELS]; /* rx netdev-pointers */ - isdn_net_dev *st_netdev[ISDN_MAX_CHANNELS]; /* stat netdev-pointers */ - ulong ibytes[ISDN_MAX_CHANNELS]; /* Statistics incoming bytes */ - ulong obytes[ISDN_MAX_CHANNELS]; /* Statistics outgoing bytes */ - int v110emu[ISDN_MAX_CHANNELS]; /* V.110 emulator-mode 0=none */ - atomic_t v110use[ISDN_MAX_CHANNELS]; /* Usage-Semaphore for stream */ - isdn_v110_stream *v110[ISDN_MAX_CHANNELS]; /* V.110 private data */ - struct mutex mtx; /* serialize list access*/ - unsigned long global_features; -} isdn_dev; - -extern isdn_dev *dev; - - -#endif /* __ISDN_H__ */ diff --git a/include/linux/isdn/hdlc.h b/include/linux/isdn/hdlc.h deleted file mode 100644 index fe2c1279c139..000000000000 --- a/include/linux/isdn/hdlc.h +++ /dev/null @@ -1,69 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* - * hdlc.h -- General purpose ISDN HDLC decoder. - * - * Implementation of a HDLC decoder/encoder in software. - * Necessary because some ISDN devices don't have HDLC - * controllers. - * - * Copyright (C) - * 2009 Karsten Keil <keil@b1-systems.de> - * 2002 Wolfgang Mües <wolfgang@iksw-muees.de> - * 2001 Frode Isaksen <fisaksen@bewan.com> - * 2001 Kai Germaschewski <kai.germaschewski@gmx.de> - */ - -#ifndef __ISDNHDLC_H__ -#define __ISDNHDLC_H__ - -struct isdnhdlc_vars { - int bit_shift; - int hdlc_bits1; - int data_bits; - int ffbit_shift; /* encoding only */ - int state; - int dstpos; - - u16 crc; - - u8 cbin; - u8 shift_reg; - u8 ffvalue; - - /* set if transferring data */ - u32 data_received:1; - /* set if D channel (send idle instead of flags) */ - u32 dchannel:1; - /* set if 56K adaptation */ - u32 do_adapt56:1; - /* set if in closing phase (need to send CRC + flag) */ - u32 do_closing:1; - /* set if data is bitreverse */ - u32 do_bitreverse:1; -}; - -/* Feature Flags */ -#define HDLC_56KBIT 0x01 -#define HDLC_DCHANNEL 0x02 -#define HDLC_BITREVERSE 0x04 - -/* - The return value from isdnhdlc_decode is - the frame length, 0 if no complete frame was decoded, - or a negative error number -*/ -#define HDLC_FRAMING_ERROR 1 -#define HDLC_CRC_ERROR 2 -#define HDLC_LENGTH_ERROR 3 - -extern void isdnhdlc_rcv_init(struct isdnhdlc_vars *hdlc, u32 features); - -extern int isdnhdlc_decode(struct isdnhdlc_vars *hdlc, const u8 *src, - int slen, int *count, u8 *dst, int dsize); - -extern void isdnhdlc_out_init(struct isdnhdlc_vars *hdlc, u32 features); - -extern int isdnhdlc_encode(struct isdnhdlc_vars *hdlc, const u8 *src, - u16 slen, int *count, u8 *dst, int dsize); - -#endif /* __ISDNHDLC_H__ */ diff --git a/include/linux/isdn_divertif.h b/include/linux/isdn_divertif.h deleted file mode 100644 index 19ab361f9f07..000000000000 --- a/include/linux/isdn_divertif.h +++ /dev/null @@ -1,35 +0,0 @@ -/* $Id: isdn_divertif.h,v 1.4.6.1 2001/09/23 22:25:05 kai Exp $ - * - * Header for the diversion supplementary interface for i4l. - * - * Author Werner Cornelius (werner@titro.de) - * Copyright by Werner Cornelius (werner@titro.de) - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - * - */ -#ifndef _LINUX_ISDN_DIVERTIF_H -#define _LINUX_ISDN_DIVERTIF_H - -#include <linux/isdnif.h> -#include <linux/types.h> -#include <uapi/linux/isdn_divertif.h> - -/***************************************************************/ -/* structure exchanging data between isdn hl and divert module */ -/***************************************************************/ -typedef struct - { ulong if_magic; /* magic info and version */ - int cmd; /* command */ - int (*stat_callback)(isdn_ctrl *); /* supplied by divert module when calling */ - int (*ll_cmd)(isdn_ctrl *); /* supplied by hl on return */ - char * (*drv_to_name)(int); /* map a driver id to name, supplied by hl */ - int (*name_to_drv)(char *); /* map a driver id to name, supplied by hl */ - } isdn_divert_if; - -/*********************/ -/* function register */ -/*********************/ -extern int DIVERT_REG_NAME(isdn_divert_if *); -#endif /* _LINUX_ISDN_DIVERTIF_H */ diff --git a/include/linux/isdn_ppp.h b/include/linux/isdn_ppp.h deleted file mode 100644 index a0070c6dfaf8..000000000000 --- a/include/linux/isdn_ppp.h +++ /dev/null @@ -1,194 +0,0 @@ -/* Linux ISDN subsystem, sync PPP, interface to ipppd - * - * Copyright 1994-1999 by Fritz Elfert (fritz@isdn4linux.de) - * Copyright 1995,96 Thinking Objects Software GmbH Wuerzburg - * Copyright 1995,96 by Michael Hipp (Michael.Hipp@student.uni-tuebingen.de) - * Copyright 2000-2002 by Kai Germaschewski (kai@germaschewski.name) - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - * - */ -#ifndef _LINUX_ISDN_PPP_H -#define _LINUX_ISDN_PPP_H - - - - -#ifdef CONFIG_IPPP_FILTER -#include <linux/filter.h> -#endif -#include <uapi/linux/isdn_ppp.h> - -#define DECOMP_ERR_NOMEM (-10) - -#define MP_END_FRAG 0x40 -#define MP_BEGIN_FRAG 0x80 - -#define MP_MAX_QUEUE_LEN 16 - -/* - * We need a way for the decompressor to influence the generation of CCP - * Reset-Requests in a variety of ways. The decompressor is already returning - * a lot of information (generated skb length, error conditions) so we use - * another parameter. This parameter is a pointer to a structure which is - * to be marked valid by the decompressor and only in this case is ever used. - * Furthermore, the only case where this data is used is when the decom- - * pressor returns DECOMP_ERROR. - * - * We use this same struct for the reset entry of the compressor to commu- - * nicate to its caller how to deal with sending of a Reset Ack. In this - * case, expra is not used, but other options still apply (suppressing - * sending with rsend, appending arbitrary data, etc). - */ - -#define IPPP_RESET_MAXDATABYTES 32 - -struct isdn_ppp_resetparams { - unsigned char valid:1; /* rw Is this structure filled at all ? */ - unsigned char rsend:1; /* rw Should we send one at all ? */ - unsigned char idval:1; /* rw Is the id field valid ? */ - unsigned char dtval:1; /* rw Is the data field valid ? */ - unsigned char expra:1; /* rw Is an Ack expected for this Req ? */ - unsigned char id; /* wo Send CCP ResetReq with this id */ - unsigned short maxdlen; /* ro Max bytes to be stored in data field */ - unsigned short dlen; /* rw Bytes stored in data field */ - unsigned char *data; /* wo Data for ResetReq info field */ -}; - -/* - * this is an 'old friend' from ppp-comp.h under a new name - * check the original include for more information - */ -struct isdn_ppp_compressor { - struct isdn_ppp_compressor *next, *prev; - struct module *owner; - int num; /* CCP compression protocol number */ - - void *(*alloc) (struct isdn_ppp_comp_data *); - void (*free) (void *state); - int (*init) (void *state, struct isdn_ppp_comp_data *, - int unit,int debug); - - /* The reset entry needs to get more exact information about the - ResetReq or ResetAck it was called with. The parameters are - obvious. If reset is called without a Req or Ack frame which - could be handed into it, code MUST be set to 0. Using rsparm, - the reset entry can control if and how a ResetAck is returned. */ - - void (*reset) (void *state, unsigned char code, unsigned char id, - unsigned char *data, unsigned len, - struct isdn_ppp_resetparams *rsparm); - - int (*compress) (void *state, struct sk_buff *in, - struct sk_buff *skb_out, int proto); - - int (*decompress) (void *state,struct sk_buff *in, - struct sk_buff *skb_out, - struct isdn_ppp_resetparams *rsparm); - - void (*incomp) (void *state, struct sk_buff *in,int proto); - void (*stat) (void *state, struct compstat *stats); -}; - -extern int isdn_ppp_register_compressor(struct isdn_ppp_compressor *); -extern int isdn_ppp_unregister_compressor(struct isdn_ppp_compressor *); -extern int isdn_ppp_dial_slave(char *); -extern int isdn_ppp_hangup_slave(char *); - -typedef struct { - unsigned long seqerrs; - unsigned long frame_drops; - unsigned long overflows; - unsigned long max_queue_len; -} isdn_mppp_stats; - -typedef struct { - int mp_mrru; /* unused */ - struct sk_buff * frags; /* fragments sl list -- use skb->next */ - long frames; /* number of frames in the frame list */ - unsigned int seq; /* last processed packet seq #: any packets - * with smaller seq # will be dropped - * unconditionally */ - spinlock_t lock; - int ref_ct; - /* statistics */ - isdn_mppp_stats stats; -} ippp_bundle; - -#define NUM_RCV_BUFFS 64 - -struct ippp_buf_queue { - struct ippp_buf_queue *next; - struct ippp_buf_queue *last; - char *buf; /* NULL here indicates end of queue */ - int len; -}; - -/* The data structure for one CCP reset transaction */ -enum ippp_ccp_reset_states { - CCPResetIdle, - CCPResetSentReq, - CCPResetRcvdReq, - CCPResetSentAck, - CCPResetRcvdAck -}; - -struct ippp_ccp_reset_state { - enum ippp_ccp_reset_states state; /* State of this transaction */ - struct ippp_struct *is; /* Backlink to device stuff */ - unsigned char id; /* Backlink id index */ - unsigned char ta:1; /* The timer is active (flag) */ - unsigned char expra:1; /* We expect a ResetAck at all */ - int dlen; /* Databytes stored in data */ - struct timer_list timer; /* For timeouts/retries */ - /* This is a hack but seems sufficient for the moment. We do not want - to have this be yet another allocation for some bytes, it is more - memory management overhead than the whole mess is worth. */ - unsigned char data[IPPP_RESET_MAXDATABYTES]; -}; - -/* The data structure keeping track of the currently outstanding CCP Reset - transactions. */ -struct ippp_ccp_reset { - struct ippp_ccp_reset_state *rs[256]; /* One per possible id */ - unsigned char lastid; /* Last id allocated by the engine */ -}; - -struct ippp_struct { - struct ippp_struct *next_link; - int state; - spinlock_t buflock; - struct ippp_buf_queue rq[NUM_RCV_BUFFS]; /* packet queue for isdn_ppp_read() */ - struct ippp_buf_queue *first; /* pointer to (current) first packet */ - struct ippp_buf_queue *last; /* pointer to (current) last used packet in queue */ - wait_queue_head_t wq; - struct task_struct *tk; - unsigned int mpppcfg; - unsigned int pppcfg; - unsigned int mru; - unsigned int mpmru; - unsigned int mpmtu; - unsigned int maxcid; - struct isdn_net_local_s *lp; - int unit; - int minor; - unsigned int last_link_seqno; - long mp_seqno; -#ifdef CONFIG_ISDN_PPP_VJ - unsigned char *cbuf; - struct slcompress *slcomp; -#endif -#ifdef CONFIG_IPPP_FILTER - struct bpf_prog *pass_filter; /* filter for packets to pass */ - struct bpf_prog *active_filter; /* filter for pkts to reset idle */ -#endif - unsigned long debug; - struct isdn_ppp_compressor *compressor,*decompressor; - struct isdn_ppp_compressor *link_compressor,*link_decompressor; - void *decomp_stat,*comp_stat,*link_decomp_stat,*link_comp_stat; - struct ippp_ccp_reset *reset; /* Allocated on demand, may never be needed */ - unsigned long compflags; -}; - -#endif /* _LINUX_ISDN_PPP_H */ diff --git a/include/linux/isdnif.h b/include/linux/isdnif.h deleted file mode 100644 index 8d80fdc68647..000000000000 --- a/include/linux/isdnif.h +++ /dev/null @@ -1,505 +0,0 @@ -/* $Id: isdnif.h,v 1.43.2.2 2004/01/12 23:08:35 keil Exp $ - * - * Linux ISDN subsystem - * Definition of the interface between the subsystem and its low-level drivers. - * - * Copyright 1994,95,96 by Fritz Elfert (fritz@isdn4linux.de) - * Copyright 1995,96 Thinking Objects Software GmbH Wuerzburg - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - * - */ -#ifndef __ISDNIF_H__ -#define __ISDNIF_H__ - - -#include <linux/skbuff.h> -#include <uapi/linux/isdnif.h> - -/***************************************************************************/ -/* Extensions made by Werner Cornelius (werner@ikt.de) */ -/* */ -/* The proceed command holds a incoming call in a state to leave processes */ -/* enough time to check whether ist should be accepted. */ -/* The PROT_IO Command extends the interface to make protocol dependent */ -/* features available (call diversion, call waiting...). */ -/* */ -/* The PROT_IO Command is executed with the desired driver id and the arg */ -/* parameter coded as follows: */ -/* The lower 8 bits of arg contain the desired protocol from ISDN_PTYPE */ -/* definitions. The upper 24 bits represent the protocol specific cmd/stat.*/ -/* Any additional data is protocol and command specific. */ -/* This mechanism also applies to the statcallb callback STAT_PROT. */ -/* */ -/* This suggested extension permits an easy expansion of protocol specific */ -/* handling. Extensions may be added at any time without changing the HL */ -/* driver code and not getting conflicts without certifications. */ -/* The well known CAPI 2.0 interface handles such extensions in a similar */ -/* way. Perhaps a protocol specific module may be added and separately */ -/* loaded and linked to the basic isdn module for handling. */ -/***************************************************************************/ - -/*****************/ -/* DSS1 commands */ -/*****************/ -#define DSS1_CMD_INVOKE ((0x00 << 8) | ISDN_PTYPE_EURO) /* invoke a supplementary service */ -#define DSS1_CMD_INVOKE_ABORT ((0x01 << 8) | ISDN_PTYPE_EURO) /* abort a invoke cmd */ - -/*******************************/ -/* DSS1 Status callback values */ -/*******************************/ -#define DSS1_STAT_INVOKE_RES ((0x80 << 8) | ISDN_PTYPE_EURO) /* Result for invocation */ -#define DSS1_STAT_INVOKE_ERR ((0x81 << 8) | ISDN_PTYPE_EURO) /* Error Return for invocation */ -#define DSS1_STAT_INVOKE_BRD ((0x82 << 8) | ISDN_PTYPE_EURO) /* Deliver invoke broadcast info */ - - -/*********************************************************************/ -/* structures for DSS1 commands and callback */ -/* */ -/* An action is invoked by sending a DSS1_CMD_INVOKE. The ll_id, proc*/ -/* timeout, datalen and data fields must be set before calling. */ -/* */ -/* The return value is a positive hl_id value also delivered in the */ -/* hl_id field. A value of zero signals no more left hl_id capacitys.*/ -/* A negative return value signals errors in LL. So if the return */ -/* value is <= 0 no action in LL will be taken -> request ignored */ -/* */ -/* The timeout field must be filled with a positive value specifying */ -/* the amount of time the INVOKED process waits for a reaction from */ -/* the network. */ -/* If a response (either error or result) is received during this */ -/* intervall, a reporting callback is initiated and the process will */ -/* be deleted, the hl identifier will be freed. */ -/* If no response is received during the specified intervall, a error*/ -/* callback is initiated with timeout set to -1 and a datalen set */ -/* to 0. */ -/* If timeout is set to a value <= 0 during INVOCATION the process is*/ -/* immediately deleted after sending the data. No callback occurs ! */ -/* */ -/* A currently waiting process may be aborted with INVOKE_ABORT. No */ -/* callback will occur when a process has been aborted. */ -/* */ -/* Broadcast invoke frames from the network are reported via the */ -/* STAT_INVOKE_BRD callback. The ll_id is set to 0, the other fields */ -/* are supplied by the network and not by the HL. */ -/*********************************************************************/ - -/*****************/ -/* NI1 commands */ -/*****************/ -#define NI1_CMD_INVOKE ((0x00 << 8) | ISDN_PTYPE_NI1) /* invoke a supplementary service */ -#define NI1_CMD_INVOKE_ABORT ((0x01 << 8) | ISDN_PTYPE_NI1) /* abort a invoke cmd */ - -/*******************************/ -/* NI1 Status callback values */ -/*******************************/ -#define NI1_STAT_INVOKE_RES ((0x80 << 8) | ISDN_PTYPE_NI1) /* Result for invocation */ -#define NI1_STAT_INVOKE_ERR ((0x81 << 8) | ISDN_PTYPE_NI1) /* Error Return for invocation */ -#define NI1_STAT_INVOKE_BRD ((0x82 << 8) | ISDN_PTYPE_NI1) /* Deliver invoke broadcast info */ - -typedef struct - { ulong ll_id; /* ID supplied by LL when executing */ - /* a command and returned by HL for */ - /* INVOKE_RES and INVOKE_ERR */ - int hl_id; /* ID supplied by HL when called */ - /* for executing a cmd and delivered */ - /* for results and errors */ - /* must be supplied by LL when aborting*/ - int proc; /* invoke procedure used by CMD_INVOKE */ - /* returned by callback and broadcast */ - int timeout; /* timeout for INVOKE CMD in ms */ - /* -1 in stat callback when timed out */ - /* error value when error callback */ - int datalen; /* length of cmd or stat data */ - u_char *data;/* pointer to data delivered or send */ - } isdn_cmd_stat; - -/* - * Commands from linklevel to lowlevel - * - */ -#define ISDN_CMD_IOCTL 0 /* Perform ioctl */ -#define ISDN_CMD_DIAL 1 /* Dial out */ -#define ISDN_CMD_ACCEPTD 2 /* Accept an incoming call on D-Chan. */ -#define ISDN_CMD_ACCEPTB 3 /* Request B-Channel connect. */ -#define ISDN_CMD_HANGUP 4 /* Hangup */ -#define ISDN_CMD_CLREAZ 5 /* Clear EAZ(s) of channel */ -#define ISDN_CMD_SETEAZ 6 /* Set EAZ(s) of channel */ -#define ISDN_CMD_GETEAZ 7 /* Get EAZ(s) of channel */ -#define ISDN_CMD_SETSIL 8 /* Set Service-Indicator-List of channel */ -#define ISDN_CMD_GETSIL 9 /* Get Service-Indicator-List of channel */ -#define ISDN_CMD_SETL2 10 /* Set B-Chan. Layer2-Parameter */ -#define ISDN_CMD_GETL2 11 /* Get B-Chan. Layer2-Parameter */ -#define ISDN_CMD_SETL3 12 /* Set B-Chan. Layer3-Parameter */ -#define ISDN_CMD_GETL3 13 /* Get B-Chan. Layer3-Parameter */ -// #define ISDN_CMD_LOCK 14 /* Signal usage by upper levels */ -// #define ISDN_CMD_UNLOCK 15 /* Release usage-lock */ -#define ISDN_CMD_SUSPEND 16 /* Suspend connection */ -#define ISDN_CMD_RESUME 17 /* Resume connection */ -#define ISDN_CMD_PROCEED 18 /* Proceed with call establishment */ -#define ISDN_CMD_ALERT 19 /* Alert after Proceeding */ -#define ISDN_CMD_REDIR 20 /* Redir a incoming call */ -#define ISDN_CMD_PROT_IO 21 /* Protocol specific commands */ -#define CAPI_PUT_MESSAGE 22 /* CAPI message send down or up */ -#define ISDN_CMD_FAXCMD 23 /* FAX commands to HL-driver */ -#define ISDN_CMD_AUDIO 24 /* DSP, DTMF, ... settings */ - -/* - * Status-Values delivered from lowlevel to linklevel via - * statcallb(). - * - */ -#define ISDN_STAT_STAVAIL 256 /* Raw status-data available */ -#define ISDN_STAT_ICALL 257 /* Incoming call detected */ -#define ISDN_STAT_RUN 258 /* Signal protocol-code is running */ -#define ISDN_STAT_STOP 259 /* Signal halt of protocol-code */ -#define ISDN_STAT_DCONN 260 /* Signal D-Channel connect */ -#define ISDN_STAT_BCONN 261 /* Signal B-Channel connect */ -#define ISDN_STAT_DHUP 262 /* Signal D-Channel disconnect */ -#define ISDN_STAT_BHUP 263 /* Signal B-Channel disconnect */ -#define ISDN_STAT_CINF 264 /* Charge-Info */ -#define ISDN_STAT_LOAD 265 /* Signal new lowlevel-driver is loaded */ -#define ISDN_STAT_UNLOAD 266 /* Signal unload of lowlevel-driver */ -#define ISDN_STAT_BSENT 267 /* Signal packet sent */ -#define ISDN_STAT_NODCH 268 /* Signal no D-Channel */ -#define ISDN_STAT_ADDCH 269 /* Add more Channels */ -#define ISDN_STAT_CAUSE 270 /* Cause-Message */ -#define ISDN_STAT_ICALLW 271 /* Incoming call without B-chan waiting */ -#define ISDN_STAT_REDIR 272 /* Redir result */ -#define ISDN_STAT_PROT 273 /* protocol IO specific callback */ -#define ISDN_STAT_DISPLAY 274 /* deliver a received display message */ -#define ISDN_STAT_L1ERR 275 /* Signal Layer-1 Error */ -#define ISDN_STAT_FAXIND 276 /* FAX indications from HL-driver */ -#define ISDN_STAT_AUDIO 277 /* DTMF, DSP indications */ -#define ISDN_STAT_DISCH 278 /* Disable/Enable channel usage */ - -/* - * Audio commands - */ -#define ISDN_AUDIO_SETDD 0 /* Set DTMF detection */ -#define ISDN_AUDIO_DTMF 1 /* Rx/Tx DTMF */ - -/* - * Values for errcode field - */ -#define ISDN_STAT_L1ERR_SEND 1 -#define ISDN_STAT_L1ERR_RECV 2 - -/* - * Values for feature-field of interface-struct. - */ -/* Layer 2 */ -#define ISDN_FEATURE_L2_X75I (0x0001 << ISDN_PROTO_L2_X75I) -#define ISDN_FEATURE_L2_X75UI (0x0001 << ISDN_PROTO_L2_X75UI) -#define ISDN_FEATURE_L2_X75BUI (0x0001 << ISDN_PROTO_L2_X75BUI) -#define ISDN_FEATURE_L2_HDLC (0x0001 << ISDN_PROTO_L2_HDLC) -#define ISDN_FEATURE_L2_TRANS (0x0001 << ISDN_PROTO_L2_TRANS) -#define ISDN_FEATURE_L2_X25DTE (0x0001 << ISDN_PROTO_L2_X25DTE) -#define ISDN_FEATURE_L2_X25DCE (0x0001 << ISDN_PROTO_L2_X25DCE) -#define ISDN_FEATURE_L2_V11096 (0x0001 << ISDN_PROTO_L2_V11096) -#define ISDN_FEATURE_L2_V11019 (0x0001 << ISDN_PROTO_L2_V11019) -#define ISDN_FEATURE_L2_V11038 (0x0001 << ISDN_PROTO_L2_V11038) -#define ISDN_FEATURE_L2_MODEM (0x0001 << ISDN_PROTO_L2_MODEM) -#define ISDN_FEATURE_L2_FAX (0x0001 << ISDN_PROTO_L2_FAX) -#define ISDN_FEATURE_L2_HDLC_56K (0x0001 << ISDN_PROTO_L2_HDLC_56K) - -#define ISDN_FEATURE_L2_MASK (0x0FFFF) /* Max. 16 protocols */ -#define ISDN_FEATURE_L2_SHIFT (0) - -/* Layer 3 */ -#define ISDN_FEATURE_L3_TRANS (0x10000 << ISDN_PROTO_L3_TRANS) -#define ISDN_FEATURE_L3_TRANSDSP (0x10000 << ISDN_PROTO_L3_TRANSDSP) -#define ISDN_FEATURE_L3_FCLASS2 (0x10000 << ISDN_PROTO_L3_FCLASS2) -#define ISDN_FEATURE_L3_FCLASS1 (0x10000 << ISDN_PROTO_L3_FCLASS1) - -#define ISDN_FEATURE_L3_MASK (0x0FF0000) /* Max. 8 Protocols */ -#define ISDN_FEATURE_L3_SHIFT (16) - -/* Signaling */ -#define ISDN_FEATURE_P_UNKNOWN (0x1000000 << ISDN_PTYPE_UNKNOWN) -#define ISDN_FEATURE_P_1TR6 (0x1000000 << ISDN_PTYPE_1TR6) -#define ISDN_FEATURE_P_EURO (0x1000000 << ISDN_PTYPE_EURO) -#define ISDN_FEATURE_P_NI1 (0x1000000 << ISDN_PTYPE_NI1) - -#define ISDN_FEATURE_P_MASK (0x0FF000000) /* Max. 8 Protocols */ -#define ISDN_FEATURE_P_SHIFT (24) - -typedef struct setup_parm { - unsigned char phone[32]; /* Remote Phone-Number */ - unsigned char eazmsn[32]; /* Local EAZ or MSN */ - unsigned char si1; /* Service Indicator 1 */ - unsigned char si2; /* Service Indicator 2 */ - unsigned char plan; /* Numbering plan */ - unsigned char screen; /* Screening info */ -} setup_parm; - - -#ifdef CONFIG_ISDN_TTY_FAX -/* T.30 Fax G3 */ - -#define FAXIDLEN 21 - -typedef struct T30_s { - /* session parameters */ - __u8 resolution; - __u8 rate; - __u8 width; - __u8 length; - __u8 compression; - __u8 ecm; - __u8 binary; - __u8 scantime; - __u8 id[FAXIDLEN]; - /* additional parameters */ - __u8 phase; - __u8 direction; - __u8 code; - __u8 badlin; - __u8 badmul; - __u8 bor; - __u8 fet; - __u8 pollid[FAXIDLEN]; - __u8 cq; - __u8 cr; - __u8 ctcrty; - __u8 minsp; - __u8 phcto; - __u8 rel; - __u8 nbc; - /* remote station parameters */ - __u8 r_resolution; - __u8 r_rate; - __u8 r_width; - __u8 r_length; - __u8 r_compression; - __u8 r_ecm; - __u8 r_binary; - __u8 r_scantime; - __u8 r_id[FAXIDLEN]; - __u8 r_code; -} __packed T30_s; - -#define ISDN_TTY_FAX_CONN_IN 0 -#define ISDN_TTY_FAX_CONN_OUT 1 - -#define ISDN_TTY_FAX_FCON 0 -#define ISDN_TTY_FAX_DIS 1 -#define ISDN_TTY_FAX_FTT 2 -#define ISDN_TTY_FAX_MCF 3 -#define ISDN_TTY_FAX_DCS 4 -#define ISDN_TTY_FAX_TRAIN_OK 5 -#define ISDN_TTY_FAX_EOP 6 -#define ISDN_TTY_FAX_EOM 7 -#define ISDN_TTY_FAX_MPS 8 -#define ISDN_TTY_FAX_DTC 9 -#define ISDN_TTY_FAX_RID 10 -#define ISDN_TTY_FAX_HNG 11 -#define ISDN_TTY_FAX_DT 12 -#define ISDN_TTY_FAX_FCON_I 13 -#define ISDN_TTY_FAX_DR 14 -#define ISDN_TTY_FAX_ET 15 -#define ISDN_TTY_FAX_CFR 16 -#define ISDN_TTY_FAX_PTS 17 -#define ISDN_TTY_FAX_SENT 18 - -#define ISDN_FAX_PHASE_IDLE 0 -#define ISDN_FAX_PHASE_A 1 -#define ISDN_FAX_PHASE_B 2 -#define ISDN_FAX_PHASE_C 3 -#define ISDN_FAX_PHASE_D 4 -#define ISDN_FAX_PHASE_E 5 - -#endif /* TTY_FAX */ - -#define ISDN_FAX_CLASS1_FAE 0 -#define ISDN_FAX_CLASS1_FTS 1 -#define ISDN_FAX_CLASS1_FRS 2 -#define ISDN_FAX_CLASS1_FTM 3 -#define ISDN_FAX_CLASS1_FRM 4 -#define ISDN_FAX_CLASS1_FTH 5 -#define ISDN_FAX_CLASS1_FRH 6 -#define ISDN_FAX_CLASS1_CTRL 7 - -#define ISDN_FAX_CLASS1_OK 0 -#define ISDN_FAX_CLASS1_CONNECT 1 -#define ISDN_FAX_CLASS1_NOCARR 2 -#define ISDN_FAX_CLASS1_ERROR 3 -#define ISDN_FAX_CLASS1_FCERROR 4 -#define ISDN_FAX_CLASS1_QUERY 5 - -typedef struct { - __u8 cmd; - __u8 subcmd; - __u8 para[50]; -} aux_s; - -#define AT_COMMAND 0 -#define AT_EQ_VALUE 1 -#define AT_QUERY 2 -#define AT_EQ_QUERY 3 - -/* CAPI structs */ - -/* this is compatible to the old union size */ -#define MAX_CAPI_PARA_LEN 50 - -typedef struct { - /* Header */ - __u16 Length; - __u16 ApplId; - __u8 Command; - __u8 Subcommand; - __u16 Messagenumber; - - /* Parameter */ - union { - __u32 Controller; - __u32 PLCI; - __u32 NCCI; - } adr; - __u8 para[MAX_CAPI_PARA_LEN]; -} capi_msg; - -/* - * Structure for exchanging above infos - * - */ -typedef struct { - int driver; /* Lowlevel-Driver-ID */ - int command; /* Command or Status (see above) */ - ulong arg; /* Additional Data */ - union { - ulong errcode; /* Type of error with STAT_L1ERR */ - int length; /* Amount of bytes sent with STAT_BSENT */ - u_char num[50]; /* Additional Data */ - setup_parm setup;/* For SETUP msg */ - capi_msg cmsg; /* For CAPI like messages */ - char display[85];/* display message data */ - isdn_cmd_stat isdn_io; /* ISDN IO-parameter/result */ - aux_s aux; /* for modem commands/indications */ -#ifdef CONFIG_ISDN_TTY_FAX - T30_s *fax; /* Pointer to ttys fax struct */ -#endif - ulong userdata; /* User Data */ - } parm; -} isdn_ctrl; - -#define dss1_io isdn_io -#define ni1_io isdn_io - -/* - * The interface-struct itself (initialized at load-time of lowlevel-driver) - * - * See Documentation/isdn/INTERFACE for a description, how the communication - * between the ISDN subsystem and its drivers is done. - * - */ -typedef struct { - struct module *owner; - - /* Number of channels supported by this driver - */ - int channels; - - /* - * Maximum Size of transmit/receive-buffer this driver supports. - */ - int maxbufsize; - - /* Feature-Flags for this driver. - * See defines ISDN_FEATURE_... for Values - */ - unsigned long features; - - /* - * Needed for calculating - * dev->hard_header_len = linklayer header + hl_hdrlen; - * Drivers, not supporting sk_buff's should set this to 0. - */ - unsigned short hl_hdrlen; - - /* - * Receive-Callback using sk_buff's - * Parameters: - * int Driver-ID - * int local channel-number (0 ...) - * struct sk_buff *skb received Data - */ - void (*rcvcallb_skb)(int, int, struct sk_buff *); - - /* Status-Callback - * Parameters: - * isdn_ctrl* - * driver = Driver ID. - * command = One of above ISDN_STAT_... constants. - * arg = depending on status-type. - * num = depending on status-type. - */ - int (*statcallb)(isdn_ctrl*); - - /* Send command - * Parameters: - * isdn_ctrl* - * driver = Driver ID. - * command = One of above ISDN_CMD_... constants. - * arg = depending on command. - * num = depending on command. - */ - int (*command)(isdn_ctrl*); - - /* - * Send data using sk_buff's - * Parameters: - * int driverId - * int local channel-number (0...) - * int Flag: Need ACK for this packet. - * struct sk_buff *skb Data to send - */ - int (*writebuf_skb) (int, int, int, struct sk_buff *); - - /* Send raw D-Channel-Commands - * Parameters: - * u_char pointer data - * int length of data - * int driverId - * int local channel-number (0 ...) - */ - int (*writecmd)(const u_char __user *, int, int, int); - - /* Read raw Status replies - * u_char pointer data (volatile) - * int length of buffer - * int driverId - * int local channel-number (0 ...) - */ - int (*readstat)(u_char __user *, int, int, int); - - char id[20]; -} isdn_if; - -/* - * Function which must be called by lowlevel-driver at loadtime with - * the following fields of above struct set: - * - * channels Number of channels that will be supported. - * hl_hdrlen Space to preserve in sk_buff's when sending. Drivers, not - * supporting sk_buff's should set this to 0. - * command Address of Command-Handler. - * features Bitwise coded Features of this driver. (use ISDN_FEATURE_...) - * writebuf_skb Address of Skbuff-Send-Handler. - * writecmd " " D-Channel " which accepts raw D-Ch-Commands. - * readstat " " D-Channel " which delivers raw Status-Data. - * - * The linklevel-driver fills the following fields: - * - * channels Driver-ID assigned to this driver. (Must be used on all - * subsequent callbacks. - * rcvcallb_skb Address of handler for received Skbuff's. - * statcallb " " " for status-changes. - * - */ -extern int register_isdn(isdn_if*); -#include <linux/uaccess.h> - -#endif /* __ISDNIF_H__ */ diff --git a/include/linux/iversion.h b/include/linux/iversion.h index be50ef7cedab..2917ef990d43 100644 --- a/include/linux/iversion.h +++ b/include/linux/iversion.h @@ -113,6 +113,30 @@ inode_peek_iversion_raw(const struct inode *inode) } /** + * inode_set_max_iversion_raw - update i_version new value is larger + * @inode: inode to set + * @val: new i_version to set + * + * Some self-managed filesystems (e.g Ceph) will only update the i_version + * value if the new value is larger than the one we already have. + */ +static inline void +inode_set_max_iversion_raw(struct inode *inode, u64 val) +{ + u64 cur, old; + + cur = inode_peek_iversion_raw(inode); + for (;;) { + if (cur > val) + break; + old = atomic64_cmpxchg(&inode->i_version, cur, val); + if (likely(old == cur)) + break; + cur = old; + } +} + +/** * inode_set_iversion - set i_version to a particular value * @inode: inode to set * @val: new i_version value to set diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h index 5c04181b7c6d..603fbc4e2f70 100644 --- a/include/linux/jbd2.h +++ b/include/linux/jbd2.h @@ -451,6 +451,22 @@ struct jbd2_inode { * @i_flags: Flags of inode [j_list_lock] */ unsigned long i_flags; + + /** + * @i_dirty_start: + * + * Offset in bytes where the dirty range for this inode starts. + * [j_list_lock] + */ + loff_t i_dirty_start; + + /** + * @i_dirty_end: + * + * Inclusive offset in bytes where the dirty range for this inode + * ends. [j_list_lock] + */ + loff_t i_dirty_end; }; struct jbd2_revoke_table_s; @@ -1357,7 +1373,6 @@ void jbd2_journal_set_triggers(struct buffer_head *, struct jbd2_buffer_trigger_type *type); extern int jbd2_journal_dirty_metadata (handle_t *, struct buffer_head *); extern int jbd2_journal_forget (handle_t *, struct buffer_head *); -extern void journal_sync_buffer (struct buffer_head *); extern int jbd2_journal_invalidatepage(journal_t *, struct page *, unsigned int, unsigned int); extern int jbd2_journal_try_to_free_buffers(journal_t *, struct page *, gfp_t); @@ -1395,8 +1410,12 @@ extern int jbd2_journal_clear_err (journal_t *); extern int jbd2_journal_bmap(journal_t *, unsigned long, unsigned long long *); extern int jbd2_journal_force_commit(journal_t *); extern int jbd2_journal_force_commit_nested(journal_t *); -extern int jbd2_journal_inode_add_write(handle_t *handle, struct jbd2_inode *inode); -extern int jbd2_journal_inode_add_wait(handle_t *handle, struct jbd2_inode *inode); +extern int jbd2_journal_inode_ranged_write(handle_t *handle, + struct jbd2_inode *inode, loff_t start_byte, + loff_t length); +extern int jbd2_journal_inode_ranged_wait(handle_t *handle, + struct jbd2_inode *inode, loff_t start_byte, + loff_t length); extern int jbd2_journal_begin_ordered_truncate(journal_t *journal, struct jbd2_inode *inode, loff_t new_size); extern void jbd2_journal_init_jbd_inode(struct jbd2_inode *jinode, struct inode *inode); diff --git a/include/linux/jhash.h b/include/linux/jhash.h index 8037850f3104..ba2f6a9776b6 100644 --- a/include/linux/jhash.h +++ b/include/linux/jhash.h @@ -17,7 +17,7 @@ * if SELF_TEST is defined. You can use this free for any purpose. It's in * the public domain. It has no warranty. * - * Copyright (C) 2009-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu) + * Copyright (C) 2009-2010 Jozsef Kadlecsik (kadlec@netfilter.org) * * I've modified Bob's hash to be useful in the Linux kernel, and * any bugs present are my fault. diff --git a/include/linux/jump_label.h b/include/linux/jump_label.h index 3e113a1fa0f1..3526c0aee954 100644 --- a/include/linux/jump_label.h +++ b/include/linux/jump_label.h @@ -215,6 +215,9 @@ extern void arch_jump_label_transform(struct jump_entry *entry, enum jump_label_type type); extern void arch_jump_label_transform_static(struct jump_entry *entry, enum jump_label_type type); +extern bool arch_jump_label_transform_queue(struct jump_entry *entry, + enum jump_label_type type); +extern void arch_jump_label_transform_apply(void); extern int jump_label_text_reserved(void *start, void *end); extern void static_key_slow_inc(struct static_key *key); extern void static_key_slow_dec(struct static_key *key); diff --git a/include/linux/jump_label_ratelimit.h b/include/linux/jump_label_ratelimit.h index 42710d5949ba..8c3ee291b2d8 100644 --- a/include/linux/jump_label_ratelimit.h +++ b/include/linux/jump_label_ratelimit.h @@ -60,8 +60,6 @@ extern void jump_label_update_timeout(struct work_struct *work); 0), \ } -#define static_branch_deferred_inc(x) static_branch_inc(&(x)->key) - #else /* !CONFIG_JUMP_LABEL */ struct static_key_deferred { struct static_key key; @@ -95,4 +93,7 @@ jump_label_rate_limit(struct static_key_deferred *key, STATIC_KEY_CHECK_USE(key); } #endif /* CONFIG_JUMP_LABEL */ + +#define static_branch_deferred_inc(x) static_branch_inc(&(x)->key) + #endif /* _LINUX_JUMP_LABEL_RATELIMIT_H */ diff --git a/include/linux/kasan-checks.h b/include/linux/kasan-checks.h index a61dc075e2ce..ac6aba632f2d 100644 --- a/include/linux/kasan-checks.h +++ b/include/linux/kasan-checks.h @@ -2,14 +2,43 @@ #ifndef _LINUX_KASAN_CHECKS_H #define _LINUX_KASAN_CHECKS_H -#if defined(__SANITIZE_ADDRESS__) || defined(__KASAN_INTERNAL) -void kasan_check_read(const volatile void *p, unsigned int size); -void kasan_check_write(const volatile void *p, unsigned int size); +#include <linux/types.h> + +/* + * __kasan_check_*: Always available when KASAN is enabled. This may be used + * even in compilation units that selectively disable KASAN, but must use KASAN + * to validate access to an address. Never use these in header files! + */ +#ifdef CONFIG_KASAN +bool __kasan_check_read(const volatile void *p, unsigned int size); +bool __kasan_check_write(const volatile void *p, unsigned int size); +#else +static inline bool __kasan_check_read(const volatile void *p, unsigned int size) +{ + return true; +} +static inline bool __kasan_check_write(const volatile void *p, unsigned int size) +{ + return true; +} +#endif + +/* + * kasan_check_*: Only available when the particular compilation unit has KASAN + * instrumentation enabled. May be used in header files. + */ +#ifdef __SANITIZE_ADDRESS__ +#define kasan_check_read __kasan_check_read +#define kasan_check_write __kasan_check_write #else -static inline void kasan_check_read(const volatile void *p, unsigned int size) -{ } -static inline void kasan_check_write(const volatile void *p, unsigned int size) -{ } +static inline bool kasan_check_read(const volatile void *p, unsigned int size) +{ + return true; +} +static inline bool kasan_check_write(const volatile void *p, unsigned int size) +{ + return true; +} #endif #endif diff --git a/include/linux/kasan.h b/include/linux/kasan.h index b40ea104dd36..cc8a03cc9674 100644 --- a/include/linux/kasan.h +++ b/include/linux/kasan.h @@ -76,8 +76,11 @@ void kasan_free_shadow(const struct vm_struct *vm); int kasan_add_zero_shadow(void *start, unsigned long size); void kasan_remove_zero_shadow(void *start, unsigned long size); -size_t ksize(const void *); -static inline void kasan_unpoison_slab(const void *ptr) { ksize(ptr); } +size_t __ksize(const void *); +static inline void kasan_unpoison_slab(const void *ptr) +{ + kasan_unpoison_shadow(ptr, __ksize(ptr)); +} size_t kasan_metadata_size(struct kmem_cache *cache); bool kasan_save_enable_multi_shot(void); diff --git a/include/linux/kernel.h b/include/linux/kernel.h index 0c9bc231107f..d83d403dac2e 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h @@ -88,6 +88,8 @@ */ #define FIELD_SIZEOF(t, f) (sizeof(((t*)0)->f)) +#define typeof_member(T, m) typeof(((T*)0)->m) + #define DIV_ROUND_UP __KERNEL_DIV_ROUND_UP #define DIV_ROUND_DOWN_ULL(ll, d) \ @@ -215,7 +217,9 @@ extern void __cant_sleep(const char *file, int line, int preempt_offset); * might_sleep - annotation for functions that can sleep * * this macro will print a stack trace if it is executed in an atomic - * context (spinlock, irq-handler, ...). + * context (spinlock, irq-handler, ...). Additional sections where blocking is + * not allowed can be annotated with non_block_start() and non_block_end() + * pairs. * * This is a useful debugging help to be able to catch problems early and not * be bitten later when the calling function happens to sleep when it is not @@ -231,6 +235,23 @@ extern void __cant_sleep(const char *file, int line, int preempt_offset); # define cant_sleep() \ do { __cant_sleep(__FILE__, __LINE__, 0); } while (0) # define sched_annotate_sleep() (current->task_state_change = 0) +/** + * non_block_start - annotate the start of section where sleeping is prohibited + * + * This is on behalf of the oom reaper, specifically when it is calling the mmu + * notifiers. The problem is that if the notifier were to block on, for example, + * mutex_lock() and if the process which holds that mutex were to perform a + * sleeping memory allocation, the oom reaper is now blocked on completion of + * that memory allocation. Other blocking calls like wait_event() pose similar + * issues. + */ +# define non_block_start() (current->non_block_count++) +/** + * non_block_end - annotate the end of section where sleeping is prohibited + * + * Closes a section opened by non_block_start(). + */ +# define non_block_end() WARN_ON(current->non_block_count-- == 0) #else static inline void ___might_sleep(const char *file, int line, int preempt_offset) { } @@ -239,6 +260,8 @@ extern void __cant_sleep(const char *file, int line, int preempt_offset); # define might_sleep() do { might_resched(); } while (0) # define cant_sleep() do { } while (0) # define sched_annotate_sleep() do { } while (0) +# define non_block_start() do { } while (0) +# define non_block_end() do { } while (0) #endif #define might_sleep_if(cond) do { if (cond) might_sleep(); } while (0) diff --git a/include/linux/kexec.h b/include/linux/kexec.h index 58b27c7bdc2b..1776eb2e43a4 100644 --- a/include/linux/kexec.h +++ b/include/linux/kexec.h @@ -183,6 +183,8 @@ int kexec_purgatory_get_set_symbol(struct kimage *image, const char *name, bool get_value); void *kexec_purgatory_get_symbol_addr(struct kimage *image, const char *name); +int __weak arch_kexec_kernel_image_probe(struct kimage *image, void *buf, + unsigned long buf_len); void * __weak arch_kexec_kernel_image_load(struct kimage *image); int __weak arch_kexec_apply_relocations_add(struct purgatory_info *pi, Elf_Shdr *section, @@ -216,6 +218,29 @@ extern int crash_prepare_elf64_headers(struct crash_mem *mem, int kernel_map, void **addr, unsigned long *sz); #endif /* CONFIG_KEXEC_FILE */ +#ifdef CONFIG_KEXEC_ELF +struct kexec_elf_info { + /* + * Where the ELF binary contents are kept. + * Memory managed by the user of the struct. + */ + const char *buffer; + + const struct elfhdr *ehdr; + const struct elf_phdr *proghdrs; +}; + +int kexec_build_elf_info(const char *buf, size_t len, struct elfhdr *ehdr, + struct kexec_elf_info *elf_info); + +int kexec_elf_load(struct kimage *image, struct elfhdr *ehdr, + struct kexec_elf_info *elf_info, + struct kexec_buf *kbuf, + unsigned long *lowest_load_addr); + +void kexec_free_elf_info(struct kexec_elf_info *elf_info); +int kexec_elf_probe(const char *buf, unsigned long len); +#endif struct kimage { kimage_entry_t head; kimage_entry_t *entry; diff --git a/include/linux/key-type.h b/include/linux/key-type.h index 331cab70db09..4ded94bcf274 100644 --- a/include/linux/key-type.h +++ b/include/linux/key-type.h @@ -70,6 +70,9 @@ struct key_type { */ size_t def_datalen; + unsigned int flags; +#define KEY_TYPE_NET_DOMAIN 0x00000001 /* Keys of this type have a net namespace domain */ + /* vet a description */ int (*vet_description)(const char *description); diff --git a/include/linux/key.h b/include/linux/key.h index 1c8b88b455ef..6cf8e71cf8b7 100644 --- a/include/linux/key.h +++ b/include/linux/key.h @@ -31,6 +31,7 @@ typedef int32_t key_serial_t; typedef uint32_t key_perm_t; struct key; +struct net; #ifdef CONFIG_KEYS @@ -77,13 +78,34 @@ struct cred; struct key_type; struct key_owner; +struct key_tag; struct keyring_list; struct keyring_name; +struct key_tag { + struct rcu_head rcu; + refcount_t usage; + bool removed; /* T when subject removed */ +}; + struct keyring_index_key { + /* [!] If this structure is altered, the union in struct key must change too! */ + unsigned long hash; /* Hash value */ + union { + struct { +#ifdef __LITTLE_ENDIAN /* Put desc_len at the LSB of x */ + u16 desc_len; + char desc[sizeof(long) - 2]; /* First few chars of description */ +#else + char desc[sizeof(long) - 2]; /* First few chars of description */ + u16 desc_len; +#endif + }; + unsigned long x; + }; struct key_type *type; + struct key_tag *domain_tag; /* Domain of operation */ const char *description; - size_t desc_len; }; union key_payload { @@ -197,7 +219,10 @@ struct key { union { struct keyring_index_key index_key; struct { + unsigned long hash; + unsigned long len_desc; struct key_type *type; /* type of key */ + struct key_tag *domain_tag; /* Domain of operation */ char *description; }; }; @@ -248,6 +273,8 @@ extern struct key *key_alloc(struct key_type *type, extern void key_revoke(struct key *key); extern void key_invalidate(struct key *key); extern void key_put(struct key *key); +extern bool key_put_tag(struct key_tag *tag); +extern void key_remove_domain(struct key_tag *domain_tag); static inline struct key *__key_get(struct key *key) { @@ -265,26 +292,68 @@ static inline void key_ref_put(key_ref_t key_ref) key_put(key_ref_to_ptr(key_ref)); } -extern struct key *request_key(struct key_type *type, - const char *description, - const char *callout_info); +extern struct key *request_key_tag(struct key_type *type, + const char *description, + struct key_tag *domain_tag, + const char *callout_info); + +extern struct key *request_key_rcu(struct key_type *type, + const char *description, + struct key_tag *domain_tag); extern struct key *request_key_with_auxdata(struct key_type *type, const char *description, + struct key_tag *domain_tag, const void *callout_info, size_t callout_len, void *aux); -extern struct key *request_key_async(struct key_type *type, - const char *description, - const void *callout_info, - size_t callout_len); +/** + * request_key - Request a key and wait for construction + * @type: Type of key. + * @description: The searchable description of the key. + * @callout_info: The data to pass to the instantiation upcall (or NULL). + * + * As for request_key_tag(), but with the default global domain tag. + */ +static inline struct key *request_key(struct key_type *type, + const char *description, + const char *callout_info) +{ + return request_key_tag(type, description, NULL, callout_info); +} -extern struct key *request_key_async_with_auxdata(struct key_type *type, - const char *description, - const void *callout_info, - size_t callout_len, - void *aux); +#ifdef CONFIG_NET +/** + * request_key_net - Request a key for a net namespace and wait for construction + * @type: Type of key. + * @description: The searchable description of the key. + * @net: The network namespace that is the key's domain of operation. + * @callout_info: The data to pass to the instantiation upcall (or NULL). + * + * As for request_key() except that it does not add the returned key to a + * keyring if found, new keys are always allocated in the user's quota, the + * callout_info must be a NUL-terminated string and no auxiliary data can be + * passed. Only keys that operate the specified network namespace are used. + * + * Furthermore, it then works as wait_for_key_construction() to wait for the + * completion of keys undergoing construction with a non-interruptible wait. + */ +#define request_key_net(type, description, net, callout_info) \ + request_key_tag(type, description, net->key_domain, callout_info); + +/** + * request_key_net_rcu - Request a key for a net namespace under RCU conditions + * @type: Type of key. + * @description: The searchable description of the key. + * @net: The network namespace that is the key's domain of operation. + * + * As for request_key_rcu() except that only keys that operate the specified + * network namespace are used. + */ +#define request_key_net_rcu(type, description, net) \ + request_key_rcu(type, description, net->key_domain); +#endif /* CONFIG_NET */ extern int wait_for_key_construction(struct key *key, bool intr); @@ -305,6 +374,11 @@ extern int key_update(key_ref_t key, extern int key_link(struct key *keyring, struct key *key); +extern int key_move(struct key *key, + struct key *from_keyring, + struct key *to_keyring, + unsigned int flags); + extern int key_unlink(struct key *keyring, struct key *key); @@ -324,7 +398,8 @@ extern int keyring_clear(struct key *keyring); extern key_ref_t keyring_search(key_ref_t keyring, struct key_type *type, - const char *description); + const char *description, + bool recurse); extern int keyring_add_key(struct key *keyring, struct key *key); @@ -343,6 +418,7 @@ extern void key_set_timeout(struct key *, unsigned); extern key_ref_t lookup_user_key(key_serial_t id, unsigned long flags, key_perm_t perm); +extern void key_free_user_ns(struct user_namespace *); /* * The permissions required on a key that we're looking up. @@ -397,8 +473,8 @@ extern struct ctl_table key_sysctls[]; * the userspace interface */ extern int install_thread_keyring_to_cred(struct cred *cred); -extern void key_fsuid_changed(struct task_struct *tsk); -extern void key_fsgid_changed(struct task_struct *tsk); +extern void key_fsuid_changed(struct cred *new_cred); +extern void key_fsgid_changed(struct cred *new_cred); extern void key_init(void); #else /* CONFIG_KEYS */ @@ -413,9 +489,11 @@ extern void key_init(void); #define make_key_ref(k, p) NULL #define key_ref_to_ptr(k) NULL #define is_key_possessed(k) 0 -#define key_fsuid_changed(t) do { } while(0) -#define key_fsgid_changed(t) do { } while(0) +#define key_fsuid_changed(c) do { } while(0) +#define key_fsgid_changed(c) do { } while(0) #define key_init() do { } while(0) +#define key_free_user_ns(ns) do { } while(0) +#define key_remove_domain(d) do { } while(0) #endif /* CONFIG_KEYS */ #endif /* __KERNEL__ */ diff --git a/include/linux/kgdb.h b/include/linux/kgdb.h index fbf144aaa749..b072aeb1fd78 100644 --- a/include/linux/kgdb.h +++ b/include/linux/kgdb.h @@ -326,8 +326,10 @@ extern atomic_t kgdb_active; (raw_smp_processor_id() == atomic_read(&kgdb_active)) extern bool dbg_is_early; extern void __init dbg_late_init(void); +extern void kgdb_panic(const char *msg); #else /* ! CONFIG_KGDB */ #define in_dbg_master() (0) #define dbg_late_init() +static inline void kgdb_panic(const char *msg) {} #endif /* ! CONFIG_KGDB */ #endif /* _KGDB_H_ */ diff --git a/include/linux/khugepaged.h b/include/linux/khugepaged.h index 082d1d2a5216..bc45ea1efbf7 100644 --- a/include/linux/khugepaged.h +++ b/include/linux/khugepaged.h @@ -15,6 +15,14 @@ extern int __khugepaged_enter(struct mm_struct *mm); extern void __khugepaged_exit(struct mm_struct *mm); extern int khugepaged_enter_vma_merge(struct vm_area_struct *vma, unsigned long vm_flags); +#ifdef CONFIG_SHMEM +extern void collapse_pte_mapped_thp(struct mm_struct *mm, unsigned long addr); +#else +static inline void collapse_pte_mapped_thp(struct mm_struct *mm, + unsigned long addr) +{ +} +#endif #define khugepaged_enabled() \ (transparent_hugepage_flags & \ @@ -73,6 +81,10 @@ static inline int khugepaged_enter_vma_merge(struct vm_area_struct *vma, { return 0; } +static inline void collapse_pte_mapped_thp(struct mm_struct *mm, + unsigned long addr) +{ +} #endif /* CONFIG_TRANSPARENT_HUGEPAGE */ #endif /* _LINUX_KHUGEPAGED_H */ diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h index 443d9800ca3f..04bdaf01112c 100644 --- a/include/linux/kprobes.h +++ b/include/linux/kprobes.h @@ -458,4 +458,23 @@ static inline bool is_kprobe_optinsn_slot(unsigned long addr) } #endif +/* Returns true if kprobes handled the fault */ +static nokprobe_inline bool kprobe_page_fault(struct pt_regs *regs, + unsigned int trap) +{ + if (!kprobes_built_in()) + return false; + if (user_mode(regs)) + return false; + /* + * To be potentially processing a kprobe fault and to be allowed + * to call kprobe_running(), we have to be non-preemptible. + */ + if (preemptible()) + return false; + if (!kprobe_running()) + return false; + return kprobe_fault_handler(regs, trap); +} + #endif /* _LINUX_KPROBES_H */ diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h index d1ad38a3f048..fcb46b3374c6 100644 --- a/include/linux/kvm_host.h +++ b/include/linux/kvm_host.h @@ -159,7 +159,7 @@ static inline bool is_error_page(struct page *page) extern struct kmem_cache *kvm_vcpu_cache; -extern spinlock_t kvm_lock; +extern struct mutex kvm_lock; extern struct list_head vm_list; struct kvm_io_range { @@ -318,6 +318,7 @@ struct kvm_vcpu { } spin_loop; #endif bool preempted; + bool ready; struct kvm_vcpu_arch arch; struct dentry *debugfs_dentry; }; @@ -860,17 +861,19 @@ int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu); void kvm_arch_vcpu_postcreate(struct kvm_vcpu *vcpu); void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu); -bool kvm_arch_has_vcpu_debugfs(void); -int kvm_arch_create_vcpu_debugfs(struct kvm_vcpu *vcpu); +#ifdef __KVM_HAVE_ARCH_VCPU_DEBUGFS +void kvm_arch_create_vcpu_debugfs(struct kvm_vcpu *vcpu); +#endif int kvm_arch_hardware_enable(void); void kvm_arch_hardware_disable(void); int kvm_arch_hardware_setup(void); void kvm_arch_hardware_unsetup(void); -void kvm_arch_check_processor_compat(void *rtn); +int kvm_arch_check_processor_compat(void); int kvm_arch_vcpu_runnable(struct kvm_vcpu *vcpu); bool kvm_arch_vcpu_in_kernel(struct kvm_vcpu *vcpu); int kvm_arch_vcpu_should_kick(struct kvm_vcpu *vcpu); +bool kvm_arch_dy_runnable(struct kvm_vcpu *vcpu); #ifndef __KVM_HAVE_ARCH_VM_ALLOC /* @@ -990,6 +993,7 @@ void kvm_unregister_irq_ack_notifier(struct kvm *kvm, struct kvm_irq_ack_notifier *kian); int kvm_request_irq_source_id(struct kvm *kvm); void kvm_free_irq_source_id(struct kvm *kvm, int irq_source_id); +bool kvm_arch_irqfd_allowed(struct kvm *kvm, struct kvm_irqfd *args); /* * search_memslots() and __gfn_to_memslot() are here because they are diff --git a/include/linux/lcd.h b/include/linux/lcd.h index 851eee8fff25..238fb1dfed98 100644 --- a/include/linux/lcd.h +++ b/include/linux/lcd.h @@ -41,16 +41,6 @@ struct lcd_ops { /* Get the LCD panel power status (0: full on, 1..3: controller power on, flat panel power off, 4: full off), see FB_BLANK_XXX */ int (*get_power)(struct lcd_device *); - /* - * Enable or disable power to the LCD(0: on; 4: off, see FB_BLANK_XXX) - * and this callback would be called proir to fb driver's callback. - * - * P.S. note that if early_set_power is not NULL then early fb notifier - * would be registered. - */ - int (*early_set_power)(struct lcd_device *, int power); - /* revert the effects of the early blank event. */ - int (*r_early_set_power)(struct lcd_device *, int power); /* Enable or disable power to the LCD (0: on; 4: off, see FB_BLANK_XXX) */ int (*set_power)(struct lcd_device *, int power); /* Get the current contrast setting (0-max_contrast) */ diff --git a/include/linux/led-class-flash.h b/include/linux/led-class-flash.h index f52713f0a269..1e824963af17 100644 --- a/include/linux/led-class-flash.h +++ b/include/linux/led-class-flash.h @@ -86,15 +86,20 @@ static inline struct led_classdev_flash *lcdev_to_flcdev( } /** - * led_classdev_flash_register - register a new object of led_classdev class - * with support for flash LEDs - * @parent: the flash LED to register + * led_classdev_flash_register_ext - register a new object of LED class with + * init data and with support for flash LEDs + * @parent: LED flash controller device this flash LED is driven by * @fled_cdev: the led_classdev_flash structure for this device + * @init_data: the LED class flash device initialization data * * Returns: 0 on success or negative error value on failure */ -extern int led_classdev_flash_register(struct device *parent, - struct led_classdev_flash *fled_cdev); +extern int led_classdev_flash_register_ext(struct device *parent, + struct led_classdev_flash *fled_cdev, + struct led_init_data *init_data); + +#define led_classdev_flash_register(parent, fled_cdev) \ + led_classdev_flash_register_ext(parent, fled_cdev, NULL) /** * led_classdev_flash_unregister - unregisters an object of led_classdev class diff --git a/include/linux/leds-ti-lmu-common.h b/include/linux/leds-ti-lmu-common.h new file mode 100644 index 000000000000..5eb111f38803 --- /dev/null +++ b/include/linux/leds-ti-lmu-common.h @@ -0,0 +1,47 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +// TI LMU Common Core +// Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/ + +#ifndef _TI_LMU_COMMON_H_ +#define _TI_LMU_COMMON_H_ + +#include <linux/delay.h> +#include <linux/device.h> +#include <linux/init.h> +#include <linux/leds.h> +#include <linux/module.h> +#include <linux/regmap.h> +#include <linux/slab.h> +#include <uapi/linux/uleds.h> + +#define LMU_11BIT_LSB_MASK (BIT(0) | BIT(1) | BIT(2)) +#define LMU_11BIT_MSB_SHIFT 3 + +#define MAX_BRIGHTNESS_8BIT 255 +#define MAX_BRIGHTNESS_11BIT 2047 + +struct ti_lmu_bank { + struct regmap *regmap; + + int max_brightness; + + u8 lsb_brightness_reg; + u8 msb_brightness_reg; + + u8 runtime_ramp_reg; + u32 ramp_up_usec; + u32 ramp_down_usec; +}; + +int ti_lmu_common_set_brightness(struct ti_lmu_bank *lmu_bank, int brightness); + +int ti_lmu_common_set_ramp(struct ti_lmu_bank *lmu_bank); + +int ti_lmu_common_get_ramp_params(struct device *dev, + struct fwnode_handle *child, + struct ti_lmu_bank *lmu_data); + +int ti_lmu_common_get_brt_res(struct device *dev, struct fwnode_handle *child, + struct ti_lmu_bank *lmu_data); + +#endif /* _TI_LMU_COMMON_H_ */ diff --git a/include/linux/leds.h b/include/linux/leds.h index 9b2bf574a17a..b8df71193329 100644 --- a/include/linux/leds.h +++ b/include/linux/leds.h @@ -8,6 +8,7 @@ #ifndef __LINUX_LEDS_H_INCLUDED #define __LINUX_LEDS_H_INCLUDED +#include <dt-bindings/leds/common.h> #include <linux/device.h> #include <linux/kernfs.h> #include <linux/list.h> @@ -30,6 +31,30 @@ enum led_brightness { LED_FULL = 255, }; +struct led_init_data { + /* device fwnode handle */ + struct fwnode_handle *fwnode; + /* + * default <color:function> tuple, for backward compatibility + * with in-driver hard-coded LED names used as a fallback when + * DT "label" property is absent; it should be set to NULL + * in new LED class drivers. + */ + const char *default_label; + /* + * string to be used for devicename section of LED class device + * either for label based LED name composition path or for fwnode + * based when devname_mandatory is true + */ + const char *devicename; + /* + * indicates if LED name should always comprise devicename section; + * only LEDs exposed by drivers of hot-pluggable devices should + * set it to true + */ + bool devname_mandatory; +}; + struct led_classdev { const char *name; enum led_brightness brightness; @@ -125,16 +150,46 @@ struct led_classdev { struct mutex led_access; }; -extern int of_led_classdev_register(struct device *parent, - struct device_node *np, - struct led_classdev *led_cdev); -#define led_classdev_register(parent, led_cdev) \ - of_led_classdev_register(parent, NULL, led_cdev) -extern int devm_of_led_classdev_register(struct device *parent, - struct device_node *np, - struct led_classdev *led_cdev); -#define devm_led_classdev_register(parent, led_cdev) \ - devm_of_led_classdev_register(parent, NULL, led_cdev) +/** + * led_classdev_register_ext - register a new object of LED class with + * init data + * @parent: LED controller device this LED is driven by + * @led_cdev: the led_classdev structure for this device + * @init_data: the LED class device initialization data + * + * Register a new object of LED class, with name derived from init_data. + * + * Returns: 0 on success or negative error value on failure + */ +extern int led_classdev_register_ext(struct device *parent, + struct led_classdev *led_cdev, + struct led_init_data *init_data); + +/** + * led_classdev_register - register a new object of LED class + * @parent: LED controller device this LED is driven by + * @led_cdev: the led_classdev structure for this device + * + * Register a new object of LED class, with name derived from the name property + * of passed led_cdev argument. + * + * Returns: 0 on success or negative error value on failure + */ +static inline int led_classdev_register(struct device *parent, + struct led_classdev *led_cdev) +{ + return led_classdev_register_ext(parent, led_cdev, NULL); +} + +extern int devm_led_classdev_register_ext(struct device *parent, + struct led_classdev *led_cdev, + struct led_init_data *init_data); + +static inline int devm_led_classdev_register(struct device *parent, + struct led_classdev *led_cdev) +{ + return devm_led_classdev_register_ext(parent, led_cdev, NULL); +} extern void led_classdev_unregister(struct led_classdev *led_cdev); extern void devm_led_classdev_unregister(struct device *parent, struct led_classdev *led_cdev); @@ -244,6 +299,22 @@ extern void led_sysfs_disable(struct led_classdev *led_cdev); extern void led_sysfs_enable(struct led_classdev *led_cdev); /** + * led_compose_name - compose LED class device name + * @dev: LED controller device object + * @child: child fwnode_handle describing a LED or a group of synchronized LEDs; + * it must be provided only for fwnode based LEDs + * @led_classdev_name: composed LED class device name + * + * Create LED class device name basing on the provided init_data argument. + * The name can have <devicename:color:function> or <color:function>. + * form, depending on the init_data configuration. + * + * Returns: 0 on success or negative error value on failure + */ +extern int led_compose_name(struct device *dev, struct led_init_data *init_data, + char *led_classdev_name); + +/** * led_sysfs_is_disabled - check if LED sysfs interface is disabled * @led_cdev: the LED to query * @@ -420,6 +491,15 @@ struct led_platform_data { struct led_info *leds; }; +struct led_properties { + u32 color; + bool color_present; + const char *function; + u32 func_enum; + bool func_enum_present; + const char *label; +}; + struct gpio_desc; typedef int (*gpio_blink_set_t)(struct gpio_desc *desc, int state, unsigned long *delay_on, diff --git a/include/linux/libnvdimm.h b/include/linux/libnvdimm.h index 03d5c3aece9d..b6eddf912568 100644 --- a/include/linux/libnvdimm.h +++ b/include/linux/libnvdimm.h @@ -11,6 +11,7 @@ #include <linux/types.h> #include <linux/uuid.h> #include <linux/spinlock.h> +#include <linux/bio.h> struct badrange_entry { u64 start; @@ -57,6 +58,9 @@ enum { */ ND_REGION_PERSIST_MEMCTRL = 2, + /* Platform provides asynchronous flush mechanism */ + ND_REGION_ASYNC = 3, + /* mark newly adjusted resources as requiring a label update */ DPA_RESOURCE_ADJUSTED = 1 << 0, }; @@ -113,6 +117,7 @@ struct nd_mapping_desc { int position; }; +struct nd_region; struct nd_region_desc { struct resource *res; struct nd_mapping_desc *mapping; @@ -125,6 +130,7 @@ struct nd_region_desc { int target_node; unsigned long flags; struct device_node *of_node; + int (*flush)(struct nd_region *nd_region, struct bio *bio); }; struct device; @@ -154,8 +160,11 @@ static inline struct nd_blk_region_desc *to_blk_region_desc( } -enum nvdimm_security_state { - NVDIMM_SECURITY_ERROR = -1, +/* + * Note that separate bits for locked + unlocked are defined so that + * 'flags == 0' corresponds to an error / not-supported state. + */ +enum nvdimm_security_bits { NVDIMM_SECURITY_DISABLED, NVDIMM_SECURITY_UNLOCKED, NVDIMM_SECURITY_LOCKED, @@ -176,7 +185,7 @@ enum nvdimm_passphrase_type { }; struct nvdimm_security_ops { - enum nvdimm_security_state (*state)(struct nvdimm *nvdimm, + unsigned long (*get_flags)(struct nvdimm *nvdimm, enum nvdimm_passphrase_type pass_type); int (*freeze)(struct nvdimm *nvdimm); int (*change_key)(struct nvdimm *nvdimm, @@ -252,10 +261,12 @@ unsigned long nd_blk_memremap_flags(struct nd_blk_region *ndbr); unsigned int nd_region_acquire_lane(struct nd_region *nd_region); void nd_region_release_lane(struct nd_region *nd_region, unsigned int lane); u64 nd_fletcher64(void *addr, size_t len, bool le); -void nvdimm_flush(struct nd_region *nd_region); +int nvdimm_flush(struct nd_region *nd_region, struct bio *bio); +int generic_nvdimm_flush(struct nd_region *nd_region); int nvdimm_has_flush(struct nd_region *nd_region); int nvdimm_has_cache(struct nd_region *nd_region); int nvdimm_in_overwrite(struct nvdimm *nvdimm); +bool is_nvdimm_sync(struct nd_region *nd_region); static inline int nvdimm_ctl(struct nvdimm *nvdimm, unsigned int cmd, void *buf, unsigned int buf_len, int *cmd_rc) diff --git a/include/linux/lightnvm.h b/include/linux/lightnvm.h index 4d0d5655c7b2..ee8ec2e68055 100644 --- a/include/linux/lightnvm.h +++ b/include/linux/lightnvm.h @@ -88,8 +88,7 @@ typedef int (nvm_op_bb_tbl_fn)(struct nvm_dev *, struct ppa_addr, u8 *); typedef int (nvm_op_set_bb_fn)(struct nvm_dev *, struct ppa_addr *, int, int); typedef int (nvm_get_chk_meta_fn)(struct nvm_dev *, sector_t, int, struct nvm_chk_meta *); -typedef int (nvm_submit_io_fn)(struct nvm_dev *, struct nvm_rq *); -typedef int (nvm_submit_io_sync_fn)(struct nvm_dev *, struct nvm_rq *); +typedef int (nvm_submit_io_fn)(struct nvm_dev *, struct nvm_rq *, void *); typedef void *(nvm_create_dma_pool_fn)(struct nvm_dev *, char *, int); typedef void (nvm_destroy_dma_pool_fn)(void *); typedef void *(nvm_dev_dma_alloc_fn)(struct nvm_dev *, void *, gfp_t, @@ -104,7 +103,6 @@ struct nvm_dev_ops { nvm_get_chk_meta_fn *get_chk_meta; nvm_submit_io_fn *submit_io; - nvm_submit_io_sync_fn *submit_io_sync; nvm_create_dma_pool_fn *create_dma_pool; nvm_destroy_dma_pool_fn *destroy_dma_pool; @@ -682,8 +680,8 @@ extern int nvm_get_chunk_meta(struct nvm_tgt_dev *, struct ppa_addr, int, struct nvm_chk_meta *); extern int nvm_set_chunk_meta(struct nvm_tgt_dev *, struct ppa_addr *, int, int); -extern int nvm_submit_io(struct nvm_tgt_dev *, struct nvm_rq *); -extern int nvm_submit_io_sync(struct nvm_tgt_dev *, struct nvm_rq *); +extern int nvm_submit_io(struct nvm_tgt_dev *, struct nvm_rq *, void *); +extern int nvm_submit_io_sync(struct nvm_tgt_dev *, struct nvm_rq *, void *); extern void nvm_end_io(struct nvm_rq *); #else /* CONFIG_NVM */ diff --git a/include/linux/list.h b/include/linux/list.h index e951228db4b2..85c92555e31f 100644 --- a/include/linux/list.h +++ b/include/linux/list.h @@ -106,6 +106,20 @@ static inline void __list_del(struct list_head * prev, struct list_head * next) WRITE_ONCE(prev->next, next); } +/* + * Delete a list entry and clear the 'prev' pointer. + * + * This is a special-purpose list clearing method used in the networking code + * for lists allocated as per-cpu, where we don't want to incur the extra + * WRITE_ONCE() overhead of a regular list_del_init(). The code that uses this + * needs to check the node 'prev' pointer instead of calling list_empty(). + */ +static inline void __list_del_clearprev(struct list_head *entry) +{ + __list_del(entry->prev, entry->next); + entry->prev = NULL; +} + /** * list_del - deletes entry from list. * @entry: the element to delete from the list. diff --git a/include/linux/livepatch.h b/include/linux/livepatch.h index eeba421cc671..273400814020 100644 --- a/include/linux/livepatch.h +++ b/include/linux/livepatch.h @@ -35,7 +35,6 @@ * @stack_node: list node for klp_ops func_stack list * @old_size: size of the old function * @new_size: size of the new function - * @kobj_added: @kobj has been added and needs freeing * @nop: temporary patch to use the original code again; dyn. allocated * @patched: the func has been added to the klp_ops list * @transition: the func is currently being applied or reverted @@ -113,7 +112,6 @@ struct klp_callbacks { * @node: list node for klp_patch obj_list * @mod: kernel module associated with the patched object * (NULL for vmlinux) - * @kobj_added: @kobj has been added and needs freeing * @dynamic: temporary object for nop functions; dynamically allocated * @patched: the object's funcs have been added to the klp_ops list */ @@ -140,7 +138,6 @@ struct klp_object { * @list: list node for global list of actively used patches * @kobj: kobject for sysfs resources * @obj_list: dynamic list of the object entries - * @kobj_added: @kobj has been added and needs freeing * @enabled: the patch is enabled (but operation may be incomplete) * @forced: was involved in a forced transition * @free_work: patch cleanup from workqueue-context diff --git a/include/linux/lockd/lockd.h b/include/linux/lockd/lockd.h index c9b422dde542..d294dde9e546 100644 --- a/include/linux/lockd/lockd.h +++ b/include/linux/lockd/lockd.h @@ -282,6 +282,7 @@ void nlmsvc_traverse_blocks(struct nlm_host *, struct nlm_file *, nlm_host_match_fn_t match); void nlmsvc_grant_reply(struct nlm_cookie *, __be32); void nlmsvc_release_call(struct nlm_rqst *); +void nlmsvc_locks_init_private(struct file_lock *, struct nlm_host *, pid_t); /* * File handling for the server personality @@ -289,6 +290,7 @@ void nlmsvc_release_call(struct nlm_rqst *); __be32 nlm_lookup_file(struct svc_rqst *, struct nlm_file **, struct nfs_fh *); void nlm_release_file(struct nlm_file *); +void nlmsvc_release_lockowner(struct nlm_lock *); void nlmsvc_mark_resources(struct net *); void nlmsvc_free_host_resources(struct nlm_host *); void nlmsvc_invalidate_all(void); diff --git a/include/linux/lockdep.h b/include/linux/lockdep.h index 6e2377e6c1d6..b8a835fd611b 100644 --- a/include/linux/lockdep.h +++ b/include/linux/lockdep.h @@ -5,7 +5,7 @@ * Copyright (C) 2006,2007 Red Hat, Inc., Ingo Molnar <mingo@redhat.com> * Copyright (C) 2007 Red Hat, Inc., Peter Zijlstra * - * see Documentation/locking/lockdep-design.txt for more details. + * see Documentation/locking/lockdep-design.rst for more details. */ #ifndef __LINUX_LOCKDEP_H #define __LINUX_LOCKDEP_H @@ -66,10 +66,7 @@ struct lock_class_key { extern struct lock_class_key __lockdep_no_validate__; -struct lock_trace { - unsigned int nr_entries; - unsigned int offset; -}; +struct lock_trace; #define LOCKSTAT_POINTS 4 @@ -97,7 +94,7 @@ struct lock_class { */ struct list_head locks_after, locks_before; - struct lockdep_subclass_key *key; + const struct lockdep_subclass_key *key; unsigned int subclass; unsigned int dep_gen_id; @@ -105,7 +102,7 @@ struct lock_class { * IRQ/softirq usage tracking bits: */ unsigned long usage_mask; - struct lock_trace usage_traces[XXX_LOCK_USAGE_STATES]; + const struct lock_trace *usage_traces[XXX_LOCK_USAGE_STATES]; /* * Generation counter, when doing certain classes of graph walking, @@ -193,7 +190,7 @@ struct lock_list { struct list_head entry; struct lock_class *class; struct lock_class *links_to; - struct lock_trace trace; + const struct lock_trace *trace; int distance; /* @@ -203,11 +200,17 @@ struct lock_list { struct lock_list *parent; }; -/* - * We record lock dependency chains, so that we can cache them: +/** + * struct lock_chain - lock dependency chain record + * + * @irq_context: the same as irq_context in held_lock below + * @depth: the number of held locks in this chain + * @base: the index in chain_hlocks for this chain + * @entry: the collided lock chains in lock_chain hash list + * @chain_key: the hash key of this lock_chain */ struct lock_chain { - /* see BUILD_BUG_ON()s in lookup_chain_cache() */ + /* see BUILD_BUG_ON()s in add_chain_cache() */ unsigned int irq_context : 2, depth : 6, base : 24; @@ -217,12 +220,8 @@ struct lock_chain { }; #define MAX_LOCKDEP_KEYS_BITS 13 -/* - * Subtract one because we offset hlock->class_idx by 1 in order - * to make 0 mean no class. This avoids overflowing the class_idx - * bitfield and hitting the BUG in hlock_class(). - */ -#define MAX_LOCKDEP_KEYS ((1UL << MAX_LOCKDEP_KEYS_BITS) - 1) +#define MAX_LOCKDEP_KEYS (1UL << MAX_LOCKDEP_KEYS_BITS) +#define INITIAL_CHAIN_KEY -1 struct held_lock { /* @@ -247,6 +246,11 @@ struct held_lock { u64 waittime_stamp; u64 holdtime_stamp; #endif + /* + * class_idx is zero-indexed; it points to the element in + * lock_classes this held lock instance belongs to. class_idx is in + * the range from 0 to (MAX_LOCKDEP_KEYS-1) inclusive. + */ unsigned int class_idx:MAX_LOCKDEP_KEYS_BITS; /* * The lock-stack is unified in that the lock chains of interrupt @@ -281,6 +285,8 @@ extern void lockdep_free_key_range(void *start, unsigned long size); extern asmlinkage void lockdep_sys_exit(void); extern void lockdep_set_selftest_task(struct task_struct *task); +extern void lockdep_init_task(struct task_struct *task); + extern void lockdep_off(void); extern void lockdep_on(void); @@ -385,7 +391,7 @@ extern void lock_unpin_lock(struct lockdep_map *lock, struct pin_cookie); WARN_ON(debug_locks && !lockdep_is_held(l)); \ } while (0) -#define lockdep_assert_held_exclusive(l) do { \ +#define lockdep_assert_held_write(l) do { \ WARN_ON(debug_locks && !lockdep_is_held_type(l, 0)); \ } while (0) @@ -405,6 +411,10 @@ extern void lock_unpin_lock(struct lockdep_map *lock, struct pin_cookie); #else /* !CONFIG_LOCKDEP */ +static inline void lockdep_init_task(struct task_struct *task) +{ +} + static inline void lockdep_off(void) { } @@ -466,7 +476,7 @@ struct lockdep_map { }; #define lockdep_is_held_type(l, r) (1) #define lockdep_assert_held(l) do { (void)(l); } while (0) -#define lockdep_assert_held_exclusive(l) do { (void)(l); } while (0) +#define lockdep_assert_held_write(l) do { (void)(l); } while (0) #define lockdep_assert_held_read(l) do { (void)(l); } while (0) #define lockdep_assert_held_once(l) do { (void)(l); } while (0) @@ -497,7 +507,6 @@ enum xhlock_context_t { { .name = (_name), .key = (void *)(_key), } static inline void lockdep_invariant_state(bool force) {} -static inline void lockdep_init_task(struct task_struct *task) {} static inline void lockdep_free_task(struct task_struct *task) {} #ifdef CONFIG_LOCK_STAT @@ -632,11 +641,18 @@ do { \ "IRQs not disabled as expected\n"); \ } while (0) +#define lockdep_assert_in_irq() do { \ + WARN_ONCE(debug_locks && !current->lockdep_recursion && \ + !current->hardirq_context, \ + "Not in hardirq as expected\n"); \ + } while (0) + #else # define might_lock(lock) do { } while (0) # define might_lock_read(lock) do { } while (0) # define lockdep_assert_irqs_enabled() do { } while (0) # define lockdep_assert_irqs_disabled() do { } while (0) +# define lockdep_assert_in_irq() do { } while (0) #endif #ifdef CONFIG_LOCKDEP diff --git a/include/linux/log2.h b/include/linux/log2.h index 1aec01365ed4..83a4a3ca3e8a 100644 --- a/include/linux/log2.h +++ b/include/linux/log2.h @@ -220,4 +220,38 @@ int __order_base_2(unsigned long n) ilog2((n) - 1) + 1) : \ __order_base_2(n) \ ) + +static inline __attribute__((const)) +int __bits_per(unsigned long n) +{ + if (n < 2) + return 1; + if (is_power_of_2(n)) + return order_base_2(n) + 1; + return order_base_2(n); +} + +/** + * bits_per - calculate the number of bits required for the argument + * @n: parameter + * + * This is constant-capable and can be used for compile time + * initializations, e.g bitfields. + * + * The first few values calculated by this routine: + * bf(0) = 1 + * bf(1) = 1 + * bf(2) = 2 + * bf(3) = 2 + * bf(4) = 3 + * ... and so on. + */ +#define bits_per(n) \ +( \ + __builtin_constant_p(n) ? ( \ + ((n) == 0 || (n) == 1) \ + ? 1 : ilog2(n) + 1 \ + ) : \ + __bits_per(n) \ +) #endif /* _LINUX_LOG2_H */ diff --git a/include/linux/logic_pio.h b/include/linux/logic_pio.h index cbd9d8495690..88e1e6304a71 100644 --- a/include/linux/logic_pio.h +++ b/include/linux/logic_pio.h @@ -117,6 +117,7 @@ struct logic_pio_hwaddr *find_io_range_by_fwnode(struct fwnode_handle *fwnode); unsigned long logic_pio_trans_hwaddr(struct fwnode_handle *fwnode, resource_size_t hw_addr, resource_size_t size); int logic_pio_register_range(struct logic_pio_hwaddr *newrange); +void logic_pio_unregister_range(struct logic_pio_hwaddr *range); resource_size_t logic_pio_to_hwaddr(unsigned long pio); unsigned long logic_pio_trans_cpuaddr(resource_size_t hw_addr); diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h index 2f4ba9062fb8..a3763247547c 100644 --- a/include/linux/lsm_hooks.h +++ b/include/linux/lsm_hooks.h @@ -77,7 +77,7 @@ * state. This is called immediately after commit_creds(). * * Security hooks for mount using fs_context. - * [See also Documentation/filesystems/mounting.txt] + * [See also Documentation/filesystems/mount_api.txt] * * @fs_context_dup: * Allocate and attach a security structure to sc->security. This pointer @@ -339,6 +339,9 @@ * Check for permission to change root directory. * @path contains the path structure. * Return 0 if permission is granted. + * @path_notify: + * Check permissions before setting a watch on events as defined by @mask, + * on an object at @path, whose type is defined by @obj_type. * @inode_readlink: * Check the permission to read the symbolic link. * @dentry contains the dentry structure for the file link. @@ -1540,7 +1543,9 @@ union security_list_options { int (*path_chown)(const struct path *path, kuid_t uid, kgid_t gid); int (*path_chroot)(const struct path *path); #endif - + /* Needed for inode based security check */ + int (*path_notify)(const struct path *path, u64 mask, + unsigned int obj_type); int (*inode_alloc_security)(struct inode *inode); void (*inode_free_security)(struct inode *inode); int (*inode_init_security)(struct inode *inode, struct inode *dir, @@ -1866,6 +1871,8 @@ struct security_hook_heads { struct hlist_head path_chown; struct hlist_head path_chroot; #endif + /* Needed for inode based modules as well */ + struct hlist_head path_notify; struct hlist_head inode_alloc_security; struct hlist_head inode_free_security; struct hlist_head inode_init_security; diff --git a/include/linux/lz4.h b/include/linux/lz4.h index 394e3d9213b8..b16e15b9587a 100644 --- a/include/linux/lz4.h +++ b/include/linux/lz4.h @@ -278,7 +278,7 @@ int LZ4_decompress_fast(const char *source, char *dest, int originalSize); * @compressedSize: is the precise full size of the compressed block * @maxDecompressedSize: is the size of 'dest' buffer * - * Decompresses data fom 'source' into 'dest'. + * Decompresses data from 'source' into 'dest'. * If the source stream is detected malformed, the function will * stop decoding and return a negative result. * This function is protected against buffer overflow exploits, @@ -522,7 +522,7 @@ int LZ4_setStreamDecode(LZ4_streamDecode_t *LZ4_streamDecode, const char *dictionary, int dictSize); /** - * LZ4_decompress_fast_continue() - Decompress blocks in streaming mode + * LZ4_decompress_safe_continue() - Decompress blocks in streaming mode * @LZ4_streamDecode: the 'LZ4_streamDecode_t' structure * @source: source address of the compressed data * @dest: output buffer address of the uncompressed data @@ -530,7 +530,7 @@ int LZ4_setStreamDecode(LZ4_streamDecode_t *LZ4_streamDecode, * @compressedSize: is the precise full size of the compressed block * @maxDecompressedSize: is the size of 'dest' buffer * - * These decoding function allows decompression of multiple blocks + * This decoding function allows decompression of multiple blocks * in "streaming" mode. * Previously decoded blocks *must* remain available at the memory position * where they were decoded (up to 64 KB) @@ -569,7 +569,7 @@ int LZ4_decompress_safe_continue(LZ4_streamDecode_t *LZ4_streamDecode, * which must be already allocated with 'originalSize' bytes * @originalSize: is the original and therefore uncompressed size * - * These decoding function allows decompression of multiple blocks + * This decoding function allows decompression of multiple blocks * in "streaming" mode. * Previously decoded blocks *must* remain available at the memory position * where they were decoded (up to 64 KB) @@ -610,10 +610,10 @@ int LZ4_decompress_fast_continue(LZ4_streamDecode_t *LZ4_streamDecode, * @dictStart: pointer to the start of the dictionary in memory * @dictSize: size of dictionary * - * These decoding function works the same as + * This decoding function works the same as * a combination of LZ4_setStreamDecode() followed by * LZ4_decompress_safe_continue() - * It is stand-alone, and don'tn eed a LZ4_streamDecode_t structure. + * It is stand-alone, and doesn't need an LZ4_streamDecode_t structure. * * Return: number of bytes decompressed into destination buffer * (necessarily <= maxDecompressedSize) @@ -633,10 +633,10 @@ int LZ4_decompress_safe_usingDict(const char *source, char *dest, * @dictStart: pointer to the start of the dictionary in memory * @dictSize: size of dictionary * - * These decoding function works the same as + * This decoding function works the same as * a combination of LZ4_setStreamDecode() followed by - * LZ4_decompress_safe_continue() - * It is stand-alone, and don'tn eed a LZ4_streamDecode_t structure. + * LZ4_decompress_fast_continue() + * It is stand-alone, and doesn't need an LZ4_streamDecode_t structure. * * Return: number of bytes decompressed into destination buffer * (necessarily <= maxDecompressedSize) diff --git a/include/linux/mailbox/mtk-cmdq-mailbox.h b/include/linux/mailbox/mtk-cmdq-mailbox.h index ccb73422c2fa..e6f54ef6698b 100644 --- a/include/linux/mailbox/mtk-cmdq-mailbox.h +++ b/include/linux/mailbox/mtk-cmdq-mailbox.h @@ -20,6 +20,9 @@ #define CMDQ_WFE_WAIT BIT(15) #define CMDQ_WFE_WAIT_VALUE 0x1 +/** cmdq event maximum */ +#define CMDQ_MAX_EVENT 0x3ff + /* * CMDQ_CODE_MASK: * set write mask diff --git a/include/linux/mdio.h b/include/linux/mdio.h index e8242ad88c81..a7604248777b 100644 --- a/include/linux/mdio.h +++ b/include/linux/mdio.h @@ -68,6 +68,17 @@ struct mdio_driver { #define to_mdio_driver(d) \ container_of(to_mdio_common_driver(d), struct mdio_driver, mdiodrv) +/* device driver data */ +static inline void mdiodev_set_drvdata(struct mdio_device *mdio, void *data) +{ + dev_set_drvdata(&mdio->dev, data); +} + +static inline void *mdiodev_get_drvdata(struct mdio_device *mdio) +{ + return dev_get_drvdata(&mdio->dev); +} + void mdio_device_free(struct mdio_device *mdiodev); struct mdio_device *mdio_device_create(struct mii_bus *bus, int addr); int mdio_device_register(struct mdio_device *mdiodev); diff --git a/include/linux/mem_encrypt.h b/include/linux/mem_encrypt.h index 470bd53a89df..5c4a18a91f89 100644 --- a/include/linux/mem_encrypt.h +++ b/include/linux/mem_encrypt.h @@ -18,23 +18,10 @@ #else /* !CONFIG_ARCH_HAS_MEM_ENCRYPT */ -#define sme_me_mask 0ULL - -static inline bool sme_active(void) { return false; } -static inline bool sev_active(void) { return false; } +static inline bool mem_encrypt_active(void) { return false; } #endif /* CONFIG_ARCH_HAS_MEM_ENCRYPT */ -static inline bool mem_encrypt_active(void) -{ - return sme_me_mask; -} - -static inline u64 sme_get_me_mask(void) -{ - return sme_me_mask; -} - #ifdef CONFIG_AMD_MEM_ENCRYPT /* * The __sme_set() and __sme_clr() macros are useful for adding or removing diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h index 1dcb763bb610..9b60863429cc 100644 --- a/include/linux/memcontrol.h +++ b/include/linux/memcontrol.h @@ -128,9 +128,8 @@ struct mem_cgroup_per_node { struct mem_cgroup_reclaim_iter iter[DEF_PRIORITY + 1]; -#ifdef CONFIG_MEMCG_KMEM struct memcg_shrinker_map __rcu *shrinker_map; -#endif + struct rb_node tree_node; /* RB tree node */ unsigned long usage_in_excess;/* Set to the value by which */ /* the soft limit is exceeded*/ @@ -184,6 +183,23 @@ struct memcg_padding { #endif /* + * Remember four most recent foreign writebacks with dirty pages in this + * cgroup. Inode sharing is expected to be uncommon and, even if we miss + * one in a given round, we're likely to catch it later if it keeps + * foreign-dirtying, so a fairly low count should be enough. + * + * See mem_cgroup_track_foreign_dirty_slowpath() for details. + */ +#define MEMCG_CGWB_FRN_CNT 4 + +struct memcg_cgwb_frn { + u64 bdi_id; /* bdi->id of the foreign inode */ + int memcg_id; /* memcg->css.id of foreign inode */ + u64 at; /* jiffies_64 at the time of dirtying */ + struct wb_completion done; /* tracks in-flight foreign writebacks */ +}; + +/* * The memory controller data structure. The memory controller controls both * page cache and RSS per cgroup. We would eventually like to provide * statistics based on the statistics developed by Rik Van Riel for clock-pro, @@ -233,8 +249,9 @@ struct mem_cgroup { /* OOM-Killer disable */ int oom_kill_disable; - /* memory.events */ + /* memory.events and memory.events.local */ struct cgroup_file events_file; + struct cgroup_file events_local_file; /* handle for "memory.swap.events" */ struct cgroup_file swap_events_file; @@ -281,6 +298,7 @@ struct mem_cgroup { /* memory.events */ atomic_long_t memory_events[MEMCG_NR_MEMORY_EVENTS]; + atomic_long_t memory_events_local[MEMCG_NR_MEMORY_EVENTS]; unsigned long socket_pressure; @@ -305,12 +323,17 @@ struct mem_cgroup { #ifdef CONFIG_CGROUP_WRITEBACK struct list_head cgwb_list; struct wb_domain cgwb_domain; + struct memcg_cgwb_frn cgwb_frn[MEMCG_CGWB_FRN_CNT]; #endif /* List of events which userspace want to receive */ struct list_head event_list; spinlock_t event_list_lock; +#ifdef CONFIG_TRANSPARENT_HUGEPAGE + struct deferred_split deferred_split_queue; +#endif + struct mem_cgroup_per_node *nodeinfo[0]; /* WARNING: nodeinfo must be the last member here */ }; @@ -392,7 +415,6 @@ out: struct lruvec *mem_cgroup_page_lruvec(struct page *, struct pglist_data *); -bool task_in_mem_cgroup(struct task_struct *task, struct mem_cgroup *memcg); struct mem_cgroup *mem_cgroup_from_task(struct task_struct *p); struct mem_cgroup *get_mem_cgroup_from_mm(struct mm_struct *mm); @@ -667,6 +689,7 @@ static inline unsigned long lruvec_page_state_local(struct lruvec *lruvec, void __mod_lruvec_state(struct lruvec *lruvec, enum node_stat_item idx, int val); +void __mod_lruvec_slab_state(void *p, enum node_stat_item idx, int val); static inline void mod_lruvec_state(struct lruvec *lruvec, enum node_stat_item idx, int val) @@ -747,6 +770,9 @@ static inline void count_memcg_event_mm(struct mm_struct *mm, static inline void memcg_memory_event(struct mem_cgroup *memcg, enum memcg_memory_event event) { + atomic_long_inc(&memcg->memory_events_local[event]); + cgroup_file_notify(&memcg->events_local_file); + do { atomic_long_inc(&memcg->memory_events[event]); cgroup_file_notify(&memcg->events_file); @@ -870,12 +896,6 @@ static inline bool mm_match_cgroup(struct mm_struct *mm, return true; } -static inline bool task_in_mem_cgroup(struct task_struct *task, - const struct mem_cgroup *memcg) -{ - return true; -} - static inline struct mem_cgroup *get_mem_cgroup_from_mm(struct mm_struct *mm) { return NULL; @@ -1074,6 +1094,14 @@ static inline void mod_lruvec_page_state(struct page *page, mod_node_page_state(page_pgdat(page), idx, val); } +static inline void __mod_lruvec_slab_state(void *p, enum node_stat_item idx, + int val) +{ + struct page *page = virt_to_head_page(p); + + __mod_node_page_state(page_pgdat(page), idx, val); +} + static inline unsigned long mem_cgroup_soft_limit_reclaim(pg_data_t *pgdat, int order, gfp_t gfp_mask, @@ -1161,6 +1189,16 @@ static inline void __dec_lruvec_page_state(struct page *page, __mod_lruvec_page_state(page, idx, -1); } +static inline void __inc_lruvec_slab_state(void *p, enum node_stat_item idx) +{ + __mod_lruvec_slab_state(p, idx, 1); +} + +static inline void __dec_lruvec_slab_state(void *p, enum node_stat_item idx) +{ + __mod_lruvec_slab_state(p, idx, -1); +} + /* idx can be of type enum memcg_stat_item or node_stat_item */ static inline void inc_memcg_state(struct mem_cgroup *memcg, int idx) @@ -1220,6 +1258,18 @@ void mem_cgroup_wb_stats(struct bdi_writeback *wb, unsigned long *pfilepages, unsigned long *pheadroom, unsigned long *pdirty, unsigned long *pwriteback); +void mem_cgroup_track_foreign_dirty_slowpath(struct page *page, + struct bdi_writeback *wb); + +static inline void mem_cgroup_track_foreign_dirty(struct page *page, + struct bdi_writeback *wb) +{ + if (unlikely(&page->mem_cgroup->css != wb->memcg_css)) + mem_cgroup_track_foreign_dirty_slowpath(page, wb); +} + +void mem_cgroup_flush_foreign(struct bdi_writeback *wb); + #else /* CONFIG_CGROUP_WRITEBACK */ static inline struct wb_domain *mem_cgroup_wb_domain(struct bdi_writeback *wb) @@ -1235,6 +1285,15 @@ static inline void mem_cgroup_wb_stats(struct bdi_writeback *wb, { } +static inline void mem_cgroup_track_foreign_dirty(struct page *page, + struct bdi_writeback *wb) +{ +} + +static inline void mem_cgroup_flush_foreign(struct bdi_writeback *wb) +{ +} + #endif /* CONFIG_CGROUP_WRITEBACK */ struct sock; @@ -1255,6 +1314,11 @@ static inline bool mem_cgroup_under_socket_pressure(struct mem_cgroup *memcg) } while ((memcg = parent_mem_cgroup(memcg))); return false; } + +extern int memcg_expand_shrinker_maps(int new_id); + +extern void memcg_set_shrinker_bit(struct mem_cgroup *memcg, + int nid, int shrinker_id); #else #define mem_cgroup_sockets_enabled 0 static inline void mem_cgroup_sk_alloc(struct sock *sk) { }; @@ -1263,6 +1327,11 @@ static inline bool mem_cgroup_under_socket_pressure(struct mem_cgroup *memcg) { return false; } + +static inline void memcg_set_shrinker_bit(struct mem_cgroup *memcg, + int nid, int shrinker_id) +{ +} #endif struct kmem_cache *memcg_kmem_get_cache(struct kmem_cache *cachep); @@ -1273,6 +1342,8 @@ int __memcg_kmem_charge(struct page *page, gfp_t gfp, int order); void __memcg_kmem_uncharge(struct page *page, int order); int __memcg_kmem_charge_memcg(struct page *page, gfp_t gfp, int order, struct mem_cgroup *memcg); +void __memcg_kmem_uncharge_memcg(struct mem_cgroup *memcg, + unsigned int nr_pages); extern struct static_key_false memcg_kmem_enabled_key; extern struct workqueue_struct *memcg_kmem_cache_wq; @@ -1314,6 +1385,14 @@ static inline int memcg_kmem_charge_memcg(struct page *page, gfp_t gfp, return __memcg_kmem_charge_memcg(page, gfp, order, memcg); return 0; } + +static inline void memcg_kmem_uncharge_memcg(struct page *page, int order, + struct mem_cgroup *memcg) +{ + if (memcg_kmem_enabled()) + __memcg_kmem_uncharge_memcg(memcg, 1 << order); +} + /* * helper for accessing a memcg's index. It will be used as an index in the * child cache array in kmem_cache, and also to derive its name. This function @@ -1324,10 +1403,6 @@ static inline int memcg_cache_id(struct mem_cgroup *memcg) return memcg ? memcg->kmemcg_id : -1; } -extern int memcg_expand_shrinker_maps(int new_id); - -extern void memcg_set_shrinker_bit(struct mem_cgroup *memcg, - int nid, int shrinker_id); #else static inline int memcg_kmem_charge(struct page *page, gfp_t gfp, int order) @@ -1369,8 +1444,6 @@ static inline void memcg_put_cache_ids(void) { } -static inline void memcg_set_shrinker_bit(struct mem_cgroup *memcg, - int nid, int shrinker_id) { } #endif /* CONFIG_MEMCG_KMEM */ #endif /* _LINUX_MEMCONTROL_H */ diff --git a/include/linux/memory.h b/include/linux/memory.h index e1dc1bb2b787..0ebb105eb261 100644 --- a/include/linux/memory.h +++ b/include/linux/memory.h @@ -25,7 +25,6 @@ struct memory_block { unsigned long start_section_nr; - unsigned long end_section_nr; unsigned long state; /* serialized by the dev->lock */ int section_count; /* serialized by mem_sysfs_mutex */ int online_type; /* for passing data to online routine */ @@ -80,9 +79,9 @@ struct mem_section; #define IPC_CALLBACK_PRI 10 #ifndef CONFIG_MEMORY_HOTPLUG_SPARSE -static inline int memory_dev_init(void) +static inline void memory_dev_init(void) { - return 0; + return; } static inline int register_memory_notifier(struct notifier_block *nb) { @@ -111,16 +110,15 @@ extern int register_memory_notifier(struct notifier_block *nb); extern void unregister_memory_notifier(struct notifier_block *nb); extern int register_memory_isolate_notifier(struct notifier_block *nb); extern void unregister_memory_isolate_notifier(struct notifier_block *nb); -int hotplug_memory_register(int nid, struct mem_section *section); -#ifdef CONFIG_MEMORY_HOTREMOVE -extern void unregister_memory_section(struct mem_section *); -#endif -extern int memory_dev_init(void); +int create_memory_block_devices(unsigned long start, unsigned long size); +void remove_memory_block_devices(unsigned long start, unsigned long size); +extern void memory_dev_init(void); extern int memory_notify(unsigned long val, void *v); extern int memory_isolate_notify(unsigned long val, void *v); -extern struct memory_block *find_memory_block_hinted(struct mem_section *, - struct memory_block *); extern struct memory_block *find_memory_block(struct mem_section *); +typedef int (*walk_memory_blocks_func_t)(struct memory_block *, void *); +extern int walk_memory_blocks(unsigned long start, unsigned long size, + void *arg, walk_memory_blocks_func_t func); #define CONFIG_MEM_BLOCK_SIZE (PAGES_PER_SECTION<<PAGE_SHIFT) #endif /* CONFIG_MEMORY_HOTPLUG_SPARSE */ diff --git a/include/linux/memory_hotplug.h b/include/linux/memory_hotplug.h index ae892eef8b82..f46ea71b4ffd 100644 --- a/include/linux/memory_hotplug.h +++ b/include/linux/memory_hotplug.h @@ -123,20 +123,10 @@ static inline bool movable_node_is_enabled(void) return movable_node_enabled; } -#ifdef CONFIG_MEMORY_HOTREMOVE extern void arch_remove_memory(int nid, u64 start, u64 size, struct vmem_altmap *altmap); extern void __remove_pages(struct zone *zone, unsigned long start_pfn, unsigned long nr_pages, struct vmem_altmap *altmap); -#endif /* CONFIG_MEMORY_HOTREMOVE */ - -/* - * Do we want sysfs memblock files created. This will allow userspace to online - * and offline memory explicitly. Lack of this bit means that the caller has to - * call move_pfn_range_to_zone to finish the initialization. - */ - -#define MHP_MEMBLOCK_API (1<<0) /* reasonably generic interface to expand the physical pages */ extern int __add_pages(int nid, unsigned long start_pfn, unsigned long nr_pages, @@ -324,7 +314,7 @@ static inline void pgdat_resize_init(struct pglist_data *pgdat) {} extern bool is_mem_section_removable(unsigned long pfn, unsigned long nr_pages); extern void try_offline_node(int nid); extern int offline_pages(unsigned long start_pfn, unsigned long nr_pages); -extern void remove_memory(int nid, u64 start, u64 size); +extern int remove_memory(int nid, u64 start, u64 size); extern void __remove_memory(int nid, u64 start, u64 size); #else @@ -341,22 +331,25 @@ static inline int offline_pages(unsigned long start_pfn, unsigned long nr_pages) return -EINVAL; } -static inline void remove_memory(int nid, u64 start, u64 size) {} +static inline int remove_memory(int nid, u64 start, u64 size) +{ + return -EBUSY; +} + static inline void __remove_memory(int nid, u64 start, u64 size) {} #endif /* CONFIG_MEMORY_HOTREMOVE */ extern void __ref free_area_init_core_hotplug(int nid); -extern int walk_memory_range(unsigned long start_pfn, unsigned long end_pfn, - void *arg, int (*func)(struct memory_block *, void *)); extern int __add_memory(int nid, u64 start, u64 size); extern int add_memory(int nid, u64 start, u64 size); extern int add_memory_resource(int nid, struct resource *resource); extern void move_pfn_range_to_zone(struct zone *zone, unsigned long start_pfn, unsigned long nr_pages, struct vmem_altmap *altmap); extern bool is_memblock_offlined(struct memory_block *mem); -extern int sparse_add_one_section(int nid, unsigned long start_pfn, - struct vmem_altmap *altmap); -extern void sparse_remove_one_section(struct zone *zone, struct mem_section *ms, +extern int sparse_add_section(int nid, unsigned long pfn, + unsigned long nr_pages, struct vmem_altmap *altmap); +extern void sparse_remove_section(struct mem_section *ms, + unsigned long pfn, unsigned long nr_pages, unsigned long map_offset, struct vmem_altmap *altmap); extern struct page *sparse_decode_mem_map(unsigned long coded_mem_map, unsigned long pnum); diff --git a/include/linux/mempolicy.h b/include/linux/mempolicy.h index 5228c62af416..bac395f1d00a 100644 --- a/include/linux/mempolicy.h +++ b/include/linux/mempolicy.h @@ -139,6 +139,8 @@ struct mempolicy *mpol_shared_policy_lookup(struct shared_policy *sp, struct mempolicy *get_task_policy(struct task_struct *p); struct mempolicy *__get_vma_policy(struct vm_area_struct *vma, unsigned long addr); +struct mempolicy *get_vma_policy(struct vm_area_struct *vma, + unsigned long addr); bool vma_policy_mof(struct vm_area_struct *vma); extern void numa_default_policy(void); diff --git a/include/linux/memremap.h b/include/linux/memremap.h index 1732dea030b2..bef51e35d8d2 100644 --- a/include/linux/memremap.h +++ b/include/linux/memremap.h @@ -37,13 +37,6 @@ struct vmem_altmap { * A more complete discussion of unaddressable memory may be found in * include/linux/hmm.h and Documentation/vm/hmm.rst. * - * MEMORY_DEVICE_PUBLIC: - * Device memory that is cache coherent from device and CPU point of view. This - * is use on platform that have an advance system bus (like CAPI or CCIX). A - * driver can hotplug the device memory using ZONE_DEVICE and with that memory - * type. Any page of a process can be migrated to such memory. However no one - * should be allow to pin such memory so that it can always be evicted. - * * MEMORY_DEVICE_FS_DAX: * Host memory that has similar access semantics as System RAM i.e. DMA * coherent and supports page pinning. In support of coordinating page @@ -52,55 +45,85 @@ struct vmem_altmap { * wakeup is used to coordinate physical address space management (ex: * fs truncate/hole punch) vs pinned pages (ex: device dma). * + * MEMORY_DEVICE_DEVDAX: + * Host memory that has similar access semantics as System RAM i.e. DMA + * coherent and supports page pinning. In contrast to + * MEMORY_DEVICE_FS_DAX, this memory is access via a device-dax + * character device. + * * MEMORY_DEVICE_PCI_P2PDMA: * Device memory residing in a PCI BAR intended for use with Peer-to-Peer * transactions. */ enum memory_type { + /* 0 is reserved to catch uninitialized type fields */ MEMORY_DEVICE_PRIVATE = 1, - MEMORY_DEVICE_PUBLIC, MEMORY_DEVICE_FS_DAX, + MEMORY_DEVICE_DEVDAX, MEMORY_DEVICE_PCI_P2PDMA, }; -/* - * Additional notes about MEMORY_DEVICE_PRIVATE may be found in - * include/linux/hmm.h and Documentation/vm/hmm.rst. There is also a brief - * explanation in include/linux/memory_hotplug.h. - * - * The page_free() callback is called once the page refcount reaches 1 - * (ZONE_DEVICE pages never reach 0 refcount unless there is a refcount bug. - * This allows the device driver to implement its own memory management.) - */ -typedef void (*dev_page_free_t)(struct page *page, void *data); +struct dev_pagemap_ops { + /* + * Called once the page refcount reaches 1. (ZONE_DEVICE pages never + * reach 0 refcount unless there is a refcount bug. This allows the + * device driver to implement its own memory management.) + */ + void (*page_free)(struct page *page); + + /* + * Transition the refcount in struct dev_pagemap to the dead state. + */ + void (*kill)(struct dev_pagemap *pgmap); + + /* + * Wait for refcount in struct dev_pagemap to be idle and reap it. + */ + void (*cleanup)(struct dev_pagemap *pgmap); + + /* + * Used for private (un-addressable) device memory only. Must migrate + * the page back to a CPU accessible page. + */ + vm_fault_t (*migrate_to_ram)(struct vm_fault *vmf); +}; + +#define PGMAP_ALTMAP_VALID (1 << 0) /** * struct dev_pagemap - metadata for ZONE_DEVICE mappings - * @page_free: free page callback when page refcount reaches 1 * @altmap: pre-allocated/reserved memory for vmemmap allocations * @res: physical address range covered by @ref * @ref: reference count that pins the devm_memremap_pages() mapping - * @kill: callback to transition @ref to the dead state - * @cleanup: callback to wait for @ref to be idle and reap it + * @internal_ref: internal reference if @ref is not provided by the caller + * @done: completion for @internal_ref * @dev: host device of the mapping for debug * @data: private data pointer for page_free() * @type: memory type: see MEMORY_* in memory_hotplug.h + * @flags: PGMAP_* flags to specify defailed behavior + * @ops: method table */ struct dev_pagemap { - dev_page_free_t page_free; struct vmem_altmap altmap; - bool altmap_valid; struct resource res; struct percpu_ref *ref; - void (*kill)(struct percpu_ref *ref); - void (*cleanup)(struct percpu_ref *ref); - struct device *dev; - void *data; + struct percpu_ref internal_ref; + struct completion done; enum memory_type type; - u64 pci_p2pdma_bus_offset; + unsigned int flags; + const struct dev_pagemap_ops *ops; }; +static inline struct vmem_altmap *pgmap_altmap(struct dev_pagemap *pgmap) +{ + if (pgmap->flags & PGMAP_ALTMAP_VALID) + return &pgmap->altmap; + return NULL; +} + #ifdef CONFIG_ZONE_DEVICE +void *memremap_pages(struct dev_pagemap *pgmap, int nid); +void memunmap_pages(struct dev_pagemap *pgmap); void *devm_memremap_pages(struct device *dev, struct dev_pagemap *pgmap); void devm_memunmap_pages(struct device *dev, struct dev_pagemap *pgmap); struct dev_pagemap *get_dev_pagemap(unsigned long pfn, diff --git a/include/linux/mfd/aat2870.h b/include/linux/mfd/aat2870.h index af7267c480ee..2445842d482d 100644 --- a/include/linux/mfd/aat2870.h +++ b/include/linux/mfd/aat2870.h @@ -136,7 +136,6 @@ struct aat2870_data { /* for debugfs */ struct dentry *dentry_root; - struct dentry *dentry_reg; }; struct aat2870_subdev_info { diff --git a/include/linux/mfd/cros_ec.h b/include/linux/mfd/cros_ec.h index 5ddca44be06d..61c2875c2a40 100644 --- a/include/linux/mfd/cros_ec.h +++ b/include/linux/mfd/cros_ec.h @@ -8,181 +8,11 @@ #ifndef __LINUX_MFD_CROS_EC_H #define __LINUX_MFD_CROS_EC_H -#include <linux/cdev.h> #include <linux/device.h> -#include <linux/notifier.h> -#include <linux/mfd/cros_ec_commands.h> -#include <linux/mutex.h> - -#define CROS_EC_DEV_NAME "cros_ec" -#define CROS_EC_DEV_FP_NAME "cros_fp" -#define CROS_EC_DEV_PD_NAME "cros_pd" -#define CROS_EC_DEV_TP_NAME "cros_tp" -#define CROS_EC_DEV_ISH_NAME "cros_ish" - -/* - * The EC is unresponsive for a time after a reboot command. Add a - * simple delay to make sure that the bus stays locked. - */ -#define EC_REBOOT_DELAY_MS 50 - -/* - * Max bus-specific overhead incurred by request/responses. - * I2C requires 1 additional byte for requests. - * I2C requires 2 additional bytes for responses. - * SPI requires up to 32 additional bytes for responses. - */ -#define EC_PROTO_VERSION_UNKNOWN 0 -#define EC_MAX_REQUEST_OVERHEAD 1 -#define EC_MAX_RESPONSE_OVERHEAD 32 - -/* - * Command interface between EC and AP, for LPC, I2C and SPI interfaces. - */ -enum { - EC_MSG_TX_HEADER_BYTES = 3, - EC_MSG_TX_TRAILER_BYTES = 1, - EC_MSG_TX_PROTO_BYTES = EC_MSG_TX_HEADER_BYTES + - EC_MSG_TX_TRAILER_BYTES, - EC_MSG_RX_PROTO_BYTES = 3, - - /* Max length of messages for proto 2*/ - EC_PROTO2_MSG_BYTES = EC_PROTO2_MAX_PARAM_SIZE + - EC_MSG_TX_PROTO_BYTES, - - EC_MAX_MSG_BYTES = 64 * 1024, -}; - -/** - * struct cros_ec_command - Information about a ChromeOS EC command. - * @version: Command version number (often 0). - * @command: Command to send (EC_CMD_...). - * @outsize: Outgoing length in bytes. - * @insize: Max number of bytes to accept from the EC. - * @result: EC's response to the command (separate from communication failure). - * @data: Where to put the incoming data from EC and outgoing data to EC. - */ -struct cros_ec_command { - uint32_t version; - uint32_t command; - uint32_t outsize; - uint32_t insize; - uint32_t result; - uint8_t data[0]; -}; - -/** - * struct cros_ec_device - Information about a ChromeOS EC device. - * @phys_name: Name of physical comms layer (e.g. 'i2c-4'). - * @dev: Device pointer for physical comms device - * @was_wake_device: True if this device was set to wake the system from - * sleep at the last suspend. - * @cros_class: The class structure for this device. - * @cmd_readmem: Direct read of the EC memory-mapped region, if supported. - * @offset: Is within EC_LPC_ADDR_MEMMAP region. - * @bytes: Number of bytes to read. zero means "read a string" (including - * the trailing '\0'). At most only EC_MEMMAP_SIZE bytes can be - * read. Caller must ensure that the buffer is large enough for the - * result when reading a string. - * @max_request: Max size of message requested. - * @max_response: Max size of message response. - * @max_passthru: Max sice of passthru message. - * @proto_version: The protocol version used for this device. - * @priv: Private data. - * @irq: Interrupt to use. - * @id: Device id. - * @din: Input buffer (for data from EC). This buffer will always be - * dword-aligned and include enough space for up to 7 word-alignment - * bytes also, so we can ensure that the body of the message is always - * dword-aligned (64-bit). We use this alignment to keep ARM and x86 - * happy. Probably word alignment would be OK, there might be a small - * performance advantage to using dword. - * @dout: Output buffer (for data to EC). This buffer will always be - * dword-aligned and include enough space for up to 7 word-alignment - * bytes also, so we can ensure that the body of the message is always - * dword-aligned (64-bit). We use this alignment to keep ARM and x86 - * happy. Probably word alignment would be OK, there might be a small - * performance advantage to using dword. - * @din_size: Size of din buffer to allocate (zero to use static din). - * @dout_size: Size of dout buffer to allocate (zero to use static dout). - * @wake_enabled: True if this device can wake the system from sleep. - * @suspended: True if this device had been suspended. - * @cmd_xfer: Send command to EC and get response. - * Returns the number of bytes received if the communication - * succeeded, but that doesn't mean the EC was happy with the - * command. The caller should check msg.result for the EC's result - * code. - * @pkt_xfer: Send packet to EC and get response. - * @lock: One transaction at a time. - * @mkbp_event_supported: True if this EC supports the MKBP event protocol. - * @host_sleep_v1: True if this EC supports the sleep v1 command. - * @event_notifier: Interrupt event notifier for transport devices. - * @event_data: Raw payload transferred with the MKBP event. - * @event_size: Size in bytes of the event data. - * @host_event_wake_mask: Mask of host events that cause wake from suspend. - */ -struct cros_ec_device { - /* These are used by other drivers that want to talk to the EC */ - const char *phys_name; - struct device *dev; - bool was_wake_device; - struct class *cros_class; - int (*cmd_readmem)(struct cros_ec_device *ec, unsigned int offset, - unsigned int bytes, void *dest); - - /* These are used to implement the platform-specific interface */ - u16 max_request; - u16 max_response; - u16 max_passthru; - u16 proto_version; - void *priv; - int irq; - u8 *din; - u8 *dout; - int din_size; - int dout_size; - bool wake_enabled; - bool suspended; - int (*cmd_xfer)(struct cros_ec_device *ec, - struct cros_ec_command *msg); - int (*pkt_xfer)(struct cros_ec_device *ec, - struct cros_ec_command *msg); - struct mutex lock; - bool mkbp_event_supported; - bool host_sleep_v1; - struct blocking_notifier_head event_notifier; - - struct ec_response_get_next_event_v1 event_data; - int event_size; - u32 host_event_wake_mask; -}; - -/** - * struct cros_ec_sensor_platform - ChromeOS EC sensor platform information. - * @sensor_num: Id of the sensor, as reported by the EC. - */ -struct cros_ec_sensor_platform { - u8 sensor_num; -}; - -/** - * struct cros_ec_platform - ChromeOS EC platform information. - * @ec_name: Name of EC device (e.g. 'cros-ec', 'cros-pd', ...) - * used in /dev/ and sysfs. - * @cmd_offset: Offset to apply for each command. Set when - * registering a device behind another one. - */ -struct cros_ec_platform { - const char *ec_name; - u16 cmd_offset; -}; - -struct cros_ec_debugfs; /** * struct cros_ec_dev - ChromeOS EC device entry point. * @class_dev: Device structure used in sysfs. - * @cdev: Character device structure in /dev. * @ec_dev: cros_ec_device structure to talk to the physical device. * @dev: Pointer to the platform device. * @debug_info: cros_ec_debugfs structure for debugging information. @@ -192,7 +22,6 @@ struct cros_ec_debugfs; */ struct cros_ec_dev { struct device class_dev; - struct cdev cdev; struct cros_ec_device *ec_dev; struct device *dev; struct cros_ec_debugfs *debug_info; @@ -203,123 +32,4 @@ struct cros_ec_dev { #define to_cros_ec_dev(dev) container_of(dev, struct cros_ec_dev, class_dev) -/** - * cros_ec_suspend() - Handle a suspend operation for the ChromeOS EC device. - * @ec_dev: Device to suspend. - * - * This can be called by drivers to handle a suspend event. - * - * Return: 0 on success or negative error code. - */ -int cros_ec_suspend(struct cros_ec_device *ec_dev); - -/** - * cros_ec_resume() - Handle a resume operation for the ChromeOS EC device. - * @ec_dev: Device to resume. - * - * This can be called by drivers to handle a resume event. - * - * Return: 0 on success or negative error code. - */ -int cros_ec_resume(struct cros_ec_device *ec_dev); - -/** - * cros_ec_prepare_tx() - Prepare an outgoing message in the output buffer. - * @ec_dev: Device to register. - * @msg: Message to write. - * - * This is intended to be used by all ChromeOS EC drivers, but at present - * only SPI uses it. Once LPC uses the same protocol it can start using it. - * I2C could use it now, with a refactor of the existing code. - * - * Return: 0 on success or negative error code. - */ -int cros_ec_prepare_tx(struct cros_ec_device *ec_dev, - struct cros_ec_command *msg); - -/** - * cros_ec_check_result() - Check ec_msg->result. - * @ec_dev: EC device. - * @msg: Message to check. - * - * This is used by ChromeOS EC drivers to check the ec_msg->result for - * errors and to warn about them. - * - * Return: 0 on success or negative error code. - */ -int cros_ec_check_result(struct cros_ec_device *ec_dev, - struct cros_ec_command *msg); - -/** - * cros_ec_cmd_xfer() - Send a command to the ChromeOS EC. - * @ec_dev: EC device. - * @msg: Message to write. - * - * Call this to send a command to the ChromeOS EC. This should be used - * instead of calling the EC's cmd_xfer() callback directly. - * - * Return: 0 on success or negative error code. - */ -int cros_ec_cmd_xfer(struct cros_ec_device *ec_dev, - struct cros_ec_command *msg); - -/** - * cros_ec_cmd_xfer_status() - Send a command to the ChromeOS EC. - * @ec_dev: EC device. - * @msg: Message to write. - * - * This function is identical to cros_ec_cmd_xfer, except it returns success - * status only if both the command was transmitted successfully and the EC - * replied with success status. It's not necessary to check msg->result when - * using this function. - * - * Return: The number of bytes transferred on success or negative error code. - */ -int cros_ec_cmd_xfer_status(struct cros_ec_device *ec_dev, - struct cros_ec_command *msg); - -/** - * cros_ec_register() - Register a new ChromeOS EC, using the provided info. - * @ec_dev: Device to register. - * - * Before calling this, allocate a pointer to a new device and then fill - * in all the fields up to the --private-- marker. - * - * Return: 0 on success or negative error code. - */ -int cros_ec_register(struct cros_ec_device *ec_dev); - -/** - * cros_ec_query_all() - Query the protocol version supported by the - * ChromeOS EC. - * @ec_dev: Device to register. - * - * Return: 0 on success or negative error code. - */ -int cros_ec_query_all(struct cros_ec_device *ec_dev); - -/** - * cros_ec_get_next_event() - Fetch next event from the ChromeOS EC. - * @ec_dev: Device to fetch event from. - * @wake_event: Pointer to a bool set to true upon return if the event might be - * treated as a wake event. Ignored if null. - * - * Return: negative error code on errors; 0 for no data; or else number of - * bytes received (i.e., an event was retrieved successfully). Event types are - * written out to @ec_dev->event_data.event_type on success. - */ -int cros_ec_get_next_event(struct cros_ec_device *ec_dev, bool *wake_event); - -/** - * cros_ec_get_host_event() - Return a mask of event set by the ChromeOS EC. - * @ec_dev: Device to fetch event from. - * - * When MKBP is supported, when the EC raises an interrupt, we collect the - * events raised and call the functions in the ec notifier. This function - * is a helper to know which events are raised. - * - * Return: 0 on error or non-zero bitmask of one or more EC_HOST_EVENT_*. - */ -u32 cros_ec_get_host_event(struct cros_ec_device *ec_dev); - #endif /* __LINUX_MFD_CROS_EC_H */ diff --git a/include/linux/mfd/da9062/registers.h b/include/linux/mfd/da9062/registers.h index fe04b708742b..2906bf6160fb 100644 --- a/include/linux/mfd/da9062/registers.h +++ b/include/linux/mfd/da9062/registers.h @@ -797,6 +797,9 @@ #define DA9062AA_BUCK3_SL_A_SHIFT 7 #define DA9062AA_BUCK3_SL_A_MASK BIT(7) +/* DA9062AA_VLDO[1-4]_A common */ +#define DA9062AA_VLDO_A_MIN_SEL 2 + /* DA9062AA_VLDO1_A = 0x0A9 */ #define DA9062AA_VLDO1_A_SHIFT 0 #define DA9062AA_VLDO1_A_MASK 0x3f diff --git a/include/linux/mfd/da9063/pdata.h b/include/linux/mfd/da9063/pdata.h deleted file mode 100644 index 77c566ab96ab..000000000000 --- a/include/linux/mfd/da9063/pdata.h +++ /dev/null @@ -1,109 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* - * Platform configuration options for DA9063 - * - * Copyright 2012 Dialog Semiconductor Ltd. - * - * Author: Michal Hajduk, Dialog Semiconductor - * Author: Krystian Garbaciak, Dialog Semiconductor - */ - -#ifndef __MFD_DA9063_PDATA_H__ -#define __MFD_DA9063_PDATA_H__ - -#include <linux/regulator/machine.h> - -/* - * Regulator configuration - */ -/* DA9063 and DA9063L regulator IDs */ -enum { - /* BUCKs */ - DA9063_ID_BCORE1, - DA9063_ID_BCORE2, - DA9063_ID_BPRO, - DA9063_ID_BMEM, - DA9063_ID_BIO, - DA9063_ID_BPERI, - - /* BCORE1 and BCORE2 in merged mode */ - DA9063_ID_BCORES_MERGED, - /* BMEM and BIO in merged mode */ - DA9063_ID_BMEM_BIO_MERGED, - /* When two BUCKs are merged, they cannot be reused separately */ - - /* LDOs on both DA9063 and DA9063L */ - DA9063_ID_LDO3, - DA9063_ID_LDO7, - DA9063_ID_LDO8, - DA9063_ID_LDO9, - DA9063_ID_LDO11, - - /* DA9063-only LDOs */ - DA9063_ID_LDO1, - DA9063_ID_LDO2, - DA9063_ID_LDO4, - DA9063_ID_LDO5, - DA9063_ID_LDO6, - DA9063_ID_LDO10, -}; - -/* Regulators platform data */ -struct da9063_regulator_data { - int id; - struct regulator_init_data *initdata; -}; - -struct da9063_regulators_pdata { - unsigned n_regulators; - struct da9063_regulator_data *regulator_data; -}; - - -/* - * RGB LED configuration - */ -/* LED IDs for flags in struct led_info. */ -enum { - DA9063_GPIO11_LED, - DA9063_GPIO14_LED, - DA9063_GPIO15_LED, - - DA9063_LED_NUM -}; -#define DA9063_LED_ID_MASK 0x3 - -/* LED polarity for flags in struct led_info. */ -#define DA9063_LED_HIGH_LEVEL_ACTIVE 0x0 -#define DA9063_LED_LOW_LEVEL_ACTIVE 0x4 - - -/* - * General PMIC configuration - */ -/* HWMON ADC channels configuration */ -#define DA9063_FLG_FORCE_IN0_MANUAL_MODE 0x0010 -#define DA9063_FLG_FORCE_IN0_AUTO_MODE 0x0020 -#define DA9063_FLG_FORCE_IN1_MANUAL_MODE 0x0040 -#define DA9063_FLG_FORCE_IN1_AUTO_MODE 0x0080 -#define DA9063_FLG_FORCE_IN2_MANUAL_MODE 0x0100 -#define DA9063_FLG_FORCE_IN2_AUTO_MODE 0x0200 -#define DA9063_FLG_FORCE_IN3_MANUAL_MODE 0x0400 -#define DA9063_FLG_FORCE_IN3_AUTO_MODE 0x0800 - -/* Disable register caching. */ -#define DA9063_FLG_NO_CACHE 0x0008 - -struct da9063; - -/* DA9063 platform data */ -struct da9063_pdata { - int (*init)(struct da9063 *da9063); - int irq_base; - bool key_power; - unsigned flags; - struct da9063_regulators_pdata *regulators_pdata; - struct led_platform_data *leds_pdata; -}; - -#endif /* __MFD_DA9063_PDATA_H__ */ diff --git a/include/linux/mfd/intel_soc_pmic_mrfld.h b/include/linux/mfd/intel_soc_pmic_mrfld.h new file mode 100644 index 000000000000..4daecd682275 --- /dev/null +++ b/include/linux/mfd/intel_soc_pmic_mrfld.h @@ -0,0 +1,81 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Header file for Intel Merrifield Basin Cove PMIC + * + * Copyright (C) 2019 Intel Corporation. All rights reserved. + */ + +#ifndef __INTEL_SOC_PMIC_MRFLD_H__ +#define __INTEL_SOC_PMIC_MRFLD_H__ + +#include <linux/bits.h> + +#define BCOVE_ID 0x00 + +#define BCOVE_ID_MINREV0 GENMASK(2, 0) +#define BCOVE_ID_MAJREV0 GENMASK(5, 3) +#define BCOVE_ID_VENDID0 GENMASK(7, 6) + +#define BCOVE_MINOR(x) (unsigned int)(((x) & BCOVE_ID_MINREV0) >> 0) +#define BCOVE_MAJOR(x) (unsigned int)(((x) & BCOVE_ID_MAJREV0) >> 3) +#define BCOVE_VENDOR(x) (unsigned int)(((x) & BCOVE_ID_VENDID0) >> 6) + +#define BCOVE_IRQLVL1 0x01 + +#define BCOVE_PBIRQ 0x02 +#define BCOVE_TMUIRQ 0x03 +#define BCOVE_THRMIRQ 0x04 +#define BCOVE_BCUIRQ 0x05 +#define BCOVE_ADCIRQ 0x06 +#define BCOVE_CHGRIRQ0 0x07 +#define BCOVE_CHGRIRQ1 0x08 +#define BCOVE_GPIOIRQ 0x09 +#define BCOVE_CRITIRQ 0x0B + +#define BCOVE_MIRQLVL1 0x0C + +#define BCOVE_MPBIRQ 0x0D +#define BCOVE_MTMUIRQ 0x0E +#define BCOVE_MTHRMIRQ 0x0F +#define BCOVE_MBCUIRQ 0x10 +#define BCOVE_MADCIRQ 0x11 +#define BCOVE_MCHGRIRQ0 0x12 +#define BCOVE_MCHGRIRQ1 0x13 +#define BCOVE_MGPIOIRQ 0x14 +#define BCOVE_MCRITIRQ 0x16 + +#define BCOVE_SCHGRIRQ0 0x4E +#define BCOVE_SCHGRIRQ1 0x4F + +/* Level 1 IRQs */ +#define BCOVE_LVL1_PWRBTN BIT(0) /* power button */ +#define BCOVE_LVL1_TMU BIT(1) /* time management unit */ +#define BCOVE_LVL1_THRM BIT(2) /* thermal */ +#define BCOVE_LVL1_BCU BIT(3) /* burst control unit */ +#define BCOVE_LVL1_ADC BIT(4) /* ADC */ +#define BCOVE_LVL1_CHGR BIT(5) /* charger */ +#define BCOVE_LVL1_GPIO BIT(6) /* GPIO */ +#define BCOVE_LVL1_CRIT BIT(7) /* critical event */ + +/* Level 2 IRQs: power button */ +#define BCOVE_PBIRQ_PBTN BIT(0) +#define BCOVE_PBIRQ_UBTN BIT(1) + +/* Level 2 IRQs: ADC */ +#define BCOVE_ADCIRQ_BATTEMP BIT(2) +#define BCOVE_ADCIRQ_SYSTEMP BIT(3) +#define BCOVE_ADCIRQ_BATTID BIT(4) +#define BCOVE_ADCIRQ_VIBATT BIT(5) +#define BCOVE_ADCIRQ_CCTICK BIT(7) + +/* Level 2 IRQs: charger */ +#define BCOVE_CHGRIRQ_BAT0ALRT BIT(4) +#define BCOVE_CHGRIRQ_BAT1ALRT BIT(5) +#define BCOVE_CHGRIRQ_BATCRIT BIT(6) + +#define BCOVE_CHGRIRQ_VBUSDET BIT(0) +#define BCOVE_CHGRIRQ_DCDET BIT(1) +#define BCOVE_CHGRIRQ_BATTDET BIT(2) +#define BCOVE_CHGRIRQ_USBIDDET BIT(3) + +#endif /* __INTEL_SOC_PMIC_MRFLD_H__ */ diff --git a/include/linux/mfd/lp87565.h b/include/linux/mfd/lp87565.h index e619def115b4..ce965354bbad 100644 --- a/include/linux/mfd/lp87565.h +++ b/include/linux/mfd/lp87565.h @@ -14,6 +14,7 @@ enum lp87565_device_type { LP87565_DEVICE_TYPE_UNKNOWN = 0, + LP87565_DEVICE_TYPE_LP87561_Q1, LP87565_DEVICE_TYPE_LP87565_Q1, }; @@ -246,6 +247,7 @@ enum LP87565_regulator_id { LP87565_BUCK_3, LP87565_BUCK_10, LP87565_BUCK_23, + LP87565_BUCK_3210, }; /** diff --git a/include/linux/mfd/madera/core.h b/include/linux/mfd/madera/core.h index 4d5d51a9c8a6..7ffa696cce7c 100644 --- a/include/linux/mfd/madera/core.h +++ b/include/linux/mfd/madera/core.h @@ -1,12 +1,8 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0-only */ /* * MFD internals for Cirrus Logic Madera codecs * * Copyright (C) 2015-2018 Cirrus Logic - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by the - * Free Software Foundation; version 2. */ #ifndef MADERA_CORE_H @@ -26,15 +22,21 @@ enum madera_type { CS47L85 = 2, CS47L90 = 3, CS47L91 = 4, + CS47L92 = 5, + CS47L93 = 6, WM1840 = 7, + CS47L15 = 8, + CS42L92 = 9, }; #define MADERA_MAX_CORE_SUPPLIES 2 #define MADERA_MAX_GPIOS 40 +#define CS47L15_NUM_GPIOS 15 #define CS47L35_NUM_GPIOS 16 #define CS47L85_NUM_GPIOS 40 #define CS47L90_NUM_GPIOS 38 +#define CS47L92_NUM_GPIOS 16 #define MADERA_MAX_MICBIAS 4 diff --git a/include/linux/mfd/madera/pdata.h b/include/linux/mfd/madera/pdata.h index 8dc852402dbb..fa9595dd42ba 100644 --- a/include/linux/mfd/madera/pdata.h +++ b/include/linux/mfd/madera/pdata.h @@ -1,12 +1,8 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0-only */ /* * Platform data for Cirrus Logic Madera codecs * * Copyright (C) 2015-2018 Cirrus Logic - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by the - * Free Software Foundation; version 2. */ #ifndef MADERA_PDATA_H @@ -16,6 +12,7 @@ #include <linux/regulator/arizona-ldo1.h> #include <linux/regulator/arizona-micsupp.h> #include <linux/regulator/machine.h> +#include <sound/madera-pdata.h> #define MADERA_MAX_MICBIAS 4 #define MADERA_MAX_CHILD_MICBIAS 4 @@ -34,11 +31,13 @@ struct madera_codec_pdata; * @micvdd: Substruct of pdata for the MICVDD regulator * @irq_flags: Mode for primary IRQ (defaults to active low) * @gpio_base: Base GPIO number - * @gpio_configs: Array of GPIO configurations (See Documentation/pinctrl.txt) + * @gpio_configs: Array of GPIO configurations (See + * Documentation/driver-api/pinctl.rst) * @n_gpio_configs: Number of entries in gpio_configs * @gpsw: General purpose switch mode setting. Depends on the external * hardware connected to the switch. (See the SW1_MODE field * in the datasheet for the available values for your codec) + * @codec: Substruct of pdata for the ASoC codec driver */ struct madera_pdata { struct gpio_desc *reset; @@ -53,6 +52,8 @@ struct madera_pdata { int n_gpio_configs; u32 gpsw[MADERA_MAX_GPSW]; + + struct madera_codec_pdata codec; }; #endif diff --git a/include/linux/mfd/madera/registers.h b/include/linux/mfd/madera/registers.h index 977e06101711..fe909d177762 100644 --- a/include/linux/mfd/madera/registers.h +++ b/include/linux/mfd/madera/registers.h @@ -1,12 +1,8 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0-only */ /* * Madera register definitions * * Copyright (C) 2015-2018 Cirrus Logic - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by the - * Free Software Foundation; version 2. */ #ifndef MADERA_REGISTERS_H @@ -76,10 +72,14 @@ #define MADERA_FLL1_CONTROL_4 0x174 #define MADERA_FLL1_CONTROL_5 0x175 #define MADERA_FLL1_CONTROL_6 0x176 -#define MADERA_FLL1_LOOP_FILTER_TEST_1 0x177 -#define MADERA_FLL1_NCO_TEST_0 0x178 +#define CS47L92_FLL1_CONTROL_7 0x177 +#define CS47L92_FLL1_CONTROL_8 0x178 #define MADERA_FLL1_CONTROL_7 0x179 +#define CS47L92_FLL1_CONTROL_9 0x179 #define MADERA_FLL1_EFS_2 0x17A +#define CS47L92_FLL1_CONTROL_10 0x17A +#define MADERA_FLL1_CONTROL_11 0x17B +#define MADERA_FLL1_DIGITAL_TEST_1 0x17D #define CS47L35_FLL1_SYNCHRONISER_1 0x17F #define CS47L35_FLL1_SYNCHRONISER_2 0x180 #define CS47L35_FLL1_SYNCHRONISER_3 0x181 @@ -98,16 +98,21 @@ #define MADERA_FLL1_SYNCHRONISER_7 0x187 #define MADERA_FLL1_SPREAD_SPECTRUM 0x189 #define MADERA_FLL1_GPIO_CLOCK 0x18A +#define CS47L92_FLL1_GPIO_CLOCK 0x18E #define MADERA_FLL2_CONTROL_1 0x191 #define MADERA_FLL2_CONTROL_2 0x192 #define MADERA_FLL2_CONTROL_3 0x193 #define MADERA_FLL2_CONTROL_4 0x194 #define MADERA_FLL2_CONTROL_5 0x195 #define MADERA_FLL2_CONTROL_6 0x196 -#define MADERA_FLL2_LOOP_FILTER_TEST_1 0x197 -#define MADERA_FLL2_NCO_TEST_0 0x198 +#define CS47L92_FLL2_CONTROL_7 0x197 +#define CS47L92_FLL2_CONTROL_8 0x198 #define MADERA_FLL2_CONTROL_7 0x199 +#define CS47L92_FLL2_CONTROL_9 0x199 #define MADERA_FLL2_EFS_2 0x19A +#define CS47L92_FLL2_CONTROL_10 0x19A +#define MADERA_FLL2_CONTROL_11 0x19B +#define MADERA_FLL2_DIGITAL_TEST_1 0x19D #define MADERA_FLL2_SYNCHRONISER_1 0x1A1 #define MADERA_FLL2_SYNCHRONISER_2 0x1A2 #define MADERA_FLL2_SYNCHRONISER_3 0x1A3 @@ -117,14 +122,13 @@ #define MADERA_FLL2_SYNCHRONISER_7 0x1A7 #define MADERA_FLL2_SPREAD_SPECTRUM 0x1A9 #define MADERA_FLL2_GPIO_CLOCK 0x1AA +#define CS47L92_FLL2_GPIO_CLOCK 0x1AE #define MADERA_FLL3_CONTROL_1 0x1B1 #define MADERA_FLL3_CONTROL_2 0x1B2 #define MADERA_FLL3_CONTROL_3 0x1B3 #define MADERA_FLL3_CONTROL_4 0x1B4 #define MADERA_FLL3_CONTROL_5 0x1B5 #define MADERA_FLL3_CONTROL_6 0x1B6 -#define MADERA_FLL3_LOOP_FILTER_TEST_1 0x1B7 -#define MADERA_FLL3_NCO_TEST_0 0x1B8 #define MADERA_FLL3_CONTROL_7 0x1B9 #define MADERA_FLL3_SYNCHRONISER_1 0x1C1 #define MADERA_FLL3_SYNCHRONISER_2 0x1C2 @@ -244,6 +248,8 @@ #define MADERA_IN6R_CONTROL 0x33C #define MADERA_ADC_DIGITAL_VOLUME_6R 0x33D #define MADERA_DMIC6R_CONTROL 0x33E +#define CS47L15_ADC_INT_BIAS 0x3A8 +#define CS47L15_PGA_BIAS_SEL 0x3C4 #define MADERA_OUTPUT_ENABLES_1 0x400 #define MADERA_OUTPUT_STATUS_1 0x401 #define MADERA_RAW_OUTPUT_STATUS_1 0x406 @@ -265,6 +271,7 @@ #define MADERA_NOISE_GATE_SELECT_2R 0x41F #define MADERA_OUTPUT_PATH_CONFIG_3L 0x420 #define MADERA_DAC_DIGITAL_VOLUME_3L 0x421 +#define MADERA_OUTPUT_PATH_CONFIG_3 0x422 #define MADERA_NOISE_GATE_SELECT_3L 0x423 #define MADERA_OUTPUT_PATH_CONFIG_3R 0x424 #define MADERA_DAC_DIGITAL_VOLUME_3R 0x425 @@ -287,9 +294,6 @@ #define MADERA_OUTPUT_PATH_CONFIG_6R 0x43C #define MADERA_DAC_DIGITAL_VOLUME_6R 0x43D #define MADERA_NOISE_GATE_SELECT_6R 0x43F -#define MADERA_DRE_ENABLE 0x440 -#define MADERA_EDRE_ENABLE 0x448 -#define MADERA_EDRE_MANUAL 0x44A #define MADERA_DAC_AEC_CONTROL_1 0x450 #define MADERA_DAC_AEC_CONTROL_2 0x451 #define MADERA_NOISE_GATE_CONTROL 0x458 @@ -367,8 +371,20 @@ #define MADERA_AIF3_FRAME_CTRL_2 0x588 #define MADERA_AIF3_FRAME_CTRL_3 0x589 #define MADERA_AIF3_FRAME_CTRL_4 0x58A +#define MADERA_AIF3_FRAME_CTRL_5 0x58B +#define MADERA_AIF3_FRAME_CTRL_6 0x58C +#define MADERA_AIF3_FRAME_CTRL_7 0x58D +#define MADERA_AIF3_FRAME_CTRL_8 0x58E +#define MADERA_AIF3_FRAME_CTRL_9 0x58F +#define MADERA_AIF3_FRAME_CTRL_10 0x590 #define MADERA_AIF3_FRAME_CTRL_11 0x591 #define MADERA_AIF3_FRAME_CTRL_12 0x592 +#define MADERA_AIF3_FRAME_CTRL_13 0x593 +#define MADERA_AIF3_FRAME_CTRL_14 0x594 +#define MADERA_AIF3_FRAME_CTRL_15 0x595 +#define MADERA_AIF3_FRAME_CTRL_16 0x596 +#define MADERA_AIF3_FRAME_CTRL_17 0x597 +#define MADERA_AIF3_FRAME_CTRL_18 0x598 #define MADERA_AIF3_TX_ENABLES 0x599 #define MADERA_AIF3_RX_ENABLES 0x59A #define MADERA_AIF3_FORCE_WRITE 0x59B @@ -660,6 +676,54 @@ #define MADERA_AIF3TX2MIX_INPUT_3_VOLUME 0x78D #define MADERA_AIF3TX2MIX_INPUT_4_SOURCE 0x78E #define MADERA_AIF3TX2MIX_INPUT_4_VOLUME 0x78F +#define MADERA_AIF3TX3MIX_INPUT_1_SOURCE 0x790 +#define MADERA_AIF3TX3MIX_INPUT_1_VOLUME 0x791 +#define MADERA_AIF3TX3MIX_INPUT_2_SOURCE 0x792 +#define MADERA_AIF3TX3MIX_INPUT_2_VOLUME 0x793 +#define MADERA_AIF3TX3MIX_INPUT_3_SOURCE 0x794 +#define MADERA_AIF3TX3MIX_INPUT_3_VOLUME 0x795 +#define MADERA_AIF3TX3MIX_INPUT_4_SOURCE 0x796 +#define MADERA_AIF3TX3MIX_INPUT_4_VOLUME 0x797 +#define MADERA_AIF3TX4MIX_INPUT_1_SOURCE 0x798 +#define MADERA_AIF3TX4MIX_INPUT_1_VOLUME 0x799 +#define MADERA_AIF3TX4MIX_INPUT_2_SOURCE 0x79A +#define MADERA_AIF3TX4MIX_INPUT_2_VOLUME 0x79B +#define MADERA_AIF3TX4MIX_INPUT_3_SOURCE 0x79C +#define MADERA_AIF3TX4MIX_INPUT_3_VOLUME 0x79D +#define MADERA_AIF3TX4MIX_INPUT_4_SOURCE 0x79E +#define MADERA_AIF3TX4MIX_INPUT_4_VOLUME 0x79F +#define CS47L92_AIF3TX5MIX_INPUT_1_SOURCE 0x7A0 +#define CS47L92_AIF3TX5MIX_INPUT_1_VOLUME 0x7A1 +#define CS47L92_AIF3TX5MIX_INPUT_2_SOURCE 0x7A2 +#define CS47L92_AIF3TX5MIX_INPUT_2_VOLUME 0x7A3 +#define CS47L92_AIF3TX5MIX_INPUT_3_SOURCE 0x7A4 +#define CS47L92_AIF3TX5MIX_INPUT_3_VOLUME 0x7A5 +#define CS47L92_AIF3TX5MIX_INPUT_4_SOURCE 0x7A6 +#define CS47L92_AIF3TX5MIX_INPUT_4_VOLUME 0x7A7 +#define CS47L92_AIF3TX6MIX_INPUT_1_SOURCE 0x7A8 +#define CS47L92_AIF3TX6MIX_INPUT_1_VOLUME 0x7A9 +#define CS47L92_AIF3TX6MIX_INPUT_2_SOURCE 0x7AA +#define CS47L92_AIF3TX6MIX_INPUT_2_VOLUME 0x7AB +#define CS47L92_AIF3TX6MIX_INPUT_3_SOURCE 0x7AC +#define CS47L92_AIF3TX6MIX_INPUT_3_VOLUME 0x7AD +#define CS47L92_AIF3TX6MIX_INPUT_4_SOURCE 0x7AE +#define CS47L92_AIF3TX6MIX_INPUT_4_VOLUME 0x7AF +#define CS47L92_AIF3TX7MIX_INPUT_1_SOURCE 0x7B0 +#define CS47L92_AIF3TX7MIX_INPUT_1_VOLUME 0x7B1 +#define CS47L92_AIF3TX7MIX_INPUT_2_SOURCE 0x7B2 +#define CS47L92_AIF3TX7MIX_INPUT_2_VOLUME 0x7B3 +#define CS47L92_AIF3TX7MIX_INPUT_3_SOURCE 0x7B4 +#define CS47L92_AIF3TX7MIX_INPUT_3_VOLUME 0x7B5 +#define CS47L92_AIF3TX7MIX_INPUT_4_SOURCE 0x7B6 +#define CS47L92_AIF3TX7MIX_INPUT_4_VOLUME 0x7B7 +#define CS47L92_AIF3TX8MIX_INPUT_1_SOURCE 0x7B8 +#define CS47L92_AIF3TX8MIX_INPUT_1_VOLUME 0x7B9 +#define CS47L92_AIF3TX8MIX_INPUT_2_SOURCE 0x7BA +#define CS47L92_AIF3TX8MIX_INPUT_2_VOLUME 0x7BB +#define CS47L92_AIF3TX8MIX_INPUT_3_SOURCE 0x7BC +#define CS47L92_AIF3TX8MIX_INPUT_3_VOLUME 0x7BD +#define CS47L92_AIF3TX8MIX_INPUT_4_SOURCE 0x7BE +#define CS47L92_AIF3TX8MIX_INPUT_4_VOLUME 0x7BF #define MADERA_AIF4TX1MIX_INPUT_1_SOURCE 0x7A0 #define MADERA_AIF4TX1MIX_INPUT_1_VOLUME 0x7A1 #define MADERA_AIF4TX1MIX_INPUT_2_SOURCE 0x7A2 @@ -1103,68 +1167,8 @@ #define MADERA_FCR_ADC_REFORMATTER_CONTROL 0xF73 #define MADERA_FCR_COEFF_START 0xF74 #define MADERA_FCR_COEFF_END 0xFC5 -#define MADERA_DAC_COMP_1 0x1300 -#define MADERA_DAC_COMP_2 0x1302 -#define MADERA_FRF_COEFFICIENT_1L_1 0x1380 -#define MADERA_FRF_COEFFICIENT_1L_2 0x1381 -#define MADERA_FRF_COEFFICIENT_1L_3 0x1382 -#define MADERA_FRF_COEFFICIENT_1L_4 0x1383 -#define MADERA_FRF_COEFFICIENT_1R_1 0x1390 -#define MADERA_FRF_COEFFICIENT_1R_2 0x1391 -#define MADERA_FRF_COEFFICIENT_1R_3 0x1392 -#define MADERA_FRF_COEFFICIENT_1R_4 0x1393 -#define MADERA_FRF_COEFFICIENT_2L_1 0x13A0 -#define MADERA_FRF_COEFFICIENT_2L_2 0x13A1 -#define MADERA_FRF_COEFFICIENT_2L_3 0x13A2 -#define MADERA_FRF_COEFFICIENT_2L_4 0x13A3 -#define MADERA_FRF_COEFFICIENT_2R_1 0x13B0 -#define MADERA_FRF_COEFFICIENT_2R_2 0x13B1 -#define MADERA_FRF_COEFFICIENT_2R_3 0x13B2 -#define MADERA_FRF_COEFFICIENT_2R_4 0x13B3 -#define MADERA_FRF_COEFFICIENT_3L_1 0x13C0 -#define MADERA_FRF_COEFFICIENT_3L_2 0x13C1 -#define MADERA_FRF_COEFFICIENT_3L_3 0x13C2 -#define MADERA_FRF_COEFFICIENT_3L_4 0x13C3 -#define MADERA_FRF_COEFFICIENT_3R_1 0x13D0 -#define MADERA_FRF_COEFFICIENT_3R_2 0x13D1 -#define MADERA_FRF_COEFFICIENT_3R_3 0x13D2 -#define MADERA_FRF_COEFFICIENT_3R_4 0x13D3 -#define MADERA_FRF_COEFFICIENT_4L_1 0x13E0 -#define MADERA_FRF_COEFFICIENT_4L_2 0x13E1 -#define MADERA_FRF_COEFFICIENT_4L_3 0x13E2 -#define MADERA_FRF_COEFFICIENT_4L_4 0x13E3 -#define MADERA_FRF_COEFFICIENT_4R_1 0x13F0 -#define MADERA_FRF_COEFFICIENT_4R_2 0x13F1 -#define MADERA_FRF_COEFFICIENT_4R_3 0x13F2 -#define MADERA_FRF_COEFFICIENT_4R_4 0x13F3 -#define CS47L35_FRF_COEFFICIENT_4L_1 0x13A0 -#define CS47L35_FRF_COEFFICIENT_4L_2 0x13A1 -#define CS47L35_FRF_COEFFICIENT_4L_3 0x13A2 -#define CS47L35_FRF_COEFFICIENT_4L_4 0x13A3 -#define CS47L35_FRF_COEFFICIENT_5L_1 0x13B0 -#define CS47L35_FRF_COEFFICIENT_5L_2 0x13B1 -#define CS47L35_FRF_COEFFICIENT_5L_3 0x13B2 -#define CS47L35_FRF_COEFFICIENT_5L_4 0x13B3 -#define CS47L35_FRF_COEFFICIENT_5R_1 0x13C0 -#define CS47L35_FRF_COEFFICIENT_5R_2 0x13C1 -#define CS47L35_FRF_COEFFICIENT_5R_3 0x13C2 -#define CS47L35_FRF_COEFFICIENT_5R_4 0x13C3 -#define MADERA_FRF_COEFFICIENT_5L_1 0x1400 -#define MADERA_FRF_COEFFICIENT_5L_2 0x1401 -#define MADERA_FRF_COEFFICIENT_5L_3 0x1402 -#define MADERA_FRF_COEFFICIENT_5L_4 0x1403 -#define MADERA_FRF_COEFFICIENT_5R_1 0x1410 -#define MADERA_FRF_COEFFICIENT_5R_2 0x1411 -#define MADERA_FRF_COEFFICIENT_5R_3 0x1412 -#define MADERA_FRF_COEFFICIENT_5R_4 0x1413 -#define MADERA_FRF_COEFFICIENT_6L_1 0x1420 -#define MADERA_FRF_COEFFICIENT_6L_2 0x1421 -#define MADERA_FRF_COEFFICIENT_6L_3 0x1422 -#define MADERA_FRF_COEFFICIENT_6L_4 0x1423 -#define MADERA_FRF_COEFFICIENT_6R_1 0x1430 -#define MADERA_FRF_COEFFICIENT_6R_2 0x1431 -#define MADERA_FRF_COEFFICIENT_6R_3 0x1432 -#define MADERA_FRF_COEFFICIENT_6R_4 0x1433 +#define MADERA_AUXPDM1_CTRL_0 0x10C0 +#define MADERA_AUXPDM1_CTRL_1 0x10C1 #define MADERA_DFC1_CTRL 0x1480 #define MADERA_DFC1_RX 0x1482 #define MADERA_DFC1_TX 0x1484 @@ -1202,6 +1206,8 @@ #define MADERA_GPIO1_CTRL_2 0x1701 #define MADERA_GPIO2_CTRL_1 0x1702 #define MADERA_GPIO2_CTRL_2 0x1703 +#define MADERA_GPIO15_CTRL_1 0x171C +#define MADERA_GPIO15_CTRL_2 0x171D #define MADERA_GPIO16_CTRL_1 0x171E #define MADERA_GPIO16_CTRL_2 0x171F #define MADERA_GPIO38_CTRL_1 0x174A @@ -1232,6 +1238,7 @@ #define MADERA_IRQ2_CTRL 0x1A82 #define MADERA_INTERRUPT_RAW_STATUS_1 0x1AA0 #define MADERA_WSEQ_SEQUENCE_1 0x3000 +#define MADERA_WSEQ_SEQUENCE_225 0x31C0 #define MADERA_WSEQ_SEQUENCE_252 0x31F6 #define CS47L35_OTP_HPDET_CAL_1 0x31F8 #define CS47L35_OTP_HPDET_CAL_2 0x31FA @@ -1441,6 +1448,12 @@ #define MADERA_OPCLK_ASYNC_SEL_WIDTH 3 /* (0x0171) FLL1_Control_1 */ +#define CS47L92_FLL1_REFCLK_SRC_MASK 0xF000 +#define CS47L92_FLL1_REFCLK_SRC_SHIFT 12 +#define CS47L92_FLL1_REFCLK_SRC_WIDTH 4 +#define MADERA_FLL1_HOLD_MASK 0x0004 +#define MADERA_FLL1_HOLD_SHIFT 2 +#define MADERA_FLL1_HOLD_WIDTH 1 #define MADERA_FLL1_FREERUN 0x0002 #define MADERA_FLL1_FREERUN_MASK 0x0002 #define MADERA_FLL1_FREERUN_SHIFT 1 @@ -1473,6 +1486,9 @@ #define MADERA_FLL1_FRATIO_MASK 0x0F00 #define MADERA_FLL1_FRATIO_SHIFT 8 #define MADERA_FLL1_FRATIO_WIDTH 4 +#define MADERA_FLL1_FB_DIV_MASK 0x03FF +#define MADERA_FLL1_FB_DIV_SHIFT 0 +#define MADERA_FLL1_FB_DIV_WIDTH 10 /* (0x0176) FLL1_Control_6 */ #define MADERA_FLL1_REFCLK_DIV_MASK 0x00C0 @@ -1482,15 +1498,6 @@ #define MADERA_FLL1_REFCLK_SRC_SHIFT 0 #define MADERA_FLL1_REFCLK_SRC_WIDTH 4 -/* (0x0177) FLL1_Loop_Filter_Test_1 */ -#define MADERA_FLL1_FRC_INTEG_UPD 0x8000 -#define MADERA_FLL1_FRC_INTEG_UPD_MASK 0x8000 -#define MADERA_FLL1_FRC_INTEG_UPD_SHIFT 15 -#define MADERA_FLL1_FRC_INTEG_UPD_WIDTH 1 -#define MADERA_FLL1_FRC_INTEG_VAL_MASK 0x0FFF -#define MADERA_FLL1_FRC_INTEG_VAL_SHIFT 0 -#define MADERA_FLL1_FRC_INTEG_VAL_WIDTH 12 - /* (0x0179) FLL1_Control_7 */ #define MADERA_FLL1_GAIN_MASK 0x003c #define MADERA_FLL1_GAIN_SHIFT 2 @@ -1504,6 +1511,30 @@ #define MADERA_FLL1_PHASE_ENA_SHIFT 11 #define MADERA_FLL1_PHASE_ENA_WIDTH 1 +/* (0x017A) FLL1_Control_10 */ +#define MADERA_FLL1_HP_MASK 0xC000 +#define MADERA_FLL1_HP_SHIFT 14 +#define MADERA_FLL1_HP_WIDTH 2 +#define MADERA_FLL1_PHASEDET_ENA_MASK 0x1000 +#define MADERA_FLL1_PHASEDET_ENA_SHIFT 12 +#define MADERA_FLL1_PHASEDET_ENA_WIDTH 1 + +/* (0x017B) FLL1_Control_11 */ +#define MADERA_FLL1_LOCKDET_THR_MASK 0x001E +#define MADERA_FLL1_LOCKDET_THR_SHIFT 1 +#define MADERA_FLL1_LOCKDET_THR_WIDTH 4 +#define MADERA_FLL1_LOCKDET_MASK 0x0001 +#define MADERA_FLL1_LOCKDET_SHIFT 0 +#define MADERA_FLL1_LOCKDET_WIDTH 1 + +/* (0x017D) FLL1_Digital_Test_1 */ +#define MADERA_FLL1_SYNC_EFS_ENA_MASK 0x0100 +#define MADERA_FLL1_SYNC_EFS_ENA_SHIFT 8 +#define MADERA_FLL1_SYNC_EFS_ENA_WIDTH 1 +#define MADERA_FLL1_CLK_VCO_FAST_SRC_MASK 0x0003 +#define MADERA_FLL1_CLK_VCO_FAST_SRC_SHIFT 0 +#define MADERA_FLL1_CLK_VCO_FAST_SRC_WIDTH 2 + /* (0x0181) FLL1_Synchroniser_1 */ #define MADERA_FLL1_SYNC_ENA 0x0001 #define MADERA_FLL1_SYNC_ENA_MASK 0x0001 @@ -1625,6 +1656,13 @@ #define MADERA_LDO2_ENA_WIDTH 1 /* (0x0218) Mic_Bias_Ctrl_1 */ +#define MADERA_MICB1_EXT_CAP 0x8000 +#define MADERA_MICB1_EXT_CAP_MASK 0x8000 +#define MADERA_MICB1_EXT_CAP_SHIFT 15 +#define MADERA_MICB1_EXT_CAP_WIDTH 1 +#define MADERA_MICB1_LVL_MASK 0x01E0 +#define MADERA_MICB1_LVL_SHIFT 5 +#define MADERA_MICB1_LVL_WIDTH 4 #define MADERA_MICB1_ENA 0x0001 #define MADERA_MICB1_ENA_MASK 0x0001 #define MADERA_MICB1_ENA_SHIFT 0 @@ -2308,6 +2346,17 @@ #define MADERA_OUT1R_ENA_SHIFT 0 #define MADERA_OUT1R_ENA_WIDTH 1 +/* (0x0408) Output_Rate_1 */ +#define MADERA_CP_DAC_MODE_MASK 0x0040 +#define MADERA_CP_DAC_MODE_SHIFT 6 +#define MADERA_CP_DAC_MODE_WIDTH 1 +#define MADERA_OUT_EXT_CLK_DIV_MASK 0x0030 +#define MADERA_OUT_EXT_CLK_DIV_SHIFT 4 +#define MADERA_OUT_EXT_CLK_DIV_WIDTH 2 +#define MADERA_OUT_CLK_SRC_MASK 0x0007 +#define MADERA_OUT_CLK_SRC_SHIFT 0 +#define MADERA_OUT_CLK_SRC_WIDTH 3 + /* (0x0409) Output_Volume_Ramp */ #define MADERA_OUT_VD_RAMP_MASK 0x0070 #define MADERA_OUT_VD_RAMP_SHIFT 4 @@ -2829,6 +2878,30 @@ #define MADERA_AIF2RX1_ENA_WIDTH 1 /* (0x0599) AIF3_Tx_Enables */ +#define MADERA_AIF3TX8_ENA 0x0080 +#define MADERA_AIF3TX8_ENA_MASK 0x0080 +#define MADERA_AIF3TX8_ENA_SHIFT 7 +#define MADERA_AIF3TX8_ENA_WIDTH 1 +#define MADERA_AIF3TX7_ENA 0x0040 +#define MADERA_AIF3TX7_ENA_MASK 0x0040 +#define MADERA_AIF3TX7_ENA_SHIFT 6 +#define MADERA_AIF3TX7_ENA_WIDTH 1 +#define MADERA_AIF3TX6_ENA 0x0020 +#define MADERA_AIF3TX6_ENA_MASK 0x0020 +#define MADERA_AIF3TX6_ENA_SHIFT 5 +#define MADERA_AIF3TX6_ENA_WIDTH 1 +#define MADERA_AIF3TX5_ENA 0x0010 +#define MADERA_AIF3TX5_ENA_MASK 0x0010 +#define MADERA_AIF3TX5_ENA_SHIFT 4 +#define MADERA_AIF3TX5_ENA_WIDTH 1 +#define MADERA_AIF3TX4_ENA 0x0008 +#define MADERA_AIF3TX4_ENA_MASK 0x0008 +#define MADERA_AIF3TX4_ENA_SHIFT 3 +#define MADERA_AIF3TX4_ENA_WIDTH 1 +#define MADERA_AIF3TX3_ENA 0x0004 +#define MADERA_AIF3TX3_ENA_MASK 0x0004 +#define MADERA_AIF3TX3_ENA_SHIFT 2 +#define MADERA_AIF3TX3_ENA_WIDTH 1 #define MADERA_AIF3TX2_ENA 0x0002 #define MADERA_AIF3TX2_ENA_MASK 0x0002 #define MADERA_AIF3TX2_ENA_SHIFT 1 @@ -2839,6 +2912,30 @@ #define MADERA_AIF3TX1_ENA_WIDTH 1 /* (0x059A) AIF3_Rx_Enables */ +#define MADERA_AIF3RX8_ENA 0x0080 +#define MADERA_AIF3RX8_ENA_MASK 0x0080 +#define MADERA_AIF3RX8_ENA_SHIFT 7 +#define MADERA_AIF3RX8_ENA_WIDTH 1 +#define MADERA_AIF3RX7_ENA 0x0040 +#define MADERA_AIF3RX7_ENA_MASK 0x0040 +#define MADERA_AIF3RX7_ENA_SHIFT 6 +#define MADERA_AIF3RX7_ENA_WIDTH 1 +#define MADERA_AIF3RX6_ENA 0x0020 +#define MADERA_AIF3RX6_ENA_MASK 0x0020 +#define MADERA_AIF3RX6_ENA_SHIFT 5 +#define MADERA_AIF3RX6_ENA_WIDTH 1 +#define MADERA_AIF3RX5_ENA 0x0010 +#define MADERA_AIF3RX5_ENA_MASK 0x0010 +#define MADERA_AIF3RX5_ENA_SHIFT 4 +#define MADERA_AIF3RX5_ENA_WIDTH 1 +#define MADERA_AIF3RX4_ENA 0x0008 +#define MADERA_AIF3RX4_ENA_MASK 0x0008 +#define MADERA_AIF3RX4_ENA_SHIFT 3 +#define MADERA_AIF3RX4_ENA_WIDTH 1 +#define MADERA_AIF3RX3_ENA 0x0004 +#define MADERA_AIF3RX3_ENA_MASK 0x0004 +#define MADERA_AIF3RX3_ENA_SHIFT 2 +#define MADERA_AIF3RX3_ENA_WIDTH 1 #define MADERA_AIF3RX2_ENA 0x0002 #define MADERA_AIF3RX2_ENA_MASK 0x0002 #define MADERA_AIF3RX2_ENA_SHIFT 1 @@ -3453,6 +3550,25 @@ #define MADERA_FCR_MIC_MODE_SEL_SHIFT 2 #define MADERA_FCR_MIC_MODE_SEL_WIDTH 2 +/* (0x10C0) AUXPDM1_CTRL_0 */ +#define MADERA_AUXPDM1_SRC_MASK 0x0F00 +#define MADERA_AUXPDM1_SRC_SHIFT 8 +#define MADERA_AUXPDM1_SRC_WIDTH 4 +#define MADERA_AUXPDM1_TXEDGE_MASK 0x0010 +#define MADERA_AUXPDM1_TXEDGE_SHIFT 4 +#define MADERA_AUXPDM1_TXEDGE_WIDTH 1 +#define MADERA_AUXPDM1_MSTR_MASK 0x0008 +#define MADERA_AUXPDM1_MSTR_SHIFT 3 +#define MADERA_AUXPDM1_MSTR_WIDTH 1 +#define MADERA_AUXPDM1_ENABLE_MASK 0x0001 +#define MADERA_AUXPDM1_ENABLE_SHIFT 0 +#define MADERA_AUXPDM1_ENABLE_WIDTH 1 + +/* (0x10C1) AUXPDM1_CTRL_1 */ +#define MADERA_AUXPDM1_CLK_FREQ_MASK 0xC000 +#define MADERA_AUXPDM1_CLK_FREQ_SHIFT 14 +#define MADERA_AUXPDM1_CLK_FREQ_WIDTH 2 + /* (0x1480) DFC1_CTRL_W0 */ #define MADERA_DFC1_RATE_MASK 0x007C #define MADERA_DFC1_RATE_SHIFT 2 diff --git a/include/linux/mfd/mt6397/core.h b/include/linux/mfd/mt6397/core.h index 25a95e72179b..fc88d315bdde 100644 --- a/include/linux/mfd/mt6397/core.h +++ b/include/linux/mfd/mt6397/core.h @@ -7,6 +7,14 @@ #ifndef __MFD_MT6397_CORE_H__ #define __MFD_MT6397_CORE_H__ +#include <linux/mutex.h> + +enum chip_id { + MT6323_CHIP_ID = 0x23, + MT6391_CHIP_ID = 0x91, + MT6397_CHIP_ID = 0x97, +}; + enum mt6397_irq_numbers { MT6397_IRQ_SPKL_AB = 0, MT6397_IRQ_SPKR_AB, @@ -54,6 +62,9 @@ struct mt6397_chip { u16 irq_masks_cache[2]; u16 int_con[2]; u16 int_status[2]; + u16 chip_id; }; +int mt6397_irq_init(struct mt6397_chip *chip); + #endif /* __MFD_MT6397_CORE_H__ */ diff --git a/include/linux/mfd/rk808.h b/include/linux/mfd/rk808.h index 1d831c7222b9..7cfd2b0504df 100644 --- a/include/linux/mfd/rk808.h +++ b/include/linux/mfd/rk808.h @@ -374,6 +374,7 @@ enum rk805_reg { #define SWITCH1_EN BIT(5) #define DEV_OFF_RST BIT(3) #define DEV_OFF BIT(0) +#define RTC_STOP BIT(0) #define VB_LO_ACT BIT(4) #define VB_LO_SEL_3500MV (7 << 0) @@ -387,7 +388,179 @@ enum rk805_reg { #define SHUTDOWN_FUN (0x2 << 2) #define SLEEP_FUN (0x1 << 2) #define RK8XX_ID_MSK 0xfff0 +#define PWM_MODE_MSK BIT(7) #define FPWM_MODE BIT(7) +#define AUTO_PWM_MODE 0 + +enum rk817_reg_id { + RK817_ID_DCDC1 = 0, + RK817_ID_DCDC2, + RK817_ID_DCDC3, + RK817_ID_DCDC4, + RK817_ID_LDO1, + RK817_ID_LDO2, + RK817_ID_LDO3, + RK817_ID_LDO4, + RK817_ID_LDO5, + RK817_ID_LDO6, + RK817_ID_LDO7, + RK817_ID_LDO8, + RK817_ID_LDO9, + RK817_ID_BOOST, + RK817_ID_BOOST_OTG_SW, + RK817_NUM_REGULATORS +}; + +enum rk809_reg_id { + RK809_ID_DCDC5 = RK817_ID_BOOST, + RK809_ID_SW1, + RK809_ID_SW2, + RK809_NUM_REGULATORS +}; + +#define RK817_SECONDS_REG 0x00 +#define RK817_MINUTES_REG 0x01 +#define RK817_HOURS_REG 0x02 +#define RK817_DAYS_REG 0x03 +#define RK817_MONTHS_REG 0x04 +#define RK817_YEARS_REG 0x05 +#define RK817_WEEKS_REG 0x06 +#define RK817_ALARM_SECONDS_REG 0x07 +#define RK817_ALARM_MINUTES_REG 0x08 +#define RK817_ALARM_HOURS_REG 0x09 +#define RK817_ALARM_DAYS_REG 0x0a +#define RK817_ALARM_MONTHS_REG 0x0b +#define RK817_ALARM_YEARS_REG 0x0c +#define RK817_RTC_CTRL_REG 0xd +#define RK817_RTC_STATUS_REG 0xe +#define RK817_RTC_INT_REG 0xf +#define RK817_RTC_COMP_LSB_REG 0x10 +#define RK817_RTC_COMP_MSB_REG 0x11 + +#define RK817_POWER_EN_REG(i) (0xb1 + (i)) +#define RK817_POWER_SLP_EN_REG(i) (0xb5 + (i)) + +#define RK817_POWER_CONFIG (0xb9) + +#define RK817_BUCK_CONFIG_REG(i) (0xba + (i) * 3) + +#define RK817_BUCK1_ON_VSEL_REG 0xBB +#define RK817_BUCK1_SLP_VSEL_REG 0xBC + +#define RK817_BUCK2_CONFIG_REG 0xBD +#define RK817_BUCK2_ON_VSEL_REG 0xBE +#define RK817_BUCK2_SLP_VSEL_REG 0xBF + +#define RK817_BUCK3_CONFIG_REG 0xC0 +#define RK817_BUCK3_ON_VSEL_REG 0xC1 +#define RK817_BUCK3_SLP_VSEL_REG 0xC2 + +#define RK817_BUCK4_CONFIG_REG 0xC3 +#define RK817_BUCK4_ON_VSEL_REG 0xC4 +#define RK817_BUCK4_SLP_VSEL_REG 0xC5 + +#define RK817_LDO_ON_VSEL_REG(idx) (0xcc + (idx) * 2) +#define RK817_BOOST_OTG_CFG (0xde) + +#define RK817_ID_MSB 0xed +#define RK817_ID_LSB 0xee + +#define RK817_SYS_STS 0xf0 +#define RK817_SYS_CFG(i) (0xf1 + (i)) + +#define RK817_ON_SOURCE_REG 0xf5 +#define RK817_OFF_SOURCE_REG 0xf6 + +/* INTERRUPT REGISTER */ +#define RK817_INT_STS_REG0 0xf8 +#define RK817_INT_STS_MSK_REG0 0xf9 +#define RK817_INT_STS_REG1 0xfa +#define RK817_INT_STS_MSK_REG1 0xfb +#define RK817_INT_STS_REG2 0xfc +#define RK817_INT_STS_MSK_REG2 0xfd +#define RK817_GPIO_INT_CFG 0xfe + +/* IRQ Definitions */ +#define RK817_IRQ_PWRON_FALL 0 +#define RK817_IRQ_PWRON_RISE 1 +#define RK817_IRQ_PWRON 2 +#define RK817_IRQ_PWMON_LP 3 +#define RK817_IRQ_HOTDIE 4 +#define RK817_IRQ_RTC_ALARM 5 +#define RK817_IRQ_RTC_PERIOD 6 +#define RK817_IRQ_VB_LO 7 +#define RK817_IRQ_PLUG_IN 8 +#define RK817_IRQ_PLUG_OUT 9 +#define RK817_IRQ_CHRG_TERM 10 +#define RK817_IRQ_CHRG_TIME 11 +#define RK817_IRQ_CHRG_TS 12 +#define RK817_IRQ_USB_OV 13 +#define RK817_IRQ_CHRG_IN_CLMP 14 +#define RK817_IRQ_BAT_DIS_ILIM 15 +#define RK817_IRQ_GATE_GPIO 16 +#define RK817_IRQ_TS_GPIO 17 +#define RK817_IRQ_CODEC_PD 18 +#define RK817_IRQ_CODEC_PO 19 +#define RK817_IRQ_CLASSD_MUTE_DONE 20 +#define RK817_IRQ_CLASSD_OCP 21 +#define RK817_IRQ_BAT_OVP 22 +#define RK817_IRQ_CHRG_BAT_HI 23 +#define RK817_IRQ_END (RK817_IRQ_CHRG_BAT_HI + 1) + +/* + * rtc_ctrl 0xd + * same as 808, except bit4 + */ +#define RK817_RTC_CTRL_RSV4 BIT(4) + +/* power config 0xb9 */ +#define RK817_BUCK3_FB_RES_MSK BIT(6) +#define RK817_BUCK3_FB_RES_INTER BIT(6) +#define RK817_BUCK3_FB_RES_EXT 0 + +/* buck config 0xba */ +#define RK817_RAMP_RATE_OFFSET 6 +#define RK817_RAMP_RATE_MASK (0x3 << RK817_RAMP_RATE_OFFSET) +#define RK817_RAMP_RATE_3MV_PER_US (0x0 << RK817_RAMP_RATE_OFFSET) +#define RK817_RAMP_RATE_6_3MV_PER_US (0x1 << RK817_RAMP_RATE_OFFSET) +#define RK817_RAMP_RATE_12_5MV_PER_US (0x2 << RK817_RAMP_RATE_OFFSET) +#define RK817_RAMP_RATE_25MV_PER_US (0x3 << RK817_RAMP_RATE_OFFSET) + +/* sys_cfg1 0xf2 */ +#define RK817_HOTDIE_TEMP_MSK (0x3 << 4) +#define RK817_HOTDIE_85 (0x0 << 4) +#define RK817_HOTDIE_95 (0x1 << 4) +#define RK817_HOTDIE_105 (0x2 << 4) +#define RK817_HOTDIE_115 (0x3 << 4) + +#define RK817_TSD_TEMP_MSK BIT(6) +#define RK817_TSD_140 0 +#define RK817_TSD_160 BIT(6) + +#define RK817_CLK32KOUT2_EN BIT(7) + +/* sys_cfg3 0xf4 */ +#define RK817_SLPPIN_FUNC_MSK (0x3 << 3) +#define SLPPIN_NULL_FUN (0x0 << 3) +#define SLPPIN_SLP_FUN (0x1 << 3) +#define SLPPIN_DN_FUN (0x2 << 3) +#define SLPPIN_RST_FUN (0x3 << 3) + +#define RK817_RST_FUNC_MSK (0x3 << 6) +#define RK817_RST_FUNC_SFT (6) +#define RK817_RST_FUNC_CNT (3) +#define RK817_RST_FUNC_DEV (0) /* reset the dev */ +#define RK817_RST_FUNC_REG (0x1 << 6) /* reset the reg only */ + +#define RK817_SLPPOL_MSK BIT(5) +#define RK817_SLPPOL_H BIT(5) +#define RK817_SLPPOL_L (0) + +/* gpio&int 0xfe */ +#define RK817_INT_POL_MSK BIT(1) +#define RK817_INT_POL_H BIT(1) +#define RK817_INT_POL_L 0 +#define RK809_BUCK5_CONFIG(i) (RK817_BOOST_OTG_CFG + (i) * 1) enum { BUCK_ILMIN_50MA, @@ -435,6 +608,8 @@ enum { enum { RK805_ID = 0x8050, RK808_ID = 0x0000, + RK809_ID = 0x8090, + RK817_ID = 0x8170, RK818_ID = 0x8181, }; @@ -445,5 +620,7 @@ struct rk808 { long variant; const struct regmap_config *regmap_cfg; const struct regmap_irq_chip *regmap_irq_chip; + void (*pm_pwroff_fn)(void); + void (*pm_pwroff_prep_fn)(void); }; #endif /* __LINUX_REGULATOR_RK808_H */ diff --git a/include/linux/mfd/rohm-bd70528.h b/include/linux/mfd/rohm-bd70528.h new file mode 100644 index 000000000000..1013e60c5b25 --- /dev/null +++ b/include/linux/mfd/rohm-bd70528.h @@ -0,0 +1,408 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* Copyright (C) 2018 ROHM Semiconductors */ + +#ifndef __LINUX_MFD_BD70528_H__ +#define __LINUX_MFD_BD70528_H__ + +#include <linux/bits.h> +#include <linux/device.h> +#include <linux/mfd/rohm-generic.h> +#include <linux/regmap.h> + +enum { + BD70528_BUCK1, + BD70528_BUCK2, + BD70528_BUCK3, + BD70528_LDO1, + BD70528_LDO2, + BD70528_LDO3, + BD70528_LED1, + BD70528_LED2, +}; + +struct bd70528_data { + struct rohm_regmap_dev chip; + struct mutex rtc_timer_lock; +}; + +#define BD70528_BUCK_VOLTS 17 +#define BD70528_BUCK_VOLTS 17 +#define BD70528_BUCK_VOLTS 17 +#define BD70528_LDO_VOLTS 0x20 + +#define BD70528_REG_BUCK1_EN 0x0F +#define BD70528_REG_BUCK1_VOLT 0x15 +#define BD70528_REG_BUCK2_EN 0x10 +#define BD70528_REG_BUCK2_VOLT 0x16 +#define BD70528_REG_BUCK3_EN 0x11 +#define BD70528_REG_BUCK3_VOLT 0x17 +#define BD70528_REG_LDO1_EN 0x1b +#define BD70528_REG_LDO1_VOLT 0x1e +#define BD70528_REG_LDO2_EN 0x1c +#define BD70528_REG_LDO2_VOLT 0x1f +#define BD70528_REG_LDO3_EN 0x1d +#define BD70528_REG_LDO3_VOLT 0x20 +#define BD70528_REG_LED_CTRL 0x2b +#define BD70528_REG_LED_VOLT 0x29 +#define BD70528_REG_LED_EN 0x2a + +/* main irq registers */ +#define BD70528_REG_INT_MAIN 0x7E +#define BD70528_REG_INT_MAIN_MASK 0x74 + +/* 'sub irq' registers */ +#define BD70528_REG_INT_SHDN 0x7F +#define BD70528_REG_INT_PWR_FLT 0x80 +#define BD70528_REG_INT_VR_FLT 0x81 +#define BD70528_REG_INT_MISC 0x82 +#define BD70528_REG_INT_BAT1 0x83 +#define BD70528_REG_INT_BAT2 0x84 +#define BD70528_REG_INT_RTC 0x85 +#define BD70528_REG_INT_GPIO 0x86 +#define BD70528_REG_INT_OP_FAIL 0x87 + +#define BD70528_REG_INT_SHDN_MASK 0x75 +#define BD70528_REG_INT_PWR_FLT_MASK 0x76 +#define BD70528_REG_INT_VR_FLT_MASK 0x77 +#define BD70528_REG_INT_MISC_MASK 0x78 +#define BD70528_REG_INT_BAT1_MASK 0x79 +#define BD70528_REG_INT_BAT2_MASK 0x7a +#define BD70528_REG_INT_RTC_MASK 0x7b +#define BD70528_REG_INT_GPIO_MASK 0x7c +#define BD70528_REG_INT_OP_FAIL_MASK 0x7d + +/* Reset related 'magic' registers */ +#define BD70528_REG_SHIPMODE 0x03 +#define BD70528_REG_HWRESET 0x04 +#define BD70528_REG_WARMRESET 0x05 +#define BD70528_REG_STANDBY 0x06 + +/* GPIO registers */ +#define BD70528_REG_GPIO_STATE 0x8F + +#define BD70528_REG_GPIO1_IN 0x4d +#define BD70528_REG_GPIO2_IN 0x4f +#define BD70528_REG_GPIO3_IN 0x51 +#define BD70528_REG_GPIO4_IN 0x53 +#define BD70528_REG_GPIO1_OUT 0x4e +#define BD70528_REG_GPIO2_OUT 0x50 +#define BD70528_REG_GPIO3_OUT 0x52 +#define BD70528_REG_GPIO4_OUT 0x54 + +/* clk control */ + +#define BD70528_REG_CLK_OUT 0x2c + +/* RTC */ + +#define BD70528_REG_RTC_COUNT_H 0x2d +#define BD70528_REG_RTC_COUNT_L 0x2e +#define BD70528_REG_RTC_SEC 0x2f +#define BD70528_REG_RTC_MINUTE 0x30 +#define BD70528_REG_RTC_HOUR 0x31 +#define BD70528_REG_RTC_WEEK 0x32 +#define BD70528_REG_RTC_DAY 0x33 +#define BD70528_REG_RTC_MONTH 0x34 +#define BD70528_REG_RTC_YEAR 0x35 + +#define BD70528_REG_RTC_ALM_SEC 0x36 +#define BD70528_REG_RTC_ALM_START BD70528_REG_RTC_ALM_SEC +#define BD70528_REG_RTC_ALM_MINUTE 0x37 +#define BD70528_REG_RTC_ALM_HOUR 0x38 +#define BD70528_REG_RTC_ALM_WEEK 0x39 +#define BD70528_REG_RTC_ALM_DAY 0x3a +#define BD70528_REG_RTC_ALM_MONTH 0x3b +#define BD70528_REG_RTC_ALM_YEAR 0x3c +#define BD70528_REG_RTC_ALM_MASK 0x3d +#define BD70528_REG_RTC_ALM_REPEAT 0x3e +#define BD70528_REG_RTC_START BD70528_REG_RTC_SEC + +#define BD70528_REG_RTC_WAKE_SEC 0x43 +#define BD70528_REG_RTC_WAKE_START BD70528_REG_RTC_WAKE_SEC +#define BD70528_REG_RTC_WAKE_MIN 0x44 +#define BD70528_REG_RTC_WAKE_HOUR 0x45 +#define BD70528_REG_RTC_WAKE_CTRL 0x46 + +#define BD70528_REG_ELAPSED_TIMER_EN 0x42 +#define BD70528_REG_WAKE_EN 0x46 + +/* WDT registers */ +#define BD70528_REG_WDT_CTRL 0x4A +#define BD70528_REG_WDT_HOUR 0x49 +#define BD70528_REG_WDT_MINUTE 0x48 +#define BD70528_REG_WDT_SEC 0x47 + +/* Charger / Battery */ +#define BD70528_REG_CHG_CURR_STAT 0x59 +#define BD70528_REG_CHG_BAT_STAT 0x57 +#define BD70528_REG_CHG_BAT_TEMP 0x58 +#define BD70528_REG_CHG_IN_STAT 0x56 +#define BD70528_REG_CHG_DCIN_ILIM 0x5d +#define BD70528_REG_CHG_CHG_CURR_WARM 0x61 +#define BD70528_REG_CHG_CHG_CURR_COLD 0x62 + +/* Masks for main IRQ register bits */ +enum { + BD70528_INT_SHDN, +#define BD70528_INT_SHDN_MASK BIT(BD70528_INT_SHDN) + BD70528_INT_PWR_FLT, +#define BD70528_INT_PWR_FLT_MASK BIT(BD70528_INT_PWR_FLT) + BD70528_INT_VR_FLT, +#define BD70528_INT_VR_FLT_MASK BIT(BD70528_INT_VR_FLT) + BD70528_INT_MISC, +#define BD70528_INT_MISC_MASK BIT(BD70528_INT_MISC) + BD70528_INT_BAT1, +#define BD70528_INT_BAT1_MASK BIT(BD70528_INT_BAT1) + BD70528_INT_RTC, +#define BD70528_INT_RTC_MASK BIT(BD70528_INT_RTC) + BD70528_INT_GPIO, +#define BD70528_INT_GPIO_MASK BIT(BD70528_INT_GPIO) + BD70528_INT_OP_FAIL, +#define BD70528_INT_OP_FAIL_MASK BIT(BD70528_INT_OP_FAIL) +}; + +/* IRQs */ +enum { + /* Shutdown register IRQs */ + BD70528_INT_LONGPUSH, + BD70528_INT_WDT, + BD70528_INT_HWRESET, + BD70528_INT_RSTB_FAULT, + BD70528_INT_VBAT_UVLO, + BD70528_INT_TSD, + BD70528_INT_RSTIN, + /* Power failure register IRQs */ + BD70528_INT_BUCK1_FAULT, + BD70528_INT_BUCK2_FAULT, + BD70528_INT_BUCK3_FAULT, + BD70528_INT_LDO1_FAULT, + BD70528_INT_LDO2_FAULT, + BD70528_INT_LDO3_FAULT, + BD70528_INT_LED1_FAULT, + BD70528_INT_LED2_FAULT, + /* VR FAULT register IRQs */ + BD70528_INT_BUCK1_OCP, + BD70528_INT_BUCK2_OCP, + BD70528_INT_BUCK3_OCP, + BD70528_INT_LED1_OCP, + BD70528_INT_LED2_OCP, + BD70528_INT_BUCK1_FULLON, + BD70528_INT_BUCK2_FULLON, + /* PMU register interrupts */ + BD70528_INT_SHORTPUSH, + BD70528_INT_AUTO_WAKEUP, + BD70528_INT_STATE_CHANGE, + /* Charger 1 register IRQs */ + BD70528_INT_BAT_OV_RES, + BD70528_INT_BAT_OV_DET, + BD70528_INT_DBAT_DET, + BD70528_INT_BATTSD_COLD_RES, + BD70528_INT_BATTSD_COLD_DET, + BD70528_INT_BATTSD_HOT_RES, + BD70528_INT_BATTSD_HOT_DET, + BD70528_INT_CHG_TSD, + /* Charger 2 register IRQs */ + BD70528_INT_BAT_RMV, + BD70528_INT_BAT_DET, + BD70528_INT_DCIN2_OV_RES, + BD70528_INT_DCIN2_OV_DET, + BD70528_INT_DCIN2_RMV, + BD70528_INT_DCIN2_DET, + BD70528_INT_DCIN1_RMV, + BD70528_INT_DCIN1_DET, + /* RTC register IRQs */ + BD70528_INT_RTC_ALARM, + BD70528_INT_ELPS_TIM, + /* GPIO register IRQs */ + BD70528_INT_GPIO0, + BD70528_INT_GPIO1, + BD70528_INT_GPIO2, + BD70528_INT_GPIO3, + /* Invalid operation register IRQs */ + BD70528_INT_BUCK1_DVS_OPFAIL, + BD70528_INT_BUCK2_DVS_OPFAIL, + BD70528_INT_BUCK3_DVS_OPFAIL, + BD70528_INT_LED1_VOLT_OPFAIL, + BD70528_INT_LED2_VOLT_OPFAIL, +}; + +/* Masks */ +#define BD70528_INT_LONGPUSH_MASK 0x1 +#define BD70528_INT_WDT_MASK 0x2 +#define BD70528_INT_HWRESET_MASK 0x4 +#define BD70528_INT_RSTB_FAULT_MASK 0x8 +#define BD70528_INT_VBAT_UVLO_MASK 0x10 +#define BD70528_INT_TSD_MASK 0x20 +#define BD70528_INT_RSTIN_MASK 0x40 + +#define BD70528_INT_BUCK1_FAULT_MASK 0x1 +#define BD70528_INT_BUCK2_FAULT_MASK 0x2 +#define BD70528_INT_BUCK3_FAULT_MASK 0x4 +#define BD70528_INT_LDO1_FAULT_MASK 0x8 +#define BD70528_INT_LDO2_FAULT_MASK 0x10 +#define BD70528_INT_LDO3_FAULT_MASK 0x20 +#define BD70528_INT_LED1_FAULT_MASK 0x40 +#define BD70528_INT_LED2_FAULT_MASK 0x80 + +#define BD70528_INT_BUCK1_OCP_MASK 0x1 +#define BD70528_INT_BUCK2_OCP_MASK 0x2 +#define BD70528_INT_BUCK3_OCP_MASK 0x4 +#define BD70528_INT_LED1_OCP_MASK 0x8 +#define BD70528_INT_LED2_OCP_MASK 0x10 +#define BD70528_INT_BUCK1_FULLON_MASK 0x20 +#define BD70528_INT_BUCK2_FULLON_MASK 0x40 + +#define BD70528_INT_SHORTPUSH_MASK 0x1 +#define BD70528_INT_AUTO_WAKEUP_MASK 0x2 +#define BD70528_INT_STATE_CHANGE_MASK 0x10 + +#define BD70528_INT_BAT_OV_RES_MASK 0x1 +#define BD70528_INT_BAT_OV_DET_MASK 0x2 +#define BD70528_INT_DBAT_DET_MASK 0x4 +#define BD70528_INT_BATTSD_COLD_RES_MASK 0x8 +#define BD70528_INT_BATTSD_COLD_DET_MASK 0x10 +#define BD70528_INT_BATTSD_HOT_RES_MASK 0x20 +#define BD70528_INT_BATTSD_HOT_DET_MASK 0x40 +#define BD70528_INT_CHG_TSD_MASK 0x80 + +#define BD70528_INT_BAT_RMV_MASK 0x1 +#define BD70528_INT_BAT_DET_MASK 0x2 +#define BD70528_INT_DCIN2_OV_RES_MASK 0x4 +#define BD70528_INT_DCIN2_OV_DET_MASK 0x8 +#define BD70528_INT_DCIN2_RMV_MASK 0x10 +#define BD70528_INT_DCIN2_DET_MASK 0x20 +#define BD70528_INT_DCIN1_RMV_MASK 0x40 +#define BD70528_INT_DCIN1_DET_MASK 0x80 + +#define BD70528_INT_RTC_ALARM_MASK 0x1 +#define BD70528_INT_ELPS_TIM_MASK 0x2 + +#define BD70528_INT_GPIO0_MASK 0x1 +#define BD70528_INT_GPIO1_MASK 0x2 +#define BD70528_INT_GPIO2_MASK 0x4 +#define BD70528_INT_GPIO3_MASK 0x8 + +#define BD70528_INT_BUCK1_DVS_OPFAIL_MASK 0x1 +#define BD70528_INT_BUCK2_DVS_OPFAIL_MASK 0x2 +#define BD70528_INT_BUCK3_DVS_OPFAIL_MASK 0x4 +#define BD70528_INT_LED1_VOLT_OPFAIL_MASK 0x10 +#define BD70528_INT_LED2_VOLT_OPFAIL_MASK 0x20 + +#define BD70528_DEBOUNCE_MASK 0x3 + +#define BD70528_DEBOUNCE_DISABLE 0 +#define BD70528_DEBOUNCE_15MS 1 +#define BD70528_DEBOUNCE_30MS 2 +#define BD70528_DEBOUNCE_50MS 3 + +#define BD70528_GPIO_DRIVE_MASK 0x2 +#define BD70528_GPIO_PUSH_PULL 0x0 +#define BD70528_GPIO_OPEN_DRAIN 0x2 + +#define BD70528_GPIO_OUT_EN_MASK 0x80 +#define BD70528_GPIO_OUT_ENABLE 0x80 +#define BD70528_GPIO_OUT_DISABLE 0x0 + +#define BD70528_GPIO_OUT_HI 0x1 +#define BD70528_GPIO_OUT_LO 0x0 +#define BD70528_GPIO_OUT_MASK 0x1 + +#define BD70528_GPIO_IN_STATE_BASE 1 + +#define BD70528_CLK_OUT_EN_MASK 0x1 + +/* RTC masks to mask out reserved bits */ + +#define BD70528_MASK_RTC_SEC 0x7f +#define BD70528_MASK_RTC_MINUTE 0x7f +#define BD70528_MASK_RTC_HOUR_24H 0x80 +#define BD70528_MASK_RTC_HOUR_PM 0x20 +#define BD70528_MASK_RTC_HOUR 0x1f +#define BD70528_MASK_RTC_DAY 0x3f +#define BD70528_MASK_RTC_WEEK 0x07 +#define BD70528_MASK_RTC_MONTH 0x1f +#define BD70528_MASK_RTC_YEAR 0xff +#define BD70528_MASK_RTC_COUNT_L 0x7f + +#define BD70528_MASK_ELAPSED_TIMER_EN 0x1 +/* Mask second, min and hour fields + * HW would support ALM irq for over 24h + * (by setting day, month and year too) + * but as we wish to keep this same as for + * wake-up we limit ALM to 24H and only + * unmask sec, min and hour + */ +#define BD70528_MASK_ALM_EN 0x7 +#define BD70528_MASK_WAKE_EN 0x1 + +/* WDT masks */ +#define BD70528_MASK_WDT_EN 0x1 +#define BD70528_MASK_WDT_HOUR 0x1 +#define BD70528_MASK_WDT_MINUTE 0x7f +#define BD70528_MASK_WDT_SEC 0x7f + +#define BD70528_WDT_STATE_BIT 0x1 +#define BD70528_ELAPSED_STATE_BIT 0x2 +#define BD70528_WAKE_STATE_BIT 0x4 + +/* Charger masks */ +#define BD70528_MASK_CHG_STAT 0x7f +#define BD70528_MASK_CHG_BAT_TIMER 0x20 +#define BD70528_MASK_CHG_BAT_OVERVOLT 0x10 +#define BD70528_MASK_CHG_BAT_DETECT 0x1 +#define BD70528_MASK_CHG_DCIN1_UVLO 0x1 +#define BD70528_MASK_CHG_DCIN_ILIM 0x3f +#define BD70528_MASK_CHG_CHG_CURR 0x1f +#define BD70528_MASK_CHG_TRICKLE_CURR 0x10 + +/* + * Note, external battery register is the lonely rider at + * address 0xc5. See how to stuff that in the regmap + */ +#define BD70528_MAX_REGISTER 0x94 + +/* Buck control masks */ +#define BD70528_MASK_RUN_EN 0x4 +#define BD70528_MASK_STBY_EN 0x2 +#define BD70528_MASK_IDLE_EN 0x1 +#define BD70528_MASK_LED1_EN 0x1 +#define BD70528_MASK_LED2_EN 0x10 + +#define BD70528_MASK_BUCK_VOLT 0xf +#define BD70528_MASK_LDO_VOLT 0x1f +#define BD70528_MASK_LED1_VOLT 0x1 +#define BD70528_MASK_LED2_VOLT 0x10 + +/* Misc irq masks */ +#define BD70528_INT_MASK_SHORT_PUSH 1 +#define BD70528_INT_MASK_AUTO_WAKE 2 +#define BD70528_INT_MASK_POWER_STATE 4 + +#define BD70528_MASK_BUCK_RAMP 0x10 +#define BD70528_SIFT_BUCK_RAMP 4 + +#if IS_ENABLED(CONFIG_BD70528_WATCHDOG) + +int bd70528_wdt_set(struct rohm_regmap_dev *data, int enable, int *old_state); +void bd70528_wdt_lock(struct rohm_regmap_dev *data); +void bd70528_wdt_unlock(struct rohm_regmap_dev *data); + +#else /* CONFIG_BD70528_WATCHDOG */ + +static inline int bd70528_wdt_set(struct rohm_regmap_dev *data, int enable, + int *old_state) +{ + return 0; +} + +static inline void bd70528_wdt_lock(struct rohm_regmap_dev *data) +{ +} + +static inline void bd70528_wdt_unlock(struct rohm_regmap_dev *data) +{ +} + +#endif /* CONFIG_BD70528_WATCHDOG */ + +#endif /* __LINUX_MFD_BD70528_H__ */ diff --git a/include/linux/mfd/rohm-bd718x7.h b/include/linux/mfd/rohm-bd718x7.h index fd194bfc836f..7f2dbde402a1 100644 --- a/include/linux/mfd/rohm-bd718x7.h +++ b/include/linux/mfd/rohm-bd718x7.h @@ -4,15 +4,10 @@ #ifndef __LINUX_MFD_BD718XX_H__ #define __LINUX_MFD_BD718XX_H__ +#include <linux/mfd/rohm-generic.h> #include <linux/regmap.h> enum { - BD718XX_TYPE_BD71837 = 0, - BD718XX_TYPE_BD71847, - BD718XX_TYPE_AMOUNT -}; - -enum { BD718XX_BUCK1 = 0, BD718XX_BUCK2, BD718XX_BUCK3, @@ -321,18 +316,17 @@ enum { BD718XX_PWRBTN_LONG_PRESS_15S }; -struct bd718xx_clk; - struct bd718xx { - unsigned int chip_type; - struct device *dev; - struct regmap *regmap; - unsigned long int id; + /* + * Please keep this as the first member here as some + * drivers (clk) supporting more than one chip may only know this + * generic struct 'struct rohm_regmap_dev' and assume it is + * the first chunk of parent device's private data. + */ + struct rohm_regmap_dev chip; int chip_irq; struct regmap_irq_chip_data *irq_data; - - struct bd718xx_clk *clk; }; #endif /* __LINUX_MFD_BD718XX_H__ */ diff --git a/include/linux/mfd/rohm-generic.h b/include/linux/mfd/rohm-generic.h new file mode 100644 index 000000000000..bff15ac26f2c --- /dev/null +++ b/include/linux/mfd/rohm-generic.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* Copyright (C) 2018 ROHM Semiconductors */ + +#ifndef __LINUX_MFD_ROHM_H__ +#define __LINUX_MFD_ROHM_H__ + +enum { + ROHM_CHIP_TYPE_BD71837 = 0, + ROHM_CHIP_TYPE_BD71847, + ROHM_CHIP_TYPE_BD70528, + ROHM_CHIP_TYPE_AMOUNT +}; + +struct rohm_regmap_dev { + unsigned int chip_type; + struct device *dev; + struct regmap *regmap; +}; + +#endif diff --git a/include/linux/mfd/samsung/core.h b/include/linux/mfd/samsung/core.h index 3ca17eb89aa2..f1631a39acfc 100644 --- a/include/linux/mfd/samsung/core.h +++ b/include/linux/mfd/samsung/core.h @@ -20,6 +20,7 @@ #define MIN_850_MV 850000 #define MIN_800_MV 800000 #define MIN_750_MV 750000 +#define MIN_650_MV 650000 #define MIN_600_MV 600000 #define MIN_500_MV 500000 diff --git a/include/linux/mfd/samsung/s2mps11.h b/include/linux/mfd/samsung/s2mps11.h index 6e7668a389a1..4805c90609c4 100644 --- a/include/linux/mfd/samsung/s2mps11.h +++ b/include/linux/mfd/samsung/s2mps11.h @@ -170,7 +170,9 @@ enum s2mps11_regulators { #define S2MPS11_ENABLE_MASK (0x03 << S2MPS11_ENABLE_SHIFT) #define S2MPS11_ENABLE_SHIFT 0x06 #define S2MPS11_LDO_N_VOLTAGES (S2MPS11_LDO_VSEL_MASK + 1) -#define S2MPS11_BUCK_N_VOLTAGES (S2MPS11_BUCK_VSEL_MASK + 1) +#define S2MPS11_BUCK12346_N_VOLTAGES 153 +#define S2MPS11_BUCK5_N_VOLTAGES 216 +#define S2MPS11_BUCK7810_N_VOLTAGES 225 #define S2MPS11_BUCK9_N_VOLTAGES (S2MPS11_BUCK9_VSEL_MASK + 1) #define S2MPS11_RAMP_DELAY 25000 /* uV/us */ @@ -188,4 +190,9 @@ enum s2mps11_regulators { #define S2MPS11_BUCK6_RAMP_EN_SHIFT 0 #define S2MPS11_PMIC_EN_SHIFT 6 +/* + * Bits for "enable suspend" (On/Off controlled by PWREN) + * are the same as in S2MPS14: S2MPS14_ENABLE_SUSPEND + */ + #endif /* __LINUX_MFD_S2MPS11_H */ diff --git a/include/linux/mfd/stmfx.h b/include/linux/mfd/stmfx.h index d890595b89b6..3c67983678ec 100644 --- a/include/linux/mfd/stmfx.h +++ b/include/linux/mfd/stmfx.h @@ -5,7 +5,7 @@ */ #ifndef MFD_STMFX_H -#define MFX_STMFX_H +#define MFD_STMFX_H #include <linux/regmap.h> diff --git a/include/linux/mfd/syscon.h b/include/linux/mfd/syscon.h index f0273c9e972b..112dc66262cc 100644 --- a/include/linux/mfd/syscon.h +++ b/include/linux/mfd/syscon.h @@ -17,24 +17,24 @@ struct device_node; #ifdef CONFIG_MFD_SYSCON +extern struct regmap *device_node_to_regmap(struct device_node *np); extern struct regmap *syscon_node_to_regmap(struct device_node *np); extern struct regmap *syscon_regmap_lookup_by_compatible(const char *s); -extern struct regmap *syscon_regmap_lookup_by_pdevname(const char *s); extern struct regmap *syscon_regmap_lookup_by_phandle( struct device_node *np, const char *property); #else -static inline struct regmap *syscon_node_to_regmap(struct device_node *np) +static inline struct regmap *device_node_to_regmap(struct device_node *np) { return ERR_PTR(-ENOTSUPP); } -static inline struct regmap *syscon_regmap_lookup_by_compatible(const char *s) +static inline struct regmap *syscon_node_to_regmap(struct device_node *np) { return ERR_PTR(-ENOTSUPP); } -static inline struct regmap *syscon_regmap_lookup_by_pdevname(const char *s) +static inline struct regmap *syscon_regmap_lookup_by_compatible(const char *s) { return ERR_PTR(-ENOTSUPP); } diff --git a/include/linux/mfd/ti-lmu-register.h b/include/linux/mfd/ti-lmu-register.h index 222cb14c5b0f..116a749e0302 100644 --- a/include/linux/mfd/ti-lmu-register.h +++ b/include/linux/mfd/ti-lmu-register.h @@ -187,47 +187,26 @@ #define LM3695_MAX_REG 0x14 -/* LM3697 */ -#define LM3697_REG_HVLED_OUTPUT_CFG 0x10 -#define LM3697_HVLED1_CFG_MASK BIT(0) -#define LM3697_HVLED2_CFG_MASK BIT(1) -#define LM3697_HVLED3_CFG_MASK BIT(2) -#define LM3697_HVLED1_CFG_SHIFT 0 -#define LM3697_HVLED2_CFG_SHIFT 1 -#define LM3697_HVLED3_CFG_SHIFT 2 +/* LM36274 */ +#define LM36274_REG_REV 0x01 +#define LM36274_REG_BL_CFG_1 0x02 +#define LM36274_REG_BL_CFG_2 0x03 +#define LM36274_REG_BRT_LSB 0x04 +#define LM36274_REG_BRT_MSB 0x05 +#define LM36274_REG_BL_EN 0x08 + +#define LM36274_REG_BIAS_CONFIG_1 0x09 +#define LM36274_EXT_EN_MASK BIT(0) +#define LM36274_EN_VNEG_MASK BIT(1) +#define LM36274_EN_VPOS_MASK BIT(2) + +#define LM36274_REG_BIAS_CONFIG_2 0x0a +#define LM36274_REG_BIAS_CONFIG_3 0x0b +#define LM36274_REG_VOUT_BOOST 0x0c +#define LM36274_REG_VOUT_POS 0x0d +#define LM36274_REG_VOUT_NEG 0x0e +#define LM36274_VOUT_MASK 0x3F + +#define LM36274_MAX_REG 0x13 -#define LM3697_REG_BL0_RAMP 0x11 -#define LM3697_REG_BL1_RAMP 0x12 -#define LM3697_RAMPUP_MASK 0xF0 -#define LM3697_RAMPUP_SHIFT 4 -#define LM3697_RAMPDN_MASK 0x0F -#define LM3697_RAMPDN_SHIFT 0 - -#define LM3697_REG_RAMP_CONF 0x14 -#define LM3697_RAMP_MASK 0x0F -#define LM3697_RAMP_EACH 0x05 - -#define LM3697_REG_PWM_CFG 0x1C -#define LM3697_PWM_A_MASK BIT(0) -#define LM3697_PWM_B_MASK BIT(1) - -#define LM3697_REG_IMAX_A 0x17 -#define LM3697_REG_IMAX_B 0x18 - -#define LM3697_REG_FEEDBACK_ENABLE 0x19 - -#define LM3697_REG_BRT_A_LSB 0x20 -#define LM3697_REG_BRT_A_MSB 0x21 -#define LM3697_REG_BRT_B_LSB 0x22 -#define LM3697_REG_BRT_B_MSB 0x23 - -#define LM3697_REG_ENABLE 0x24 - -#define LM3697_REG_OPEN_FAULT_STATUS 0xB0 - -#define LM3697_REG_SHORT_FAULT_STATUS 0xB2 - -#define LM3697_REG_MONITOR_ENABLE 0xB4 - -#define LM3697_MAX_REG 0xB4 #endif diff --git a/include/linux/mfd/ti-lmu.h b/include/linux/mfd/ti-lmu.h index 7d1e9c24f818..0bc0e8199798 100644 --- a/include/linux/mfd/ti-lmu.h +++ b/include/linux/mfd/ti-lmu.h @@ -23,7 +23,7 @@ enum ti_lmu_id { LM3632, LM3633, LM3695, - LM3697, + LM36274, LMU_MAX_ID, }; @@ -65,6 +65,9 @@ enum lm363x_regulator_id { LM3632_BOOST, /* Boost output */ LM3632_LDO_POS, /* Positive display bias output */ LM3632_LDO_NEG, /* Negative display bias output */ + LM36274_BOOST, /* Boost output */ + LM36274_LDO_POS, /* Positive display bias output */ + LM36274_LDO_NEG, /* Negative display bias output */ }; /** diff --git a/include/linux/mfd/wm831x/pdata.h b/include/linux/mfd/wm831x/pdata.h index 071cdf3e16cf..986986fe4e4e 100644 --- a/include/linux/mfd/wm831x/pdata.h +++ b/include/linux/mfd/wm831x/pdata.h @@ -47,7 +47,6 @@ struct wm831x_battery_pdata { * I2C or SPI buses. */ struct wm831x_buckv_pdata { - int dvs_gpio; /** CPU GPIO to use for DVS switching */ int dvs_control_src; /** Hardware DVS source to use (1 or 2) */ int dvs_init_state; /** DVS state to expect on startup */ int dvs_state_gpio; /** CPU GPIO to use for monitoring status */ diff --git a/include/linux/migrate.h b/include/linux/migrate.h index e13d9bf2f9a5..72120061b7d4 100644 --- a/include/linux/migrate.h +++ b/include/linux/migrate.h @@ -77,8 +77,7 @@ extern void migrate_page_copy(struct page *newpage, struct page *page); extern int migrate_huge_page_move_mapping(struct address_space *mapping, struct page *newpage, struct page *page); extern int migrate_page_move_mapping(struct address_space *mapping, - struct page *newpage, struct page *page, enum migrate_mode mode, - int extra_count); + struct page *newpage, struct page *page, int extra_count); #else static inline void putback_movable_pages(struct list_head *l) {} @@ -167,8 +166,6 @@ static inline int migrate_misplaced_transhuge_page(struct mm_struct *mm, #define MIGRATE_PFN_MIGRATE (1UL << 1) #define MIGRATE_PFN_LOCKED (1UL << 2) #define MIGRATE_PFN_WRITE (1UL << 3) -#define MIGRATE_PFN_DEVICE (1UL << 4) -#define MIGRATE_PFN_ERROR (1UL << 5) #define MIGRATE_PFN_SHIFT 6 static inline struct page *migrate_pfn_to_page(unsigned long mpfn) @@ -183,107 +180,27 @@ static inline unsigned long migrate_pfn(unsigned long pfn) return (pfn << MIGRATE_PFN_SHIFT) | MIGRATE_PFN_VALID; } -/* - * struct migrate_vma_ops - migrate operation callback - * - * @alloc_and_copy: alloc destination memory and copy source memory to it - * @finalize_and_map: allow caller to map the successfully migrated pages - * - * - * The alloc_and_copy() callback happens once all source pages have been locked, - * unmapped and checked (checked whether pinned or not). All pages that can be - * migrated will have an entry in the src array set with the pfn value of the - * page and with the MIGRATE_PFN_VALID and MIGRATE_PFN_MIGRATE flag set (other - * flags might be set but should be ignored by the callback). - * - * The alloc_and_copy() callback can then allocate destination memory and copy - * source memory to it for all those entries (ie with MIGRATE_PFN_VALID and - * MIGRATE_PFN_MIGRATE flag set). Once these are allocated and copied, the - * callback must update each corresponding entry in the dst array with the pfn - * value of the destination page and with the MIGRATE_PFN_VALID and - * MIGRATE_PFN_LOCKED flags set (destination pages must have their struct pages - * locked, via lock_page()). - * - * At this point the alloc_and_copy() callback is done and returns. - * - * Note that the callback does not have to migrate all the pages that are - * marked with MIGRATE_PFN_MIGRATE flag in src array unless this is a migration - * from device memory to system memory (ie the MIGRATE_PFN_DEVICE flag is also - * set in the src array entry). If the device driver cannot migrate a device - * page back to system memory, then it must set the corresponding dst array - * entry to MIGRATE_PFN_ERROR. This will trigger a SIGBUS if CPU tries to - * access any of the virtual addresses originally backed by this page. Because - * a SIGBUS is such a severe result for the userspace process, the device - * driver should avoid setting MIGRATE_PFN_ERROR unless it is really in an - * unrecoverable state. - * - * For empty entry inside CPU page table (pte_none() or pmd_none() is true) we - * do set MIGRATE_PFN_MIGRATE flag inside the corresponding source array thus - * allowing device driver to allocate device memory for those unback virtual - * address. For this the device driver simply have to allocate device memory - * and properly set the destination entry like for regular migration. Note that - * this can still fails and thus inside the device driver must check if the - * migration was successful for those entry inside the finalize_and_map() - * callback just like for regular migration. - * - * THE alloc_and_copy() CALLBACK MUST NOT CHANGE ANY OF THE SRC ARRAY ENTRIES - * OR BAD THINGS WILL HAPPEN ! - * - * - * The finalize_and_map() callback happens after struct page migration from - * source to destination (destination struct pages are the struct pages for the - * memory allocated by the alloc_and_copy() callback). Migration can fail, and - * thus the finalize_and_map() allows the driver to inspect which pages were - * successfully migrated, and which were not. Successfully migrated pages will - * have the MIGRATE_PFN_MIGRATE flag set for their src array entry. - * - * It is safe to update device page table from within the finalize_and_map() - * callback because both destination and source page are still locked, and the - * mmap_sem is held in read mode (hence no one can unmap the range being - * migrated). - * - * Once callback is done cleaning up things and updating its page table (if it - * chose to do so, this is not an obligation) then it returns. At this point, - * the HMM core will finish up the final steps, and the migration is complete. - * - * THE finalize_and_map() CALLBACK MUST NOT CHANGE ANY OF THE SRC OR DST ARRAY - * ENTRIES OR BAD THINGS WILL HAPPEN ! - */ -struct migrate_vma_ops { - void (*alloc_and_copy)(struct vm_area_struct *vma, - const unsigned long *src, - unsigned long *dst, - unsigned long start, - unsigned long end, - void *private); - void (*finalize_and_map)(struct vm_area_struct *vma, - const unsigned long *src, - const unsigned long *dst, - unsigned long start, - unsigned long end, - void *private); +struct migrate_vma { + struct vm_area_struct *vma; + /* + * Both src and dst array must be big enough for + * (end - start) >> PAGE_SHIFT entries. + * + * The src array must not be modified by the caller after + * migrate_vma_setup(), and must not change the dst array after + * migrate_vma_pages() returns. + */ + unsigned long *dst; + unsigned long *src; + unsigned long cpages; + unsigned long npages; + unsigned long start; + unsigned long end; }; -#if defined(CONFIG_MIGRATE_VMA_HELPER) -int migrate_vma(const struct migrate_vma_ops *ops, - struct vm_area_struct *vma, - unsigned long start, - unsigned long end, - unsigned long *src, - unsigned long *dst, - void *private); -#else -static inline int migrate_vma(const struct migrate_vma_ops *ops, - struct vm_area_struct *vma, - unsigned long start, - unsigned long end, - unsigned long *src, - unsigned long *dst, - void *private) -{ - return -EINVAL; -} -#endif /* IS_ENABLED(CONFIG_MIGRATE_VMA_HELPER) */ +int migrate_vma_setup(struct migrate_vma *args); +void migrate_vma_pages(struct migrate_vma *migrate); +void migrate_vma_finalize(struct migrate_vma *migrate); #endif /* CONFIG_MIGRATION */ diff --git a/include/linux/mlx5/accel.h b/include/linux/mlx5/accel.h index 70e7e5673ce9..5613e677a5f9 100644 --- a/include/linux/mlx5/accel.h +++ b/include/linux/mlx5/accel.h @@ -114,7 +114,7 @@ enum mlx5_accel_ipsec_cap { MLX5_ACCEL_IPSEC_CAP_TX_IV_IS_ESN = 1 << 7, }; -#ifdef CONFIG_MLX5_ACCEL +#ifdef CONFIG_MLX5_FPGA_IPSEC u32 mlx5_accel_ipsec_device_caps(struct mlx5_core_dev *mdev); diff --git a/include/linux/mlx5/cq.h b/include/linux/mlx5/cq.h index 769326ea1d9b..40748fc1b11b 100644 --- a/include/linux/mlx5/cq.h +++ b/include/linux/mlx5/cq.h @@ -47,7 +47,7 @@ struct mlx5_core_cq { struct completion free; unsigned vector; unsigned int irqn; - void (*comp) (struct mlx5_core_cq *); + void (*comp)(struct mlx5_core_cq *cq, struct mlx5_eqe *eqe); void (*event) (struct mlx5_core_cq *, enum mlx5_event); u32 cons_index; unsigned arm_sn; @@ -55,7 +55,7 @@ struct mlx5_core_cq { int pid; struct { struct list_head list; - void (*comp)(struct mlx5_core_cq *); + void (*comp)(struct mlx5_core_cq *cq, struct mlx5_eqe *eqe); void *priv; } tasklet_ctx; int reset_notify_added; @@ -185,7 +185,7 @@ static inline void mlx5_cq_put(struct mlx5_core_cq *cq) } int mlx5_core_create_cq(struct mlx5_core_dev *dev, struct mlx5_core_cq *cq, - u32 *in, int inlen); + u32 *in, int inlen, u32 *out, int outlen); int mlx5_core_destroy_cq(struct mlx5_core_dev *dev, struct mlx5_core_cq *cq); int mlx5_core_query_cq(struct mlx5_core_dev *dev, struct mlx5_core_cq *cq, u32 *out, int outlen); diff --git a/include/linux/mlx5/device.h b/include/linux/mlx5/device.h index fc2b6e807f06..cc1c230f10ee 100644 --- a/include/linux/mlx5/device.h +++ b/include/linux/mlx5/device.h @@ -328,6 +328,7 @@ enum mlx5_event { MLX5_EVENT_TYPE_GPIO_EVENT = 0x15, MLX5_EVENT_TYPE_PORT_MODULE_EVENT = 0x16, MLX5_EVENT_TYPE_TEMP_WARN_EVENT = 0x17, + MLX5_EVENT_TYPE_XRQ_ERROR = 0x18, MLX5_EVENT_TYPE_REMOTE_CONFIG = 0x19, MLX5_EVENT_TYPE_GENERAL_EVENT = 0x22, MLX5_EVENT_TYPE_MONITOR_COUNTER = 0x24, @@ -342,16 +343,17 @@ enum mlx5_event { MLX5_EVENT_TYPE_PAGE_FAULT = 0xc, MLX5_EVENT_TYPE_NIC_VPORT_CHANGE = 0xd, - MLX5_EVENT_TYPE_HOST_PARAMS_CHANGE = 0xe, + MLX5_EVENT_TYPE_ESW_FUNCTIONS_CHANGED = 0xe, MLX5_EVENT_TYPE_DCT_DRAINED = 0x1c, + MLX5_EVENT_TYPE_DCT_KEY_VIOLATION = 0x1d, MLX5_EVENT_TYPE_FPGA_ERROR = 0x20, MLX5_EVENT_TYPE_FPGA_QP_ERROR = 0x21, MLX5_EVENT_TYPE_DEVICE_TRACER = 0x26, - MLX5_EVENT_TYPE_MAX = MLX5_EVENT_TYPE_DEVICE_TRACER + 1, + MLX5_EVENT_TYPE_MAX = 0x100, }; enum { @@ -437,6 +439,7 @@ enum { MLX5_OPCODE_SET_PSV = 0x20, MLX5_OPCODE_GET_PSV = 0x21, MLX5_OPCODE_CHECK_PSV = 0x22, + MLX5_OPCODE_DUMP = 0x23, MLX5_OPCODE_RGET_PSV = 0x26, MLX5_OPCODE_RCHECK_PSV = 0x27, @@ -445,6 +448,14 @@ enum { }; enum { + MLX5_OPC_MOD_TLS_TIS_STATIC_PARAMS = 0x1, +}; + +enum { + MLX5_OPC_MOD_TLS_TIS_PROGRESS_PARAMS = 0x1, +}; + +enum { MLX5_SET_PORT_RESET_QKEY = 0, MLX5_SET_PORT_GUID0 = 16, MLX5_SET_PORT_NODE_GUID = 17, @@ -510,6 +521,10 @@ struct mlx5_cmd_layout { u8 status_own; }; +enum mlx5_fatal_assert_bit_offsets { + MLX5_RFR_OFFSET = 31, +}; + struct health_buffer { __be32 assert_var[5]; __be32 rsvd0[3]; @@ -518,12 +533,16 @@ struct health_buffer { __be32 rsvd1[2]; __be32 fw_ver; __be32 hw_id; - __be32 rsvd2; + __be32 rfr; u8 irisc_index; u8 synd; __be16 ext_synd; }; +enum mlx5_initializing_bit_offsets { + MLX5_FW_RESET_SUPPORTED_OFFSET = 30, +}; + enum mlx5_cmd_addr_l_sz_offset { MLX5_NIC_IFC_OFFSET = 8, }; @@ -567,6 +586,12 @@ struct mlx5_eqe_cq_err { u8 syndrome; }; +struct mlx5_eqe_xrq_err { + __be32 reserved1[5]; + __be32 type_xrqn; + __be32 reserved2; +}; + struct mlx5_eqe_port_state { u8 reserved0[8]; u8 port; @@ -681,6 +706,7 @@ union ev_data { struct mlx5_eqe_pps pps; struct mlx5_eqe_dct dct; struct mlx5_eqe_temp_warning temp_warning; + struct mlx5_eqe_xrq_err xrq_err; } __packed; struct mlx5_eqe { @@ -1077,6 +1103,9 @@ enum mlx5_cap_type { MLX5_CAP_DEBUG, MLX5_CAP_RESERVED_14, MLX5_CAP_DEV_MEM, + MLX5_CAP_RESERVED_16, + MLX5_CAP_TLS, + MLX5_CAP_DEV_EVENT = 0x14, /* NUM OF CAP Types */ MLX5_CAP_NUM }; @@ -1142,6 +1171,9 @@ enum mlx5_qcam_feature_groups { #define MLX5_CAP_FLOWTABLE(mdev, cap) \ MLX5_GET(flow_table_nic_cap, mdev->caps.hca_cur[MLX5_CAP_FLOW_TABLE], cap) +#define MLX5_CAP64_FLOWTABLE(mdev, cap) \ + MLX5_GET64(flow_table_nic_cap, (mdev)->caps.hca_cur[MLX5_CAP_FLOW_TABLE], cap) + #define MLX5_CAP_FLOWTABLE_MAX(mdev, cap) \ MLX5_GET(flow_table_nic_cap, mdev->caps.hca_max[MLX5_CAP_FLOW_TABLE], cap) @@ -1205,6 +1237,10 @@ enum mlx5_qcam_feature_groups { MLX5_GET(e_switch_cap, \ mdev->caps.hca_cur[MLX5_CAP_ESWITCH], cap) +#define MLX5_CAP64_ESW_FLOWTABLE(mdev, cap) \ + MLX5_GET64(flow_table_eswitch_cap, \ + (mdev)->caps.hca_cur[MLX5_CAP_ESWITCH_FLOW_TABLE], cap) + #define MLX5_CAP_ESW_MAX(mdev, cap) \ MLX5_GET(e_switch_cap, \ mdev->caps.hca_max[MLX5_CAP_ESWITCH], cap) @@ -1255,6 +1291,12 @@ enum mlx5_qcam_feature_groups { #define MLX5_CAP64_DEV_MEM(mdev, cap)\ MLX5_GET64(device_mem_cap, mdev->caps.hca_cur[MLX5_CAP_DEV_MEM], cap) +#define MLX5_CAP_TLS(mdev, cap) \ + MLX5_GET(tls_cap, (mdev)->caps.hca_cur[MLX5_CAP_TLS], cap) + +#define MLX5_CAP_DEV_EVENT(mdev, cap)\ + MLX5_ADDR_OF(device_event_cap, (mdev)->caps.hca_cur[MLX5_CAP_DEV_EVENT], cap) + enum { MLX5_CMD_STAT_OK = 0x0, MLX5_CMD_STAT_INT_ERR = 0x1, @@ -1283,6 +1325,7 @@ enum { MLX5_PER_PRIORITY_COUNTERS_GROUP = 0x10, MLX5_PER_TRAFFIC_CLASS_COUNTERS_GROUP = 0x11, MLX5_PHYSICAL_LAYER_COUNTERS_GROUP = 0x12, + MLX5_PER_TRAFFIC_CLASS_CONGESTION_GROUP = 0x13, MLX5_PHYSICAL_LAYER_STATISTICAL_GROUP = 0x16, MLX5_INFINIBAND_PORT_COUNTERS_GROUP = 0x20, }; diff --git a/include/linux/mlx5/driver.h b/include/linux/mlx5/driver.h index 5a27246db883..3e80f03a387f 100644 --- a/include/linux/mlx5/driver.h +++ b/include/linux/mlx5/driver.h @@ -41,18 +41,20 @@ #include <linux/semaphore.h> #include <linux/slab.h> #include <linux/vmalloc.h> -#include <linux/radix-tree.h> +#include <linux/xarray.h> #include <linux/workqueue.h> #include <linux/mempool.h> #include <linux/interrupt.h> #include <linux/idr.h> #include <linux/notifier.h> +#include <linux/refcount.h> #include <linux/mlx5/device.h> #include <linux/mlx5/doorbell.h> #include <linux/mlx5/eq.h> #include <linux/timecounter.h> #include <linux/ptp_clock_kernel.h> +#include <net/devlink.h> enum { MLX5_BOARD_ID_LEN = 64, @@ -107,6 +109,7 @@ enum { MLX5_REG_FPGA_CAP = 0x4022, MLX5_REG_FPGA_CTRL = 0x4023, MLX5_REG_FPGA_ACCESS_REG = 0x4024, + MLX5_REG_CORE_DUMP = 0x402e, MLX5_REG_PCAP = 0x5001, MLX5_REG_PMTU = 0x5003, MLX5_REG_PTYS = 0x5004, @@ -137,6 +140,7 @@ enum { MLX5_REG_MTPPS = 0x9053, MLX5_REG_MTPPSE = 0x9054, MLX5_REG_MPEGC = 0x9056, + MLX5_REG_MCQS = 0x9060, MLX5_REG_MCQI = 0x9061, MLX5_REG_MCC = 0x9062, MLX5_REG_MCDA = 0x9063, @@ -180,8 +184,12 @@ enum port_state_policy { MLX5_POLICY_INVALID = 0xffffffff }; +enum mlx5_coredev_type { + MLX5_COREDEV_PF, + MLX5_COREDEV_VF +}; + struct mlx5_field_desc { - struct dentry *dent; int i; }; @@ -234,11 +242,6 @@ struct mlx5_cmd_msg { struct mlx5_cmd_debug { struct dentry *dbg_root; - struct dentry *dbg_in; - struct dentry *dbg_out; - struct dentry *dbg_outlen; - struct dentry *dbg_status; - struct dentry *dbg_run; void *in_msg; void *out_msg; u8 status; @@ -263,8 +266,6 @@ struct mlx5_cmd_stats { u64 sum; u64 n; struct dentry *root; - struct dentry *avg; - struct dentry *count; /* protect command average calculations */ spinlock_t lock; }; @@ -390,7 +391,7 @@ enum mlx5_res_type { struct mlx5_core_rsc_common { enum mlx5_res_type res; - atomic_t refcount; + refcount_t refcount; struct completion free; }; @@ -433,13 +434,18 @@ struct mlx5_core_health { struct timer_list timer; u32 prev; int miss_counter; - bool sick; + u8 synd; + u32 fatal_error; + u32 crdump_size; /* wq spinlock to synchronize draining */ spinlock_t wq_lock; struct workqueue_struct *wq; unsigned long flags; - struct work_struct work; + struct work_struct fatal_report_work; + struct work_struct report_work; struct delayed_work recover_work; + struct devlink_health_reporter *fw_reporter; + struct devlink_health_reporter *fw_fatal_reporter; }; struct mlx5_qp_table { @@ -451,13 +457,6 @@ struct mlx5_qp_table { struct radix_tree_root tree; }; -struct mlx5_mkey_table { - /* protect radix tree - */ - rwlock_t lock; - struct radix_tree_root tree; -}; - struct mlx5_vf_context { int enabled; u64 port_guid; @@ -468,7 +467,18 @@ struct mlx5_vf_context { struct mlx5_core_sriov { struct mlx5_vf_context *vfs_ctx; int num_vfs; - int enabled_vfs; + u16 max_vfs; +}; + +struct mlx5_fc_pool { + struct mlx5_core_dev *dev; + struct mutex pool_lock; /* protects pool lists */ + struct list_head fully_used; + struct list_head partially_used; + struct list_head unused; + int available_fcs; + int used_fcs; + int threshold; }; struct mlx5_fc_stats { @@ -482,6 +492,8 @@ struct mlx5_fc_stats { struct delayed_work work; unsigned long next_query; unsigned long sampling_interval; /* jiffies */ + u32 *bulk_query_out; + struct mlx5_fc_pool fc_pool; }; struct mlx5_events; @@ -490,6 +502,7 @@ struct mlx5_eswitch; struct mlx5_lag; struct mlx5_devcom; struct mlx5_eq_table; +struct mlx5_irq_table; struct mlx5_rate_limit { u32 rate; @@ -519,6 +532,8 @@ struct mlx5_core_roce { }; struct mlx5_priv { + /* IRQ table valid only for real pci devices PF or VF */ + struct mlx5_irq_table *irq_table; struct mlx5_eq_table *eq_table; /* pages stuff */ @@ -541,9 +556,7 @@ struct mlx5_priv { struct dentry *cmdif_debugfs; /* end: qp staff */ - /* start: mkey staff */ - struct mlx5_mkey_table mkey_table; - /* end: mkey staff */ + struct xarray mkey_table; /* start: alloc staff */ /* protect buffer alocation according to numa node */ @@ -570,7 +583,6 @@ struct mlx5_priv { struct mlx5_core_sriov sriov; struct mlx5_lag *lag; struct mlx5_devcom *devcom; - unsigned long pci_dev_data; struct mlx5_core_roce roce; struct mlx5_fc_stats fc_stats; struct mlx5_rl_table rl_table; @@ -580,6 +592,7 @@ struct mlx5_priv { }; enum mlx5_device_state { + MLX5_DEVICE_STATE_UNINITIALIZED, MLX5_DEVICE_STATE_UP, MLX5_DEVICE_STATE_INTERNAL_ERROR, }; @@ -613,6 +626,11 @@ struct mlx5e_resources { struct mlx5_sq_bfreg bfreg; }; +enum mlx5_sw_icm_type { + MLX5_SW_ICM_TYPE_STEERING, + MLX5_SW_ICM_TYPE_HEADER_MODIFY, +}; + #define MLX5_MAX_RESERVED_GIDS 8 struct mlx5_rsvd_gids { @@ -644,11 +662,18 @@ struct mlx5_clock { struct mlx5_pps pps_info; }; +struct mlx5_dm; struct mlx5_fw_tracer; struct mlx5_vxlan; +struct mlx5_geneve; +struct mlx5_hv_vhca; + +#define MLX5_LOG_SW_ICM_BLOCK_SIZE(dev) (MLX5_CAP_DEV_MEM(dev, log_sw_icm_alloc_granularity)) +#define MLX5_SW_ICM_BLOCK_SIZE(dev) (1 << MLX5_LOG_SW_ICM_BLOCK_SIZE(dev)) struct mlx5_core_dev { struct device *device; + enum mlx5_coredev_type coredev_type; struct pci_dev *pdev; /* sync pci state */ struct mutex pci_status_mutex; @@ -679,7 +704,9 @@ struct mlx5_core_dev { atomic_t num_qps; u32 issi; struct mlx5e_resources mlx5e_res; + struct mlx5_dm *dm; struct mlx5_vxlan *vxlan; + struct mlx5_geneve *geneve; struct { struct mlx5_rsvd_gids reserved_gids; u32 roce_en; @@ -690,6 +717,8 @@ struct mlx5_core_dev { struct mlx5_clock clock; struct mlx5_ib_clock_info *clock_info; struct mlx5_fw_tracer *tracer; + u32 vsc_addr; + struct mlx5_hv_vhca *hv_vhca; }; struct mlx5_db { @@ -901,7 +930,6 @@ void mlx5_start_health_poll(struct mlx5_core_dev *dev); void mlx5_stop_health_poll(struct mlx5_core_dev *dev, bool disable_health); void mlx5_drain_health_wq(struct mlx5_core_dev *dev); void mlx5_trigger_health_work(struct mlx5_core_dev *dev); -void mlx5_drain_health_recovery(struct mlx5_core_dev *dev); int mlx5_buf_alloc_node(struct mlx5_core_dev *dev, int size, struct mlx5_frag_buf *buf, int node); int mlx5_buf_alloc(struct mlx5_core_dev *dev, @@ -949,7 +977,7 @@ int mlx5_vector2eqn(struct mlx5_core_dev *dev, int vector, int *eqn, int mlx5_core_attach_mcg(struct mlx5_core_dev *dev, union ib_gid *mgid, u32 qpn); int mlx5_core_detach_mcg(struct mlx5_core_dev *dev, union ib_gid *mgid, u32 qpn); -int mlx5_qp_debugfs_init(struct mlx5_core_dev *dev); +void mlx5_qp_debugfs_init(struct mlx5_core_dev *dev); void mlx5_qp_debugfs_cleanup(struct mlx5_core_dev *dev); int mlx5_core_access_reg(struct mlx5_core_dev *dev, void *data_in, int size_in, void *data_out, int size_out, @@ -961,7 +989,7 @@ int mlx5_db_alloc_node(struct mlx5_core_dev *dev, struct mlx5_db *db, void mlx5_db_free(struct mlx5_core_dev *dev, struct mlx5_db *db); const char *mlx5_command_str(int command); -int mlx5_cmdif_debugfs_init(struct mlx5_core_dev *dev); +void mlx5_cmdif_debugfs_init(struct mlx5_core_dev *dev); void mlx5_cmdif_debugfs_cleanup(struct mlx5_core_dev *dev); int mlx5_core_create_psv(struct mlx5_core_dev *dev, u32 pdn, int npsvs, u32 *sig_index); @@ -1042,6 +1070,8 @@ int mlx5_register_interface(struct mlx5_interface *intf); void mlx5_unregister_interface(struct mlx5_interface *intf); int mlx5_notifier_register(struct mlx5_core_dev *dev, struct notifier_block *nb); int mlx5_notifier_unregister(struct mlx5_core_dev *dev, struct notifier_block *nb); +int mlx5_eq_notifier_register(struct mlx5_core_dev *dev, struct mlx5_nb *nb); +int mlx5_eq_notifier_unregister(struct mlx5_core_dev *dev, struct mlx5_nb *nb); int mlx5_core_query_vendor_id(struct mlx5_core_dev *mdev, u32 *vendor_id); @@ -1058,6 +1088,10 @@ int mlx5_lag_query_cong_counters(struct mlx5_core_dev *dev, size_t *offsets); struct mlx5_uars_page *mlx5_get_uars_page(struct mlx5_core_dev *mdev); void mlx5_put_uars_page(struct mlx5_core_dev *mdev, struct mlx5_uars_page *up); +int mlx5_dm_sw_icm_alloc(struct mlx5_core_dev *dev, enum mlx5_sw_icm_type type, + u64 length, u16 uid, phys_addr_t *addr, u32 *obj_id); +int mlx5_dm_sw_icm_dealloc(struct mlx5_core_dev *dev, enum mlx5_sw_icm_type type, + u64 length, u16 uid, phys_addr_t addr, u32 obj_id); #ifdef CONFIG_MLX5_CORE_IPOIB struct net_device *mlx5_rdma_netdev_alloc(struct mlx5_core_dev *mdev, @@ -1082,9 +1116,9 @@ enum { MLX5_PCI_DEV_IS_VF = 1 << 0, }; -static inline int mlx5_core_is_pf(struct mlx5_core_dev *dev) +static inline bool mlx5_core_is_pf(const struct mlx5_core_dev *dev) { - return !(dev->priv.pci_dev_data & MLX5_PCI_DEV_IS_VF); + return dev->coredev_type == MLX5_COREDEV_PF; } static inline bool mlx5_core_is_ecpf(struct mlx5_core_dev *dev) @@ -1092,23 +1126,20 @@ static inline bool mlx5_core_is_ecpf(struct mlx5_core_dev *dev) return dev->caps.embedded_cpu; } -static inline bool mlx5_core_is_ecpf_esw_manager(struct mlx5_core_dev *dev) +static inline bool +mlx5_core_is_ecpf_esw_manager(const struct mlx5_core_dev *dev) { return dev->caps.embedded_cpu && MLX5_CAP_GEN(dev, eswitch_manager); } -static inline bool mlx5_ecpf_vport_exists(struct mlx5_core_dev *dev) +static inline bool mlx5_ecpf_vport_exists(const struct mlx5_core_dev *dev) { return mlx5_core_is_pf(dev) && MLX5_CAP_ESW(dev, ecpf_vport_exists); } -#define MLX5_HOST_PF_MAX_VFS (127u) -static inline u16 mlx5_core_max_vfs(struct mlx5_core_dev *dev) +static inline u16 mlx5_core_max_vfs(const struct mlx5_core_dev *dev) { - if (mlx5_core_is_ecpf_esw_manager(dev)) - return MLX5_HOST_PF_MAX_VFS; - else - return pci_sriov_get_totalvfs(dev->pdev); + return dev->priv.sriov.max_vfs; } static inline int mlx5_get_gid_table_len(u16 param) diff --git a/include/linux/mlx5/eq.h b/include/linux/mlx5/eq.h index 00045cc4ea11..e49d8c0d4f26 100644 --- a/include/linux/mlx5/eq.h +++ b/include/linux/mlx5/eq.h @@ -4,17 +4,7 @@ #ifndef MLX5_CORE_EQ_H #define MLX5_CORE_EQ_H -enum { - MLX5_EQ_PAGEREQ_IDX = 0, - MLX5_EQ_CMD_IDX = 1, - MLX5_EQ_ASYNC_IDX = 2, - /* reserved to be used by mlx5_core ulps (mlx5e/mlx5_ib) */ - MLX5_EQ_PFAULT_IDX = 3, - MLX5_EQ_MAX_ASYNC_EQS, - /* completion eqs vector indices start here */ - MLX5_EQ_VEC_COMP_BASE = MLX5_EQ_MAX_ASYNC_EQS, -}; - +#define MLX5_IRQ_VEC_COMP_BASE 1 #define MLX5_NUM_CMD_EQE (32) #define MLX5_NUM_ASYNC_EQE (0x1000) #define MLX5_NUM_SPARE_EQE (0x80) @@ -23,18 +13,19 @@ struct mlx5_eq; struct mlx5_core_dev; struct mlx5_eq_param { - u8 index; + u8 irq_index; int nent; - u64 mask; - void *context; - irq_handler_t handler; + u64 mask[4]; }; struct mlx5_eq * -mlx5_eq_create_generic(struct mlx5_core_dev *dev, const char *name, - struct mlx5_eq_param *param); +mlx5_eq_create_generic(struct mlx5_core_dev *dev, struct mlx5_eq_param *param); int mlx5_eq_destroy_generic(struct mlx5_core_dev *dev, struct mlx5_eq *eq); +int mlx5_eq_enable(struct mlx5_core_dev *dev, struct mlx5_eq *eq, + struct notifier_block *nb); +void mlx5_eq_disable(struct mlx5_core_dev *dev, struct mlx5_eq *eq, + struct notifier_block *nb); struct mlx5_eqe *mlx5_eq_get_eqe(struct mlx5_eq *eq, u32 cc); void mlx5_eq_update_ci(struct mlx5_eq *eq, u32 cc, bool arm); diff --git a/include/linux/mlx5/eswitch.h b/include/linux/mlx5/eswitch.h index cf226c190329..98e667b176ef 100644 --- a/include/linux/mlx5/eswitch.h +++ b/include/linux/mlx5/eswitch.h @@ -7,13 +7,14 @@ #define _MLX5_ESWITCH_ #include <linux/mlx5/driver.h> +#include <net/devlink.h> #define MLX5_ESWITCH_MANAGER(mdev) MLX5_CAP_GEN(mdev, eswitch_manager) enum { - SRIOV_NONE, - SRIOV_LEGACY, - SRIOV_OFFLOADS + MLX5_ESWITCH_NONE, + MLX5_ESWITCH_LEGACY, + MLX5_ESWITCH_OFFLOADS }; enum { @@ -29,25 +30,28 @@ enum { }; struct mlx5_eswitch_rep; -struct mlx5_eswitch_rep_if { - int (*load)(struct mlx5_core_dev *dev, - struct mlx5_eswitch_rep *rep); - void (*unload)(struct mlx5_eswitch_rep *rep); - void *(*get_proto_dev)(struct mlx5_eswitch_rep *rep); - void *priv; - atomic_t state; +struct mlx5_eswitch_rep_ops { + int (*load)(struct mlx5_core_dev *dev, struct mlx5_eswitch_rep *rep); + void (*unload)(struct mlx5_eswitch_rep *rep); + void *(*get_proto_dev)(struct mlx5_eswitch_rep *rep); +}; + +struct mlx5_eswitch_rep_data { + void *priv; + atomic_t state; }; struct mlx5_eswitch_rep { - struct mlx5_eswitch_rep_if rep_if[NUM_REP_TYPES]; + struct mlx5_eswitch_rep_data rep_data[NUM_REP_TYPES]; u16 vport; - u8 hw_id[ETH_ALEN]; u16 vlan; + /* Only IB rep is using vport_index */ + u16 vport_index; u32 vlan_refcount; }; void mlx5_eswitch_register_vport_reps(struct mlx5_eswitch *esw, - struct mlx5_eswitch_rep_if *rep_if, + const struct mlx5_eswitch_rep_ops *ops, u8 rep_type); void mlx5_eswitch_unregister_vport_reps(struct mlx5_eswitch *esw, u8 rep_type); void *mlx5_eswitch_get_proto_dev(struct mlx5_eswitch *esw, @@ -56,8 +60,45 @@ void *mlx5_eswitch_get_proto_dev(struct mlx5_eswitch *esw, struct mlx5_eswitch_rep *mlx5_eswitch_vport_rep(struct mlx5_eswitch *esw, u16 vport_num); void *mlx5_eswitch_uplink_get_proto_dev(struct mlx5_eswitch *esw, u8 rep_type); -u8 mlx5_eswitch_mode(struct mlx5_eswitch *esw); struct mlx5_flow_handle * mlx5_eswitch_add_send_to_vport_rule(struct mlx5_eswitch *esw, u16 vport_num, u32 sqn); + +u16 mlx5_eswitch_get_total_vports(const struct mlx5_core_dev *dev); + +#ifdef CONFIG_MLX5_ESWITCH +enum devlink_eswitch_encap_mode +mlx5_eswitch_get_encap_mode(const struct mlx5_core_dev *dev); + +bool mlx5_eswitch_vport_match_metadata_enabled(const struct mlx5_eswitch *esw); +u32 mlx5_eswitch_get_vport_metadata_for_match(const struct mlx5_eswitch *esw, + u16 vport_num); +u8 mlx5_eswitch_mode(struct mlx5_eswitch *esw); +#else /* CONFIG_MLX5_ESWITCH */ + +static inline u8 mlx5_eswitch_mode(struct mlx5_eswitch *esw) +{ + return MLX5_ESWITCH_NONE; +} + +static inline enum devlink_eswitch_encap_mode +mlx5_eswitch_get_encap_mode(const struct mlx5_core_dev *dev) +{ + return DEVLINK_ESWITCH_ENCAP_MODE_NONE; +} + +static inline bool +mlx5_eswitch_vport_match_metadata_enabled(const struct mlx5_eswitch *esw) +{ + return false; +}; + +static inline u32 +mlx5_eswitch_get_vport_metadata_for_match(const struct mlx5_eswitch *esw, + int vport_num) +{ + return 0; +}; +#endif /* CONFIG_MLX5_ESWITCH */ + #endif diff --git a/include/linux/mlx5/fs.h b/include/linux/mlx5/fs.h index e690ba0f965c..724d276ea133 100644 --- a/include/linux/mlx5/fs.h +++ b/include/linux/mlx5/fs.h @@ -47,6 +47,7 @@ enum { enum { MLX5_FLOW_TABLE_TUNNEL_EN_REFORMAT = BIT(0), MLX5_FLOW_TABLE_TUNNEL_EN_DECAP = BIT(1), + MLX5_FLOW_TABLE_TERMINATION = BIT(2), }; #define LEFTOVERS_RULE_NUM 2 @@ -74,6 +75,7 @@ enum mlx5_flow_namespace_type { MLX5_FLOW_NAMESPACE_SNIFFER_TX, MLX5_FLOW_NAMESPACE_EGRESS, MLX5_FLOW_NAMESPACE_RDMA_RX, + MLX5_FLOW_NAMESPACE_RDMA_RX_KERNEL, }; enum { @@ -82,15 +84,28 @@ enum { FDB_SLOW_PATH, }; +struct mlx5_pkt_reformat; +struct mlx5_modify_hdr; struct mlx5_flow_table; struct mlx5_flow_group; struct mlx5_flow_namespace; struct mlx5_flow_handle; +enum { + FLOW_CONTEXT_HAS_TAG = BIT(0), +}; + +struct mlx5_flow_context { + u32 flags; + u32 flow_tag; + u32 flow_source; +}; + struct mlx5_flow_spec { u8 match_criteria_enable; u32 match_criteria[MLX5_ST_SZ_DW(fte_match_param)]; u32 match_value[MLX5_ST_SZ_DW(fte_match_param)]; + struct mlx5_flow_context flow_context; }; enum { @@ -108,12 +123,17 @@ struct mlx5_flow_destination { struct { u16 num; u16 vhca_id; - u32 reformat_id; + struct mlx5_pkt_reformat *pkt_reformat; u8 flags; } vport; }; }; +struct mod_hdr_tbl { + struct mutex lock; /* protects hlist */ + DECLARE_HASHTABLE(hlist, 8); +}; + struct mlx5_flow_namespace * mlx5_get_fdb_sub_ns(struct mlx5_core_dev *dev, int n); struct mlx5_flow_namespace * @@ -172,15 +192,13 @@ struct mlx5_fs_vlan { #define MLX5_FS_VLAN_DEPTH 2 enum { - FLOW_ACT_HAS_TAG = BIT(0), - FLOW_ACT_NO_APPEND = BIT(1), + FLOW_ACT_NO_APPEND = BIT(0), }; struct mlx5_flow_act { u32 action; - u32 flow_tag; - u32 reformat_id; - u32 modify_id; + struct mlx5_modify_hdr *modify_hdr; + struct mlx5_pkt_reformat *pkt_reformat; uintptr_t esp_id; u32 flags; struct mlx5_fs_vlan vlan[MLX5_FS_VLAN_DEPTH]; @@ -189,9 +207,6 @@ struct mlx5_flow_act { #define MLX5_DECLARE_FLOW_ACT(name) \ struct mlx5_flow_act name = { .action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST,\ - .flow_tag = MLX5_FS_DEFAULT_FLOW_TAG, \ - .reformat_id = 0, \ - .modify_id = 0, \ .flags = 0, } /* Single destination per rule. @@ -199,7 +214,7 @@ struct mlx5_flow_act { */ struct mlx5_flow_handle * mlx5_add_flow_rules(struct mlx5_flow_table *ft, - struct mlx5_flow_spec *spec, + const struct mlx5_flow_spec *spec, struct mlx5_flow_act *flow_act, struct mlx5_flow_destination *dest, int num_dest); @@ -211,6 +226,7 @@ int mlx5_modify_rule_destination(struct mlx5_flow_handle *handler, struct mlx5_fc *mlx5_fc_create(struct mlx5_core_dev *dev, bool aging); void mlx5_fc_destroy(struct mlx5_core_dev *dev, struct mlx5_fc *counter); +u64 mlx5_fc_query_lastuse(struct mlx5_fc *counter); void mlx5_fc_query_cached(struct mlx5_fc *counter, u64 *bytes, u64 *packets, u64 *lastuse); int mlx5_fc_query(struct mlx5_core_dev *dev, struct mlx5_fc *counter, @@ -220,19 +236,18 @@ u32 mlx5_fc_id(struct mlx5_fc *counter); int mlx5_fs_add_rx_underlay_qpn(struct mlx5_core_dev *dev, u32 underlay_qpn); int mlx5_fs_remove_rx_underlay_qpn(struct mlx5_core_dev *dev, u32 underlay_qpn); -int mlx5_modify_header_alloc(struct mlx5_core_dev *dev, - u8 namespace, u8 num_actions, - void *modify_actions, u32 *modify_header_id); +struct mlx5_modify_hdr *mlx5_modify_header_alloc(struct mlx5_core_dev *dev, + u8 ns_type, u8 num_actions, + void *modify_actions); void mlx5_modify_header_dealloc(struct mlx5_core_dev *dev, - u32 modify_header_id); - -int mlx5_packet_reformat_alloc(struct mlx5_core_dev *dev, - int reformat_type, - size_t size, - void *reformat_data, - enum mlx5_flow_namespace_type namespace, - u32 *packet_reformat_id); + struct mlx5_modify_hdr *modify_hdr); + +struct mlx5_pkt_reformat *mlx5_packet_reformat_alloc(struct mlx5_core_dev *dev, + int reformat_type, + size_t size, + void *reformat_data, + enum mlx5_flow_namespace_type ns_type); void mlx5_packet_reformat_dealloc(struct mlx5_core_dev *dev, - u32 packet_reformat_id); + struct mlx5_pkt_reformat *reformat); #endif diff --git a/include/linux/mlx5/mlx5_ifc.h b/include/linux/mlx5/mlx5_ifc.h index 5e74305e2e57..a487b681b516 100644 --- a/include/linux/mlx5/mlx5_ifc.h +++ b/include/linux/mlx5/mlx5_ifc.h @@ -91,6 +91,20 @@ enum { enum { MLX5_OBJ_TYPE_GENEVE_TLV_OPT = 0x000b, + MLX5_OBJ_TYPE_MKEY = 0xff01, + MLX5_OBJ_TYPE_QP = 0xff02, + MLX5_OBJ_TYPE_PSV = 0xff03, + MLX5_OBJ_TYPE_RMP = 0xff04, + MLX5_OBJ_TYPE_XRC_SRQ = 0xff05, + MLX5_OBJ_TYPE_RQ = 0xff06, + MLX5_OBJ_TYPE_SQ = 0xff07, + MLX5_OBJ_TYPE_TIR = 0xff08, + MLX5_OBJ_TYPE_TIS = 0xff09, + MLX5_OBJ_TYPE_DCT = 0xff0a, + MLX5_OBJ_TYPE_XRQ = 0xff0b, + MLX5_OBJ_TYPE_RQT = 0xff0e, + MLX5_OBJ_TYPE_FLOW_COUNTER = 0xff0f, + MLX5_OBJ_TYPE_CQ = 0xff10, }; enum { @@ -106,6 +120,9 @@ enum { MLX5_CMD_OP_QUERY_ISSI = 0x10a, MLX5_CMD_OP_SET_ISSI = 0x10b, MLX5_CMD_OP_SET_DRIVER_VERSION = 0x10d, + MLX5_CMD_OP_QUERY_SF_PARTITION = 0x111, + MLX5_CMD_OP_ALLOC_SF = 0x113, + MLX5_CMD_OP_DEALLOC_SF = 0x114, MLX5_CMD_OP_CREATE_MKEY = 0x200, MLX5_CMD_OP_QUERY_MKEY = 0x201, MLX5_CMD_OP_DESTROY_MKEY = 0x202, @@ -155,7 +172,9 @@ enum { MLX5_CMD_OP_QUERY_XRQ_DC_PARAMS_ENTRY = 0x725, MLX5_CMD_OP_SET_XRQ_DC_PARAMS_ENTRY = 0x726, MLX5_CMD_OP_QUERY_XRQ_ERROR_PARAMS = 0x727, - MLX5_CMD_OP_QUERY_HOST_PARAMS = 0x740, + MLX5_CMD_OP_RELEASE_XRQ_ERROR = 0x729, + MLX5_CMD_OP_MODIFY_XRQ = 0x72a, + MLX5_CMD_OP_QUERY_ESW_FUNCTIONS = 0x740, MLX5_CMD_OP_QUERY_VPORT_STATE = 0x750, MLX5_CMD_OP_MODIFY_VPORT_STATE = 0x751, MLX5_CMD_OP_QUERY_ESW_VPORT_CONTEXT = 0x752, @@ -263,6 +282,7 @@ enum { MLX5_CMD_OP_ALLOC_MODIFY_HEADER_CONTEXT = 0x940, MLX5_CMD_OP_DEALLOC_MODIFY_HEADER_CONTEXT = 0x941, MLX5_CMD_OP_QUERY_MODIFY_HEADER_CONTEXT = 0x942, + MLX5_CMD_OP_SYNC_STEERING = 0xb00, MLX5_CMD_OP_FPGA_CREATE_QP = 0x960, MLX5_CMD_OP_FPGA_MODIFY_QP = 0x961, MLX5_CMD_OP_FPGA_QUERY_QP = 0x962, @@ -382,7 +402,8 @@ struct mlx5_ifc_flow_table_prop_layout_bits { u8 reformat_and_modify_action[0x1]; u8 reserved_at_15[0x2]; u8 table_miss_action_domain[0x1]; - u8 reserved_at_18[0x8]; + u8 termination_table[0x1]; + u8 reserved_at_19[0x7]; u8 reserved_at_20[0x2]; u8 log_max_ft_size[0x6]; u8 log_max_modify_header_context[0x8]; @@ -465,7 +486,11 @@ union mlx5_ifc_gre_key_bits { }; struct mlx5_ifc_fte_match_set_misc_bits { - u8 reserved_at_0[0x8]; + u8 gre_c_present[0x1]; + u8 reserved_auto1[0x1]; + u8 gre_k_present[0x1]; + u8 gre_s_present[0x1]; + u8 source_vhca_port[0x4]; u8 source_sqn[0x18]; u8 source_eswitch_owner_vhca_id[0x10]; @@ -527,16 +552,56 @@ struct mlx5_ifc_fte_match_set_misc2_bits { struct mlx5_ifc_fte_match_mpls_bits outer_first_mpls_over_udp; - u8 reserved_at_80[0x100]; + u8 metadata_reg_c_7[0x20]; + + u8 metadata_reg_c_6[0x20]; + + u8 metadata_reg_c_5[0x20]; + + u8 metadata_reg_c_4[0x20]; + + u8 metadata_reg_c_3[0x20]; + + u8 metadata_reg_c_2[0x20]; + + u8 metadata_reg_c_1[0x20]; + + u8 metadata_reg_c_0[0x20]; u8 metadata_reg_a[0x20]; - u8 reserved_at_1a0[0x60]; + u8 metadata_reg_b[0x20]; + + u8 reserved_at_1c0[0x40]; }; struct mlx5_ifc_fte_match_set_misc3_bits { - u8 reserved_at_0[0x120]; + u8 inner_tcp_seq_num[0x20]; + + u8 outer_tcp_seq_num[0x20]; + + u8 inner_tcp_ack_num[0x20]; + + u8 outer_tcp_ack_num[0x20]; + + u8 reserved_at_80[0x8]; + u8 outer_vxlan_gpe_vni[0x18]; + + u8 outer_vxlan_gpe_next_protocol[0x8]; + u8 outer_vxlan_gpe_flags[0x8]; + u8 reserved_at_b0[0x10]; + + u8 icmp_header_data[0x20]; + + u8 icmpv6_header_data[0x20]; + + u8 icmp_type[0x8]; + u8 icmp_code[0x8]; + u8 icmpv6_type[0x8]; + u8 icmpv6_code[0x8]; + u8 geneve_tlv_option_0_data[0x20]; + u8 reserved_at_140[0xc0]; }; @@ -632,11 +697,33 @@ struct mlx5_ifc_flow_table_nic_cap_bits { struct mlx5_ifc_flow_table_prop_layout_bits flow_table_properties_nic_transmit_sniffer; - u8 reserved_at_e00[0x7200]; + u8 reserved_at_e00[0x1200]; + + u8 sw_steering_nic_rx_action_drop_icm_address[0x40]; + + u8 sw_steering_nic_tx_action_drop_icm_address[0x40]; + + u8 sw_steering_nic_tx_action_allow_icm_address[0x40]; + + u8 reserved_at_20c0[0x5f40]; +}; + +enum { + MLX5_FDB_TO_VPORT_REG_C_0 = 0x01, + MLX5_FDB_TO_VPORT_REG_C_1 = 0x02, + MLX5_FDB_TO_VPORT_REG_C_2 = 0x04, + MLX5_FDB_TO_VPORT_REG_C_3 = 0x08, + MLX5_FDB_TO_VPORT_REG_C_4 = 0x10, + MLX5_FDB_TO_VPORT_REG_C_5 = 0x20, + MLX5_FDB_TO_VPORT_REG_C_6 = 0x40, + MLX5_FDB_TO_VPORT_REG_C_7 = 0x80, }; struct mlx5_ifc_flow_table_eswitch_cap_bits { - u8 reserved_at_0[0x1a]; + u8 fdb_to_vport_reg_c_id[0x8]; + u8 reserved_at_8[0xf]; + u8 flow_source[0x1]; + u8 reserved_at_18[0x2]; u8 multi_fdb_encap[0x1]; u8 reserved_at_1b[0x1]; u8 fdb_multi_path_to_table[0x1]; @@ -650,7 +737,17 @@ struct mlx5_ifc_flow_table_eswitch_cap_bits { struct mlx5_ifc_flow_table_prop_layout_bits flow_table_properties_esw_acl_egress; - u8 reserved_at_800[0x7800]; + u8 reserved_at_800[0x1000]; + + u8 sw_steering_fdb_action_drop_icm_address_rx[0x40]; + + u8 sw_steering_fdb_action_drop_icm_address_tx[0x40]; + + u8 sw_steering_uplink_icm_address_rx[0x40]; + + u8 sw_steering_uplink_icm_address_tx[0x40]; + + u8 reserved_at_1900[0x6700]; }; enum { @@ -664,7 +761,11 @@ struct mlx5_ifc_e_switch_cap_bits { u8 vport_svlan_insert[0x1]; u8 vport_cvlan_insert_if_not_exist[0x1]; u8 vport_cvlan_insert_overwrite[0x1]; - u8 reserved_at_5[0x16]; + u8 reserved_at_5[0x3]; + u8 esw_uplink_ingress_acl[0x1]; + u8 reserved_at_9[0x10]; + u8 esw_functions_changed[0x1]; + u8 reserved_at_1a[0x1]; u8 ecpf_vport_exists[0x1]; u8 counter_eswitch_affinity[0x1]; u8 merged_eswitch[0x1]; @@ -680,7 +781,11 @@ struct mlx5_ifc_e_switch_cap_bits { u8 reserved_2b[0x6]; u8 max_encap_header_size[0xa]; - u8 reserved_40[0x7c0]; + u8 reserved_at_40[0xb]; + u8 log_max_esw_sf[0x5]; + u8 esw_sf_base_id[0x10]; + + u8 reserved_at_60[0x7a0]; }; @@ -715,7 +820,9 @@ struct mlx5_ifc_qos_cap_bits { }; struct mlx5_ifc_debug_cap_bits { - u8 reserved_at_0[0x20]; + u8 core_dump_general[0x1]; + u8 core_dump_qp[0x1]; + u8 reserved_at_2[0x1e]; u8 reserved_at_20[0x2]; u8 stall_detect[0x1]; @@ -749,7 +856,10 @@ struct mlx5_ifc_per_protocol_networking_offload_caps_bits { u8 swp[0x1]; u8 swp_csum[0x1]; u8 swp_lso[0x1]; - u8 reserved_at_23[0xd]; + u8 cqe_checksum_full[0x1]; + u8 reserved_at_24[0x5]; + u8 tunnel_stateless_ip_over_ip[0x1]; + u8 reserved_at_2a[0x6]; u8 max_vxlan_udp_ports[0x8]; u8 reserved_at_38[0x6]; u8 max_geneve_opt_len[0x1]; @@ -788,6 +898,25 @@ struct mlx5_ifc_roce_cap_bits { u8 reserved_at_100[0x700]; }; +struct mlx5_ifc_sync_steering_in_bits { + u8 opcode[0x10]; + u8 uid[0x10]; + + u8 reserved_at_20[0x10]; + u8 op_mod[0x10]; + + u8 reserved_at_40[0xc0]; +}; + +struct mlx5_ifc_sync_steering_out_bits { + u8 status[0x8]; + u8 reserved_at_8[0x18]; + + u8 syndrome[0x20]; + + u8 reserved_at_40[0x40]; +}; + struct mlx5_ifc_device_mem_cap_bits { u8 memic[0x1]; u8 reserved_at_1[0x1f]; @@ -818,6 +947,12 @@ struct mlx5_ifc_device_mem_cap_bits { u8 reserved_at_180[0x680]; }; +struct mlx5_ifc_device_event_cap_bits { + u8 user_affiliated_events[4][0x40]; + + u8 user_unaffiliated_events[4][0x40]; +}; + enum { MLX5_ATOMIC_CAPS_ATOMIC_SIZE_QP_1_BYTE = 0x0, MLX5_ATOMIC_CAPS_ATOMIC_SIZE_QP_2_BYTES = 0x2, @@ -881,7 +1016,9 @@ struct mlx5_ifc_odp_cap_bits { struct mlx5_ifc_odp_per_transport_service_cap_bits xrc_odp_caps; - u8 reserved_at_100[0x700]; + struct mlx5_ifc_odp_per_transport_service_cap_bits dc_odp_caps; + + u8 reserved_at_120[0x6E0]; }; struct mlx5_ifc_calc_op { @@ -911,6 +1048,16 @@ struct mlx5_ifc_vector_calc_cap_bits { u8 reserved_at_c0[0x720]; }; +struct mlx5_ifc_tls_cap_bits { + u8 tls_1_2_aes_gcm_128[0x1]; + u8 tls_1_3_aes_gcm_128[0x1]; + u8 tls_1_2_aes_gcm_256[0x1]; + u8 tls_1_3_aes_gcm_256[0x1]; + u8 reserved_at_4[0x1c]; + + u8 reserved_at_20[0x7e0]; +}; + enum { MLX5_WQ_TYPE_LINKED_LIST = 0x0, MLX5_WQ_TYPE_CYCLIC = 0x1, @@ -963,10 +1110,31 @@ enum { }; enum { + MLX5_FLEX_PARSER_VXLAN_GPE_ENABLED = 1 << 7, + MLX5_FLEX_PARSER_ICMP_V4_ENABLED = 1 << 8, + MLX5_FLEX_PARSER_ICMP_V6_ENABLED = 1 << 9, +}; + +enum { MLX5_UCTX_CAP_RAW_TX = 1UL << 0, MLX5_UCTX_CAP_INTERNAL_DEV_RES = 1UL << 1, }; +#define MLX5_FC_BULK_SIZE_FACTOR 128 + +enum mlx5_fc_bulk_alloc_bitmask { + MLX5_FC_BULK_128 = (1 << 0), + MLX5_FC_BULK_256 = (1 << 1), + MLX5_FC_BULK_512 = (1 << 2), + MLX5_FC_BULK_1024 = (1 << 3), + MLX5_FC_BULK_2048 = (1 << 4), + MLX5_FC_BULK_4096 = (1 << 5), + MLX5_FC_BULK_8192 = (1 << 6), + MLX5_FC_BULK_16384 = (1 << 7), +}; + +#define MLX5_FC_BULK_NUM_FCS(fc_enum) (MLX5_FC_BULK_SIZE_FACTOR * (fc_enum)) + struct mlx5_ifc_cmd_hca_cap_bits { u8 reserved_at_0[0x30]; u8 vhca_id[0x10]; @@ -975,7 +1143,8 @@ struct mlx5_ifc_cmd_hca_cap_bits { u8 log_max_srq_sz[0x8]; u8 log_max_qp_sz[0x8]; - u8 reserved_at_90[0x8]; + u8 event_cap[0x1]; + u8 reserved_at_91[0x7]; u8 prio_tag_required[0x1]; u8 reserved_at_99[0x2]; u8 log_max_qp[0x5]; @@ -1023,7 +1192,12 @@ struct mlx5_ifc_cmd_hca_cap_bits { u8 cc_modify_allowed[0x1]; u8 start_pad[0x1]; u8 cache_line_128byte[0x1]; - u8 reserved_at_165[0xa]; + u8 reserved_at_165[0x4]; + u8 rts2rts_qp_counters_set_id[0x1]; + u8 reserved_at_16a[0x2]; + u8 vnic_env_int_rq_oob[0x1]; + u8 sbcam_reg[0x1]; + u8 reserved_at_16e[0x1]; u8 qcam_reg[0x1]; u8 gid_table_size[0x10]; @@ -1152,7 +1326,9 @@ struct mlx5_ifc_cmd_hca_cap_bits { u8 reserved_at_263[0x8]; u8 log_bf_reg_size[0x5]; - u8 reserved_at_270[0xb]; + u8 reserved_at_270[0x8]; + u8 lag_tx_port_affinity[0x1]; + u8 reserved_at_279[0x2]; u8 lag_master[0x1]; u8 num_lag_ports[0x4]; @@ -1168,7 +1344,8 @@ struct mlx5_ifc_cmd_hca_cap_bits { u8 reserved_at_2e0[0x7]; u8 max_qp_mcg[0x19]; - u8 reserved_at_300[0x18]; + u8 reserved_at_300[0x10]; + u8 flow_counter_bulk_alloc[0x8]; u8 log_max_mcg[0x8]; u8 reserved_at_320[0x3]; @@ -1240,7 +1417,8 @@ struct mlx5_ifc_cmd_hca_cap_bits { u8 reserved_at_440[0x20]; - u8 reserved_at_460[0x3]; + u8 tls[0x1]; + u8 reserved_at_461[0x2]; u8 log_max_uctx[0x5]; u8 reserved_at_468[0x3]; u8 log_max_umem[0x5]; @@ -1265,7 +1443,9 @@ struct mlx5_ifc_cmd_hca_cap_bits { u8 max_geneve_tlv_option_data_len[0x5]; u8 reserved_at_570[0x10]; - u8 reserved_at_580[0x3c]; + u8 reserved_at_580[0x33]; + u8 log_max_dek[0x5]; + u8 reserved_at_5b8[0x4]; u8 mini_cqe_resp_stride_index[0x1]; u8 cqe_128_always[0x1]; u8 cqe_compression_128[0x1]; @@ -1295,13 +1475,33 @@ struct mlx5_ifc_cmd_hca_cap_bits { u8 reserved_at_640[0x10]; u8 num_q_monitor_counters[0x10]; - u8 reserved_at_660[0x40]; + u8 reserved_at_660[0x20]; + + u8 sf[0x1]; + u8 sf_set_partition[0x1]; + u8 reserved_at_682[0x1]; + u8 log_max_sf[0x5]; + u8 reserved_at_688[0x8]; + u8 log_min_sf_size[0x8]; + u8 max_num_sf_partitions[0x8]; u8 uctx_cap[0x20]; u8 reserved_at_6c0[0x4]; u8 flex_parser_id_geneve_tlv_option_0[0x4]; - u8 reserved_at_6c8[0x138]; + u8 flex_parser_id_icmp_dw1[0x4]; + u8 flex_parser_id_icmp_dw0[0x4]; + u8 flex_parser_id_icmpv6_dw1[0x4]; + u8 flex_parser_id_icmpv6_dw0[0x4]; + u8 flex_parser_id_outer_first_mpls_over_gre[0x4]; + u8 flex_parser_id_outer_first_mpls_over_udp_label[0x4]; + + u8 reserved_at_6e0[0x10]; + u8 sf_base_id[0x10]; + + u8 reserved_at_700[0x80]; + u8 vhca_tunnel_commands[0x40]; + u8 reserved_at_7c0[0x40]; }; enum mlx5_flow_destination_type { @@ -1761,12 +1961,28 @@ struct mlx5_ifc_ib_port_cntrs_grp_data_layout_bits { u8 port_xmit_wait[0x20]; }; -struct mlx5_ifc_eth_per_traffic_grp_data_layout_bits { +struct mlx5_ifc_eth_per_tc_prio_grp_data_layout_bits { u8 transmit_queue_high[0x20]; u8 transmit_queue_low[0x20]; - u8 reserved_at_40[0x780]; + u8 no_buffer_discard_uc_high[0x20]; + + u8 no_buffer_discard_uc_low[0x20]; + + u8 reserved_at_80[0x740]; +}; + +struct mlx5_ifc_eth_per_tc_congest_prio_grp_data_layout_bits { + u8 wred_discard_high[0x20]; + + u8 wred_discard_low[0x20]; + + u8 ecn_marked_tc_high[0x20]; + + u8 ecn_marked_tc_low[0x20]; + + u8 reserved_at_80[0x740]; }; struct mlx5_ifc_eth_per_prio_grp_data_layout_bits { @@ -2531,7 +2747,10 @@ union mlx5_ifc_hca_cap_union_bits { struct mlx5_ifc_e_switch_cap_bits e_switch_cap; struct mlx5_ifc_vector_calc_cap_bits vector_calc_cap; struct mlx5_ifc_qos_cap_bits qos_cap; + struct mlx5_ifc_debug_cap_bits debug_cap; struct mlx5_ifc_fpga_cap_bits fpga_cap; + struct mlx5_ifc_tls_cap_bits tls_cap; + struct mlx5_ifc_device_mem_cap_bits device_mem_cap; u8 reserved_at_0[0x8000]; }; @@ -2549,6 +2768,12 @@ enum { MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH_2 = 0x800, }; +enum { + MLX5_FLOW_CONTEXT_FLOW_SOURCE_ANY_VPORT = 0x0, + MLX5_FLOW_CONTEXT_FLOW_SOURCE_UPLINK = 0x1, + MLX5_FLOW_CONTEXT_FLOW_SOURCE_LOCAL_VPORT = 0x2, +}; + struct mlx5_ifc_vlan_bits { u8 ethtype[0x10]; u8 prio[0x3]; @@ -2568,7 +2793,9 @@ struct mlx5_ifc_flow_context_bits { u8 action[0x10]; u8 extended_destination[0x1]; - u8 reserved_at_80[0x7]; + u8 reserved_at_81[0x1]; + u8 flow_source[0x2]; + u8 reserved_at_84[0x4]; u8 destination_list_size[0x18]; u8 reserved_at_a0[0x8]; @@ -2652,7 +2879,11 @@ struct mlx5_ifc_vnic_diagnostic_statistics_bits { u8 transmit_discard_vport_down[0x40]; - u8 reserved_at_140[0xec0]; + u8 reserved_at_140[0xa0]; + + u8 internal_rq_out_of_buffer[0x20]; + + u8 reserved_at_200[0xe00]; }; struct mlx5_ifc_traffic_counter_bits { @@ -2663,7 +2894,8 @@ struct mlx5_ifc_traffic_counter_bits { struct mlx5_ifc_tisc_bits { u8 strict_lag_tx_port_affinity[0x1]; - u8 reserved_at_1[0x3]; + u8 tls_en[0x1]; + u8 reserved_at_2[0x2]; u8 lag_tx_port_affinity[0x04]; u8 reserved_at_8[0x4]; @@ -2677,7 +2909,11 @@ struct mlx5_ifc_tisc_bits { u8 reserved_at_140[0x8]; u8 underlay_qpn[0x18]; - u8 reserved_at_160[0x3a0]; + + u8 reserved_at_160[0x8]; + u8 pd[0x18]; + + u8 reserved_at_180[0x380]; }; enum { @@ -2834,6 +3070,13 @@ enum { SCHEDULING_CONTEXT_ELEMENT_TYPE_PARA_VPORT_TC = 0x3, }; +enum { + ELEMENT_TYPE_CAP_MASK_TASR = 1 << 0, + ELEMENT_TYPE_CAP_MASK_VPORT = 1 << 1, + ELEMENT_TYPE_CAP_MASK_VPORT_TC = 1 << 2, + ELEMENT_TYPE_CAP_MASK_PARA_VPORT_TC = 1 << 3, +}; + struct mlx5_ifc_scheduling_context_bits { u8 element_type[0x8]; u8 reserved_at_8[0x18]; @@ -3093,12 +3336,14 @@ struct mlx5_ifc_hca_vport_context_bits { }; struct mlx5_ifc_esw_vport_context_bits { - u8 reserved_at_0[0x3]; + u8 fdb_to_vport_reg_c[0x1]; + u8 reserved_at_1[0x2]; u8 vport_svlan_strip[0x1]; u8 vport_cvlan_strip[0x1]; u8 vport_svlan_insert[0x1]; u8 vport_cvlan_insert[0x2]; - u8 reserved_at_8[0x18]; + u8 fdb_to_vport_reg_c_id[0x8]; + u8 reserved_at_10[0x10]; u8 reserved_at_20[0x20]; @@ -3109,7 +3354,11 @@ struct mlx5_ifc_esw_vport_context_bits { u8 cvlan_pcp[0x3]; u8 cvlan_id[0xc]; - u8 reserved_at_60[0x7a0]; + u8 reserved_at_60[0x720]; + + u8 sw_steering_vport_icm_address_rx[0x40]; + + u8 sw_steering_vport_icm_address_tx[0x40]; }; enum { @@ -3410,7 +3659,8 @@ union mlx5_ifc_eth_cntrs_grp_data_layout_auto_bits { struct mlx5_ifc_eth_3635_cntrs_grp_data_layout_bits eth_3635_cntrs_grp_data_layout; struct mlx5_ifc_eth_extended_cntrs_grp_data_layout_bits eth_extended_cntrs_grp_data_layout; struct mlx5_ifc_eth_per_prio_grp_data_layout_bits eth_per_prio_grp_data_layout; - struct mlx5_ifc_eth_per_traffic_grp_data_layout_bits eth_per_traffic_grp_data_layout; + struct mlx5_ifc_eth_per_tc_prio_grp_data_layout_bits eth_per_tc_prio_grp_data_layout; + struct mlx5_ifc_eth_per_tc_congest_prio_grp_data_layout_bits eth_per_tc_congest_prio_grp_data_layout; struct mlx5_ifc_ib_port_cntrs_grp_data_layout_bits ib_port_cntrs_grp_data_layout; struct mlx5_ifc_phys_layer_cntrs_bits phys_layer_cntrs; struct mlx5_ifc_phys_layer_statistical_cntrs_bits phys_layer_statistical_cntrs; @@ -4795,23 +5045,98 @@ struct mlx5_ifc_query_hca_cap_in_bits { u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_at_40[0x40]; + u8 other_function[0x1]; + u8 reserved_at_41[0xf]; + u8 function_id[0x10]; + + u8 reserved_at_60[0x20]; }; -struct mlx5_ifc_query_flow_table_out_bits { +struct mlx5_ifc_other_hca_cap_bits { + u8 roce[0x1]; + u8 reserved_0[0x27f]; +}; + +struct mlx5_ifc_query_other_hca_cap_out_bits { u8 status[0x8]; - u8 reserved_at_8[0x18]; + u8 reserved_0[0x18]; u8 syndrome[0x20]; - u8 reserved_at_40[0x80]; + u8 reserved_1[0x40]; - u8 reserved_at_c0[0x8]; + struct mlx5_ifc_other_hca_cap_bits other_capability; +}; + +struct mlx5_ifc_query_other_hca_cap_in_bits { + u8 opcode[0x10]; + u8 reserved_0[0x10]; + + u8 reserved_1[0x10]; + u8 op_mod[0x10]; + + u8 reserved_2[0x10]; + u8 function_id[0x10]; + + u8 reserved_3[0x20]; +}; + +struct mlx5_ifc_modify_other_hca_cap_out_bits { + u8 status[0x8]; + u8 reserved_0[0x18]; + + u8 syndrome[0x20]; + + u8 reserved_1[0x40]; +}; + +struct mlx5_ifc_modify_other_hca_cap_in_bits { + u8 opcode[0x10]; + u8 reserved_0[0x10]; + + u8 reserved_1[0x10]; + u8 op_mod[0x10]; + + u8 reserved_2[0x10]; + u8 function_id[0x10]; + u8 field_select[0x20]; + + struct mlx5_ifc_other_hca_cap_bits other_capability; +}; + +struct mlx5_ifc_flow_table_context_bits { + u8 reformat_en[0x1]; + u8 decap_en[0x1]; + u8 sw_owner[0x1]; + u8 termination_table[0x1]; + u8 table_miss_action[0x4]; u8 level[0x8]; - u8 reserved_at_d0[0x8]; + u8 reserved_at_10[0x8]; u8 log_size[0x8]; - u8 reserved_at_e0[0x120]; + u8 reserved_at_20[0x8]; + u8 table_miss_id[0x18]; + + u8 reserved_at_40[0x8]; + u8 lag_master_next_table_id[0x18]; + + u8 reserved_at_60[0x60]; + + u8 sw_owner_icm_root_1[0x40]; + + u8 sw_owner_icm_root_0[0x40]; + +}; + +struct mlx5_ifc_query_flow_table_out_bits { + u8 status[0x8]; + u8 reserved_at_8[0x18]; + + u8 syndrome[0x20]; + + u8 reserved_at_40[0x80]; + + struct mlx5_ifc_flow_table_context_bits flow_table_context; }; struct mlx5_ifc_query_flow_table_in_bits { @@ -4979,7 +5304,8 @@ struct mlx5_ifc_modify_esw_vport_context_out_bits { }; struct mlx5_ifc_esw_vport_context_fields_select_bits { - u8 reserved_at_0[0x1c]; + u8 reserved_at_0[0x1b]; + u8 fdb_to_vport_reg_c_id[0x1]; u8 vport_cvlan_insert[0x1]; u8 vport_svlan_insert[0x1]; u8 vport_cvlan_strip[0x1]; @@ -5080,7 +5406,7 @@ struct mlx5_ifc_alloc_packet_reformat_context_out_bits { u8 reserved_at_60[0x20]; }; -enum { +enum mlx5_reformat_ctx_type { MLX5_REFORMAT_TYPE_L2_TO_VXLAN = 0x0, MLX5_REFORMAT_TYPE_L2_TO_NVGRE = 0x1, MLX5_REFORMAT_TYPE_L2_TO_L2_TUNNEL = 0x2, @@ -5176,6 +5502,16 @@ enum { MLX5_ACTION_IN_FIELD_OUT_DIPV4 = 0x16, MLX5_ACTION_IN_FIELD_OUT_FIRST_VID = 0x17, MLX5_ACTION_IN_FIELD_OUT_IPV6_HOPLIMIT = 0x47, + MLX5_ACTION_IN_FIELD_METADATA_REG_A = 0x49, + MLX5_ACTION_IN_FIELD_METADATA_REG_B = 0x50, + MLX5_ACTION_IN_FIELD_METADATA_REG_C_0 = 0x51, + MLX5_ACTION_IN_FIELD_METADATA_REG_C_1 = 0x52, + MLX5_ACTION_IN_FIELD_METADATA_REG_C_2 = 0x53, + MLX5_ACTION_IN_FIELD_METADATA_REG_C_3 = 0x54, + MLX5_ACTION_IN_FIELD_METADATA_REG_C_4 = 0x55, + MLX5_ACTION_IN_FIELD_METADATA_REG_C_5 = 0x56, + MLX5_ACTION_IN_FIELD_OUT_TCP_SEQ_NUM = 0x59, + MLX5_ACTION_IN_FIELD_OUT_TCP_ACK_NUM = 0x5B, }; struct mlx5_ifc_alloc_modify_header_context_out_bits { @@ -5864,10 +6200,12 @@ struct mlx5_ifc_modify_cq_in_bits { struct mlx5_ifc_cqc_bits cq_context; - u8 reserved_at_280[0x40]; + u8 reserved_at_280[0x60]; u8 cq_umem_valid[0x1]; - u8 reserved_at_2c1[0x5bf]; + u8 reserved_at_2e1[0x1f]; + + u8 reserved_at_300[0x580]; u8 pas[0][0x40]; }; @@ -7221,34 +7559,26 @@ struct mlx5_ifc_create_mkey_in_bits { u8 klm_pas_mtt[0][0x20]; }; +enum { + MLX5_FLOW_TABLE_TYPE_NIC_RX = 0x0, + MLX5_FLOW_TABLE_TYPE_NIC_TX = 0x1, + MLX5_FLOW_TABLE_TYPE_ESW_EGRESS_ACL = 0x2, + MLX5_FLOW_TABLE_TYPE_ESW_INGRESS_ACL = 0x3, + MLX5_FLOW_TABLE_TYPE_FDB = 0X4, + MLX5_FLOW_TABLE_TYPE_SNIFFER_RX = 0X5, + MLX5_FLOW_TABLE_TYPE_SNIFFER_TX = 0X6, +}; + struct mlx5_ifc_create_flow_table_out_bits { u8 status[0x8]; - u8 reserved_at_8[0x18]; + u8 icm_address_63_40[0x18]; u8 syndrome[0x20]; - u8 reserved_at_40[0x8]; + u8 icm_address_39_32[0x8]; u8 table_id[0x18]; - u8 reserved_at_60[0x20]; -}; - -struct mlx5_ifc_flow_table_context_bits { - u8 reformat_en[0x1]; - u8 decap_en[0x1]; - u8 reserved_at_2[0x2]; - u8 table_miss_action[0x4]; - u8 level[0x8]; - u8 reserved_at_10[0x8]; - u8 log_size[0x8]; - - u8 reserved_at_20[0x8]; - u8 table_miss_id[0x18]; - - u8 reserved_at_40[0x8]; - u8 lag_master_next_table_id[0x18]; - - u8 reserved_at_60[0xe0]; + u8 icm_address_31_0[0x20]; }; struct mlx5_ifc_create_flow_table_in_bits { @@ -7355,9 +7685,9 @@ struct mlx5_ifc_create_eq_in_bits { u8 reserved_at_280[0x40]; - u8 event_bitmask[0x40]; + u8 event_bitmask[4][0x40]; - u8 reserved_at_300[0x580]; + u8 reserved_at_3c0[0x4c0]; u8 pas[0][0x40]; }; @@ -7703,7 +8033,8 @@ struct mlx5_ifc_alloc_flow_counter_in_bits { u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_at_40[0x40]; + u8 reserved_at_40[0x38]; + u8 flow_counter_bulk[0x8]; }; struct mlx5_ifc_add_vxlan_udp_dport_out_bits { @@ -8475,7 +8806,7 @@ struct mlx5_ifc_mcam_access_reg_bits { u8 mcda[0x1]; u8 mcc[0x1]; u8 mcqi[0x1]; - u8 reserved_at_1f[0x1]; + u8 mcqs[0x1]; u8 regs_95_to_87[0x9]; u8 mpegc[0x1]; @@ -8546,6 +8877,18 @@ struct mlx5_ifc_qcam_reg_bits { u8 reserved_at_1c0[0x80]; }; +struct mlx5_ifc_core_dump_reg_bits { + u8 reserved_at_0[0x18]; + u8 core_dump_type[0x8]; + + u8 reserved_at_20[0x30]; + u8 vhca_id[0x10]; + + u8 reserved_at_60[0x8]; + u8 qpn[0x18]; + u8 reserved_at_80[0x180]; +}; + struct mlx5_ifc_pcap_reg_bits { u8 reserved_at_0[0x8]; u8 local_port[0x8]; @@ -8955,6 +9298,24 @@ struct mlx5_ifc_mtppse_reg_bits { u8 reserved_at_40[0x40]; }; +struct mlx5_ifc_mcqs_reg_bits { + u8 last_index_flag[0x1]; + u8 reserved_at_1[0x7]; + u8 fw_device[0x8]; + u8 component_index[0x10]; + + u8 reserved_at_20[0x10]; + u8 identifier[0x10]; + + u8 reserved_at_40[0x17]; + u8 component_status[0x5]; + u8 component_update_state[0x4]; + + u8 last_update_state_changer_type[0x4]; + u8 last_update_state_changer_host_id[0x4]; + u8 reserved_at_68[0x18]; +}; + struct mlx5_ifc_mcqi_cap_bits { u8 supported_info_bitmask[0x20]; @@ -8975,6 +9336,43 @@ struct mlx5_ifc_mcqi_cap_bits { u8 reserved_at_86[0x1a]; }; +struct mlx5_ifc_mcqi_version_bits { + u8 reserved_at_0[0x2]; + u8 build_time_valid[0x1]; + u8 user_defined_time_valid[0x1]; + u8 reserved_at_4[0x14]; + u8 version_string_length[0x8]; + + u8 version[0x20]; + + u8 build_time[0x40]; + + u8 user_defined_time[0x40]; + + u8 build_tool_version[0x20]; + + u8 reserved_at_e0[0x20]; + + u8 version_string[92][0x8]; +}; + +struct mlx5_ifc_mcqi_activation_method_bits { + u8 pending_server_ac_power_cycle[0x1]; + u8 pending_server_dc_power_cycle[0x1]; + u8 pending_server_reboot[0x1]; + u8 pending_fw_reset[0x1]; + u8 auto_activate[0x1]; + u8 all_hosts_sync[0x1]; + u8 device_hw_reset[0x1]; + u8 reserved_at_7[0x19]; +}; + +union mlx5_ifc_mcqi_reg_data_bits { + struct mlx5_ifc_mcqi_cap_bits mcqi_caps; + struct mlx5_ifc_mcqi_version_bits mcqi_version; + struct mlx5_ifc_mcqi_activation_method_bits mcqi_activation_mathod; +}; + struct mlx5_ifc_mcqi_reg_bits { u8 read_pending_component[0x1]; u8 reserved_at_1[0xf]; @@ -8992,7 +9390,7 @@ struct mlx5_ifc_mcqi_reg_bits { u8 reserved_at_a0[0x10]; u8 data_size[0x10]; - u8 data[0][0x20]; + union mlx5_ifc_mcqi_reg_data_bits data[0]; }; struct mlx5_ifc_mcc_reg_bits { @@ -9042,7 +9440,8 @@ union mlx5_ifc_ports_control_registers_document_bits { struct mlx5_ifc_eth_802_3_cntrs_grp_data_layout_bits eth_802_3_cntrs_grp_data_layout; struct mlx5_ifc_eth_extended_cntrs_grp_data_layout_bits eth_extended_cntrs_grp_data_layout; struct mlx5_ifc_eth_per_prio_grp_data_layout_bits eth_per_prio_grp_data_layout; - struct mlx5_ifc_eth_per_traffic_grp_data_layout_bits eth_per_traffic_grp_data_layout; + struct mlx5_ifc_eth_per_tc_prio_grp_data_layout_bits eth_per_tc_prio_grp_data_layout; + struct mlx5_ifc_eth_per_tc_congest_prio_grp_data_layout_bits eth_per_tc_congest_prio_grp_data_layout; struct mlx5_ifc_lane_2_module_mapping_bits lane_2_module_mapping; struct mlx5_ifc_pamp_reg_bits pamp_reg; struct mlx5_ifc_paos_reg_bits paos_reg; @@ -9389,8 +9788,6 @@ struct mlx5_ifc_query_lag_out_bits { u8 syndrome[0x20]; - u8 reserved_at_40[0x40]; - struct mlx5_ifc_lagc_bits ctx; }; @@ -9518,7 +9915,7 @@ struct mlx5_ifc_general_obj_in_cmd_hdr_bits { u8 opcode[0x10]; u8 uid[0x10]; - u8 reserved_at_20[0x10]; + u8 vhca_tunnel_id[0x10]; u8 obj_type[0x10]; u8 obj_id[0x20]; @@ -9689,10 +10086,11 @@ struct mlx5_ifc_mtrc_ctrl_bits { struct mlx5_ifc_host_params_context_bits { u8 host_number[0x8]; - u8 reserved_at_8[0x8]; + u8 reserved_at_8[0x7]; + u8 host_pf_disabled[0x1]; u8 host_num_of_vfs[0x10]; - u8 reserved_at_20[0x10]; + u8 host_total_vfs[0x10]; u8 host_pci_bus[0x10]; u8 reserved_at_40[0x10]; @@ -9704,7 +10102,7 @@ struct mlx5_ifc_host_params_context_bits { u8 reserved_at_80[0x180]; }; -struct mlx5_ifc_query_host_params_in_bits { +struct mlx5_ifc_query_esw_functions_in_bits { u8 opcode[0x10]; u8 reserved_at_10[0x10]; @@ -9714,7 +10112,7 @@ struct mlx5_ifc_query_host_params_in_bits { u8 reserved_at_40[0x40]; }; -struct mlx5_ifc_query_host_params_out_bits { +struct mlx5_ifc_query_esw_functions_out_bits { u8 status[0x8]; u8 reserved_at_8[0x18]; @@ -9725,6 +10123,164 @@ struct mlx5_ifc_query_host_params_out_bits { struct mlx5_ifc_host_params_context_bits host_params_context; u8 reserved_at_280[0x180]; + u8 host_sf_enable[0][0x40]; +}; + +struct mlx5_ifc_sf_partition_bits { + u8 reserved_at_0[0x10]; + u8 log_num_sf[0x8]; + u8 log_sf_bar_size[0x8]; +}; + +struct mlx5_ifc_query_sf_partitions_out_bits { + u8 status[0x8]; + u8 reserved_at_8[0x18]; + + u8 syndrome[0x20]; + + u8 reserved_at_40[0x18]; + u8 num_sf_partitions[0x8]; + + u8 reserved_at_60[0x20]; + + struct mlx5_ifc_sf_partition_bits sf_partition[0]; +}; + +struct mlx5_ifc_query_sf_partitions_in_bits { + u8 opcode[0x10]; + u8 reserved_at_10[0x10]; + + u8 reserved_at_20[0x10]; + u8 op_mod[0x10]; + + u8 reserved_at_40[0x40]; +}; + +struct mlx5_ifc_dealloc_sf_out_bits { + u8 status[0x8]; + u8 reserved_at_8[0x18]; + + u8 syndrome[0x20]; + + u8 reserved_at_40[0x40]; +}; + +struct mlx5_ifc_dealloc_sf_in_bits { + u8 opcode[0x10]; + u8 reserved_at_10[0x10]; + + u8 reserved_at_20[0x10]; + u8 op_mod[0x10]; + + u8 reserved_at_40[0x10]; + u8 function_id[0x10]; + + u8 reserved_at_60[0x20]; +}; + +struct mlx5_ifc_alloc_sf_out_bits { + u8 status[0x8]; + u8 reserved_at_8[0x18]; + + u8 syndrome[0x20]; + + u8 reserved_at_40[0x40]; +}; + +struct mlx5_ifc_alloc_sf_in_bits { + u8 opcode[0x10]; + u8 reserved_at_10[0x10]; + + u8 reserved_at_20[0x10]; + u8 op_mod[0x10]; + + u8 reserved_at_40[0x10]; + u8 function_id[0x10]; + + u8 reserved_at_60[0x20]; +}; + +struct mlx5_ifc_affiliated_event_header_bits { + u8 reserved_at_0[0x10]; + u8 obj_type[0x10]; + + u8 obj_id[0x20]; +}; + +enum { + MLX5_HCA_CAP_GENERAL_OBJECT_TYPES_ENCRYPTION_KEY = BIT(0xc), +}; + +enum { + MLX5_GENERAL_OBJECT_TYPES_ENCRYPTION_KEY = 0xc, +}; + +struct mlx5_ifc_encryption_key_obj_bits { + u8 modify_field_select[0x40]; + + u8 reserved_at_40[0x14]; + u8 key_size[0x4]; + u8 reserved_at_58[0x4]; + u8 key_type[0x4]; + + u8 reserved_at_60[0x8]; + u8 pd[0x18]; + + u8 reserved_at_80[0x180]; + u8 key[8][0x20]; + + u8 reserved_at_300[0x500]; +}; + +struct mlx5_ifc_create_encryption_key_in_bits { + struct mlx5_ifc_general_obj_in_cmd_hdr_bits general_obj_in_cmd_hdr; + struct mlx5_ifc_encryption_key_obj_bits encryption_key_object; +}; + +enum { + MLX5_GENERAL_OBJECT_TYPE_ENCRYPTION_KEY_KEY_SIZE_128 = 0x0, + MLX5_GENERAL_OBJECT_TYPE_ENCRYPTION_KEY_KEY_SIZE_256 = 0x1, +}; + +enum { + MLX5_GENERAL_OBJECT_TYPE_ENCRYPTION_KEY_TYPE_DEK = 0x1, +}; + +struct mlx5_ifc_tls_static_params_bits { + u8 const_2[0x2]; + u8 tls_version[0x4]; + u8 const_1[0x2]; + u8 reserved_at_8[0x14]; + u8 encryption_standard[0x4]; + + u8 reserved_at_20[0x20]; + + u8 initial_record_number[0x40]; + + u8 resync_tcp_sn[0x20]; + + u8 gcm_iv[0x20]; + + u8 implicit_iv[0x40]; + + u8 reserved_at_100[0x8]; + u8 dek_index[0x18]; + + u8 reserved_at_120[0xe0]; +}; + +struct mlx5_ifc_tls_progress_params_bits { + u8 reserved_at_0[0x8]; + u8 tisn[0x18]; + + u8 next_record_tcp_sn[0x20]; + + u8 hw_resync_tcp_sn[0x20]; + + u8 record_tracker_state[0x2]; + u8 auth_state[0x2]; + u8 reserved_at_64[0x4]; + u8 hw_offset_record_number[0x18]; }; #endif /* MLX5_IFC_H */ diff --git a/include/linux/mlx5/qp.h b/include/linux/mlx5/qp.h index 3ba4edbd17a6..ae63b1ae9004 100644 --- a/include/linux/mlx5/qp.h +++ b/include/linux/mlx5/qp.h @@ -37,7 +37,8 @@ #include <linux/mlx5/driver.h> #define MLX5_INVALID_LKEY 0x100 -#define MLX5_SIG_WQE_SIZE (MLX5_SEND_WQE_BB * 5) +/* UMR (3 WQE_BB's) + SIG (3 WQE_BB's) + PSV (mem) + PSV (wire) */ +#define MLX5_SIG_WQE_SIZE (MLX5_SEND_WQE_BB * 8) #define MLX5_DIF_SIZE 8 #define MLX5_STRIDE_BLOCK_OP 0x400 #define MLX5_CPY_GRD_MASK 0xc0 @@ -70,6 +71,7 @@ enum mlx5_qp_optpar { MLX5_QP_OPTPAR_CQN_RCV = 1 << 19, MLX5_QP_OPTPAR_DC_HS = 1 << 20, MLX5_QP_OPTPAR_DC_KEY = 1 << 21, + MLX5_QP_OPTPAR_COUNTER_SET_ID = 1 << 25, }; enum mlx5_qp_state { @@ -202,7 +204,12 @@ struct mlx5_wqe_ctrl_seg { u8 signature; u8 rsvd[2]; u8 fm_ce_se; - __be32 imm; + union { + __be32 general_id; + __be32 imm; + __be32 umr_mkey; + __be32 tisn; + }; }; #define MLX5_WQE_CTRL_DS_MASK 0x3f @@ -551,11 +558,6 @@ static inline struct mlx5_core_qp *__mlx5_qp_lookup(struct mlx5_core_dev *dev, u return radix_tree_lookup(&dev->priv.qp_table.tree, qpn); } -static inline struct mlx5_core_mkey *__mlx5_mr_lookup(struct mlx5_core_dev *dev, u32 key) -{ - return radix_tree_lookup(&dev->priv.mkey_table.tree, key); -} - int mlx5_core_create_dct(struct mlx5_core_dev *dev, struct mlx5_core_dct *qp, u32 *in, int inlen, diff --git a/include/linux/mlx5/vport.h b/include/linux/mlx5/vport.h index 3d1c6cdbbba7..16060fb9b5e5 100644 --- a/include/linux/mlx5/vport.h +++ b/include/linux/mlx5/vport.h @@ -44,9 +44,6 @@ MLX5_VPORT_UPLINK_PLACEHOLDER + \ MLX5_VPORT_ECPF_PLACEHOLDER(mdev)) -#define MLX5_TOTAL_VPORTS(mdev) (MLX5_SPECIAL_VPORTS(mdev) + \ - mlx5_core_max_vfs(mdev)) - #define MLX5_VPORT_MANAGER(mdev) \ (MLX5_CAP_GEN(mdev, vport_group_manager) && \ (MLX5_CAP_GEN(mdev, port_type) == MLX5_CAP_PORT_TYPE_ETH) && \ @@ -58,6 +55,7 @@ enum { MLX5_CAP_INLINE_MODE_NOT_REQUIRED, }; +/* Vport number for each function must keep unchanged */ enum { MLX5_VPORT_PF = 0x0, MLX5_VPORT_FIRST_VF = 0x1, @@ -69,7 +67,8 @@ u8 mlx5_query_vport_state(struct mlx5_core_dev *mdev, u8 opmod, u16 vport); int mlx5_modify_vport_admin_state(struct mlx5_core_dev *mdev, u8 opmod, u16 vport, u8 other_vport, u8 state); int mlx5_query_nic_vport_mac_address(struct mlx5_core_dev *mdev, - u16 vport, u8 *addr); + u16 vport, bool other, u8 *addr); +int mlx5_query_mac_address(struct mlx5_core_dev *mdev, u8 *addr); int mlx5_query_nic_vport_min_inline(struct mlx5_core_dev *mdev, u16 vport, u8 *min_inline); void mlx5_query_min_inline(struct mlx5_core_dev *mdev, u8 *min_inline); diff --git a/include/linux/mm.h b/include/linux/mm.h index dd0b5f4e1e45..cc292273e6ba 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -541,13 +541,30 @@ static inline void vma_set_anonymous(struct vm_area_struct *vma) vma->vm_ops = NULL; } +static inline bool vma_is_anonymous(struct vm_area_struct *vma) +{ + return !vma->vm_ops; +} + +#ifdef CONFIG_SHMEM +/* + * The vma_is_shmem is not inline because it is used only by slow + * paths in userfault. + */ +bool vma_is_shmem(struct vm_area_struct *vma); +#else +static inline bool vma_is_shmem(struct vm_area_struct *vma) { return false; } +#endif + +int vma_is_stack_for_current(struct vm_area_struct *vma); + /* flush_tlb_range() takes a vma, not a mm, and can care about flags */ #define TLB_FLUSH_VMA(mm,flags) { .vm_mm = (mm), .vm_flags = (flags) } struct mmu_gather; struct inode; -#if !defined(__HAVE_ARCH_PTE_DEVMAP) || !defined(CONFIG_TRANSPARENT_HUGEPAGE) +#if !defined(CONFIG_ARCH_HAS_PTE_DEVMAP) || !defined(CONFIG_TRANSPARENT_HUGEPAGE) static inline int pmd_devmap(pmd_t pmd) { return 0; @@ -633,6 +650,11 @@ static inline bool is_vmalloc_addr(const void *x) return false; #endif } + +#ifndef is_ioremap_addr +#define is_ioremap_addr(x) is_vmalloc_addr(x) +#endif + #ifdef CONFIG_MMU extern int is_vmalloc_or_module_addr(const void *x); #else @@ -783,6 +805,24 @@ static inline void set_compound_order(struct page *page, unsigned int order) page[1].compound_order = order; } +/* Returns the number of pages in this potentially compound page. */ +static inline unsigned long compound_nr(struct page *page) +{ + return 1UL << compound_order(page); +} + +/* Returns the number of bytes in this potentially compound page. */ +static inline unsigned long page_size(struct page *page) +{ + return PAGE_SIZE << compound_order(page); +} + +/* Returns the number of bits needed for the number of bytes in a page */ +static inline unsigned int page_shift(struct page *page) +{ + return PAGE_SHIFT + compound_order(page); +} + void free_compound_page(struct page *page); #ifdef CONFIG_MMU @@ -932,8 +972,6 @@ static inline bool is_zone_device_page(const struct page *page) #endif #ifdef CONFIG_DEV_PAGEMAP_OPS -void dev_pagemap_get_ops(void); -void dev_pagemap_put_ops(void); void __put_devmap_managed_page(struct page *page); DECLARE_STATIC_KEY_FALSE(devmap_managed_key); static inline bool put_devmap_managed_page(struct page *page) @@ -944,7 +982,6 @@ static inline bool put_devmap_managed_page(struct page *page) return false; switch (page->pgmap->type) { case MEMORY_DEVICE_PRIVATE: - case MEMORY_DEVICE_PUBLIC: case MEMORY_DEVICE_FS_DAX: __put_devmap_managed_page(page); return true; @@ -954,60 +991,28 @@ static inline bool put_devmap_managed_page(struct page *page) return false; } -static inline bool is_device_private_page(const struct page *page) -{ - return is_zone_device_page(page) && - page->pgmap->type == MEMORY_DEVICE_PRIVATE; -} - -static inline bool is_device_public_page(const struct page *page) -{ - return is_zone_device_page(page) && - page->pgmap->type == MEMORY_DEVICE_PUBLIC; -} - -#ifdef CONFIG_PCI_P2PDMA -static inline bool is_pci_p2pdma_page(const struct page *page) -{ - return is_zone_device_page(page) && - page->pgmap->type == MEMORY_DEVICE_PCI_P2PDMA; -} -#else /* CONFIG_PCI_P2PDMA */ -static inline bool is_pci_p2pdma_page(const struct page *page) -{ - return false; -} -#endif /* CONFIG_PCI_P2PDMA */ - #else /* CONFIG_DEV_PAGEMAP_OPS */ -static inline void dev_pagemap_get_ops(void) -{ -} - -static inline void dev_pagemap_put_ops(void) -{ -} - static inline bool put_devmap_managed_page(struct page *page) { return false; } +#endif /* CONFIG_DEV_PAGEMAP_OPS */ static inline bool is_device_private_page(const struct page *page) { - return false; -} - -static inline bool is_device_public_page(const struct page *page) -{ - return false; + return IS_ENABLED(CONFIG_DEV_PAGEMAP_OPS) && + IS_ENABLED(CONFIG_DEVICE_PRIVATE) && + is_zone_device_page(page) && + page->pgmap->type == MEMORY_DEVICE_PRIVATE; } static inline bool is_pci_p2pdma_page(const struct page *page) { - return false; + return IS_ENABLED(CONFIG_DEV_PAGEMAP_OPS) && + IS_ENABLED(CONFIG_PCI_P2PDMA) && + is_zone_device_page(page) && + page->pgmap->type == MEMORY_DEVICE_PCI_P2PDMA; } -#endif /* CONFIG_DEV_PAGEMAP_OPS */ /* 127: arbitrary random number, small enough to assemble well */ #define page_ref_zero_or_close_to_overflow(page) \ @@ -1070,8 +1075,9 @@ static inline void put_user_page(struct page *page) put_page(page); } -void put_user_pages_dirty(struct page **pages, unsigned long npages); -void put_user_pages_dirty_lock(struct page **pages, unsigned long npages); +void put_user_pages_dirty_lock(struct page **pages, unsigned long npages, + bool make_dirty); + void put_user_pages(struct page **pages, unsigned long npages); #if defined(CONFIG_SPARSEMEM) && !defined(CONFIG_SPARSEMEM_VMEMMAP) @@ -1418,7 +1424,11 @@ extern void pagefault_out_of_memory(void); extern void show_free_areas(unsigned int flags, nodemask_t *nodemask); +#ifdef CONFIG_MMU extern bool can_do_mlock(void); +#else +static inline bool can_do_mlock(void) { return false; } +#endif extern int user_shm_lock(size_t, struct user_struct *); extern void user_shm_unlock(size_t, struct user_struct *); @@ -1431,10 +1441,8 @@ struct zap_details { pgoff_t last_index; /* Highest page->index to unmap */ }; -struct page *_vm_normal_page(struct vm_area_struct *vma, unsigned long addr, - pte_t pte, bool with_public_device); -#define vm_normal_page(vma, addr, pte) _vm_normal_page(vma, addr, pte, false) - +struct page *vm_normal_page(struct vm_area_struct *vma, unsigned long addr, + pte_t pte); struct page *vm_normal_page_pmd(struct vm_area_struct *vma, unsigned long addr, pmd_t pmd); @@ -1445,54 +1453,8 @@ void zap_page_range(struct vm_area_struct *vma, unsigned long address, void unmap_vmas(struct mmu_gather *tlb, struct vm_area_struct *start_vma, unsigned long start, unsigned long end); -/** - * mm_walk - callbacks for walk_page_range - * @pud_entry: if set, called for each non-empty PUD (2nd-level) entry - * this handler should only handle pud_trans_huge() puds. - * the pmd_entry or pte_entry callbacks will be used for - * regular PUDs. - * @pmd_entry: if set, called for each non-empty PMD (3rd-level) entry - * this handler is required to be able to handle - * pmd_trans_huge() pmds. They may simply choose to - * split_huge_page() instead of handling it explicitly. - * @pte_entry: if set, called for each non-empty PTE (4th-level) entry - * @pte_hole: if set, called for each hole at all levels - * @hugetlb_entry: if set, called for each hugetlb entry - * @test_walk: caller specific callback function to determine whether - * we walk over the current vma or not. Returning 0 - * value means "do page table walk over the current vma," - * and a negative one means "abort current page table walk - * right now." 1 means "skip the current vma." - * @mm: mm_struct representing the target process of page table walk - * @vma: vma currently walked (NULL if walking outside vmas) - * @private: private data for callbacks' usage - * - * (see the comment on walk_page_range() for more details) - */ -struct mm_walk { - int (*pud_entry)(pud_t *pud, unsigned long addr, - unsigned long next, struct mm_walk *walk); - int (*pmd_entry)(pmd_t *pmd, unsigned long addr, - unsigned long next, struct mm_walk *walk); - int (*pte_entry)(pte_t *pte, unsigned long addr, - unsigned long next, struct mm_walk *walk); - int (*pte_hole)(unsigned long addr, unsigned long next, - struct mm_walk *walk); - int (*hugetlb_entry)(pte_t *pte, unsigned long hmask, - unsigned long addr, unsigned long next, - struct mm_walk *walk); - int (*test_walk)(unsigned long addr, unsigned long next, - struct mm_walk *walk); - struct mm_struct *mm; - struct vm_area_struct *vma; - void *private; -}; - struct mmu_notifier_range; -int walk_page_range(unsigned long addr, unsigned long end, - struct mm_walk *walk); -int walk_page_vma(struct vm_area_struct *vma, struct mm_walk *walk); void free_pgd_range(struct mmu_gather *tlb, unsigned long addr, unsigned long end, unsigned long floor, unsigned long ceiling); int copy_page_range(struct mm_struct *dst, struct mm_struct *src, @@ -1575,6 +1537,10 @@ long get_user_pages_unlocked(unsigned long start, unsigned long nr_pages, int get_user_pages_fast(unsigned long start, int nr_pages, unsigned int gup_flags, struct page **pages); +int account_locked_vm(struct mm_struct *mm, unsigned long pages, bool inc); +int __account_locked_vm(struct mm_struct *mm, unsigned long pages, bool inc, + struct task_struct *task, bool bypass_rlim); + /* Container for pinned pfns / pages */ struct frame_vector { unsigned int nr_allocated; /* Number of frames we have space for */ @@ -1648,23 +1614,6 @@ int clear_page_dirty_for_io(struct page *page); int get_cmdline(struct task_struct *task, char *buffer, int buflen); -static inline bool vma_is_anonymous(struct vm_area_struct *vma) -{ - return !vma->vm_ops; -} - -#ifdef CONFIG_SHMEM -/* - * The vma_is_shmem is not inline because it is used only by slow - * paths in userfault. - */ -bool vma_is_shmem(struct vm_area_struct *vma); -#else -static inline bool vma_is_shmem(struct vm_area_struct *vma) { return false; } -#endif - -int vma_is_stack_for_current(struct vm_area_struct *vma); - extern unsigned long move_page_tables(struct vm_area_struct *vma, unsigned long old_addr, struct vm_area_struct *new_vma, unsigned long new_addr, unsigned long len, @@ -1782,7 +1731,7 @@ static inline void sync_mm_rss(struct mm_struct *mm) } #endif -#ifndef __HAVE_ARCH_PTE_DEVMAP +#ifndef CONFIG_ARCH_HAS_PTE_DEVMAP static inline int pte_devmap(pte_t pte) { return 0; @@ -2000,7 +1949,7 @@ static inline void pgtable_init(void) pgtable_cache_init(); } -static inline bool pgtable_page_ctor(struct page *page) +static inline bool pgtable_pte_page_ctor(struct page *page) { if (!ptlock_init(page)) return false; @@ -2009,7 +1958,7 @@ static inline bool pgtable_page_ctor(struct page *page) return true; } -static inline void pgtable_page_dtor(struct page *page) +static inline void pgtable_pte_page_dtor(struct page *page) { ptlock_free(page); __ClearPageTable(page); @@ -2379,6 +2328,8 @@ extern int install_special_mapping(struct mm_struct *mm, unsigned long addr, unsigned long len, unsigned long flags, struct page **pages); +unsigned long randomize_stack_top(unsigned long stack_top); + extern unsigned long get_unmapped_area(struct file *, unsigned long, unsigned long, unsigned long, unsigned long); extern unsigned long mmap_region(struct file *file, unsigned long addr, @@ -2642,6 +2593,7 @@ struct page *follow_page(struct vm_area_struct *vma, unsigned long address, #define FOLL_COW 0x4000 /* internal GUP flag */ #define FOLL_ANON 0x8000 /* don't do file mappings */ #define FOLL_LONGTERM 0x10000 /* mapping lifetime is indefinite: see below */ +#define FOLL_SPLIT_PMD 0x20000 /* split huge pmd before returning */ /* * NOTE on FOLL_LONGTERM: @@ -2681,8 +2633,7 @@ static inline int vm_fault_to_errno(vm_fault_t vm_fault, int foll_flags) return 0; } -typedef int (*pte_fn_t)(pte_t *pte, pgtable_t token, unsigned long addr, - void *data); +typedef int (*pte_fn_t)(pte_t *pte, unsigned long addr, void *data); extern int apply_to_page_range(struct mm_struct *mm, unsigned long address, unsigned long size, pte_fn_t fn, void *data); @@ -2696,11 +2647,42 @@ static inline void kernel_poison_pages(struct page *page, int numpages, int enable) { } #endif -extern bool _debug_pagealloc_enabled; +#ifdef CONFIG_INIT_ON_ALLOC_DEFAULT_ON +DECLARE_STATIC_KEY_TRUE(init_on_alloc); +#else +DECLARE_STATIC_KEY_FALSE(init_on_alloc); +#endif +static inline bool want_init_on_alloc(gfp_t flags) +{ + if (static_branch_unlikely(&init_on_alloc) && + !page_poisoning_enabled()) + return true; + return flags & __GFP_ZERO; +} + +#ifdef CONFIG_INIT_ON_FREE_DEFAULT_ON +DECLARE_STATIC_KEY_TRUE(init_on_free); +#else +DECLARE_STATIC_KEY_FALSE(init_on_free); +#endif +static inline bool want_init_on_free(void) +{ + return static_branch_unlikely(&init_on_free) && + !page_poisoning_enabled(); +} + +#ifdef CONFIG_DEBUG_PAGEALLOC_ENABLE_DEFAULT +DECLARE_STATIC_KEY_TRUE(_debug_pagealloc_enabled); +#else +DECLARE_STATIC_KEY_FALSE(_debug_pagealloc_enabled); +#endif static inline bool debug_pagealloc_enabled(void) { - return IS_ENABLED(CONFIG_DEBUG_PAGEALLOC) && _debug_pagealloc_enabled; + if (!IS_ENABLED(CONFIG_DEBUG_PAGEALLOC)) + return false; + + return static_branch_unlikely(&_debug_pagealloc_enabled); } #if defined(CONFIG_DEBUG_PAGEALLOC) || defined(CONFIG_ARCH_HAS_SET_DIRECT_MAP) @@ -2756,11 +2738,17 @@ extern int randomize_va_space; #endif const char * arch_vma_name(struct vm_area_struct *vma); +#ifdef CONFIG_MMU void print_vma_addr(char *prefix, unsigned long rip); +#else +static inline void print_vma_addr(char *prefix, unsigned long rip) +{ +} +#endif void *sparse_buffer_alloc(unsigned long size); -struct page *sparse_mem_map_populate(unsigned long pnum, int nid, - struct vmem_altmap *altmap); +struct page * __populate_section_memmap(unsigned long pfn, + unsigned long nr_pages, int nid, struct vmem_altmap *altmap); pgd_t *vmemmap_pgd_populate(unsigned long addr, int node); p4d_t *vmemmap_p4d_populate(pgd_t *pgd, unsigned long addr, int node); pud_t *vmemmap_pud_populate(p4d_t *p4d, unsigned long addr, int node); @@ -2850,11 +2838,9 @@ extern long copy_huge_page_from_user(struct page *dst_page, bool allow_pagefault); #endif /* CONFIG_TRANSPARENT_HUGEPAGE || CONFIG_HUGETLBFS */ -extern struct page_ext_operations debug_guardpage_ops; - #ifdef CONFIG_DEBUG_PAGEALLOC extern unsigned int _debug_guardpage_minorder; -extern bool _debug_guardpage_enabled; +DECLARE_STATIC_KEY_FALSE(_debug_guardpage_enabled); static inline unsigned int debug_guardpage_minorder(void) { @@ -2863,21 +2849,15 @@ static inline unsigned int debug_guardpage_minorder(void) static inline bool debug_guardpage_enabled(void) { - return _debug_guardpage_enabled; + return static_branch_unlikely(&_debug_guardpage_enabled); } static inline bool page_is_guard(struct page *page) { - struct page_ext *page_ext; - if (!debug_guardpage_enabled()) return false; - page_ext = lookup_page_ext(page); - if (unlikely(!page_ext)) - return false; - - return test_bit(PAGE_EXT_DEBUG_GUARD, &page_ext->flags); + return PageGuard(page); } #else static inline unsigned int debug_guardpage_minorder(void) { return 0; } @@ -2891,5 +2871,12 @@ void __init setup_nr_node_ids(void); static inline void setup_nr_node_ids(void) {} #endif +extern int memcmp_pages(struct page *page1, struct page *page2); + +static inline int pages_identical(struct page *page1, struct page *page2) +{ + return !memcmp_pages(page1, page2); +} + #endif /* __KERNEL__ */ #endif /* _LINUX_MM_H */ diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h index 8ec38b11b361..5183e0d77dfa 100644 --- a/include/linux/mm_types.h +++ b/include/linux/mm_types.h @@ -25,7 +25,6 @@ struct address_space; struct mem_cgroup; -struct hmm; /* * Each physical page in the system has a struct page associated with @@ -139,6 +138,7 @@ struct page { struct { /* Second tail page of compound page */ unsigned long _compound_pad_1; /* compound_head */ unsigned long _compound_pad_2; + /* For both global and memcg */ struct list_head deferred_list; }; struct { /* Page table pages */ @@ -158,8 +158,17 @@ struct page { struct { /* ZONE_DEVICE pages */ /** @pgmap: Points to the hosting device page map. */ struct dev_pagemap *pgmap; - unsigned long hmm_data; - unsigned long _zd_pad_1; /* uses mapping */ + void *zone_device_data; + /* + * ZONE_DEVICE private pages are counted as being + * mapped so the next 3 words hold the mapping, index, + * and private fields from the source anonymous or + * page cache page while the page is migrated to device + * private memory. + * ZONE_DEVICE MEMORY_DEVICE_FS_DAX pages also + * use the mapping, index, and private fields when + * pmem backed DAX files are mapped. + */ }; /** @rcu_head: You can use this to free a page by RCU. */ @@ -329,7 +338,9 @@ struct vm_area_struct { struct file * vm_file; /* File we map to (can be NULL). */ void * vm_private_data; /* was vm_pte (shared mem) */ +#ifdef CONFIG_SWAP atomic_long_t swap_readahead_info; +#endif #ifndef CONFIG_MMU struct vm_region *vm_region; /* NOMMU mapping region */ #endif @@ -500,11 +511,6 @@ struct mm_struct { atomic_long_t hugetlb_usage; #endif struct work_struct async_put_work; - -#if IS_ENABLED(CONFIG_HMM) - /* HMM needs to track a few things per mm */ - struct hmm *hmm; -#endif } __randomize_layout; /* diff --git a/include/linux/mm_types_task.h b/include/linux/mm_types_task.h index d7016dcb245e..c1bc6731125c 100644 --- a/include/linux/mm_types_task.h +++ b/include/linux/mm_types_task.h @@ -36,6 +36,10 @@ struct vmacache { struct vm_area_struct *vmas[VMACACHE_SIZE]; }; +/* + * When updating this, please also update struct resident_page_types[] in + * kernel/fork.c + */ enum { MM_FILEPAGES, /* Resident file mapping pages */ MM_ANONPAGES, /* Resident anonymous pages */ diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index 7ac3755444d3..ba703384bea0 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h @@ -128,6 +128,7 @@ struct mmc_host_ops { int (*get_cd)(struct mmc_host *host); void (*enable_sdio_irq)(struct mmc_host *host, int enable); + /* Mandatory callback when using MMC_CAP2_SDIO_IRQ_NOTHREAD. */ void (*ack_sdio_irq)(struct mmc_host *host); /* optional callback for HC quirks */ @@ -367,6 +368,7 @@ struct mmc_host { #define MMC_CAP2_CQE (1 << 23) /* Has eMMC command queue engine */ #define MMC_CAP2_CQE_DCMD (1 << 24) /* CQE can issue a direct command */ #define MMC_CAP2_AVOID_3_3V (1 << 25) /* Host must negotiate down from 3.3V */ +#define MMC_CAP2_MERGE_CAPABLE (1 << 26) /* Host can merge a segment over the segment size */ int fixed_drv_type; /* fixed driver type for non-removable media */ @@ -396,6 +398,7 @@ struct mmc_host { unsigned int retune_paused:1; /* re-tuning is temporarily disabled */ unsigned int use_blk_mq:1; /* use blk-mq */ unsigned int retune_crc_disable:1; /* don't trigger retune upon crc */ + unsigned int can_dma_map_merge:1; /* merging can be used */ int rescan_disable; /* disable card detection */ int rescan_entered; /* used with nonremovable devices */ @@ -493,6 +496,15 @@ void mmc_command_done(struct mmc_host *host, struct mmc_request *mrq); void mmc_cqe_request_done(struct mmc_host *host, struct mmc_request *mrq); +/* + * May be called from host driver's system/runtime suspend/resume callbacks, + * to know if SDIO IRQs has been claimed. + */ +static inline bool sdio_irq_claimed(struct mmc_host *host) +{ + return host->sdio_irqs > 0; +} + static inline void mmc_signal_sdio_irq(struct mmc_host *host) { host->ops->enable_sdio_irq(host, 0); @@ -501,7 +513,6 @@ static inline void mmc_signal_sdio_irq(struct mmc_host *host) wake_up_process(host->sdio_irq_thread); } -void sdio_run_irqs(struct mmc_host *host); void sdio_signal_irq(struct mmc_host *host); #ifdef CONFIG_REGULATOR diff --git a/include/linux/mmu_notifier.h b/include/linux/mmu_notifier.h index b6c004bd9f6a..1bd8e6a09a3c 100644 --- a/include/linux/mmu_notifier.h +++ b/include/linux/mmu_notifier.h @@ -42,6 +42,10 @@ enum mmu_notifier_event { #ifdef CONFIG_MMU_NOTIFIER +#ifdef CONFIG_LOCKDEP +extern struct lockdep_map __mmu_notifier_invalidate_range_start_map; +#endif + /* * The mmu notifier_mm structure is allocated and installed in * mm->mmu_notifier_mm inside the mm_take_all_locks() protected @@ -211,6 +215,19 @@ struct mmu_notifier_ops { */ void (*invalidate_range)(struct mmu_notifier *mn, struct mm_struct *mm, unsigned long start, unsigned long end); + + /* + * These callbacks are used with the get/put interface to manage the + * lifetime of the mmu_notifier memory. alloc_notifier() returns a new + * notifier for use with the mm. + * + * free_notifier() is only called after the mmu_notifier has been + * fully put, calls to any ops callback are prevented and no ops + * callbacks are currently running. It is called from a SRCU callback + * and cannot sleep. + */ + struct mmu_notifier *(*alloc_notifier)(struct mm_struct *mm); + void (*free_notifier)(struct mmu_notifier *mn); }; /* @@ -227,6 +244,9 @@ struct mmu_notifier_ops { struct mmu_notifier { struct hlist_node hlist; const struct mmu_notifier_ops *ops; + struct mm_struct *mm; + struct rcu_head rcu; + unsigned int users; }; static inline int mm_has_notifiers(struct mm_struct *mm) @@ -234,14 +254,27 @@ static inline int mm_has_notifiers(struct mm_struct *mm) return unlikely(mm->mmu_notifier_mm); } +struct mmu_notifier *mmu_notifier_get_locked(const struct mmu_notifier_ops *ops, + struct mm_struct *mm); +static inline struct mmu_notifier * +mmu_notifier_get(const struct mmu_notifier_ops *ops, struct mm_struct *mm) +{ + struct mmu_notifier *ret; + + down_write(&mm->mmap_sem); + ret = mmu_notifier_get_locked(ops, mm); + up_write(&mm->mmap_sem); + return ret; +} +void mmu_notifier_put(struct mmu_notifier *mn); +void mmu_notifier_synchronize(void); + extern int mmu_notifier_register(struct mmu_notifier *mn, struct mm_struct *mm); extern int __mmu_notifier_register(struct mmu_notifier *mn, struct mm_struct *mm); extern void mmu_notifier_unregister(struct mmu_notifier *mn, struct mm_struct *mm); -extern void mmu_notifier_unregister_no_release(struct mmu_notifier *mn, - struct mm_struct *mm); extern void __mmu_notifier_mm_destroy(struct mm_struct *mm); extern void __mmu_notifier_release(struct mm_struct *mm); extern int __mmu_notifier_clear_flush_young(struct mm_struct *mm, @@ -310,25 +343,36 @@ static inline void mmu_notifier_change_pte(struct mm_struct *mm, static inline void mmu_notifier_invalidate_range_start(struct mmu_notifier_range *range) { + might_sleep(); + + lock_map_acquire(&__mmu_notifier_invalidate_range_start_map); if (mm_has_notifiers(range->mm)) { range->flags |= MMU_NOTIFIER_RANGE_BLOCKABLE; __mmu_notifier_invalidate_range_start(range); } + lock_map_release(&__mmu_notifier_invalidate_range_start_map); } static inline int mmu_notifier_invalidate_range_start_nonblock(struct mmu_notifier_range *range) { + int ret = 0; + + lock_map_acquire(&__mmu_notifier_invalidate_range_start_map); if (mm_has_notifiers(range->mm)) { range->flags &= ~MMU_NOTIFIER_RANGE_BLOCKABLE; - return __mmu_notifier_invalidate_range_start(range); + ret = __mmu_notifier_invalidate_range_start(range); } - return 0; + lock_map_release(&__mmu_notifier_invalidate_range_start_map); + return ret; } static inline void mmu_notifier_invalidate_range_end(struct mmu_notifier_range *range) { + if (mmu_notifier_range_blockable(range)) + might_sleep(); + if (mm_has_notifiers(range->mm)) __mmu_notifier_invalidate_range_end(range, false); } @@ -482,9 +526,6 @@ static inline void mmu_notifier_range_init(struct mmu_notifier_range *range, set_pte_at(___mm, ___address, __ptep, ___pte); \ }) -extern void mmu_notifier_call_srcu(struct rcu_head *rcu, - void (*func)(struct rcu_head *rcu)); - #else /* CONFIG_MMU_NOTIFIER */ struct mmu_notifier_range { @@ -581,6 +622,10 @@ static inline void mmu_notifier_mm_destroy(struct mm_struct *mm) #define pudp_huge_clear_flush_notify pudp_huge_clear_flush #define set_pte_at_notify set_pte_at +static inline void mmu_notifier_synchronize(void) +{ +} + #endif /* CONFIG_MMU_NOTIFIER */ #endif /* _LINUX_MMU_NOTIFIER_H */ diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h index 70394cabaf4e..bda20282746b 100644 --- a/include/linux/mmzone.h +++ b/include/linux/mmzone.h @@ -215,8 +215,9 @@ enum node_stat_item { NR_INACTIVE_FILE, /* " " " " " */ NR_ACTIVE_FILE, /* " " " " " */ NR_UNEVICTABLE, /* " " " " " */ - NR_SLAB_RECLAIMABLE, - NR_SLAB_UNRECLAIMABLE, + NR_SLAB_RECLAIMABLE, /* Please do not reorder this item */ + NR_SLAB_UNRECLAIMABLE, /* and this one without looking at + * memcg_flush_percpu_vmstats() first. */ NR_ISOLATED_ANON, /* Temporary isolated pages from anon lru */ NR_ISOLATED_FILE, /* Temporary isolated pages from file lru */ WORKINGSET_NODES, @@ -234,6 +235,8 @@ enum node_stat_item { NR_SHMEM, /* shmem pages (included tmpfs/GEM pages) */ NR_SHMEM_THPS, NR_SHMEM_PMDMAPPED, + NR_FILE_THPS, + NR_FILE_PMDMAPPED, NR_ANON_THPS, NR_UNSTABLE_NFS, /* NFS unstable pages */ NR_VMSCAN_WRITE, @@ -676,6 +679,14 @@ struct zonelist { extern struct page *mem_map; #endif +#ifdef CONFIG_TRANSPARENT_HUGEPAGE +struct deferred_split { + spinlock_t split_queue_lock; + struct list_head split_queue; + unsigned long split_queue_len; +}; +#endif + /* * On NUMA machines, each NUMA node would have a pg_data_t to describe * it's memory layout. On UMA machines there is a single pglist_data which @@ -755,9 +766,7 @@ typedef struct pglist_data { #endif /* CONFIG_DEFERRED_STRUCT_PAGE_INIT */ #ifdef CONFIG_TRANSPARENT_HUGEPAGE - spinlock_t split_queue_lock; - struct list_head split_queue; - unsigned long split_queue_len; + struct deferred_split deferred_split_queue; #endif /* Fields commonly accessed by the page reclaim scanner */ @@ -855,18 +864,6 @@ static inline int local_memory_node(int node_id) { return node_id; }; */ #define zone_idx(zone) ((zone) - (zone)->zone_pgdat->node_zones) -#ifdef CONFIG_ZONE_DEVICE -static inline bool is_dev_zone(const struct zone *zone) -{ - return zone_idx(zone) == ZONE_DEVICE; -} -#else -static inline bool is_dev_zone(const struct zone *zone) -{ - return false; -} -#endif - /* * Returns true if a zone has pages managed by the buddy allocator. * All the reclaim decisions have to use this function rather than @@ -1160,6 +1157,29 @@ static inline unsigned long section_nr_to_pfn(unsigned long sec) #define SECTION_ALIGN_UP(pfn) (((pfn) + PAGES_PER_SECTION - 1) & PAGE_SECTION_MASK) #define SECTION_ALIGN_DOWN(pfn) ((pfn) & PAGE_SECTION_MASK) +#define SUBSECTION_SHIFT 21 + +#define PFN_SUBSECTION_SHIFT (SUBSECTION_SHIFT - PAGE_SHIFT) +#define PAGES_PER_SUBSECTION (1UL << PFN_SUBSECTION_SHIFT) +#define PAGE_SUBSECTION_MASK (~(PAGES_PER_SUBSECTION-1)) + +#if SUBSECTION_SHIFT > SECTION_SIZE_BITS +#error Subsection size exceeds section size +#else +#define SUBSECTIONS_PER_SECTION (1UL << (SECTION_SIZE_BITS - SUBSECTION_SHIFT)) +#endif + +#define SUBSECTION_ALIGN_UP(pfn) ALIGN((pfn), PAGES_PER_SUBSECTION) +#define SUBSECTION_ALIGN_DOWN(pfn) ((pfn) & PAGE_SUBSECTION_MASK) + +struct mem_section_usage { + DECLARE_BITMAP(subsection_map, SUBSECTIONS_PER_SECTION); + /* See declaration of similar field in struct zone */ + unsigned long pageblock_flags[0]; +}; + +void subsection_map_init(unsigned long pfn, unsigned long nr_pages); + struct page; struct page_ext; struct mem_section { @@ -1177,8 +1197,7 @@ struct mem_section { */ unsigned long section_mem_map; - /* See declaration of similar field in struct zone */ - unsigned long *pageblock_flags; + struct mem_section_usage *usage; #ifdef CONFIG_PAGE_EXTENSION /* * If SPARSEMEM, pgdat doesn't have page_ext pointer. We use @@ -1209,6 +1228,11 @@ extern struct mem_section **mem_section; extern struct mem_section mem_section[NR_SECTION_ROOTS][SECTIONS_PER_ROOT]; #endif +static inline unsigned long *section_to_usemap(struct mem_section *ms) +{ + return ms->usage->pageblock_flags; +} + static inline struct mem_section *__nr_to_section(unsigned long nr) { #ifdef CONFIG_SPARSEMEM_EXTREME @@ -1219,8 +1243,8 @@ static inline struct mem_section *__nr_to_section(unsigned long nr) return NULL; return &mem_section[SECTION_NR_TO_ROOT(nr)][nr & SECTION_ROOT_MASK]; } -extern int __section_nr(struct mem_section* ms); -extern unsigned long usemap_size(void); +extern unsigned long __section_nr(struct mem_section *ms); +extern size_t mem_section_usage_size(void); /* * We use the lower bits of the mem_map pointer to store @@ -1238,7 +1262,8 @@ extern unsigned long usemap_size(void); #define SECTION_MARKED_PRESENT (1UL<<0) #define SECTION_HAS_MEM_MAP (1UL<<1) #define SECTION_IS_ONLINE (1UL<<2) -#define SECTION_MAP_LAST_BIT (1UL<<3) +#define SECTION_IS_EARLY (1UL<<3) +#define SECTION_MAP_LAST_BIT (1UL<<4) #define SECTION_MAP_MASK (~(SECTION_MAP_LAST_BIT-1)) #define SECTION_NID_SHIFT 3 @@ -1264,6 +1289,11 @@ static inline int valid_section(struct mem_section *section) return (section && (section->section_mem_map & SECTION_HAS_MEM_MAP)); } +static inline int early_section(struct mem_section *section) +{ + return (section && (section->section_mem_map & SECTION_IS_EARLY)); +} + static inline int valid_section_nr(unsigned long nr) { return valid_section(__nr_to_section(nr)); @@ -1291,14 +1321,42 @@ static inline struct mem_section *__pfn_to_section(unsigned long pfn) return __nr_to_section(pfn_to_section_nr(pfn)); } -extern int __highest_present_section_nr; +extern unsigned long __highest_present_section_nr; + +static inline int subsection_map_index(unsigned long pfn) +{ + return (pfn & ~(PAGE_SECTION_MASK)) / PAGES_PER_SUBSECTION; +} + +#ifdef CONFIG_SPARSEMEM_VMEMMAP +static inline int pfn_section_valid(struct mem_section *ms, unsigned long pfn) +{ + int idx = subsection_map_index(pfn); + + return test_bit(idx, ms->usage->subsection_map); +} +#else +static inline int pfn_section_valid(struct mem_section *ms, unsigned long pfn) +{ + return 1; +} +#endif #ifndef CONFIG_HAVE_ARCH_PFN_VALID static inline int pfn_valid(unsigned long pfn) { + struct mem_section *ms; + if (pfn_to_section_nr(pfn) >= NR_MEM_SECTIONS) return 0; - return valid_section(__nr_to_section(pfn_to_section_nr(pfn))); + ms = __nr_to_section(pfn_to_section_nr(pfn)); + if (!valid_section(ms)) + return 0; + /* + * Traditionally early sections always returned pfn_valid() for + * the entire section-sized span. + */ + return early_section(ms) || pfn_section_valid(ms, pfn); } #endif @@ -1330,6 +1388,7 @@ void sparse_init(void); #define sparse_init() do {} while (0) #define sparse_index_init(_sec, _nid) do {} while (0) #define pfn_present pfn_valid +#define subsection_map_init(_pfn, _nr_pages) do {} while (0) #endif /* CONFIG_SPARSEMEM */ /* diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h index 448621c32e4d..5714fd35a83c 100644 --- a/include/linux/mod_devicetable.h +++ b/include/linux/mod_devicetable.h @@ -16,6 +16,25 @@ typedef unsigned long kernel_ulong_t; #define PCI_ANY_ID (~0) +/** + * struct pci_device_id - PCI device ID structure + * @vendor: Vendor ID to match (or PCI_ANY_ID) + * @device: Device ID to match (or PCI_ANY_ID) + * @subvendor: Subsystem vendor ID to match (or PCI_ANY_ID) + * @subdevice: Subsystem device ID to match (or PCI_ANY_ID) + * @class: Device class, subclass, and "interface" to match. + * See Appendix D of the PCI Local Bus Spec or + * include/linux/pci_ids.h for a full list of classes. + * Most drivers do not need to specify class/class_mask + * as vendor/device is normally sufficient. + * @class_mask: Limit which sub-fields of the class field are compared. + * See drivers/scsi/sym53c8xx_2/ for example of usage. + * @driver_data: Data private to the driver. + * Most drivers don't need to use driver_data field. + * Best practice is to use driver_data as an index + * into a static list of equivalent device types, + * instead of using it as a pointer. + */ struct pci_device_id { __u32 vendor, device; /* Vendor and device ID or PCI_ANY_ID*/ __u32 subvendor, subdevice; /* Subsystem ID's or PCI_ANY_ID */ @@ -257,17 +276,17 @@ struct pcmcia_device_id { __u16 match_flags; __u16 manf_id; - __u16 card_id; + __u16 card_id; - __u8 func_id; + __u8 func_id; /* for real multi-function devices */ - __u8 function; + __u8 function; /* for pseudo multi-function devices */ - __u8 device_no; + __u8 device_no; - __u32 prod_id_hash[4]; + __u32 prod_id_hash[4]; /* not matched against in kernelspace */ const char * prod_id[4]; @@ -795,9 +814,11 @@ struct tee_client_device_id { /** * struct wmi_device_id - WMI device identifier * @guid_string: 36 char string of the form fa50ff2b-f2e8-45de-83fa-65417f2f49ba + * @context: pointer to driver specific data */ struct wmi_device_id { const char guid_string[UUID_STRING_LEN+1]; + const void *context; }; #endif /* LINUX_MOD_DEVICETABLE_H */ diff --git a/include/linux/module.h b/include/linux/module.h index 188998d3dca9..6d20895e7739 100644 --- a/include/linux/module.h +++ b/include/linux/module.h @@ -21,13 +21,11 @@ #include <linux/rbtree_latch.h> #include <linux/error-injection.h> #include <linux/tracepoint-defs.h> +#include <linux/srcu.h> #include <linux/percpu.h> #include <asm/module.h> -/* In stripped ARM and x86-64 modules, ~ is surprisingly rare. */ -#define MODULE_SIG_STRING "~Module signature appended~\n" - /* Not Yet Implemented */ #define MODULE_SUPPORTED_DEVICE(name) @@ -275,6 +273,8 @@ extern typeof(name) __mod_##type##__##name##_device_table \ * files require multiple MODULE_FIRMWARE() specifiers */ #define MODULE_FIRMWARE(_firmware) MODULE_INFO(firmware, _firmware) +#define MODULE_IMPORT_NS(ns) MODULE_INFO(import_ns, #ns) + struct notifier_block; #ifdef CONFIG_MODULES @@ -450,6 +450,10 @@ struct module { unsigned int num_tracepoints; tracepoint_ptr_t *tracepoints_ptrs; #endif +#ifdef CONFIG_TREE_SRCU + unsigned int num_srcu_structs; + struct srcu_struct **srcu_struct_ptrs; +#endif #ifdef CONFIG_BPF_EVENTS unsigned int num_bpf_raw_events; struct bpf_raw_event_map *bpf_raw_events; diff --git a/include/linux/module_signature.h b/include/linux/module_signature.h new file mode 100644 index 000000000000..7eb4b00381ac --- /dev/null +++ b/include/linux/module_signature.h @@ -0,0 +1,46 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Module signature handling. + * + * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + */ + +#ifndef _LINUX_MODULE_SIGNATURE_H +#define _LINUX_MODULE_SIGNATURE_H + +#include <linux/types.h> + +/* In stripped ARM and x86-64 modules, ~ is surprisingly rare. */ +#define MODULE_SIG_STRING "~Module signature appended~\n" + +enum pkey_id_type { + PKEY_ID_PGP, /* OpenPGP generated key ID */ + PKEY_ID_X509, /* X.509 arbitrary subjectKeyIdentifier */ + PKEY_ID_PKCS7, /* Signature in PKCS#7 message */ +}; + +/* + * Module signature information block. + * + * The constituents of the signature section are, in order: + * + * - Signer's name + * - Key identifier + * - Signature data + * - Information block + */ +struct module_signature { + u8 algo; /* Public-key crypto algorithm [0] */ + u8 hash; /* Digest algorithm [0] */ + u8 id_type; /* Key identifier type [PKEY_ID_PKCS7] */ + u8 signer_len; /* Length of signer's name [0] */ + u8 key_id_len; /* Length of key identifier [0] */ + u8 __pad[3]; + __be32 sig_len; /* Length of signature data */ +}; + +int mod_check_sig(const struct module_signature *ms, size_t file_len, + const char *name); + +#endif /* _LINUX_MODULE_SIGNATURE_H */ diff --git a/include/linux/moduleloader.h b/include/linux/moduleloader.h index 31013c2effd3..5229c18025e9 100644 --- a/include/linux/moduleloader.h +++ b/include/linux/moduleloader.h @@ -29,6 +29,11 @@ void *module_alloc(unsigned long size); /* Free memory returned from module_alloc. */ void module_memfree(void *module_region); +/* Determines if the section name is an exit section (that is only used during + * module unloading) + */ +bool module_exit_section(const char *name); + /* * Apply the given relocation to the (simplified) ELF. Return -error * or 0. diff --git a/include/linux/moxtet.h b/include/linux/moxtet.h new file mode 100644 index 000000000000..490db6886dcc --- /dev/null +++ b/include/linux/moxtet.h @@ -0,0 +1,109 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Turris Mox module configuration bus driver + * + * Copyright (C) 2019 Marek Behun <marek.behun@nic.cz> + */ + +#ifndef __LINUX_MOXTET_H +#define __LINUX_MOXTET_H + +#include <linux/device.h> +#include <linux/irq.h> +#include <linux/irqdomain.h> +#include <linux/mutex.h> + +#define TURRIS_MOX_MAX_MODULES 10 + +enum turris_mox_cpu_module_id { + TURRIS_MOX_CPU_ID_EMMC = 0x00, + TURRIS_MOX_CPU_ID_SD = 0x10, +}; + +enum turris_mox_module_id { + TURRIS_MOX_MODULE_FIRST = 0x01, + + TURRIS_MOX_MODULE_SFP = 0x01, + TURRIS_MOX_MODULE_PCI = 0x02, + TURRIS_MOX_MODULE_TOPAZ = 0x03, + TURRIS_MOX_MODULE_PERIDOT = 0x04, + TURRIS_MOX_MODULE_USB3 = 0x05, + TURRIS_MOX_MODULE_PCI_BRIDGE = 0x06, + + TURRIS_MOX_MODULE_LAST = 0x06, +}; + +#define MOXTET_NIRQS 16 + +extern struct bus_type moxtet_type; + +struct moxtet { + struct device *dev; + struct mutex lock; + u8 modules[TURRIS_MOX_MAX_MODULES]; + int count; + u8 tx[TURRIS_MOX_MAX_MODULES]; + int dev_irq; + struct { + struct irq_domain *domain; + struct irq_chip chip; + unsigned long masked, exists; + struct moxtet_irqpos { + u8 idx; + u8 bit; + } position[MOXTET_NIRQS]; + } irq; +#ifdef CONFIG_DEBUG_FS + struct dentry *debugfs_root; +#endif +}; + +struct moxtet_driver { + const enum turris_mox_module_id *id_table; + struct device_driver driver; +}; + +static inline struct moxtet_driver * +to_moxtet_driver(struct device_driver *drv) +{ + if (!drv) + return NULL; + return container_of(drv, struct moxtet_driver, driver); +} + +extern int __moxtet_register_driver(struct module *owner, + struct moxtet_driver *mdrv); + +static inline void moxtet_unregister_driver(struct moxtet_driver *mdrv) +{ + if (mdrv) + driver_unregister(&mdrv->driver); +} + +#define moxtet_register_driver(driver) \ + __moxtet_register_driver(THIS_MODULE, driver) + +#define module_moxtet_driver(__moxtet_driver) \ + module_driver(__moxtet_driver, moxtet_register_driver, \ + moxtet_unregister_driver) + +struct moxtet_device { + struct device dev; + struct moxtet *moxtet; + enum turris_mox_module_id id; + unsigned int idx; +}; + +extern int moxtet_device_read(struct device *dev); +extern int moxtet_device_write(struct device *dev, u8 val); +extern int moxtet_device_written(struct device *dev); + +static inline struct moxtet_device * +to_moxtet_device(struct device *dev) +{ + if (!dev) + return NULL; + return container_of(dev, struct moxtet_device, dev); +} + +#endif /* __LINUX_MOXTET_H */ diff --git a/include/linux/msi.h b/include/linux/msi.h index d48e919d55ae..8ad679e9d9c0 100644 --- a/include/linux/msi.h +++ b/include/linux/msi.h @@ -64,6 +64,10 @@ struct ti_sci_inta_msi_desc { * @msg: The last set MSI message cached for reuse * @affinity: Optional pointer to a cpu affinity mask for this descriptor * + * @write_msi_msg: Callback that may be called when the MSI message + * address or data changes + * @write_msi_msg_data: Data parameter for the callback. + * * @masked: [PCI MSI/X] Mask bits * @is_msix: [PCI MSI/X] True if MSI-X * @multiple: [PCI MSI/X] log2 num of messages allocated @@ -90,6 +94,9 @@ struct msi_desc { const void *iommu_cookie; #endif + void (*write_msi_msg)(struct msi_desc *entry, void *data); + void *write_msi_msg_data; + union { /* PCI MSI/X specific data */ struct { @@ -100,6 +107,7 @@ struct msi_desc { u8 multi_cap : 3; u8 maskbit : 1; u8 is_64 : 1; + u8 is_virtual : 1; u16 entry_nr; unsigned default_irq; } msi_attrib; diff --git a/include/linux/mtd/cfi.h b/include/linux/mtd/cfi.h index 208c87cf2e3e..c98a21108688 100644 --- a/include/linux/mtd/cfi.h +++ b/include/linux/mtd/cfi.h @@ -219,6 +219,13 @@ struct cfi_pri_amdstd { uint8_t VppMin; uint8_t VppMax; uint8_t TopBottom; + /* Below field are added from version 1.5 */ + uint8_t ProgramSuspend; + uint8_t UnlockBypass; + uint8_t SecureSiliconSector; + uint8_t SoftwareFeatures; +#define CFI_POLL_STATUS_REG BIT(0) +#define CFI_POLL_DQ BIT(1) } __packed; /* Vendor-Specific PRI for Atmel chips (command set 0x0002) */ diff --git a/include/linux/mtd/hyperbus.h b/include/linux/mtd/hyperbus.h new file mode 100644 index 000000000000..2dfe65964f6e --- /dev/null +++ b/include/linux/mtd/hyperbus.h @@ -0,0 +1,84 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/ + */ + +#ifndef __LINUX_MTD_HYPERBUS_H__ +#define __LINUX_MTD_HYPERBUS_H__ + +#include <linux/mtd/map.h> + +enum hyperbus_memtype { + HYPERFLASH, + HYPERRAM, +}; + +/** + * struct hyperbus_device - struct representing HyperBus slave device + * @map: map_info struct for accessing MMIO HyperBus flash memory + * @np: pointer to HyperBus slave device node + * @mtd: pointer to MTD struct + * @ctlr: pointer to HyperBus controller struct + * @memtype: type of memory device: HyperFlash or HyperRAM + */ + +struct hyperbus_device { + struct map_info map; + struct device_node *np; + struct mtd_info *mtd; + struct hyperbus_ctlr *ctlr; + enum hyperbus_memtype memtype; +}; + +/** + * struct hyperbus_ops - struct representing custom HyperBus operations + * @read16: read 16 bit of data from flash in a single burst. Used to read + * from non default address space, such as ID/CFI space + * @write16: write 16 bit of data to flash in a single burst. Used to + * send cmd to flash or write single 16 bit word at a time. + * @copy_from: copy data from flash memory + * @copy_to: copy data to flash memory + * @calibrate: calibrate HyperBus controller + */ + +struct hyperbus_ops { + u16 (*read16)(struct hyperbus_device *hbdev, unsigned long addr); + void (*write16)(struct hyperbus_device *hbdev, + unsigned long addr, u16 val); + void (*copy_from)(struct hyperbus_device *hbdev, void *to, + unsigned long from, ssize_t len); + void (*copy_to)(struct hyperbus_device *dev, unsigned long to, + const void *from, ssize_t len); + int (*calibrate)(struct hyperbus_device *dev); +}; + +/** + * struct hyperbus_ctlr - struct representing HyperBus controller + * @dev: pointer to HyperBus controller device + * @calibrated: flag to indicate ctlr calibration sequence is complete + * @ops: HyperBus controller ops + */ +struct hyperbus_ctlr { + struct device *dev; + bool calibrated; + + const struct hyperbus_ops *ops; +}; + +/** + * hyperbus_register_device - probe and register a HyperBus slave memory device + * @hbdev: hyperbus_device struct with dev, np and ctlr field populated + * + * Return: 0 for success, others for failure. + */ +int hyperbus_register_device(struct hyperbus_device *hbdev); + +/** + * hyperbus_unregister_device - deregister HyperBus slave memory device + * @hbdev: hyperbus_device to be unregistered + * + * Return: 0 for success, others for failure. + */ +int hyperbus_unregister_device(struct hyperbus_device *hbdev); + +#endif /* __LINUX_MTD_HYPERBUS_H__ */ diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h index 936a3fdb48b5..249e8d9bfbcd 100644 --- a/include/linux/mtd/mtd.h +++ b/include/linux/mtd/mtd.h @@ -189,6 +189,9 @@ struct module; /* only needed for owner field in mtd_info */ */ struct mtd_debug_info { struct dentry *dfs_dir; + + const char *partname; + const char *partid; }; struct mtd_info { @@ -316,6 +319,12 @@ struct mtd_info { int (*_get_device) (struct mtd_info *mtd); void (*_put_device) (struct mtd_info *mtd); + /* + * flag indicates a panic write, low level drivers can take appropriate + * action if required to ensure writes go through + */ + bool oops_panic_write; + struct notifier_block reboot_notifier; /* default mode before reboot */ /* ECC status information */ diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h index cebc38b6d6f5..0c7483843a32 100644 --- a/include/linux/mtd/nand.h +++ b/include/linux/mtd/nand.h @@ -346,7 +346,7 @@ static inline unsigned int nanddev_ntargets(const struct nand_device *nand) } /** - * nanddev_neraseblocks() - Get the total number of erasablocks + * nanddev_neraseblocks() - Get the total number of eraseblocks * @nand: NAND device * * Return: the total number of eraseblocks exposed by @nand. diff --git a/include/linux/mtd/onenand_regs.h b/include/linux/mtd/onenand_regs.h index 2d12a1b18742..5f728407a579 100644 --- a/include/linux/mtd/onenand_regs.h +++ b/include/linux/mtd/onenand_regs.h @@ -77,6 +77,7 @@ #define ONENAND_DEVICE_DENSITY_1Gb (0x003) #define ONENAND_DEVICE_DENSITY_2Gb (0x004) #define ONENAND_DEVICE_DENSITY_4Gb (0x005) +#define ONENAND_DEVICE_DENSITY_8Gb (0x006) /* * Version ID Register F002h (R) diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h index ac3884a28dea..4ab9bccfcde0 100644 --- a/include/linux/mtd/rawnand.h +++ b/include/linux/mtd/rawnand.h @@ -874,6 +874,42 @@ int nand_op_parser_exec_op(struct nand_chip *chip, const struct nand_op_parser *parser, const struct nand_operation *op, bool check_only); +static inline void nand_op_trace(const char *prefix, + const struct nand_op_instr *instr) +{ +#if IS_ENABLED(CONFIG_DYNAMIC_DEBUG) || defined(DEBUG) + switch (instr->type) { + case NAND_OP_CMD_INSTR: + pr_debug("%sCMD [0x%02x]\n", prefix, + instr->ctx.cmd.opcode); + break; + case NAND_OP_ADDR_INSTR: + pr_debug("%sADDR [%d cyc: %*ph]\n", prefix, + instr->ctx.addr.naddrs, + instr->ctx.addr.naddrs < 64 ? + instr->ctx.addr.naddrs : 64, + instr->ctx.addr.addrs); + break; + case NAND_OP_DATA_IN_INSTR: + pr_debug("%sDATA_IN [%d B%s]\n", prefix, + instr->ctx.data.len, + instr->ctx.data.force_8bit ? + ", force 8-bit" : ""); + break; + case NAND_OP_DATA_OUT_INSTR: + pr_debug("%sDATA_OUT [%d B%s]\n", prefix, + instr->ctx.data.len, + instr->ctx.data.force_8bit ? + ", force 8-bit" : ""); + break; + case NAND_OP_WAITRDY_INSTR: + pr_debug("%sWAITRDY [max %d ms]\n", prefix, + instr->ctx.waitrdy.timeout_ms); + break; + } +#endif +} + /** * struct nand_controller_ops - Controller operations * diff --git a/include/linux/mtd/sharpsl.h b/include/linux/mtd/sharpsl.h index 01306ebe266d..d2c3cf29e0d1 100644 --- a/include/linux/mtd/sharpsl.h +++ b/include/linux/mtd/sharpsl.h @@ -5,6 +5,9 @@ * Copyright (C) 2008 Dmitry Baryshkov */ +#ifndef _MTD_SHARPSL_H +#define _MTD_SHARPSL_H + #include <linux/mtd/rawnand.h> #include <linux/mtd/nand_ecc.h> #include <linux/mtd/partitions.h> @@ -16,3 +19,5 @@ struct sharpsl_nand_platform_data { unsigned int nr_partitions; const char *const *part_parsers; }; + +#endif /* _MTD_SHARPSL_H */ diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h index 9f57cdfcc93d..fc0b4b19c900 100644 --- a/include/linux/mtd/spi-nor.h +++ b/include/linux/mtd/spi-nor.h @@ -9,6 +9,7 @@ #include <linux/bitops.h> #include <linux/mtd/cfi.h> #include <linux/mtd/mtd.h> +#include <linux/spi/spi-mem.h> /* * Manufacturer IDs @@ -224,7 +225,6 @@ static inline u8 spi_nor_get_protocol_width(enum spi_nor_protocol proto) return spi_nor_get_protocol_data_nbits(proto); } -#define SPI_NOR_MAX_CMD_SIZE 8 enum spi_nor_ops { SPI_NOR_OPS_READ = 0, SPI_NOR_OPS_WRITE, @@ -237,12 +237,12 @@ enum spi_nor_option_flags { SNOR_F_USE_FSR = BIT(0), SNOR_F_HAS_SR_TB = BIT(1), SNOR_F_NO_OP_CHIP_ERASE = BIT(2), - SNOR_F_S3AN_ADDR_DEFAULT = BIT(3), - SNOR_F_READY_XSR_RDY = BIT(4), - SNOR_F_USE_CLSR = BIT(5), - SNOR_F_BROKEN_RESET = BIT(6), - SNOR_F_4B_OPCODES = BIT(7), - SNOR_F_HAS_4BAIT = BIT(8), + SNOR_F_READY_XSR_RDY = BIT(3), + SNOR_F_USE_CLSR = BIT(4), + SNOR_F_BROKEN_RESET = BIT(5), + SNOR_F_4B_OPCODES = BIT(6), + SNOR_F_HAS_4BAIT = BIT(7), + SNOR_F_HAS_LOCK = BIT(8), }; /** @@ -334,6 +334,195 @@ struct spi_nor_erase_map { }; /** + * struct spi_nor_hwcaps - Structure for describing the hardware capabilies + * supported by the SPI controller (bus master). + * @mask: the bitmask listing all the supported hw capabilies + */ +struct spi_nor_hwcaps { + u32 mask; +}; + +/* + *(Fast) Read capabilities. + * MUST be ordered by priority: the higher bit position, the higher priority. + * As a matter of performances, it is relevant to use Octal SPI protocols first, + * then Quad SPI protocols before Dual SPI protocols, Fast Read and lastly + * (Slow) Read. + */ +#define SNOR_HWCAPS_READ_MASK GENMASK(14, 0) +#define SNOR_HWCAPS_READ BIT(0) +#define SNOR_HWCAPS_READ_FAST BIT(1) +#define SNOR_HWCAPS_READ_1_1_1_DTR BIT(2) + +#define SNOR_HWCAPS_READ_DUAL GENMASK(6, 3) +#define SNOR_HWCAPS_READ_1_1_2 BIT(3) +#define SNOR_HWCAPS_READ_1_2_2 BIT(4) +#define SNOR_HWCAPS_READ_2_2_2 BIT(5) +#define SNOR_HWCAPS_READ_1_2_2_DTR BIT(6) + +#define SNOR_HWCAPS_READ_QUAD GENMASK(10, 7) +#define SNOR_HWCAPS_READ_1_1_4 BIT(7) +#define SNOR_HWCAPS_READ_1_4_4 BIT(8) +#define SNOR_HWCAPS_READ_4_4_4 BIT(9) +#define SNOR_HWCAPS_READ_1_4_4_DTR BIT(10) + +#define SNOR_HWCAPS_READ_OCTAL GENMASK(14, 11) +#define SNOR_HWCAPS_READ_1_1_8 BIT(11) +#define SNOR_HWCAPS_READ_1_8_8 BIT(12) +#define SNOR_HWCAPS_READ_8_8_8 BIT(13) +#define SNOR_HWCAPS_READ_1_8_8_DTR BIT(14) + +/* + * Page Program capabilities. + * MUST be ordered by priority: the higher bit position, the higher priority. + * Like (Fast) Read capabilities, Octal/Quad SPI protocols are preferred to the + * legacy SPI 1-1-1 protocol. + * Note that Dual Page Programs are not supported because there is no existing + * JEDEC/SFDP standard to define them. Also at this moment no SPI flash memory + * implements such commands. + */ +#define SNOR_HWCAPS_PP_MASK GENMASK(22, 16) +#define SNOR_HWCAPS_PP BIT(16) + +#define SNOR_HWCAPS_PP_QUAD GENMASK(19, 17) +#define SNOR_HWCAPS_PP_1_1_4 BIT(17) +#define SNOR_HWCAPS_PP_1_4_4 BIT(18) +#define SNOR_HWCAPS_PP_4_4_4 BIT(19) + +#define SNOR_HWCAPS_PP_OCTAL GENMASK(22, 20) +#define SNOR_HWCAPS_PP_1_1_8 BIT(20) +#define SNOR_HWCAPS_PP_1_8_8 BIT(21) +#define SNOR_HWCAPS_PP_8_8_8 BIT(22) + +#define SNOR_HWCAPS_X_X_X (SNOR_HWCAPS_READ_2_2_2 | \ + SNOR_HWCAPS_READ_4_4_4 | \ + SNOR_HWCAPS_READ_8_8_8 | \ + SNOR_HWCAPS_PP_4_4_4 | \ + SNOR_HWCAPS_PP_8_8_8) + +#define SNOR_HWCAPS_DTR (SNOR_HWCAPS_READ_1_1_1_DTR | \ + SNOR_HWCAPS_READ_1_2_2_DTR | \ + SNOR_HWCAPS_READ_1_4_4_DTR | \ + SNOR_HWCAPS_READ_1_8_8_DTR) + +#define SNOR_HWCAPS_ALL (SNOR_HWCAPS_READ_MASK | \ + SNOR_HWCAPS_PP_MASK) + +struct spi_nor_read_command { + u8 num_mode_clocks; + u8 num_wait_states; + u8 opcode; + enum spi_nor_protocol proto; +}; + +struct spi_nor_pp_command { + u8 opcode; + enum spi_nor_protocol proto; +}; + +enum spi_nor_read_command_index { + SNOR_CMD_READ, + SNOR_CMD_READ_FAST, + SNOR_CMD_READ_1_1_1_DTR, + + /* Dual SPI */ + SNOR_CMD_READ_1_1_2, + SNOR_CMD_READ_1_2_2, + SNOR_CMD_READ_2_2_2, + SNOR_CMD_READ_1_2_2_DTR, + + /* Quad SPI */ + SNOR_CMD_READ_1_1_4, + SNOR_CMD_READ_1_4_4, + SNOR_CMD_READ_4_4_4, + SNOR_CMD_READ_1_4_4_DTR, + + /* Octal SPI */ + SNOR_CMD_READ_1_1_8, + SNOR_CMD_READ_1_8_8, + SNOR_CMD_READ_8_8_8, + SNOR_CMD_READ_1_8_8_DTR, + + SNOR_CMD_READ_MAX +}; + +enum spi_nor_pp_command_index { + SNOR_CMD_PP, + + /* Quad SPI */ + SNOR_CMD_PP_1_1_4, + SNOR_CMD_PP_1_4_4, + SNOR_CMD_PP_4_4_4, + + /* Octal SPI */ + SNOR_CMD_PP_1_1_8, + SNOR_CMD_PP_1_8_8, + SNOR_CMD_PP_8_8_8, + + SNOR_CMD_PP_MAX +}; + +/* Forward declaration that will be used in 'struct spi_nor_flash_parameter' */ +struct spi_nor; + +/** + * struct spi_nor_locking_ops - SPI NOR locking methods + * @lock: lock a region of the SPI NOR. + * @unlock: unlock a region of the SPI NOR. + * @is_locked: check if a region of the SPI NOR is completely locked + */ +struct spi_nor_locking_ops { + int (*lock)(struct spi_nor *nor, loff_t ofs, uint64_t len); + int (*unlock)(struct spi_nor *nor, loff_t ofs, uint64_t len); + int (*is_locked)(struct spi_nor *nor, loff_t ofs, uint64_t len); +}; + +/** + * struct spi_nor_flash_parameter - SPI NOR flash parameters and settings. + * Includes legacy flash parameters and settings that can be overwritten + * by the spi_nor_fixups hooks, or dynamically when parsing the JESD216 + * Serial Flash Discoverable Parameters (SFDP) tables. + * + * @size: the flash memory density in bytes. + * @page_size: the page size of the SPI NOR flash memory. + * @hwcaps: describes the read and page program hardware + * capabilities. + * @reads: read capabilities ordered by priority: the higher index + * in the array, the higher priority. + * @page_programs: page program capabilities ordered by priority: the + * higher index in the array, the higher priority. + * @erase_map: the erase map parsed from the SFDP Sector Map Parameter + * Table. + * @quad_enable: enables SPI NOR quad mode. + * @set_4byte: puts the SPI NOR in 4 byte addressing mode. + * @convert_addr: converts an absolute address into something the flash + * will understand. Particularly useful when pagesize is + * not a power-of-2. + * @setup: configures the SPI NOR memory. Useful for SPI NOR + * flashes that have peculiarities to the SPI NOR standard + * e.g. different opcodes, specific address calculation, + * page size, etc. + * @locking_ops: SPI NOR locking methods. + */ +struct spi_nor_flash_parameter { + u64 size; + u32 page_size; + + struct spi_nor_hwcaps hwcaps; + struct spi_nor_read_command reads[SNOR_CMD_READ_MAX]; + struct spi_nor_pp_command page_programs[SNOR_CMD_PP_MAX]; + + struct spi_nor_erase_map erase_map; + + int (*quad_enable)(struct spi_nor *nor); + int (*set_4byte)(struct spi_nor *nor, bool enable); + u32 (*convert_addr)(struct spi_nor *nor, u32 addr); + int (*setup)(struct spi_nor *nor, const struct spi_nor_hwcaps *hwcaps); + + const struct spi_nor_locking_ops *locking_ops; +}; + +/** * struct flash_info - Forward declaration of a structure used internally by * spi_nor_scan() */ @@ -344,6 +533,10 @@ struct flash_info; * @mtd: point to a mtd_info structure * @lock: the lock for the read/write/erase/lock/unlock operations * @dev: point to a spi device, or a spi nor controller device. + * @spimem: point to the spi mem device + * @bouncebuf: bounce buffer used when the buffer passed by the MTD + * layer is not DMA-able + * @bouncebuf_size: size of the bounce buffer * @info: spi-nor part JDEC MFR id and other info * @page_size: the page size of the SPI NOR * @addr_width: number of address bytes @@ -356,8 +549,6 @@ struct flash_info; * @read_proto: the SPI protocol for read operations * @write_proto: the SPI protocol for write operations * @reg_proto the SPI protocol for read_reg/write_reg/erase operations - * @cmd_buf: used by the write_reg - * @erase_map: the erase map of the SPI NOR * @prepare: [OPTIONAL] do some preparations for the * read/write/erase/lock/unlock operations * @unprepare: [OPTIONAL] do some post work after the @@ -369,19 +560,21 @@ struct flash_info; * @erase: [DRIVER-SPECIFIC] erase a sector of the SPI NOR * at the offset @offs; if not provided by the driver, * spi-nor will send the erase opcode via write_reg() - * @flash_lock: [FLASH-SPECIFIC] lock a region of the SPI NOR - * @flash_unlock: [FLASH-SPECIFIC] unlock a region of the SPI NOR - * @flash_is_locked: [FLASH-SPECIFIC] check if a region of the SPI NOR is - * @quad_enable: [FLASH-SPECIFIC] enables SPI NOR quad mode * @clear_sr_bp: [FLASH-SPECIFIC] clears the Block Protection Bits from * the SPI NOR Status Register. - * completely locked + * @params: [FLASH-SPECIFIC] SPI-NOR flash parameters and settings. + * The structure includes legacy flash parameters and + * settings that can be overwritten by the spi_nor_fixups + * hooks, or dynamically when parsing the SFDP tables. * @priv: the private data */ struct spi_nor { struct mtd_info mtd; struct mutex lock; struct device *dev; + struct spi_mem *spimem; + u8 *bouncebuf; + size_t bouncebuf_size; const struct flash_info *info; u32 page_size; u8 addr_width; @@ -394,8 +587,6 @@ struct spi_nor { enum spi_nor_protocol reg_proto; bool sst_write_second; u32 flags; - u8 cmd_buf[SPI_NOR_MAX_CMD_SIZE]; - struct spi_nor_erase_map erase_map; int (*prepare)(struct spi_nor *nor, enum spi_nor_ops ops); void (*unprepare)(struct spi_nor *nor, enum spi_nor_ops ops); @@ -408,11 +599,8 @@ struct spi_nor { size_t len, const u_char *write_buf); int (*erase)(struct spi_nor *nor, loff_t offs); - int (*flash_lock)(struct spi_nor *nor, loff_t ofs, uint64_t len); - int (*flash_unlock)(struct spi_nor *nor, loff_t ofs, uint64_t len); - int (*flash_is_locked)(struct spi_nor *nor, loff_t ofs, uint64_t len); - int (*quad_enable)(struct spi_nor *nor); int (*clear_sr_bp)(struct spi_nor *nor); + struct spi_nor_flash_parameter params; void *priv; }; @@ -443,7 +631,7 @@ spi_nor_region_mark_overlay(struct spi_nor_erase_region *region) static bool __maybe_unused spi_nor_has_uniform_erase(const struct spi_nor *nor) { - return !!nor->erase_map.uniform_erase_type; + return !!nor->params.erase_map.uniform_erase_type; } static inline void spi_nor_set_flash_node(struct spi_nor *nor, @@ -458,67 +646,6 @@ static inline struct device_node *spi_nor_get_flash_node(struct spi_nor *nor) } /** - * struct spi_nor_hwcaps - Structure for describing the hardware capabilies - * supported by the SPI controller (bus master). - * @mask: the bitmask listing all the supported hw capabilies - */ -struct spi_nor_hwcaps { - u32 mask; -}; - -/* - *(Fast) Read capabilities. - * MUST be ordered by priority: the higher bit position, the higher priority. - * As a matter of performances, it is relevant to use Octal SPI protocols first, - * then Quad SPI protocols before Dual SPI protocols, Fast Read and lastly - * (Slow) Read. - */ -#define SNOR_HWCAPS_READ_MASK GENMASK(14, 0) -#define SNOR_HWCAPS_READ BIT(0) -#define SNOR_HWCAPS_READ_FAST BIT(1) -#define SNOR_HWCAPS_READ_1_1_1_DTR BIT(2) - -#define SNOR_HWCAPS_READ_DUAL GENMASK(6, 3) -#define SNOR_HWCAPS_READ_1_1_2 BIT(3) -#define SNOR_HWCAPS_READ_1_2_2 BIT(4) -#define SNOR_HWCAPS_READ_2_2_2 BIT(5) -#define SNOR_HWCAPS_READ_1_2_2_DTR BIT(6) - -#define SNOR_HWCAPS_READ_QUAD GENMASK(10, 7) -#define SNOR_HWCAPS_READ_1_1_4 BIT(7) -#define SNOR_HWCAPS_READ_1_4_4 BIT(8) -#define SNOR_HWCAPS_READ_4_4_4 BIT(9) -#define SNOR_HWCAPS_READ_1_4_4_DTR BIT(10) - -#define SNOR_HWCAPS_READ_OCTAL GENMASK(14, 11) -#define SNOR_HWCAPS_READ_1_1_8 BIT(11) -#define SNOR_HWCAPS_READ_1_8_8 BIT(12) -#define SNOR_HWCAPS_READ_8_8_8 BIT(13) -#define SNOR_HWCAPS_READ_1_8_8_DTR BIT(14) - -/* - * Page Program capabilities. - * MUST be ordered by priority: the higher bit position, the higher priority. - * Like (Fast) Read capabilities, Octal/Quad SPI protocols are preferred to the - * legacy SPI 1-1-1 protocol. - * Note that Dual Page Programs are not supported because there is no existing - * JEDEC/SFDP standard to define them. Also at this moment no SPI flash memory - * implements such commands. - */ -#define SNOR_HWCAPS_PP_MASK GENMASK(22, 16) -#define SNOR_HWCAPS_PP BIT(16) - -#define SNOR_HWCAPS_PP_QUAD GENMASK(19, 17) -#define SNOR_HWCAPS_PP_1_1_4 BIT(17) -#define SNOR_HWCAPS_PP_1_4_4 BIT(18) -#define SNOR_HWCAPS_PP_4_4_4 BIT(19) - -#define SNOR_HWCAPS_PP_OCTAL GENMASK(22, 20) -#define SNOR_HWCAPS_PP_1_1_8 BIT(20) -#define SNOR_HWCAPS_PP_1_8_8 BIT(21) -#define SNOR_HWCAPS_PP_8_8_8 BIT(22) - -/** * spi_nor_scan() - scan the SPI NOR * @nor: the spi_nor structure * @name: the chip type name diff --git a/include/linux/mtd/spinand.h b/include/linux/mtd/spinand.h index 507f7e289bd1..4ea558bd3c46 100644 --- a/include/linux/mtd/spinand.h +++ b/include/linux/mtd/spinand.h @@ -68,30 +68,60 @@ SPI_MEM_OP_DUMMY(ndummy, 1), \ SPI_MEM_OP_DATA_IN(len, buf, 1)) +#define SPINAND_PAGE_READ_FROM_CACHE_OP_3A(fast, addr, ndummy, buf, len) \ + SPI_MEM_OP(SPI_MEM_OP_CMD(fast ? 0x0b : 0x03, 1), \ + SPI_MEM_OP_ADDR(3, addr, 1), \ + SPI_MEM_OP_DUMMY(ndummy, 1), \ + SPI_MEM_OP_DATA_IN(len, buf, 1)) + #define SPINAND_PAGE_READ_FROM_CACHE_X2_OP(addr, ndummy, buf, len) \ SPI_MEM_OP(SPI_MEM_OP_CMD(0x3b, 1), \ SPI_MEM_OP_ADDR(2, addr, 1), \ SPI_MEM_OP_DUMMY(ndummy, 1), \ SPI_MEM_OP_DATA_IN(len, buf, 2)) +#define SPINAND_PAGE_READ_FROM_CACHE_X2_OP_3A(addr, ndummy, buf, len) \ + SPI_MEM_OP(SPI_MEM_OP_CMD(0x3b, 1), \ + SPI_MEM_OP_ADDR(3, addr, 1), \ + SPI_MEM_OP_DUMMY(ndummy, 1), \ + SPI_MEM_OP_DATA_IN(len, buf, 2)) + #define SPINAND_PAGE_READ_FROM_CACHE_X4_OP(addr, ndummy, buf, len) \ SPI_MEM_OP(SPI_MEM_OP_CMD(0x6b, 1), \ SPI_MEM_OP_ADDR(2, addr, 1), \ SPI_MEM_OP_DUMMY(ndummy, 1), \ SPI_MEM_OP_DATA_IN(len, buf, 4)) +#define SPINAND_PAGE_READ_FROM_CACHE_X4_OP_3A(addr, ndummy, buf, len) \ + SPI_MEM_OP(SPI_MEM_OP_CMD(0x6b, 1), \ + SPI_MEM_OP_ADDR(3, addr, 1), \ + SPI_MEM_OP_DUMMY(ndummy, 1), \ + SPI_MEM_OP_DATA_IN(len, buf, 4)) + #define SPINAND_PAGE_READ_FROM_CACHE_DUALIO_OP(addr, ndummy, buf, len) \ SPI_MEM_OP(SPI_MEM_OP_CMD(0xbb, 1), \ SPI_MEM_OP_ADDR(2, addr, 2), \ SPI_MEM_OP_DUMMY(ndummy, 2), \ SPI_MEM_OP_DATA_IN(len, buf, 2)) +#define SPINAND_PAGE_READ_FROM_CACHE_DUALIO_OP_3A(addr, ndummy, buf, len) \ + SPI_MEM_OP(SPI_MEM_OP_CMD(0xbb, 1), \ + SPI_MEM_OP_ADDR(3, addr, 2), \ + SPI_MEM_OP_DUMMY(ndummy, 2), \ + SPI_MEM_OP_DATA_IN(len, buf, 2)) + #define SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(addr, ndummy, buf, len) \ SPI_MEM_OP(SPI_MEM_OP_CMD(0xeb, 1), \ SPI_MEM_OP_ADDR(2, addr, 4), \ SPI_MEM_OP_DUMMY(ndummy, 4), \ SPI_MEM_OP_DATA_IN(len, buf, 4)) +#define SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP_3A(addr, ndummy, buf, len) \ + SPI_MEM_OP(SPI_MEM_OP_CMD(0xeb, 1), \ + SPI_MEM_OP_ADDR(3, addr, 4), \ + SPI_MEM_OP_DUMMY(ndummy, 4), \ + SPI_MEM_OP_DATA_IN(len, buf, 4)) + #define SPINAND_PROG_EXEC_OP(addr) \ SPI_MEM_OP(SPI_MEM_OP_CMD(0x10, 1), \ SPI_MEM_OP_ADDR(3, addr, 1), \ @@ -197,6 +227,7 @@ struct spinand_manufacturer { extern const struct spinand_manufacturer gigadevice_spinand_manufacturer; extern const struct spinand_manufacturer macronix_spinand_manufacturer; extern const struct spinand_manufacturer micron_spinand_manufacturer; +extern const struct spinand_manufacturer paragon_spinand_manufacturer; extern const struct spinand_manufacturer toshiba_spinand_manufacturer; extern const struct spinand_manufacturer winbond_spinand_manufacturer; @@ -260,7 +291,7 @@ struct spinand_ecc_info { */ struct spinand_info { const char *model; - u8 devid; + u16 devid; u32 flags; struct nand_memory_organization memorg; struct nand_ecc_req eccreq; @@ -422,7 +453,7 @@ static inline void spinand_set_of_node(struct spinand_device *spinand, int spinand_match_and_init(struct spinand_device *dev, const struct spinand_info *table, - unsigned int table_size, u8 devid); + unsigned int table_size, u16 devid); int spinand_upd_cfg(struct spinand_device *spinand, u8 mask, u8 val); int spinand_select_target(struct spinand_device *spinand, unsigned int target); diff --git a/include/linux/mtd/super.h b/include/linux/mtd/super.h index 056c9932c723..3608a6c36fac 100644 --- a/include/linux/mtd/super.h +++ b/include/linux/mtd/super.h @@ -14,9 +14,9 @@ #include <linux/fs.h> #include <linux/mount.h> -extern struct dentry *mount_mtd(struct file_system_type *fs_type, int flags, - const char *dev_name, void *data, - int (*fill_super)(struct super_block *, void *, int)); +extern int get_tree_mtd(struct fs_context *fc, + int (*fill_super)(struct super_block *sb, + struct fs_context *fc)); extern void kill_mtd_super(struct super_block *sb); diff --git a/include/linux/mutex.h b/include/linux/mutex.h index 3093dd162424..aca8f36dfac9 100644 --- a/include/linux/mutex.h +++ b/include/linux/mutex.h @@ -66,16 +66,6 @@ struct mutex { }; /* - * Internal helper function; C doesn't allow us to hide it :/ - * - * DO NOT USE (outside of mutex code). - */ -static inline struct task_struct *__mutex_owner(struct mutex *lock) -{ - return (struct task_struct *)(atomic_long_read(&lock->owner) & ~0x07); -} - -/* * This is the control structure for tasks blocked on mutex, * which resides on the blocked task's kernel stack: */ @@ -144,14 +134,11 @@ extern void __mutex_init(struct mutex *lock, const char *name, * * Returns true if the mutex is locked, false if unlocked. */ -static inline bool mutex_is_locked(struct mutex *lock) -{ - return __mutex_owner(lock) != NULL; -} +extern bool mutex_is_locked(struct mutex *lock); /* * See kernel/locking/mutex.c for detailed documentation of these APIs. - * Also see Documentation/locking/mutex-design.txt. + * Also see Documentation/locking/mutex-design.rst. */ #ifdef CONFIG_DEBUG_LOCK_ALLOC extern void mutex_lock_nested(struct mutex *lock, unsigned int subclass); @@ -220,13 +207,7 @@ enum mutex_trylock_recursive_enum { * - MUTEX_TRYLOCK_SUCCESS - lock acquired, * - MUTEX_TRYLOCK_RECURSIVE - we already owned the lock. */ -static inline /* __deprecated */ __must_check enum mutex_trylock_recursive_enum -mutex_trylock_recursive(struct mutex *lock) -{ - if (unlikely(__mutex_owner(lock) == current)) - return MUTEX_TRYLOCK_RECURSIVE; - - return mutex_trylock(lock); -} +extern /* __deprecated */ __must_check enum mutex_trylock_recursive_enum +mutex_trylock_recursive(struct mutex *lock); #endif /* __LINUX_MUTEX_H */ diff --git a/include/linux/mv643xx.h b/include/linux/mv643xx.h index 4471cf96ef69..47e5679b48e1 100644 --- a/include/linux/mv643xx.h +++ b/include/linux/mv643xx.h @@ -918,52 +918,6 @@ extern void mv64340_irq_init(unsigned int base); -/* MPSC Platform Device, Driver Data (Shared register regions) */ -#define MPSC_SHARED_NAME "mpsc_shared" - -#define MPSC_ROUTING_BASE_ORDER 0 -#define MPSC_SDMA_INTR_BASE_ORDER 1 - -#define MPSC_ROUTING_REG_BLOCK_SIZE 0x000c -#define MPSC_SDMA_INTR_REG_BLOCK_SIZE 0x0084 - -struct mpsc_shared_pdata { - u32 mrr_val; - u32 rcrr_val; - u32 tcrr_val; - u32 intr_cause_val; - u32 intr_mask_val; -}; - -/* MPSC Platform Device, Driver Data */ -#define MPSC_CTLR_NAME "mpsc" - -#define MPSC_BASE_ORDER 0 -#define MPSC_SDMA_BASE_ORDER 1 -#define MPSC_BRG_BASE_ORDER 2 - -#define MPSC_REG_BLOCK_SIZE 0x0038 -#define MPSC_SDMA_REG_BLOCK_SIZE 0x0c18 -#define MPSC_BRG_REG_BLOCK_SIZE 0x0008 - -struct mpsc_pdata { - u8 mirror_regs; - u8 cache_mgmt; - u8 max_idle; - int default_baud; - int default_bits; - int default_parity; - int default_flow; - u32 chr_1_val; - u32 chr_2_val; - u32 chr_10_val; - u32 mpcr_val; - u32 bcr_val; - u8 brg_can_tune; - u8 brg_clk_src; - u32 brg_clk_freq; -}; - /* Watchdog Platform Device, Driver Data */ #define MV64x60_WDT_NAME "mv64x60_wdt" diff --git a/include/linux/namei.h b/include/linux/namei.h index 9138b4471dbf..397a08ade6a2 100644 --- a/include/linux/namei.h +++ b/include/linux/namei.h @@ -16,39 +16,28 @@ enum { MAX_NESTED_LINKS = 8 }; */ enum {LAST_NORM, LAST_ROOT, LAST_DOT, LAST_DOTDOT, LAST_BIND}; -/* - * The bitmask for a lookup event: - * - follow links at the end - * - require a directory - * - ending slashes ok even for nonexistent files - * - internal "there are more path components" flag - * - dentry cache is untrusted; force a real lookup - * - suppress terminal automount - * - skip revalidation - * - don't fetch xattrs on audit_inode - */ -#define LOOKUP_FOLLOW 0x0001 -#define LOOKUP_DIRECTORY 0x0002 -#define LOOKUP_AUTOMOUNT 0x0004 - +/* pathwalk mode */ +#define LOOKUP_FOLLOW 0x0001 /* follow links at the end */ +#define LOOKUP_DIRECTORY 0x0002 /* require a directory */ +#define LOOKUP_AUTOMOUNT 0x0004 /* force terminal automount */ +#define LOOKUP_EMPTY 0x4000 /* accept empty path [user_... only] */ +#define LOOKUP_DOWN 0x8000 /* follow mounts in the starting point */ + +#define LOOKUP_REVAL 0x0020 /* tell ->d_revalidate() to trust no cache */ +#define LOOKUP_RCU 0x0040 /* RCU pathwalk mode; semi-internal */ + +/* These tell filesystem methods that we are dealing with the final component... */ +#define LOOKUP_OPEN 0x0100 /* ... in open */ +#define LOOKUP_CREATE 0x0200 /* ... in object creation */ +#define LOOKUP_EXCL 0x0400 /* ... in exclusive creation */ +#define LOOKUP_RENAME_TARGET 0x0800 /* ... in destination of rename() */ + +/* internal use only */ #define LOOKUP_PARENT 0x0010 -#define LOOKUP_REVAL 0x0020 -#define LOOKUP_RCU 0x0040 #define LOOKUP_NO_REVAL 0x0080 -#define LOOKUP_NO_EVAL 0x0100 - -/* - * Intent data - */ -#define LOOKUP_OPEN 0x0100 -#define LOOKUP_CREATE 0x0200 -#define LOOKUP_EXCL 0x0400 -#define LOOKUP_RENAME_TARGET 0x0800 - #define LOOKUP_JUMPED 0x1000 #define LOOKUP_ROOT 0x2000 -#define LOOKUP_EMPTY 0x4000 -#define LOOKUP_DOWN 0x8000 +#define LOOKUP_ROOT_GRABBED 0x0008 extern int path_pts(struct path *path); @@ -60,22 +49,6 @@ static inline int user_path_at(int dfd, const char __user *name, unsigned flags, return user_path_at_empty(dfd, name, flags, path, NULL); } -static inline int user_path(const char __user *name, struct path *path) -{ - return user_path_at_empty(AT_FDCWD, name, LOOKUP_FOLLOW, path, NULL); -} - -static inline int user_lpath(const char __user *name, struct path *path) -{ - return user_path_at_empty(AT_FDCWD, name, 0, path, NULL); -} - -static inline int user_path_dir(const char __user *name, struct path *path) -{ - return user_path_at_empty(AT_FDCWD, name, - LOOKUP_FOLLOW | LOOKUP_DIRECTORY, path, NULL); -} - extern int kern_path(const char *, unsigned, struct path *); extern struct dentry *kern_path_create(int, const char *, struct path *, unsigned int); diff --git a/include/linux/net.h b/include/linux/net.h index f7d672cf25b5..9cafb5f353a9 100644 --- a/include/linux/net.h +++ b/include/linux/net.h @@ -116,11 +116,11 @@ struct socket { unsigned long flags; - struct socket_wq *wq; - struct file *file; struct sock *sk; const struct proto_ops *ops; + + struct socket_wq wq; }; struct vm_area_struct; diff --git a/include/linux/net_dim.h b/include/linux/net_dim.h deleted file mode 100644 index fd458389f7d1..000000000000 --- a/include/linux/net_dim.h +++ /dev/null @@ -1,418 +0,0 @@ -/* - * Copyright (c) 2016, Mellanox Technologies. All rights reserved. - * Copyright (c) 2017-2018, Broadcom Limited. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#ifndef NET_DIM_H -#define NET_DIM_H - -#include <linux/module.h> - -struct net_dim_cq_moder { - u16 usec; - u16 pkts; - u8 cq_period_mode; -}; - -struct net_dim_sample { - ktime_t time; - u32 pkt_ctr; - u32 byte_ctr; - u16 event_ctr; -}; - -struct net_dim_stats { - int ppms; /* packets per msec */ - int bpms; /* bytes per msec */ - int epms; /* events per msec */ -}; - -struct net_dim { /* Adaptive Moderation */ - u8 state; - struct net_dim_stats prev_stats; - struct net_dim_sample start_sample; - struct work_struct work; - u8 profile_ix; - u8 mode; - u8 tune_state; - u8 steps_right; - u8 steps_left; - u8 tired; -}; - -enum { - NET_DIM_CQ_PERIOD_MODE_START_FROM_EQE = 0x0, - NET_DIM_CQ_PERIOD_MODE_START_FROM_CQE = 0x1, - NET_DIM_CQ_PERIOD_NUM_MODES -}; - -/* Adaptive moderation logic */ -enum { - NET_DIM_START_MEASURE, - NET_DIM_MEASURE_IN_PROGRESS, - NET_DIM_APPLY_NEW_PROFILE, -}; - -enum { - NET_DIM_PARKING_ON_TOP, - NET_DIM_PARKING_TIRED, - NET_DIM_GOING_RIGHT, - NET_DIM_GOING_LEFT, -}; - -enum { - NET_DIM_STATS_WORSE, - NET_DIM_STATS_SAME, - NET_DIM_STATS_BETTER, -}; - -enum { - NET_DIM_STEPPED, - NET_DIM_TOO_TIRED, - NET_DIM_ON_EDGE, -}; - -#define NET_DIM_PARAMS_NUM_PROFILES 5 -/* Adaptive moderation profiles */ -#define NET_DIM_DEFAULT_RX_CQ_MODERATION_PKTS_FROM_EQE 256 -#define NET_DIM_DEFAULT_TX_CQ_MODERATION_PKTS_FROM_EQE 128 -#define NET_DIM_DEF_PROFILE_CQE 1 -#define NET_DIM_DEF_PROFILE_EQE 1 - -/* All profiles sizes must be NET_PARAMS_DIM_NUM_PROFILES */ -#define NET_DIM_RX_EQE_PROFILES { \ - {1, NET_DIM_DEFAULT_RX_CQ_MODERATION_PKTS_FROM_EQE}, \ - {8, NET_DIM_DEFAULT_RX_CQ_MODERATION_PKTS_FROM_EQE}, \ - {64, NET_DIM_DEFAULT_RX_CQ_MODERATION_PKTS_FROM_EQE}, \ - {128, NET_DIM_DEFAULT_RX_CQ_MODERATION_PKTS_FROM_EQE}, \ - {256, NET_DIM_DEFAULT_RX_CQ_MODERATION_PKTS_FROM_EQE}, \ -} - -#define NET_DIM_RX_CQE_PROFILES { \ - {2, 256}, \ - {8, 128}, \ - {16, 64}, \ - {32, 64}, \ - {64, 64} \ -} - -#define NET_DIM_TX_EQE_PROFILES { \ - {1, NET_DIM_DEFAULT_TX_CQ_MODERATION_PKTS_FROM_EQE}, \ - {8, NET_DIM_DEFAULT_TX_CQ_MODERATION_PKTS_FROM_EQE}, \ - {32, NET_DIM_DEFAULT_TX_CQ_MODERATION_PKTS_FROM_EQE}, \ - {64, NET_DIM_DEFAULT_TX_CQ_MODERATION_PKTS_FROM_EQE}, \ - {128, NET_DIM_DEFAULT_TX_CQ_MODERATION_PKTS_FROM_EQE} \ -} - -#define NET_DIM_TX_CQE_PROFILES { \ - {5, 128}, \ - {8, 64}, \ - {16, 32}, \ - {32, 32}, \ - {64, 32} \ -} - -static const struct net_dim_cq_moder -rx_profile[NET_DIM_CQ_PERIOD_NUM_MODES][NET_DIM_PARAMS_NUM_PROFILES] = { - NET_DIM_RX_EQE_PROFILES, - NET_DIM_RX_CQE_PROFILES, -}; - -static const struct net_dim_cq_moder -tx_profile[NET_DIM_CQ_PERIOD_NUM_MODES][NET_DIM_PARAMS_NUM_PROFILES] = { - NET_DIM_TX_EQE_PROFILES, - NET_DIM_TX_CQE_PROFILES, -}; - -static inline struct net_dim_cq_moder -net_dim_get_rx_moderation(u8 cq_period_mode, int ix) -{ - struct net_dim_cq_moder cq_moder = rx_profile[cq_period_mode][ix]; - - cq_moder.cq_period_mode = cq_period_mode; - return cq_moder; -} - -static inline struct net_dim_cq_moder -net_dim_get_def_rx_moderation(u8 cq_period_mode) -{ - u8 profile_ix = cq_period_mode == NET_DIM_CQ_PERIOD_MODE_START_FROM_CQE ? - NET_DIM_DEF_PROFILE_CQE : NET_DIM_DEF_PROFILE_EQE; - - return net_dim_get_rx_moderation(cq_period_mode, profile_ix); -} - -static inline struct net_dim_cq_moder -net_dim_get_tx_moderation(u8 cq_period_mode, int ix) -{ - struct net_dim_cq_moder cq_moder = tx_profile[cq_period_mode][ix]; - - cq_moder.cq_period_mode = cq_period_mode; - return cq_moder; -} - -static inline struct net_dim_cq_moder -net_dim_get_def_tx_moderation(u8 cq_period_mode) -{ - u8 profile_ix = cq_period_mode == NET_DIM_CQ_PERIOD_MODE_START_FROM_CQE ? - NET_DIM_DEF_PROFILE_CQE : NET_DIM_DEF_PROFILE_EQE; - - return net_dim_get_tx_moderation(cq_period_mode, profile_ix); -} - -static inline bool net_dim_on_top(struct net_dim *dim) -{ - switch (dim->tune_state) { - case NET_DIM_PARKING_ON_TOP: - case NET_DIM_PARKING_TIRED: - return true; - case NET_DIM_GOING_RIGHT: - return (dim->steps_left > 1) && (dim->steps_right == 1); - default: /* NET_DIM_GOING_LEFT */ - return (dim->steps_right > 1) && (dim->steps_left == 1); - } -} - -static inline void net_dim_turn(struct net_dim *dim) -{ - switch (dim->tune_state) { - case NET_DIM_PARKING_ON_TOP: - case NET_DIM_PARKING_TIRED: - break; - case NET_DIM_GOING_RIGHT: - dim->tune_state = NET_DIM_GOING_LEFT; - dim->steps_left = 0; - break; - case NET_DIM_GOING_LEFT: - dim->tune_state = NET_DIM_GOING_RIGHT; - dim->steps_right = 0; - break; - } -} - -static inline int net_dim_step(struct net_dim *dim) -{ - if (dim->tired == (NET_DIM_PARAMS_NUM_PROFILES * 2)) - return NET_DIM_TOO_TIRED; - - switch (dim->tune_state) { - case NET_DIM_PARKING_ON_TOP: - case NET_DIM_PARKING_TIRED: - break; - case NET_DIM_GOING_RIGHT: - if (dim->profile_ix == (NET_DIM_PARAMS_NUM_PROFILES - 1)) - return NET_DIM_ON_EDGE; - dim->profile_ix++; - dim->steps_right++; - break; - case NET_DIM_GOING_LEFT: - if (dim->profile_ix == 0) - return NET_DIM_ON_EDGE; - dim->profile_ix--; - dim->steps_left++; - break; - } - - dim->tired++; - return NET_DIM_STEPPED; -} - -static inline void net_dim_park_on_top(struct net_dim *dim) -{ - dim->steps_right = 0; - dim->steps_left = 0; - dim->tired = 0; - dim->tune_state = NET_DIM_PARKING_ON_TOP; -} - -static inline void net_dim_park_tired(struct net_dim *dim) -{ - dim->steps_right = 0; - dim->steps_left = 0; - dim->tune_state = NET_DIM_PARKING_TIRED; -} - -static inline void net_dim_exit_parking(struct net_dim *dim) -{ - dim->tune_state = dim->profile_ix ? NET_DIM_GOING_LEFT : - NET_DIM_GOING_RIGHT; - net_dim_step(dim); -} - -#define IS_SIGNIFICANT_DIFF(val, ref) \ - (((100UL * abs((val) - (ref))) / (ref)) > 10) /* more than 10% difference */ - -static inline int net_dim_stats_compare(struct net_dim_stats *curr, - struct net_dim_stats *prev) -{ - if (!prev->bpms) - return curr->bpms ? NET_DIM_STATS_BETTER : - NET_DIM_STATS_SAME; - - if (IS_SIGNIFICANT_DIFF(curr->bpms, prev->bpms)) - return (curr->bpms > prev->bpms) ? NET_DIM_STATS_BETTER : - NET_DIM_STATS_WORSE; - - if (!prev->ppms) - return curr->ppms ? NET_DIM_STATS_BETTER : - NET_DIM_STATS_SAME; - - if (IS_SIGNIFICANT_DIFF(curr->ppms, prev->ppms)) - return (curr->ppms > prev->ppms) ? NET_DIM_STATS_BETTER : - NET_DIM_STATS_WORSE; - - if (!prev->epms) - return NET_DIM_STATS_SAME; - - if (IS_SIGNIFICANT_DIFF(curr->epms, prev->epms)) - return (curr->epms < prev->epms) ? NET_DIM_STATS_BETTER : - NET_DIM_STATS_WORSE; - - return NET_DIM_STATS_SAME; -} - -static inline bool net_dim_decision(struct net_dim_stats *curr_stats, - struct net_dim *dim) -{ - int prev_state = dim->tune_state; - int prev_ix = dim->profile_ix; - int stats_res; - int step_res; - - switch (dim->tune_state) { - case NET_DIM_PARKING_ON_TOP: - stats_res = net_dim_stats_compare(curr_stats, &dim->prev_stats); - if (stats_res != NET_DIM_STATS_SAME) - net_dim_exit_parking(dim); - break; - - case NET_DIM_PARKING_TIRED: - dim->tired--; - if (!dim->tired) - net_dim_exit_parking(dim); - break; - - case NET_DIM_GOING_RIGHT: - case NET_DIM_GOING_LEFT: - stats_res = net_dim_stats_compare(curr_stats, &dim->prev_stats); - if (stats_res != NET_DIM_STATS_BETTER) - net_dim_turn(dim); - - if (net_dim_on_top(dim)) { - net_dim_park_on_top(dim); - break; - } - - step_res = net_dim_step(dim); - switch (step_res) { - case NET_DIM_ON_EDGE: - net_dim_park_on_top(dim); - break; - case NET_DIM_TOO_TIRED: - net_dim_park_tired(dim); - break; - } - - break; - } - - if ((prev_state != NET_DIM_PARKING_ON_TOP) || - (dim->tune_state != NET_DIM_PARKING_ON_TOP)) - dim->prev_stats = *curr_stats; - - return dim->profile_ix != prev_ix; -} - -static inline void net_dim_sample(u16 event_ctr, - u64 packets, - u64 bytes, - struct net_dim_sample *s) -{ - s->time = ktime_get(); - s->pkt_ctr = packets; - s->byte_ctr = bytes; - s->event_ctr = event_ctr; -} - -#define NET_DIM_NEVENTS 64 -#define BIT_GAP(bits, end, start) ((((end) - (start)) + BIT_ULL(bits)) & (BIT_ULL(bits) - 1)) - -static inline void net_dim_calc_stats(struct net_dim_sample *start, - struct net_dim_sample *end, - struct net_dim_stats *curr_stats) -{ - /* u32 holds up to 71 minutes, should be enough */ - u32 delta_us = ktime_us_delta(end->time, start->time); - u32 npkts = BIT_GAP(BITS_PER_TYPE(u32), end->pkt_ctr, start->pkt_ctr); - u32 nbytes = BIT_GAP(BITS_PER_TYPE(u32), end->byte_ctr, - start->byte_ctr); - - if (!delta_us) - return; - - curr_stats->ppms = DIV_ROUND_UP(npkts * USEC_PER_MSEC, delta_us); - curr_stats->bpms = DIV_ROUND_UP(nbytes * USEC_PER_MSEC, delta_us); - curr_stats->epms = DIV_ROUND_UP(NET_DIM_NEVENTS * USEC_PER_MSEC, - delta_us); -} - -static inline void net_dim(struct net_dim *dim, - struct net_dim_sample end_sample) -{ - struct net_dim_stats curr_stats; - u16 nevents; - - switch (dim->state) { - case NET_DIM_MEASURE_IN_PROGRESS: - nevents = BIT_GAP(BITS_PER_TYPE(u16), - end_sample.event_ctr, - dim->start_sample.event_ctr); - if (nevents < NET_DIM_NEVENTS) - break; - net_dim_calc_stats(&dim->start_sample, &end_sample, - &curr_stats); - if (net_dim_decision(&curr_stats, dim)) { - dim->state = NET_DIM_APPLY_NEW_PROFILE; - schedule_work(&dim->work); - break; - } - /* fall through */ - case NET_DIM_START_MEASURE: - net_dim_sample(end_sample.event_ctr, end_sample.pkt_ctr, end_sample.byte_ctr, - &dim->start_sample); - dim->state = NET_DIM_MEASURE_IN_PROGRESS; - break; - case NET_DIM_APPLY_NEW_PROFILE: - break; - } -} - -#endif /* NET_DIM_H */ diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index eeacebd7debb..9eda1c31d1f7 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -332,6 +332,8 @@ struct napi_struct { struct net_device *dev; struct gro_list gro_hash[GRO_HASH_BUCKETS]; struct sk_buff *skb; + struct list_head rx_list; /* Pending GRO_NORMAL skbs */ + int rx_count; /* length of rx_list */ struct hrtimer timer; struct list_head dev_list; struct hlist_node napi_hash_node; @@ -845,6 +847,7 @@ enum tc_setup_type { TC_SETUP_QDISC_ETF, TC_SETUP_ROOT_QDISC, TC_SETUP_QDISC_GRED, + TC_SETUP_QDISC_TAPRIO, }; /* These structures hold the attributes of bpf state that are being passed @@ -899,6 +902,10 @@ struct netdev_bpf { }; }; +/* Flags for ndo_xsk_wakeup. */ +#define XDP_WAKEUP_RX (1 << 0) +#define XDP_WAKEUP_TX (1 << 1) + #ifdef CONFIG_XFRM_OFFLOAD struct xfrmdev_ops { int (*xdo_dev_state_add) (struct xfrm_state *x); @@ -1225,6 +1232,12 @@ struct tlsdev_ops; * that got dropped are freed/returned via xdp_return_frame(). * Returns negative number, means general error invoking ndo, meaning * no frames were xmit'ed and core-caller will free all frames. + * int (*ndo_xsk_wakeup)(struct net_device *dev, u32 queue_id, u32 flags); + * This function is used to wake up the softirq, ksoftirqd or kthread + * responsible for sending and/or receiving packets on a specific + * queue id bound to an AF_XDP socket. The flags field specifies if + * only RX, only Tx, or both should be woken up using the flags + * XDP_WAKEUP_RX and XDP_WAKEUP_TX. * struct devlink_port *(*ndo_get_devlink_port)(struct net_device *dev); * Get devlink port instance associated with a given netdev. * Called with a reference on the netdevice and devlink locks only, @@ -1424,8 +1437,8 @@ struct net_device_ops { int (*ndo_xdp_xmit)(struct net_device *dev, int n, struct xdp_frame **xdp, u32 flags); - int (*ndo_xsk_async_xmit)(struct net_device *dev, - u32 queue_id); + int (*ndo_xsk_wakeup)(struct net_device *dev, + u32 queue_id, u32 flags); struct devlink_port * (*ndo_get_devlink_port)(struct net_device *dev); }; @@ -3270,7 +3283,7 @@ static inline void netdev_tx_completed_queue(struct netdev_queue *dev_queue, */ smp_mb(); - if (dql_avail(&dev_queue->dql) < 0) + if (unlikely(dql_avail(&dev_queue->dql) < 0)) return; if (test_and_clear_bit(__QUEUE_STATE_STACK_XOFF, &dev_queue->state)) @@ -4239,6 +4252,7 @@ extern int dev_weight_rx_bias; extern int dev_weight_tx_bias; extern int dev_rx_weight; extern int dev_tx_weight; +extern int gro_normal_batch; bool netdev_has_upper_dev(struct net_device *dev, struct net_device *upper_dev); struct net_device *netdev_upper_get_next_dev_rcu(struct net_device *dev, @@ -4870,4 +4884,6 @@ do { \ #define PTYPE_HASH_SIZE (16) #define PTYPE_HASH_MASK (PTYPE_HASH_SIZE - 1) +extern struct net_device *blackhole_netdev; + #endif /* _LINUX_NETDEVICE_H */ diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h index 996bc247ef6e..77ebb61faf48 100644 --- a/include/linux/netfilter.h +++ b/include/linux/netfilter.h @@ -15,7 +15,6 @@ #include <linux/netdevice.h> #include <net/net_namespace.h> -#ifdef CONFIG_NETFILTER static inline int NF_DROP_GETERR(int verdict) { return -(verdict >> NF_VERDICT_QBITS); @@ -118,6 +117,7 @@ struct nf_hook_entries { */ }; +#ifdef CONFIG_NETFILTER static inline struct nf_hook_ops **nf_hook_entries_get_hook_ops(const struct nf_hook_entries *e) { unsigned int n = e->num_hook_entries; @@ -336,11 +336,6 @@ int compat_nf_getsockopt(struct sock *sk, u_int8_t pf, int optval, char __user *opt, int *len); #endif -/* Call this before modifying an existing packet: ensures it is - modifiable and linear to the point you care about (writable_len). - Returns true or false. */ -int skb_make_writable(struct sk_buff *skb, unsigned int writable_len); - struct flowi; struct nf_queue_entry; @@ -427,7 +422,7 @@ nf_nat_decode_session(struct sk_buff *skb, struct flowi *fl, u_int8_t family) } #endif /*CONFIG_NETFILTER*/ -#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) +#if IS_ENABLED(CONFIG_NF_CONNTRACK) #include <linux/netfilter/nf_conntrack_zones_common.h> extern void (*ip_ct_attach)(struct sk_buff *, const struct sk_buff *) __rcu; diff --git a/include/linux/netfilter/ipset/ip_set.h b/include/linux/netfilter/ipset/ip_set.h index f5e03809cdb2..9bc255a8461b 100644 --- a/include/linux/netfilter/ipset/ip_set.h +++ b/include/linux/netfilter/ipset/ip_set.h @@ -2,7 +2,7 @@ /* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu> * Patrick Schaaf <bof@bof.de> * Martin Josefsson <gandalf@wlug.westbo.se> - * Copyright (C) 2003-2013 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu> + * Copyright (C) 2003-2013 Jozsef Kadlecsik <kadlec@netfilter.org> */ #ifndef _IP_SET_H #define _IP_SET_H @@ -452,10 +452,240 @@ bitmap_bytes(u32 a, u32 b) return 4 * ((((b - a + 8) / 8) + 3) / 4); } -#include <linux/netfilter/ipset/ip_set_timeout.h> -#include <linux/netfilter/ipset/ip_set_comment.h> -#include <linux/netfilter/ipset/ip_set_counter.h> -#include <linux/netfilter/ipset/ip_set_skbinfo.h> +/* How often should the gc be run by default */ +#define IPSET_GC_TIME (3 * 60) + +/* Timeout period depending on the timeout value of the given set */ +#define IPSET_GC_PERIOD(timeout) \ + ((timeout/3) ? min_t(u32, (timeout)/3, IPSET_GC_TIME) : 1) + +/* Entry is set with no timeout value */ +#define IPSET_ELEM_PERMANENT 0 + +/* Set is defined with timeout support: timeout value may be 0 */ +#define IPSET_NO_TIMEOUT UINT_MAX + +/* Max timeout value, see msecs_to_jiffies() in jiffies.h */ +#define IPSET_MAX_TIMEOUT (UINT_MAX >> 1)/MSEC_PER_SEC + +#define ip_set_adt_opt_timeout(opt, set) \ +((opt)->ext.timeout != IPSET_NO_TIMEOUT ? (opt)->ext.timeout : (set)->timeout) + +static inline unsigned int +ip_set_timeout_uget(struct nlattr *tb) +{ + unsigned int timeout = ip_set_get_h32(tb); + + /* Normalize to fit into jiffies */ + if (timeout > IPSET_MAX_TIMEOUT) + timeout = IPSET_MAX_TIMEOUT; + + return timeout; +} + +static inline bool +ip_set_timeout_expired(const unsigned long *t) +{ + return *t != IPSET_ELEM_PERMANENT && time_is_before_jiffies(*t); +} + +static inline void +ip_set_timeout_set(unsigned long *timeout, u32 value) +{ + unsigned long t; + + if (!value) { + *timeout = IPSET_ELEM_PERMANENT; + return; + } + + t = msecs_to_jiffies(value * MSEC_PER_SEC) + jiffies; + if (t == IPSET_ELEM_PERMANENT) + /* Bingo! :-) */ + t--; + *timeout = t; +} + +static inline u32 +ip_set_timeout_get(const unsigned long *timeout) +{ + u32 t; + + if (*timeout == IPSET_ELEM_PERMANENT) + return 0; + + t = jiffies_to_msecs(*timeout - jiffies)/MSEC_PER_SEC; + /* Zero value in userspace means no timeout */ + return t == 0 ? 1 : t; +} + +static inline char* +ip_set_comment_uget(struct nlattr *tb) +{ + return nla_data(tb); +} + +/* Called from uadd only, protected by the set spinlock. + * The kadt functions don't use the comment extensions in any way. + */ +static inline void +ip_set_init_comment(struct ip_set *set, struct ip_set_comment *comment, + const struct ip_set_ext *ext) +{ + struct ip_set_comment_rcu *c = rcu_dereference_protected(comment->c, 1); + size_t len = ext->comment ? strlen(ext->comment) : 0; + + if (unlikely(c)) { + set->ext_size -= sizeof(*c) + strlen(c->str) + 1; + kfree_rcu(c, rcu); + rcu_assign_pointer(comment->c, NULL); + } + if (!len) + return; + if (unlikely(len > IPSET_MAX_COMMENT_SIZE)) + len = IPSET_MAX_COMMENT_SIZE; + c = kmalloc(sizeof(*c) + len + 1, GFP_ATOMIC); + if (unlikely(!c)) + return; + strlcpy(c->str, ext->comment, len + 1); + set->ext_size += sizeof(*c) + strlen(c->str) + 1; + rcu_assign_pointer(comment->c, c); +} + +/* Used only when dumping a set, protected by rcu_read_lock() */ +static inline int +ip_set_put_comment(struct sk_buff *skb, const struct ip_set_comment *comment) +{ + struct ip_set_comment_rcu *c = rcu_dereference(comment->c); + + if (!c) + return 0; + return nla_put_string(skb, IPSET_ATTR_COMMENT, c->str); +} + +/* Called from uadd/udel, flush or the garbage collectors protected + * by the set spinlock. + * Called when the set is destroyed and when there can't be any user + * of the set data anymore. + */ +static inline void +ip_set_comment_free(struct ip_set *set, struct ip_set_comment *comment) +{ + struct ip_set_comment_rcu *c; + + c = rcu_dereference_protected(comment->c, 1); + if (unlikely(!c)) + return; + set->ext_size -= sizeof(*c) + strlen(c->str) + 1; + kfree_rcu(c, rcu); + rcu_assign_pointer(comment->c, NULL); +} + +static inline void +ip_set_add_bytes(u64 bytes, struct ip_set_counter *counter) +{ + atomic64_add((long long)bytes, &(counter)->bytes); +} + +static inline void +ip_set_add_packets(u64 packets, struct ip_set_counter *counter) +{ + atomic64_add((long long)packets, &(counter)->packets); +} + +static inline u64 +ip_set_get_bytes(const struct ip_set_counter *counter) +{ + return (u64)atomic64_read(&(counter)->bytes); +} + +static inline u64 +ip_set_get_packets(const struct ip_set_counter *counter) +{ + return (u64)atomic64_read(&(counter)->packets); +} + +static inline bool +ip_set_match_counter(u64 counter, u64 match, u8 op) +{ + switch (op) { + case IPSET_COUNTER_NONE: + return true; + case IPSET_COUNTER_EQ: + return counter == match; + case IPSET_COUNTER_NE: + return counter != match; + case IPSET_COUNTER_LT: + return counter < match; + case IPSET_COUNTER_GT: + return counter > match; + } + return false; +} + +static inline void +ip_set_update_counter(struct ip_set_counter *counter, + const struct ip_set_ext *ext, u32 flags) +{ + if (ext->packets != ULLONG_MAX && + !(flags & IPSET_FLAG_SKIP_COUNTER_UPDATE)) { + ip_set_add_bytes(ext->bytes, counter); + ip_set_add_packets(ext->packets, counter); + } +} + +static inline bool +ip_set_put_counter(struct sk_buff *skb, const struct ip_set_counter *counter) +{ + return nla_put_net64(skb, IPSET_ATTR_BYTES, + cpu_to_be64(ip_set_get_bytes(counter)), + IPSET_ATTR_PAD) || + nla_put_net64(skb, IPSET_ATTR_PACKETS, + cpu_to_be64(ip_set_get_packets(counter)), + IPSET_ATTR_PAD); +} + +static inline void +ip_set_init_counter(struct ip_set_counter *counter, + const struct ip_set_ext *ext) +{ + if (ext->bytes != ULLONG_MAX) + atomic64_set(&(counter)->bytes, (long long)(ext->bytes)); + if (ext->packets != ULLONG_MAX) + atomic64_set(&(counter)->packets, (long long)(ext->packets)); +} + +static inline void +ip_set_get_skbinfo(struct ip_set_skbinfo *skbinfo, + const struct ip_set_ext *ext, + struct ip_set_ext *mext, u32 flags) +{ + mext->skbinfo = *skbinfo; +} + +static inline bool +ip_set_put_skbinfo(struct sk_buff *skb, const struct ip_set_skbinfo *skbinfo) +{ + /* Send nonzero parameters only */ + return ((skbinfo->skbmark || skbinfo->skbmarkmask) && + nla_put_net64(skb, IPSET_ATTR_SKBMARK, + cpu_to_be64((u64)skbinfo->skbmark << 32 | + skbinfo->skbmarkmask), + IPSET_ATTR_PAD)) || + (skbinfo->skbprio && + nla_put_net32(skb, IPSET_ATTR_SKBPRIO, + cpu_to_be32(skbinfo->skbprio))) || + (skbinfo->skbqueue && + nla_put_net16(skb, IPSET_ATTR_SKBQUEUE, + cpu_to_be16(skbinfo->skbqueue))); +} + +static inline void +ip_set_init_skbinfo(struct ip_set_skbinfo *skbinfo, + const struct ip_set_ext *ext) +{ + *skbinfo = ext->skbinfo; +} #define IP_SET_INIT_KEXT(skb, opt, set) \ { .bytes = (skb)->len, .packets = 1, \ diff --git a/include/linux/netfilter/ipset/ip_set_comment.h b/include/linux/netfilter/ipset/ip_set_comment.h deleted file mode 100644 index 0b894d81bbf2..000000000000 --- a/include/linux/netfilter/ipset/ip_set_comment.h +++ /dev/null @@ -1,73 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -#ifndef _IP_SET_COMMENT_H -#define _IP_SET_COMMENT_H - -/* Copyright (C) 2013 Oliver Smith <oliver@8.c.9.b.0.7.4.0.1.0.0.2.ip6.arpa> - */ - -#ifdef __KERNEL__ - -static inline char* -ip_set_comment_uget(struct nlattr *tb) -{ - return nla_data(tb); -} - -/* Called from uadd only, protected by the set spinlock. - * The kadt functions don't use the comment extensions in any way. - */ -static inline void -ip_set_init_comment(struct ip_set *set, struct ip_set_comment *comment, - const struct ip_set_ext *ext) -{ - struct ip_set_comment_rcu *c = rcu_dereference_protected(comment->c, 1); - size_t len = ext->comment ? strlen(ext->comment) : 0; - - if (unlikely(c)) { - set->ext_size -= sizeof(*c) + strlen(c->str) + 1; - kfree_rcu(c, rcu); - rcu_assign_pointer(comment->c, NULL); - } - if (!len) - return; - if (unlikely(len > IPSET_MAX_COMMENT_SIZE)) - len = IPSET_MAX_COMMENT_SIZE; - c = kmalloc(sizeof(*c) + len + 1, GFP_ATOMIC); - if (unlikely(!c)) - return; - strlcpy(c->str, ext->comment, len + 1); - set->ext_size += sizeof(*c) + strlen(c->str) + 1; - rcu_assign_pointer(comment->c, c); -} - -/* Used only when dumping a set, protected by rcu_read_lock() */ -static inline int -ip_set_put_comment(struct sk_buff *skb, const struct ip_set_comment *comment) -{ - struct ip_set_comment_rcu *c = rcu_dereference(comment->c); - - if (!c) - return 0; - return nla_put_string(skb, IPSET_ATTR_COMMENT, c->str); -} - -/* Called from uadd/udel, flush or the garbage collectors protected - * by the set spinlock. - * Called when the set is destroyed and when there can't be any user - * of the set data anymore. - */ -static inline void -ip_set_comment_free(struct ip_set *set, struct ip_set_comment *comment) -{ - struct ip_set_comment_rcu *c; - - c = rcu_dereference_protected(comment->c, 1); - if (unlikely(!c)) - return; - set->ext_size -= sizeof(*c) + strlen(c->str) + 1; - kfree_rcu(c, rcu); - rcu_assign_pointer(comment->c, NULL); -} - -#endif -#endif diff --git a/include/linux/netfilter/ipset/ip_set_counter.h b/include/linux/netfilter/ipset/ip_set_counter.h deleted file mode 100644 index 5477492c8374..000000000000 --- a/include/linux/netfilter/ipset/ip_set_counter.h +++ /dev/null @@ -1,85 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -#ifndef _IP_SET_COUNTER_H -#define _IP_SET_COUNTER_H - -/* Copyright (C) 2015 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu> - */ - -#ifdef __KERNEL__ - -static inline void -ip_set_add_bytes(u64 bytes, struct ip_set_counter *counter) -{ - atomic64_add((long long)bytes, &(counter)->bytes); -} - -static inline void -ip_set_add_packets(u64 packets, struct ip_set_counter *counter) -{ - atomic64_add((long long)packets, &(counter)->packets); -} - -static inline u64 -ip_set_get_bytes(const struct ip_set_counter *counter) -{ - return (u64)atomic64_read(&(counter)->bytes); -} - -static inline u64 -ip_set_get_packets(const struct ip_set_counter *counter) -{ - return (u64)atomic64_read(&(counter)->packets); -} - -static inline bool -ip_set_match_counter(u64 counter, u64 match, u8 op) -{ - switch (op) { - case IPSET_COUNTER_NONE: - return true; - case IPSET_COUNTER_EQ: - return counter == match; - case IPSET_COUNTER_NE: - return counter != match; - case IPSET_COUNTER_LT: - return counter < match; - case IPSET_COUNTER_GT: - return counter > match; - } - return false; -} - -static inline void -ip_set_update_counter(struct ip_set_counter *counter, - const struct ip_set_ext *ext, u32 flags) -{ - if (ext->packets != ULLONG_MAX && - !(flags & IPSET_FLAG_SKIP_COUNTER_UPDATE)) { - ip_set_add_bytes(ext->bytes, counter); - ip_set_add_packets(ext->packets, counter); - } -} - -static inline bool -ip_set_put_counter(struct sk_buff *skb, const struct ip_set_counter *counter) -{ - return nla_put_net64(skb, IPSET_ATTR_BYTES, - cpu_to_be64(ip_set_get_bytes(counter)), - IPSET_ATTR_PAD) || - nla_put_net64(skb, IPSET_ATTR_PACKETS, - cpu_to_be64(ip_set_get_packets(counter)), - IPSET_ATTR_PAD); -} - -static inline void -ip_set_init_counter(struct ip_set_counter *counter, - const struct ip_set_ext *ext) -{ - if (ext->bytes != ULLONG_MAX) - atomic64_set(&(counter)->bytes, (long long)(ext->bytes)); - if (ext->packets != ULLONG_MAX) - atomic64_set(&(counter)->packets, (long long)(ext->packets)); -} - -#endif /* __KERNEL__ */ -#endif /* _IP_SET_COUNTER_H */ diff --git a/include/linux/netfilter/ipset/ip_set_getport.h b/include/linux/netfilter/ipset/ip_set_getport.h index ac6a11d38a19..d74cd112b88a 100644 --- a/include/linux/netfilter/ipset/ip_set_getport.h +++ b/include/linux/netfilter/ipset/ip_set_getport.h @@ -2,10 +2,14 @@ #ifndef _IP_SET_GETPORT_H #define _IP_SET_GETPORT_H +#include <linux/skbuff.h> +#include <linux/types.h> +#include <uapi/linux/in.h> + extern bool ip_set_get_ip4_port(const struct sk_buff *skb, bool src, __be16 *port, u8 *proto); -#if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE) +#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES) extern bool ip_set_get_ip6_port(const struct sk_buff *skb, bool src, __be16 *port, u8 *proto); #else diff --git a/include/linux/netfilter/ipset/ip_set_skbinfo.h b/include/linux/netfilter/ipset/ip_set_skbinfo.h deleted file mode 100644 index aae081e085c6..000000000000 --- a/include/linux/netfilter/ipset/ip_set_skbinfo.h +++ /dev/null @@ -1,43 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -#ifndef _IP_SET_SKBINFO_H -#define _IP_SET_SKBINFO_H - -/* Copyright (C) 2015 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu> - */ - -#ifdef __KERNEL__ - -static inline void -ip_set_get_skbinfo(struct ip_set_skbinfo *skbinfo, - const struct ip_set_ext *ext, - struct ip_set_ext *mext, u32 flags) -{ - mext->skbinfo = *skbinfo; -} - -static inline bool -ip_set_put_skbinfo(struct sk_buff *skb, const struct ip_set_skbinfo *skbinfo) -{ - /* Send nonzero parameters only */ - return ((skbinfo->skbmark || skbinfo->skbmarkmask) && - nla_put_net64(skb, IPSET_ATTR_SKBMARK, - cpu_to_be64((u64)skbinfo->skbmark << 32 | - skbinfo->skbmarkmask), - IPSET_ATTR_PAD)) || - (skbinfo->skbprio && - nla_put_net32(skb, IPSET_ATTR_SKBPRIO, - cpu_to_be32(skbinfo->skbprio))) || - (skbinfo->skbqueue && - nla_put_net16(skb, IPSET_ATTR_SKBQUEUE, - cpu_to_be16(skbinfo->skbqueue))); -} - -static inline void -ip_set_init_skbinfo(struct ip_set_skbinfo *skbinfo, - const struct ip_set_ext *ext) -{ - *skbinfo = ext->skbinfo; -} - -#endif /* __KERNEL__ */ -#endif /* _IP_SET_SKBINFO_H */ diff --git a/include/linux/netfilter/ipset/ip_set_timeout.h b/include/linux/netfilter/ipset/ip_set_timeout.h deleted file mode 100644 index 88926b4c75f0..000000000000 --- a/include/linux/netfilter/ipset/ip_set_timeout.h +++ /dev/null @@ -1,78 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -#ifndef _IP_SET_TIMEOUT_H -#define _IP_SET_TIMEOUT_H - -/* Copyright (C) 2003-2013 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu> - */ - -#ifdef __KERNEL__ - -/* How often should the gc be run by default */ -#define IPSET_GC_TIME (3 * 60) - -/* Timeout period depending on the timeout value of the given set */ -#define IPSET_GC_PERIOD(timeout) \ - ((timeout/3) ? min_t(u32, (timeout)/3, IPSET_GC_TIME) : 1) - -/* Entry is set with no timeout value */ -#define IPSET_ELEM_PERMANENT 0 - -/* Set is defined with timeout support: timeout value may be 0 */ -#define IPSET_NO_TIMEOUT UINT_MAX - -/* Max timeout value, see msecs_to_jiffies() in jiffies.h */ -#define IPSET_MAX_TIMEOUT (UINT_MAX >> 1)/MSEC_PER_SEC - -#define ip_set_adt_opt_timeout(opt, set) \ -((opt)->ext.timeout != IPSET_NO_TIMEOUT ? (opt)->ext.timeout : (set)->timeout) - -static inline unsigned int -ip_set_timeout_uget(struct nlattr *tb) -{ - unsigned int timeout = ip_set_get_h32(tb); - - /* Normalize to fit into jiffies */ - if (timeout > IPSET_MAX_TIMEOUT) - timeout = IPSET_MAX_TIMEOUT; - - return timeout; -} - -static inline bool -ip_set_timeout_expired(const unsigned long *t) -{ - return *t != IPSET_ELEM_PERMANENT && time_is_before_jiffies(*t); -} - -static inline void -ip_set_timeout_set(unsigned long *timeout, u32 value) -{ - unsigned long t; - - if (!value) { - *timeout = IPSET_ELEM_PERMANENT; - return; - } - - t = msecs_to_jiffies(value * MSEC_PER_SEC) + jiffies; - if (t == IPSET_ELEM_PERMANENT) - /* Bingo! :-) */ - t--; - *timeout = t; -} - -static inline u32 -ip_set_timeout_get(const unsigned long *timeout) -{ - u32 t; - - if (*timeout == IPSET_ELEM_PERMANENT) - return 0; - - t = jiffies_to_msecs(*timeout - jiffies)/MSEC_PER_SEC; - /* Zero value in userspace means no timeout */ - return t == 0 ? 1 : t; -} - -#endif /* __KERNEL__ */ -#endif /* _IP_SET_TIMEOUT_H */ diff --git a/include/linux/netfilter/nf_conntrack_amanda.h b/include/linux/netfilter/nf_conntrack_amanda.h index 34345e543ba2..6f0ac896fcc9 100644 --- a/include/linux/netfilter/nf_conntrack_amanda.h +++ b/include/linux/netfilter/nf_conntrack_amanda.h @@ -3,6 +3,10 @@ #define _NF_CONNTRACK_AMANDA_H /* AMANDA tracking. */ +#include <linux/netfilter.h> +#include <linux/skbuff.h> +#include <net/netfilter/nf_conntrack_expect.h> + extern unsigned int (*nf_nat_amanda_hook)(struct sk_buff *skb, enum ip_conntrack_info ctinfo, unsigned int protoff, diff --git a/include/linux/netfilter/nf_conntrack_common.h b/include/linux/netfilter/nf_conntrack_common.h index e142b2b5f1ea..1db83c931d9c 100644 --- a/include/linux/netfilter/nf_conntrack_common.h +++ b/include/linux/netfilter/nf_conntrack_common.h @@ -2,6 +2,7 @@ #ifndef _NF_CONNTRACK_COMMON_H #define _NF_CONNTRACK_COMMON_H +#include <linux/atomic.h> #include <uapi/linux/netfilter/nf_conntrack_common.h> struct ip_conntrack_stat { @@ -19,4 +20,23 @@ struct ip_conntrack_stat { unsigned int search_restart; }; +#define NFCT_INFOMASK 7UL +#define NFCT_PTRMASK ~(NFCT_INFOMASK) + +struct nf_conntrack { + atomic_t use; +}; + +void nf_conntrack_destroy(struct nf_conntrack *nfct); +static inline void nf_conntrack_put(struct nf_conntrack *nfct) +{ + if (nfct && atomic_dec_and_test(&nfct->use)) + nf_conntrack_destroy(nfct); +} +static inline void nf_conntrack_get(struct nf_conntrack *nfct) +{ + if (nfct) + atomic_inc(&nfct->use); +} + #endif /* _NF_CONNTRACK_COMMON_H */ diff --git a/include/linux/netfilter/nf_conntrack_dccp.h b/include/linux/netfilter/nf_conntrack_dccp.h index ace0f952d50f..c509ed76e714 100644 --- a/include/linux/netfilter/nf_conntrack_dccp.h +++ b/include/linux/netfilter/nf_conntrack_dccp.h @@ -25,7 +25,6 @@ enum ct_dccp_roles { }; #define CT_DCCP_ROLE_MAX (__CT_DCCP_ROLE_MAX - 1) -#ifdef __KERNEL__ #include <linux/netfilter/nf_conntrack_tuple_common.h> struct nf_ct_dccp { @@ -36,6 +35,4 @@ struct nf_ct_dccp { u_int64_t handshake_seq; }; -#endif /* __KERNEL__ */ - #endif /* _NF_CONNTRACK_DCCP_H */ diff --git a/include/linux/netfilter/nf_conntrack_ftp.h b/include/linux/netfilter/nf_conntrack_ftp.h index 73a296dfd019..0e38302820b9 100644 --- a/include/linux/netfilter/nf_conntrack_ftp.h +++ b/include/linux/netfilter/nf_conntrack_ftp.h @@ -2,8 +2,12 @@ #ifndef _NF_CONNTRACK_FTP_H #define _NF_CONNTRACK_FTP_H +#include <linux/netfilter.h> +#include <linux/skbuff.h> +#include <linux/types.h> +#include <net/netfilter/nf_conntrack_expect.h> #include <uapi/linux/netfilter/nf_conntrack_ftp.h> - +#include <uapi/linux/netfilter/nf_conntrack_tuple_common.h> #define FTP_PORT 21 @@ -20,8 +24,6 @@ struct nf_ct_ftp_master { u_int16_t flags[IP_CT_DIR_MAX]; }; -struct nf_conntrack_expect; - /* For NAT to hook in when we find a packet which describes what other * connection we should expect. */ extern unsigned int (*nf_nat_ftp_hook)(struct sk_buff *skb, diff --git a/include/linux/netfilter/nf_conntrack_h323.h b/include/linux/netfilter/nf_conntrack_h323.h index f76ed373a2a5..4561ec0fcea4 100644 --- a/include/linux/netfilter/nf_conntrack_h323.h +++ b/include/linux/netfilter/nf_conntrack_h323.h @@ -2,9 +2,12 @@ #ifndef _NF_CONNTRACK_H323_H #define _NF_CONNTRACK_H323_H -#ifdef __KERNEL__ - +#include <linux/netfilter.h> +#include <linux/skbuff.h> +#include <linux/types.h> #include <linux/netfilter/nf_conntrack_h323_asn1.h> +#include <net/netfilter/nf_conntrack_expect.h> +#include <uapi/linux/netfilter/nf_conntrack_tuple_common.h> #define RAS_PORT 1719 #define Q931_PORT 1720 @@ -28,8 +31,6 @@ struct nf_ct_h323_master { }; }; -struct nf_conn; - int get_h225_addr(struct nf_conn *ct, unsigned char *data, TransportAddress *taddr, union nf_inet_addr *addr, __be16 *port); @@ -94,5 +95,3 @@ extern int (*nat_q931_hook) (struct sk_buff *skb, struct nf_conn *ct, struct nf_conntrack_expect *exp); #endif - -#endif diff --git a/include/linux/netfilter/nf_conntrack_h323_asn1.h b/include/linux/netfilter/nf_conntrack_h323_asn1.h index 91d6275292a5..bd6797f823b2 100644 --- a/include/linux/netfilter/nf_conntrack_h323_asn1.h +++ b/include/linux/netfilter/nf_conntrack_h323_asn1.h @@ -1,7 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /**************************************************************************** - * ip_conntrack_h323_asn1.h - BER and PER decoding library for H.323 - * conntrack/NAT module. + * BER and PER decoding library for H.323 conntrack/NAT module. * * Copyright (c) 2006 by Jing Min Zhao <zhaojingmin@users.sourceforge.net> * @@ -38,6 +37,8 @@ /***************************************************************************** * H.323 Types ****************************************************************************/ + +#include <linux/types.h> #include <linux/netfilter/nf_conntrack_h323_types.h> typedef struct { diff --git a/include/linux/netfilter/nf_conntrack_h323_types.h b/include/linux/netfilter/nf_conntrack_h323_types.h index 7a6871ac8784..74c6f9241944 100644 --- a/include/linux/netfilter/nf_conntrack_h323_types.h +++ b/include/linux/netfilter/nf_conntrack_h323_types.h @@ -4,6 +4,9 @@ * Copyright (c) 2006 Jing Min Zhao <zhaojingmin@users.sourceforge.net> */ +#ifndef _NF_CONNTRACK_H323_TYPES_H +#define _NF_CONNTRACK_H323_TYPES_H + typedef struct TransportAddress_ipAddress { /* SEQUENCE */ int options; /* No use */ unsigned int ip; @@ -931,3 +934,5 @@ typedef struct RasMessage { /* CHOICE */ InfoRequestResponse infoRequestResponse; }; } RasMessage; + +#endif /* _NF_CONNTRACK_H323_TYPES_H */ diff --git a/include/linux/netfilter/nf_conntrack_irc.h b/include/linux/netfilter/nf_conntrack_irc.h index 00c2b74206e1..d02255f721e1 100644 --- a/include/linux/netfilter/nf_conntrack_irc.h +++ b/include/linux/netfilter/nf_conntrack_irc.h @@ -2,7 +2,9 @@ #ifndef _NF_CONNTRACK_IRC_H #define _NF_CONNTRACK_IRC_H -#ifdef __KERNEL__ +#include <linux/netfilter.h> +#include <linux/skbuff.h> +#include <net/netfilter/nf_conntrack_expect.h> #define IRC_PORT 6667 @@ -13,5 +15,4 @@ extern unsigned int (*nf_nat_irc_hook)(struct sk_buff *skb, unsigned int matchlen, struct nf_conntrack_expect *exp); -#endif /* __KERNEL__ */ #endif /* _NF_CONNTRACK_IRC_H */ diff --git a/include/linux/netfilter/nf_conntrack_pptp.h b/include/linux/netfilter/nf_conntrack_pptp.h index 833a5b2255ea..fcc409de31a4 100644 --- a/include/linux/netfilter/nf_conntrack_pptp.h +++ b/include/linux/netfilter/nf_conntrack_pptp.h @@ -3,7 +3,12 @@ #ifndef _NF_CONNTRACK_PPTP_H #define _NF_CONNTRACK_PPTP_H +#include <linux/netfilter.h> +#include <linux/skbuff.h> +#include <linux/types.h> #include <linux/netfilter/nf_conntrack_common.h> +#include <net/netfilter/nf_conntrack_expect.h> +#include <uapi/linux/netfilter/nf_conntrack_tuple_common.h> extern const char *const pptp_msg_name[]; @@ -45,8 +50,6 @@ struct nf_nat_pptp { __be16 pac_call_id; /* NAT'ed PAC call id */ }; -#ifdef __KERNEL__ - #define PPTP_CONTROL_PORT 1723 #define PPTP_PACKET_CONTROL 1 @@ -297,10 +300,6 @@ union pptp_ctrl_union { struct PptpSetLinkInfo setlink; }; -/* crap needed for nf_conntrack_compat.h */ -struct nf_conn; -struct nf_conntrack_expect; - extern int (*nf_nat_pptp_hook_outbound)(struct sk_buff *skb, struct nf_conn *ct, enum ip_conntrack_info ctinfo, @@ -323,5 +322,4 @@ extern void (*nf_nat_pptp_hook_expectfn)(struct nf_conn *ct, struct nf_conntrack_expect *exp); -#endif /* __KERNEL__ */ #endif /* _NF_CONNTRACK_PPTP_H */ diff --git a/include/linux/netfilter/nf_conntrack_proto_gre.h b/include/linux/netfilter/nf_conntrack_proto_gre.h index 25f9a770fb84..f33aa6021364 100644 --- a/include/linux/netfilter/nf_conntrack_proto_gre.h +++ b/include/linux/netfilter/nf_conntrack_proto_gre.h @@ -10,7 +10,6 @@ struct nf_ct_gre { unsigned int timeout; }; -#ifdef __KERNEL__ #include <net/netfilter/nf_conntrack_tuple.h> struct nf_conn; @@ -32,5 +31,4 @@ void nf_ct_gre_keymap_destroy(struct nf_conn *ct); bool gre_pkt_to_tuple(const struct sk_buff *skb, unsigned int dataoff, struct net *net, struct nf_conntrack_tuple *tuple); -#endif /* __KERNEL__ */ #endif /* _CONNTRACK_PROTO_GRE_H */ diff --git a/include/linux/netfilter/nf_conntrack_sane.h b/include/linux/netfilter/nf_conntrack_sane.h index 7d2de44edce3..46c7acd1b4a7 100644 --- a/include/linux/netfilter/nf_conntrack_sane.h +++ b/include/linux/netfilter/nf_conntrack_sane.h @@ -3,8 +3,6 @@ #define _NF_CONNTRACK_SANE_H /* SANE tracking. */ -#ifdef __KERNEL__ - #define SANE_PORT 6566 enum sane_state { @@ -17,6 +15,4 @@ struct nf_ct_sane_master { enum sane_state state; }; -#endif /* __KERNEL__ */ - #endif /* _NF_CONNTRACK_SANE_H */ diff --git a/include/linux/netfilter/nf_conntrack_sip.h b/include/linux/netfilter/nf_conntrack_sip.h index c7fc38807a33..c620521c42bc 100644 --- a/include/linux/netfilter/nf_conntrack_sip.h +++ b/include/linux/netfilter/nf_conntrack_sip.h @@ -1,11 +1,10 @@ /* SPDX-License-Identifier: GPL-2.0 */ #ifndef __NF_CONNTRACK_SIP_H__ #define __NF_CONNTRACK_SIP_H__ -#ifdef __KERNEL__ - -#include <net/netfilter/nf_conntrack_expect.h> +#include <linux/skbuff.h> #include <linux/types.h> +#include <net/netfilter/nf_conntrack_expect.h> #define SIP_PORT 5060 #define SIP_TIMEOUT 3600 @@ -196,5 +195,4 @@ int ct_sip_get_sdp_header(const struct nf_conn *ct, const char *dptr, enum sdp_header_types term, unsigned int *matchoff, unsigned int *matchlen); -#endif /* __KERNEL__ */ #endif /* __NF_CONNTRACK_SIP_H__ */ diff --git a/include/linux/netfilter/nf_conntrack_snmp.h b/include/linux/netfilter/nf_conntrack_snmp.h index 818088c47475..87e4f33eb55f 100644 --- a/include/linux/netfilter/nf_conntrack_snmp.h +++ b/include/linux/netfilter/nf_conntrack_snmp.h @@ -2,6 +2,9 @@ #ifndef _NF_CONNTRACK_SNMP_H #define _NF_CONNTRACK_SNMP_H +#include <linux/netfilter.h> +#include <linux/skbuff.h> + extern int (*nf_nat_snmp_hook)(struct sk_buff *skb, unsigned int protoff, struct nf_conn *ct, diff --git a/include/linux/netfilter/nf_conntrack_tftp.h b/include/linux/netfilter/nf_conntrack_tftp.h index 5769e12dd0a2..dc4c1b9beac0 100644 --- a/include/linux/netfilter/nf_conntrack_tftp.h +++ b/include/linux/netfilter/nf_conntrack_tftp.h @@ -4,6 +4,11 @@ #define TFTP_PORT 69 +#include <linux/netfilter.h> +#include <linux/skbuff.h> +#include <linux/types.h> +#include <net/netfilter/nf_conntrack_expect.h> + struct tftphdr { __be16 opcode; }; diff --git a/include/linux/netfilter/x_tables.h b/include/linux/netfilter/x_tables.h index 1f852ef7b098..1b261c51b3a3 100644 --- a/include/linux/netfilter/x_tables.h +++ b/include/linux/netfilter/x_tables.h @@ -336,7 +336,7 @@ void xt_free_table_info(struct xt_table_info *info); /** * xt_recseq - recursive seqcount for netfilter use - * + * * Packet processing changes the seqcount only if no recursion happened * get_counters() can use read_seqcount_begin()/read_seqcount_retry(), * because we use the normal seqcount convention : diff --git a/include/linux/netfilter/xt_hashlimit.h b/include/linux/netfilter/xt_hashlimit.h deleted file mode 100644 index 169d03983589..000000000000 --- a/include/linux/netfilter/xt_hashlimit.h +++ /dev/null @@ -1,11 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef _XT_HASHLIMIT_H -#define _XT_HASHLIMIT_H - -#include <uapi/linux/netfilter/xt_hashlimit.h> - -#define XT_HASHLIMIT_ALL (XT_HASHLIMIT_HASH_DIP | XT_HASHLIMIT_HASH_DPT | \ - XT_HASHLIMIT_HASH_SIP | XT_HASHLIMIT_HASH_SPT | \ - XT_HASHLIMIT_INVERT | XT_HASHLIMIT_BYTES |\ - XT_HASHLIMIT_RATE_MATCH) -#endif /*_XT_HASHLIMIT_H*/ diff --git a/include/linux/netfilter/xt_physdev.h b/include/linux/netfilter/xt_physdev.h deleted file mode 100644 index 4ca0593949cd..000000000000 --- a/include/linux/netfilter/xt_physdev.h +++ /dev/null @@ -1,8 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef _XT_PHYSDEV_H -#define _XT_PHYSDEV_H - -#include <linux/if.h> -#include <uapi/linux/netfilter/xt_physdev.h> - -#endif /*_XT_PHYSDEV_H*/ diff --git a/include/linux/netfilter_bridge.h b/include/linux/netfilter_bridge.h index 5f2614d02e03..f980edfdd278 100644 --- a/include/linux/netfilter_bridge.h +++ b/include/linux/netfilter_bridge.h @@ -5,6 +5,13 @@ #include <uapi/linux/netfilter_bridge.h> #include <linux/skbuff.h> +struct nf_bridge_frag_data { + char mac[ETH_HLEN]; + bool vlan_present; + u16 vlan_tci; + __be16 vlan_proto; +}; + #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER) int br_handle_frame_finish(struct net *net, struct sock *sk, struct sk_buff *skb); diff --git a/include/linux/netfilter_bridge/ebt_802_3.h b/include/linux/netfilter_bridge/ebt_802_3.h deleted file mode 100644 index c6147f9c0d80..000000000000 --- a/include/linux/netfilter_bridge/ebt_802_3.h +++ /dev/null @@ -1,12 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef __LINUX_BRIDGE_EBT_802_3_H -#define __LINUX_BRIDGE_EBT_802_3_H - -#include <linux/skbuff.h> -#include <uapi/linux/netfilter_bridge/ebt_802_3.h> - -static inline struct ebt_802_3_hdr *ebt_802_3_hdr(const struct sk_buff *skb) -{ - return (struct ebt_802_3_hdr *)skb_mac_header(skb); -} -#endif diff --git a/include/linux/netfilter_bridge/ebtables.h b/include/linux/netfilter_bridge/ebtables.h index c6935be7c6ca..162f59d0d17a 100644 --- a/include/linux/netfilter_bridge/ebtables.h +++ b/include/linux/netfilter_bridge/ebtables.h @@ -105,6 +105,7 @@ struct ebt_table { #define EBT_ALIGN(s) (((s) + (__alignof__(struct _xt_align)-1)) & \ ~(__alignof__(struct _xt_align)-1)) + extern int ebt_register_table(struct net *net, const struct ebt_table *table, const struct nf_hook_ops *ops, diff --git a/include/linux/netfilter_ipv4/ip_tables.h b/include/linux/netfilter_ipv4/ip_tables.h index d026e63a5aa4..e9e1ed74cdf1 100644 --- a/include/linux/netfilter_ipv4/ip_tables.h +++ b/include/linux/netfilter_ipv4/ip_tables.h @@ -17,14 +17,11 @@ #include <linux/if.h> #include <linux/in.h> +#include <linux/init.h> #include <linux/ip.h> #include <linux/skbuff.h> - -#include <linux/init.h> #include <uapi/linux/netfilter_ipv4/ip_tables.h> -extern void ipt_init(void) __init; - int ipt_register_table(struct net *net, const struct xt_table *table, const struct ipt_replace *repl, const struct nf_hook_ops *ops, struct xt_table **res); diff --git a/include/linux/netfilter_ipv6.h b/include/linux/netfilter_ipv6.h index 12113e502656..aac42c28fe62 100644 --- a/include/linux/netfilter_ipv6.h +++ b/include/linux/netfilter_ipv6.h @@ -1,13 +1,26 @@ /* IPv6-specific defines for netfilter. * (C)1998 Rusty Russell -- This code is GPL. * (C)1999 David Jeffery - * this header was blatantly ripped from netfilter_ipv4.h + * this header was blatantly ripped from netfilter_ipv4.h * it's amazing what adding a bunch of 6s can do =8^) */ #ifndef __LINUX_IP6_NETFILTER_H #define __LINUX_IP6_NETFILTER_H #include <uapi/linux/netfilter_ipv6.h> +#include <net/tcp.h> + +/* Check for an extension */ +static inline int +nf_ip6_ext_hdr(u8 nexthdr) +{ return (nexthdr == IPPROTO_HOPOPTS) || + (nexthdr == IPPROTO_ROUTING) || + (nexthdr == IPPROTO_FRAGMENT) || + (nexthdr == IPPROTO_ESP) || + (nexthdr == IPPROTO_AH) || + (nexthdr == IPPROTO_NONE) || + (nexthdr == IPPROTO_DSTOPTS); +} /* Extra routing may needed on local out, as the QUEUE target never returns * control to the table. @@ -19,6 +32,7 @@ struct ip6_rt_info { }; struct nf_queue_entry; +struct nf_bridge_frag_data; /* * Hook functions for ipv6 to allow xt_* modules to be built-in even @@ -34,11 +48,24 @@ struct nf_ipv6_ops { struct in6_addr *saddr); int (*route)(struct net *net, struct dst_entry **dst, struct flowi *fl, bool strict); + u32 (*cookie_init_sequence)(const struct ipv6hdr *iph, + const struct tcphdr *th, u16 *mssp); + int (*cookie_v6_check)(const struct ipv6hdr *iph, + const struct tcphdr *th, __u32 cookie); #endif void (*route_input)(struct sk_buff *skb); int (*fragment)(struct net *net, struct sock *sk, struct sk_buff *skb, int (*output)(struct net *, struct sock *, struct sk_buff *)); int (*reroute)(struct sk_buff *skb, const struct nf_queue_entry *entry); +#if IS_MODULE(CONFIG_IPV6) + int (*br_defrag)(struct net *net, struct sk_buff *skb, u32 user); + int (*br_fragment)(struct net *net, struct sock *sk, + struct sk_buff *skb, + struct nf_bridge_frag_data *data, + int (*output)(struct net *, struct sock *sk, + const struct nf_bridge_frag_data *data, + struct sk_buff *)); +#endif }; #ifdef CONFIG_NETFILTER @@ -60,8 +87,10 @@ static inline int nf_ipv6_chk_addr(struct net *net, const struct in6_addr *addr, return 1; return v6_ops->chk_addr(net, addr, dev, strict); -#else +#elif IS_BUILTIN(CONFIG_IPV6) return ipv6_chk_addr(net, addr, dev, strict); +#else + return 1; #endif } @@ -86,6 +115,52 @@ static inline int nf_ip6_route(struct net *net, struct dst_entry **dst, #endif } +#include <net/netfilter/ipv6/nf_defrag_ipv6.h> + +static inline int nf_ipv6_br_defrag(struct net *net, struct sk_buff *skb, + u32 user) +{ +#if IS_MODULE(CONFIG_IPV6) + const struct nf_ipv6_ops *v6_ops = nf_get_ipv6_ops(); + + if (!v6_ops) + return 1; + + return v6_ops->br_defrag(net, skb, user); +#elif IS_BUILTIN(CONFIG_IPV6) + return nf_ct_frag6_gather(net, skb, user); +#else + return 1; +#endif +} + +int br_ip6_fragment(struct net *net, struct sock *sk, struct sk_buff *skb, + struct nf_bridge_frag_data *data, + int (*output)(struct net *, struct sock *sk, + const struct nf_bridge_frag_data *data, + struct sk_buff *)); + +static inline int nf_br_ip6_fragment(struct net *net, struct sock *sk, + struct sk_buff *skb, + struct nf_bridge_frag_data *data, + int (*output)(struct net *, struct sock *sk, + const struct nf_bridge_frag_data *data, + struct sk_buff *)) +{ +#if IS_MODULE(CONFIG_IPV6) + const struct nf_ipv6_ops *v6_ops = nf_get_ipv6_ops(); + + if (!v6_ops) + return 1; + + return v6_ops->br_fragment(net, sk, skb, data, output); +#elif IS_BUILTIN(CONFIG_IPV6) + return br_ip6_fragment(net, sk, skb, data, output); +#else + return 1; +#endif +} + int ip6_route_me_harder(struct net *net, struct sk_buff *skb); static inline int nf_ip6_route_me_harder(struct net *net, struct sk_buff *skb) @@ -97,9 +172,44 @@ static inline int nf_ip6_route_me_harder(struct net *net, struct sk_buff *skb) return -EHOSTUNREACH; return v6_ops->route_me_harder(net, skb); -#else +#elif IS_BUILTIN(CONFIG_IPV6) return ip6_route_me_harder(net, skb); +#else + return -EHOSTUNREACH; +#endif +} + +static inline u32 nf_ipv6_cookie_init_sequence(const struct ipv6hdr *iph, + const struct tcphdr *th, + u16 *mssp) +{ +#if IS_ENABLED(CONFIG_SYN_COOKIES) +#if IS_MODULE(CONFIG_IPV6) + const struct nf_ipv6_ops *v6_ops = nf_get_ipv6_ops(); + + if (v6_ops) + return v6_ops->cookie_init_sequence(iph, th, mssp); +#elif IS_BUILTIN(CONFIG_IPV6) + return __cookie_v6_init_sequence(iph, th, mssp); +#endif +#endif + return 0; +} + +static inline int nf_cookie_v6_check(const struct ipv6hdr *iph, + const struct tcphdr *th, __u32 cookie) +{ +#if IS_ENABLED(CONFIG_SYN_COOKIES) +#if IS_MODULE(CONFIG_IPV6) + const struct nf_ipv6_ops *v6_ops = nf_get_ipv6_ops(); + + if (v6_ops) + return v6_ops->cookie_v6_check(iph, th, cookie); +#elif IS_BUILTIN(CONFIG_IPV6) + return __cookie_v6_check(iph, th, cookie); +#endif #endif + return 0; } __sum16 nf_ip6_checksum(struct sk_buff *skb, unsigned int hook, diff --git a/include/linux/netfilter_ipv6/ip6_tables.h b/include/linux/netfilter_ipv6/ip6_tables.h index 99cbfd3add40..78ab959c4575 100644 --- a/include/linux/netfilter_ipv6/ip6_tables.h +++ b/include/linux/netfilter_ipv6/ip6_tables.h @@ -17,15 +17,13 @@ #include <linux/if.h> #include <linux/in6.h> +#include <linux/init.h> #include <linux/ipv6.h> #include <linux/skbuff.h> - -#include <linux/init.h> #include <uapi/linux/netfilter_ipv6/ip6_tables.h> -extern void ip6t_init(void) __init; - extern void *ip6t_alloc_initial_table(const struct xt_table *); + int ip6t_register_table(struct net *net, const struct xt_table *table, const struct ip6t_replace *repl, const struct nf_hook_ops *ops, struct xt_table **res); @@ -35,18 +33,6 @@ extern unsigned int ip6t_do_table(struct sk_buff *skb, const struct nf_hook_state *state, struct xt_table *table); -/* Check for an extension */ -static inline int -ip6t_ext_hdr(u8 nexthdr) -{ return (nexthdr == IPPROTO_HOPOPTS) || - (nexthdr == IPPROTO_ROUTING) || - (nexthdr == IPPROTO_FRAGMENT) || - (nexthdr == IPPROTO_ESP) || - (nexthdr == IPPROTO_AH) || - (nexthdr == IPPROTO_NONE) || - (nexthdr == IPPROTO_DSTOPTS); -} - #ifdef CONFIG_COMPAT #include <net/compat.h> diff --git a/include/linux/netlink.h b/include/linux/netlink.h index 593d1b9c33a8..205fa7b1f07a 100644 --- a/include/linux/netlink.h +++ b/include/linux/netlink.h @@ -192,7 +192,14 @@ struct netlink_callback { bool strict_check; u16 answer_flags; unsigned int prev_seq, seq; - long args[6]; + union { + u8 ctx[48]; + + /* args is deprecated. Cast a struct over ctx instead + * for proper type safety. + */ + long args[6]; + }; }; struct netlink_notify { diff --git a/include/linux/nfs4.h b/include/linux/nfs4.h index 22494d170619..fd59904a282c 100644 --- a/include/linux/nfs4.h +++ b/include/linux/nfs4.h @@ -660,6 +660,7 @@ enum pnfs_update_layout_reason { PNFS_UPDATE_LAYOUT_BLOCKED, PNFS_UPDATE_LAYOUT_INVALID_OPEN, PNFS_UPDATE_LAYOUT_SEND_LAYOUTGET, + PNFS_UPDATE_LAYOUT_EXIT, }; #define NFS4_OP_MAP_NUM_LONGS \ diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h index d363d5765cdf..570a60c2f4f4 100644 --- a/include/linux/nfs_fs.h +++ b/include/linux/nfs_fs.h @@ -223,6 +223,8 @@ struct nfs4_copy_state { #define NFS_INO_INVALID_MTIME BIT(10) /* cached mtime is invalid */ #define NFS_INO_INVALID_SIZE BIT(11) /* cached size is invalid */ #define NFS_INO_INVALID_OTHER BIT(12) /* other attrs are invalid */ +#define NFS_INO_DATA_INVAL_DEFER \ + BIT(13) /* Deferred cache invalidation */ #define NFS_INO_INVALID_ATTR (NFS_INO_INVALID_CHANGE \ | NFS_INO_INVALID_CTIME \ @@ -488,6 +490,9 @@ extern const struct file_operations nfs_dir_operations; extern const struct dentry_operations nfs_dentry_operations; extern void nfs_force_lookup_revalidate(struct inode *dir); +extern struct dentry *nfs_add_or_obtain(struct dentry *dentry, + struct nfs_fh *fh, struct nfs_fattr *fattr, + struct nfs4_label *label); extern int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fh, struct nfs_fattr *fattr, struct nfs4_label *label); extern int nfs_may_open(struct inode *inode, const struct cred *cred, int openflags); diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h index 1e78032a174b..a87fe854f008 100644 --- a/include/linux/nfs_fs_sb.h +++ b/include/linux/nfs_fs_sb.h @@ -58,6 +58,7 @@ struct nfs_client { struct nfs_subversion * cl_nfs_mod; /* pointer to nfs version module */ u32 cl_minorversion;/* NFSv4 minorversion */ + unsigned int cl_nconnect; /* Number of connections */ const char * cl_principal; /* used for machine cred */ #if IS_ENABLED(CONFIG_NFS_V4) diff --git a/include/linux/node.h b/include/linux/node.h index 1a557c589ecb..4866f32a02d8 100644 --- a/include/linux/node.h +++ b/include/linux/node.h @@ -137,10 +137,7 @@ static inline int register_one_node(int nid) extern void unregister_one_node(int nid); extern int register_cpu_under_node(unsigned int cpu, unsigned int nid); extern int unregister_cpu_under_node(unsigned int cpu, unsigned int nid); -extern int register_mem_sect_under_node(struct memory_block *mem_blk, - void *arg); -extern int unregister_mem_sect_under_nodes(struct memory_block *mem_blk, - unsigned long phys_index); +extern void unregister_memory_block_under_nodes(struct memory_block *mem_blk); extern int register_memory_node_under_compute_node(unsigned int mem_nid, unsigned int cpu_nid, @@ -171,15 +168,8 @@ static inline int unregister_cpu_under_node(unsigned int cpu, unsigned int nid) { return 0; } -static inline int register_mem_sect_under_node(struct memory_block *mem_blk, - void *arg) +static inline void unregister_memory_block_under_nodes(struct memory_block *mem_blk) { - return 0; -} -static inline int unregister_mem_sect_under_nodes(struct memory_block *mem_blk, - unsigned long phys_index) -{ - return 0; } static inline void register_hugetlbfs_with_node(node_registration_func_t reg, diff --git a/include/linux/ntb.h b/include/linux/ntb.h index 56a92e3ae3ae..8c13538aeffe 100644 --- a/include/linux/ntb.h +++ b/include/linux/ntb.h @@ -58,9 +58,11 @@ #include <linux/completion.h> #include <linux/device.h> +#include <linux/interrupt.h> struct ntb_client; struct ntb_dev; +struct ntb_msi; struct pci_dev; /** @@ -205,7 +207,7 @@ static inline int ntb_ctx_ops_is_valid(const struct ntb_ctx_ops *ops) } /** - * struct ntb_ctx_ops - ntb device operations + * struct ntb_dev_ops - ntb device operations * @port_number: See ntb_port_number(). * @peer_port_count: See ntb_peer_port_count(). * @peer_port_number: See ntb_peer_port_number(). @@ -404,7 +406,7 @@ struct ntb_client { #define drv_ntb_client(__drv) container_of((__drv), struct ntb_client, drv) /** - * struct ntb_device - ntb device + * struct ntb_dev - ntb device * @dev: Linux device object. * @pdev: PCI device entry of the ntb. * @topo: Detected topology of the ntb. @@ -426,6 +428,10 @@ struct ntb_dev { spinlock_t ctx_lock; /* block unregister until device is fully released */ struct completion released; + +#ifdef CONFIG_NTB_MSI + struct ntb_msi *msi; +#endif }; #define dev_ntb(__dev) container_of((__dev), struct ntb_dev, dev) @@ -616,7 +622,6 @@ static inline int ntb_port_number(struct ntb_dev *ntb) return ntb->ops->port_number(ntb); } - /** * ntb_peer_port_count() - get the number of peer device ports * @ntb: NTB device context. @@ -654,6 +659,58 @@ static inline int ntb_peer_port_number(struct ntb_dev *ntb, int pidx) } /** + * ntb_logical_port_number() - get the logical port number of the local port + * @ntb: NTB device context. + * + * The Logical Port Number is defined to be a unique number for each + * port starting from zero through to the number of ports minus one. + * This is in contrast to the Port Number where each port can be assigned + * any unique physical number by the hardware. + * + * The logical port number is useful for calculating the resource indexes + * used by peers. + * + * Return: the logical port number or negative value indicating an error + */ +static inline int ntb_logical_port_number(struct ntb_dev *ntb) +{ + int lport = ntb_port_number(ntb); + int pidx; + + if (lport < 0) + return lport; + + for (pidx = 0; pidx < ntb_peer_port_count(ntb); pidx++) + if (lport <= ntb_peer_port_number(ntb, pidx)) + return pidx; + + return pidx; +} + +/** + * ntb_peer_logical_port_number() - get the logical peer port by given index + * @ntb: NTB device context. + * @pidx: Peer port index. + * + * The Logical Port Number is defined to be a unique number for each + * port starting from zero through to the number of ports minus one. + * This is in contrast to the Port Number where each port can be assigned + * any unique physical number by the hardware. + * + * The logical port number is useful for calculating the resource indexes + * used by peers. + * + * Return: the peer's logical port number or negative value indicating an error + */ +static inline int ntb_peer_logical_port_number(struct ntb_dev *ntb, int pidx) +{ + if (ntb_peer_port_number(ntb, pidx) < ntb_port_number(ntb)) + return pidx; + else + return pidx + 1; +} + +/** * ntb_peer_port_idx() - get the peer device port index by given port number * @ntb: NTB device context. * @port: Peer port number. @@ -1506,4 +1563,141 @@ static inline int ntb_peer_msg_write(struct ntb_dev *ntb, int pidx, int midx, return ntb->ops->peer_msg_write(ntb, pidx, midx, msg); } +/** + * ntb_peer_resource_idx() - get a resource index for a given peer idx + * @ntb: NTB device context. + * @pidx: Peer port index. + * + * When constructing a graph of peers, each remote peer must use a different + * resource index (mw, doorbell, etc) to communicate with each other + * peer. + * + * In a two peer system, this function should always return 0 such that + * resource 0 points to the remote peer on both ports. + * + * In a 5 peer system, this function will return the following matrix + * + * pidx \ port 0 1 2 3 4 + * 0 0 0 1 2 3 + * 1 0 1 1 2 3 + * 2 0 1 2 2 3 + * 3 0 1 2 3 3 + * + * For example, if this function is used to program peer's memory + * windows, port 0 will program MW 0 on all it's peers to point to itself. + * port 1 will program MW 0 in port 0 to point to itself and MW 1 on all + * other ports. etc. + * + * For the legacy two host case, ntb_port_number() and ntb_peer_port_number() + * both return zero and therefore this function will always return zero. + * So MW 0 on each host would be programmed to point to the other host. + * + * Return: the resource index to use for that peer. + */ +static inline int ntb_peer_resource_idx(struct ntb_dev *ntb, int pidx) +{ + int local_port, peer_port; + + if (pidx >= ntb_peer_port_count(ntb)) + return -EINVAL; + + local_port = ntb_logical_port_number(ntb); + peer_port = ntb_peer_logical_port_number(ntb, pidx); + + if (peer_port < local_port) + return local_port - 1; + else + return local_port; +} + +/** + * ntb_peer_highest_mw_idx() - get a memory window index for a given peer idx + * using the highest index memory windows first + * + * @ntb: NTB device context. + * @pidx: Peer port index. + * + * Like ntb_peer_resource_idx(), except it returns indexes starting with + * last memory window index. + * + * Return: the resource index to use for that peer. + */ +static inline int ntb_peer_highest_mw_idx(struct ntb_dev *ntb, int pidx) +{ + int ret; + + ret = ntb_peer_resource_idx(ntb, pidx); + if (ret < 0) + return ret; + + return ntb_mw_count(ntb, pidx) - ret - 1; +} + +struct ntb_msi_desc { + u32 addr_offset; + u32 data; +}; + +#ifdef CONFIG_NTB_MSI + +int ntb_msi_init(struct ntb_dev *ntb, void (*desc_changed)(void *ctx)); +int ntb_msi_setup_mws(struct ntb_dev *ntb); +void ntb_msi_clear_mws(struct ntb_dev *ntb); +int ntbm_msi_request_threaded_irq(struct ntb_dev *ntb, irq_handler_t handler, + irq_handler_t thread_fn, + const char *name, void *dev_id, + struct ntb_msi_desc *msi_desc); +void ntbm_msi_free_irq(struct ntb_dev *ntb, unsigned int irq, void *dev_id); +int ntb_msi_peer_trigger(struct ntb_dev *ntb, int peer, + struct ntb_msi_desc *desc); +int ntb_msi_peer_addr(struct ntb_dev *ntb, int peer, + struct ntb_msi_desc *desc, + phys_addr_t *msi_addr); + +#else /* not CONFIG_NTB_MSI */ + +static inline int ntb_msi_init(struct ntb_dev *ntb, + void (*desc_changed)(void *ctx)) +{ + return -EOPNOTSUPP; +} +static inline int ntb_msi_setup_mws(struct ntb_dev *ntb) +{ + return -EOPNOTSUPP; +} +static inline void ntb_msi_clear_mws(struct ntb_dev *ntb) {} +static inline int ntbm_msi_request_threaded_irq(struct ntb_dev *ntb, + irq_handler_t handler, + irq_handler_t thread_fn, + const char *name, void *dev_id, + struct ntb_msi_desc *msi_desc) +{ + return -EOPNOTSUPP; +} +static inline void ntbm_msi_free_irq(struct ntb_dev *ntb, unsigned int irq, + void *dev_id) {} +static inline int ntb_msi_peer_trigger(struct ntb_dev *ntb, int peer, + struct ntb_msi_desc *desc) +{ + return -EOPNOTSUPP; +} +static inline int ntb_msi_peer_addr(struct ntb_dev *ntb, int peer, + struct ntb_msi_desc *desc, + phys_addr_t *msi_addr) +{ + return -EOPNOTSUPP; + +} + +#endif /* CONFIG_NTB_MSI */ + +static inline int ntbm_msi_request_irq(struct ntb_dev *ntb, + irq_handler_t handler, + const char *name, void *dev_id, + struct ntb_msi_desc *msi_desc) +{ + return ntbm_msi_request_threaded_irq(ntb, handler, NULL, name, + dev_id, msi_desc); +} + #endif diff --git a/include/linux/nvme-fc-driver.h b/include/linux/nvme-fc-driver.h index c48e96436f56..10f81629b9ce 100644 --- a/include/linux/nvme-fc-driver.h +++ b/include/linux/nvme-fc-driver.h @@ -6,6 +6,8 @@ #ifndef _NVME_FC_DRIVER_H #define _NVME_FC_DRIVER_H 1 +#include <linux/scatterlist.h> + /* * ********************** LLDD FC-NVME Host API ******************** @@ -791,6 +793,11 @@ struct nvmet_fc_target_port { * nvmefc_tgt_fcp_req. * Entrypoint is Optional. * + * @discovery_event: Called by the transport to generate an RSCN + * change notifications to NVME initiators. The RSCN notifications + * should cause the initiator to rescan the discovery controller + * on the targetport. + * * @max_hw_queues: indicates the maximum number of hw queues the LLDD * supports for cpu affinitization. * Value is Mandatory. Must be at least 1. @@ -832,6 +839,7 @@ struct nvmet_fc_target_template { struct nvmefc_tgt_fcp_req *fcpreq); void (*defer_rcv)(struct nvmet_fc_target_port *tgtport, struct nvmefc_tgt_fcp_req *fcpreq); + void (*discovery_event)(struct nvmet_fc_target_port *tgtport); u32 max_hw_queues; u16 max_sgl_segments; diff --git a/include/linux/nvme.h b/include/linux/nvme.h index 8028adacaff3..f61d6906e59d 100644 --- a/include/linux/nvme.h +++ b/include/linux/nvme.h @@ -140,6 +140,7 @@ enum { * Submission and Completion Queue Entry Sizes for the NVM command set. * (In bytes and specified as a power of two (2^n)). */ +#define NVME_ADM_SQES 6 #define NVME_NVM_IOSQES 6 #define NVME_NVM_IOCQES 4 @@ -315,7 +316,7 @@ struct nvme_id_ns { __u8 nmic; __u8 rescap; __u8 fpi; - __u8 rsvd33; + __u8 dlfeat; __le16 nawun; __le16 nawupf; __le16 nacwu; @@ -324,11 +325,17 @@ struct nvme_id_ns { __le16 nabspf; __le16 noiob; __u8 nvmcap[16]; - __u8 rsvd64[28]; + __le16 npwg; + __le16 npwa; + __le16 npdg; + __le16 npda; + __le16 nows; + __u8 rsvd74[18]; __le32 anagrpid; __u8 rsvd96[3]; __u8 nsattr; - __u8 rsvd100[4]; + __le16 nvmsetid; + __le16 endgid; __u8 nguid[16]; __u8 eui64[8]; struct nvme_lbaf lbaf[16]; @@ -562,6 +569,22 @@ enum nvme_opcode { nvme_cmd_resv_release = 0x15, }; +#define nvme_opcode_name(opcode) { opcode, #opcode } +#define show_nvm_opcode_name(val) \ + __print_symbolic(val, \ + nvme_opcode_name(nvme_cmd_flush), \ + nvme_opcode_name(nvme_cmd_write), \ + nvme_opcode_name(nvme_cmd_read), \ + nvme_opcode_name(nvme_cmd_write_uncor), \ + nvme_opcode_name(nvme_cmd_compare), \ + nvme_opcode_name(nvme_cmd_write_zeroes), \ + nvme_opcode_name(nvme_cmd_dsm), \ + nvme_opcode_name(nvme_cmd_resv_register), \ + nvme_opcode_name(nvme_cmd_resv_report), \ + nvme_opcode_name(nvme_cmd_resv_acquire), \ + nvme_opcode_name(nvme_cmd_resv_release)) + + /* * Descriptor subtype - lower 4 bits of nvme_(keyed_)sgl_desc identifier * @@ -792,7 +815,35 @@ enum nvme_admin_opcode { nvme_admin_security_send = 0x81, nvme_admin_security_recv = 0x82, nvme_admin_sanitize_nvm = 0x84, -}; + nvme_admin_get_lba_status = 0x86, +}; + +#define nvme_admin_opcode_name(opcode) { opcode, #opcode } +#define show_admin_opcode_name(val) \ + __print_symbolic(val, \ + nvme_admin_opcode_name(nvme_admin_delete_sq), \ + nvme_admin_opcode_name(nvme_admin_create_sq), \ + nvme_admin_opcode_name(nvme_admin_get_log_page), \ + nvme_admin_opcode_name(nvme_admin_delete_cq), \ + nvme_admin_opcode_name(nvme_admin_create_cq), \ + nvme_admin_opcode_name(nvme_admin_identify), \ + nvme_admin_opcode_name(nvme_admin_abort_cmd), \ + nvme_admin_opcode_name(nvme_admin_set_features), \ + nvme_admin_opcode_name(nvme_admin_get_features), \ + nvme_admin_opcode_name(nvme_admin_async_event), \ + nvme_admin_opcode_name(nvme_admin_ns_mgmt), \ + nvme_admin_opcode_name(nvme_admin_activate_fw), \ + nvme_admin_opcode_name(nvme_admin_download_fw), \ + nvme_admin_opcode_name(nvme_admin_ns_attach), \ + nvme_admin_opcode_name(nvme_admin_keep_alive), \ + nvme_admin_opcode_name(nvme_admin_directive_send), \ + nvme_admin_opcode_name(nvme_admin_directive_recv), \ + nvme_admin_opcode_name(nvme_admin_dbbuf), \ + nvme_admin_opcode_name(nvme_admin_format_nvm), \ + nvme_admin_opcode_name(nvme_admin_security_send), \ + nvme_admin_opcode_name(nvme_admin_security_recv), \ + nvme_admin_opcode_name(nvme_admin_sanitize_nvm), \ + nvme_admin_opcode_name(nvme_admin_get_lba_status)) enum { NVME_QUEUE_PHYS_CONTIG = (1 << 0), @@ -1008,6 +1059,23 @@ enum nvmf_capsule_command { nvme_fabrics_type_property_get = 0x04, }; +#define nvme_fabrics_type_name(type) { type, #type } +#define show_fabrics_type_name(type) \ + __print_symbolic(type, \ + nvme_fabrics_type_name(nvme_fabrics_type_property_set), \ + nvme_fabrics_type_name(nvme_fabrics_type_connect), \ + nvme_fabrics_type_name(nvme_fabrics_type_property_get)) + +/* + * If not fabrics command, fctype will be ignored. + */ +#define show_opcode_name(qid, opcode, fctype) \ + ((opcode) == nvme_fabrics_command ? \ + show_fabrics_type_name(fctype) : \ + ((qid) ? \ + show_nvm_opcode_name(opcode) : \ + show_admin_opcode_name(opcode))) + struct nvmf_common_command { __u8 opcode; __u8 resv1; @@ -1165,6 +1233,11 @@ struct nvme_command { }; }; +static inline bool nvme_is_fabrics(struct nvme_command *cmd) +{ + return cmd->common.opcode == nvme_fabrics_command; +} + struct nvme_error_slot { __le64 error_count; __le16 sqid; @@ -1186,7 +1259,7 @@ static inline bool nvme_is_write(struct nvme_command *cmd) * * Why can't we simply have a Fabrics In and Fabrics out command? */ - if (unlikely(cmd->common.opcode == nvme_fabrics_command)) + if (unlikely(nvme_is_fabrics(cmd))) return cmd->fabrics.fctype & 1; return cmd->common.opcode & 1; } diff --git a/include/linux/of.h b/include/linux/of.h index 0cf857012f11..844f89e1b039 100644 --- a/include/linux/of.h +++ b/include/linux/of.h @@ -1164,7 +1164,7 @@ static inline int of_property_read_string_index(const struct device_node *np, } /** - * of_property_read_bool - Findfrom a property + * of_property_read_bool - Find a property * @np: device node from which the property value is to be read. * @propname: name of the property to be searched. * diff --git a/include/linux/of_fdt.h b/include/linux/of_fdt.h index a713e5d156d8..acf820e88952 100644 --- a/include/linux/of_fdt.h +++ b/include/linux/of_fdt.h @@ -23,15 +23,6 @@ struct device_node; /* For scanning an arbitrary device-tree at any time */ -extern char *of_fdt_get_string(const void *blob, u32 offset); -extern void *of_fdt_get_property(const void *blob, - unsigned long node, - const char *name, - int *size); -extern bool of_fdt_is_big_endian(const void *blob, - unsigned long node); -extern int of_fdt_match(const void *blob, unsigned long node, - const char *const *compat); extern void *of_fdt_unflatten_tree(const unsigned long *blob, struct device_node *dad, struct device_node **mynodes); @@ -64,9 +55,7 @@ extern int of_get_flat_dt_subnode_by_name(unsigned long node, extern const void *of_get_flat_dt_prop(unsigned long node, const char *name, int *size); extern int of_flat_dt_is_compatible(unsigned long node, const char *name); -extern int of_flat_dt_match(unsigned long node, const char *const *matches); extern unsigned long of_get_flat_dt_root(void); -extern int of_get_flat_dt_size(void); extern uint32_t of_get_flat_dt_phandle(unsigned long node); extern int early_init_dt_scan_chosen(unsigned long node, const char *uname, diff --git a/include/linux/of_gpio.h b/include/linux/of_gpio.h index f9737dea9d1f..16967390a3fe 100644 --- a/include/linux/of_gpio.h +++ b/include/linux/of_gpio.h @@ -61,10 +61,6 @@ static inline int of_mm_gpiochip_add(struct device_node *np, } extern void of_mm_gpiochip_remove(struct of_mm_gpio_chip *mm_gc); -extern int of_gpio_simple_xlate(struct gpio_chip *gc, - const struct of_phandle_args *gpiospec, - u32 *flags); - #else /* CONFIG_OF_GPIO */ /* Drivers may not strictly depend on the GPIO support, so let them link. */ @@ -77,13 +73,6 @@ static inline int of_get_named_gpio_flags(struct device_node *np, return -ENOSYS; } -static inline int of_gpio_simple_xlate(struct gpio_chip *gc, - const struct of_phandle_args *gpiospec, - u32 *flags) -{ - return -ENOSYS; -} - #endif /* CONFIG_OF_GPIO */ /** diff --git a/include/linux/olpc-ec.h b/include/linux/olpc-ec.h index 79bdc6328c52..c4602364e909 100644 --- a/include/linux/olpc-ec.h +++ b/include/linux/olpc-ec.h @@ -2,6 +2,8 @@ #ifndef _LINUX_OLPC_EC_H #define _LINUX_OLPC_EC_H +#include <linux/bits.h> + /* XO-1 EC commands */ #define EC_FIRMWARE_REV 0x08 #define EC_WRITE_SCI_MASK 0x1b @@ -16,28 +18,57 @@ #define EC_SCI_QUERY 0x84 #define EC_EXT_SCI_QUERY 0x85 +/* SCI source values */ +#define EC_SCI_SRC_GAME BIT(0) +#define EC_SCI_SRC_BATTERY BIT(1) +#define EC_SCI_SRC_BATSOC BIT(2) +#define EC_SCI_SRC_BATERR BIT(3) +#define EC_SCI_SRC_EBOOK BIT(4) /* XO-1 only */ +#define EC_SCI_SRC_WLAN BIT(5) /* XO-1 only */ +#define EC_SCI_SRC_ACPWR BIT(6) +#define EC_SCI_SRC_BATCRIT BIT(7) +#define EC_SCI_SRC_GPWAKE BIT(8) /* XO-1.5 only */ +#define EC_SCI_SRC_ALL GENMASK(8, 0) + struct platform_device; struct olpc_ec_driver { - int (*probe)(struct platform_device *); int (*suspend)(struct platform_device *); int (*resume)(struct platform_device *); int (*ec_cmd)(u8, u8 *, size_t, u8 *, size_t, void *); + + bool wakeup_available; }; -#ifdef CONFIG_OLPC +#ifdef CONFIG_OLPC_EC extern void olpc_ec_driver_register(struct olpc_ec_driver *drv, void *arg); extern int olpc_ec_cmd(u8 cmd, u8 *inbuf, size_t inlen, u8 *outbuf, size_t outlen); +extern void olpc_ec_wakeup_set(u16 value); +extern void olpc_ec_wakeup_clear(u16 value); + +extern int olpc_ec_mask_write(u16 bits); +extern int olpc_ec_sci_query(u16 *sci_value); + +extern bool olpc_ec_wakeup_available(void); + #else static inline int olpc_ec_cmd(u8 cmd, u8 *inbuf, size_t inlen, u8 *outbuf, size_t outlen) { return -ENODEV; } -#endif /* CONFIG_OLPC */ +static inline void olpc_ec_wakeup_set(u16 value) { } +static inline void olpc_ec_wakeup_clear(u16 value) { } + +static inline bool olpc_ec_wakeup_available(void) +{ + return false; +} + +#endif /* CONFIG_OLPC_EC */ #endif /* _LINUX_OLPC_EC_H */ diff --git a/include/linux/omap-dma.h b/include/linux/omap-dma.h index 840ce551e773..ba3cfbb52312 100644 --- a/include/linux/omap-dma.h +++ b/include/linux/omap-dma.h @@ -1,8 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 */ #ifndef __LINUX_OMAP_DMA_H #define __LINUX_OMAP_DMA_H -#include <linux/omap-dmaengine.h> - /* * Legacy OMAP DMA handling defines and functions * diff --git a/include/linux/omap-dmaengine.h b/include/linux/omap-dmaengine.h deleted file mode 100644 index b6e42f933c40..000000000000 --- a/include/linux/omap-dmaengine.h +++ /dev/null @@ -1,18 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * OMAP DMA Engine support - */ -#ifndef __LINUX_OMAP_DMAENGINE_H -#define __LINUX_OMAP_DMAENGINE_H - -struct dma_chan; - -#if defined(CONFIG_DMA_OMAP) || (defined(CONFIG_DMA_OMAP_MODULE) && defined(MODULE)) -bool omap_dma_filter_fn(struct dma_chan *, void *); -#else -static inline bool omap_dma_filter_fn(struct dma_chan *c, void *d) -{ - return false; -} -#endif -#endif /* __LINUX_OMAP_DMAENGINE_H */ diff --git a/include/linux/omap-iommu.h b/include/linux/omap-iommu.h index 153bf25b4df3..2c32ca09df02 100644 --- a/include/linux/omap-iommu.h +++ b/include/linux/omap-iommu.h @@ -10,12 +10,27 @@ #ifndef _OMAP_IOMMU_H_ #define _OMAP_IOMMU_H_ +struct iommu_domain; + #ifdef CONFIG_OMAP_IOMMU extern void omap_iommu_save_ctx(struct device *dev); extern void omap_iommu_restore_ctx(struct device *dev); + +int omap_iommu_domain_deactivate(struct iommu_domain *domain); +int omap_iommu_domain_activate(struct iommu_domain *domain); #else static inline void omap_iommu_save_ctx(struct device *dev) {} static inline void omap_iommu_restore_ctx(struct device *dev) {} + +static inline int omap_iommu_domain_deactivate(struct iommu_domain *domain) +{ + return -ENODEV; +} + +static inline int omap_iommu_domain_activate(struct iommu_domain *domain) +{ + return -ENODEV; +} #endif #endif diff --git a/include/linux/omap-mailbox.h b/include/linux/omap-mailbox.h index 6dbcd2da0332..8aa984ec1f38 100644 --- a/include/linux/omap-mailbox.h +++ b/include/linux/omap-mailbox.h @@ -6,7 +6,9 @@ #ifndef OMAP_MAILBOX_H #define OMAP_MAILBOX_H -typedef u32 mbox_msg_t; +typedef uintptr_t mbox_msg_t; + +#define omap_mbox_message(data) (u32)(mbox_msg_t)(data) typedef int __bitwise omap_mbox_irq_t; #define IRQ_TX ((__force omap_mbox_irq_t) 1) diff --git a/include/linux/oom.h b/include/linux/oom.h index d07992009265..c696c265f019 100644 --- a/include/linux/oom.h +++ b/include/linux/oom.h @@ -108,7 +108,6 @@ static inline vm_fault_t check_stable_address_space(struct mm_struct *mm) bool __oom_reap_task_mm(struct mm_struct *mm); extern unsigned long oom_badness(struct task_struct *p, - struct mem_cgroup *memcg, const nodemask_t *nodemask, unsigned long totalpages); extern bool out_of_memory(struct oom_control *oc); diff --git a/include/linux/oxu210hp.h b/include/linux/oxu210hp.h deleted file mode 100644 index 94cd25165c08..000000000000 --- a/include/linux/oxu210hp.h +++ /dev/null @@ -1,8 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* platform data for the OXU210HP HCD */ - -struct oxu210hp_platform_data { - unsigned int bus16:1; - unsigned int use_hcd_otg:1; - unsigned int use_hcd_sph:1; -}; diff --git a/include/linux/padata.h b/include/linux/padata.h index 56f09e36f770..23717eeaad23 100644 --- a/include/linux/padata.h +++ b/include/linux/padata.h @@ -12,7 +12,6 @@ #include <linux/workqueue.h> #include <linux/spinlock.h> #include <linux/list.h> -#include <linux/timer.h> #include <linux/notifier.h> #include <linux/kobject.h> @@ -36,6 +35,7 @@ struct padata_priv { struct parallel_data *pd; int cb_cpu; int cpu; + unsigned int seq_nr; int info; void (*parallel)(struct padata_priv *padata); void (*serial)(struct padata_priv *padata); @@ -73,20 +73,14 @@ struct padata_serial_queue { * @serial: List to wait for serialization after reordering. * @pwork: work struct for parallelization. * @swork: work struct for serialization. - * @pd: Backpointer to the internal control structure. * @work: work struct for parallelization. - * @reorder_work: work struct for reordering. * @num_obj: Number of objects that are processed by this cpu. - * @cpu_index: Index of the cpu. */ struct padata_parallel_queue { struct padata_list parallel; struct padata_list reorder; - struct parallel_data *pd; struct work_struct work; - struct work_struct reorder_work; atomic_t num_obj; - int cpu_index; }; /** @@ -110,10 +104,11 @@ struct padata_cpumask { * @reorder_objects: Number of objects waiting in the reorder queues. * @refcnt: Number of objects holding a reference on this parallel_data. * @max_seq_nr: Maximal used sequence number. + * @processed: Number of already processed objects. + * @cpu: Next CPU to be processed. * @cpumask: The cpumasks in use for parallel and serial workers. + * @reorder_work: work struct for reordering. * @lock: Reorder lock. - * @processed: Number of already processed objects. - * @timer: Reorder timer. */ struct parallel_data { struct padata_instance *pinst; @@ -122,17 +117,19 @@ struct parallel_data { atomic_t reorder_objects; atomic_t refcnt; atomic_t seq_nr; + unsigned int processed; + int cpu; struct padata_cpumask cpumask; + struct work_struct reorder_work; spinlock_t lock ____cacheline_aligned; - unsigned int processed; - struct timer_list timer; }; /** * struct padata_instance - The overall control structure. * * @cpu_notifier: cpu hotplug notifier. - * @wq: The workqueue in use. + * @parallel_wq: The workqueue used for parallel work. + * @serial_wq: The workqueue used for serial work. * @pd: The internal control structure. * @cpumask: User supplied cpumasks for parallel and serial works. * @cpumask_change_notifier: Notifiers chain for user-defined notify @@ -144,7 +141,8 @@ struct parallel_data { */ struct padata_instance { struct hlist_node node; - struct workqueue_struct *wq; + struct workqueue_struct *parallel_wq; + struct workqueue_struct *serial_wq; struct parallel_data *pd; struct padata_cpumask cpumask; struct blocking_notifier_head cpumask_change_notifier; @@ -156,11 +154,10 @@ struct padata_instance { #define PADATA_INVALID 4 }; -extern struct padata_instance *padata_alloc_possible( - struct workqueue_struct *wq); +extern struct padata_instance *padata_alloc_possible(const char *name); extern void padata_free(struct padata_instance *pinst); extern int padata_do_parallel(struct padata_instance *pinst, - struct padata_priv *padata, int cb_cpu); + struct padata_priv *padata, int *cb_cpu); extern void padata_do_serial(struct padata_priv *padata); extern int padata_set_cpumask(struct padata_instance *pinst, int cpumask_type, cpumask_var_t cpumask); diff --git a/include/linux/page-flags-layout.h b/include/linux/page-flags-layout.h index 1dda31825ec4..71283739ffd2 100644 --- a/include/linux/page-flags-layout.h +++ b/include/linux/page-flags-layout.h @@ -32,6 +32,7 @@ #endif /* CONFIG_SPARSEMEM */ +#ifndef BUILD_VDSO32_64 /* * page->flags layout: * @@ -76,20 +77,22 @@ #define LAST_CPUPID_SHIFT 0 #endif -#if SECTIONS_WIDTH+ZONES_WIDTH+NODES_SHIFT+LAST_CPUPID_SHIFT <= BITS_PER_LONG - NR_PAGEFLAGS +#ifdef CONFIG_KASAN_SW_TAGS +#define KASAN_TAG_WIDTH 8 +#else +#define KASAN_TAG_WIDTH 0 +#endif + +#if SECTIONS_WIDTH+ZONES_WIDTH+NODES_SHIFT+LAST_CPUPID_SHIFT+KASAN_TAG_WIDTH \ + <= BITS_PER_LONG - NR_PAGEFLAGS #define LAST_CPUPID_WIDTH LAST_CPUPID_SHIFT #else #define LAST_CPUPID_WIDTH 0 #endif -#ifdef CONFIG_KASAN_SW_TAGS -#define KASAN_TAG_WIDTH 8 #if SECTIONS_WIDTH+NODES_WIDTH+ZONES_WIDTH+LAST_CPUPID_WIDTH+KASAN_TAG_WIDTH \ > BITS_PER_LONG - NR_PAGEFLAGS -#error "KASAN: not enough bits in page flags for tag" -#endif -#else -#define KASAN_TAG_WIDTH 0 +#error "Not enough bits in page flags" #endif /* @@ -104,4 +107,5 @@ #define LAST_CPUPID_NOT_IN_PAGE_FLAGS #endif +#endif #endif /* _LINUX_PAGE_FLAGS_LAYOUT */ diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h index 9f8712a4b1a5..f91cb8898ff0 100644 --- a/include/linux/page-flags.h +++ b/include/linux/page-flags.h @@ -152,6 +152,8 @@ enum pageflags { PG_savepinned = PG_dirty, /* Has a grant mapping of another (foreign) domain's page. */ PG_foreign = PG_owner_priv_1, + /* Remapped by swiotlb-xen. */ + PG_xen_remapped = PG_owner_priv_1, /* SLOB */ PG_slob_free = PG_private, @@ -329,6 +331,8 @@ PAGEFLAG(Pinned, pinned, PF_NO_COMPOUND) TESTSCFLAG(Pinned, pinned, PF_NO_COMPOUND) PAGEFLAG(SavePinned, savepinned, PF_NO_COMPOUND); PAGEFLAG(Foreign, foreign, PF_NO_COMPOUND); +PAGEFLAG(XenRemapped, xen_remapped, PF_NO_COMPOUND) + TESTCLEARFLAG(XenRemapped, xen_remapped, PF_NO_COMPOUND) PAGEFLAG(Reserved, reserved, PF_NO_COMPOUND) __CLEARPAGEFLAG(Reserved, reserved, PF_NO_COMPOUND) @@ -703,6 +707,7 @@ PAGEFLAG_FALSE(DoubleMap) #define PG_offline 0x00000100 #define PG_kmemcg 0x00000200 #define PG_table 0x00000400 +#define PG_guard 0x00000800 #define PageType(page, flag) \ ((page->page_type & (PAGE_TYPE_BASE | flag)) == PAGE_TYPE_BASE) @@ -754,6 +759,11 @@ PAGE_TYPE_OPS(Kmemcg, kmemcg) */ PAGE_TYPE_OPS(Table, table) +/* + * Marks guardpages used with debug_pagealloc. + */ +PAGE_TYPE_OPS(Guard, guard) + extern bool is_free_buddy_page(struct page *page); __PAGEFLAG(Isolated, isolated, PF_ANY); diff --git a/include/linux/page-isolation.h b/include/linux/page-isolation.h index 280ae96dc4c3..1099c2fee20f 100644 --- a/include/linux/page-isolation.h +++ b/include/linux/page-isolation.h @@ -50,7 +50,7 @@ start_isolate_page_range(unsigned long start_pfn, unsigned long end_pfn, * Changes MIGRATE_ISOLATE to MIGRATE_MOVABLE. * target range is [start_pfn, end_pfn) */ -int +void undo_isolate_page_range(unsigned long start_pfn, unsigned long end_pfn, unsigned migratetype); diff --git a/include/linux/page_ext.h b/include/linux/page_ext.h index f84f167ec04c..682fd465df06 100644 --- a/include/linux/page_ext.h +++ b/include/linux/page_ext.h @@ -17,8 +17,8 @@ struct page_ext_operations { #ifdef CONFIG_PAGE_EXTENSION enum page_ext_flags { - PAGE_EXT_DEBUG_GUARD, PAGE_EXT_OWNER, + PAGE_EXT_OWNER_ACTIVE, #if defined(CONFIG_IDLE_PAGE_TRACKING) && !defined(CONFIG_64BIT) PAGE_EXT_YOUNG, PAGE_EXT_IDLE, diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h index fe0b29bf2df7..37a4d9e32cd3 100644 --- a/include/linux/pagemap.h +++ b/include/linux/pagemap.h @@ -333,6 +333,16 @@ static inline struct page *grab_cache_page_nowait(struct address_space *mapping, mapping_gfp_mask(mapping)); } +static inline struct page *find_subpage(struct page *page, pgoff_t offset) +{ + if (PageHuge(page)) + return page; + + VM_BUG_ON_PAGE(PageTail(page), page); + + return page + (offset & (compound_nr(page) - 1)); +} + struct page *find_get_entry(struct address_space *mapping, pgoff_t offset); struct page *find_lock_entry(struct address_space *mapping, pgoff_t offset); unsigned find_get_entries(struct address_space *mapping, pgoff_t start, @@ -383,8 +393,7 @@ extern int read_cache_pages(struct address_space *mapping, static inline struct page *read_mapping_page(struct address_space *mapping, pgoff_t index, void *data) { - filler_t *filler = (filler_t *)mapping->a_ops->readpage; - return read_cache_page(mapping, index, filler, data); + return read_cache_page(mapping, index, NULL, data); } /* @@ -452,6 +461,9 @@ extern int __lock_page_or_retry(struct page *page, struct mm_struct *mm, unsigned int flags); extern void unlock_page(struct page *page); +/* + * Return true if the page was successfully locked + */ static inline int trylock_page(struct page *page) { page = compound_head(page); diff --git a/include/linux/pagewalk.h b/include/linux/pagewalk.h new file mode 100644 index 000000000000..bddd9759bab9 --- /dev/null +++ b/include/linux/pagewalk.h @@ -0,0 +1,66 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _LINUX_PAGEWALK_H +#define _LINUX_PAGEWALK_H + +#include <linux/mm.h> + +struct mm_walk; + +/** + * mm_walk_ops - callbacks for walk_page_range + * @pud_entry: if set, called for each non-empty PUD (2nd-level) entry + * this handler should only handle pud_trans_huge() puds. + * the pmd_entry or pte_entry callbacks will be used for + * regular PUDs. + * @pmd_entry: if set, called for each non-empty PMD (3rd-level) entry + * this handler is required to be able to handle + * pmd_trans_huge() pmds. They may simply choose to + * split_huge_page() instead of handling it explicitly. + * @pte_entry: if set, called for each non-empty PTE (4th-level) entry + * @pte_hole: if set, called for each hole at all levels + * @hugetlb_entry: if set, called for each hugetlb entry + * @test_walk: caller specific callback function to determine whether + * we walk over the current vma or not. Returning 0 means + * "do page table walk over the current vma", returning + * a negative value means "abort current page table walk + * right now" and returning 1 means "skip the current vma" + */ +struct mm_walk_ops { + int (*pud_entry)(pud_t *pud, unsigned long addr, + unsigned long next, struct mm_walk *walk); + int (*pmd_entry)(pmd_t *pmd, unsigned long addr, + unsigned long next, struct mm_walk *walk); + int (*pte_entry)(pte_t *pte, unsigned long addr, + unsigned long next, struct mm_walk *walk); + int (*pte_hole)(unsigned long addr, unsigned long next, + struct mm_walk *walk); + int (*hugetlb_entry)(pte_t *pte, unsigned long hmask, + unsigned long addr, unsigned long next, + struct mm_walk *walk); + int (*test_walk)(unsigned long addr, unsigned long next, + struct mm_walk *walk); +}; + +/** + * mm_walk - walk_page_range data + * @ops: operation to call during the walk + * @mm: mm_struct representing the target process of page table walk + * @vma: vma currently walked (NULL if walking outside vmas) + * @private: private data for callbacks' usage + * + * (see the comment on walk_page_range() for more details) + */ +struct mm_walk { + const struct mm_walk_ops *ops; + struct mm_struct *mm; + struct vm_area_struct *vma; + void *private; +}; + +int walk_page_range(struct mm_struct *mm, unsigned long start, + unsigned long end, const struct mm_walk_ops *ops, + void *private); +int walk_page_vma(struct vm_area_struct *vma, const struct mm_walk_ops *ops, + void *private); + +#endif /* _LINUX_PAGEWALK_H */ diff --git a/include/linux/pci-acpi.h b/include/linux/pci-acpi.h index 8082b612f561..62b7fdcc661c 100644 --- a/include/linux/pci-acpi.h +++ b/include/linux/pci-acpi.h @@ -107,9 +107,10 @@ static inline void acpiphp_check_host_bridge(struct acpi_device *adev) { } #endif extern const guid_t pci_acpi_dsm_guid; -#define DEVICE_LABEL_DSM 0x07 -#define RESET_DELAY_DSM 0x08 -#define FUNCTION_DELAY_DSM 0x09 +#define IGNORE_PCI_BOOT_CONFIG_DSM 0x05 +#define DEVICE_LABEL_DSM 0x07 +#define RESET_DELAY_DSM 0x08 +#define FUNCTION_DELAY_DSM 0x09 #else /* CONFIG_ACPI */ static inline void acpi_pci_add_bus(struct pci_bus *bus) { } diff --git a/include/linux/pci-aspm.h b/include/linux/pci-aspm.h deleted file mode 100644 index df28af5cef21..000000000000 --- a/include/linux/pci-aspm.h +++ /dev/null @@ -1,35 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * aspm.h - * - * PCI Express ASPM defines and function prototypes - * - * Copyright (C) 2007 Intel Corp. - * Zhang Yanmin (yanmin.zhang@intel.com) - * Shaohua Li (shaohua.li@intel.com) - * - * For more information, please consult the following manuals (look at - * http://www.pcisig.com/ for how to get them): - * - * PCI Express Specification - */ - -#ifndef LINUX_ASPM_H -#define LINUX_ASPM_H - -#include <linux/pci.h> - -#define PCIE_LINK_STATE_L0S 1 -#define PCIE_LINK_STATE_L1 2 -#define PCIE_LINK_STATE_CLKPM 4 - -#ifdef CONFIG_PCIEASPM -void pci_disable_link_state(struct pci_dev *pdev, int state); -void pci_disable_link_state_locked(struct pci_dev *pdev, int state); -void pcie_no_aspm(void); -#else -static inline void pci_disable_link_state(struct pci_dev *pdev, int state) { } -static inline void pcie_no_aspm(void) { } -#endif - -#endif /* LINUX_ASPM_H */ diff --git a/include/linux/pci-p2pdma.h b/include/linux/pci-p2pdma.h index bca9bc3e5be7..8318a97c9c61 100644 --- a/include/linux/pci-p2pdma.h +++ b/include/linux/pci-p2pdma.h @@ -30,8 +30,10 @@ struct scatterlist *pci_p2pmem_alloc_sgl(struct pci_dev *pdev, unsigned int *nents, u32 length); void pci_p2pmem_free_sgl(struct pci_dev *pdev, struct scatterlist *sgl); void pci_p2pmem_publish(struct pci_dev *pdev, bool publish); -int pci_p2pdma_map_sg(struct device *dev, struct scatterlist *sg, int nents, - enum dma_data_direction dir); +int pci_p2pdma_map_sg_attrs(struct device *dev, struct scatterlist *sg, + int nents, enum dma_data_direction dir, unsigned long attrs); +void pci_p2pdma_unmap_sg_attrs(struct device *dev, struct scatterlist *sg, + int nents, enum dma_data_direction dir, unsigned long attrs); int pci_p2pdma_enable_store(const char *page, struct pci_dev **p2p_dev, bool *use_p2pdma); ssize_t pci_p2pdma_enable_show(char *page, struct pci_dev *p2p_dev, @@ -81,11 +83,17 @@ static inline void pci_p2pmem_free_sgl(struct pci_dev *pdev, static inline void pci_p2pmem_publish(struct pci_dev *pdev, bool publish) { } -static inline int pci_p2pdma_map_sg(struct device *dev, - struct scatterlist *sg, int nents, enum dma_data_direction dir) +static inline int pci_p2pdma_map_sg_attrs(struct device *dev, + struct scatterlist *sg, int nents, enum dma_data_direction dir, + unsigned long attrs) { return 0; } +static inline void pci_p2pdma_unmap_sg_attrs(struct device *dev, + struct scatterlist *sg, int nents, enum dma_data_direction dir, + unsigned long attrs) +{ +} static inline int pci_p2pdma_enable_store(const char *page, struct pci_dev **p2p_dev, bool *use_p2pdma) { @@ -111,4 +119,16 @@ static inline struct pci_dev *pci_p2pmem_find(struct device *client) return pci_p2pmem_find_many(&client, 1); } +static inline int pci_p2pdma_map_sg(struct device *dev, struct scatterlist *sg, + int nents, enum dma_data_direction dir) +{ + return pci_p2pdma_map_sg_attrs(dev, sg, nents, dir, 0); +} + +static inline void pci_p2pdma_unmap_sg(struct device *dev, + struct scatterlist *sg, int nents, enum dma_data_direction dir) +{ + pci_p2pdma_unmap_sg_attrs(dev, sg, nents, dir, 0); +} + #endif /* _LINUX_PCI_P2P_H */ diff --git a/include/linux/pci.h b/include/linux/pci.h index dd436da7eccc..f9088c89a534 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -6,12 +6,18 @@ * Copyright 1994, Drew Eckhardt * Copyright 1997--1999 Martin Mares <mj@ucw.cz> * + * PCI Express ASPM defines and function prototypes + * Copyright (c) 2007 Intel Corp. + * Zhang Yanmin (yanmin.zhang@intel.com) + * Shaohua Li (shaohua.li@intel.com) + * * For more information, please consult the following manuals (look at * http://www.pcisig.com/ for how to get them): * * PCI BIOS Specification * PCI Local Bus Specification * PCI to PCI Bridge Specification + * PCI Express Specification * PCI System Design Guide */ #ifndef LINUX_PCI_H @@ -145,12 +151,9 @@ static inline const char *pci_power_name(pci_power_t state) return pci_power_names[1 + (__force int) state]; } -#define PCI_PM_D2_DELAY 200 -#define PCI_PM_D3_WAIT 10 -#define PCI_PM_D3COLD_WAIT 100 -#define PCI_PM_BUS_WAIT 50 - /** + * typedef pci_channel_state_t + * * The pci_channel state describes connectivity between the CPU and * the PCI device. If some PCI bus between here and the PCI device * has crashed or locked up, this info is reflected here. @@ -258,6 +261,7 @@ enum pci_bus_speed { PCIE_SPEED_5_0GT = 0x15, PCIE_SPEED_8_0GT = 0x16, PCIE_SPEED_16_0GT = 0x17, + PCIE_SPEED_32_0GT = 0x18, PCI_SPEED_UNKNOWN = 0xff, }; @@ -383,7 +387,7 @@ struct pci_dev { unsigned int is_busmaster:1; /* Is busmaster */ unsigned int no_msi:1; /* May not use MSI */ - unsigned int no_64bit_msi:1; /* May only use 32-bit MSIs */ + unsigned int no_64bit_msi:1; /* May only use 32-bit MSIs */ unsigned int block_cfg_access:1; /* Config space access blocked */ unsigned int broken_parity_status:1; /* Generates false positive parity */ unsigned int irq_reroute_variant:2; /* Needs IRQ rerouting variant */ @@ -415,7 +419,6 @@ struct pci_dev { unsigned int broken_intx_masking:1; /* INTx masking can't be used */ unsigned int io_window_1k:1; /* Intel bridge 1K I/O windows */ unsigned int irq_managed:1; - unsigned int has_secondary_link:1; unsigned int non_compliant_bars:1; /* Broken BARs; ignore them */ unsigned int is_probed:1; /* Device probing in progress */ unsigned int link_active_reporting:1;/* Device capable of reporting link active */ @@ -506,6 +509,8 @@ struct pci_host_bridge { unsigned int native_shpc_hotplug:1; /* OS may use SHPC hotplug */ unsigned int native_pme:1; /* OS may use PCIe PME */ unsigned int native_ltr:1; /* OS may use PCIe LTR */ + unsigned int preserve_config:1; /* Preserve FW resource setup */ + /* Resource alignment requirements */ resource_size_t (*align_resource)(struct pci_dev *dev, const struct resource *res, @@ -644,9 +649,6 @@ static inline struct pci_dev *pci_upstream_bridge(struct pci_dev *dev) return dev->bus->self; } -struct device *pci_get_host_bridge_device(struct pci_dev *dev); -void pci_put_host_bridge_device(struct device *dev); - #ifdef CONFIG_PCI_MSI static inline bool pci_dev_msi_enabled(struct pci_dev *pci_dev) { @@ -776,6 +778,50 @@ struct pci_error_handlers { struct module; + +/** + * struct pci_driver - PCI driver structure + * @node: List of driver structures. + * @name: Driver name. + * @id_table: Pointer to table of device IDs the driver is + * interested in. Most drivers should export this + * table using MODULE_DEVICE_TABLE(pci,...). + * @probe: This probing function gets called (during execution + * of pci_register_driver() for already existing + * devices or later if a new device gets inserted) for + * all PCI devices which match the ID table and are not + * "owned" by the other drivers yet. This function gets + * passed a "struct pci_dev \*" for each device whose + * entry in the ID table matches the device. The probe + * function returns zero when the driver chooses to + * take "ownership" of the device or an error code + * (negative number) otherwise. + * The probe function always gets called from process + * context, so it can sleep. + * @remove: The remove() function gets called whenever a device + * being handled by this driver is removed (either during + * deregistration of the driver or when it's manually + * pulled out of a hot-pluggable slot). + * The remove function always gets called from process + * context, so it can sleep. + * @suspend: Put device into low power state. + * @suspend_late: Put device into low power state. + * @resume_early: Wake device from low power state. + * @resume: Wake device from low power state. + * (Please see Documentation/power/pci.rst for descriptions + * of PCI Power Management and the related functions.) + * @shutdown: Hook into reboot_notifier_list (kernel/sys.c). + * Intended to stop any idling DMA operations. + * Useful for enabling wake-on-lan (NIC) or changing + * the power state of a device before reboot. + * e.g. drivers/net/e100.c. + * @sriov_configure: Optional driver callback to allow configuration of + * number of VFs to enable via sysfs "sriov_numvfs" file. + * @err_handler: See Documentation/PCI/pci-error-recovery.rst + * @groups: Sysfs attribute groups. + * @driver: Driver model structure. + * @dynids: List of dynamically added device IDs. + */ struct pci_driver { struct list_head node; const char *name; @@ -876,6 +922,11 @@ enum { PCI_SCAN_ALL_PCIE_DEVS = 0x00000040, /* Scan all, not just dev 0 */ }; +#define PCI_IRQ_LEGACY (1 << 0) /* Allow legacy interrupts */ +#define PCI_IRQ_MSI (1 << 1) /* Allow MSI interrupts */ +#define PCI_IRQ_MSIX (1 << 2) /* Allow MSI-X interrupts */ +#define PCI_IRQ_AFFINITY (1 << 3) /* Auto-assign affinity */ + /* These external functions are only available when PCI support is enabled */ #ifdef CONFIG_PCI @@ -920,7 +971,7 @@ resource_size_t pcibios_align_resource(void *, const struct resource *, resource_size_t, resource_size_t); -/* Weak but can be overriden by arch */ +/* Weak but can be overridden by arch */ void pci_fixup_cardbus(struct pci_bus *); /* Generic PCI functions used internally */ @@ -946,7 +997,6 @@ struct pci_bus *pci_scan_root_bus(struct device *parent, int bus, int pci_scan_root_bus_bridge(struct pci_host_bridge *bridge); struct pci_bus *pci_add_new_bus(struct pci_bus *parent, struct pci_dev *dev, int busnr); -void pcie_update_link_speed(struct pci_bus *bus, u16 link_status); struct pci_slot *pci_create_slot(struct pci_bus *parent, int slot_nr, const char *name, struct hotplug_slot *hotplug); @@ -1192,19 +1242,12 @@ int pci_wake_from_d3(struct pci_dev *dev, bool enable); int pci_prepare_to_sleep(struct pci_dev *dev); int pci_back_from_sleep(struct pci_dev *dev); bool pci_dev_run_wake(struct pci_dev *dev); -bool pci_check_pme_status(struct pci_dev *dev); -void pci_pme_wakeup_bus(struct pci_bus *bus); void pci_d3cold_enable(struct pci_dev *dev); void pci_d3cold_disable(struct pci_dev *dev); bool pcie_relaxed_ordering_enabled(struct pci_dev *dev); void pci_wakeup_bus(struct pci_bus *bus); void pci_bus_set_current_state(struct pci_bus *bus, pci_power_t state); -/* PCI Virtual Channel */ -int pci_save_vc_state(struct pci_dev *dev); -void pci_restore_vc_state(struct pci_dev *dev); -void pci_allocate_vc_save_buffers(struct pci_dev *dev); - /* For use by arch with custom probe code */ void set_pcie_port_type(struct pci_dev *pdev); void set_pcie_hotplug_bridge(struct pci_dev *pdev); @@ -1248,8 +1291,6 @@ int pci_request_selected_regions_exclusive(struct pci_dev *, int, const char *); void pci_release_selected_regions(struct pci_dev *, int); /* drivers/pci/bus.c */ -struct pci_bus *pci_bus_get(struct pci_bus *bus); -void pci_bus_put(struct pci_bus *bus); void pci_add_resource(struct list_head *resources, struct resource *res); void pci_add_resource_offset(struct list_head *resources, struct resource *res, resource_size_t offset); @@ -1359,10 +1400,14 @@ resource_size_t pcibios_window_alignment(struct pci_bus *bus, int pci_set_vga_state(struct pci_dev *pdev, bool decode, unsigned int command_bits, u32 flags); -#define PCI_IRQ_LEGACY (1 << 0) /* Allow legacy interrupts */ -#define PCI_IRQ_MSI (1 << 1) /* Allow MSI interrupts */ -#define PCI_IRQ_MSIX (1 << 2) /* Allow MSI-X interrupts */ -#define PCI_IRQ_AFFINITY (1 << 3) /* Auto-assign affinity */ +/* + * Virtual interrupts allow for more interrupts to be allocated + * than the device has interrupts for. These are not programmed + * into the device's MSI-X table and must be handled by some + * other driver means. + */ +#define PCI_IRQ_VIRTUAL (1 << 4) + #define PCI_IRQ_ALL_TYPES \ (PCI_IRQ_LEGACY | PCI_IRQ_MSI | PCI_IRQ_MSIX) @@ -1459,14 +1504,6 @@ static inline int pci_irq_get_node(struct pci_dev *pdev, int vec) } #endif -static inline int -pci_alloc_irq_vectors(struct pci_dev *dev, unsigned int min_vecs, - unsigned int max_vecs, unsigned int flags) -{ - return pci_alloc_irq_vectors_affinity(dev, min_vecs, max_vecs, flags, - NULL); -} - /** * pci_irqd_intx_xlate() - Translate PCI INTx value to an IRQ domain hwirq * @d: the INTx IRQ domain @@ -1507,10 +1544,24 @@ extern bool pcie_ports_native; #define pcie_ports_native false #endif +#define PCIE_LINK_STATE_L0S 1 +#define PCIE_LINK_STATE_L1 2 +#define PCIE_LINK_STATE_CLKPM 4 + #ifdef CONFIG_PCIEASPM +int pci_disable_link_state(struct pci_dev *pdev, int state); +int pci_disable_link_state_locked(struct pci_dev *pdev, int state); +void pcie_no_aspm(void); bool pcie_aspm_support_enabled(void); +bool pcie_aspm_enabled(struct pci_dev *pdev); #else +static inline int pci_disable_link_state(struct pci_dev *pdev, int state) +{ return 0; } +static inline int pci_disable_link_state_locked(struct pci_dev *pdev, int state) +{ return 0; } +static inline void pcie_no_aspm(void) { } static inline bool pcie_aspm_support_enabled(void) { return false; } +static inline bool pcie_aspm_enabled(struct pci_dev *pdev) { return false; } #endif #ifdef CONFIG_PCIEAER @@ -1519,23 +1570,8 @@ bool pci_aer_available(void); static inline bool pci_aer_available(void) { return false; } #endif -#ifdef CONFIG_PCIE_ECRC -void pcie_set_ecrc_checking(struct pci_dev *dev); -void pcie_ecrc_get_policy(char *str); -#else -static inline void pcie_set_ecrc_checking(struct pci_dev *dev) { } -static inline void pcie_ecrc_get_policy(char *str) { } -#endif - bool pci_ats_disabled(void); -#ifdef CONFIG_PCIE_PTM -int pci_enable_ptm(struct pci_dev *dev, u8 *granularity); -#else -static inline int pci_enable_ptm(struct pci_dev *dev, u8 *granularity) -{ return -EINVAL; } -#endif - void pci_cfg_access_lock(struct pci_dev *dev); bool pci_cfg_access_trylock(struct pci_dev *dev); void pci_cfg_access_unlock(struct pci_dev *dev); @@ -1689,11 +1725,6 @@ static inline void pci_release_regions(struct pci_dev *dev) { } static inline unsigned long pci_address_to_pio(phys_addr_t addr) { return -1; } -static inline void pci_block_cfg_access(struct pci_dev *dev) { } -static inline int pci_block_cfg_access_in_atomic(struct pci_dev *dev) -{ return 0; } -static inline void pci_unblock_cfg_access(struct pci_dev *dev) { } - static inline struct pci_bus *pci_find_next_bus(const struct pci_bus *from) { return NULL; } static inline struct pci_dev *pci_get_slot(struct pci_bus *bus, @@ -1722,17 +1753,36 @@ static inline const struct pci_device_id *pci_match_id(const struct pci_device_i struct pci_dev *dev) { return NULL; } static inline bool pci_ats_disabled(void) { return true; } + +static inline int pci_irq_vector(struct pci_dev *dev, unsigned int nr) +{ + return -EINVAL; +} + +static inline int +pci_alloc_irq_vectors_affinity(struct pci_dev *dev, unsigned int min_vecs, + unsigned int max_vecs, unsigned int flags, + struct irq_affinity *aff_desc) +{ + return -ENOSPC; +} #endif /* CONFIG_PCI */ +static inline int +pci_alloc_irq_vectors(struct pci_dev *dev, unsigned int min_vecs, + unsigned int max_vecs, unsigned int flags) +{ + return pci_alloc_irq_vectors_affinity(dev, min_vecs, max_vecs, flags, + NULL); +} + #ifdef CONFIG_PCI_ATS /* Address Translation Service */ -void pci_ats_init(struct pci_dev *dev); int pci_enable_ats(struct pci_dev *dev, int ps); void pci_disable_ats(struct pci_dev *dev); int pci_ats_queue_depth(struct pci_dev *dev); int pci_ats_page_aligned(struct pci_dev *dev); #else -static inline void pci_ats_init(struct pci_dev *d) { } static inline int pci_enable_ats(struct pci_dev *d, int ps) { return -ENODEV; } static inline void pci_disable_ats(struct pci_dev *d) { } static inline int pci_ats_queue_depth(struct pci_dev *d) { return -ENODEV; } @@ -1743,7 +1793,7 @@ static inline int pci_ats_page_aligned(struct pci_dev *dev) { return 0; } #include <asm/pci.h> -/* These two functions provide almost identical functionality. Depennding +/* These two functions provide almost identical functionality. Depending * on the architecture, one will be implemented as a wrapper around the * other (in drivers/pci/mmap.c). * @@ -1812,25 +1862,9 @@ static inline const char *pci_name(const struct pci_dev *pdev) return dev_name(&pdev->dev); } - -/* - * Some archs don't want to expose struct resource to userland as-is - * in sysfs and /proc - */ -#ifdef HAVE_ARCH_PCI_RESOURCE_TO_USER void pci_resource_to_user(const struct pci_dev *dev, int bar, const struct resource *rsrc, resource_size_t *start, resource_size_t *end); -#else -static inline void pci_resource_to_user(const struct pci_dev *dev, int bar, - const struct resource *rsrc, resource_size_t *start, - resource_size_t *end) -{ - *start = rsrc->start; - *end = rsrc->end; -} -#endif /* HAVE_ARCH_PCI_RESOURCE_TO_USER */ - /* * The world is not perfect and supplies us with broken PCI devices. @@ -1972,10 +2006,6 @@ extern unsigned long pci_cardbus_mem_size; extern u8 pci_dfl_cache_line_size; extern u8 pci_cache_line_size; -extern unsigned long pci_hotplug_io_size; -extern unsigned long pci_hotplug_mem_size; -extern unsigned long pci_hotplug_bus_size; - /* Architecture-specific versions may override these (weak) */ void pcibios_disable_device(struct pci_dev *dev); void pcibios_set_master(struct pci_dev *dev); @@ -2207,7 +2237,7 @@ static inline u8 pci_vpd_srdt_tag(const u8 *srdt) /** * pci_vpd_info_field_size - Extracts the information field length - * @lrdt: Pointer to the beginning of an information field header + * @info_field: Pointer to the beginning of an information field header * * Returns the extracted information field length. */ @@ -2245,10 +2275,6 @@ int pci_vpd_find_info_keyword(const u8 *buf, unsigned int off, #ifdef CONFIG_OF struct device_node; struct irq_domain; -void pci_set_of_node(struct pci_dev *dev); -void pci_release_of_node(struct pci_dev *dev); -void pci_set_bus_of_node(struct pci_bus *bus); -void pci_release_bus_of_node(struct pci_bus *bus); struct irq_domain *pci_host_bridge_of_msi_domain(struct pci_bus *bus); int pci_parse_request_of_pci_ranges(struct device *dev, struct list_head *resources, @@ -2258,10 +2284,6 @@ int pci_parse_request_of_pci_ranges(struct device *dev, struct device_node *pcibios_get_phb_of_node(struct pci_bus *bus); #else /* CONFIG_OF */ -static inline void pci_set_of_node(struct pci_dev *dev) { } -static inline void pci_release_of_node(struct pci_dev *dev) { } -static inline void pci_set_bus_of_node(struct pci_bus *bus) { } -static inline void pci_release_bus_of_node(struct pci_bus *bus) { } static inline struct irq_domain * pci_host_bridge_of_msi_domain(struct pci_bus *bus) { return NULL; } static inline int pci_parse_request_of_pci_ranges(struct device *dev, @@ -2375,4 +2397,7 @@ void pci_uevent_ers(struct pci_dev *pdev, enum pci_ers_result err_type); #define pci_notice_ratelimited(pdev, fmt, arg...) \ dev_notice_ratelimited(&(pdev)->dev, fmt, ##arg) +#define pci_info_ratelimited(pdev, fmt, arg...) \ + dev_info_ratelimited(&(pdev)->dev, fmt, ##arg) + #endif /* LINUX_PCI_H */ diff --git a/include/linux/pci_hotplug.h b/include/linux/pci_hotplug.h index f694eb2ca978..b482e42d7153 100644 --- a/include/linux/pci_hotplug.h +++ b/include/linux/pci_hotplug.h @@ -86,114 +86,14 @@ void pci_hp_deregister(struct hotplug_slot *slot); #define pci_hp_initialize(slot, bus, nr, name) \ __pci_hp_initialize(slot, bus, nr, name, THIS_MODULE, KBUILD_MODNAME) -/* PCI Setting Record (Type 0) */ -struct hpp_type0 { - u32 revision; - u8 cache_line_size; - u8 latency_timer; - u8 enable_serr; - u8 enable_perr; -}; - -/* PCI-X Setting Record (Type 1) */ -struct hpp_type1 { - u32 revision; - u8 max_mem_read; - u8 avg_max_split; - u16 tot_max_split; -}; - -/* PCI Express Setting Record (Type 2) */ -struct hpp_type2 { - u32 revision; - u32 unc_err_mask_and; - u32 unc_err_mask_or; - u32 unc_err_sever_and; - u32 unc_err_sever_or; - u32 cor_err_mask_and; - u32 cor_err_mask_or; - u32 adv_err_cap_and; - u32 adv_err_cap_or; - u16 pci_exp_devctl_and; - u16 pci_exp_devctl_or; - u16 pci_exp_lnkctl_and; - u16 pci_exp_lnkctl_or; - u32 sec_unc_err_sever_and; - u32 sec_unc_err_sever_or; - u32 sec_unc_err_mask_and; - u32 sec_unc_err_mask_or; -}; - -/* - * _HPX PCI Express Setting Record (Type 3) - */ -struct hpx_type3 { - u16 device_type; - u16 function_type; - u16 config_space_location; - u16 pci_exp_cap_id; - u16 pci_exp_cap_ver; - u16 pci_exp_vendor_id; - u16 dvsec_id; - u16 dvsec_rev; - u16 match_offset; - u32 match_mask_and; - u32 match_value; - u16 reg_offset; - u32 reg_mask_and; - u32 reg_mask_or; -}; - -struct hotplug_program_ops { - void (*program_type0)(struct pci_dev *dev, struct hpp_type0 *hpp); - void (*program_type1)(struct pci_dev *dev, struct hpp_type1 *hpp); - void (*program_type2)(struct pci_dev *dev, struct hpp_type2 *hpp); - void (*program_type3)(struct pci_dev *dev, struct hpx_type3 *hpp); -}; - -enum hpx_type3_dev_type { - HPX_TYPE_ENDPOINT = BIT(0), - HPX_TYPE_LEG_END = BIT(1), - HPX_TYPE_RC_END = BIT(2), - HPX_TYPE_RC_EC = BIT(3), - HPX_TYPE_ROOT_PORT = BIT(4), - HPX_TYPE_UPSTREAM = BIT(5), - HPX_TYPE_DOWNSTREAM = BIT(6), - HPX_TYPE_PCI_BRIDGE = BIT(7), - HPX_TYPE_PCIE_BRIDGE = BIT(8), -}; - -enum hpx_type3_fn_type { - HPX_FN_NORMAL = BIT(0), - HPX_FN_SRIOV_PHYS = BIT(1), - HPX_FN_SRIOV_VIRT = BIT(2), -}; - -enum hpx_type3_cfg_loc { - HPX_CFG_PCICFG = 0, - HPX_CFG_PCIE_CAP = 1, - HPX_CFG_PCIE_CAP_EXT = 2, - HPX_CFG_VEND_CAP = 3, - HPX_CFG_DVSEC = 4, - HPX_CFG_MAX, -}; - #ifdef CONFIG_ACPI #include <linux/acpi.h> -int pci_acpi_program_hp_params(struct pci_dev *dev, - const struct hotplug_program_ops *hp_ops); bool pciehp_is_native(struct pci_dev *bridge); int acpi_get_hp_hw_control_from_firmware(struct pci_dev *bridge); bool shpchp_is_native(struct pci_dev *bridge); int acpi_pci_check_ejectable(struct pci_bus *pbus, acpi_handle handle); int acpi_pci_detect_ejectable(acpi_handle handle); #else -static inline int pci_acpi_program_hp_params(struct pci_dev *dev, - const struct hotplug_program_ops *hp_ops) -{ - return -ENODEV; -} - static inline int acpi_get_hp_hw_control_from_firmware(struct pci_dev *bridge) { return 0; diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 70e86148cb1e..21a572469a4e 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -548,6 +548,7 @@ #define PCI_DEVICE_ID_AMD_17H_DF_F3 0x1463 #define PCI_DEVICE_ID_AMD_17H_M10H_DF_F3 0x15eb #define PCI_DEVICE_ID_AMD_17H_M30H_DF_F3 0x1493 +#define PCI_DEVICE_ID_AMD_17H_M70H_DF_F3 0x1443 #define PCI_DEVICE_ID_AMD_CNB17H_F3 0x1703 #define PCI_DEVICE_ID_AMD_LANCE 0x2000 #define PCI_DEVICE_ID_AMD_LANCE_HOME 0x2001 @@ -1070,7 +1071,6 @@ #define PCI_VENDOR_ID_SGI 0x10a9 #define PCI_DEVICE_ID_SGI_IOC3 0x0003 #define PCI_DEVICE_ID_SGI_LITHIUM 0x1002 -#define PCI_DEVICE_ID_SGI_IOC4 0x100a #define PCI_VENDOR_ID_WINBOND 0x10ad #define PCI_DEVICE_ID_WINBOND_82C105 0x0105 @@ -1112,7 +1112,7 @@ #define PCI_VENDOR_ID_AL 0x10b9 #define PCI_DEVICE_ID_AL_M1533 0x1533 -#define PCI_DEVICE_ID_AL_M1535 0x1535 +#define PCI_DEVICE_ID_AL_M1535 0x1535 #define PCI_DEVICE_ID_AL_M1541 0x1541 #define PCI_DEVICE_ID_AL_M1563 0x1563 #define PCI_DEVICE_ID_AL_M1621 0x1621 @@ -1336,6 +1336,7 @@ #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP78S_SMBUS 0x0752 #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP77_IDE 0x0759 #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP73_SMBUS 0x07D8 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_320M 0x08A0 #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP79_SMBUS 0x0AA2 #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP89_SATA 0x0D85 @@ -1752,7 +1753,7 @@ #define PCI_VENDOR_ID_STALLION 0x124d /* Allied Telesyn */ -#define PCI_VENDOR_ID_AT 0x1259 +#define PCI_VENDOR_ID_AT 0x1259 #define PCI_SUBDEVICE_ID_AT_2700FX 0x2701 #define PCI_SUBDEVICE_ID_AT_2701FX 0x2703 @@ -1950,6 +1951,8 @@ #define PCI_VENDOR_ID_DIGIGRAM 0x1369 #define PCI_SUBDEVICE_ID_DIGIGRAM_LX6464ES_SERIAL_SUBSYSTEM 0xc001 #define PCI_SUBDEVICE_ID_DIGIGRAM_LX6464ES_CAE_SERIAL_SUBSYSTEM 0xc002 +#define PCI_SUBDEVICE_ID_DIGIGRAM_LX6464ESE_SERIAL_SUBSYSTEM 0xc021 +#define PCI_SUBDEVICE_ID_DIGIGRAM_LX6464ESE_CAE_SERIAL_SUBSYSTEM 0xc022 #define PCI_VENDOR_ID_KAWASAKI 0x136b #define PCI_DEVICE_ID_MCHIP_KL5A72002 0xff01 @@ -2131,6 +2134,7 @@ #define PCI_VENDOR_ID_MYRICOM 0x14c1 #define PCI_VENDOR_ID_MEDIATEK 0x14c3 +#define PCI_DEVICE_ID_MEDIATEK_7629 0x7629 #define PCI_VENDOR_ID_TITAN 0x14D2 #define PCI_DEVICE_ID_TITAN_010L 0x8001 @@ -2366,6 +2370,7 @@ #define PCI_DEVICE_ID_SYNOPSYS_HAPSUSB3 0xabcd #define PCI_DEVICE_ID_SYNOPSYS_HAPSUSB3_AXI 0xabce #define PCI_DEVICE_ID_SYNOPSYS_HAPSUSB31 0xabcf +#define PCI_DEVICE_ID_SYNOPSYS_EDDA 0xedda #define PCI_VENDOR_ID_USR 0x16ec @@ -2403,6 +2408,8 @@ #define PCI_DEVICE_ID_RDC_R6061 0x6061 #define PCI_DEVICE_ID_RDC_D1010 0x1010 +#define PCI_VENDOR_ID_GLI 0x17a0 + #define PCI_VENDOR_ID_LENOVO 0x17aa #define PCI_VENDOR_ID_QCOM 0x17cb @@ -2550,7 +2557,7 @@ #define PCI_DEVICE_ID_KORENIX_JETCARDF2 0x1700 #define PCI_DEVICE_ID_KORENIX_JETCARDF3 0x17ff -#define PCI_VENDOR_ID_HUAWEI 0x19e5 +#define PCI_VENDOR_ID_HUAWEI 0x19e5 #define PCI_VENDOR_ID_NETRONOME 0x19ee #define PCI_DEVICE_ID_NETRONOME_NFP4000 0x4000 @@ -2568,6 +2575,8 @@ #define PCI_VENDOR_ID_ASMEDIA 0x1b21 +#define PCI_VENDOR_ID_AMAZON_ANNAPURNA_LABS 0x1c36 + #define PCI_VENDOR_ID_CIRCUITCO 0x1cc8 #define PCI_SUBSYSTEM_ID_CIRCUITCO_MINNOWBOARD 0x0001 diff --git a/include/linux/percpu-refcount.h b/include/linux/percpu-refcount.h index b297cd1cd4f1..7aef0abc194a 100644 --- a/include/linux/percpu-refcount.h +++ b/include/linux/percpu-refcount.h @@ -75,14 +75,21 @@ enum { * operation using percpu_ref_switch_to_percpu(). If initialized * with this flag, the ref will stay in atomic mode until * percpu_ref_switch_to_percpu() is invoked on it. + * Implies ALLOW_REINIT. */ PERCPU_REF_INIT_ATOMIC = 1 << 0, /* * Start dead w/ ref == 0 in atomic mode. Must be revived with - * percpu_ref_reinit() before used. Implies INIT_ATOMIC. + * percpu_ref_reinit() before used. Implies INIT_ATOMIC and + * ALLOW_REINIT. */ PERCPU_REF_INIT_DEAD = 1 << 1, + + /* + * Allow switching from atomic mode to percpu mode. + */ + PERCPU_REF_ALLOW_REINIT = 1 << 2, }; struct percpu_ref { @@ -95,6 +102,7 @@ struct percpu_ref { percpu_ref_func_t *release; percpu_ref_func_t *confirm_switch; bool force_atomic:1; + bool allow_reinit:1; struct rcu_head rcu; }; diff --git a/include/linux/percpu-rwsem.h b/include/linux/percpu-rwsem.h index 03cb4b6f842e..3998cdf9cd14 100644 --- a/include/linux/percpu-rwsem.h +++ b/include/linux/percpu-rwsem.h @@ -17,14 +17,18 @@ struct percpu_rw_semaphore { int readers_block; }; -#define DEFINE_STATIC_PERCPU_RWSEM(name) \ +#define __DEFINE_PERCPU_RWSEM(name, is_static) \ static DEFINE_PER_CPU(unsigned int, __percpu_rwsem_rc_##name); \ -static struct percpu_rw_semaphore name = { \ - .rss = __RCU_SYNC_INITIALIZER(name.rss, RCU_SCHED_SYNC), \ +is_static struct percpu_rw_semaphore name = { \ + .rss = __RCU_SYNC_INITIALIZER(name.rss), \ .read_count = &__percpu_rwsem_rc_##name, \ .rw_sem = __RWSEM_INITIALIZER(name.rw_sem), \ .writer = __RCUWAIT_INITIALIZER(name.writer), \ } +#define DEFINE_PERCPU_RWSEM(name) \ + __DEFINE_PERCPU_RWSEM(name, /* not static */) +#define DEFINE_STATIC_PERCPU_RWSEM(name) \ + __DEFINE_PERCPU_RWSEM(name, static) extern int __percpu_down_read(struct percpu_rw_semaphore *, int); extern void __percpu_up_read(struct percpu_rw_semaphore *); @@ -117,7 +121,7 @@ static inline void percpu_rwsem_release(struct percpu_rw_semaphore *sem, lock_release(&sem->rw_sem.dep_map, 1, ip); #ifdef CONFIG_RWSEM_SPIN_ON_OWNER if (!read) - sem->rw_sem.owner = RWSEM_OWNER_UNKNOWN; + atomic_long_set(&sem->rw_sem.owner, RWSEM_OWNER_UNKNOWN); #endif } @@ -127,7 +131,7 @@ static inline void percpu_rwsem_acquire(struct percpu_rw_semaphore *sem, lock_acquire(&sem->rw_sem.dep_map, 0, 1, read, 1, NULL, ip); #ifdef CONFIG_RWSEM_SPIN_ON_OWNER if (!read) - sem->rw_sem.owner = current; + atomic_long_set(&sem->rw_sem.owner, (long)current); #endif } diff --git a/include/linux/percpu.h b/include/linux/percpu.h index 9909dc0e273a..5e76af742c80 100644 --- a/include/linux/percpu.h +++ b/include/linux/percpu.h @@ -105,7 +105,7 @@ extern struct pcpu_alloc_info * __init pcpu_alloc_alloc_info(int nr_groups, int nr_units); extern void __init pcpu_free_alloc_info(struct pcpu_alloc_info *ai); -extern int __init pcpu_setup_first_chunk(const struct pcpu_alloc_info *ai, +extern void __init pcpu_setup_first_chunk(const struct pcpu_alloc_info *ai, void *base_addr); #ifdef CONFIG_NEED_PER_CPU_EMBED_FIRST_CHUNK diff --git a/include/linux/perf/arm_pmu.h b/include/linux/perf/arm_pmu.h index a9b0ee408fbd..71f525a35ac2 100644 --- a/include/linux/perf/arm_pmu.h +++ b/include/linux/perf/arm_pmu.h @@ -171,4 +171,6 @@ void armpmu_free_irq(int irq, int cpu); #endif /* CONFIG_ARM_PMU */ +#define ARMV8_SPE_PDEV_NAME "arm,spe-v1" + #endif /* __ARM_PMU_H__ */ diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h index 2bca72f3028b..61448c19a132 100644 --- a/include/linux/perf_event.h +++ b/include/linux/perf_event.h @@ -246,6 +246,7 @@ struct perf_event; #define PERF_PMU_CAP_ITRACE 0x20 #define PERF_PMU_CAP_HETEROGENEOUS_CPUS 0x40 #define PERF_PMU_CAP_NO_EXCLUDE 0x80 +#define PERF_PMU_CAP_AUX_OUTPUT 0x100 /** * struct pmu - generic performance monitoring unit @@ -256,6 +257,7 @@ struct pmu { struct module *module; struct device *dev; const struct attribute_group **attr_groups; + const struct attribute_group **attr_update; const char *name; int type; @@ -446,6 +448,16 @@ struct pmu { /* optional */ /* + * Check if event can be used for aux_output purposes for + * events of this PMU. + * + * Runs from perf_event_open(). Should return 0 for "no match" + * or non-zero for "match". + */ + int (*aux_output_match) (struct perf_event *event); + /* optional */ + + /* * Filter events for PMU-specific reasons. */ int (*filter_match) (struct perf_event *event); /* optional */ @@ -680,6 +692,9 @@ struct perf_event { struct perf_addr_filter_range *addr_filter_ranges; unsigned long addr_filters_gen; + /* for aux_output events */ + struct perf_event *aux_event; + void (*destroy)(struct perf_event *); struct rcu_head rcu_head; @@ -749,6 +764,11 @@ struct perf_event_context { int nr_stat; int nr_freq; int rotate_disable; + /* + * Set when nr_events != nr_active, except tolerant to events not + * necessary to be active due to scheduling constraints, such as cgroups. + */ + int rotate_necessary; refcount_t refcount; struct task_struct *task; @@ -1049,6 +1069,11 @@ static inline int in_software_context(struct perf_event *event) return event->ctx->pmu->task_ctx_nr == perf_sw_context; } +static inline int is_exclusive_pmu(struct pmu *pmu) +{ + return pmu->capabilities & PERF_PMU_CAP_EXCLUSIVE; +} + extern struct static_key perf_swevent_enabled[PERF_COUNT_SW_MAX]; extern void ___perf_sw_event(u32, u64, struct pt_regs *, u64); diff --git a/include/linux/pfn_t.h b/include/linux/pfn_t.h index 3c202a11a79e..2d9148221e9a 100644 --- a/include/linux/pfn_t.h +++ b/include/linux/pfn_t.h @@ -66,13 +66,6 @@ static inline phys_addr_t pfn_t_to_phys(pfn_t pfn) return PFN_PHYS(pfn_t_to_pfn(pfn)); } -static inline void *pfn_t_to_virt(pfn_t pfn) -{ - if (pfn_t_has_page(pfn) && !is_device_private_page(pfn_t_to_page(pfn))) - return __va(pfn_t_to_phys(pfn)); - return NULL; -} - static inline pfn_t page_to_pfn_t(struct page *page) { return pfn_to_pfn_t(page_to_pfn(page)); @@ -104,7 +97,7 @@ static inline pud_t pfn_t_pud(pfn_t pfn, pgprot_t pgprot) #endif #endif -#ifdef __HAVE_ARCH_PTE_DEVMAP +#ifdef CONFIG_ARCH_HAS_PTE_DEVMAP static inline bool pfn_t_devmap(pfn_t pfn) { const u64 flags = PFN_DEV|PFN_MAP; @@ -122,7 +115,7 @@ pmd_t pmd_mkdevmap(pmd_t pmd); defined(CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD) pud_t pud_mkdevmap(pud_t pud); #endif -#endif /* __HAVE_ARCH_PTE_DEVMAP */ +#endif /* CONFIG_ARCH_HAS_PTE_DEVMAP */ #ifdef CONFIG_ARCH_HAS_PTE_SPECIAL static inline bool pfn_t_special(pfn_t pfn) diff --git a/include/linux/phy.h b/include/linux/phy.h index 6424586fe2d6..a7ecbe0e55aa 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -55,6 +55,9 @@ extern __ETHTOOL_DECLARE_LINK_MODE_MASK(phy_10gbit_full_features) __ro_after_ini #define PHY_10GBIT_FEC_FEATURES ((unsigned long *)&phy_10gbit_fec_features) #define PHY_10GBIT_FULL_FEATURES ((unsigned long *)&phy_10gbit_full_features) +extern const int phy_basic_ports_array[3]; +extern const int phy_fibre_port_array[1]; +extern const int phy_all_ports_features_array[7]; extern const int phy_10_100_features_array[4]; extern const int phy_basic_t1_features_array[2]; extern const int phy_gbit_features_array[2]; @@ -98,6 +101,7 @@ typedef enum { PHY_INTERFACE_MODE_XAUI, /* 10GBASE-KR, XFI, SFI - single lane 10G Serdes */ PHY_INTERFACE_MODE_10GKR, + PHY_INTERFACE_MODE_USXGMII, PHY_INTERFACE_MODE_MAX, } phy_interface_t; @@ -173,6 +177,8 @@ static inline const char *phy_modes(phy_interface_t interface) return "xaui"; case PHY_INTERFACE_MODE_10GKR: return "10gbase-kr"; + case PHY_INTERFACE_MODE_USXGMII: + return "usxgmii"; default: return "unknown"; } @@ -180,7 +186,6 @@ static inline const char *phy_modes(phy_interface_t interface) #define PHY_INIT_TIMEOUT 100000 -#define PHY_STATE_TIME 1 #define PHY_FORCE_TIMEOUT 10 #define PHY_MAX_ADDR 32 @@ -193,6 +198,8 @@ static inline const char *phy_modes(phy_interface_t interface) /* Or MII_ADDR_C45 into regnum for read/write on mii_bus to enable the 21 bit IEEE 802.3ae clause 45 addressing mode used by 10GIGE phy chips. */ #define MII_ADDR_C45 (1<<30) +#define MII_DEVADDR_C45_SHIFT 16 +#define MII_REGADDR_C45_MASK GENMASK(15, 0) struct device; struct phylink; @@ -290,12 +297,6 @@ struct phy_device *mdiobus_scan(struct mii_bus *bus, int addr); * - irq or timer will set RUNNING if link comes back * - phy_stop moves to HALTED * - * FORCING: PHY is being configured with forced settings - * - if link is up, move to RUNNING - * - If link is down, we drop to the next highest setting, and - * retry (FORCING) after a timeout - * - phy_stop moves to HALTED - * * RUNNING: PHY is currently up, running, and possibly sending * and/or receiving packets * - irq or timer will set NOLINK if link goes down @@ -312,7 +313,6 @@ enum phy_state { PHY_UP, PHY_RUNNING, PHY_NOLINK, - PHY_FORCING, }; /** @@ -340,8 +340,6 @@ struct phy_c45_device_ids { * loopback_enabled: Set true if this phy has been loopbacked successfully. * state: state of the PHY for management purposes * dev_flags: Device-specific flags used by the PHY driver. - * link_timeout: The number of timer firings to wait before the - * giving up on the current attempt at acquiring a link * irq: IRQ number of the PHY's interrupt (-1 if none) * phy_timer: The timer for handling the state machine * attached_dev: The attached enet driver's device instance ptr @@ -405,12 +403,12 @@ struct phy_device { __ETHTOOL_DECLARE_LINK_MODE_MASK(supported); __ETHTOOL_DECLARE_LINK_MODE_MASK(advertising); __ETHTOOL_DECLARE_LINK_MODE_MASK(lp_advertising); + /* used with phy_speed_down */ + __ETHTOOL_DECLARE_LINK_MODE_MASK(adv_old); /* Energy efficient ethernet modes which should be prohibited */ u32 eee_broken_modes; - int link_timeout; - #ifdef CONFIG_LED_TRIGGER_PHY struct phy_led_trigger *phy_led_triggers; unsigned int phy_num_led_triggers; @@ -529,6 +527,9 @@ struct phy_driver { */ int (*did_interrupt)(struct phy_device *phydev); + /* Override default interrupt handling */ + int (*handle_interrupt)(struct phy_device *phydev); + /* Clears up any memory if needed */ void (*remove)(struct phy_device *phydev); @@ -666,6 +667,7 @@ size_t phy_speeds(unsigned int *speeds, size_t size, unsigned long *mask); void of_set_phy_supported(struct phy_device *phydev); void of_set_phy_eee_broken(struct phy_device *phydev); +int phy_speed_down_core(struct phy_device *phydev); /** * phy_is_started - Convenience function to check whether PHY is started @@ -985,6 +987,8 @@ int phy_select_page(struct phy_device *phydev, int page); int phy_restore_page(struct phy_device *phydev, int oldpage, int ret); int phy_read_paged(struct phy_device *phydev, int page, u32 regnum); int phy_write_paged(struct phy_device *phydev, int page, u32 regnum, u16 val); +int phy_modify_paged_changed(struct phy_device *phydev, int page, u32 regnum, + u16 mask, u16 set); int phy_modify_paged(struct phy_device *phydev, int page, u32 regnum, u16 mask, u16 set); @@ -1065,12 +1069,11 @@ void phy_attached_print(struct phy_device *phydev, const char *fmt, ...) void phy_attached_info(struct phy_device *phydev); /* Clause 22 PHY */ -int genphy_config_init(struct phy_device *phydev); int genphy_read_abilities(struct phy_device *phydev); int genphy_setup_forced(struct phy_device *phydev); int genphy_restart_aneg(struct phy_device *phydev); int genphy_config_eee_advert(struct phy_device *phydev); -int genphy_config_aneg(struct phy_device *phydev); +int __genphy_config_aneg(struct phy_device *phydev, bool changed); int genphy_aneg_done(struct phy_device *phydev); int genphy_update_link(struct phy_device *phydev); int genphy_read_status(struct phy_device *phydev); @@ -1078,6 +1081,12 @@ int genphy_suspend(struct phy_device *phydev); int genphy_resume(struct phy_device *phydev); int genphy_loopback(struct phy_device *phydev, bool enable); int genphy_soft_reset(struct phy_device *phydev); + +static inline int genphy_config_aneg(struct phy_device *phydev) +{ + return __genphy_config_aneg(phydev, false); +} + static inline int genphy_no_soft_reset(struct phy_device *phydev) { return 0; @@ -1108,6 +1117,7 @@ int genphy_c45_an_disable_aneg(struct phy_device *phydev); int genphy_c45_read_mdix(struct phy_device *phydev); int genphy_c45_pma_read_abilities(struct phy_device *phydev); int genphy_c45_read_status(struct phy_device *phydev); +int genphy_c45_config_aneg(struct phy_device *phydev); /* The gen10g_* functions are the old Clause 45 stub */ int gen10g_config_aneg(struct phy_device *phydev); @@ -1129,6 +1139,7 @@ int phy_driver_register(struct phy_driver *new_driver, struct module *owner); int phy_drivers_register(struct phy_driver *new_driver, int n, struct module *owner); void phy_state_machine(struct work_struct *work); +void phy_queue_state_machine(struct phy_device *phydev, unsigned long jiffies); void phy_mac_interrupt(struct phy_device *phydev); void phy_start_machine(struct phy_device *phydev); void phy_stop_machine(struct phy_device *phydev); @@ -1139,6 +1150,7 @@ int phy_ethtool_ksettings_set(struct phy_device *phydev, const struct ethtool_link_ksettings *cmd); int phy_mii_ioctl(struct phy_device *phydev, struct ifreq *ifr, int cmd); void phy_request_interrupt(struct phy_device *phydev); +void phy_free_interrupt(struct phy_device *phydev); void phy_print_status(struct phy_device *phydev); int phy_set_max_speed(struct phy_device *phydev, u32 max_speed); void phy_remove_link_mode(struct phy_device *phydev, u32 link_mode); diff --git a/include/linux/phy_fixed.h b/include/linux/phy_fixed.h index 1e5d86ebdaeb..52bc8e487ef7 100644 --- a/include/linux/phy_fixed.h +++ b/include/linux/phy_fixed.h @@ -11,6 +11,7 @@ struct fixed_phy_status { }; struct device_node; +struct gpio_desc; #if IS_ENABLED(CONFIG_FIXED_PHY) extern int fixed_phy_change_carrier(struct net_device *dev, bool new_carrier); diff --git a/include/linux/phylink.h b/include/linux/phylink.h index 2d2e55dfea94..300ecdb6790a 100644 --- a/include/linux/phylink.h +++ b/include/linux/phylink.h @@ -54,6 +54,21 @@ struct phylink_link_state { unsigned int an_complete:1; }; +enum phylink_op_type { + PHYLINK_NETDEV = 0, + PHYLINK_DEV, +}; + +/** + * struct phylink_config - PHYLINK configuration structure + * @dev: a pointer to a struct device associated with the MAC + * @type: operation type of PHYLINK instance + */ +struct phylink_config { + struct device *dev; + enum phylink_op_type type; +}; + /** * struct phylink_mac_ops - MAC operations structure. * @validate: Validate and update the link configuration. @@ -66,16 +81,17 @@ struct phylink_link_state { * The individual methods are described more fully below. */ struct phylink_mac_ops { - void (*validate)(struct net_device *ndev, unsigned long *supported, + void (*validate)(struct phylink_config *config, + unsigned long *supported, struct phylink_link_state *state); - int (*mac_link_state)(struct net_device *ndev, + int (*mac_link_state)(struct phylink_config *config, struct phylink_link_state *state); - void (*mac_config)(struct net_device *ndev, unsigned int mode, + void (*mac_config)(struct phylink_config *config, unsigned int mode, const struct phylink_link_state *state); - void (*mac_an_restart)(struct net_device *ndev); - void (*mac_link_down)(struct net_device *ndev, unsigned int mode, + void (*mac_an_restart)(struct phylink_config *config); + void (*mac_link_down)(struct phylink_config *config, unsigned int mode, phy_interface_t interface); - void (*mac_link_up)(struct net_device *ndev, unsigned int mode, + void (*mac_link_up)(struct phylink_config *config, unsigned int mode, phy_interface_t interface, struct phy_device *phy); }; @@ -83,7 +99,7 @@ struct phylink_mac_ops { #if 0 /* For kernel-doc purposes only. */ /** * validate - Validate and update the link configuration - * @ndev: a pointer to a &struct net_device for the MAC. + * @config: a pointer to a &struct phylink_config. * @supported: ethtool bitmask for supported link modes. * @state: a pointer to a &struct phylink_link_state. * @@ -93,19 +109,26 @@ struct phylink_mac_ops { * Note that the PHY may be able to transform from one connection * technology to another, so, eg, don't clear 1000BaseX just * because the MAC is unable to BaseX mode. This is more about - * clearing unsupported speeds and duplex settings. + * clearing unsupported speeds and duplex settings. The port modes + * should not be cleared; phylink_set_port_modes() will help with this. * * If the @state->interface mode is %PHY_INTERFACE_MODE_1000BASEX * or %PHY_INTERFACE_MODE_2500BASEX, select the appropriate mode * based on @state->advertising and/or @state->speed and update - * @state->interface accordingly. + * @state->interface accordingly. See phylink_helper_basex_speed(). + * + * When @state->interface is %PHY_INTERFACE_MODE_NA, phylink expects the + * MAC driver to return all supported link modes. + * + * If the @state->interface mode is not supported, then the @supported + * mask must be cleared. */ -void validate(struct net_device *ndev, unsigned long *supported, +void validate(struct phylink_config *config, unsigned long *supported, struct phylink_link_state *state); /** * mac_link_state() - Read the current link state from the hardware - * @ndev: a pointer to a &struct net_device for the MAC. + * @config: a pointer to a &struct phylink_config. * @state: a pointer to a &struct phylink_link_state. * * Read the current link state from the MAC, reporting the current @@ -114,12 +137,12 @@ void validate(struct net_device *ndev, unsigned long *supported, * negotiation completion state in @state->an_complete, and link * up state in @state->link. */ -int mac_link_state(struct net_device *ndev, +int mac_link_state(struct phylink_config *config, struct phylink_link_state *state); /** * mac_config() - configure the MAC for the selected mode and state - * @ndev: a pointer to a &struct net_device for the MAC. + * @config: a pointer to a &struct phylink_config. * @mode: one of %MLO_AN_FIXED, %MLO_AN_PHY, %MLO_AN_INBAND. * @state: a pointer to a &struct phylink_link_state. * @@ -168,18 +191,18 @@ int mac_link_state(struct net_device *ndev, * down. This "update" behaviour is critical to avoid bouncing the * link up status. */ -void mac_config(struct net_device *ndev, unsigned int mode, +void mac_config(struct phylink_config *config, unsigned int mode, const struct phylink_link_state *state); /** * mac_an_restart() - restart 802.3z BaseX autonegotiation - * @ndev: a pointer to a &struct net_device for the MAC. + * @config: a pointer to a &struct phylink_config. */ -void mac_an_restart(struct net_device *ndev); +void mac_an_restart(struct phylink_config *config); /** * mac_link_down() - take the link down - * @ndev: a pointer to a &struct net_device for the MAC. + * @config: a pointer to a &struct phylink_config. * @mode: link autonegotiation mode * @interface: link &typedef phy_interface_t mode * @@ -188,12 +211,12 @@ void mac_an_restart(struct net_device *ndev); * Energy Efficient Ethernet MAC configuration. Interface type * selection must be done in mac_config(). */ -void mac_link_down(struct net_device *ndev, unsigned int mode, +void mac_link_down(struct phylink_config *config, unsigned int mode, phy_interface_t interface); /** * mac_link_up() - allow the link to come up - * @ndev: a pointer to a &struct net_device for the MAC. + * @config: a pointer to a &struct phylink_config. * @mode: link autonegotiation mode * @interface: link &typedef phy_interface_t mode * @phy: any attached phy @@ -204,13 +227,14 @@ void mac_link_down(struct net_device *ndev, unsigned int mode, * phy_init_eee() and perform appropriate MAC configuration for EEE. * Interface type selection must be done in mac_config(). */ -void mac_link_up(struct net_device *ndev, unsigned int mode, +void mac_link_up(struct phylink_config *config, unsigned int mode, phy_interface_t interface, struct phy_device *phy); #endif -struct phylink *phylink_create(struct net_device *, struct fwnode_handle *, - phy_interface_t iface, const struct phylink_mac_ops *ops); +struct phylink *phylink_create(struct phylink_config *, struct fwnode_handle *, + phy_interface_t iface, + const struct phylink_mac_ops *ops); void phylink_destroy(struct phylink *); int phylink_connect_phy(struct phylink *, struct phy_device *); diff --git a/include/linux/pid.h b/include/linux/pid.h index 3c8ef5a199ca..9645b1194c98 100644 --- a/include/linux/pid.h +++ b/include/linux/pid.h @@ -3,6 +3,8 @@ #define _LINUX_PID_H #include <linux/rculist.h> +#include <linux/wait.h> +#include <linux/refcount.h> enum pid_type { @@ -56,10 +58,12 @@ struct upid { struct pid { - atomic_t count; + refcount_t count; unsigned int level; /* lists of tasks that use this pid */ struct hlist_head tasks[PIDTYPE_MAX]; + /* wait queue for pidfd notifications */ + wait_queue_head_t wait_pidfd; struct rcu_head rcu; struct upid numbers[1]; }; @@ -68,10 +72,14 @@ extern struct pid init_struct_pid; extern const struct file_operations pidfd_fops; +struct file; + +extern struct pid *pidfd_pid(const struct file *file); + static inline struct pid *get_pid(struct pid *pid) { if (pid) - atomic_inc(&pid->count); + refcount_inc(&pid->count); return pid; } diff --git a/include/linux/pinctrl/consumer.h b/include/linux/pinctrl/consumer.h index 86720a5a384f..7f8c7d9583d3 100644 --- a/include/linux/pinctrl/consumer.h +++ b/include/linux/pinctrl/consumer.h @@ -24,6 +24,7 @@ struct device; #ifdef CONFIG_PINCTRL /* External interface to pin control */ +extern bool pinctrl_gpio_can_use_line(unsigned gpio); extern int pinctrl_gpio_request(unsigned gpio); extern void pinctrl_gpio_free(unsigned gpio); extern int pinctrl_gpio_direction_input(unsigned gpio); @@ -61,6 +62,11 @@ static inline int pinctrl_pm_select_idle_state(struct device *dev) #else /* !CONFIG_PINCTRL */ +static inline bool pinctrl_gpio_can_use_line(unsigned gpio) +{ + return true; +} + static inline int pinctrl_gpio_request(unsigned gpio) { return 0; diff --git a/include/linux/pinctrl/pinconf-generic.h b/include/linux/pinctrl/pinconf-generic.h index 6f260c1d3467..6aeb711f7cd1 100644 --- a/include/linux/pinctrl/pinconf-generic.h +++ b/include/linux/pinctrl/pinconf-generic.h @@ -11,6 +11,12 @@ #ifndef __LINUX_PINCTRL_PINCONF_GENERIC_H #define __LINUX_PINCTRL_PINCONF_GENERIC_H +#include <linux/device.h> +#include <linux/pinctrl/machine.h> + +struct pinctrl_dev; +struct pinctrl_map; + /** * enum pin_config_param - possible pin configuration parameters * @PIN_CONFIG_BIAS_BUS_HOLD: the pin will be set to weakly latch so that it @@ -54,6 +60,8 @@ * push-pull mode, the argument is ignored. * @PIN_CONFIG_DRIVE_STRENGTH: the pin will sink or source at most the current * passed as argument. The argument is in mA. + * @PIN_CONFIG_DRIVE_STRENGTH_UA: the pin will sink or source at most the current + * passed as argument. The argument is in uA. * @PIN_CONFIG_INPUT_DEBOUNCE: this will configure the pin to debounce mode, * which means it will wait for signals to settle when reading inputs. The * argument gives the debounce time in usecs. Setting the @@ -111,6 +119,7 @@ enum pin_config_param { PIN_CONFIG_DRIVE_OPEN_SOURCE, PIN_CONFIG_DRIVE_PUSH_PULL, PIN_CONFIG_DRIVE_STRENGTH, + PIN_CONFIG_DRIVE_STRENGTH_UA, PIN_CONFIG_INPUT_DEBOUNCE, PIN_CONFIG_INPUT_ENABLE, PIN_CONFIG_INPUT_SCHMITT, @@ -155,9 +164,6 @@ static inline unsigned long pinconf_to_config_packed(enum pin_config_param param return PIN_CONF_PACKED(param, argument); } -#ifdef CONFIG_GENERIC_PINCONF - -#ifdef CONFIG_DEBUG_FS #define PCONFDUMP(a, b, c, d) { \ .param = a, .display = b, .format = c, .has_arg = d \ } @@ -168,14 +174,6 @@ struct pin_config_item { const char * const format; bool has_arg; }; -#endif /* CONFIG_DEBUG_FS */ - -#ifdef CONFIG_OF - -#include <linux/device.h> -#include <linux/pinctrl/machine.h> -struct pinctrl_dev; -struct pinctrl_map; struct pinconf_generic_params { const char * const property; @@ -220,8 +218,5 @@ static inline int pinconf_generic_dt_node_to_map_all( return pinconf_generic_dt_node_to_map(pctldev, np_config, map, num_maps, PIN_MAP_TYPE_INVALID); } -#endif - -#endif /* CONFIG_GENERIC_PINCONF */ #endif /* __LINUX_PINCTRL_PINCONF_GENERIC_H */ diff --git a/include/linux/pinctrl/pinconf.h b/include/linux/pinctrl/pinconf.h index 514414a5ad01..f8a8215e9021 100644 --- a/include/linux/pinctrl/pinconf.h +++ b/include/linux/pinctrl/pinconf.h @@ -11,7 +11,7 @@ #ifndef __LINUX_PINCTRL_PINCONF_H #define __LINUX_PINCTRL_PINCONF_H -#ifdef CONFIG_PINCONF +#include <linux/types.h> struct pinctrl_dev; struct seq_file; @@ -64,6 +64,4 @@ struct pinconf_ops { unsigned long config); }; -#endif - #endif /* __LINUX_PINCTRL_PINCONF_H */ diff --git a/include/linux/pinctrl/pinctrl-state.h b/include/linux/pinctrl/pinctrl-state.h index a0e785815a64..635d97e9285e 100644 --- a/include/linux/pinctrl/pinctrl-state.h +++ b/include/linux/pinctrl/pinctrl-state.h @@ -3,6 +3,9 @@ * Standard pin control state definitions */ +#ifndef __LINUX_PINCTRL_PINCTRL_STATE_H +#define __LINUX_PINCTRL_PINCTRL_STATE_H + /** * @PINCTRL_STATE_DEFAULT: the state the pinctrl handle shall be put * into as default, usually this means the pins are up and ready to @@ -31,3 +34,5 @@ #define PINCTRL_STATE_INIT "init" #define PINCTRL_STATE_IDLE "idle" #define PINCTRL_STATE_SLEEP "sleep" + +#endif /* __LINUX_PINCTRL_PINCTRL_STATE_H */ diff --git a/include/linux/pinctrl/pinctrl.h b/include/linux/pinctrl/pinctrl.h index e429e5d92dd6..7ce23450a1cb 100644 --- a/include/linux/pinctrl/pinctrl.h +++ b/include/linux/pinctrl/pinctrl.h @@ -11,8 +11,6 @@ #ifndef __LINUX_PINCTRL_PINCTRL_H #define __LINUX_PINCTRL_PINCTRL_H -#ifdef CONFIG_PINCTRL - #include <linux/radix-tree.h> #include <linux/list.h> #include <linux/seq_file.h> @@ -124,6 +122,10 @@ struct pinctrl_ops { * the hardware description * @custom_conf_items: Information how to print @params in debugfs, must be * the same size as the @custom_params, i.e. @num_custom_params + * @link_consumers: If true create a device link between pinctrl and its + * consumers (i.e. the devices requesting pin control states). This is + * sometimes necessary to ascertain the right suspend/resume order for + * example. */ struct pinctrl_desc { const char *name; @@ -138,6 +140,7 @@ struct pinctrl_desc { const struct pinconf_generic_params *custom_params; const struct pin_config_item *custom_conf_items; #endif + bool link_consumers; }; /* External interface to pin controller */ @@ -166,7 +169,6 @@ extern struct pinctrl_dev *devm_pinctrl_register(struct device *dev, extern void devm_pinctrl_unregister(struct device *dev, struct pinctrl_dev *pctldev); -extern bool pin_is_valid(struct pinctrl_dev *pctldev, int pin); extern void pinctrl_add_gpio_range(struct pinctrl_dev *pctldev, struct pinctrl_gpio_range *range); extern void pinctrl_add_gpio_ranges(struct pinctrl_dev *pctldev, @@ -197,16 +199,5 @@ struct pinctrl_dev *of_pinctrl_get(struct device_node *np) extern const char *pinctrl_dev_get_name(struct pinctrl_dev *pctldev); extern const char *pinctrl_dev_get_devname(struct pinctrl_dev *pctldev); extern void *pinctrl_dev_get_drvdata(struct pinctrl_dev *pctldev); -#else - -struct pinctrl_dev; - -/* Sufficiently stupid default functions when pinctrl is not in use */ -static inline bool pin_is_valid(struct pinctrl_dev *pctldev, int pin) -{ - return pin >= 0; -} - -#endif /* !CONFIG_PINCTRL */ #endif /* __LINUX_PINCTRL_PINCTRL_H */ diff --git a/include/linux/pinctrl/pinmux.h b/include/linux/pinctrl/pinmux.h index e873ed97d79e..9a647fa5c8f1 100644 --- a/include/linux/pinctrl/pinmux.h +++ b/include/linux/pinctrl/pinmux.h @@ -15,8 +15,6 @@ #include <linux/seq_file.h> #include <linux/pinctrl/pinctrl.h> -#ifdef CONFIG_PINMUX - struct pinctrl_dev; /** @@ -84,6 +82,4 @@ struct pinmux_ops { bool strict; }; -#endif /* CONFIG_PINMUX */ - #endif /* __LINUX_PINCTRL_PINMUX_H */ diff --git a/include/linux/platform_data/cros_ec_chardev.h b/include/linux/platform_data/cros_ec_chardev.h new file mode 100644 index 000000000000..7de8faaf77df --- /dev/null +++ b/include/linux/platform_data/cros_ec_chardev.h @@ -0,0 +1,38 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * ChromeOS EC device interface. + * + * Copyright (C) 2014 Google, Inc. + */ + +#ifndef _UAPI_LINUX_CROS_EC_DEV_H_ +#define _UAPI_LINUX_CROS_EC_DEV_H_ + +#include <linux/bits.h> +#include <linux/ioctl.h> +#include <linux/types.h> + +#include <linux/platform_data/cros_ec_commands.h> + +#define CROS_EC_DEV_VERSION "1.0.0" + +/** + * struct cros_ec_readmem - Struct used to read mapped memory. + * @offset: Within EC_LPC_ADDR_MEMMAP region. + * @bytes: Number of bytes to read. Zero means "read a string" (including '\0') + * At most only EC_MEMMAP_SIZE bytes can be read. + * @buffer: Where to store the result. The ioctl returns the number of bytes + * read or negative on error. + */ +struct cros_ec_readmem { + uint32_t offset; + uint32_t bytes; + uint8_t buffer[EC_MEMMAP_SIZE]; +}; + +#define CROS_EC_DEV_IOC 0xEC +#define CROS_EC_DEV_IOCXCMD _IOWR(CROS_EC_DEV_IOC, 0, struct cros_ec_command) +#define CROS_EC_DEV_IOCRDMEM _IOWR(CROS_EC_DEV_IOC, 1, struct cros_ec_readmem) +#define CROS_EC_DEV_IOCEVENTMASK _IO(CROS_EC_DEV_IOC, 2) + +#endif /* _CROS_EC_DEV_H_ */ diff --git a/include/linux/mfd/cros_ec_commands.h b/include/linux/platform_data/cros_ec_commands.h index 114614e20e4d..98415686cbfa 100644 --- a/include/linux/mfd/cros_ec_commands.h +++ b/include/linux/platform_data/cros_ec_commands.h @@ -4,17 +4,20 @@ * * Copyright (C) 2012 Google, Inc * - * The ChromeOS EC multi function device is used to mux all the requests - * to the EC device for its multiple features: keyboard controller, - * battery charging and regulator control, firmware update. - * - * NOTE: This file is copied verbatim from the ChromeOS EC Open Source - * project in an attempt to make future updates easy to make. + * NOTE: This file is auto-generated from ChromeOS EC Open Source code from + * https://chromium.googlesource.com/chromiumos/platform/ec/+/master/include/ec_commands.h */ +/* Host communication command constants for Chrome EC */ + #ifndef __CROS_EC_COMMANDS_H #define __CROS_EC_COMMANDS_H + + + +#define BUILD_ASSERT(_cond) + /* * Current version of this protocol * @@ -25,7 +28,7 @@ #define EC_PROTO_VERSION 0x00000002 /* Command version mask */ -#define EC_VER_MASK(version) (1UL << (version)) +#define EC_VER_MASK(version) BIT(version) /* I/O addresses for ACPI commands */ #define EC_LPC_ADDR_ACPI_DATA 0x62 @@ -39,25 +42,28 @@ /* Protocol version 2 */ #define EC_LPC_ADDR_HOST_ARGS 0x800 /* And 0x801, 0x802, 0x803 */ #define EC_LPC_ADDR_HOST_PARAM 0x804 /* For version 2 params; size is - * EC_PROTO2_MAX_PARAM_SIZE */ + * EC_PROTO2_MAX_PARAM_SIZE + */ /* Protocol version 3 */ #define EC_LPC_ADDR_HOST_PACKET 0x800 /* Offset of version 3 packet */ #define EC_LPC_HOST_PACKET_SIZE 0x100 /* Max size of version 3 packet */ -/* The actual block is 0x800-0x8ff, but some BIOSes think it's 0x880-0x8ff - * and they tell the kernel that so we have to think of it as two parts. */ +/* + * The actual block is 0x800-0x8ff, but some BIOSes think it's 0x880-0x8ff + * and they tell the kernel that so we have to think of it as two parts. + */ #define EC_HOST_CMD_REGION0 0x800 #define EC_HOST_CMD_REGION1 0x880 #define EC_HOST_CMD_REGION_SIZE 0x80 /* EC command register bit functions */ -#define EC_LPC_CMDR_DATA (1 << 0) /* Data ready for host to read */ -#define EC_LPC_CMDR_PENDING (1 << 1) /* Write pending to EC */ -#define EC_LPC_CMDR_BUSY (1 << 2) /* EC is busy processing a command */ -#define EC_LPC_CMDR_CMD (1 << 3) /* Last host write was a command */ -#define EC_LPC_CMDR_ACPI_BRST (1 << 4) /* Burst mode (not used) */ -#define EC_LPC_CMDR_SCI (1 << 5) /* SCI event is pending */ -#define EC_LPC_CMDR_SMI (1 << 6) /* SMI event is pending */ +#define EC_LPC_CMDR_DATA BIT(0) /* Data ready for host to read */ +#define EC_LPC_CMDR_PENDING BIT(1) /* Write pending to EC */ +#define EC_LPC_CMDR_BUSY BIT(2) /* EC is busy processing a command */ +#define EC_LPC_CMDR_CMD BIT(3) /* Last host write was a command */ +#define EC_LPC_CMDR_ACPI_BRST BIT(4) /* Burst mode (not used) */ +#define EC_LPC_CMDR_SCI BIT(5) /* SCI event is pending */ +#define EC_LPC_CMDR_SMI BIT(6) /* SMI event is pending */ #define EC_LPC_ADDR_MEMMAP 0x900 #define EC_MEMMAP_SIZE 255 /* ACPI IO buffer max is 255 bytes */ @@ -77,13 +83,15 @@ /* Unused 0x28 - 0x2f */ #define EC_MEMMAP_SWITCHES 0x30 /* 8 bits */ /* Unused 0x31 - 0x33 */ -#define EC_MEMMAP_HOST_EVENTS 0x34 /* 32 bits */ -/* Reserve 0x38 - 0x3f for additional host event-related stuff */ -/* Battery values are all 32 bits */ +#define EC_MEMMAP_HOST_EVENTS 0x34 /* 64 bits */ +/* Battery values are all 32 bits, unless otherwise noted. */ #define EC_MEMMAP_BATT_VOLT 0x40 /* Battery Present Voltage */ #define EC_MEMMAP_BATT_RATE 0x44 /* Battery Present Rate */ #define EC_MEMMAP_BATT_CAP 0x48 /* Battery Remaining Capacity */ -#define EC_MEMMAP_BATT_FLAG 0x4c /* Battery State, defined below */ +#define EC_MEMMAP_BATT_FLAG 0x4c /* Battery State, see below (8-bit) */ +#define EC_MEMMAP_BATT_COUNT 0x4d /* Battery Count (8-bit) */ +#define EC_MEMMAP_BATT_INDEX 0x4e /* Current Battery Data Index (8-bit) */ +/* Unused 0x4f */ #define EC_MEMMAP_BATT_DCAP 0x50 /* Battery Design Capacity */ #define EC_MEMMAP_BATT_DVLT 0x54 /* Battery Design Voltage */ #define EC_MEMMAP_BATT_LFCC 0x58 /* Battery Last Full Charge Capacity */ @@ -97,15 +105,24 @@ /* Unused 0x84 - 0x8f */ #define EC_MEMMAP_ACC_STATUS 0x90 /* Accelerometer status (8 bits )*/ /* Unused 0x91 */ -#define EC_MEMMAP_ACC_DATA 0x92 /* Accelerometer data 0x92 - 0x9f */ +#define EC_MEMMAP_ACC_DATA 0x92 /* Accelerometers data 0x92 - 0x9f */ +/* 0x92: Lid Angle if available, LID_ANGLE_UNRELIABLE otherwise */ +/* 0x94 - 0x99: 1st Accelerometer */ +/* 0x9a - 0x9f: 2nd Accelerometer */ #define EC_MEMMAP_GYRO_DATA 0xa0 /* Gyroscope data 0xa0 - 0xa5 */ -/* Unused 0xa6 - 0xfe (remember, 0xff is NOT part of the memmap region) */ +/* Unused 0xa6 - 0xdf */ +/* + * ACPI is unable to access memory mapped data at or above this offset due to + * limitations of the ACPI protocol. Do not place data in the range 0xe0 - 0xfe + * which might be needed by ACPI. + */ +#define EC_MEMMAP_NO_ACPI 0xe0 /* Define the format of the accelerometer mapped memory status byte. */ #define EC_MEMMAP_ACC_STATUS_SAMPLE_ID_MASK 0x0f -#define EC_MEMMAP_ACC_STATUS_BUSY_BIT (1 << 4) -#define EC_MEMMAP_ACC_STATUS_PRESENCE_BIT (1 << 7) +#define EC_MEMMAP_ACC_STATUS_BUSY_BIT BIT(4) +#define EC_MEMMAP_ACC_STATUS_PRESENCE_BIT BIT(7) /* Number of temp sensors at EC_MEMMAP_TEMP_SENSOR */ #define EC_TEMP_SENSOR_ENTRIES 16 @@ -149,6 +166,8 @@ #define EC_BATT_FLAG_DISCHARGING 0x04 #define EC_BATT_FLAG_CHARGING 0x08 #define EC_BATT_FLAG_LEVEL_CRITICAL 0x10 +/* Set if some of the static/dynamic data is invalid (or outdated). */ +#define EC_BATT_FLAG_INVALID_DATA 0x20 /* Switch flags at EC_MEMMAP_SWITCHES */ #define EC_SWITCH_LID_OPEN 0x01 @@ -174,20 +193,242 @@ #define EC_WIRELESS_SWITCH_WWAN 0x04 /* WWAN power */ #define EC_WIRELESS_SWITCH_WLAN_POWER 0x08 /* WLAN power */ +/*****************************************************************************/ +/* + * ACPI commands + * + * These are valid ONLY on the ACPI command/data port. + */ + +/* + * ACPI Read Embedded Controller + * + * This reads from ACPI memory space on the EC (EC_ACPI_MEM_*). + * + * Use the following sequence: + * + * - Write EC_CMD_ACPI_READ to EC_LPC_ADDR_ACPI_CMD + * - Wait for EC_LPC_CMDR_PENDING bit to clear + * - Write address to EC_LPC_ADDR_ACPI_DATA + * - Wait for EC_LPC_CMDR_DATA bit to set + * - Read value from EC_LPC_ADDR_ACPI_DATA + */ +#define EC_CMD_ACPI_READ 0x0080 + +/* + * ACPI Write Embedded Controller + * + * This reads from ACPI memory space on the EC (EC_ACPI_MEM_*). + * + * Use the following sequence: + * + * - Write EC_CMD_ACPI_WRITE to EC_LPC_ADDR_ACPI_CMD + * - Wait for EC_LPC_CMDR_PENDING bit to clear + * - Write address to EC_LPC_ADDR_ACPI_DATA + * - Wait for EC_LPC_CMDR_PENDING bit to clear + * - Write value to EC_LPC_ADDR_ACPI_DATA + */ +#define EC_CMD_ACPI_WRITE 0x0081 + +/* + * ACPI Burst Enable Embedded Controller + * + * This enables burst mode on the EC to allow the host to issue several + * commands back-to-back. While in this mode, writes to mapped multi-byte + * data are locked out to ensure data consistency. + */ +#define EC_CMD_ACPI_BURST_ENABLE 0x0082 + +/* + * ACPI Burst Disable Embedded Controller + * + * This disables burst mode on the EC and stops preventing EC writes to mapped + * multi-byte data. + */ +#define EC_CMD_ACPI_BURST_DISABLE 0x0083 + +/* + * ACPI Query Embedded Controller + * + * This clears the lowest-order bit in the currently pending host events, and + * sets the result code to the 1-based index of the bit (event 0x00000001 = 1, + * event 0x80000000 = 32), or 0 if no event was pending. + */ +#define EC_CMD_ACPI_QUERY_EVENT 0x0084 + +/* Valid addresses in ACPI memory space, for read/write commands */ + +/* Memory space version; set to EC_ACPI_MEM_VERSION_CURRENT */ +#define EC_ACPI_MEM_VERSION 0x00 +/* + * Test location; writing value here updates test compliment byte to (0xff - + * value). + */ +#define EC_ACPI_MEM_TEST 0x01 +/* Test compliment; writes here are ignored. */ +#define EC_ACPI_MEM_TEST_COMPLIMENT 0x02 + +/* Keyboard backlight brightness percent (0 - 100) */ +#define EC_ACPI_MEM_KEYBOARD_BACKLIGHT 0x03 +/* DPTF Target Fan Duty (0-100, 0xff for auto/none) */ +#define EC_ACPI_MEM_FAN_DUTY 0x04 + +/* + * DPTF temp thresholds. Any of the EC's temp sensors can have up to two + * independent thresholds attached to them. The current value of the ID + * register determines which sensor is affected by the THRESHOLD and COMMIT + * registers. The THRESHOLD register uses the same EC_TEMP_SENSOR_OFFSET scheme + * as the memory-mapped sensors. The COMMIT register applies those settings. + * + * The spec does not mandate any way to read back the threshold settings + * themselves, but when a threshold is crossed the AP needs a way to determine + * which sensor(s) are responsible. Each reading of the ID register clears and + * returns one sensor ID that has crossed one of its threshold (in either + * direction) since the last read. A value of 0xFF means "no new thresholds + * have tripped". Setting or enabling the thresholds for a sensor will clear + * the unread event count for that sensor. + */ +#define EC_ACPI_MEM_TEMP_ID 0x05 +#define EC_ACPI_MEM_TEMP_THRESHOLD 0x06 +#define EC_ACPI_MEM_TEMP_COMMIT 0x07 +/* + * Here are the bits for the COMMIT register: + * bit 0 selects the threshold index for the chosen sensor (0/1) + * bit 1 enables/disables the selected threshold (0 = off, 1 = on) + * Each write to the commit register affects one threshold. + */ +#define EC_ACPI_MEM_TEMP_COMMIT_SELECT_MASK BIT(0) +#define EC_ACPI_MEM_TEMP_COMMIT_ENABLE_MASK BIT(1) +/* + * Example: + * + * Set the thresholds for sensor 2 to 50 C and 60 C: + * write 2 to [0x05] -- select temp sensor 2 + * write 0x7b to [0x06] -- C_TO_K(50) - EC_TEMP_SENSOR_OFFSET + * write 0x2 to [0x07] -- enable threshold 0 with this value + * write 0x85 to [0x06] -- C_TO_K(60) - EC_TEMP_SENSOR_OFFSET + * write 0x3 to [0x07] -- enable threshold 1 with this value + * + * Disable the 60 C threshold, leaving the 50 C threshold unchanged: + * write 2 to [0x05] -- select temp sensor 2 + * write 0x1 to [0x07] -- disable threshold 1 + */ + +/* DPTF battery charging current limit */ +#define EC_ACPI_MEM_CHARGING_LIMIT 0x08 + +/* Charging limit is specified in 64 mA steps */ +#define EC_ACPI_MEM_CHARGING_LIMIT_STEP_MA 64 +/* Value to disable DPTF battery charging limit */ +#define EC_ACPI_MEM_CHARGING_LIMIT_DISABLED 0xff + +/* + * Report device orientation + * Bits Definition + * 3:1 Device DPTF Profile Number (DDPN) + * 0 = Reserved for backward compatibility (indicates no valid + * profile number. Host should fall back to using TBMD). + * 1..7 = DPTF Profile number to indicate to host which table needs + * to be loaded. + * 0 Tablet Mode Device Indicator (TBMD) + */ +#define EC_ACPI_MEM_DEVICE_ORIENTATION 0x09 +#define EC_ACPI_MEM_TBMD_SHIFT 0 +#define EC_ACPI_MEM_TBMD_MASK 0x1 +#define EC_ACPI_MEM_DDPN_SHIFT 1 +#define EC_ACPI_MEM_DDPN_MASK 0x7 + +/* + * Report device features. Uses the same format as the host command, except: + * + * bit 0 (EC_FEATURE_LIMITED) changes meaning from "EC code has a limited set + * of features", which is of limited interest when the system is already + * interpreting ACPI bytecode, to "EC_FEATURES[0-7] is not supported". Since + * these are supported, it defaults to 0. + * This allows detecting the presence of this field since older versions of + * the EC codebase would simply return 0xff to that unknown address. Check + * FEATURES0 != 0xff (or FEATURES0[0] == 0) to make sure that the other bits + * are valid. + */ +#define EC_ACPI_MEM_DEVICE_FEATURES0 0x0a +#define EC_ACPI_MEM_DEVICE_FEATURES1 0x0b +#define EC_ACPI_MEM_DEVICE_FEATURES2 0x0c +#define EC_ACPI_MEM_DEVICE_FEATURES3 0x0d +#define EC_ACPI_MEM_DEVICE_FEATURES4 0x0e +#define EC_ACPI_MEM_DEVICE_FEATURES5 0x0f +#define EC_ACPI_MEM_DEVICE_FEATURES6 0x10 +#define EC_ACPI_MEM_DEVICE_FEATURES7 0x11 + +#define EC_ACPI_MEM_BATTERY_INDEX 0x12 + +/* + * USB Port Power. Each bit indicates whether the corresponding USB ports' power + * is enabled (1) or disabled (0). + * bit 0 USB port ID 0 + * ... + * bit 7 USB port ID 7 + */ +#define EC_ACPI_MEM_USB_PORT_POWER 0x13 + +/* + * ACPI addresses 0x20 - 0xff map to EC_MEMMAP offset 0x00 - 0xdf. This data + * is read-only from the AP. Added in EC_ACPI_MEM_VERSION 2. + */ +#define EC_ACPI_MEM_MAPPED_BEGIN 0x20 +#define EC_ACPI_MEM_MAPPED_SIZE 0xe0 + +/* Current version of ACPI memory address space */ +#define EC_ACPI_MEM_VERSION_CURRENT 2 + + /* * This header file is used in coreboot both in C and ACPI code. The ACPI code * is pre-processed to handle constants but the ASL compiler is unable to * handle actual C code so keep it separate. */ -#ifndef __ACPI__ + + +/* + * Attributes for EC request and response packets. Just defining __packed + * results in inefficient assembly code on ARM, if the structure is actually + * 32-bit aligned, as it should be for all buffers. + * + * Be very careful when adding these to existing structures. They will round + * up the structure size to the specified boundary. + * + * Also be very careful to make that if a structure is included in some other + * parent structure that the alignment will still be true given the packing of + * the parent structure. This is particularly important if the sub-structure + * will be passed as a pointer to another function, since that function will + * not know about the misaligment caused by the parent structure's packing. + * + * Also be very careful using __packed - particularly when nesting non-packed + * structures inside packed ones. In fact, DO NOT use __packed directly; + * always use one of these attributes. + * + * Once everything is annotated properly, the following search strings should + * not return ANY matches in this file other than right here: + * + * "__packed" - generates inefficient code; all sub-structs must also be packed + * + * "struct [^_]" - all structs should be annotated, except for structs that are + * members of other structs/unions (and their original declarations should be + * annotated). + */ /* - * Define __packed if someone hasn't beat us to it. Linux kernel style - * checking prefers __packed over __attribute__((packed)). + * Packed structures make no assumption about alignment, so they do inefficient + * byte-wise reads. */ -#ifndef __packed -#define __packed __attribute__((packed)) -#endif +#define __ec_align1 __packed +#define __ec_align2 __packed +#define __ec_align4 __packed +#define __ec_align_size1 __packed +#define __ec_align_offset1 __packed +#define __ec_align_offset2 __packed +#define __ec_todo_packed __packed +#define __ec_todo_unpacked + /* LPC command status byte masks */ /* EC has written a byte in the data register and host hasn't read it yet */ @@ -198,7 +439,7 @@ #define EC_LPC_STATUS_PROCESSING 0x04 /* Last write to EC was a command, not data */ #define EC_LPC_STATUS_LAST_CMD 0x08 -/* EC is in burst mode. Unsupported by Chrome EC, so this bit is never set */ +/* EC is in burst mode */ #define EC_LPC_STATUS_BURST_MODE 0x10 /* SCI event is pending (requesting SCI query) */ #define EC_LPC_STATUS_SCI_PENDING 0x20 @@ -214,7 +455,10 @@ #define EC_LPC_STATUS_BUSY_MASK \ (EC_LPC_STATUS_FROM_HOST | EC_LPC_STATUS_PROCESSING) -/* Host command response codes */ +/* + * Host command response codes (16-bit). Note that response codes should be + * stored in a uint16_t rather than directly in a value of this type. + */ enum ec_status { EC_RES_SUCCESS = 0, EC_RES_INVALID_COMMAND = 1, @@ -230,7 +474,13 @@ enum ec_status { EC_RES_OVERFLOW = 11, /* Table / data overflow */ EC_RES_INVALID_HEADER = 12, /* Header contains invalid data */ EC_RES_REQUEST_TRUNCATED = 13, /* Didn't get the entire request */ - EC_RES_RESPONSE_TOO_BIG = 14 /* Response was too big to handle */ + EC_RES_RESPONSE_TOO_BIG = 14, /* Response was too big to handle */ + EC_RES_BUS_ERROR = 15, /* Communications bus error */ + EC_RES_BUSY = 16, /* Up but too busy. Should retry */ + EC_RES_INVALID_HEADER_VERSION = 17, /* Header version invalid */ + EC_RES_INVALID_HEADER_CRC = 18, /* Header CRC invalid */ + EC_RES_INVALID_DATA_CRC = 19, /* Data CRC invalid */ + EC_RES_DUP_UNAVAILABLE = 20, /* Can't resend response */ }; /* @@ -250,7 +500,8 @@ enum host_event_code { EC_HOST_EVENT_BATTERY_CRITICAL = 7, EC_HOST_EVENT_BATTERY = 8, EC_HOST_EVENT_THERMAL_THRESHOLD = 9, - EC_HOST_EVENT_THERMAL_OVERLOAD = 10, + /* Event generated by a device attached to the EC */ + EC_HOST_EVENT_DEVICE = 10, EC_HOST_EVENT_THERMAL = 11, EC_HOST_EVENT_USB_CHARGER = 12, EC_HOST_EVENT_KEY_PRESSED = 13, @@ -277,15 +528,34 @@ enum host_event_code { EC_HOST_EVENT_HANG_DETECT = 20, /* Hang detect logic detected a hang and warm rebooted the AP */ EC_HOST_EVENT_HANG_REBOOT = 21, + /* PD MCU triggering host event */ EC_HOST_EVENT_PD_MCU = 22, - /* EC desires to change state of host-controlled USB mux */ - EC_HOST_EVENT_USB_MUX = 28, + /* Battery Status flags have changed */ + EC_HOST_EVENT_BATTERY_STATUS = 23, + + /* EC encountered a panic, triggering a reset */ + EC_HOST_EVENT_PANIC = 24, + + /* Keyboard fastboot combo has been pressed */ + EC_HOST_EVENT_KEYBOARD_FASTBOOT = 25, /* EC RTC event occurred */ EC_HOST_EVENT_RTC = 26, + /* Emulate MKBP event */ + EC_HOST_EVENT_MKBP = 27, + + /* EC desires to change state of host-controlled USB mux */ + EC_HOST_EVENT_USB_MUX = 28, + + /* TABLET/LAPTOP mode or detachable base attach/detach event */ + EC_HOST_EVENT_MODE_CHANGE = 29, + + /* Keyboard recovery combo with hardware reinitialization */ + EC_HOST_EVENT_KEYBOARD_RECOVERY_HW_REINIT = 30, + /* * The high bit of the event mask is not used as a host event code. If * it reads back as set, then the entire event mask should be @@ -296,7 +566,7 @@ enum host_event_code { EC_HOST_EVENT_INVALID = 32 }; /* Host event mask */ -#define EC_HOST_EVENT_MASK(event_code) (1UL << ((event_code) - 1)) +#define EC_HOST_EVENT_MASK(event_code) BIT_ULL((event_code) - 1) /** * struct ec_lpc_host_args - Arguments at EC_LPC_ADDR_HOST_ARGS @@ -311,7 +581,7 @@ struct ec_lpc_host_args { uint8_t command_version; uint8_t data_size; uint8_t checksum; -} __packed; +} __ec_align4; /* Flags for ec_lpc_host_args.flags */ /* @@ -321,7 +591,7 @@ struct ec_lpc_host_args { * If EC gets a command and this flag is not set, this is an old-style command. * Command version is 0 and params from host are at EC_LPC_ADDR_OLD_PARAM with * unknown length. EC must respond with an old-style response (that is, - * withouth setting EC_HOST_ARGS_FLAG_TO_HOST). + * without setting EC_HOST_ARGS_FLAG_TO_HOST). */ #define EC_HOST_ARGS_FLAG_FROM_HOST 0x01 /* @@ -482,7 +752,7 @@ struct ec_host_request { uint8_t command_version; uint8_t reserved; uint16_t data_len; -} __packed; +} __ec_align4; #define EC_HOST_RESPONSE_VERSION 3 @@ -501,18 +771,151 @@ struct ec_host_response { uint16_t result; uint16_t data_len; uint16_t reserved; -} __packed; +} __ec_align4; + +/*****************************************************************************/ + +/* + * Host command protocol V4. + * + * Packets always start with a request or response header. They are followed + * by data_len bytes of data. If the data_crc_present flag is set, the data + * bytes are followed by a CRC-8 of that data, using using x^8 + x^2 + x + 1 + * polynomial. + * + * Host algorithm when sending a request q: + * + * 101) tries_left=(some value, e.g. 3); + * 102) q.seq_num++ + * 103) q.seq_dup=0 + * 104) Calculate q.header_crc. + * 105) Send request q to EC. + * 106) Wait for response r. Go to 201 if received or 301 if timeout. + * + * 201) If r.struct_version != 4, go to 301. + * 202) If r.header_crc mismatches calculated CRC for r header, go to 301. + * 203) If r.data_crc_present and r.data_crc mismatches, go to 301. + * 204) If r.seq_num != q.seq_num, go to 301. + * 205) If r.seq_dup == q.seq_dup, return success. + * 207) If r.seq_dup == 1, go to 301. + * 208) Return error. + * + * 301) If --tries_left <= 0, return error. + * 302) If q.seq_dup == 1, go to 105. + * 303) q.seq_dup = 1 + * 304) Go to 104. + * + * EC algorithm when receiving a request q. + * EC has response buffer r, error buffer e. + * + * 101) If q.struct_version != 4, set e.result = EC_RES_INVALID_HEADER_VERSION + * and go to 301 + * 102) If q.header_crc mismatches calculated CRC, set e.result = + * EC_RES_INVALID_HEADER_CRC and go to 301 + * 103) If q.data_crc_present, calculate data CRC. If that mismatches the CRC + * byte at the end of the packet, set e.result = EC_RES_INVALID_DATA_CRC + * and go to 301. + * 104) If q.seq_dup == 0, go to 201. + * 105) If q.seq_num != r.seq_num, go to 201. + * 106) If q.seq_dup == r.seq_dup, go to 205, else go to 203. + * + * 201) Process request q into response r. + * 202) r.seq_num = q.seq_num + * 203) r.seq_dup = q.seq_dup + * 204) Calculate r.header_crc + * 205) If r.data_len > 0 and data is no longer available, set e.result = + * EC_RES_DUP_UNAVAILABLE and go to 301. + * 206) Send response r. + * + * 301) e.seq_num = q.seq_num + * 302) e.seq_dup = q.seq_dup + * 303) Calculate e.header_crc. + * 304) Send error response e. + */ + +/* Version 4 request from host */ +struct ec_host_request4 { + /* + * bits 0-3: struct_version: Structure version (=4) + * bit 4: is_response: Is response (=0) + * bits 5-6: seq_num: Sequence number + * bit 7: seq_dup: Sequence duplicate flag + */ + uint8_t fields0; + + /* + * bits 0-4: command_version: Command version + * bits 5-6: Reserved (set 0, ignore on read) + * bit 7: data_crc_present: Is data CRC present after data + */ + uint8_t fields1; + + /* Command code (EC_CMD_*) */ + uint16_t command; + + /* Length of data which follows this header (not including data CRC) */ + uint16_t data_len; + + /* Reserved (set 0, ignore on read) */ + uint8_t reserved; + + /* CRC-8 of above fields, using x^8 + x^2 + x + 1 polynomial */ + uint8_t header_crc; +} __ec_align4; + +/* Version 4 response from EC */ +struct ec_host_response4 { + /* + * bits 0-3: struct_version: Structure version (=4) + * bit 4: is_response: Is response (=1) + * bits 5-6: seq_num: Sequence number + * bit 7: seq_dup: Sequence duplicate flag + */ + uint8_t fields0; + + /* + * bits 0-6: Reserved (set 0, ignore on read) + * bit 7: data_crc_present: Is data CRC present after data + */ + uint8_t fields1; + + /* Result code (EC_RES_*) */ + uint16_t result; + + /* Length of data which follows this header (not including data CRC) */ + uint16_t data_len; + + /* Reserved (set 0, ignore on read) */ + uint8_t reserved; + + /* CRC-8 of above fields, using x^8 + x^2 + x + 1 polynomial */ + uint8_t header_crc; +} __ec_align4; + +/* Fields in fields0 byte */ +#define EC_PACKET4_0_STRUCT_VERSION_MASK 0x0f +#define EC_PACKET4_0_IS_RESPONSE_MASK 0x10 +#define EC_PACKET4_0_SEQ_NUM_SHIFT 5 +#define EC_PACKET4_0_SEQ_NUM_MASK 0x60 +#define EC_PACKET4_0_SEQ_DUP_MASK 0x80 + +/* Fields in fields1 byte */ +#define EC_PACKET4_1_COMMAND_VERSION_MASK 0x1f /* (request only) */ +#define EC_PACKET4_1_DATA_CRC_PRESENT_MASK 0x80 /*****************************************************************************/ /* * Notes on commands: * * Each command is an 16-bit command value. Commands which take params or - * return response data specify structs for that data. If no struct is + * return response data specify structures for that data. If no structure is * specified, the command does not input or output data, respectively. * Parameter/response length is implicit in the structs. Some underlying * communication protocols (I2C, SPI) may add length or checksum headers, but * those are implementation-dependent and not defined here. + * + * All commands MUST be #defined to be 4-digit UPPER CASE hex values + * (e.g., 0x00AB, not 0xab) for CONFIG_HOSTCMD_SECTION_SORTED to work. */ /*****************************************************************************/ @@ -522,7 +925,7 @@ struct ec_host_response { * Get protocol version, used to deal with non-backward compatible protocol * changes. */ -#define EC_CMD_PROTO_VERSION 0x00 +#define EC_CMD_PROTO_VERSION 0x0000 /** * struct ec_response_proto_version - Response to the proto version command. @@ -530,13 +933,13 @@ struct ec_host_response { */ struct ec_response_proto_version { uint32_t version; -} __packed; +} __ec_align4; /* * Hello. This is a simple command to test the EC is responsive to * commands. */ -#define EC_CMD_HELLO 0x01 +#define EC_CMD_HELLO 0x0001 /** * struct ec_params_hello - Parameters to the hello command. @@ -544,7 +947,7 @@ struct ec_response_proto_version { */ struct ec_params_hello { uint32_t in_data; -} __packed; +} __ec_align4; /** * struct ec_response_hello - Response to the hello command. @@ -552,10 +955,10 @@ struct ec_params_hello { */ struct ec_response_hello { uint32_t out_data; -} __packed; +} __ec_align4; /* Get version number */ -#define EC_CMD_GET_VERSION 0x02 +#define EC_CMD_GET_VERSION 0x0002 enum ec_current_image { EC_IMAGE_UNKNOWN = 0, @@ -575,10 +978,10 @@ struct ec_response_get_version { char version_string_rw[32]; char reserved[32]; uint32_t current_image; -} __packed; +} __ec_align4; /* Read test */ -#define EC_CMD_READ_TEST 0x03 +#define EC_CMD_READ_TEST 0x0003 /** * struct ec_params_read_test - Parameters for the read test command. @@ -588,7 +991,7 @@ struct ec_response_get_version { struct ec_params_read_test { uint32_t offset; uint32_t size; -} __packed; +} __ec_align4; /** * struct ec_response_read_test - Response to the read test command. @@ -596,17 +999,17 @@ struct ec_params_read_test { */ struct ec_response_read_test { uint32_t data[32]; -} __packed; +} __ec_align4; /* * Get build information * * Response is null-terminated string. */ -#define EC_CMD_GET_BUILD_INFO 0x04 +#define EC_CMD_GET_BUILD_INFO 0x0004 /* Get chip info */ -#define EC_CMD_GET_CHIP_INFO 0x05 +#define EC_CMD_GET_CHIP_INFO 0x0005 /** * struct ec_response_get_chip_info - Response to the get chip info command. @@ -618,10 +1021,10 @@ struct ec_response_get_chip_info { char vendor[32]; char name[32]; char revision[32]; -} __packed; +} __ec_align4; /* Get board HW version */ -#define EC_CMD_GET_BOARD_VERSION 0x06 +#define EC_CMD_GET_BOARD_VERSION 0x0006 /** * struct ec_response_board_version - Response to the board version command. @@ -629,7 +1032,7 @@ struct ec_response_get_chip_info { */ struct ec_response_board_version { uint16_t board_version; -} __packed; +} __ec_align2; /* * Read memory-mapped data. @@ -639,7 +1042,7 @@ struct ec_response_board_version { * * Response is params.size bytes of data. */ -#define EC_CMD_READ_MEMMAP 0x07 +#define EC_CMD_READ_MEMMAP 0x0007 /** * struct ec_params_read_memmap - Parameters for the read memory map command. @@ -649,10 +1052,10 @@ struct ec_response_board_version { struct ec_params_read_memmap { uint8_t offset; uint8_t size; -} __packed; +} __ec_align1; /* Read versions supported for a command */ -#define EC_CMD_GET_CMD_VERSIONS 0x08 +#define EC_CMD_GET_CMD_VERSIONS 0x0008 /** * struct ec_params_get_cmd_versions - Parameters for the get command versions. @@ -660,7 +1063,7 @@ struct ec_params_read_memmap { */ struct ec_params_get_cmd_versions { uint8_t cmd; -} __packed; +} __ec_align1; /** * struct ec_params_get_cmd_versions_v1 - Parameters for the get command @@ -669,7 +1072,7 @@ struct ec_params_get_cmd_versions { */ struct ec_params_get_cmd_versions_v1 { uint16_t cmd; -} __packed; +} __ec_align2; /** * struct ec_response_get_cmd_version - Response to the get command versions. @@ -678,20 +1081,20 @@ struct ec_params_get_cmd_versions_v1 { */ struct ec_response_get_cmd_versions { uint32_t version_mask; -} __packed; +} __ec_align4; /* - * Check EC communcations status (busy). This is needed on i2c/spi but not + * Check EC communications status (busy). This is needed on i2c/spi but not * on lpc since it has its own out-of-band busy indicator. * * lpc must read the status from the command register. Attempting this on * lpc will overwrite the args/parameter space and corrupt its data. */ -#define EC_CMD_GET_COMMS_STATUS 0x09 +#define EC_CMD_GET_COMMS_STATUS 0x0009 /* Avoid using ec_status which is for return values */ enum ec_comms_status { - EC_COMMS_STATUS_PROCESSING = 1 << 0, /* Processing cmd */ + EC_COMMS_STATUS_PROCESSING = BIT(0), /* Processing cmd */ }; /** @@ -701,29 +1104,29 @@ enum ec_comms_status { */ struct ec_response_get_comms_status { uint32_t flags; /* Mask of enum ec_comms_status */ -} __packed; +} __ec_align4; /* Fake a variety of responses, purely for testing purposes. */ -#define EC_CMD_TEST_PROTOCOL 0x0a +#define EC_CMD_TEST_PROTOCOL 0x000A /* Tell the EC what to send back to us. */ struct ec_params_test_protocol { uint32_t ec_result; uint32_t ret_len; uint8_t buf[32]; -} __packed; +} __ec_align4; /* Here it comes... */ struct ec_response_test_protocol { uint8_t buf[32]; -} __packed; +} __ec_align4; -/* Get prococol information */ -#define EC_CMD_GET_PROTOCOL_INFO 0x0b +/* Get protocol information */ +#define EC_CMD_GET_PROTOCOL_INFO 0x000B /* Flags for ec_response_get_protocol_info.flags */ /* EC_RES_IN_PROGRESS may be returned if a command is slow */ -#define EC_PROTOCOL_INFO_IN_PROGRESS_SUPPORTED (1 << 0) +#define EC_PROTOCOL_INFO_IN_PROGRESS_SUPPORTED BIT(0) /** * struct ec_response_get_protocol_info - Response to the get protocol info. @@ -739,7 +1142,7 @@ struct ec_response_get_protocol_info { uint16_t max_request_packet_size; uint16_t max_response_packet_size; uint32_t flags; -} __packed; +} __ec_align4; /*****************************************************************************/ @@ -757,19 +1160,19 @@ struct ec_response_get_protocol_info { struct ec_params_get_set_value { uint32_t flags; uint32_t value; -} __packed; +} __ec_align4; struct ec_response_get_set_value { uint32_t flags; uint32_t value; -} __packed; +} __ec_align4; -/* More than one command can use these structs to get/set paramters. */ -#define EC_CMD_GSV_PAUSE_IN_S5 0x0c +/* More than one command can use these structs to get/set parameters. */ +#define EC_CMD_GSV_PAUSE_IN_S5 0x000C /*****************************************************************************/ /* List the features supported by the firmware */ -#define EC_CMD_GET_FEATURES 0x0d +#define EC_CMD_GET_FEATURES 0x000D /* Supported features */ enum ec_feature_code { @@ -876,24 +1279,36 @@ enum ec_feature_code { EC_FEATURE_REFINED_TABLET_MODE_HYSTERESIS = 37, /* EC supports audio codec. */ EC_FEATURE_AUDIO_CODEC = 38, - /* EC Supports SCP. */ + /* The MCU is a System Companion Processor (SCP). */ EC_FEATURE_SCP = 39, /* The MCU is an Integrated Sensor Hub */ EC_FEATURE_ISH = 40, }; -#define EC_FEATURE_MASK_0(event_code) (1UL << (event_code % 32)) -#define EC_FEATURE_MASK_1(event_code) (1UL << (event_code - 32)) +#define EC_FEATURE_MASK_0(event_code) BIT(event_code % 32) +#define EC_FEATURE_MASK_1(event_code) BIT(event_code - 32) struct ec_response_get_features { uint32_t flags[2]; -} __packed; +} __ec_align4; + +/*****************************************************************************/ +/* Get the board's SKU ID from EC */ +#define EC_CMD_GET_SKU_ID 0x000E + +/* Set SKU ID from AP */ +#define EC_CMD_SET_SKU_ID 0x000F + +struct ec_sku_id_info { + uint32_t sku_id; +} __ec_align4; /*****************************************************************************/ /* Flash commands */ /* Get flash info */ -#define EC_CMD_FLASH_INFO 0x10 +#define EC_CMD_FLASH_INFO 0x0010 +#define EC_VER_FLASH_INFO 2 /** * struct ec_response_flash_info - Response to the flash info command. @@ -912,11 +1327,22 @@ struct ec_response_flash_info { uint32_t write_block_size; uint32_t erase_block_size; uint32_t protect_block_size; -} __packed; +} __ec_align4; -/* Flags for version 1+ flash info command */ -/* EC flash erases bits to 0 instead of 1 */ -#define EC_FLASH_INFO_ERASE_TO_0 (1 << 0) +/* + * Flags for version 1+ flash info command + * EC flash erases bits to 0 instead of 1. + */ +#define EC_FLASH_INFO_ERASE_TO_0 BIT(0) + +/* + * Flash must be selected for read/write/erase operations to succeed. This may + * be necessary on a chip where write/erase can be corrupted by other board + * activity, or where the chip needs to enable some sort of programming voltage, + * or where the read/write/erase operations require cleanly suspending other + * chip functionality. + */ +#define EC_FLASH_INFO_SELECT_REQUIRED BIT(1) /** * struct ec_response_flash_info_1 - Response to the flash info v1 command. @@ -938,7 +1364,14 @@ struct ec_response_flash_info { * fields following. * * gcc anonymous structs don't seem to get along with the __packed directive; - * if they did we'd define the version 0 struct as a sub-struct of this one. + * if they did we'd define the version 0 structure as a sub-structure of this + * one. + * + * Version 2 supports flash banks of different sizes: + * The caller specified the number of banks it has preallocated + * (num_banks_desc) + * The EC returns the number of banks describing the flash memory. + * It adds banks descriptions up to num_banks_desc. */ struct ec_response_flash_info_1 { /* Version 0 fields; see above for description */ @@ -950,14 +1383,50 @@ struct ec_response_flash_info_1 { /* Version 1 adds these fields: */ uint32_t write_ideal_size; uint32_t flags; -} __packed; +} __ec_align4; + +struct ec_params_flash_info_2 { + /* Number of banks to describe */ + uint16_t num_banks_desc; + /* Reserved; set 0; ignore on read */ + uint8_t reserved[2]; +} __ec_align4; + +struct ec_flash_bank { + /* Number of sector is in this bank. */ + uint16_t count; + /* Size in power of 2 of each sector (8 --> 256 bytes) */ + uint8_t size_exp; + /* Minimal write size for the sectors in this bank */ + uint8_t write_size_exp; + /* Erase size for the sectors in this bank */ + uint8_t erase_size_exp; + /* Size for write protection, usually identical to erase size. */ + uint8_t protect_size_exp; + /* Reserved; set 0; ignore on read */ + uint8_t reserved[2]; +}; + +struct ec_response_flash_info_2 { + /* Total flash in the EC. */ + uint32_t flash_size; + /* Flags; see EC_FLASH_INFO_* */ + uint32_t flags; + /* Maximum size to use to send data to write to the EC. */ + uint32_t write_ideal_size; + /* Number of banks present in the EC. */ + uint16_t num_banks_total; + /* Number of banks described in banks array. */ + uint16_t num_banks_desc; + struct ec_flash_bank banks[0]; +} __ec_align4; /* * Read flash * * Response is params.size bytes of data. */ -#define EC_CMD_FLASH_READ 0x11 +#define EC_CMD_FLASH_READ 0x0011 /** * struct ec_params_flash_read - Parameters for the flash read command. @@ -967,10 +1436,10 @@ struct ec_response_flash_info_1 { struct ec_params_flash_read { uint32_t offset; uint32_t size; -} __packed; +} __ec_align4; /* Write flash */ -#define EC_CMD_FLASH_WRITE 0x12 +#define EC_CMD_FLASH_WRITE 0x0012 #define EC_VER_FLASH_WRITE 1 /* Version 0 of the flash command supported only 64 bytes of data */ @@ -985,20 +1454,57 @@ struct ec_params_flash_write { uint32_t offset; uint32_t size; /* Followed by data to write */ -} __packed; +} __ec_align4; /* Erase flash */ -#define EC_CMD_FLASH_ERASE 0x13 +#define EC_CMD_FLASH_ERASE 0x0013 /** - * struct ec_params_flash_erase - Parameters for the flash erase command. + * struct ec_params_flash_erase - Parameters for the flash erase command, v0. * @offset: Byte offset to erase. * @size: Size to erase in bytes. */ struct ec_params_flash_erase { uint32_t offset; uint32_t size; -} __packed; +} __ec_align4; + +/* + * v1 add async erase: + * subcommands can returns: + * EC_RES_SUCCESS : erased (see ERASE_SECTOR_ASYNC case below). + * EC_RES_INVALID_PARAM : offset/size are not aligned on a erase boundary. + * EC_RES_ERROR : other errors. + * EC_RES_BUSY : an existing erase operation is in progress. + * EC_RES_ACCESS_DENIED: Trying to erase running image. + * + * When ERASE_SECTOR_ASYNC returns EC_RES_SUCCESS, the operation is just + * properly queued. The user must call ERASE_GET_RESULT subcommand to get + * the proper result. + * When ERASE_GET_RESULT returns EC_RES_BUSY, the caller must wait and send + * ERASE_GET_RESULT again to get the result of ERASE_SECTOR_ASYNC. + * ERASE_GET_RESULT command may timeout on EC where flash access is not + * permitted while erasing. (For instance, STM32F4). + */ +enum ec_flash_erase_cmd { + FLASH_ERASE_SECTOR, /* Erase and wait for result */ + FLASH_ERASE_SECTOR_ASYNC, /* Erase and return immediately. */ + FLASH_ERASE_GET_RESULT, /* Ask for last erase result */ +}; + +/** + * struct ec_params_flash_erase_v1 - Parameters for the flash erase command, v1. + * @cmd: One of ec_flash_erase_cmd. + * @reserved: Pad byte; currently always contains 0. + * @flag: No flags defined yet; set to 0. + * @params: Same as v0 parameters. + */ +struct ec_params_flash_erase_v1 { + uint8_t cmd; + uint8_t reserved; + uint16_t flag; + struct ec_params_flash_erase params; +} __ec_align4; /* * Get/set flash protection. @@ -1010,31 +1516,40 @@ struct ec_params_flash_erase { * * If mask=0, simply returns the current flags state. */ -#define EC_CMD_FLASH_PROTECT 0x15 +#define EC_CMD_FLASH_PROTECT 0x0015 #define EC_VER_FLASH_PROTECT 1 /* Command version 1 */ /* Flags for flash protection */ /* RO flash code protected when the EC boots */ -#define EC_FLASH_PROTECT_RO_AT_BOOT (1 << 0) +#define EC_FLASH_PROTECT_RO_AT_BOOT BIT(0) /* * RO flash code protected now. If this bit is set, at-boot status cannot * be changed. */ -#define EC_FLASH_PROTECT_RO_NOW (1 << 1) +#define EC_FLASH_PROTECT_RO_NOW BIT(1) /* Entire flash code protected now, until reboot. */ -#define EC_FLASH_PROTECT_ALL_NOW (1 << 2) +#define EC_FLASH_PROTECT_ALL_NOW BIT(2) /* Flash write protect GPIO is asserted now */ -#define EC_FLASH_PROTECT_GPIO_ASSERTED (1 << 3) +#define EC_FLASH_PROTECT_GPIO_ASSERTED BIT(3) /* Error - at least one bank of flash is stuck locked, and cannot be unlocked */ -#define EC_FLASH_PROTECT_ERROR_STUCK (1 << 4) +#define EC_FLASH_PROTECT_ERROR_STUCK BIT(4) /* * Error - flash protection is in inconsistent state. At least one bank of * flash which should be protected is not protected. Usually fixed by * re-requesting the desired flags, or by a hard reset if that fails. */ -#define EC_FLASH_PROTECT_ERROR_INCONSISTENT (1 << 5) -/* Entile flash code protected when the EC boots */ -#define EC_FLASH_PROTECT_ALL_AT_BOOT (1 << 6) +#define EC_FLASH_PROTECT_ERROR_INCONSISTENT BIT(5) +/* Entire flash code protected when the EC boots */ +#define EC_FLASH_PROTECT_ALL_AT_BOOT BIT(6) +/* RW flash code protected when the EC boots */ +#define EC_FLASH_PROTECT_RW_AT_BOOT BIT(7) +/* RW flash code protected now. */ +#define EC_FLASH_PROTECT_RW_NOW BIT(8) +/* Rollback information flash region protected when the EC boots */ +#define EC_FLASH_PROTECT_ROLLBACK_AT_BOOT BIT(9) +/* Rollback information flash region protected now */ +#define EC_FLASH_PROTECT_ROLLBACK_NOW BIT(10) + /** * struct ec_params_flash_protect - Parameters for the flash protect command. @@ -1044,7 +1559,7 @@ struct ec_params_flash_erase { struct ec_params_flash_protect { uint32_t mask; uint32_t flags; -} __packed; +} __ec_align4; /** * struct ec_response_flash_protect - Response to the flash protect command. @@ -1059,7 +1574,7 @@ struct ec_response_flash_protect { uint32_t flags; uint32_t valid_flags; uint32_t writable_flags; -} __packed; +} __ec_align4; /* * Note: commands 0x14 - 0x19 version 0 were old commands to get/set flash @@ -1067,22 +1582,37 @@ struct ec_response_flash_protect { */ /* Get the region offset/size */ -#define EC_CMD_FLASH_REGION_INFO 0x16 +#define EC_CMD_FLASH_REGION_INFO 0x0016 #define EC_VER_FLASH_REGION_INFO 1 enum ec_flash_region { /* Region which holds read-only EC image */ EC_FLASH_REGION_RO = 0, - /* Region which holds rewritable EC image */ - EC_FLASH_REGION_RW, + /* + * Region which holds active RW image. 'Active' is different from + * 'running'. Active means 'scheduled-to-run'. Since RO image always + * scheduled to run, active/non-active applies only to RW images (for + * the same reason 'update' applies only to RW images. It's a state of + * an image on a flash. Running image can be RO, RW_A, RW_B but active + * image can only be RW_A or RW_B. In recovery mode, an active RW image + * doesn't enter 'running' state but it's still active on a flash. + */ + EC_FLASH_REGION_ACTIVE, /* * Region which should be write-protected in the factory (a superset of * EC_FLASH_REGION_RO) */ EC_FLASH_REGION_WP_RO, + /* Region which holds updatable (non-active) RW image */ + EC_FLASH_REGION_UPDATE, /* Number of regions */ EC_FLASH_REGION_COUNT, }; +/* + * 'RW' is vague if there are multiple RW images; we mean the active one, + * so the old constant is deprecated. + */ +#define EC_FLASH_REGION_RW EC_FLASH_REGION_ACTIVE /** * struct ec_params_flash_region_info - Parameters for the flash region info @@ -1091,15 +1621,15 @@ enum ec_flash_region { */ struct ec_params_flash_region_info { uint32_t region; -} __packed; +} __ec_align4; struct ec_response_flash_region_info { uint32_t offset; uint32_t size; -} __packed; +} __ec_align4; /* Read/write VbNvContext */ -#define EC_CMD_VBNV_CONTEXT 0x17 +#define EC_CMD_VBNV_CONTEXT 0x0017 #define EC_VER_VBNV_CONTEXT 1 #define EC_VBNV_BLOCK_SIZE 16 @@ -1111,52 +1641,99 @@ enum ec_vbnvcontext_op { struct ec_params_vbnvcontext { uint32_t op; uint8_t block[EC_VBNV_BLOCK_SIZE]; -} __packed; +} __ec_align4; struct ec_response_vbnvcontext { uint8_t block[EC_VBNV_BLOCK_SIZE]; -} __packed; +} __ec_align4; + + +/* Get SPI flash information */ +#define EC_CMD_FLASH_SPI_INFO 0x0018 + +struct ec_response_flash_spi_info { + /* JEDEC info from command 0x9F (manufacturer, memory type, size) */ + uint8_t jedec[3]; + + /* Pad byte; currently always contains 0 */ + uint8_t reserved0; + + /* Manufacturer / device ID from command 0x90 */ + uint8_t mfr_dev_id[2]; + + /* Status registers from command 0x05 and 0x35 */ + uint8_t sr1, sr2; +} __ec_align1; + + +/* Select flash during flash operations */ +#define EC_CMD_FLASH_SELECT 0x0019 + +/** + * struct ec_params_flash_select - Parameters for the flash select command. + * @select: 1 to select flash, 0 to deselect flash + */ +struct ec_params_flash_select { + uint8_t select; +} __ec_align4; + /*****************************************************************************/ /* PWM commands */ /* Get fan target RPM */ -#define EC_CMD_PWM_GET_FAN_TARGET_RPM 0x20 +#define EC_CMD_PWM_GET_FAN_TARGET_RPM 0x0020 struct ec_response_pwm_get_fan_rpm { uint32_t rpm; -} __packed; +} __ec_align4; /* Set target fan RPM */ -#define EC_CMD_PWM_SET_FAN_TARGET_RPM 0x21 +#define EC_CMD_PWM_SET_FAN_TARGET_RPM 0x0021 -struct ec_params_pwm_set_fan_target_rpm { +/* Version 0 of input params */ +struct ec_params_pwm_set_fan_target_rpm_v0 { uint32_t rpm; -} __packed; +} __ec_align4; + +/* Version 1 of input params */ +struct ec_params_pwm_set_fan_target_rpm_v1 { + uint32_t rpm; + uint8_t fan_idx; +} __ec_align_size1; /* Get keyboard backlight */ -#define EC_CMD_PWM_GET_KEYBOARD_BACKLIGHT 0x22 +/* OBSOLETE - Use EC_CMD_PWM_SET_DUTY */ +#define EC_CMD_PWM_GET_KEYBOARD_BACKLIGHT 0x0022 struct ec_response_pwm_get_keyboard_backlight { uint8_t percent; uint8_t enabled; -} __packed; +} __ec_align1; /* Set keyboard backlight */ -#define EC_CMD_PWM_SET_KEYBOARD_BACKLIGHT 0x23 +/* OBSOLETE - Use EC_CMD_PWM_SET_DUTY */ +#define EC_CMD_PWM_SET_KEYBOARD_BACKLIGHT 0x0023 struct ec_params_pwm_set_keyboard_backlight { uint8_t percent; -} __packed; +} __ec_align1; /* Set target fan PWM duty cycle */ -#define EC_CMD_PWM_SET_FAN_DUTY 0x24 +#define EC_CMD_PWM_SET_FAN_DUTY 0x0024 -struct ec_params_pwm_set_fan_duty { +/* Version 0 of input params */ +struct ec_params_pwm_set_fan_duty_v0 { uint32_t percent; -} __packed; +} __ec_align4; -#define EC_CMD_PWM_SET_DUTY 0x25 +/* Version 1 of input params */ +struct ec_params_pwm_set_fan_duty_v1 { + uint32_t percent; + uint8_t fan_idx; +} __ec_align_size1; + +#define EC_CMD_PWM_SET_DUTY 0x0025 /* 16 bit duty cycle, 0xffff = 100% */ #define EC_PWM_MAX_DUTY 0xffff @@ -1174,18 +1751,18 @@ struct ec_params_pwm_set_duty { uint16_t duty; /* Duty cycle, EC_PWM_MAX_DUTY = 100% */ uint8_t pwm_type; /* ec_pwm_type */ uint8_t index; /* Type-specific index, or 0 if unique */ -} __packed; +} __ec_align4; -#define EC_CMD_PWM_GET_DUTY 0x26 +#define EC_CMD_PWM_GET_DUTY 0x0026 struct ec_params_pwm_get_duty { uint8_t pwm_type; /* ec_pwm_type */ uint8_t index; /* Type-specific index, or 0 if unique */ -} __packed; +} __ec_align1; struct ec_response_pwm_get_duty { uint16_t duty; /* Duty cycle, EC_PWM_MAX_DUTY = 100% */ -} __packed; +} __ec_align2; /*****************************************************************************/ /* @@ -1194,11 +1771,11 @@ struct ec_response_pwm_get_duty { * into a subcommand. We'll make separate structs for subcommands with * different input args, so that we know how much to expect. */ -#define EC_CMD_LIGHTBAR_CMD 0x28 +#define EC_CMD_LIGHTBAR_CMD 0x0028 struct rgb_s { uint8_t r, g, b; -}; +} __ec_todo_unpacked; #define LB_BATTERY_LEVELS 4 @@ -1238,7 +1815,7 @@ struct lightbar_params_v0 { /* Color palette */ struct rgb_s color[8]; /* 0-3 are Google colors */ -} __packed; +} __ec_todo_packed; struct lightbar_params_v1 { /* Timing */ @@ -1251,7 +1828,10 @@ struct lightbar_params_v1 { int32_t s3_sleep_for; int32_t s3_ramp_up; int32_t s3_ramp_down; + int32_t s5_ramp_up; + int32_t s5_ramp_down; int32_t tap_tick_delay; + int32_t tap_gate_delay; int32_t tap_display_time; /* Tap-for-battery params */ @@ -1279,84 +1859,182 @@ struct lightbar_params_v1 { uint8_t s0_idx[2][LB_BATTERY_LEVELS]; /* AP is running */ uint8_t s3_idx[2][LB_BATTERY_LEVELS]; /* AP is sleeping */ + /* s5: single color pulse on inhibited power-up */ + uint8_t s5_idx; + /* Color palette */ struct rgb_s color[8]; /* 0-3 are Google colors */ -} __packed; +} __ec_todo_packed; -/* Lightbar program */ +/* Lightbar command params v2 + * crbug.com/467716 + * + * lightbar_parms_v1 was too big for i2c, therefore in v2, we split them up by + * logical groups to make it more manageable ( < 120 bytes). + * + * NOTE: Each of these groups must be less than 120 bytes. + */ + +struct lightbar_params_v2_timing { + /* Timing */ + int32_t google_ramp_up; + int32_t google_ramp_down; + int32_t s3s0_ramp_up; + int32_t s0_tick_delay[2]; /* AC=0/1 */ + int32_t s0a_tick_delay[2]; /* AC=0/1 */ + int32_t s0s3_ramp_down; + int32_t s3_sleep_for; + int32_t s3_ramp_up; + int32_t s3_ramp_down; + int32_t s5_ramp_up; + int32_t s5_ramp_down; + int32_t tap_tick_delay; + int32_t tap_gate_delay; + int32_t tap_display_time; +} __ec_todo_packed; + +struct lightbar_params_v2_tap { + /* Tap-for-battery params */ + uint8_t tap_pct_red; + uint8_t tap_pct_green; + uint8_t tap_seg_min_on; + uint8_t tap_seg_max_on; + uint8_t tap_seg_osc; + uint8_t tap_idx[3]; +} __ec_todo_packed; + +struct lightbar_params_v2_oscillation { + /* Oscillation */ + uint8_t osc_min[2]; /* AC=0/1 */ + uint8_t osc_max[2]; /* AC=0/1 */ + uint8_t w_ofs[2]; /* AC=0/1 */ +} __ec_todo_packed; + +struct lightbar_params_v2_brightness { + /* Brightness limits based on the backlight and AC. */ + uint8_t bright_bl_off_fixed[2]; /* AC=0/1 */ + uint8_t bright_bl_on_min[2]; /* AC=0/1 */ + uint8_t bright_bl_on_max[2]; /* AC=0/1 */ +} __ec_todo_packed; + +struct lightbar_params_v2_thresholds { + /* Battery level thresholds */ + uint8_t battery_threshold[LB_BATTERY_LEVELS - 1]; +} __ec_todo_packed; + +struct lightbar_params_v2_colors { + /* Map [AC][battery_level] to color index */ + uint8_t s0_idx[2][LB_BATTERY_LEVELS]; /* AP is running */ + uint8_t s3_idx[2][LB_BATTERY_LEVELS]; /* AP is sleeping */ + + /* s5: single color pulse on inhibited power-up */ + uint8_t s5_idx; + + /* Color palette */ + struct rgb_s color[8]; /* 0-3 are Google colors */ +} __ec_todo_packed; + +/* Lightbar program. */ #define EC_LB_PROG_LEN 192 struct lightbar_program { uint8_t size; uint8_t data[EC_LB_PROG_LEN]; -}; +} __ec_todo_unpacked; struct ec_params_lightbar { uint8_t cmd; /* Command (see enum lightbar_command) */ union { - struct { - /* no args */ - } dump, off, on, init, get_seq, get_params_v0, get_params_v1, - version, get_brightness, get_demo, suspend, resume; + /* + * The following commands have no args: + * + * dump, off, on, init, get_seq, get_params_v0, get_params_v1, + * version, get_brightness, get_demo, suspend, resume, + * get_params_v2_timing, get_params_v2_tap, get_params_v2_osc, + * get_params_v2_bright, get_params_v2_thlds, + * get_params_v2_colors + * + * Don't use an empty struct, because C++ hates that. + */ - struct { + struct __ec_todo_unpacked { uint8_t num; } set_brightness, seq, demo; - struct { + struct __ec_todo_unpacked { uint8_t ctrl, reg, value; } reg; - struct { + struct __ec_todo_unpacked { uint8_t led, red, green, blue; } set_rgb; - struct { + struct __ec_todo_unpacked { uint8_t led; } get_rgb; - struct { + struct __ec_todo_unpacked { uint8_t enable; } manual_suspend_ctrl; struct lightbar_params_v0 set_params_v0; struct lightbar_params_v1 set_params_v1; + + struct lightbar_params_v2_timing set_v2par_timing; + struct lightbar_params_v2_tap set_v2par_tap; + struct lightbar_params_v2_oscillation set_v2par_osc; + struct lightbar_params_v2_brightness set_v2par_bright; + struct lightbar_params_v2_thresholds set_v2par_thlds; + struct lightbar_params_v2_colors set_v2par_colors; + struct lightbar_program set_program; }; -} __packed; +} __ec_todo_packed; struct ec_response_lightbar { union { - struct { - struct { + struct __ec_todo_unpacked { + struct __ec_todo_unpacked { uint8_t reg; uint8_t ic0; uint8_t ic1; } vals[23]; } dump; - struct { + struct __ec_todo_unpacked { uint8_t num; } get_seq, get_brightness, get_demo; struct lightbar_params_v0 get_params_v0; struct lightbar_params_v1 get_params_v1; - struct { + + struct lightbar_params_v2_timing get_params_v2_timing; + struct lightbar_params_v2_tap get_params_v2_tap; + struct lightbar_params_v2_oscillation get_params_v2_osc; + struct lightbar_params_v2_brightness get_params_v2_bright; + struct lightbar_params_v2_thresholds get_params_v2_thlds; + struct lightbar_params_v2_colors get_params_v2_colors; + + struct __ec_todo_unpacked { uint32_t num; uint32_t flags; } version; - struct { + struct __ec_todo_unpacked { uint8_t red, green, blue; } get_rgb; - struct { - /* no return params */ - } off, on, init, set_brightness, seq, reg, set_rgb, - demo, set_params_v0, set_params_v1, - set_program, manual_suspend_ctrl, suspend, resume; + /* + * The following commands have no response: + * + * off, on, init, set_brightness, seq, reg, set_rgb, demo, + * set_params_v0, set_params_v1, set_program, + * manual_suspend_ctrl, suspend, resume, set_v2par_timing, + * set_v2par_tap, set_v2par_osc, set_v2par_bright, + * set_v2par_thlds, set_v2par_colors + */ }; -} __packed; +} __ec_todo_packed; /* Lightbar commands */ enum lightbar_command { @@ -1382,13 +2060,25 @@ enum lightbar_command { LIGHTBAR_CMD_MANUAL_SUSPEND_CTRL = 19, LIGHTBAR_CMD_SUSPEND = 20, LIGHTBAR_CMD_RESUME = 21, + LIGHTBAR_CMD_GET_PARAMS_V2_TIMING = 22, + LIGHTBAR_CMD_SET_PARAMS_V2_TIMING = 23, + LIGHTBAR_CMD_GET_PARAMS_V2_TAP = 24, + LIGHTBAR_CMD_SET_PARAMS_V2_TAP = 25, + LIGHTBAR_CMD_GET_PARAMS_V2_OSCILLATION = 26, + LIGHTBAR_CMD_SET_PARAMS_V2_OSCILLATION = 27, + LIGHTBAR_CMD_GET_PARAMS_V2_BRIGHTNESS = 28, + LIGHTBAR_CMD_SET_PARAMS_V2_BRIGHTNESS = 29, + LIGHTBAR_CMD_GET_PARAMS_V2_THRESHOLDS = 30, + LIGHTBAR_CMD_SET_PARAMS_V2_THRESHOLDS = 31, + LIGHTBAR_CMD_GET_PARAMS_V2_COLORS = 32, + LIGHTBAR_CMD_SET_PARAMS_V2_COLORS = 33, LIGHTBAR_NUM_CMDS }; /*****************************************************************************/ /* LED control commands */ -#define EC_CMD_LED_CONTROL 0x29 +#define EC_CMD_LED_CONTROL 0x0029 enum ec_led_id { /* LED to indicate battery state of charge */ @@ -1400,13 +2090,21 @@ enum ec_led_id { EC_LED_ID_POWER_LED, /* LED on power adapter or its plug */ EC_LED_ID_ADAPTER_LED, + /* LED to indicate left side */ + EC_LED_ID_LEFT_LED, + /* LED to indicate right side */ + EC_LED_ID_RIGHT_LED, + /* LED to indicate recovery mode with HW_REINIT */ + EC_LED_ID_RECOVERY_HW_REINIT_LED, + /* LED to indicate sysrq debug mode. */ + EC_LED_ID_SYSRQ_DEBUG_LED, EC_LED_ID_COUNT }; /* LED control flags */ -#define EC_LED_FLAGS_QUERY (1 << 0) /* Query LED capability only */ -#define EC_LED_FLAGS_AUTO (1 << 1) /* Switch LED back to automatic control */ +#define EC_LED_FLAGS_QUERY BIT(0) /* Query LED capability only */ +#define EC_LED_FLAGS_AUTO BIT(1) /* Switch LED back to automatic control */ enum ec_led_colors { EC_LED_COLOR_RED = 0, @@ -1414,6 +2112,7 @@ enum ec_led_colors { EC_LED_COLOR_BLUE, EC_LED_COLOR_YELLOW, EC_LED_COLOR_WHITE, + EC_LED_COLOR_AMBER, EC_LED_COLOR_COUNT }; @@ -1423,7 +2122,7 @@ struct ec_params_led_control { uint8_t flags; /* Control flags */ uint8_t brightness[EC_LED_COLOR_COUNT]; -} __packed; +} __ec_align1; struct ec_response_led_control { /* @@ -1434,7 +2133,7 @@ struct ec_response_led_control { * Other values means the LED is control by PWM. */ uint8_t brightness_range[EC_LED_COLOR_COUNT]; -} __packed; +} __ec_align1; /*****************************************************************************/ /* Verified boot commands */ @@ -1445,7 +2144,7 @@ struct ec_response_led_control { */ /* Verified boot hash command */ -#define EC_CMD_VBOOT_HASH 0x2A +#define EC_CMD_VBOOT_HASH 0x002A struct ec_params_vboot_hash { uint8_t cmd; /* enum ec_vboot_hash_cmd */ @@ -1455,7 +2154,7 @@ struct ec_params_vboot_hash { uint32_t offset; /* Offset in flash to hash */ uint32_t size; /* Number of bytes to hash */ uint8_t nonce_data[64]; /* Nonce data; ignored if nonce_size=0 */ -} __packed; +} __ec_align4; struct ec_response_vboot_hash { uint8_t status; /* enum ec_vboot_hash_status */ @@ -1465,7 +2164,7 @@ struct ec_response_vboot_hash { uint32_t offset; /* Offset in flash which was hashed */ uint32_t size; /* Number of bytes hashed */ uint8_t hash_digest[64]; /* Hash digest data */ -} __packed; +} __ec_align4; enum ec_vboot_hash_cmd { EC_VBOOT_HASH_GET = 0, /* Get current hash status */ @@ -1489,15 +2188,22 @@ enum ec_vboot_hash_status { * If one of these is specified, the EC will automatically update offset and * size to the correct values for the specified image (RO or RW). */ -#define EC_VBOOT_HASH_OFFSET_RO 0xfffffffe -#define EC_VBOOT_HASH_OFFSET_RW 0xfffffffd +#define EC_VBOOT_HASH_OFFSET_RO 0xfffffffe +#define EC_VBOOT_HASH_OFFSET_ACTIVE 0xfffffffd +#define EC_VBOOT_HASH_OFFSET_UPDATE 0xfffffffc + +/* + * 'RW' is vague if there are multiple RW images; we mean the active one, + * so the old constant is deprecated. + */ +#define EC_VBOOT_HASH_OFFSET_RW EC_VBOOT_HASH_OFFSET_ACTIVE /*****************************************************************************/ /* * Motion sense commands. We'll make separate structs for sub-commands with * different input args, so that we know how much to expect. */ -#define EC_CMD_MOTION_SENSE_CMD 0x2B +#define EC_CMD_MOTION_SENSE_CMD 0x002B /* Motion sense commands */ enum motionsense_command { @@ -1516,7 +2222,13 @@ enum motionsense_command { /* * EC Rate command is a setter/getter command for the EC sampling rate - * of all motion sensors in milliseconds. + * in milliseconds. + * It is per sensor, the EC run sample task at the minimum of all + * sensors EC_RATE. + * For sensors without hardware FIFO, EC_RATE should be equals to 1/ODR + * to collect all the sensor samples. + * For sensor with hardware FIFO, EC_RATE is used as the maximal delay + * to process of all motion sensors in milliseconds. */ MOTIONSENSE_CMD_EC_RATE = 2, @@ -1547,32 +2259,76 @@ enum motionsense_command { MOTIONSENSE_CMD_DATA = 6, /* - * Perform low level calibration.. On sensors that support it, ask to - * do offset calibration. + * Return sensor fifo info. + */ + MOTIONSENSE_CMD_FIFO_INFO = 7, + + /* + * Insert a flush element in the fifo and return sensor fifo info. + * The host can use that element to synchronize its operation. + */ + MOTIONSENSE_CMD_FIFO_FLUSH = 8, + + /* + * Return a portion of the fifo. + */ + MOTIONSENSE_CMD_FIFO_READ = 9, + + /* + * Perform low level calibration. + * On sensors that support it, ask to do offset calibration. */ MOTIONSENSE_CMD_PERFORM_CALIB = 10, /* - * Sensor Offset command is a setter/getter command for the offset used - * for calibration. The offsets can be calculated by the host, or via + * Sensor Offset command is a setter/getter command for the offset + * used for calibration. + * The offsets can be calculated by the host, or via * PERFORM_CALIB command. */ MOTIONSENSE_CMD_SENSOR_OFFSET = 11, - /* Number of motionsense sub-commands. */ - MOTIONSENSE_NUM_CMDS -}; + /* + * List available activities for a MOTION sensor. + * Indicates if they are enabled or disabled. + */ + MOTIONSENSE_CMD_LIST_ACTIVITIES = 12, -enum motionsensor_id { - EC_MOTION_SENSOR_ACCEL_BASE = 0, - EC_MOTION_SENSOR_ACCEL_LID = 1, - EC_MOTION_SENSOR_GYRO = 2, + /* + * Activity management + * Enable/Disable activity recognition. + */ + MOTIONSENSE_CMD_SET_ACTIVITY = 13, /* - * Note, if more sensors are added and this count changes, the padding - * in ec_response_motion_sense dump command must be modified. + * Lid Angle */ - EC_MOTION_SENSOR_COUNT = 3 + MOTIONSENSE_CMD_LID_ANGLE = 14, + + /* + * Allow the FIFO to trigger interrupt via MKBP events. + * By default the FIFO does not send interrupt to process the FIFO + * until the AP is ready or it is coming from a wakeup sensor. + */ + MOTIONSENSE_CMD_FIFO_INT_ENABLE = 15, + + /* + * Spoof the readings of the sensors. The spoofed readings can be set + * to arbitrary values, or will lock to the last read actual values. + */ + MOTIONSENSE_CMD_SPOOF = 16, + + /* Set lid angle for tablet mode detection. */ + MOTIONSENSE_CMD_TABLET_MODE_LID_ANGLE = 17, + + /* + * Sensor Scale command is a setter/getter command for the calibration + * scale. + */ + MOTIONSENSE_CMD_SENSOR_SCALE = 18, + + /* Number of motionsense sub-commands. */ + MOTIONSENSE_NUM_CMDS }; /* List of motion sensor types. */ @@ -1584,6 +2340,7 @@ enum motionsensor_type { MOTIONSENSE_TYPE_LIGHT = 4, MOTIONSENSE_TYPE_ACTIVITY = 5, MOTIONSENSE_TYPE_BARO = 6, + MOTIONSENSE_TYPE_SYNC = 7, MOTIONSENSE_TYPE_MAX, }; @@ -1591,19 +2348,116 @@ enum motionsensor_type { enum motionsensor_location { MOTIONSENSE_LOC_BASE = 0, MOTIONSENSE_LOC_LID = 1, + MOTIONSENSE_LOC_CAMERA = 2, MOTIONSENSE_LOC_MAX, }; /* List of motion sensor chips. */ enum motionsensor_chip { MOTIONSENSE_CHIP_KXCJ9 = 0, + MOTIONSENSE_CHIP_LSM6DS0 = 1, + MOTIONSENSE_CHIP_BMI160 = 2, + MOTIONSENSE_CHIP_SI1141 = 3, + MOTIONSENSE_CHIP_SI1142 = 4, + MOTIONSENSE_CHIP_SI1143 = 5, + MOTIONSENSE_CHIP_KX022 = 6, + MOTIONSENSE_CHIP_L3GD20H = 7, + MOTIONSENSE_CHIP_BMA255 = 8, + MOTIONSENSE_CHIP_BMP280 = 9, + MOTIONSENSE_CHIP_OPT3001 = 10, + MOTIONSENSE_CHIP_BH1730 = 11, + MOTIONSENSE_CHIP_GPIO = 12, + MOTIONSENSE_CHIP_LIS2DH = 13, + MOTIONSENSE_CHIP_LSM6DSM = 14, + MOTIONSENSE_CHIP_LIS2DE = 15, + MOTIONSENSE_CHIP_LIS2MDL = 16, + MOTIONSENSE_CHIP_LSM6DS3 = 17, + MOTIONSENSE_CHIP_LSM6DSO = 18, + MOTIONSENSE_CHIP_LNG2DM = 19, + MOTIONSENSE_CHIP_MAX, }; +/* List of orientation positions */ +enum motionsensor_orientation { + MOTIONSENSE_ORIENTATION_LANDSCAPE = 0, + MOTIONSENSE_ORIENTATION_PORTRAIT = 1, + MOTIONSENSE_ORIENTATION_UPSIDE_DOWN_PORTRAIT = 2, + MOTIONSENSE_ORIENTATION_UPSIDE_DOWN_LANDSCAPE = 3, + MOTIONSENSE_ORIENTATION_UNKNOWN = 4, +}; + +struct ec_response_motion_sensor_data { + /* Flags for each sensor. */ + uint8_t flags; + /* Sensor number the data comes from. */ + uint8_t sensor_num; + /* Each sensor is up to 3-axis. */ + union { + int16_t data[3]; + struct __ec_todo_packed { + uint16_t reserved; + uint32_t timestamp; + }; + struct __ec_todo_unpacked { + uint8_t activity; /* motionsensor_activity */ + uint8_t state; + int16_t add_info[2]; + }; + }; +} __ec_todo_packed; + +/* Note: used in ec_response_get_next_data */ +struct ec_response_motion_sense_fifo_info { + /* Size of the fifo */ + uint16_t size; + /* Amount of space used in the fifo */ + uint16_t count; + /* Timestamp recorded in us. + * aka accurate timestamp when host event was triggered. + */ + uint32_t timestamp; + /* Total amount of vector lost */ + uint16_t total_lost; + /* Lost events since the last fifo_info, per sensors */ + uint16_t lost[0]; +} __ec_todo_packed; + +struct ec_response_motion_sense_fifo_data { + uint32_t number_data; + struct ec_response_motion_sensor_data data[0]; +} __ec_todo_packed; + +/* List supported activity recognition */ +enum motionsensor_activity { + MOTIONSENSE_ACTIVITY_RESERVED = 0, + MOTIONSENSE_ACTIVITY_SIG_MOTION = 1, + MOTIONSENSE_ACTIVITY_DOUBLE_TAP = 2, + MOTIONSENSE_ACTIVITY_ORIENTATION = 3, +}; + +struct ec_motion_sense_activity { + uint8_t sensor_num; + uint8_t activity; /* one of enum motionsensor_activity */ + uint8_t enable; /* 1: enable, 0: disable */ + uint8_t reserved; + uint16_t parameters[3]; /* activity dependent parameters */ +} __ec_todo_unpacked; + /* Module flag masks used for the dump sub-command. */ -#define MOTIONSENSE_MODULE_FLAG_ACTIVE (1<<0) +#define MOTIONSENSE_MODULE_FLAG_ACTIVE BIT(0) /* Sensor flag masks used for the dump sub-command. */ -#define MOTIONSENSE_SENSOR_FLAG_PRESENT (1<<0) +#define MOTIONSENSE_SENSOR_FLAG_PRESENT BIT(0) + +/* + * Flush entry for synchronization. + * data contains time stamp + */ +#define MOTIONSENSE_SENSOR_FLAG_FLUSH BIT(0) +#define MOTIONSENSE_SENSOR_FLAG_TIMESTAMP BIT(1) +#define MOTIONSENSE_SENSOR_FLAG_WAKEUP BIT(2) +#define MOTIONSENSE_SENSOR_FLAG_TABLET_MODE BIT(3) +#define MOTIONSENSE_SENSOR_FLAG_ODR BIT(4) /* * Send this value for the data element to only perform a read. If you @@ -1614,48 +2468,79 @@ enum motionsensor_chip { #define EC_MOTION_SENSE_INVALID_CALIB_TEMP 0x8000 +/* MOTIONSENSE_CMD_SENSOR_OFFSET subcommand flag */ /* Set Calibration information */ -#define MOTION_SENSE_SET_OFFSET 1 +#define MOTION_SENSE_SET_OFFSET BIT(0) -struct ec_response_motion_sensor_data { - /* Flags for each sensor. */ - uint8_t flags; - /* Sensor number the data comes from */ - uint8_t sensor_num; - /* Each sensor is up to 3-axis. */ - union { - int16_t data[3]; - struct { - uint16_t rsvd; - uint32_t timestamp; - } __packed; - struct { - uint8_t activity; /* motionsensor_activity */ - uint8_t state; - int16_t add_info[2]; - }; - }; -} __packed; +/* Default Scale value, factor 1. */ +#define MOTION_SENSE_DEFAULT_SCALE BIT(15) + +#define LID_ANGLE_UNRELIABLE 500 + +enum motionsense_spoof_mode { + /* Disable spoof mode. */ + MOTIONSENSE_SPOOF_MODE_DISABLE = 0, + + /* Enable spoof mode, but use provided component values. */ + MOTIONSENSE_SPOOF_MODE_CUSTOM, + + /* Enable spoof mode, but use the current sensor values. */ + MOTIONSENSE_SPOOF_MODE_LOCK_CURRENT, + + /* Query the current spoof mode status for the sensor. */ + MOTIONSENSE_SPOOF_MODE_QUERY, +}; struct ec_params_motion_sense { uint8_t cmd; union { /* Used for MOTIONSENSE_CMD_DUMP. */ - struct { - /* no args */ + struct __ec_todo_unpacked { + /* + * Maximal number of sensor the host is expecting. + * 0 means the host is only interested in the number + * of sensors controlled by the EC. + */ + uint8_t max_sensor_count; } dump; /* - * Used for MOTIONSENSE_CMD_EC_RATE and - * MOTIONSENSE_CMD_KB_WAKE_ANGLE. + * Used for MOTIONSENSE_CMD_KB_WAKE_ANGLE. */ - struct { - /* Data to set or EC_MOTION_SENSE_NO_VALUE to read. */ + struct __ec_todo_unpacked { + /* Data to set or EC_MOTION_SENSE_NO_VALUE to read. + * kb_wake_angle: angle to wakup AP. + */ int16_t data; - } ec_rate, kb_wake_angle; + } kb_wake_angle; + + /* + * Used for MOTIONSENSE_CMD_INFO, MOTIONSENSE_CMD_DATA + * and MOTIONSENSE_CMD_PERFORM_CALIB. + */ + struct __ec_todo_unpacked { + uint8_t sensor_num; + } info, info_3, data, fifo_flush, perform_calib, + list_activities; + + /* + * Used for MOTIONSENSE_CMD_EC_RATE, MOTIONSENSE_CMD_SENSOR_ODR + * and MOTIONSENSE_CMD_SENSOR_RANGE. + */ + struct __ec_todo_unpacked { + uint8_t sensor_num; + + /* Rounding flag, true for round-up, false for down. */ + uint8_t roundup; + + uint16_t reserved; + + /* Data to set or EC_MOTION_SENSE_NO_VALUE to read. */ + int32_t data; + } ec_rate, sensor_odr, sensor_range; /* Used for MOTIONSENSE_CMD_SENSOR_OFFSET */ - struct { + struct __ec_todo_packed { uint8_t sensor_num; /* @@ -1681,36 +2566,102 @@ struct ec_params_motion_sense { * Compass: 1/16 uT */ int16_t offset[3]; - } __packed sensor_offset; + } sensor_offset; - /* Used for MOTIONSENSE_CMD_INFO. */ - struct { + /* Used for MOTIONSENSE_CMD_SENSOR_SCALE */ + struct __ec_todo_packed { uint8_t sensor_num; - } info; - /* - * Used for MOTIONSENSE_CMD_SENSOR_ODR and - * MOTIONSENSE_CMD_SENSOR_RANGE. - */ - struct { - /* Should be element of enum motionsensor_id. */ - uint8_t sensor_num; + /* + * bit 0: If set (MOTION_SENSE_SET_OFFSET), set + * the calibration information in the EC. + * If unset, just retrieve calibration information. + */ + uint16_t flags; - /* Rounding flag, true for round-up, false for down. */ - uint8_t roundup; + /* + * Temperature at calibration, in units of 0.01 C + * 0x8000: invalid / unknown. + * 0x0: 0C + * 0x7fff: +327.67C + */ + int16_t temp; - uint16_t reserved; + /* + * Scale for calibration: + * By default scale is 1, it is encoded on 16bits: + * 1 = BIT(15) + * ~2 = 0xFFFF + * ~0 = 0. + */ + uint16_t scale[3]; + } sensor_scale; - /* Data to set or EC_MOTION_SENSE_NO_VALUE to read. */ - int32_t data; - } sensor_odr, sensor_range; + + /* Used for MOTIONSENSE_CMD_FIFO_INFO */ + /* (no params) */ + + /* Used for MOTIONSENSE_CMD_FIFO_READ */ + struct __ec_todo_unpacked { + /* + * Number of expected vector to return. + * EC may return less or 0 if none available. + */ + uint32_t max_data_vector; + } fifo_read; + + struct ec_motion_sense_activity set_activity; + + /* Used for MOTIONSENSE_CMD_LID_ANGLE */ + /* (no params) */ + + /* Used for MOTIONSENSE_CMD_FIFO_INT_ENABLE */ + struct __ec_todo_unpacked { + /* + * 1: enable, 0 disable fifo, + * EC_MOTION_SENSE_NO_VALUE return value. + */ + int8_t enable; + } fifo_int_enable; + + /* Used for MOTIONSENSE_CMD_SPOOF */ + struct __ec_todo_packed { + uint8_t sensor_id; + + /* See enum motionsense_spoof_mode. */ + uint8_t spoof_enable; + + /* Ignored, used for alignment. */ + uint8_t reserved; + + /* Individual component values to spoof. */ + int16_t components[3]; + } spoof; + + /* Used for MOTIONSENSE_CMD_TABLET_MODE_LID_ANGLE. */ + struct __ec_todo_unpacked { + /* + * Lid angle threshold for switching between tablet and + * clamshell mode. + */ + int16_t lid_angle; + + /* + * Hysteresis degree to prevent fluctuations between + * clamshell and tablet mode if lid angle keeps + * changing around the threshold. Lid motion driver will + * use lid_angle + hys_degree to trigger tablet mode and + * lid_angle - hys_degree to trigger clamshell mode. + */ + int16_t hys_degree; + } tablet_mode_threshold; }; -} __packed; +} __ec_todo_packed; struct ec_response_motion_sense { union { - /* Used for MOTIONSENSE_CMD_DUMP. */ - struct { + /* Used for MOTIONSENSE_CMD_DUMP */ + struct __ec_todo_unpacked { /* Flags representing the motion sensor module. */ uint8_t module_flags; @@ -1725,7 +2676,7 @@ struct ec_response_motion_sense { } dump; /* Used for MOTIONSENSE_CMD_INFO. */ - struct { + struct __ec_todo_unpacked { /* Should be element of enum motionsensor_type. */ uint8_t type; @@ -1736,37 +2687,129 @@ struct ec_response_motion_sense { uint8_t chip; } info; + /* Used for MOTIONSENSE_CMD_INFO version 3 */ + struct __ec_todo_unpacked { + /* Should be element of enum motionsensor_type. */ + uint8_t type; + + /* Should be element of enum motionsensor_location. */ + uint8_t location; + + /* Should be element of enum motionsensor_chip. */ + uint8_t chip; + + /* Minimum sensor sampling frequency */ + uint32_t min_frequency; + + /* Maximum sensor sampling frequency */ + uint32_t max_frequency; + + /* Max number of sensor events that could be in fifo */ + uint32_t fifo_max_event_count; + } info_3; + /* Used for MOTIONSENSE_CMD_DATA */ struct ec_response_motion_sensor_data data; /* * Used for MOTIONSENSE_CMD_EC_RATE, MOTIONSENSE_CMD_SENSOR_ODR, - * MOTIONSENSE_CMD_SENSOR_RANGE, and - * MOTIONSENSE_CMD_KB_WAKE_ANGLE. + * MOTIONSENSE_CMD_SENSOR_RANGE, + * MOTIONSENSE_CMD_KB_WAKE_ANGLE, + * MOTIONSENSE_CMD_FIFO_INT_ENABLE and + * MOTIONSENSE_CMD_SPOOF. */ - struct { + struct __ec_todo_unpacked { /* Current value of the parameter queried. */ int32_t ret; - } ec_rate, sensor_odr, sensor_range, kb_wake_angle; + } ec_rate, sensor_odr, sensor_range, kb_wake_angle, + fifo_int_enable, spoof; - /* Used for MOTIONSENSE_CMD_SENSOR_OFFSET */ - struct { + /* + * Used for MOTIONSENSE_CMD_SENSOR_OFFSET, + * PERFORM_CALIB. + */ + struct __ec_todo_unpacked { int16_t temp; int16_t offset[3]; } sensor_offset, perform_calib; + + /* Used for MOTIONSENSE_CMD_SENSOR_SCALE */ + struct __ec_todo_unpacked { + int16_t temp; + uint16_t scale[3]; + } sensor_scale; + + struct ec_response_motion_sense_fifo_info fifo_info, fifo_flush; + + struct ec_response_motion_sense_fifo_data fifo_read; + + struct __ec_todo_packed { + uint16_t reserved; + uint32_t enabled; + uint32_t disabled; + } list_activities; + + /* No params for set activity */ + + /* Used for MOTIONSENSE_CMD_LID_ANGLE */ + struct __ec_todo_unpacked { + /* + * Angle between 0 and 360 degree if available, + * LID_ANGLE_UNRELIABLE otherwise. + */ + uint16_t value; + } lid_angle; + + /* Used for MOTIONSENSE_CMD_TABLET_MODE_LID_ANGLE. */ + struct __ec_todo_unpacked { + /* + * Lid angle threshold for switching between tablet and + * clamshell mode. + */ + uint16_t lid_angle; + + /* Hysteresis degree. */ + uint16_t hys_degree; + } tablet_mode_threshold; + }; -} __packed; +} __ec_todo_packed; + +/*****************************************************************************/ +/* Force lid open command */ + +/* Make lid event always open */ +#define EC_CMD_FORCE_LID_OPEN 0x002C + +struct ec_params_force_lid_open { + uint8_t enabled; +} __ec_align1; + +/*****************************************************************************/ +/* Configure the behavior of the power button */ +#define EC_CMD_CONFIG_POWER_BUTTON 0x002D + +enum ec_config_power_button_flags { + /* Enable/Disable power button pulses for x86 devices */ + EC_POWER_BUTTON_ENABLE_PULSE = BIT(0), +}; + +struct ec_params_config_power_button { + /* See enum ec_config_power_button_flags */ + uint8_t flags; +} __ec_align1; /*****************************************************************************/ /* USB charging control commands */ /* Set USB port charging mode */ -#define EC_CMD_USB_CHARGE_SET_MODE 0x30 +#define EC_CMD_USB_CHARGE_SET_MODE 0x0030 struct ec_params_usb_charge_set_mode { uint8_t usb_port_id; - uint8_t mode; -} __packed; + uint8_t mode:7; + uint8_t inhibit_charge:1; +} __ec_align1; /*****************************************************************************/ /* Persistent storage for host */ @@ -1775,35 +2818,35 @@ struct ec_params_usb_charge_set_mode { #define EC_PSTORE_SIZE_MAX 64 /* Get persistent storage info */ -#define EC_CMD_PSTORE_INFO 0x40 +#define EC_CMD_PSTORE_INFO 0x0040 struct ec_response_pstore_info { /* Persistent storage size, in bytes */ uint32_t pstore_size; /* Access size; read/write offset and size must be a multiple of this */ uint32_t access_size; -} __packed; +} __ec_align4; /* * Read persistent storage * * Response is params.size bytes of data. */ -#define EC_CMD_PSTORE_READ 0x41 +#define EC_CMD_PSTORE_READ 0x0041 struct ec_params_pstore_read { uint32_t offset; /* Byte offset to read */ uint32_t size; /* Size to read in bytes */ -} __packed; +} __ec_align4; /* Write persistent storage */ -#define EC_CMD_PSTORE_WRITE 0x42 +#define EC_CMD_PSTORE_WRITE 0x0042 struct ec_params_pstore_write { uint32_t offset; /* Byte offset to write */ uint32_t size; /* Size to write in bytes */ uint8_t data[EC_PSTORE_SIZE_MAX]; -} __packed; +} __ec_align4; /*****************************************************************************/ /* Real-time clock */ @@ -1811,21 +2854,21 @@ struct ec_params_pstore_write { /* RTC params and response structures */ struct ec_params_rtc { uint32_t time; -} __packed; +} __ec_align4; struct ec_response_rtc { uint32_t time; -} __packed; +} __ec_align4; /* These use ec_response_rtc */ -#define EC_CMD_RTC_GET_VALUE 0x44 -#define EC_CMD_RTC_GET_ALARM 0x45 +#define EC_CMD_RTC_GET_VALUE 0x0044 +#define EC_CMD_RTC_GET_ALARM 0x0045 /* These all use ec_params_rtc */ -#define EC_CMD_RTC_SET_VALUE 0x46 -#define EC_CMD_RTC_SET_ALARM 0x47 +#define EC_CMD_RTC_SET_VALUE 0x0046 +#define EC_CMD_RTC_SET_ALARM 0x0047 -/* Pass as param to SET_ALARM to clear the current alarm */ +/* Pass as time param to SET_ALARM to clear the current alarm */ #define EC_RTC_ALARM_CLEAR 0 /*****************************************************************************/ @@ -1835,8 +2878,8 @@ struct ec_response_rtc { #define EC_PORT80_SIZE_MAX 32 /* Get last port80 code from previous boot */ -#define EC_CMD_PORT80_LAST_BOOT 0x48 -#define EC_CMD_PORT80_READ 0x48 +#define EC_CMD_PORT80_LAST_BOOT 0x0048 +#define EC_CMD_PORT80_READ 0x0048 enum ec_port80_subcmd { EC_PORT80_GET_INFO = 0, @@ -1846,29 +2889,72 @@ enum ec_port80_subcmd { struct ec_params_port80_read { uint16_t subcmd; union { - struct { + struct __ec_todo_unpacked { uint32_t offset; uint32_t num_entries; } read_buffer; }; -} __packed; +} __ec_todo_packed; struct ec_response_port80_read { union { - struct { + struct __ec_todo_unpacked { uint32_t writes; uint32_t history_size; uint32_t last_boot; } get_info; - struct { + struct __ec_todo_unpacked { uint16_t codes[EC_PORT80_SIZE_MAX]; } data; }; -} __packed; +} __ec_todo_packed; struct ec_response_port80_last_boot { uint16_t code; -} __packed; +} __ec_align2; + +/*****************************************************************************/ +/* Temporary secure storage for host verified boot use */ + +/* Number of bytes in a vstore slot */ +#define EC_VSTORE_SLOT_SIZE 64 + +/* Maximum number of vstore slots */ +#define EC_VSTORE_SLOT_MAX 32 + +/* Get persistent storage info */ +#define EC_CMD_VSTORE_INFO 0x0049 +struct ec_response_vstore_info { + /* Indicates which slots are locked */ + uint32_t slot_locked; + /* Total number of slots available */ + uint8_t slot_count; +} __ec_align_size1; + +/* + * Read temporary secure storage + * + * Response is EC_VSTORE_SLOT_SIZE bytes of data. + */ +#define EC_CMD_VSTORE_READ 0x004A + +struct ec_params_vstore_read { + uint8_t slot; /* Slot to read from */ +} __ec_align1; + +struct ec_response_vstore_read { + uint8_t data[EC_VSTORE_SLOT_SIZE]; +} __ec_align1; + +/* + * Write temporary secure storage and lock it. + */ +#define EC_CMD_VSTORE_WRITE 0x004B + +struct ec_params_vstore_write { + uint8_t slot; /* Slot to write to */ + uint8_t data[EC_VSTORE_SLOT_SIZE]; +} __ec_align1; /*****************************************************************************/ /* Thermal engine commands. Note that there are two implementations. We'll @@ -1877,8 +2963,8 @@ struct ec_response_port80_last_boot { * Version 1 separates the CPU thermal limits from the fan control. */ -#define EC_CMD_THERMAL_SET_THRESHOLD 0x50 -#define EC_CMD_THERMAL_GET_THRESHOLD 0x51 +#define EC_CMD_THERMAL_SET_THRESHOLD 0x0050 +#define EC_CMD_THERMAL_GET_THRESHOLD 0x0051 /* The version 0 structs are opaque. You have to know what they are for * the get/set commands to make any sense. @@ -1889,17 +2975,17 @@ struct ec_params_thermal_set_threshold { uint8_t sensor_type; uint8_t threshold_id; uint16_t value; -} __packed; +} __ec_align2; /* Version 0 - get */ struct ec_params_thermal_get_threshold { uint8_t sensor_type; uint8_t threshold_id; -} __packed; +} __ec_align1; struct ec_response_thermal_get_threshold { uint16_t value; -} __packed; +} __ec_align2; /* The version 1 structs are visible. */ @@ -1911,71 +2997,124 @@ enum ec_temp_thresholds { EC_TEMP_THRESH_COUNT }; -/* Thermal configuration for one temperature sensor. Temps are in degrees K. +/* + * Thermal configuration for one temperature sensor. Temps are in degrees K. * Zero values will be silently ignored by the thermal task. + * + * Set 'temp_host' value allows thermal task to trigger some event with 1 degree + * hysteresis. + * For example, + * temp_host[EC_TEMP_THRESH_HIGH] = 300 K + * temp_host_release[EC_TEMP_THRESH_HIGH] = 0 K + * EC will throttle ap when temperature >= 301 K, and release throttling when + * temperature <= 299 K. + * + * Set 'temp_host_release' value allows thermal task has a custom hysteresis. + * For example, + * temp_host[EC_TEMP_THRESH_HIGH] = 300 K + * temp_host_release[EC_TEMP_THRESH_HIGH] = 295 K + * EC will throttle ap when temperature >= 301 K, and release throttling when + * temperature <= 294 K. + * + * Note that this structure is a sub-structure of + * ec_params_thermal_set_threshold_v1, but maintains its alignment there. */ struct ec_thermal_config { uint32_t temp_host[EC_TEMP_THRESH_COUNT]; /* levels of hotness */ + uint32_t temp_host_release[EC_TEMP_THRESH_COUNT]; /* release levels */ uint32_t temp_fan_off; /* no active cooling needed */ uint32_t temp_fan_max; /* max active cooling needed */ -} __packed; +} __ec_align4; /* Version 1 - get config for one sensor. */ struct ec_params_thermal_get_threshold_v1 { uint32_t sensor_num; -} __packed; +} __ec_align4; /* This returns a struct ec_thermal_config */ -/* Version 1 - set config for one sensor. - * Use read-modify-write for best results! */ +/* + * Version 1 - set config for one sensor. + * Use read-modify-write for best results! + */ struct ec_params_thermal_set_threshold_v1 { uint32_t sensor_num; struct ec_thermal_config cfg; -} __packed; +} __ec_align4; /* This returns no data */ /****************************************************************************/ /* Toggle automatic fan control */ -#define EC_CMD_THERMAL_AUTO_FAN_CTRL 0x52 +#define EC_CMD_THERMAL_AUTO_FAN_CTRL 0x0052 + +/* Version 1 of input params */ +struct ec_params_auto_fan_ctrl_v1 { + uint8_t fan_idx; +} __ec_align1; -/* Get TMP006 calibration data */ -#define EC_CMD_TMP006_GET_CALIBRATION 0x53 +/* Get/Set TMP006 calibration data */ +#define EC_CMD_TMP006_GET_CALIBRATION 0x0053 +#define EC_CMD_TMP006_SET_CALIBRATION 0x0054 + +/* + * The original TMP006 calibration only needed four params, but now we need + * more. Since the algorithm is nothing but magic numbers anyway, we'll leave + * the params opaque. The v1 "get" response will include the algorithm number + * and how many params it requires. That way we can change the EC code without + * needing to update this file. We can also use a different algorithm on each + * sensor. + */ +/* This is the same struct for both v0 and v1. */ struct ec_params_tmp006_get_calibration { uint8_t index; -} __packed; +} __ec_align1; -struct ec_response_tmp006_get_calibration { +/* Version 0 */ +struct ec_response_tmp006_get_calibration_v0 { float s0; float b0; float b1; float b2; -} __packed; - -/* Set TMP006 calibration data */ -#define EC_CMD_TMP006_SET_CALIBRATION 0x54 +} __ec_align4; -struct ec_params_tmp006_set_calibration { +struct ec_params_tmp006_set_calibration_v0 { uint8_t index; - uint8_t reserved[3]; /* Reserved; set 0 */ + uint8_t reserved[3]; float s0; float b0; float b1; float b2; -} __packed; +} __ec_align4; + +/* Version 1 */ +struct ec_response_tmp006_get_calibration_v1 { + uint8_t algorithm; + uint8_t num_params; + uint8_t reserved[2]; + float val[0]; +} __ec_align4; + +struct ec_params_tmp006_set_calibration_v1 { + uint8_t index; + uint8_t algorithm; + uint8_t num_params; + uint8_t reserved; + float val[0]; +} __ec_align4; + /* Read raw TMP006 data */ -#define EC_CMD_TMP006_GET_RAW 0x55 +#define EC_CMD_TMP006_GET_RAW 0x0055 struct ec_params_tmp006_get_raw { uint8_t index; -} __packed; +} __ec_align1; struct ec_response_tmp006_get_raw { int32_t t; /* In 1/100 K */ int32_t v; /* In nV */ -}; +} __ec_align4; /*****************************************************************************/ /* MKBP - Matrix KeyBoard Protocol */ @@ -1990,24 +3129,24 @@ struct ec_response_tmp006_get_raw { * to obtain the instantaneous state, use EC_CMD_MKBP_INFO with the type * EC_MKBP_INFO_CURRENT and event EC_MKBP_EVENT_KEY_MATRIX. */ -#define EC_CMD_MKBP_STATE 0x60 +#define EC_CMD_MKBP_STATE 0x0060 /* * Provide information about various MKBP things. See enum ec_mkbp_info_type. */ -#define EC_CMD_MKBP_INFO 0x61 +#define EC_CMD_MKBP_INFO 0x0061 struct ec_response_mkbp_info { uint32_t rows; uint32_t cols; /* Formerly "switches", which was 0. */ uint8_t reserved; -} __packed; +} __ec_align_size1; struct ec_params_mkbp_info { uint8_t info_type; uint8_t event_type; -} __packed; +} __ec_align1; enum ec_mkbp_info_type { /* @@ -2049,17 +3188,28 @@ enum ec_mkbp_info_type { }; /* Simulate key press */ -#define EC_CMD_MKBP_SIMULATE_KEY 0x62 +#define EC_CMD_MKBP_SIMULATE_KEY 0x0062 struct ec_params_mkbp_simulate_key { uint8_t col; uint8_t row; uint8_t pressed; -} __packed; +} __ec_align1; + +#define EC_CMD_GET_KEYBOARD_ID 0x0063 + +struct ec_response_keyboard_id { + uint32_t keyboard_id; +} __ec_align4; + +enum keyboard_id { + KEYBOARD_ID_UNSUPPORTED = 0, + KEYBOARD_ID_UNREADABLE = 0xffffffff, +}; /* Configure keyboard scanning */ -#define EC_CMD_MKBP_SET_CONFIG 0x64 -#define EC_CMD_MKBP_GET_CONFIG 0x65 +#define EC_CMD_MKBP_SET_CONFIG 0x0064 +#define EC_CMD_MKBP_GET_CONFIG 0x0065 /* flags */ enum mkbp_config_flags { @@ -2067,16 +3217,21 @@ enum mkbp_config_flags { }; enum mkbp_config_valid { - EC_MKBP_VALID_SCAN_PERIOD = 1 << 0, - EC_MKBP_VALID_POLL_TIMEOUT = 1 << 1, - EC_MKBP_VALID_MIN_POST_SCAN_DELAY = 1 << 3, - EC_MKBP_VALID_OUTPUT_SETTLE = 1 << 4, - EC_MKBP_VALID_DEBOUNCE_DOWN = 1 << 5, - EC_MKBP_VALID_DEBOUNCE_UP = 1 << 6, - EC_MKBP_VALID_FIFO_MAX_DEPTH = 1 << 7, + EC_MKBP_VALID_SCAN_PERIOD = BIT(0), + EC_MKBP_VALID_POLL_TIMEOUT = BIT(1), + EC_MKBP_VALID_MIN_POST_SCAN_DELAY = BIT(3), + EC_MKBP_VALID_OUTPUT_SETTLE = BIT(4), + EC_MKBP_VALID_DEBOUNCE_DOWN = BIT(5), + EC_MKBP_VALID_DEBOUNCE_UP = BIT(6), + EC_MKBP_VALID_FIFO_MAX_DEPTH = BIT(7), }; -/* Configuration for our key scanning algorithm */ +/* + * Configuration for our key scanning algorithm. + * + * Note that this is used as a sub-structure of + * ec_{params/response}_mkbp_get_config. + */ struct ec_mkbp_config { uint32_t valid_mask; /* valid fields */ uint8_t flags; /* some flags (enum mkbp_config_flags) */ @@ -2096,18 +3251,18 @@ struct ec_mkbp_config { uint16_t debounce_up_us; /* time for debounce on key up */ /* maximum depth to allow for fifo (0 = no keyscan output) */ uint8_t fifo_max_depth; -} __packed; +} __ec_align_size1; struct ec_params_mkbp_set_config { struct ec_mkbp_config config; -} __packed; +} __ec_align_size1; struct ec_response_mkbp_get_config { struct ec_mkbp_config config; -} __packed; +} __ec_align_size1; /* Run the key scan emulation */ -#define EC_CMD_KEYSCAN_SEQ_CTRL 0x66 +#define EC_CMD_KEYSCAN_SEQ_CTRL 0x0066 enum ec_keyscan_seq_cmd { EC_KEYSCAN_SEQ_STATUS = 0, /* Get status information */ @@ -2122,23 +3277,23 @@ enum ec_collect_flags { * Indicates this scan was processed by the EC. Due to timing, some * scans may be skipped. */ - EC_KEYSCAN_SEQ_FLAG_DONE = 1 << 0, + EC_KEYSCAN_SEQ_FLAG_DONE = BIT(0), }; struct ec_collect_item { uint8_t flags; /* some flags (enum ec_collect_flags) */ -}; +} __ec_align1; struct ec_params_keyscan_seq_ctrl { uint8_t cmd; /* Command to send (enum ec_keyscan_seq_cmd) */ union { - struct { + struct __ec_align1 { uint8_t active; /* still active */ uint8_t num_items; /* number of items */ /* Current item being presented */ uint8_t cur_item; } status; - struct { + struct __ec_todo_unpacked { /* * Absolute time for this scan, measured from the * start of the sequence. @@ -2146,29 +3301,40 @@ struct ec_params_keyscan_seq_ctrl { uint32_t time_us; uint8_t scan[0]; /* keyscan data */ } add; - struct { + struct __ec_align1 { uint8_t start_item; /* First item to return */ uint8_t num_items; /* Number of items to return */ } collect; }; -} __packed; +} __ec_todo_packed; struct ec_result_keyscan_seq_ctrl { union { - struct { + struct __ec_todo_unpacked { uint8_t num_items; /* Number of items */ /* Data for each item */ struct ec_collect_item item[0]; } collect; }; -} __packed; +} __ec_todo_packed; /* - * Command for retrieving the next pending MKBP event from the EC device + * Get the next pending MKBP event. * - * The device replies with UNAVAILABLE if there aren't any pending events. + * Returns EC_RES_UNAVAILABLE if there is no event pending. */ -#define EC_CMD_GET_NEXT_EVENT 0x67 +#define EC_CMD_GET_NEXT_EVENT 0x0067 + +#define EC_MKBP_HAS_MORE_EVENTS_SHIFT 7 + +/* + * We use the most significant bit of the event type to indicate to the host + * that the EC has more MKBP events available to provide. + */ +#define EC_MKBP_HAS_MORE_EVENTS BIT(EC_MKBP_HAS_MORE_EVENTS_SHIFT) + +/* The mask to apply to get the raw event type */ +#define EC_MKBP_EVENT_TYPE_MASK (BIT(EC_MKBP_HAS_MORE_EVENTS_SHIFT) - 1) enum ec_mkbp_event { /* Keyboard matrix changed. The event data is the new matrix state. */ @@ -2186,9 +3352,21 @@ enum ec_mkbp_event { /* The state of the switches have changed. */ EC_MKBP_EVENT_SWITCH = 4, - /* EC sent a sysrq command */ + /* New Fingerprint sensor event, the event data is fp_events bitmap. */ + EC_MKBP_EVENT_FINGERPRINT = 5, + + /* + * Sysrq event: send emulated sysrq. The event data is sysrq, + * corresponding to the key to be pressed. + */ EC_MKBP_EVENT_SYSRQ = 6, + /* + * New 64-bit host event. + * The event data is 8 bytes of host event flags. + */ + EC_MKBP_EVENT_HOST_EVENT64 = 7, + /* Notify the AP that something happened on CEC */ EC_MKBP_EVENT_CEC_EVENT = 8, @@ -2198,65 +3376,140 @@ enum ec_mkbp_event { /* Number of MKBP events */ EC_MKBP_EVENT_COUNT, }; +BUILD_ASSERT(EC_MKBP_EVENT_COUNT <= EC_MKBP_EVENT_TYPE_MASK); -union ec_response_get_next_data { - uint8_t key_matrix[13]; +union __ec_align_offset1 ec_response_get_next_data { + uint8_t key_matrix[13]; /* Unaligned */ - uint32_t host_event; + uint32_t host_event; + uint64_t host_event64; + + struct __ec_todo_unpacked { + /* For aligning the fifo_info */ + uint8_t reserved[3]; + struct ec_response_motion_sense_fifo_info info; + } sensor_fifo; + + uint32_t buttons; + + uint32_t switches; + + uint32_t fp_events; - uint32_t buttons; - uint32_t switches; - uint32_t sysrq; -} __packed; + uint32_t sysrq; -union ec_response_get_next_data_v1 { + /* CEC events from enum mkbp_cec_event */ + uint32_t cec_events; +}; + +union __ec_align_offset1 ec_response_get_next_data_v1 { uint8_t key_matrix[16]; + + /* Unaligned */ uint32_t host_event; + uint64_t host_event64; + + struct __ec_todo_unpacked { + /* For aligning the fifo_info */ + uint8_t reserved[3]; + struct ec_response_motion_sense_fifo_info info; + } sensor_fifo; + uint32_t buttons; + uint32_t switches; + + uint32_t fp_events; + uint32_t sysrq; + + /* CEC events from enum mkbp_cec_event */ uint32_t cec_events; + uint8_t cec_message[16]; -} __packed; +}; +BUILD_ASSERT(sizeof(union ec_response_get_next_data_v1) == 16); struct ec_response_get_next_event { uint8_t event_type; /* Followed by event data if any */ union ec_response_get_next_data data; -} __packed; +} __ec_align1; struct ec_response_get_next_event_v1 { uint8_t event_type; /* Followed by event data if any */ union ec_response_get_next_data_v1 data; -} __packed; +} __ec_align1; /* Bit indices for buttons and switches.*/ /* Buttons */ #define EC_MKBP_POWER_BUTTON 0 #define EC_MKBP_VOL_UP 1 #define EC_MKBP_VOL_DOWN 2 +#define EC_MKBP_RECOVERY 3 /* Switches */ #define EC_MKBP_LID_OPEN 0 #define EC_MKBP_TABLET_MODE 1 #define EC_MKBP_BASE_ATTACHED 2 +/* Run keyboard factory test scanning */ +#define EC_CMD_KEYBOARD_FACTORY_TEST 0x0068 + +struct ec_response_keyboard_factory_test { + uint16_t shorted; /* Keyboard pins are shorted */ +} __ec_align2; + +/* Fingerprint events in 'fp_events' for EC_MKBP_EVENT_FINGERPRINT */ +#define EC_MKBP_FP_RAW_EVENT(fp_events) ((fp_events) & 0x00FFFFFF) +#define EC_MKBP_FP_ERRCODE(fp_events) ((fp_events) & 0x0000000F) +#define EC_MKBP_FP_ENROLL_PROGRESS_OFFSET 4 +#define EC_MKBP_FP_ENROLL_PROGRESS(fpe) (((fpe) & 0x00000FF0) \ + >> EC_MKBP_FP_ENROLL_PROGRESS_OFFSET) +#define EC_MKBP_FP_MATCH_IDX_OFFSET 12 +#define EC_MKBP_FP_MATCH_IDX_MASK 0x0000F000 +#define EC_MKBP_FP_MATCH_IDX(fpe) (((fpe) & EC_MKBP_FP_MATCH_IDX_MASK) \ + >> EC_MKBP_FP_MATCH_IDX_OFFSET) +#define EC_MKBP_FP_ENROLL BIT(27) +#define EC_MKBP_FP_MATCH BIT(28) +#define EC_MKBP_FP_FINGER_DOWN BIT(29) +#define EC_MKBP_FP_FINGER_UP BIT(30) +#define EC_MKBP_FP_IMAGE_READY BIT(31) +/* code given by EC_MKBP_FP_ERRCODE() when EC_MKBP_FP_ENROLL is set */ +#define EC_MKBP_FP_ERR_ENROLL_OK 0 +#define EC_MKBP_FP_ERR_ENROLL_LOW_QUALITY 1 +#define EC_MKBP_FP_ERR_ENROLL_IMMOBILE 2 +#define EC_MKBP_FP_ERR_ENROLL_LOW_COVERAGE 3 +#define EC_MKBP_FP_ERR_ENROLL_INTERNAL 5 +/* Can be used to detect if image was usable for enrollment or not. */ +#define EC_MKBP_FP_ERR_ENROLL_PROBLEM_MASK 1 +/* code given by EC_MKBP_FP_ERRCODE() when EC_MKBP_FP_MATCH is set */ +#define EC_MKBP_FP_ERR_MATCH_NO 0 +#define EC_MKBP_FP_ERR_MATCH_NO_INTERNAL 6 +#define EC_MKBP_FP_ERR_MATCH_NO_TEMPLATES 7 +#define EC_MKBP_FP_ERR_MATCH_NO_LOW_QUALITY 2 +#define EC_MKBP_FP_ERR_MATCH_NO_LOW_COVERAGE 4 +#define EC_MKBP_FP_ERR_MATCH_YES 1 +#define EC_MKBP_FP_ERR_MATCH_YES_UPDATED 3 +#define EC_MKBP_FP_ERR_MATCH_YES_UPDATE_FAILED 5 + + /*****************************************************************************/ /* Temperature sensor commands */ /* Read temperature sensor info */ -#define EC_CMD_TEMP_SENSOR_GET_INFO 0x70 +#define EC_CMD_TEMP_SENSOR_GET_INFO 0x0070 struct ec_params_temp_sensor_get_info { uint8_t id; -} __packed; +} __ec_align1; struct ec_response_temp_sensor_get_info { char sensor_name[32]; uint8_t sensor_type; -} __packed; +} __ec_align1; /*****************************************************************************/ @@ -2269,49 +3522,131 @@ struct ec_response_temp_sensor_get_info { /*****************************************************************************/ /* Host event commands */ + +/* Obsolete. New implementation should use EC_CMD_HOST_EVENT instead */ /* * Host event mask params and response structures, shared by all of the host * event commands below. */ struct ec_params_host_event_mask { uint32_t mask; -} __packed; +} __ec_align4; struct ec_response_host_event_mask { uint32_t mask; -} __packed; +} __ec_align4; /* These all use ec_response_host_event_mask */ -#define EC_CMD_HOST_EVENT_GET_B 0x87 -#define EC_CMD_HOST_EVENT_GET_SMI_MASK 0x88 -#define EC_CMD_HOST_EVENT_GET_SCI_MASK 0x89 -#define EC_CMD_HOST_EVENT_GET_WAKE_MASK 0x8d +#define EC_CMD_HOST_EVENT_GET_B 0x0087 +#define EC_CMD_HOST_EVENT_GET_SMI_MASK 0x0088 +#define EC_CMD_HOST_EVENT_GET_SCI_MASK 0x0089 +#define EC_CMD_HOST_EVENT_GET_WAKE_MASK 0x008D /* These all use ec_params_host_event_mask */ -#define EC_CMD_HOST_EVENT_SET_SMI_MASK 0x8a -#define EC_CMD_HOST_EVENT_SET_SCI_MASK 0x8b -#define EC_CMD_HOST_EVENT_CLEAR 0x8c -#define EC_CMD_HOST_EVENT_SET_WAKE_MASK 0x8e -#define EC_CMD_HOST_EVENT_CLEAR_B 0x8f +#define EC_CMD_HOST_EVENT_SET_SMI_MASK 0x008A +#define EC_CMD_HOST_EVENT_SET_SCI_MASK 0x008B +#define EC_CMD_HOST_EVENT_CLEAR 0x008C +#define EC_CMD_HOST_EVENT_SET_WAKE_MASK 0x008E +#define EC_CMD_HOST_EVENT_CLEAR_B 0x008F + +/* + * Unified host event programming interface - Should be used by newer versions + * of BIOS/OS to program host events and masks + */ + +struct ec_params_host_event { + + /* Action requested by host - one of enum ec_host_event_action. */ + uint8_t action; + + /* + * Mask type that the host requested the action on - one of + * enum ec_host_event_mask_type. + */ + uint8_t mask_type; + + /* Set to 0, ignore on read */ + uint16_t reserved; + + /* Value to be used in case of set operations. */ + uint64_t value; +} __ec_align4; + +/* + * Response structure returned by EC_CMD_HOST_EVENT. + * Update the value on a GET request. Set to 0 on GET/CLEAR + */ + +struct ec_response_host_event { + + /* Mask value in case of get operation */ + uint64_t value; +} __ec_align4; + +enum ec_host_event_action { + /* + * params.value is ignored. Value of mask_type populated + * in response.value + */ + EC_HOST_EVENT_GET, + + /* Bits in params.value are set */ + EC_HOST_EVENT_SET, + + /* Bits in params.value are cleared */ + EC_HOST_EVENT_CLEAR, +}; + +enum ec_host_event_mask_type { + + /* Main host event copy */ + EC_HOST_EVENT_MAIN, + + /* Copy B of host events */ + EC_HOST_EVENT_B, + + /* SCI Mask */ + EC_HOST_EVENT_SCI_MASK, + + /* SMI Mask */ + EC_HOST_EVENT_SMI_MASK, + + /* Mask of events that should be always reported in hostevents */ + EC_HOST_EVENT_ALWAYS_REPORT_MASK, + + /* Active wake mask */ + EC_HOST_EVENT_ACTIVE_WAKE_MASK, + + /* Lazy wake mask for S0ix */ + EC_HOST_EVENT_LAZY_WAKE_MASK_S0IX, + + /* Lazy wake mask for S3 */ + EC_HOST_EVENT_LAZY_WAKE_MASK_S3, + + /* Lazy wake mask for S5 */ + EC_HOST_EVENT_LAZY_WAKE_MASK_S5, +}; + +#define EC_CMD_HOST_EVENT 0x00A4 /*****************************************************************************/ /* Switch commands */ /* Enable/disable LCD backlight */ -#define EC_CMD_SWITCH_ENABLE_BKLIGHT 0x90 +#define EC_CMD_SWITCH_ENABLE_BKLIGHT 0x0090 struct ec_params_switch_enable_backlight { uint8_t enabled; -} __packed; +} __ec_align1; /* Enable/disable WLAN/Bluetooth */ -#define EC_CMD_SWITCH_ENABLE_WIRELESS 0x91 +#define EC_CMD_SWITCH_ENABLE_WIRELESS 0x0091 #define EC_VER_SWITCH_ENABLE_WIRELESS 1 /* Version 0 params; no response */ struct ec_params_switch_enable_wireless_v0 { uint8_t enabled; -} __packed; +} __ec_align1; /* Version 1 params */ struct ec_params_switch_enable_wireless_v1 { @@ -2330,7 +3665,7 @@ struct ec_params_switch_enable_wireless_v1 { /* Which flags to copy from suspend_flags */ uint8_t suspend_mask; -} __packed; +} __ec_align1; /* Version 1 response */ struct ec_response_switch_enable_wireless_v1 { @@ -2339,55 +3674,56 @@ struct ec_response_switch_enable_wireless_v1 { /* Flags to leave enabled in S3 */ uint8_t suspend_flags; -} __packed; +} __ec_align1; /*****************************************************************************/ /* GPIO commands. Only available on EC if write protect has been disabled. */ /* Set GPIO output value */ -#define EC_CMD_GPIO_SET 0x92 +#define EC_CMD_GPIO_SET 0x0092 struct ec_params_gpio_set { char name[32]; uint8_t val; -} __packed; +} __ec_align1; /* Get GPIO value */ -#define EC_CMD_GPIO_GET 0x93 +#define EC_CMD_GPIO_GET 0x0093 /* Version 0 of input params and response */ struct ec_params_gpio_get { char name[32]; -} __packed; +} __ec_align1; + struct ec_response_gpio_get { uint8_t val; -} __packed; +} __ec_align1; /* Version 1 of input params and response */ struct ec_params_gpio_get_v1 { uint8_t subcmd; union { - struct { + struct __ec_align1 { char name[32]; } get_value_by_name; - struct { + struct __ec_align1 { uint8_t index; } get_info; }; -} __packed; +} __ec_align1; struct ec_response_gpio_get_v1 { union { - struct { + struct __ec_align1 { uint8_t val; } get_value_by_name, get_count; - struct { + struct __ec_todo_unpacked { uint8_t val; char name[32]; uint32_t flags; } get_info; }; -} __packed; +} __ec_todo_packed; enum gpio_get_subcmd { EC_GPIO_GET_BY_NAME = 0, @@ -2399,25 +3735,28 @@ enum gpio_get_subcmd { /* I2C commands. Only available when flash write protect is unlocked. */ /* - * TODO(crosbug.com/p/23570): These commands are deprecated, and will be - * removed soon. Use EC_CMD_I2C_XFER instead. + * CAUTION: These commands are deprecated, and are not supported anymore in EC + * builds >= 8398.0.0 (see crosbug.com/p/23570). + * + * Use EC_CMD_I2C_PASSTHRU instead. */ /* Read I2C bus */ -#define EC_CMD_I2C_READ 0x94 +#define EC_CMD_I2C_READ 0x0094 struct ec_params_i2c_read { uint16_t addr; /* 8-bit address (7-bit shifted << 1) */ uint8_t read_size; /* Either 8 or 16. */ uint8_t port; uint8_t offset; -} __packed; +} __ec_align_size1; + struct ec_response_i2c_read { uint16_t data; -} __packed; +} __ec_align2; /* Write I2C bus */ -#define EC_CMD_I2C_WRITE 0x95 +#define EC_CMD_I2C_WRITE 0x0095 struct ec_params_i2c_write { uint16_t data; @@ -2425,7 +3764,7 @@ struct ec_params_i2c_write { uint8_t write_size; /* Either 8 or 16. */ uint8_t port; uint8_t offset; -} __packed; +} __ec_align_size1; /*****************************************************************************/ /* Charge state commands. Only available when flash write protect unlocked. */ @@ -2433,7 +3772,7 @@ struct ec_params_i2c_write { /* Force charge state machine to stop charging the battery or force it to * discharge the battery. */ -#define EC_CMD_CHARGE_CONTROL 0x96 +#define EC_CMD_CHARGE_CONTROL 0x0096 #define EC_VER_CHARGE_CONTROL 1 enum ec_charge_control_mode { @@ -2444,13 +3783,12 @@ enum ec_charge_control_mode { struct ec_params_charge_control { uint32_t mode; /* enum charge_control_mode */ -} __packed; +} __ec_align4; /*****************************************************************************/ -/* Console commands. Only available when flash write protect is unlocked. */ /* Snapshot console output buffer for use by EC_CMD_CONSOLE_READ. */ -#define EC_CMD_CONSOLE_SNAPSHOT 0x97 +#define EC_CMD_CONSOLE_SNAPSHOT 0x0097 /* * Read data from the saved snapshot. If the subcmd parameter is @@ -2464,7 +3802,7 @@ struct ec_params_charge_control { * Response is null-terminated string. Empty string, if there is no more * remaining output. */ -#define EC_CMD_CONSOLE_READ 0x98 +#define EC_CMD_CONSOLE_READ 0x0098 enum ec_console_read_subcmd { CONSOLE_READ_NEXT = 0, @@ -2473,7 +3811,7 @@ enum ec_console_read_subcmd { struct ec_params_console_read_v1 { uint8_t subcmd; /* enum ec_console_read_subcmd */ -} __packed; +} __ec_align1; /*****************************************************************************/ @@ -2484,14 +3822,13 @@ struct ec_params_console_read_v1 { * EC_RES_SUCCESS if the command was successful. * EC_RES_ERROR if the cut off command failed. */ +#define EC_CMD_BATTERY_CUT_OFF 0x0099 -#define EC_CMD_BATTERY_CUT_OFF 0x99 - -#define EC_BATTERY_CUTOFF_FLAG_AT_SHUTDOWN (1 << 0) +#define EC_BATTERY_CUTOFF_FLAG_AT_SHUTDOWN BIT(0) struct ec_params_battery_cutoff { uint8_t flags; -} __packed; +} __ec_align1; /*****************************************************************************/ /* USB port mux control. */ @@ -2499,11 +3836,11 @@ struct ec_params_battery_cutoff { /* * Switch USB mux or return to automatic switching. */ -#define EC_CMD_USB_MUX 0x9a +#define EC_CMD_USB_MUX 0x009A struct ec_params_usb_mux { uint8_t mux; -} __packed; +} __ec_align1; /*****************************************************************************/ /* LDOs / FETs control. */ @@ -2516,25 +3853,25 @@ enum ec_ldo_state { /* * Switch on/off a LDO. */ -#define EC_CMD_LDO_SET 0x9b +#define EC_CMD_LDO_SET 0x009B struct ec_params_ldo_set { uint8_t index; uint8_t state; -} __packed; +} __ec_align1; /* * Get LDO state. */ -#define EC_CMD_LDO_GET 0x9c +#define EC_CMD_LDO_GET 0x009C struct ec_params_ldo_get { uint8_t index; -} __packed; +} __ec_align1; struct ec_response_ldo_get { uint8_t state; -} __packed; +} __ec_align1; /*****************************************************************************/ /* Power info. */ @@ -2542,7 +3879,7 @@ struct ec_response_ldo_get { /* * Get power info. */ -#define EC_CMD_POWER_INFO 0x9d +#define EC_CMD_POWER_INFO 0x009D struct ec_response_power_info { uint32_t usb_dev_type; @@ -2550,21 +3887,21 @@ struct ec_response_power_info { uint16_t voltage_system; uint16_t current_system; uint16_t usb_current_limit; -} __packed; +} __ec_align4; /*****************************************************************************/ /* I2C passthru command */ -#define EC_CMD_I2C_PASSTHRU 0x9e +#define EC_CMD_I2C_PASSTHRU 0x009E /* Read data; if not present, message is a write */ -#define EC_I2C_FLAG_READ (1 << 15) +#define EC_I2C_FLAG_READ BIT(15) /* Mask for address */ #define EC_I2C_ADDR_MASK 0x3ff -#define EC_I2C_STATUS_NAK (1 << 0) /* Transfer was not acknowledged */ -#define EC_I2C_STATUS_TIMEOUT (1 << 1) /* Timeout during transfer */ +#define EC_I2C_STATUS_NAK BIT(0) /* Transfer was not acknowledged */ +#define EC_I2C_STATUS_TIMEOUT BIT(1) /* Timeout during transfer */ /* Any error */ #define EC_I2C_STATUS_ERROR (EC_I2C_STATUS_NAK | EC_I2C_STATUS_TIMEOUT) @@ -2572,49 +3909,49 @@ struct ec_response_power_info { struct ec_params_i2c_passthru_msg { uint16_t addr_flags; /* I2C slave address (7 or 10 bits) and flags */ uint16_t len; /* Number of bytes to read or write */ -} __packed; +} __ec_align2; struct ec_params_i2c_passthru { uint8_t port; /* I2C port number */ uint8_t num_msgs; /* Number of messages */ struct ec_params_i2c_passthru_msg msg[]; /* Data to write for all messages is concatenated here */ -} __packed; +} __ec_align2; struct ec_response_i2c_passthru { uint8_t i2c_status; /* Status flags (EC_I2C_STATUS_...) */ uint8_t num_msgs; /* Number of messages processed */ uint8_t data[]; /* Data read by messages concatenated here */ -} __packed; +} __ec_align1; /*****************************************************************************/ /* Power button hang detect */ -#define EC_CMD_HANG_DETECT 0x9f +#define EC_CMD_HANG_DETECT 0x009F /* Reasons to start hang detection timer */ /* Power button pressed */ -#define EC_HANG_START_ON_POWER_PRESS (1 << 0) +#define EC_HANG_START_ON_POWER_PRESS BIT(0) /* Lid closed */ -#define EC_HANG_START_ON_LID_CLOSE (1 << 1) +#define EC_HANG_START_ON_LID_CLOSE BIT(1) /* Lid opened */ -#define EC_HANG_START_ON_LID_OPEN (1 << 2) +#define EC_HANG_START_ON_LID_OPEN BIT(2) /* Start of AP S3->S0 transition (booting or resuming from suspend) */ -#define EC_HANG_START_ON_RESUME (1 << 3) +#define EC_HANG_START_ON_RESUME BIT(3) /* Reasons to cancel hang detection */ /* Power button released */ -#define EC_HANG_STOP_ON_POWER_RELEASE (1 << 8) +#define EC_HANG_STOP_ON_POWER_RELEASE BIT(8) /* Any host command from AP received */ -#define EC_HANG_STOP_ON_HOST_COMMAND (1 << 9) +#define EC_HANG_STOP_ON_HOST_COMMAND BIT(9) /* Stop on end of AP S0->S3 transition (suspending or shutting down) */ -#define EC_HANG_STOP_ON_SUSPEND (1 << 10) +#define EC_HANG_STOP_ON_SUSPEND BIT(10) /* * If this flag is set, all the other fields are ignored, and the hang detect @@ -2622,14 +3959,14 @@ struct ec_response_i2c_passthru { * without reconfiguring any of the other hang detect settings. Note that * you must previously have configured the timeouts. */ -#define EC_HANG_START_NOW (1 << 30) +#define EC_HANG_START_NOW BIT(30) /* * If this flag is set, all the other fields are ignored (including * EC_HANG_START_NOW). This provides the AP a way to stop the hang timer * without reconfiguring any of the other hang detect settings. */ -#define EC_HANG_STOP_NOW (1 << 31) +#define EC_HANG_STOP_NOW BIT(31) struct ec_params_hang_detect { /* Flags; see EC_HANG_* */ @@ -2640,7 +3977,7 @@ struct ec_params_hang_detect { /* Timeout in msec before generating warm reboot, if enabled */ uint16_t warm_reboot_timeout_msec; -} __packed; +} __ec_align4; /*****************************************************************************/ /* Commands for battery charging */ @@ -2649,7 +3986,7 @@ struct ec_params_hang_detect { * This is the single catch-all host command to exchange data regarding the * charge state machine (v2 and up). */ -#define EC_CMD_CHARGE_STATE 0xa0 +#define EC_CMD_CHARGE_STATE 0x00A0 /* Subcommands for this host command */ enum charge_state_command { @@ -2669,6 +4006,11 @@ enum charge_state_params { CS_PARAM_CHG_INPUT_CURRENT, /* charger input current limit */ CS_PARAM_CHG_STATUS, /* charger-specific status */ CS_PARAM_CHG_OPTION, /* charger-specific options */ + CS_PARAM_LIMIT_POWER, /* + * Check if power is limited due to + * low battery and / or a weak external + * charger. READ ONLY. + */ /* How many so far? */ CS_NUM_BASE_PARAMS, @@ -2676,30 +4018,39 @@ enum charge_state_params { CS_PARAM_CUSTOM_PROFILE_MIN = 0x10000, CS_PARAM_CUSTOM_PROFILE_MAX = 0x1ffff, + /* Range for CONFIG_CHARGE_STATE_DEBUG params */ + CS_PARAM_DEBUG_MIN = 0x20000, + CS_PARAM_DEBUG_CTL_MODE = 0x20000, + CS_PARAM_DEBUG_MANUAL_MODE, + CS_PARAM_DEBUG_SEEMS_DEAD, + CS_PARAM_DEBUG_SEEMS_DISCONNECTED, + CS_PARAM_DEBUG_BATT_REMOVED, + CS_PARAM_DEBUG_MANUAL_CURRENT, + CS_PARAM_DEBUG_MANUAL_VOLTAGE, + CS_PARAM_DEBUG_MAX = 0x2ffff, + /* Other custom param ranges go here... */ }; struct ec_params_charge_state { uint8_t cmd; /* enum charge_state_command */ union { - struct { - /* no args */ - } get_state; + /* get_state has no args */ - struct { + struct __ec_todo_unpacked { uint32_t param; /* enum charge_state_param */ } get_param; - struct { + struct __ec_todo_unpacked { uint32_t param; /* param to set */ uint32_t value; /* value to set */ } set_param; }; -} __packed; +} __ec_todo_packed; struct ec_response_charge_state { union { - struct { + struct __ec_align4 { int ac; int chg_voltage; int chg_current; @@ -2707,24 +4058,23 @@ struct ec_response_charge_state { int batt_state_of_charge; } get_state; - struct { + struct __ec_align4 { uint32_t value; } get_param; - struct { - /* no return values */ - } set_param; + + /* set_param returns no args */ }; -} __packed; +} __ec_align4; /* * Set maximum battery charging current. */ -#define EC_CMD_CHARGE_CURRENT_LIMIT 0xa1 +#define EC_CMD_CHARGE_CURRENT_LIMIT 0x00A1 struct ec_params_current_limit { uint32_t limit; /* in mA */ -} __packed; +} __ec_align4; /* * Set maximum external voltage / current. @@ -2735,23 +4085,69 @@ struct ec_params_current_limit { struct ec_params_external_power_limit_v1 { uint16_t current_lim; /* in mA, or EC_POWER_LIMIT_NONE to clear limit */ uint16_t voltage_lim; /* in mV, or EC_POWER_LIMIT_NONE to clear limit */ -} __packed; +} __ec_align2; #define EC_POWER_LIMIT_NONE 0xffff +/* + * Set maximum voltage & current of a dedicated charge port + */ +#define EC_CMD_OVERRIDE_DEDICATED_CHARGER_LIMIT 0x00A3 + +struct ec_params_dedicated_charger_limit { + uint16_t current_lim; /* in mA */ + uint16_t voltage_lim; /* in mV */ +} __ec_align2; + +/*****************************************************************************/ +/* Hibernate/Deep Sleep Commands */ + +/* Set the delay before going into hibernation. */ +#define EC_CMD_HIBERNATION_DELAY 0x00A8 + +struct ec_params_hibernation_delay { + /* + * Seconds to wait in G3 before hibernate. Pass in 0 to read the + * current settings without changing them. + */ + uint32_t seconds; +} __ec_align4; + +struct ec_response_hibernation_delay { + /* + * The current time in seconds in which the system has been in the G3 + * state. This value is reset if the EC transitions out of G3. + */ + uint32_t time_g3; + + /* + * The current time remaining in seconds until the EC should hibernate. + * This value is also reset if the EC transitions out of G3. + */ + uint32_t time_remaining; + + /* + * The current time in seconds that the EC should wait in G3 before + * hibernating. + */ + uint32_t hibernate_delay; +} __ec_align4; + /* Inform the EC when entering a sleep state */ -#define EC_CMD_HOST_SLEEP_EVENT 0xa9 +#define EC_CMD_HOST_SLEEP_EVENT 0x00A9 enum host_sleep_event { HOST_SLEEP_EVENT_S3_SUSPEND = 1, HOST_SLEEP_EVENT_S3_RESUME = 2, HOST_SLEEP_EVENT_S0IX_SUSPEND = 3, - HOST_SLEEP_EVENT_S0IX_RESUME = 4 + HOST_SLEEP_EVENT_S0IX_RESUME = 4, + /* S3 suspend with additional enabled wake sources */ + HOST_SLEEP_EVENT_S3_WAKEABLE_SUSPEND = 5, }; struct ec_params_host_sleep_event { uint8_t sleep_event; -} __packed; +} __ec_align1; /* * Use a default timeout value (CONFIG_SLEEP_TIMEOUT_MS) for detecting sleep @@ -2782,7 +4178,7 @@ struct ec_params_host_sleep_event_v1 { /* No parameters for non-suspend messages. */ }; -} __packed; +} __ec_align2; /* A timeout occurred when this bit is set */ #define EC_HOST_RESUME_SLEEP_TIMEOUT 0x80000000 @@ -2808,42 +4204,72 @@ struct ec_response_host_sleep_event_v1 { /* No response fields for non-resume messages. */ }; -} __packed; +} __ec_align4; + +/*****************************************************************************/ +/* Device events */ +#define EC_CMD_DEVICE_EVENT 0x00AA + +enum ec_device_event { + EC_DEVICE_EVENT_TRACKPAD, + EC_DEVICE_EVENT_DSP, + EC_DEVICE_EVENT_WIFI, +}; + +enum ec_device_event_param { + /* Get and clear pending device events */ + EC_DEVICE_EVENT_PARAM_GET_CURRENT_EVENTS, + /* Get device event mask */ + EC_DEVICE_EVENT_PARAM_GET_ENABLED_EVENTS, + /* Set device event mask */ + EC_DEVICE_EVENT_PARAM_SET_ENABLED_EVENTS, +}; + +#define EC_DEVICE_EVENT_MASK(event_code) BIT(event_code % 32) + +struct ec_params_device_event { + uint32_t event_mask; + uint8_t param; +} __ec_align_size1; + +struct ec_response_device_event { + uint32_t event_mask; +} __ec_align4; /*****************************************************************************/ /* Smart battery pass-through */ /* Get / Set 16-bit smart battery registers */ -#define EC_CMD_SB_READ_WORD 0xb0 -#define EC_CMD_SB_WRITE_WORD 0xb1 +#define EC_CMD_SB_READ_WORD 0x00B0 +#define EC_CMD_SB_WRITE_WORD 0x00B1 /* Get / Set string smart battery parameters * formatted as SMBUS "block". */ -#define EC_CMD_SB_READ_BLOCK 0xb2 -#define EC_CMD_SB_WRITE_BLOCK 0xb3 +#define EC_CMD_SB_READ_BLOCK 0x00B2 +#define EC_CMD_SB_WRITE_BLOCK 0x00B3 struct ec_params_sb_rd { uint8_t reg; -} __packed; +} __ec_align1; struct ec_response_sb_rd_word { uint16_t value; -} __packed; +} __ec_align2; struct ec_params_sb_wr_word { uint8_t reg; uint16_t value; -} __packed; +} __ec_align1; struct ec_response_sb_rd_block { uint8_t data[32]; -} __packed; +} __ec_align1; struct ec_params_sb_wr_block { uint8_t reg; uint16_t data[32]; -} __packed; +} __ec_align1; /*****************************************************************************/ /* Battery vendor parameters @@ -2854,7 +4280,7 @@ struct ec_params_sb_wr_block { * requested value. */ -#define EC_CMD_BATTERY_VENDOR_PARAM 0xb4 +#define EC_CMD_BATTERY_VENDOR_PARAM 0x00B4 enum ec_battery_vendor_param_mode { BATTERY_VENDOR_PARAM_MODE_GET = 0, @@ -2865,16 +4291,187 @@ struct ec_params_battery_vendor_param { uint32_t param; uint32_t value; uint8_t mode; -} __packed; +} __ec_align_size1; struct ec_response_battery_vendor_param { uint32_t value; -} __packed; +} __ec_align4; + +/*****************************************************************************/ +/* + * Smart Battery Firmware Update Commands + */ +#define EC_CMD_SB_FW_UPDATE 0x00B5 + +enum ec_sb_fw_update_subcmd { + EC_SB_FW_UPDATE_PREPARE = 0x0, + EC_SB_FW_UPDATE_INFO = 0x1, /*query sb info */ + EC_SB_FW_UPDATE_BEGIN = 0x2, /*check if protected */ + EC_SB_FW_UPDATE_WRITE = 0x3, /*check if protected */ + EC_SB_FW_UPDATE_END = 0x4, + EC_SB_FW_UPDATE_STATUS = 0x5, + EC_SB_FW_UPDATE_PROTECT = 0x6, + EC_SB_FW_UPDATE_MAX = 0x7, +}; + +#define SB_FW_UPDATE_CMD_WRITE_BLOCK_SIZE 32 +#define SB_FW_UPDATE_CMD_STATUS_SIZE 2 +#define SB_FW_UPDATE_CMD_INFO_SIZE 8 + +struct ec_sb_fw_update_header { + uint16_t subcmd; /* enum ec_sb_fw_update_subcmd */ + uint16_t fw_id; /* firmware id */ +} __ec_align4; + +struct ec_params_sb_fw_update { + struct ec_sb_fw_update_header hdr; + union { + /* EC_SB_FW_UPDATE_PREPARE = 0x0 */ + /* EC_SB_FW_UPDATE_INFO = 0x1 */ + /* EC_SB_FW_UPDATE_BEGIN = 0x2 */ + /* EC_SB_FW_UPDATE_END = 0x4 */ + /* EC_SB_FW_UPDATE_STATUS = 0x5 */ + /* EC_SB_FW_UPDATE_PROTECT = 0x6 */ + /* Those have no args */ + + /* EC_SB_FW_UPDATE_WRITE = 0x3 */ + struct __ec_align4 { + uint8_t data[SB_FW_UPDATE_CMD_WRITE_BLOCK_SIZE]; + } write; + }; +} __ec_align4; + +struct ec_response_sb_fw_update { + union { + /* EC_SB_FW_UPDATE_INFO = 0x1 */ + struct __ec_align1 { + uint8_t data[SB_FW_UPDATE_CMD_INFO_SIZE]; + } info; + + /* EC_SB_FW_UPDATE_STATUS = 0x5 */ + struct __ec_align1 { + uint8_t data[SB_FW_UPDATE_CMD_STATUS_SIZE]; + } status; + }; +} __ec_align1; + +/* + * Entering Verified Boot Mode Command + * Default mode is VBOOT_MODE_NORMAL if EC did not receive this command. + * Valid Modes are: normal, developer, and recovery. + */ +#define EC_CMD_ENTERING_MODE 0x00B6 + +struct ec_params_entering_mode { + int vboot_mode; +} __ec_align4; + +#define VBOOT_MODE_NORMAL 0 +#define VBOOT_MODE_DEVELOPER 1 +#define VBOOT_MODE_RECOVERY 2 /*****************************************************************************/ +/* + * I2C passthru protection command: Protects I2C tunnels against access on + * certain addresses (board-specific). + */ +#define EC_CMD_I2C_PASSTHRU_PROTECT 0x00B7 + +enum ec_i2c_passthru_protect_subcmd { + EC_CMD_I2C_PASSTHRU_PROTECT_STATUS = 0x0, + EC_CMD_I2C_PASSTHRU_PROTECT_ENABLE = 0x1, +}; + +struct ec_params_i2c_passthru_protect { + uint8_t subcmd; + uint8_t port; /* I2C port number */ +} __ec_align1; + +struct ec_response_i2c_passthru_protect { + uint8_t status; /* Status flags (0: unlocked, 1: locked) */ +} __ec_align1; + + +/*****************************************************************************/ +/* + * HDMI CEC commands + * + * These commands are for sending and receiving message via HDMI CEC + */ + +#define MAX_CEC_MSG_LEN 16 + +/* CEC message from the AP to be written on the CEC bus */ +#define EC_CMD_CEC_WRITE_MSG 0x00B8 + +/** + * struct ec_params_cec_write - Message to write to the CEC bus + * @msg: message content to write to the CEC bus + */ +struct ec_params_cec_write { + uint8_t msg[MAX_CEC_MSG_LEN]; +} __ec_align1; + +/* Set various CEC parameters */ +#define EC_CMD_CEC_SET 0x00BA + +/** + * struct ec_params_cec_set - CEC parameters set + * @cmd: parameter type, can be CEC_CMD_ENABLE or CEC_CMD_LOGICAL_ADDRESS + * @val: in case cmd is CEC_CMD_ENABLE, this field can be 0 to disable CEC + * or 1 to enable CEC functionality, in case cmd is + * CEC_CMD_LOGICAL_ADDRESS, this field encodes the requested logical + * address between 0 and 15 or 0xff to unregister + */ +struct ec_params_cec_set { + uint8_t cmd; /* enum cec_command */ + uint8_t val; +} __ec_align1; + +/* Read various CEC parameters */ +#define EC_CMD_CEC_GET 0x00BB + +/** + * struct ec_params_cec_get - CEC parameters get + * @cmd: parameter type, can be CEC_CMD_ENABLE or CEC_CMD_LOGICAL_ADDRESS + */ +struct ec_params_cec_get { + uint8_t cmd; /* enum cec_command */ +} __ec_align1; + +/** + * struct ec_response_cec_get - CEC parameters get response + * @val: in case cmd was CEC_CMD_ENABLE, this field will 0 if CEC is + * disabled or 1 if CEC functionality is enabled, + * in case cmd was CEC_CMD_LOGICAL_ADDRESS, this will encode the + * configured logical address between 0 and 15 or 0xff if unregistered + */ +struct ec_response_cec_get { + uint8_t val; +} __ec_align1; + +/* CEC parameters command */ +enum cec_command { + /* CEC reading, writing and events enable */ + CEC_CMD_ENABLE, + /* CEC logical address */ + CEC_CMD_LOGICAL_ADDRESS, +}; + +/* Events from CEC to AP */ +enum mkbp_cec_event { + /* Outgoing message was acknowledged by a follower */ + EC_MKBP_CEC_SEND_OK = BIT(0), + /* Outgoing message was not acknowledged */ + EC_MKBP_CEC_SEND_FAILED = BIT(1), +}; + +/*****************************************************************************/ + /* Commands for I2S recording on audio codec. */ #define EC_CMD_CODEC_I2S 0x00BC +#define EC_WOV_I2S_SAMPLE_RATE 48000 enum ec_codec_i2s_subcmd { EC_CODEC_SET_SAMPLE_DEPTH = 0x0, @@ -2884,6 +4481,7 @@ enum ec_codec_i2s_subcmd { EC_CODEC_I2S_SET_CONFIG = 0x4, EC_CODEC_I2S_SET_TDM_CONFIG = 0x5, EC_CODEC_I2S_SET_BCLK = 0x6, + EC_CODEC_I2S_SUBCMD_COUNT = 0x7, }; enum ec_sample_depth_value { @@ -2900,10 +4498,23 @@ enum ec_i2s_config { EC_DAI_FMT_PCM_TDM = 5, }; -struct ec_param_codec_i2s { - /* - * enum ec_codec_i2s_subcmd - */ +/* + * For subcommand EC_CODEC_GET_GAIN. + */ +struct __ec_align1 ec_codec_i2s_gain { + uint8_t left; + uint8_t right; +}; + +struct __ec_todo_unpacked ec_param_codec_i2s_tdm { + int16_t ch0_delay; /* 0 to 496 */ + int16_t ch1_delay; /* -1 to 496 */ + uint8_t adjacent_to_ch0; + uint8_t adjacent_to_ch1; +}; + +struct __ec_todo_packed ec_param_codec_i2s { + /* enum ec_codec_i2s_subcmd */ uint8_t cmd; union { /* @@ -2916,10 +4527,7 @@ struct ec_param_codec_i2s { * EC_CODEC_SET_GAIN * Value should be 0~43 for both channels. */ - struct ec_param_codec_i2s_set_gain { - uint8_t left; - uint8_t right; - } __packed gain; + struct ec_codec_i2s_gain gain; /* * EC_CODEC_I2S_ENABLE @@ -2928,7 +4536,7 @@ struct ec_param_codec_i2s { uint8_t i2s_enable; /* - * EC_CODEC_I2S_SET_COFNIG + * EC_CODEC_I2S_SET_CONFIG * Value should be one of ec_i2s_config. */ uint8_t i2s_config; @@ -2937,33 +4545,15 @@ struct ec_param_codec_i2s { * EC_CODEC_I2S_SET_TDM_CONFIG * Value should be one of ec_i2s_config. */ - struct ec_param_codec_i2s_tdm { - /* - * 0 to 496 - */ - int16_t ch0_delay; - /* - * -1 to 496 - */ - int16_t ch1_delay; - uint8_t adjacent_to_ch0; - uint8_t adjacent_to_ch1; - } __packed tdm_param; + struct ec_param_codec_i2s_tdm tdm_param; /* * EC_CODEC_I2S_SET_BCLK */ uint32_t bclk; }; -} __packed; +}; -/* - * For subcommand EC_CODEC_GET_GAIN. - */ -struct ec_response_codec_gain { - uint8_t left; - uint8_t right; -} __packed; /*****************************************************************************/ /* System commands */ @@ -2972,27 +4562,29 @@ struct ec_response_codec_gain { * TODO(crosbug.com/p/23747): This is a confusing name, since it doesn't * necessarily reboot the EC. Rename to "image" or something similar? */ -#define EC_CMD_REBOOT_EC 0xd2 +#define EC_CMD_REBOOT_EC 0x00D2 /* Command */ enum ec_reboot_cmd { EC_REBOOT_CANCEL = 0, /* Cancel a pending reboot */ EC_REBOOT_JUMP_RO = 1, /* Jump to RO without rebooting */ - EC_REBOOT_JUMP_RW = 2, /* Jump to RW without rebooting */ + EC_REBOOT_JUMP_RW = 2, /* Jump to active RW without rebooting */ /* (command 3 was jump to RW-B) */ EC_REBOOT_COLD = 4, /* Cold-reboot */ EC_REBOOT_DISABLE_JUMP = 5, /* Disable jump until next reboot */ - EC_REBOOT_HIBERNATE = 6 /* Hibernate EC */ + EC_REBOOT_HIBERNATE = 6, /* Hibernate EC */ + EC_REBOOT_HIBERNATE_CLEAR_AP_OFF = 7, /* and clears AP_OFF flag */ }; /* Flags for ec_params_reboot_ec.reboot_flags */ -#define EC_REBOOT_FLAG_RESERVED0 (1 << 0) /* Was recovery request */ -#define EC_REBOOT_FLAG_ON_AP_SHUTDOWN (1 << 1) /* Reboot after AP shutdown */ +#define EC_REBOOT_FLAG_RESERVED0 BIT(0) /* Was recovery request */ +#define EC_REBOOT_FLAG_ON_AP_SHUTDOWN BIT(1) /* Reboot after AP shutdown */ +#define EC_REBOOT_FLAG_SWITCH_RW_SLOT BIT(2) /* Switch RW slot */ struct ec_params_reboot_ec { uint8_t cmd; /* enum ec_reboot_cmd */ uint8_t flags; /* See EC_REBOOT_FLAG_* */ -} __packed; +} __ec_align1; /* * Get information on last EC panic. @@ -3000,196 +4592,7 @@ struct ec_params_reboot_ec { * Returns variable-length platform-dependent panic information. See panic.h * for details. */ -#define EC_CMD_GET_PANIC_INFO 0xd3 - -/*****************************************************************************/ -/* - * ACPI commands - * - * These are valid ONLY on the ACPI command/data port. - */ - -/* - * ACPI Read Embedded Controller - * - * This reads from ACPI memory space on the EC (EC_ACPI_MEM_*). - * - * Use the following sequence: - * - * - Write EC_CMD_ACPI_READ to EC_LPC_ADDR_ACPI_CMD - * - Wait for EC_LPC_CMDR_PENDING bit to clear - * - Write address to EC_LPC_ADDR_ACPI_DATA - * - Wait for EC_LPC_CMDR_DATA bit to set - * - Read value from EC_LPC_ADDR_ACPI_DATA - */ -#define EC_CMD_ACPI_READ 0x80 - -/* - * ACPI Write Embedded Controller - * - * This reads from ACPI memory space on the EC (EC_ACPI_MEM_*). - * - * Use the following sequence: - * - * - Write EC_CMD_ACPI_WRITE to EC_LPC_ADDR_ACPI_CMD - * - Wait for EC_LPC_CMDR_PENDING bit to clear - * - Write address to EC_LPC_ADDR_ACPI_DATA - * - Wait for EC_LPC_CMDR_PENDING bit to clear - * - Write value to EC_LPC_ADDR_ACPI_DATA - */ -#define EC_CMD_ACPI_WRITE 0x81 - -/* - * ACPI Query Embedded Controller - * - * This clears the lowest-order bit in the currently pending host events, and - * sets the result code to the 1-based index of the bit (event 0x00000001 = 1, - * event 0x80000000 = 32), or 0 if no event was pending. - */ -#define EC_CMD_ACPI_QUERY_EVENT 0x84 - -/* Valid addresses in ACPI memory space, for read/write commands */ - -/* Memory space version; set to EC_ACPI_MEM_VERSION_CURRENT */ -#define EC_ACPI_MEM_VERSION 0x00 -/* - * Test location; writing value here updates test compliment byte to (0xff - - * value). - */ -#define EC_ACPI_MEM_TEST 0x01 -/* Test compliment; writes here are ignored. */ -#define EC_ACPI_MEM_TEST_COMPLIMENT 0x02 - -/* Keyboard backlight brightness percent (0 - 100) */ -#define EC_ACPI_MEM_KEYBOARD_BACKLIGHT 0x03 -/* DPTF Target Fan Duty (0-100, 0xff for auto/none) */ -#define EC_ACPI_MEM_FAN_DUTY 0x04 - -/* - * DPTF temp thresholds. Any of the EC's temp sensors can have up to two - * independent thresholds attached to them. The current value of the ID - * register determines which sensor is affected by the THRESHOLD and COMMIT - * registers. The THRESHOLD register uses the same EC_TEMP_SENSOR_OFFSET scheme - * as the memory-mapped sensors. The COMMIT register applies those settings. - * - * The spec does not mandate any way to read back the threshold settings - * themselves, but when a threshold is crossed the AP needs a way to determine - * which sensor(s) are responsible. Each reading of the ID register clears and - * returns one sensor ID that has crossed one of its threshold (in either - * direction) since the last read. A value of 0xFF means "no new thresholds - * have tripped". Setting or enabling the thresholds for a sensor will clear - * the unread event count for that sensor. - */ -#define EC_ACPI_MEM_TEMP_ID 0x05 -#define EC_ACPI_MEM_TEMP_THRESHOLD 0x06 -#define EC_ACPI_MEM_TEMP_COMMIT 0x07 -/* - * Here are the bits for the COMMIT register: - * bit 0 selects the threshold index for the chosen sensor (0/1) - * bit 1 enables/disables the selected threshold (0 = off, 1 = on) - * Each write to the commit register affects one threshold. - */ -#define EC_ACPI_MEM_TEMP_COMMIT_SELECT_MASK (1 << 0) -#define EC_ACPI_MEM_TEMP_COMMIT_ENABLE_MASK (1 << 1) -/* - * Example: - * - * Set the thresholds for sensor 2 to 50 C and 60 C: - * write 2 to [0x05] -- select temp sensor 2 - * write 0x7b to [0x06] -- C_TO_K(50) - EC_TEMP_SENSOR_OFFSET - * write 0x2 to [0x07] -- enable threshold 0 with this value - * write 0x85 to [0x06] -- C_TO_K(60) - EC_TEMP_SENSOR_OFFSET - * write 0x3 to [0x07] -- enable threshold 1 with this value - * - * Disable the 60 C threshold, leaving the 50 C threshold unchanged: - * write 2 to [0x05] -- select temp sensor 2 - * write 0x1 to [0x07] -- disable threshold 1 - */ - -/* DPTF battery charging current limit */ -#define EC_ACPI_MEM_CHARGING_LIMIT 0x08 - -/* Charging limit is specified in 64 mA steps */ -#define EC_ACPI_MEM_CHARGING_LIMIT_STEP_MA 64 -/* Value to disable DPTF battery charging limit */ -#define EC_ACPI_MEM_CHARGING_LIMIT_DISABLED 0xff - -/* Current version of ACPI memory address space */ -#define EC_ACPI_MEM_VERSION_CURRENT 1 - - -/*****************************************************************************/ -/* - * HDMI CEC commands - * - * These commands are for sending and receiving message via HDMI CEC - */ -#define EC_MAX_CEC_MSG_LEN 16 - -/* CEC message from the AP to be written on the CEC bus */ -#define EC_CMD_CEC_WRITE_MSG 0x00B8 - -/** - * struct ec_params_cec_write - Message to write to the CEC bus - * @msg: message content to write to the CEC bus - */ -struct ec_params_cec_write { - uint8_t msg[EC_MAX_CEC_MSG_LEN]; -} __packed; - -/* Set various CEC parameters */ -#define EC_CMD_CEC_SET 0x00BA - -/** - * struct ec_params_cec_set - CEC parameters set - * @cmd: parameter type, can be CEC_CMD_ENABLE or CEC_CMD_LOGICAL_ADDRESS - * @val: in case cmd is CEC_CMD_ENABLE, this field can be 0 to disable CEC - * or 1 to enable CEC functionality, in case cmd is CEC_CMD_LOGICAL_ADDRESS, - * this field encodes the requested logical address between 0 and 15 - * or 0xff to unregister - */ -struct ec_params_cec_set { - uint8_t cmd; /* enum cec_command */ - uint8_t val; -} __packed; - -/* Read various CEC parameters */ -#define EC_CMD_CEC_GET 0x00BB - -/** - * struct ec_params_cec_get - CEC parameters get - * @cmd: parameter type, can be CEC_CMD_ENABLE or CEC_CMD_LOGICAL_ADDRESS - */ -struct ec_params_cec_get { - uint8_t cmd; /* enum cec_command */ -} __packed; - -/** - * struct ec_response_cec_get - CEC parameters get response - * @val: in case cmd was CEC_CMD_ENABLE, this field will 0 if CEC is - * disabled or 1 if CEC functionality is enabled, - * in case cmd was CEC_CMD_LOGICAL_ADDRESS, this will encode the - * configured logical address between 0 and 15 or 0xff if unregistered - */ -struct ec_response_cec_get { - uint8_t val; -} __packed; - -/* CEC parameters command */ -enum ec_cec_command { - /* CEC reading, writing and events enable */ - CEC_CMD_ENABLE, - /* CEC logical address */ - CEC_CMD_LOGICAL_ADDRESS, -}; - -/* Events from CEC to AP */ -enum mkbp_cec_event { - /* Outgoing message was acknowledged by a follower */ - EC_MKBP_CEC_SEND_OK = BIT(0), - /* Outgoing message was not acknowledged */ - EC_MKBP_CEC_SEND_FAILED = BIT(1), -}; +#define EC_CMD_GET_PANIC_INFO 0x00D3 /*****************************************************************************/ /* @@ -3208,7 +4611,7 @@ enum mkbp_cec_event { * * Use EC_CMD_REBOOT_EC to reboot the EC more politely. */ -#define EC_CMD_REBOOT 0xd1 /* Think "die" */ +#define EC_CMD_REBOOT 0x00D1 /* Think "die" */ /* * Resend last response (not supported on LPC). @@ -3217,7 +4620,7 @@ enum mkbp_cec_event { * there was no previous command, or the previous command's response was too * big to save. */ -#define EC_CMD_RESEND_RESPONSE 0xdb +#define EC_CMD_RESEND_RESPONSE 0x00DB /* * This header byte on a command indicate version 0. Any header byte less @@ -3229,9 +4632,7 @@ enum mkbp_cec_event { * * The old EC interface must not use commands 0xdc or higher. */ -#define EC_CMD_VERSION0 0xdc - -#endif /* !__ACPI__ */ +#define EC_CMD_VERSION0 0x00DC /*****************************************************************************/ /* @@ -3241,21 +4642,56 @@ enum mkbp_cec_event { */ /* EC to PD MCU exchange status command */ -#define EC_CMD_PD_EXCHANGE_STATUS 0x100 +#define EC_CMD_PD_EXCHANGE_STATUS 0x0100 +#define EC_VER_PD_EXCHANGE_STATUS 2 + +enum pd_charge_state { + PD_CHARGE_NO_CHANGE = 0, /* Don't change charge state */ + PD_CHARGE_NONE, /* No charging allowed */ + PD_CHARGE_5V, /* 5V charging only */ + PD_CHARGE_MAX /* Charge at max voltage */ +}; /* Status of EC being sent to PD */ +#define EC_STATUS_HIBERNATING BIT(0) + struct ec_params_pd_status { - int8_t batt_soc; /* battery state of charge */ -} __packed; + uint8_t status; /* EC status */ + int8_t batt_soc; /* battery state of charge */ + uint8_t charge_state; /* charging state (from enum pd_charge_state) */ +} __ec_align1; /* Status of PD being sent back to EC */ +#define PD_STATUS_HOST_EVENT BIT(0) /* Forward host event to AP */ +#define PD_STATUS_IN_RW BIT(1) /* Running RW image */ +#define PD_STATUS_JUMPED_TO_IMAGE BIT(2) /* Current image was jumped to */ +#define PD_STATUS_TCPC_ALERT_0 BIT(3) /* Alert active in port 0 TCPC */ +#define PD_STATUS_TCPC_ALERT_1 BIT(4) /* Alert active in port 1 TCPC */ +#define PD_STATUS_TCPC_ALERT_2 BIT(5) /* Alert active in port 2 TCPC */ +#define PD_STATUS_TCPC_ALERT_3 BIT(6) /* Alert active in port 3 TCPC */ +#define PD_STATUS_EC_INT_ACTIVE (PD_STATUS_TCPC_ALERT_0 | \ + PD_STATUS_TCPC_ALERT_1 | \ + PD_STATUS_HOST_EVENT) struct ec_response_pd_status { - int8_t status; /* PD MCU status */ - uint32_t curr_lim_ma; /* input current limit */ -} __packed; + uint32_t curr_lim_ma; /* input current limit */ + uint16_t status; /* PD MCU status */ + int8_t active_charge_port; /* active charging port */ +} __ec_align_size1; + +/* AP to PD MCU host event status command, cleared on read */ +#define EC_CMD_PD_HOST_EVENT_STATUS 0x0104 + +/* PD MCU host event status bits */ +#define PD_EVENT_UPDATE_DEVICE BIT(0) +#define PD_EVENT_POWER_CHANGE BIT(1) +#define PD_EVENT_IDENTITY_RECEIVED BIT(2) +#define PD_EVENT_DATA_SWAP BIT(3) +struct ec_response_host_event_status { + uint32_t status; /* PD MCU host event status */ +} __ec_align4; /* Set USB type-C port role and muxes */ -#define EC_CMD_USB_PD_CONTROL 0x101 +#define EC_CMD_USB_PD_CONTROL 0x0101 enum usb_pd_control_role { USB_PD_CTRL_ROLE_NO_CHANGE = 0, @@ -3263,6 +4699,8 @@ enum usb_pd_control_role { USB_PD_CTRL_ROLE_TOGGLE_OFF = 2, USB_PD_CTRL_ROLE_FORCE_SINK = 3, USB_PD_CTRL_ROLE_FORCE_SOURCE = 4, + USB_PD_CTRL_ROLE_FREEZE = 5, + USB_PD_CTRL_ROLE_COUNT }; enum usb_pd_control_mux { @@ -3272,6 +4710,7 @@ enum usb_pd_control_mux { USB_PD_CTRL_MUX_DP = 3, USB_PD_CTRL_MUX_DOCK = 4, USB_PD_CTRL_MUX_AUTO = 5, + USB_PD_CTRL_MUX_COUNT }; enum usb_pd_control_swap { @@ -3287,11 +4726,11 @@ struct ec_params_usb_pd_control { uint8_t role; uint8_t mux; uint8_t swap; -} __packed; +} __ec_align1; -#define PD_CTRL_RESP_ENABLED_COMMS (1 << 0) /* Communication enabled */ -#define PD_CTRL_RESP_ENABLED_CONNECTED (1 << 1) /* Device connected */ -#define PD_CTRL_RESP_ENABLED_PD_CAPABLE (1 << 2) /* Partner is PD capable */ +#define PD_CTRL_RESP_ENABLED_COMMS BIT(0) /* Communication enabled */ +#define PD_CTRL_RESP_ENABLED_CONNECTED BIT(1) /* Device connected */ +#define PD_CTRL_RESP_ENABLED_PD_CAPABLE BIT(2) /* Partner is PD capable */ #define PD_CTRL_RESP_ROLE_POWER BIT(0) /* 0=SNK/1=SRC */ #define PD_CTRL_RESP_ROLE_DATA BIT(1) /* 0=UFP/1=DFP */ @@ -3301,28 +4740,54 @@ struct ec_params_usb_pd_control { #define PD_CTRL_RESP_ROLE_USB_COMM BIT(5) /* Partner USB comm capable */ #define PD_CTRL_RESP_ROLE_EXT_POWERED BIT(6) /* Partner externally powerd */ +struct ec_response_usb_pd_control { + uint8_t enabled; + uint8_t role; + uint8_t polarity; + uint8_t state; +} __ec_align1; + struct ec_response_usb_pd_control_v1 { uint8_t enabled; uint8_t role; uint8_t polarity; char state[32]; -} __packed; +} __ec_align1; + +/* Values representing usbc PD CC state */ +#define USBC_PD_CC_NONE 0 /* No accessory connected */ +#define USBC_PD_CC_NO_UFP 1 /* No UFP accessory connected */ +#define USBC_PD_CC_AUDIO_ACC 2 /* Audio accessory connected */ +#define USBC_PD_CC_DEBUG_ACC 3 /* Debug accessory connected */ +#define USBC_PD_CC_UFP_ATTACHED 4 /* UFP attached to usbc */ +#define USBC_PD_CC_DFP_ATTACHED 5 /* DPF attached to usbc */ + +struct ec_response_usb_pd_control_v2 { + uint8_t enabled; + uint8_t role; + uint8_t polarity; + char state[32]; + uint8_t cc_state; /* USBC_PD_CC_*Encoded cc state */ + uint8_t dp_mode; /* Current DP pin mode (MODE_DP_PIN_[A-E]) */ + /* CL:1500994 Current cable type */ + uint8_t reserved_cable_type; +} __ec_align1; -#define EC_CMD_USB_PD_PORTS 0x102 +#define EC_CMD_USB_PD_PORTS 0x0102 /* Maximum number of PD ports on a device, num_ports will be <= this */ #define EC_USB_PD_MAX_PORTS 8 struct ec_response_usb_pd_ports { uint8_t num_ports; -} __packed; +} __ec_align1; -#define EC_CMD_USB_PD_POWER_INFO 0x103 +#define EC_CMD_USB_PD_POWER_INFO 0x0103 #define PD_POWER_CHARGING_PORT 0xff struct ec_params_usb_pd_power_info { uint8_t port; -} __packed; +} __ec_align1; enum usb_chg_type { USB_CHG_TYPE_NONE, @@ -3335,6 +4800,7 @@ enum usb_chg_type { USB_CHG_TYPE_OTHER, USB_CHG_TYPE_VBUS, USB_CHG_TYPE_UNKNOWN, + USB_CHG_TYPE_DEDICATED, }; enum usb_power_roles { USB_PD_PORT_POWER_DISCONNECTED, @@ -3348,7 +4814,7 @@ struct usb_chg_measures { uint16_t voltage_now; uint16_t current_max; uint16_t current_lim; -} __packed; +} __ec_align2; struct ec_response_usb_pd_power_info { uint8_t role; @@ -3357,11 +4823,8 @@ struct ec_response_usb_pd_power_info { uint8_t reserved1; struct usb_chg_measures meas; uint32_t max_power; -} __packed; +} __ec_align4; -struct ec_params_usb_pd_info_request { - uint8_t port; -} __packed; /* * This command will return the number of USB PD charge port + the number @@ -3371,7 +4834,47 @@ struct ec_params_usb_pd_info_request { #define EC_CMD_CHARGE_PORT_COUNT 0x0105 struct ec_response_charge_port_count { uint8_t port_count; -} __packed; +} __ec_align1; + +/* Write USB-PD device FW */ +#define EC_CMD_USB_PD_FW_UPDATE 0x0110 + +enum usb_pd_fw_update_cmds { + USB_PD_FW_REBOOT, + USB_PD_FW_FLASH_ERASE, + USB_PD_FW_FLASH_WRITE, + USB_PD_FW_ERASE_SIG, +}; + +struct ec_params_usb_pd_fw_update { + uint16_t dev_id; + uint8_t cmd; + uint8_t port; + uint32_t size; /* Size to write in bytes */ + /* Followed by data to write */ +} __ec_align4; + +/* Write USB-PD Accessory RW_HASH table entry */ +#define EC_CMD_USB_PD_RW_HASH_ENTRY 0x0111 +/* RW hash is first 20 bytes of SHA-256 of RW section */ +#define PD_RW_HASH_SIZE 20 +struct ec_params_usb_pd_rw_hash_entry { + uint16_t dev_id; + uint8_t dev_rw_hash[PD_RW_HASH_SIZE]; + uint8_t reserved; /* + * For alignment of current_image + * TODO(rspangler) but it's not aligned! + * Should have been reserved[2]. + */ + uint32_t current_image; /* One of ec_current_image */ +} __ec_align1; + +/* Read USB-PD Accessory info */ +#define EC_CMD_USB_PD_DEV_INFO 0x0112 + +struct ec_params_usb_pd_info_request { + uint8_t port; +} __ec_align1; /* Read USB-PD Device discovery info */ #define EC_CMD_USB_PD_DISCOVERY 0x0113 @@ -3379,7 +4882,7 @@ struct ec_params_usb_pd_discovery_entry { uint16_t vid; /* USB-IF VID */ uint16_t pid; /* USB-IF PID */ uint8_t ptype; /* product type (hub,periph,cable,ama) */ -} __packed; +} __ec_align_size1; /* Override default charge behavior */ #define EC_CMD_PD_CHARGE_PORT_OVERRIDE 0x0114 @@ -3393,9 +4896,13 @@ enum usb_pd_override_ports { struct ec_params_charge_port_override { int16_t override_port; /* Override port# */ -} __packed; +} __ec_align2; -/* Read (and delete) one entry of PD event log */ +/* + * Read (and delete) one entry of PD event log. + * TODO(crbug.com/751742): Make this host command more generic to accommodate + * future non-PD logs that use the same internal EC event_log. + */ #define EC_CMD_PD_GET_LOG_ENTRY 0x0115 struct ec_response_pd_log { @@ -3404,7 +4911,7 @@ struct ec_response_pd_log { uint8_t size_port; /* [7:5] port number [4:0] payload size in bytes */ uint16_t data; /* type-defined data payload */ uint8_t payload[0]; /* optional additional data payload: 0..16 bytes */ -} __packed; +} __ec_align4; /* The timestamp is the microsecond counter shifted to get about a ms. */ #define PD_LOG_TIMESTAMP_SHIFT 10 /* 1 LSB = 1024us */ @@ -3470,35 +4977,710 @@ struct mcdp_version { uint8_t major; uint8_t minor; uint16_t build; -} __packed; +} __ec_align4; struct mcdp_info { uint8_t family[2]; uint8_t chipid[2]; struct mcdp_version irom; struct mcdp_version fw; -} __packed; +} __ec_align4; /* struct mcdp_info field decoding */ #define MCDP_CHIPID(chipid) ((chipid[0] << 8) | chipid[1]) #define MCDP_FAMILY(family) ((family[0] << 8) | family[1]) +/* Get/Set USB-PD Alternate mode info */ +#define EC_CMD_USB_PD_GET_AMODE 0x0116 +struct ec_params_usb_pd_get_mode_request { + uint16_t svid_idx; /* SVID index to get */ + uint8_t port; /* port */ +} __ec_align_size1; + +struct ec_params_usb_pd_get_mode_response { + uint16_t svid; /* SVID */ + uint16_t opos; /* Object Position */ + uint32_t vdo[6]; /* Mode VDOs */ +} __ec_align4; + +#define EC_CMD_USB_PD_SET_AMODE 0x0117 + +enum pd_mode_cmd { + PD_EXIT_MODE = 0, + PD_ENTER_MODE = 1, + /* Not a command. Do NOT remove. */ + PD_MODE_CMD_COUNT, +}; + +struct ec_params_usb_pd_set_mode_request { + uint32_t cmd; /* enum pd_mode_cmd */ + uint16_t svid; /* SVID to set */ + uint8_t opos; /* Object Position */ + uint8_t port; /* port */ +} __ec_align4; + +/* Ask the PD MCU to record a log of a requested type */ +#define EC_CMD_PD_WRITE_LOG_ENTRY 0x0118 + +struct ec_params_pd_write_log_entry { + uint8_t type; /* event type : see PD_EVENT_xx above */ + uint8_t port; /* port#, or 0 for events unrelated to a given port */ +} __ec_align1; + + +/* Control USB-PD chip */ +#define EC_CMD_PD_CONTROL 0x0119 + +enum ec_pd_control_cmd { + PD_SUSPEND = 0, /* Suspend the PD chip (EC: stop talking to PD) */ + PD_RESUME, /* Resume the PD chip (EC: start talking to PD) */ + PD_RESET, /* Force reset the PD chip */ + PD_CONTROL_DISABLE, /* Disable further calls to this command */ + PD_CHIP_ON, /* Power on the PD chip */ +}; + +struct ec_params_pd_control { + uint8_t chip; /* chip id */ + uint8_t subcmd; +} __ec_align1; + /* Get info about USB-C SS muxes */ -#define EC_CMD_USB_PD_MUX_INFO 0x11a +#define EC_CMD_USB_PD_MUX_INFO 0x011A struct ec_params_usb_pd_mux_info { uint8_t port; /* USB-C port number */ -} __packed; +} __ec_align1; /* Flags representing mux state */ -#define USB_PD_MUX_USB_ENABLED (1 << 0) -#define USB_PD_MUX_DP_ENABLED (1 << 1) -#define USB_PD_MUX_POLARITY_INVERTED (1 << 2) -#define USB_PD_MUX_HPD_IRQ (1 << 3) +#define USB_PD_MUX_USB_ENABLED BIT(0) /* USB connected */ +#define USB_PD_MUX_DP_ENABLED BIT(1) /* DP connected */ +#define USB_PD_MUX_POLARITY_INVERTED BIT(2) /* CC line Polarity inverted */ +#define USB_PD_MUX_HPD_IRQ BIT(3) /* HPD IRQ is asserted */ +#define USB_PD_MUX_HPD_LVL BIT(4) /* HPD level is asserted */ struct ec_response_usb_pd_mux_info { uint8_t flags; /* USB_PD_MUX_*-encoded USB mux state */ -} __packed; +} __ec_align1; + +#define EC_CMD_PD_CHIP_INFO 0x011B + +struct ec_params_pd_chip_info { + uint8_t port; /* USB-C port number */ + uint8_t renew; /* Force renewal */ +} __ec_align1; + +struct ec_response_pd_chip_info { + uint16_t vendor_id; + uint16_t product_id; + uint16_t device_id; + union { + uint8_t fw_version_string[8]; + uint64_t fw_version_number; + }; +} __ec_align2; + +struct ec_response_pd_chip_info_v1 { + uint16_t vendor_id; + uint16_t product_id; + uint16_t device_id; + union { + uint8_t fw_version_string[8]; + uint64_t fw_version_number; + }; + union { + uint8_t min_req_fw_version_string[8]; + uint64_t min_req_fw_version_number; + }; +} __ec_align2; + +/* Run RW signature verification and get status */ +#define EC_CMD_RWSIG_CHECK_STATUS 0x011C + +struct ec_response_rwsig_check_status { + uint32_t status; +} __ec_align4; + +/* For controlling RWSIG task */ +#define EC_CMD_RWSIG_ACTION 0x011D + +enum rwsig_action { + RWSIG_ACTION_ABORT = 0, /* Abort RWSIG and prevent jumping */ + RWSIG_ACTION_CONTINUE = 1, /* Jump to RW immediately */ +}; + +struct ec_params_rwsig_action { + uint32_t action; +} __ec_align4; + +/* Run verification on a slot */ +#define EC_CMD_EFS_VERIFY 0x011E + +struct ec_params_efs_verify { + uint8_t region; /* enum ec_flash_region */ +} __ec_align1; + +/* + * Retrieve info from Cros Board Info store. Response is based on the data + * type. Integers return a uint32. Strings return a string, using the response + * size to determine how big it is. + */ +#define EC_CMD_GET_CROS_BOARD_INFO 0x011F +/* + * Write info into Cros Board Info on EEPROM. Write fails if the board has + * hardware write-protect enabled. + */ +#define EC_CMD_SET_CROS_BOARD_INFO 0x0120 + +enum cbi_data_tag { + CBI_TAG_BOARD_VERSION = 0, /* uint32_t or smaller */ + CBI_TAG_OEM_ID = 1, /* uint32_t or smaller */ + CBI_TAG_SKU_ID = 2, /* uint32_t or smaller */ + CBI_TAG_DRAM_PART_NUM = 3, /* variable length ascii, nul terminated. */ + CBI_TAG_OEM_NAME = 4, /* variable length ascii, nul terminated. */ + CBI_TAG_MODEL_ID = 5, /* uint32_t or smaller */ + CBI_TAG_COUNT, +}; + +/* + * Flags to control read operation + * + * RELOAD: Invalidate cache and read data from EEPROM. Useful to verify + * write was successful without reboot. + */ +#define CBI_GET_RELOAD BIT(0) + +struct ec_params_get_cbi { + uint32_t tag; /* enum cbi_data_tag */ + uint32_t flag; /* CBI_GET_* */ +} __ec_align4; + +/* + * Flags to control write behavior. + * + * NO_SYNC: Makes EC update data in RAM but skip writing to EEPROM. It's + * useful when writing multiple fields in a row. + * INIT: Need to be set when creating a new CBI from scratch. All fields + * will be initialized to zero first. + */ +#define CBI_SET_NO_SYNC BIT(0) +#define CBI_SET_INIT BIT(1) + +struct ec_params_set_cbi { + uint32_t tag; /* enum cbi_data_tag */ + uint32_t flag; /* CBI_SET_* */ + uint32_t size; /* Data size */ + uint8_t data[]; /* For string and raw data */ +} __ec_align1; + +/* + * Information about resets of the AP by the EC and the EC's own uptime. + */ +#define EC_CMD_GET_UPTIME_INFO 0x0121 + +struct ec_response_uptime_info { + /* + * Number of milliseconds since the last EC boot. Sysjump resets + * typically do not restart the EC's time_since_boot epoch. + * + * WARNING: The EC's sense of time is much less accurate than the AP's + * sense of time, in both phase and frequency. This timebase is similar + * to CLOCK_MONOTONIC_RAW, but with 1% or more frequency error. + */ + uint32_t time_since_ec_boot_ms; + + /* + * Number of times the AP was reset by the EC since the last EC boot. + * Note that the AP may be held in reset by the EC during the initial + * boot sequence, such that the very first AP boot may count as more + * than one here. + */ + uint32_t ap_resets_since_ec_boot; + + /* + * The set of flags which describe the EC's most recent reset. See + * include/system.h RESET_FLAG_* for details. + */ + uint32_t ec_reset_flags; + + /* Empty log entries have both the cause and timestamp set to zero. */ + struct ap_reset_log_entry { + /* + * See include/chipset.h: enum chipset_{reset,shutdown}_reason + * for details. + */ + uint16_t reset_cause; + + /* Reserved for protocol growth. */ + uint16_t reserved; + + /* + * The time of the reset's assertion, in milliseconds since the + * last EC boot, in the same epoch as time_since_ec_boot_ms. + * Set to zero if the log entry is empty. + */ + uint32_t reset_time_ms; + } recent_ap_reset[4]; +} __ec_align4; + +/* + * Add entropy to the device secret (stored in the rollback region). + * + * Depending on the chip, the operation may take a long time (e.g. to erase + * flash), so the commands are asynchronous. + */ +#define EC_CMD_ADD_ENTROPY 0x0122 + +enum add_entropy_action { + /* Add entropy to the current secret. */ + ADD_ENTROPY_ASYNC = 0, + /* + * Add entropy, and also make sure that the previous secret is erased. + * (this can be implemented by adding entropy multiple times until + * all rolback blocks have been overwritten). + */ + ADD_ENTROPY_RESET_ASYNC = 1, + /* Read back result from the previous operation. */ + ADD_ENTROPY_GET_RESULT = 2, +}; + +struct ec_params_rollback_add_entropy { + uint8_t action; +} __ec_align1; + +/* + * Perform a single read of a given ADC channel. + */ +#define EC_CMD_ADC_READ 0x0123 + +struct ec_params_adc_read { + uint8_t adc_channel; +} __ec_align1; + +struct ec_response_adc_read { + int32_t adc_value; +} __ec_align4; + +/* + * Read back rollback info + */ +#define EC_CMD_ROLLBACK_INFO 0x0124 + +struct ec_response_rollback_info { + int32_t id; /* Incrementing number to indicate which region to use. */ + int32_t rollback_min_version; + int32_t rw_rollback_version; +} __ec_align4; + + +/* Issue AP reset */ +#define EC_CMD_AP_RESET 0x0125 + +/*****************************************************************************/ +/* The command range 0x200-0x2FF is reserved for Rotor. */ + +/*****************************************************************************/ +/* + * Reserve a range of host commands for the CR51 firmware. + */ +#define EC_CMD_CR51_BASE 0x0300 +#define EC_CMD_CR51_LAST 0x03FF + +/*****************************************************************************/ +/* Fingerprint MCU commands: range 0x0400-0x040x */ + +/* Fingerprint SPI sensor passthru command: prototyping ONLY */ +#define EC_CMD_FP_PASSTHRU 0x0400 + +#define EC_FP_FLAG_NOT_COMPLETE 0x1 + +struct ec_params_fp_passthru { + uint16_t len; /* Number of bytes to write then read */ + uint16_t flags; /* EC_FP_FLAG_xxx */ + uint8_t data[]; /* Data to send */ +} __ec_align2; + +/* Configure the Fingerprint MCU behavior */ +#define EC_CMD_FP_MODE 0x0402 + +/* Put the sensor in its lowest power mode */ +#define FP_MODE_DEEPSLEEP BIT(0) +/* Wait to see a finger on the sensor */ +#define FP_MODE_FINGER_DOWN BIT(1) +/* Poll until the finger has left the sensor */ +#define FP_MODE_FINGER_UP BIT(2) +/* Capture the current finger image */ +#define FP_MODE_CAPTURE BIT(3) +/* Finger enrollment session on-going */ +#define FP_MODE_ENROLL_SESSION BIT(4) +/* Enroll the current finger image */ +#define FP_MODE_ENROLL_IMAGE BIT(5) +/* Try to match the current finger image */ +#define FP_MODE_MATCH BIT(6) +/* Reset and re-initialize the sensor. */ +#define FP_MODE_RESET_SENSOR BIT(7) +/* special value: don't change anything just read back current mode */ +#define FP_MODE_DONT_CHANGE BIT(31) + +#define FP_VALID_MODES (FP_MODE_DEEPSLEEP | \ + FP_MODE_FINGER_DOWN | \ + FP_MODE_FINGER_UP | \ + FP_MODE_CAPTURE | \ + FP_MODE_ENROLL_SESSION | \ + FP_MODE_ENROLL_IMAGE | \ + FP_MODE_MATCH | \ + FP_MODE_RESET_SENSOR | \ + FP_MODE_DONT_CHANGE) + +/* Capture types defined in bits [30..28] */ +#define FP_MODE_CAPTURE_TYPE_SHIFT 28 +#define FP_MODE_CAPTURE_TYPE_MASK (0x7 << FP_MODE_CAPTURE_TYPE_SHIFT) +/* + * This enum must remain ordered, if you add new values you must ensure that + * FP_CAPTURE_TYPE_MAX is still the last one. + */ +enum fp_capture_type { + /* Full blown vendor-defined capture (produces 'frame_size' bytes) */ + FP_CAPTURE_VENDOR_FORMAT = 0, + /* Simple raw image capture (produces width x height x bpp bits) */ + FP_CAPTURE_SIMPLE_IMAGE = 1, + /* Self test pattern (e.g. checkerboard) */ + FP_CAPTURE_PATTERN0 = 2, + /* Self test pattern (e.g. inverted checkerboard) */ + FP_CAPTURE_PATTERN1 = 3, + /* Capture for Quality test with fixed contrast */ + FP_CAPTURE_QUALITY_TEST = 4, + /* Capture for pixel reset value test */ + FP_CAPTURE_RESET_TEST = 5, + FP_CAPTURE_TYPE_MAX, +}; +/* Extracts the capture type from the sensor 'mode' word */ +#define FP_CAPTURE_TYPE(mode) (((mode) & FP_MODE_CAPTURE_TYPE_MASK) \ + >> FP_MODE_CAPTURE_TYPE_SHIFT) + +struct ec_params_fp_mode { + uint32_t mode; /* as defined by FP_MODE_ constants */ +} __ec_align4; + +struct ec_response_fp_mode { + uint32_t mode; /* as defined by FP_MODE_ constants */ +} __ec_align4; + +/* Retrieve Fingerprint sensor information */ +#define EC_CMD_FP_INFO 0x0403 + +/* Number of dead pixels detected on the last maintenance */ +#define FP_ERROR_DEAD_PIXELS(errors) ((errors) & 0x3FF) +/* Unknown number of dead pixels detected on the last maintenance */ +#define FP_ERROR_DEAD_PIXELS_UNKNOWN (0x3FF) +/* No interrupt from the sensor */ +#define FP_ERROR_NO_IRQ BIT(12) +/* SPI communication error */ +#define FP_ERROR_SPI_COMM BIT(13) +/* Invalid sensor Hardware ID */ +#define FP_ERROR_BAD_HWID BIT(14) +/* Sensor initialization failed */ +#define FP_ERROR_INIT_FAIL BIT(15) + +struct ec_response_fp_info_v0 { + /* Sensor identification */ + uint32_t vendor_id; + uint32_t product_id; + uint32_t model_id; + uint32_t version; + /* Image frame characteristics */ + uint32_t frame_size; + uint32_t pixel_format; /* using V4L2_PIX_FMT_ */ + uint16_t width; + uint16_t height; + uint16_t bpp; + uint16_t errors; /* see FP_ERROR_ flags above */ +} __ec_align4; + +struct ec_response_fp_info { + /* Sensor identification */ + uint32_t vendor_id; + uint32_t product_id; + uint32_t model_id; + uint32_t version; + /* Image frame characteristics */ + uint32_t frame_size; + uint32_t pixel_format; /* using V4L2_PIX_FMT_ */ + uint16_t width; + uint16_t height; + uint16_t bpp; + uint16_t errors; /* see FP_ERROR_ flags above */ + /* Template/finger current information */ + uint32_t template_size; /* max template size in bytes */ + uint16_t template_max; /* maximum number of fingers/templates */ + uint16_t template_valid; /* number of valid fingers/templates */ + uint32_t template_dirty; /* bitmap of templates with MCU side changes */ + uint32_t template_version; /* version of the template format */ +} __ec_align4; + +/* Get the last captured finger frame or a template content */ +#define EC_CMD_FP_FRAME 0x0404 + +/* constants defining the 'offset' field which also contains the frame index */ +#define FP_FRAME_INDEX_SHIFT 28 +/* Frame buffer where the captured image is stored */ +#define FP_FRAME_INDEX_RAW_IMAGE 0 +/* First frame buffer holding a template */ +#define FP_FRAME_INDEX_TEMPLATE 1 +#define FP_FRAME_GET_BUFFER_INDEX(offset) ((offset) >> FP_FRAME_INDEX_SHIFT) +#define FP_FRAME_OFFSET_MASK 0x0FFFFFFF + +/* Version of the format of the encrypted templates. */ +#define FP_TEMPLATE_FORMAT_VERSION 3 + +/* Constants for encryption parameters */ +#define FP_CONTEXT_NONCE_BYTES 12 +#define FP_CONTEXT_USERID_WORDS (32 / sizeof(uint32_t)) +#define FP_CONTEXT_TAG_BYTES 16 +#define FP_CONTEXT_SALT_BYTES 16 +#define FP_CONTEXT_TPM_BYTES 32 + +struct ec_fp_template_encryption_metadata { + /* + * Version of the structure format (N=3). + */ + uint16_t struct_version; + /* Reserved bytes, set to 0. */ + uint16_t reserved; + /* + * The salt is *only* ever used for key derivation. The nonce is unique, + * a different one is used for every message. + */ + uint8_t nonce[FP_CONTEXT_NONCE_BYTES]; + uint8_t salt[FP_CONTEXT_SALT_BYTES]; + uint8_t tag[FP_CONTEXT_TAG_BYTES]; +}; + +struct ec_params_fp_frame { + /* + * The offset contains the template index or FP_FRAME_INDEX_RAW_IMAGE + * in the high nibble, and the real offset within the frame in + * FP_FRAME_OFFSET_MASK. + */ + uint32_t offset; + uint32_t size; +} __ec_align4; + +/* Load a template into the MCU */ +#define EC_CMD_FP_TEMPLATE 0x0405 + +/* Flag in the 'size' field indicating that the full template has been sent */ +#define FP_TEMPLATE_COMMIT 0x80000000 + +struct ec_params_fp_template { + uint32_t offset; + uint32_t size; + uint8_t data[]; +} __ec_align4; + +/* Clear the current fingerprint user context and set a new one */ +#define EC_CMD_FP_CONTEXT 0x0406 + +struct ec_params_fp_context { + uint32_t userid[FP_CONTEXT_USERID_WORDS]; +} __ec_align4; + +#define EC_CMD_FP_STATS 0x0407 + +#define FPSTATS_CAPTURE_INV BIT(0) +#define FPSTATS_MATCHING_INV BIT(1) + +struct ec_response_fp_stats { + uint32_t capture_time_us; + uint32_t matching_time_us; + uint32_t overall_time_us; + struct { + uint32_t lo; + uint32_t hi; + } overall_t0; + uint8_t timestamps_invalid; + int8_t template_matched; +} __ec_align2; + +#define EC_CMD_FP_SEED 0x0408 +struct ec_params_fp_seed { + /* + * Version of the structure format (N=3). + */ + uint16_t struct_version; + /* Reserved bytes, set to 0. */ + uint16_t reserved; + /* Seed from the TPM. */ + uint8_t seed[FP_CONTEXT_TPM_BYTES]; +} __ec_align4; + +#define EC_CMD_FP_ENC_STATUS 0x0409 + +/* FP TPM seed has been set or not */ +#define FP_ENC_STATUS_SEED_SET BIT(0) + +struct ec_response_fp_encryption_status { + /* Used bits in encryption engine status */ + uint32_t valid_flags; + /* Encryption engine status */ + uint32_t status; +} __ec_align4; + +/*****************************************************************************/ +/* Touchpad MCU commands: range 0x0500-0x05FF */ + +/* Perform touchpad self test */ +#define EC_CMD_TP_SELF_TEST 0x0500 + +/* Get number of frame types, and the size of each type */ +#define EC_CMD_TP_FRAME_INFO 0x0501 + +struct ec_response_tp_frame_info { + uint32_t n_frames; + uint32_t frame_sizes[0]; +} __ec_align4; + +/* Create a snapshot of current frame readings */ +#define EC_CMD_TP_FRAME_SNAPSHOT 0x0502 + +/* Read the frame */ +#define EC_CMD_TP_FRAME_GET 0x0503 + +struct ec_params_tp_frame_get { + uint32_t frame_index; + uint32_t offset; + uint32_t size; +} __ec_align4; + +/*****************************************************************************/ +/* EC-EC communication commands: range 0x0600-0x06FF */ + +#define EC_COMM_TEXT_MAX 8 + +/* + * Get battery static information, i.e. information that never changes, or + * very infrequently. + */ +#define EC_CMD_BATTERY_GET_STATIC 0x0600 + +/** + * struct ec_params_battery_static_info - Battery static info parameters + * @index: Battery index. + */ +struct ec_params_battery_static_info { + uint8_t index; +} __ec_align_size1; + +/** + * struct ec_response_battery_static_info - Battery static info response + * @design_capacity: Battery Design Capacity (mAh) + * @design_voltage: Battery Design Voltage (mV) + * @manufacturer: Battery Manufacturer String + * @model: Battery Model Number String + * @serial: Battery Serial Number String + * @type: Battery Type String + * @cycle_count: Battery Cycle Count + */ +struct ec_response_battery_static_info { + uint16_t design_capacity; + uint16_t design_voltage; + char manufacturer[EC_COMM_TEXT_MAX]; + char model[EC_COMM_TEXT_MAX]; + char serial[EC_COMM_TEXT_MAX]; + char type[EC_COMM_TEXT_MAX]; + /* TODO(crbug.com/795991): Consider moving to dynamic structure. */ + uint32_t cycle_count; +} __ec_align4; + +/* + * Get battery dynamic information, i.e. information that is likely to change + * every time it is read. + */ +#define EC_CMD_BATTERY_GET_DYNAMIC 0x0601 + +/** + * struct ec_params_battery_dynamic_info - Battery dynamic info parameters + * @index: Battery index. + */ +struct ec_params_battery_dynamic_info { + uint8_t index; +} __ec_align_size1; + +/** + * struct ec_response_battery_dynamic_info - Battery dynamic info response + * @actual_voltage: Battery voltage (mV) + * @actual_current: Battery current (mA); negative=discharging + * @remaining_capacity: Remaining capacity (mAh) + * @full_capacity: Capacity (mAh, might change occasionally) + * @flags: Flags, see EC_BATT_FLAG_* + * @desired_voltage: Charging voltage desired by battery (mV) + * @desired_current: Charging current desired by battery (mA) + */ +struct ec_response_battery_dynamic_info { + int16_t actual_voltage; + int16_t actual_current; + int16_t remaining_capacity; + int16_t full_capacity; + int16_t flags; + int16_t desired_voltage; + int16_t desired_current; +} __ec_align2; + +/* + * Control charger chip. Used to control charger chip on the slave. + */ +#define EC_CMD_CHARGER_CONTROL 0x0602 + +/** + * struct ec_params_charger_control - Charger control parameters + * @max_current: Charger current (mA). Positive to allow base to draw up to + * max_current and (possibly) charge battery, negative to request current + * from base (OTG). + * @otg_voltage: Voltage (mV) to use in OTG mode, ignored if max_current is + * >= 0. + * @allow_charging: Allow base battery charging (only makes sense if + * max_current > 0). + */ +struct ec_params_charger_control { + int16_t max_current; + uint16_t otg_voltage; + uint8_t allow_charging; +} __ec_align_size1; + +/*****************************************************************************/ +/* + * Reserve a range of host commands for board-specific, experimental, or + * special purpose features. These can be (re)used without updating this file. + * + * CAUTION: Don't go nuts with this. Shipping products should document ALL + * their EC commands for easier development, testing, debugging, and support. + * + * All commands MUST be #defined to be 4-digit UPPER CASE hex values + * (e.g., 0x00AB, not 0xab) for CONFIG_HOSTCMD_SECTION_SORTED to work. + * + * In your experimental code, you may want to do something like this: + * + * #define EC_CMD_MAGIC_FOO 0x0000 + * #define EC_CMD_MAGIC_BAR 0x0001 + * #define EC_CMD_MAGIC_HEY 0x0002 + * + * DECLARE_PRIVATE_HOST_COMMAND(EC_CMD_MAGIC_FOO, magic_foo_handler, + * EC_VER_MASK(0); + * + * DECLARE_PRIVATE_HOST_COMMAND(EC_CMD_MAGIC_BAR, magic_bar_handler, + * EC_VER_MASK(0); + * + * DECLARE_PRIVATE_HOST_COMMAND(EC_CMD_MAGIC_HEY, magic_hey_handler, + * EC_VER_MASK(0); + */ +#define EC_CMD_BOARD_SPECIFIC_BASE 0x3E00 +#define EC_CMD_BOARD_SPECIFIC_LAST 0x3FFF + +/* + * Given the private host command offset, calculate the true private host + * command value. + */ +#define EC_PRIVATE_HOST_COMMAND_VALUE(command) \ + (EC_CMD_BOARD_SPECIFIC_BASE + (command)) /*****************************************************************************/ /* @@ -3538,4 +5720,6 @@ struct ec_response_usb_pd_mux_info { #define EC_LPC_ADDR_OLD_PARAM EC_HOST_CMD_REGION1 #define EC_OLD_PARAM_SIZE EC_HOST_CMD_REGION_SIZE + + #endif /* __CROS_EC_COMMANDS_H */ diff --git a/include/linux/platform_data/cros_ec_proto.h b/include/linux/platform_data/cros_ec_proto.h new file mode 100644 index 000000000000..eab7036cda09 --- /dev/null +++ b/include/linux/platform_data/cros_ec_proto.h @@ -0,0 +1,319 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * ChromeOS Embedded Controller protocol interface. + * + * Copyright (C) 2012 Google, Inc + */ + +#ifndef __LINUX_CROS_EC_PROTO_H +#define __LINUX_CROS_EC_PROTO_H + +#include <linux/device.h> +#include <linux/mutex.h> +#include <linux/notifier.h> + +#include <linux/platform_data/cros_ec_commands.h> + +#define CROS_EC_DEV_NAME "cros_ec" +#define CROS_EC_DEV_FP_NAME "cros_fp" +#define CROS_EC_DEV_ISH_NAME "cros_ish" +#define CROS_EC_DEV_PD_NAME "cros_pd" +#define CROS_EC_DEV_SCP_NAME "cros_scp" +#define CROS_EC_DEV_TP_NAME "cros_tp" + +/* + * The EC is unresponsive for a time after a reboot command. Add a + * simple delay to make sure that the bus stays locked. + */ +#define EC_REBOOT_DELAY_MS 50 + +/* + * Max bus-specific overhead incurred by request/responses. + * I2C requires 1 additional byte for requests. + * I2C requires 2 additional bytes for responses. + * SPI requires up to 32 additional bytes for responses. + */ +#define EC_PROTO_VERSION_UNKNOWN 0 +#define EC_MAX_REQUEST_OVERHEAD 1 +#define EC_MAX_RESPONSE_OVERHEAD 32 + +/* + * Command interface between EC and AP, for LPC, I2C and SPI interfaces. + */ +enum { + EC_MSG_TX_HEADER_BYTES = 3, + EC_MSG_TX_TRAILER_BYTES = 1, + EC_MSG_TX_PROTO_BYTES = EC_MSG_TX_HEADER_BYTES + + EC_MSG_TX_TRAILER_BYTES, + EC_MSG_RX_PROTO_BYTES = 3, + + /* Max length of messages for proto 2*/ + EC_PROTO2_MSG_BYTES = EC_PROTO2_MAX_PARAM_SIZE + + EC_MSG_TX_PROTO_BYTES, + + EC_MAX_MSG_BYTES = 64 * 1024, +}; + +/** + * struct cros_ec_command - Information about a ChromeOS EC command. + * @version: Command version number (often 0). + * @command: Command to send (EC_CMD_...). + * @outsize: Outgoing length in bytes. + * @insize: Max number of bytes to accept from the EC. + * @result: EC's response to the command (separate from communication failure). + * @data: Where to put the incoming data from EC and outgoing data to EC. + */ +struct cros_ec_command { + uint32_t version; + uint32_t command; + uint32_t outsize; + uint32_t insize; + uint32_t result; + uint8_t data[0]; +}; + +/** + * struct cros_ec_device - Information about a ChromeOS EC device. + * @phys_name: Name of physical comms layer (e.g. 'i2c-4'). + * @dev: Device pointer for physical comms device + * @was_wake_device: True if this device was set to wake the system from + * sleep at the last suspend. + * @cros_class: The class structure for this device. + * @cmd_readmem: Direct read of the EC memory-mapped region, if supported. + * @offset: Is within EC_LPC_ADDR_MEMMAP region. + * @bytes: Number of bytes to read. zero means "read a string" (including + * the trailing '\0'). At most only EC_MEMMAP_SIZE bytes can be + * read. Caller must ensure that the buffer is large enough for the + * result when reading a string. + * @max_request: Max size of message requested. + * @max_response: Max size of message response. + * @max_passthru: Max sice of passthru message. + * @proto_version: The protocol version used for this device. + * @priv: Private data. + * @irq: Interrupt to use. + * @id: Device id. + * @din: Input buffer (for data from EC). This buffer will always be + * dword-aligned and include enough space for up to 7 word-alignment + * bytes also, so we can ensure that the body of the message is always + * dword-aligned (64-bit). We use this alignment to keep ARM and x86 + * happy. Probably word alignment would be OK, there might be a small + * performance advantage to using dword. + * @dout: Output buffer (for data to EC). This buffer will always be + * dword-aligned and include enough space for up to 7 word-alignment + * bytes also, so we can ensure that the body of the message is always + * dword-aligned (64-bit). We use this alignment to keep ARM and x86 + * happy. Probably word alignment would be OK, there might be a small + * performance advantage to using dword. + * @din_size: Size of din buffer to allocate (zero to use static din). + * @dout_size: Size of dout buffer to allocate (zero to use static dout). + * @wake_enabled: True if this device can wake the system from sleep. + * @suspended: True if this device had been suspended. + * @cmd_xfer: Send command to EC and get response. + * Returns the number of bytes received if the communication + * succeeded, but that doesn't mean the EC was happy with the + * command. The caller should check msg.result for the EC's result + * code. + * @pkt_xfer: Send packet to EC and get response. + * @lock: One transaction at a time. + * @mkbp_event_supported: True if this EC supports the MKBP event protocol. + * @host_sleep_v1: True if this EC supports the sleep v1 command. + * @event_notifier: Interrupt event notifier for transport devices. + * @event_data: Raw payload transferred with the MKBP event. + * @event_size: Size in bytes of the event data. + * @host_event_wake_mask: Mask of host events that cause wake from suspend. + * @ec: The platform_device used by the mfd driver to interface with the + * main EC. + * @pd: The platform_device used by the mfd driver to interface with the + * PD behind an EC. + */ +struct cros_ec_device { + /* These are used by other drivers that want to talk to the EC */ + const char *phys_name; + struct device *dev; + bool was_wake_device; + struct class *cros_class; + int (*cmd_readmem)(struct cros_ec_device *ec, unsigned int offset, + unsigned int bytes, void *dest); + + /* These are used to implement the platform-specific interface */ + u16 max_request; + u16 max_response; + u16 max_passthru; + u16 proto_version; + void *priv; + int irq; + u8 *din; + u8 *dout; + int din_size; + int dout_size; + bool wake_enabled; + bool suspended; + int (*cmd_xfer)(struct cros_ec_device *ec, + struct cros_ec_command *msg); + int (*pkt_xfer)(struct cros_ec_device *ec, + struct cros_ec_command *msg); + struct mutex lock; + bool mkbp_event_supported; + bool host_sleep_v1; + struct blocking_notifier_head event_notifier; + + struct ec_response_get_next_event_v1 event_data; + int event_size; + u32 host_event_wake_mask; + u32 last_resume_result; + + /* The platform devices used by the mfd driver */ + struct platform_device *ec; + struct platform_device *pd; +}; + +/** + * struct cros_ec_sensor_platform - ChromeOS EC sensor platform information. + * @sensor_num: Id of the sensor, as reported by the EC. + */ +struct cros_ec_sensor_platform { + u8 sensor_num; +}; + +/** + * struct cros_ec_platform - ChromeOS EC platform information. + * @ec_name: Name of EC device (e.g. 'cros-ec', 'cros-pd', ...) + * used in /dev/ and sysfs. + * @cmd_offset: Offset to apply for each command. Set when + * registering a device behind another one. + */ +struct cros_ec_platform { + const char *ec_name; + u16 cmd_offset; +}; + +/** + * cros_ec_suspend() - Handle a suspend operation for the ChromeOS EC device. + * @ec_dev: Device to suspend. + * + * This can be called by drivers to handle a suspend event. + * + * Return: 0 on success or negative error code. + */ +int cros_ec_suspend(struct cros_ec_device *ec_dev); + +/** + * cros_ec_resume() - Handle a resume operation for the ChromeOS EC device. + * @ec_dev: Device to resume. + * + * This can be called by drivers to handle a resume event. + * + * Return: 0 on success or negative error code. + */ +int cros_ec_resume(struct cros_ec_device *ec_dev); + +/** + * cros_ec_prepare_tx() - Prepare an outgoing message in the output buffer. + * @ec_dev: Device to register. + * @msg: Message to write. + * + * This is intended to be used by all ChromeOS EC drivers, but at present + * only SPI uses it. Once LPC uses the same protocol it can start using it. + * I2C could use it now, with a refactor of the existing code. + * + * Return: 0 on success or negative error code. + */ +int cros_ec_prepare_tx(struct cros_ec_device *ec_dev, + struct cros_ec_command *msg); + +/** + * cros_ec_check_result() - Check ec_msg->result. + * @ec_dev: EC device. + * @msg: Message to check. + * + * This is used by ChromeOS EC drivers to check the ec_msg->result for + * errors and to warn about them. + * + * Return: 0 on success or negative error code. + */ +int cros_ec_check_result(struct cros_ec_device *ec_dev, + struct cros_ec_command *msg); + +/** + * cros_ec_cmd_xfer() - Send a command to the ChromeOS EC. + * @ec_dev: EC device. + * @msg: Message to write. + * + * Call this to send a command to the ChromeOS EC. This should be used + * instead of calling the EC's cmd_xfer() callback directly. + * + * Return: 0 on success or negative error code. + */ +int cros_ec_cmd_xfer(struct cros_ec_device *ec_dev, + struct cros_ec_command *msg); + +/** + * cros_ec_cmd_xfer_status() - Send a command to the ChromeOS EC. + * @ec_dev: EC device. + * @msg: Message to write. + * + * This function is identical to cros_ec_cmd_xfer, except it returns success + * status only if both the command was transmitted successfully and the EC + * replied with success status. It's not necessary to check msg->result when + * using this function. + * + * Return: The number of bytes transferred on success or negative error code. + */ +int cros_ec_cmd_xfer_status(struct cros_ec_device *ec_dev, + struct cros_ec_command *msg); + +/** + * cros_ec_register() - Register a new ChromeOS EC, using the provided info. + * @ec_dev: Device to register. + * + * Before calling this, allocate a pointer to a new device and then fill + * in all the fields up to the --private-- marker. + * + * Return: 0 on success or negative error code. + */ +int cros_ec_register(struct cros_ec_device *ec_dev); + +/** + * cros_ec_unregister() - Remove a ChromeOS EC. + * @ec_dev: Device to unregister. + * + * Call this to deregister a ChromeOS EC, then clean up any private data. + * + * Return: 0 on success or negative error code. + */ +int cros_ec_unregister(struct cros_ec_device *ec_dev); + +/** + * cros_ec_query_all() - Query the protocol version supported by the + * ChromeOS EC. + * @ec_dev: Device to register. + * + * Return: 0 on success or negative error code. + */ +int cros_ec_query_all(struct cros_ec_device *ec_dev); + +/** + * cros_ec_get_next_event() - Fetch next event from the ChromeOS EC. + * @ec_dev: Device to fetch event from. + * @wake_event: Pointer to a bool set to true upon return if the event might be + * treated as a wake event. Ignored if null. + * + * Return: negative error code on errors; 0 for no data; or else number of + * bytes received (i.e., an event was retrieved successfully). Event types are + * written out to @ec_dev->event_data.event_type on success. + */ +int cros_ec_get_next_event(struct cros_ec_device *ec_dev, bool *wake_event); + +/** + * cros_ec_get_host_event() - Return a mask of event set by the ChromeOS EC. + * @ec_dev: Device to fetch event from. + * + * When MKBP is supported, when the EC raises an interrupt, we collect the + * events raised and call the functions in the ec notifier. This function + * is a helper to know which events are raised. + * + * Return: 0 on error or non-zero bitmask of one or more EC_HOST_EVENT_*. + */ +u32 cros_ec_get_host_event(struct cros_ec_device *ec_dev); + +#endif /* __LINUX_CROS_EC_PROTO_H */ diff --git a/include/linux/platform_data/dma-imx.h b/include/linux/platform_data/dma-imx.h index 80f9be858bd0..281adbb26e6b 100644 --- a/include/linux/platform_data/dma-imx.h +++ b/include/linux/platform_data/dma-imx.h @@ -52,7 +52,6 @@ struct imx_dma_data { int dma_request2; /* secondary DMA request line */ enum sdma_peripheral_type peripheral_type; int priority; - struct device_node *of_node; }; static inline int imx_dma_is_ipu(struct dma_chan *chan) diff --git a/include/linux/platform_data/dma-iop32x.h b/include/linux/platform_data/dma-iop32x.h new file mode 100644 index 000000000000..ac83cff89549 --- /dev/null +++ b/include/linux/platform_data/dma-iop32x.h @@ -0,0 +1,110 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright © 2006, Intel Corporation. + */ +#ifndef IOP_ADMA_H +#define IOP_ADMA_H +#include <linux/types.h> +#include <linux/dmaengine.h> +#include <linux/interrupt.h> + +#define IOP_ADMA_SLOT_SIZE 32 +#define IOP_ADMA_THRESHOLD 4 +#ifdef DEBUG +#define IOP_PARANOIA 1 +#else +#define IOP_PARANOIA 0 +#endif +#define iop_paranoia(x) BUG_ON(IOP_PARANOIA && (x)) + +#define DMA0_ID 0 +#define DMA1_ID 1 +#define AAU_ID 2 + +/** + * struct iop_adma_device - internal representation of an ADMA device + * @pdev: Platform device + * @id: HW ADMA Device selector + * @dma_desc_pool: base of DMA descriptor region (DMA address) + * @dma_desc_pool_virt: base of DMA descriptor region (CPU address) + * @common: embedded struct dma_device + */ +struct iop_adma_device { + struct platform_device *pdev; + int id; + dma_addr_t dma_desc_pool; + void *dma_desc_pool_virt; + struct dma_device common; +}; + +/** + * struct iop_adma_chan - internal representation of an ADMA device + * @pending: allows batching of hardware operations + * @lock: serializes enqueue/dequeue operations to the slot pool + * @mmr_base: memory mapped register base + * @chain: device chain view of the descriptors + * @device: parent device + * @common: common dmaengine channel object members + * @last_used: place holder for allocation to continue from where it left off + * @all_slots: complete domain of slots usable by the channel + * @slots_allocated: records the actual size of the descriptor slot pool + * @irq_tasklet: bottom half where iop_adma_slot_cleanup runs + */ +struct iop_adma_chan { + int pending; + spinlock_t lock; /* protects the descriptor slot pool */ + void __iomem *mmr_base; + struct list_head chain; + struct iop_adma_device *device; + struct dma_chan common; + struct iop_adma_desc_slot *last_used; + struct list_head all_slots; + int slots_allocated; + struct tasklet_struct irq_tasklet; +}; + +/** + * struct iop_adma_desc_slot - IOP-ADMA software descriptor + * @slot_node: node on the iop_adma_chan.all_slots list + * @chain_node: node on the op_adma_chan.chain list + * @hw_desc: virtual address of the hardware descriptor chain + * @phys: hardware address of the hardware descriptor chain + * @group_head: first operation in a transaction + * @slot_cnt: total slots used in an transaction (group of operations) + * @slots_per_op: number of slots per operation + * @idx: pool index + * @tx_list: list of descriptors that are associated with one operation + * @async_tx: support for the async_tx api + * @group_list: list of slots that make up a multi-descriptor transaction + * for example transfer lengths larger than the supported hw max + * @xor_check_result: result of zero sum + * @crc32_result: result crc calculation + */ +struct iop_adma_desc_slot { + struct list_head slot_node; + struct list_head chain_node; + void *hw_desc; + struct iop_adma_desc_slot *group_head; + u16 slot_cnt; + u16 slots_per_op; + u16 idx; + struct list_head tx_list; + struct dma_async_tx_descriptor async_tx; + union { + u32 *xor_check_result; + u32 *crc32_result; + u32 *pq_check_result; + }; +}; + +struct iop_adma_platform_data { + int hw_id; + dma_cap_mask_t cap_mask; + size_t pool_size; +}; + +#define to_iop_sw_desc(addr_hw_desc) \ + container_of(addr_hw_desc, struct iop_adma_desc_slot, hw_desc) +#define iop_hw_desc_slot_idx(hw_desc, idx) \ + ( (void *) (((unsigned long) hw_desc) + ((idx) << 5)) ) +#endif diff --git a/include/linux/platform_data/dwc3-omap.h b/include/linux/platform_data/dwc3-omap.h deleted file mode 100644 index 1d36ca874cc8..000000000000 --- a/include/linux/platform_data/dwc3-omap.h +++ /dev/null @@ -1,43 +0,0 @@ -/** - * dwc3-omap.h - OMAP Specific Glue layer, header. - * - * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com - * All rights reserved. - * - * Author: Felipe Balbi <balbi@ti.com> - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The names of the above-listed copyright holders may not be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * ALTERNATIVELY, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2, as published by the Free - * Software Foundation. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -enum dwc3_omap_utmi_mode { - DWC3_OMAP_UTMI_MODE_UNKNOWN = 0, - DWC3_OMAP_UTMI_MODE_HW, - DWC3_OMAP_UTMI_MODE_SW, -}; diff --git a/include/linux/platform_data/fsa9480.h b/include/linux/platform_data/fsa9480.h deleted file mode 100644 index dea8d84448ec..000000000000 --- a/include/linux/platform_data/fsa9480.h +++ /dev/null @@ -1,24 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Copyright (C) 2010 Samsung Electronics - * Minkyu Kang <mk7.kang@samsung.com> - */ - -#ifndef _FSA9480_H_ -#define _FSA9480_H_ - -#define FSA9480_ATTACHED 1 -#define FSA9480_DETACHED 0 - -struct fsa9480_platform_data { - void (*cfg_gpio) (void); - void (*usb_cb) (u8 attached); - void (*uart_cb) (u8 attached); - void (*charger_cb) (u8 attached); - void (*jig_cb) (u8 attached); - void (*reset_cb) (void); - void (*usb_power) (u8 on); - int wakeup; -}; - -#endif /* _FSA9480_H_ */ diff --git a/include/linux/platform_data/gpio-htc-egpio.h b/include/linux/platform_data/gpio-htc-egpio.h index 9a3e78082883..eaefba0b6465 100644 --- a/include/linux/platform_data/gpio-htc-egpio.h +++ b/include/linux/platform_data/gpio-htc-egpio.h @@ -50,7 +50,4 @@ struct htc_egpio_platform_data { int num_chips; }; -/* Determine the wakeup irq, to be called during early resume */ -extern int htc_egpio_get_wakeup_irq(struct device *dev); - #endif diff --git a/include/linux/platform_data/gpio-omap.h b/include/linux/platform_data/gpio-omap.h index 17edc43201d2..8b30b14b47d3 100644 --- a/include/linux/platform_data/gpio-omap.h +++ b/include/linux/platform_data/gpio-omap.h @@ -186,7 +186,7 @@ struct omap_gpio_platform_data { bool is_mpuio; /* whether the bank is of type MPUIO */ u32 non_wakeup_gpios; - struct omap_gpio_reg_offs *regs; + const struct omap_gpio_reg_offs *regs; /* Return context loss count due to PM states changing */ int (*get_context_loss_count)(struct device *dev); diff --git a/include/linux/platform_data/i2c-mux-gpio.h b/include/linux/platform_data/i2c-mux-gpio.h index 9f6ca406505b..5e4c2c272a73 100644 --- a/include/linux/platform_data/i2c-mux-gpio.h +++ b/include/linux/platform_data/i2c-mux-gpio.h @@ -19,10 +19,6 @@ * position * @n_values: Number of multiplexer positions (busses to instantiate) * @classes: Optional I2C auto-detection classes - * @gpio_chip: Optional GPIO chip name; if set, GPIO pin numbers are given - * relative to the base GPIO number of that chip - * @gpios: Array of GPIO numbers used to control MUX - * @n_gpios: Number of GPIOs used to control MUX * @idle: Bitmask to write to MUX when idle or GPIO_I2CMUX_NO_IDLE if not used */ struct i2c_mux_gpio_platform_data { @@ -31,9 +27,6 @@ struct i2c_mux_gpio_platform_data { const unsigned *values; int n_values; const unsigned *classes; - char *gpio_chip; - const unsigned *gpios; - int n_gpios; unsigned idle; }; diff --git a/include/linux/platform_data/iommu-omap.h b/include/linux/platform_data/iommu-omap.h index 44d913a7580c..8474a0208b34 100644 --- a/include/linux/platform_data/iommu-omap.h +++ b/include/linux/platform_data/iommu-omap.h @@ -13,4 +13,8 @@ struct iommu_platform_data { const char *reset_name; int (*assert_reset)(struct platform_device *pdev, const char *name); int (*deassert_reset)(struct platform_device *pdev, const char *name); + int (*device_enable)(struct platform_device *pdev); + int (*device_idle)(struct platform_device *pdev); + int (*set_pwrdm_constraint)(struct platform_device *pdev, bool request, + u8 *pwrst); }; diff --git a/include/linux/platform_data/keypad-w90p910.h b/include/linux/platform_data/keypad-w90p910.h deleted file mode 100644 index 206ca4ecd93f..000000000000 --- a/include/linux/platform_data/keypad-w90p910.h +++ /dev/null @@ -1,16 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef __ASM_ARCH_W90P910_KEYPAD_H -#define __ASM_ARCH_W90P910_KEYPAD_H - -#include <linux/input/matrix_keypad.h> - -extern void mfp_set_groupi(struct device *dev); - -struct w90p910_keypad_platform_data { - const struct matrix_keymap_data *keymap_data; - - unsigned int prescale; - unsigned int debounce; -}; - -#endif /* __ASM_ARCH_W90P910_KEYPAD_H */ diff --git a/include/linux/platform_data/leds-kirkwood-netxbig.h b/include/linux/platform_data/leds-kirkwood-netxbig.h deleted file mode 100644 index 3c85a735c380..000000000000 --- a/include/linux/platform_data/leds-kirkwood-netxbig.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Platform data structure for netxbig LED driver - * - * This file is licensed under the terms of the GNU General Public - * License version 2. This program is licensed "as is" without any - * warranty of any kind, whether express or implied. - */ - -#ifndef __LEDS_KIRKWOOD_NETXBIG_H -#define __LEDS_KIRKWOOD_NETXBIG_H - -struct netxbig_gpio_ext { - unsigned *addr; - int num_addr; - unsigned *data; - int num_data; - unsigned enable; -}; - -enum netxbig_led_mode { - NETXBIG_LED_OFF, - NETXBIG_LED_ON, - NETXBIG_LED_SATA, - NETXBIG_LED_TIMER1, - NETXBIG_LED_TIMER2, - NETXBIG_LED_MODE_NUM, -}; - -#define NETXBIG_LED_INVALID_MODE NETXBIG_LED_MODE_NUM - -struct netxbig_led_timer { - unsigned long delay_on; - unsigned long delay_off; - enum netxbig_led_mode mode; -}; - -struct netxbig_led { - const char *name; - const char *default_trigger; - int mode_addr; - int *mode_val; - int bright_addr; - int bright_max; -}; - -struct netxbig_led_platform_data { - struct netxbig_gpio_ext *gpio_ext; - struct netxbig_led_timer *timer; - int num_timer; - struct netxbig_led *leds; - int num_leds; -}; - -#endif /* __LEDS_KIRKWOOD_NETXBIG_H */ diff --git a/include/linux/platform_data/media/mmp-camera.h b/include/linux/platform_data/media/mmp-camera.h index d2d3a443eedf..53adaab64f28 100644 --- a/include/linux/platform_data/media/mmp-camera.h +++ b/include/linux/platform_data/media/mmp-camera.h @@ -12,11 +12,7 @@ enum dphy3_algo { }; struct mmp_camera_platform_data { - struct platform_device *i2c_device; - int sensor_power_gpio; - int sensor_reset_gpio; enum v4l2_mbus_type bus_type; - int mclk_min; /* The minimal value of MCLK */ int mclk_src; /* which clock source the MCLK derives from */ int mclk_div; /* Clock Divider Value for MCLK */ /* diff --git a/include/linux/platform_data/nxp-nci.h b/include/linux/platform_data/nxp-nci.h deleted file mode 100644 index 97827ad468e2..000000000000 --- a/include/linux/platform_data/nxp-nci.h +++ /dev/null @@ -1,19 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Generic platform data for the NXP NCI NFC chips. - * - * Copyright (C) 2014 NXP Semiconductors All rights reserved. - * - * Authors: Clément Perrochaud <clement.perrochaud@nxp.com> - */ - -#ifndef _NXP_NCI_H_ -#define _NXP_NCI_H_ - -struct nxp_nci_nfc_platform_data { - unsigned int gpio_en; - unsigned int gpio_fw; - unsigned int irq; -}; - -#endif /* _NXP_NCI_H_ */ diff --git a/include/linux/platform_data/pinctrl-single.h b/include/linux/platform_data/pinctrl-single.h index 1cf36fdf9510..7473d3c4cabf 100644 --- a/include/linux/platform_data/pinctrl-single.h +++ b/include/linux/platform_data/pinctrl-single.h @@ -1,4 +1,8 @@ /* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef _PINCTRL_SINGLE_H +#define _PINCTRL_SINGLE_H + /** * irq: optional wake-up interrupt * rearm: optional soc specific rearm function @@ -11,3 +15,5 @@ struct pcs_pdata { int irq; void (*rearm)(void); }; + +#endif /* _PINCTRL_SINGLE_H */ diff --git a/include/linux/platform_data/sc18is602.h b/include/linux/platform_data/sc18is602.h index e066d3b0d6d8..0e91489edfe6 100644 --- a/include/linux/platform_data/sc18is602.h +++ b/include/linux/platform_data/sc18is602.h @@ -4,7 +4,7 @@ * * Copyright (C) 2012 Guenter Roeck <linux@roeck-us.net> * - * For further information, see the Documentation/spi/spi-sc18is602 file. + * For further information, see the Documentation/spi/spi-sc18is602.rst file. */ /** diff --git a/include/linux/platform_data/sgi-w1.h b/include/linux/platform_data/sgi-w1.h new file mode 100644 index 000000000000..e28c8a90ff84 --- /dev/null +++ b/include/linux/platform_data/sgi-w1.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * SGI One-Wire (W1) IP + */ + +#ifndef PLATFORM_DATA_SGI_W1_H +#define PLATFORM_DATA_SGI_W1_H + +struct sgi_w1_platform_data { + char dev_id[64]; +}; + +#endif /* PLATFORM_DATA_SGI_W1_H */ diff --git a/include/linux/platform_data/spi-mt65xx.h b/include/linux/platform_data/spi-mt65xx.h index 617a75336d56..f0e6d6483e62 100644 --- a/include/linux/platform_data/spi-mt65xx.h +++ b/include/linux/platform_data/spi-mt65xx.h @@ -11,8 +11,6 @@ /* Board specific platform_data */ struct mtk_chip_config { - u32 tx_mlsb; - u32 rx_mlsb; u32 cs_pol; u32 sample_sel; }; diff --git a/include/linux/platform_data/spi-nuc900.h b/include/linux/platform_data/spi-nuc900.h deleted file mode 100644 index ca3510877000..000000000000 --- a/include/linux/platform_data/spi-nuc900.h +++ /dev/null @@ -1,29 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Copyright (c) 2009 Nuvoton technology corporation. - * - * Wan ZongShun <mcuos.com@gmail.com> - */ - -#ifndef __SPI_NUC900_H -#define __SPI_NUC900_H - -extern void mfp_set_groupg(struct device *dev, const char *subname); - -struct nuc900_spi_info { - unsigned int num_cs; - unsigned int lsb; - unsigned int txneg; - unsigned int rxneg; - unsigned int divider; - unsigned int sleep; - unsigned int txnum; - unsigned int txbitlen; - int bus_num; -}; - -struct nuc900_spi_chip { - unsigned char bits_per_word; -}; - -#endif /* __SPI_NUC900_H */ diff --git a/include/linux/platform_data/ti-sysc.h b/include/linux/platform_data/ti-sysc.h index 9256c0305968..b5b7a3423ca8 100644 --- a/include/linux/platform_data/ti-sysc.h +++ b/include/linux/platform_data/ti-sysc.h @@ -1,3 +1,5 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + #ifndef __TI_SYSC_DATA_H__ #define __TI_SYSC_DATA_H__ @@ -19,6 +21,7 @@ enum ti_sysc_module_type { struct ti_sysc_cookie { void *data; + void *clkdm; }; /** @@ -46,6 +49,11 @@ struct sysc_regbits { s8 emufree_shift; }; +#define SYSC_MODULE_QUIRK_SGX BIT(18) +#define SYSC_MODULE_QUIRK_HDQ1W BIT(17) +#define SYSC_MODULE_QUIRK_I2C BIT(16) +#define SYSC_MODULE_QUIRK_WDT BIT(15) +#define SYSS_QUIRK_RESETDONE_INVERTED BIT(14) #define SYSC_QUIRK_SWSUP_MSTANDBY BIT(13) #define SYSC_QUIRK_SWSUP_SIDLE_ACT BIT(12) #define SYSC_QUIRK_SWSUP_SIDLE BIT(11) @@ -65,7 +73,7 @@ struct sysc_regbits { /** * struct sysc_capabilities - capabilities for an interconnect target module - * + * @type: sysc type identifier for the module * @sysc_mask: bitmask of supported SYSCONFIG register bits * @regbits: bitmask of SYSCONFIG register bits * @mod_quirks: bitmask of module specific quirks @@ -80,8 +88,9 @@ struct sysc_capabilities { /** * struct sysc_config - configuration for an interconnect target module * @sysc_val: configured value for sysc register + * @syss_mask: configured mask value for SYSSTATUS register * @midlemodes: bitmask of supported master idle modes - * @sidlemodes: bitmask of supported master idle modes + * @sidlemodes: bitmask of supported slave idle modes * @srst_udelay: optional delay needed after OCP soft reset * @quirks: bitmask of enabled quirks */ @@ -125,9 +134,16 @@ struct ti_sysc_module_data { }; struct device; +struct clk; struct ti_sysc_platform_data { struct of_dev_auxdata *auxdata; + int (*init_clockdomain)(struct device *dev, struct clk *fck, + struct clk *ick, struct ti_sysc_cookie *cookie); + void (*clkdm_deny_idle)(struct device *dev, + const struct ti_sysc_cookie *cookie); + void (*clkdm_allow_idle)(struct device *dev, + const struct ti_sysc_cookie *cookie); int (*init_module)(struct device *dev, const struct ti_sysc_module_data *data, struct ti_sysc_cookie *cookie); diff --git a/include/linux/platform_data/video-clcd-versatile.h b/include/linux/platform_data/video-clcd-versatile.h deleted file mode 100644 index 305ebaec3afd..000000000000 --- a/include/linux/platform_data/video-clcd-versatile.h +++ /dev/null @@ -1,28 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef PLAT_CLCD_H -#define PLAT_CLCD_H - -#ifdef CONFIG_PLAT_VERSATILE_CLCD -struct clcd_panel *versatile_clcd_get_panel(const char *); -int versatile_clcd_setup_dma(struct clcd_fb *, unsigned long); -int versatile_clcd_mmap_dma(struct clcd_fb *, struct vm_area_struct *); -void versatile_clcd_remove_dma(struct clcd_fb *); -#else -static inline struct clcd_panel *versatile_clcd_get_panel(const char *s) -{ - return NULL; -} -static inline int versatile_clcd_setup_dma(struct clcd_fb *fb, unsigned long framesize) -{ - return -ENODEV; -} -static inline int versatile_clcd_mmap_dma(struct clcd_fb *fb, struct vm_area_struct *vm) -{ - return -ENODEV; -} -static inline void versatile_clcd_remove_dma(struct clcd_fb *fb) -{ -} -#endif - -#endif diff --git a/include/linux/platform_data/video-nuc900fb.h b/include/linux/platform_data/video-nuc900fb.h deleted file mode 100644 index 3da504460c91..000000000000 --- a/include/linux/platform_data/video-nuc900fb.h +++ /dev/null @@ -1,79 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* linux/include/asm/arch-nuc900/fb.h - * - * Copyright (c) 2008 Nuvoton technology corporation - * All rights reserved. - * - * Changelog: - * - * 2008/08/26 vincen.zswan modify this file for LCD. - */ - -#ifndef __ASM_ARM_FB_H -#define __ASM_ARM_FB_H - - - -/* LCD Controller Hardware Desc */ -struct nuc900fb_hw { - unsigned int lcd_dccs; - unsigned int lcd_device_ctrl; - unsigned int lcd_mpulcd_cmd; - unsigned int lcd_int_cs; - unsigned int lcd_crtc_size; - unsigned int lcd_crtc_dend; - unsigned int lcd_crtc_hr; - unsigned int lcd_crtc_hsync; - unsigned int lcd_crtc_vr; - unsigned int lcd_va_baddr0; - unsigned int lcd_va_baddr1; - unsigned int lcd_va_fbctrl; - unsigned int lcd_va_scale; - unsigned int lcd_va_test; - unsigned int lcd_va_win; - unsigned int lcd_va_stuff; -}; - -/* LCD Display Description */ -struct nuc900fb_display { - /* LCD Image type */ - unsigned type; - - /* LCD Screen Size */ - unsigned short width; - unsigned short height; - - /* LCD Screen Info */ - unsigned short xres; - unsigned short yres; - unsigned short bpp; - - unsigned long pixclock; - unsigned short left_margin; - unsigned short right_margin; - unsigned short hsync_len; - unsigned short upper_margin; - unsigned short lower_margin; - unsigned short vsync_len; - - /* hardware special register value */ - unsigned int dccs; - unsigned int devctl; - unsigned int fbctrl; - unsigned int scale; -}; - -struct nuc900fb_mach_info { - struct nuc900fb_display *displays; - unsigned num_displays; - unsigned default_display; - /* GPIO Setting Info */ - unsigned gpio_dir; - unsigned gpio_dir_mask; - unsigned gpio_data; - unsigned gpio_data_mask; -}; - -extern void __init nuc900_fb_set_platdata(struct nuc900fb_mach_info *); - -#endif /* __ASM_ARM_FB_H */ diff --git a/include/linux/platform_data/wilco-ec.h b/include/linux/platform_data/wilco-ec.h index 1ff224793c99..ad03b586a095 100644 --- a/include/linux/platform_data/wilco-ec.h +++ b/include/linux/platform_data/wilco-ec.h @@ -13,12 +13,9 @@ /* Message flags for using the mailbox() interface */ #define WILCO_EC_FLAG_NO_RESPONSE BIT(0) /* EC does not respond */ -#define WILCO_EC_FLAG_EXTENDED_DATA BIT(1) /* EC returns 256 data bytes */ /* Normal commands have a maximum 32 bytes of data */ #define EC_MAILBOX_DATA_SIZE 32 -/* Extended commands have 256 bytes of response data */ -#define EC_MAILBOX_DATA_SIZE_EXTENDED 256 /** * struct wilco_ec_device - Wilco Embedded Controller handle. @@ -32,6 +29,7 @@ * @data_size: Size of the data buffer used for EC communication. * @debugfs_pdev: The child platform_device used by the debugfs sub-driver. * @rtc_pdev: The child platform_device used by the RTC sub-driver. + * @telem_pdev: The child platform_device used by the telemetry sub-driver. */ struct wilco_ec_device { struct device *dev; @@ -43,6 +41,7 @@ struct wilco_ec_device { size_t data_size; struct platform_device *debugfs_pdev; struct platform_device *rtc_pdev; + struct platform_device *telem_pdev; }; /** @@ -85,14 +84,12 @@ struct wilco_ec_response { * enum wilco_ec_msg_type - Message type to select a set of command codes. * @WILCO_EC_MSG_LEGACY: Legacy EC messages for standard EC behavior. * @WILCO_EC_MSG_PROPERTY: Get/Set/Sync EC controlled NVRAM property. - * @WILCO_EC_MSG_TELEMETRY_SHORT: 32 bytes of telemetry data provided by the EC. - * @WILCO_EC_MSG_TELEMETRY_LONG: 256 bytes of telemetry data provided by the EC. + * @WILCO_EC_MSG_TELEMETRY: Request telemetry data from the EC. */ enum wilco_ec_msg_type { WILCO_EC_MSG_LEGACY = 0x00f0, WILCO_EC_MSG_PROPERTY = 0x00f2, - WILCO_EC_MSG_TELEMETRY_SHORT = 0x00f5, - WILCO_EC_MSG_TELEMETRY_LONG = 0x00f6, + WILCO_EC_MSG_TELEMETRY = 0x00f5, }; /** @@ -123,4 +120,87 @@ struct wilco_ec_message { */ int wilco_ec_mailbox(struct wilco_ec_device *ec, struct wilco_ec_message *msg); +/* + * A Property is typically a data item that is stored to NVRAM + * by the EC. Each of these data items has an index associated + * with it, known as the Property ID (PID). Properties may have + * variable lengths, up to a max of WILCO_EC_PROPERTY_MAX_SIZE + * bytes. Properties can be simple integers, or they may be more + * complex binary data. + */ + +#define WILCO_EC_PROPERTY_MAX_SIZE 4 + +/** + * struct ec_property_set_msg - Message to get or set a property. + * @property_id: Which property to get or set. + * @length: Number of bytes of |data| that are used. + * @data: Actual property data. + */ +struct wilco_ec_property_msg { + u32 property_id; + int length; + u8 data[WILCO_EC_PROPERTY_MAX_SIZE]; +}; + +/** + * wilco_ec_get_property() - Retrieve a property from the EC. + * @ec: Embedded Controller device. + * @prop_msg: Message for request and response. + * + * The property_id field of |prop_msg| should be filled before calling this + * function. The result will be stored in the data and length fields. + * + * Return: 0 on success, negative error code on failure. + */ +int wilco_ec_get_property(struct wilco_ec_device *ec, + struct wilco_ec_property_msg *prop_msg); + +/** + * wilco_ec_set_property() - Store a property on the EC. + * @ec: Embedded Controller device. + * @prop_msg: Message for request and response. + * + * The property_id, length, and data fields of |prop_msg| should be + * filled before calling this function. + * + * Return: 0 on success, negative error code on failure. + */ +int wilco_ec_set_property(struct wilco_ec_device *ec, + struct wilco_ec_property_msg *prop_msg); + +/** + * wilco_ec_get_byte_property() - Retrieve a byte-size property from the EC. + * @ec: Embedded Controller device. + * @property_id: Which property to retrieve. + * @val: The result value, will be filled by this function. + * + * Return: 0 on success, negative error code on failure. + */ +int wilco_ec_get_byte_property(struct wilco_ec_device *ec, u32 property_id, + u8 *val); + +/** + * wilco_ec_get_byte_property() - Store a byte-size property on the EC. + * @ec: Embedded Controller device. + * @property_id: Which property to store. + * @val: Value to store. + * + * Return: 0 on success, negative error code on failure. + */ +int wilco_ec_set_byte_property(struct wilco_ec_device *ec, u32 property_id, + u8 val); + +/** + * wilco_ec_add_sysfs() - Create sysfs entries + * @ec: Wilco EC device + * + * wilco_ec_remove_sysfs() needs to be called afterwards + * to perform the necessary cleanup. + * + * Return: 0 on success or negative error code on failure. + */ +int wilco_ec_add_sysfs(struct wilco_ec_device *ec); +void wilco_ec_remove_sysfs(struct wilco_ec_device *ec); + #endif /* WILCO_EC_H */ diff --git a/include/linux/platform_data/x86/asus-wmi.h b/include/linux/platform_data/x86/asus-wmi.h index bfba245636a7..60249e22e844 100644 --- a/include/linux/platform_data/x86/asus-wmi.h +++ b/include/linux/platform_data/x86/asus-wmi.h @@ -12,14 +12,14 @@ #define ASUS_WMI_METHODID_GPID 0x44495047 /* Get Panel ID?? (Resol) */ #define ASUS_WMI_METHODID_QMOD 0x444F4D51 /* Quiet MODe */ #define ASUS_WMI_METHODID_SPLV 0x4C425053 /* Set Panel Light Value */ -#define ASUS_WMI_METHODID_AGFN 0x4E464741 /* FaN? */ +#define ASUS_WMI_METHODID_AGFN 0x4E464741 /* Atk Generic FuNction */ #define ASUS_WMI_METHODID_SFUN 0x4E554653 /* FUNCtionalities */ #define ASUS_WMI_METHODID_SDSP 0x50534453 /* Set DiSPlay output */ #define ASUS_WMI_METHODID_GDSP 0x50534447 /* Get DiSPlay output */ #define ASUS_WMI_METHODID_DEVP 0x50564544 /* DEVice Policy */ #define ASUS_WMI_METHODID_OSVR 0x5256534F /* OS VeRsion */ -#define ASUS_WMI_METHODID_DSTS 0x53544344 /* Device STatuS */ -#define ASUS_WMI_METHODID_DSTS2 0x53545344 /* Device STatuS #2*/ +#define ASUS_WMI_METHODID_DCTS 0x53544344 /* Device status (DCTS) */ +#define ASUS_WMI_METHODID_DSTS 0x53545344 /* Device status (DSTS) */ #define ASUS_WMI_METHODID_BSTS 0x53545342 /* Bios STatuS ? */ #define ASUS_WMI_METHODID_DEVS 0x53564544 /* DEVice Set */ #define ASUS_WMI_METHODID_CFVS 0x53564643 /* CPU Frequency Volt Set */ @@ -57,6 +57,7 @@ #define ASUS_WMI_DEVID_KBD_BACKLIGHT 0x00050021 #define ASUS_WMI_DEVID_LIGHT_SENSOR 0x00050022 /* ?? */ #define ASUS_WMI_DEVID_LIGHTBAR 0x00050025 +#define ASUS_WMI_DEVID_FAN_BOOST_MODE 0x00110018 /* Misc */ #define ASUS_WMI_DEVID_CAMERA 0x00060013 @@ -71,7 +72,8 @@ /* Fan, Thermal */ #define ASUS_WMI_DEVID_THERMAL_CTRL 0x00110011 -#define ASUS_WMI_DEVID_FAN_CTRL 0x00110012 +#define ASUS_WMI_DEVID_FAN_CTRL 0x00110012 /* deprecated */ +#define ASUS_WMI_DEVID_CPU_FAN_CTRL 0x00110013 /* Power */ #define ASUS_WMI_DEVID_PROCESSOR_STATE 0x00120012 @@ -79,6 +81,9 @@ /* Deep S3 / Resume on LID open */ #define ASUS_WMI_DEVID_LID_RESUME 0x00120031 +/* Maximum charging percentage */ +#define ASUS_WMI_DEVID_RSOC 0x00120057 + /* DSTS masks */ #define ASUS_WMI_DSTS_STATUS_BIT 0x00000001 #define ASUS_WMI_DSTS_UNKNOWN_BIT 0x00000002 diff --git a/include/linux/platform_data/xilinx-ll-temac.h b/include/linux/platform_data/xilinx-ll-temac.h index 368530f98176..f4a68136afa6 100644 --- a/include/linux/platform_data/xilinx-ll-temac.h +++ b/include/linux/platform_data/xilinx-ll-temac.h @@ -4,6 +4,7 @@ #include <linux/if_ether.h> #include <linux/phy.h> +#include <linux/spinlock.h> struct ll_temac_platform_data { bool txcsum; /* Enable/disable TX checksum */ @@ -21,7 +22,7 @@ struct ll_temac_platform_data { * TEMAC IP block, the same mutex should be passed here, as * they share the same DCR bus bridge. */ - struct mutex *indirect_mutex; + spinlock_t *indirect_lock; /* DMA channel control setup */ u8 tx_irq_timeout; /* TX Interrupt Delay Time-out */ u8 tx_irq_count; /* TX Interrupt Coalescing Threshold Count */ diff --git a/include/linux/platform_device.h b/include/linux/platform_device.h index beb25f277889..1b5cec067533 100644 --- a/include/linux/platform_device.h +++ b/include/linux/platform_device.h @@ -4,7 +4,7 @@ * * Copyright (c) 2001-2003 Patrick Mochel <mochel@osdl.org> * - * See Documentation/driver-model/ for more information. + * See Documentation/driver-api/driver-model/ for more information. */ #ifndef _PLATFORM_DEVICE_H_ @@ -24,6 +24,7 @@ struct platform_device { int id; bool id_auto; struct device dev; + u64 dma_mask; u32 num_resources; struct resource *resource; @@ -48,13 +49,16 @@ extern void platform_device_unregister(struct platform_device *); extern struct bus_type platform_bus_type; extern struct device platform_bus; -extern void arch_setup_pdev_archdata(struct platform_device *); extern struct resource *platform_get_resource(struct platform_device *, unsigned int, unsigned int); +extern struct device * +platform_find_device_by_driver(struct device *start, + const struct device_driver *drv); extern void __iomem * devm_platform_ioremap_resource(struct platform_device *pdev, unsigned int index); extern int platform_get_irq(struct platform_device *, unsigned int); +extern int platform_get_irq_optional(struct platform_device *, unsigned int); extern int platform_irq_count(struct platform_device *); extern struct resource *platform_get_resource_byname(struct platform_device *, unsigned int, diff --git a/include/linux/pm.h b/include/linux/pm.h index 345d74a727e3..4c441be03079 100644 --- a/include/linux/pm.h +++ b/include/linux/pm.h @@ -271,7 +271,7 @@ typedef struct pm_message { * actions to be performed by a device driver's callbacks generally depend on * the platform and subsystem the device belongs to. * - * Refer to Documentation/power/runtime_pm.txt for more information about the + * Refer to Documentation/power/runtime_pm.rst for more information about the * role of the @runtime_suspend(), @runtime_resume() and @runtime_idle() * callbacks in device runtime power management. */ @@ -712,8 +712,6 @@ struct dev_pm_domain { extern void device_pm_lock(void); extern void dpm_resume_start(pm_message_t state); extern void dpm_resume_end(pm_message_t state); -extern void dpm_noirq_resume_devices(pm_message_t state); -extern void dpm_noirq_end(void); extern void dpm_resume_noirq(pm_message_t state); extern void dpm_resume_early(pm_message_t state); extern void dpm_resume(pm_message_t state); @@ -722,8 +720,6 @@ extern void dpm_complete(pm_message_t state); extern void device_pm_unlock(void); extern int dpm_suspend_end(pm_message_t state); extern int dpm_suspend_start(pm_message_t state); -extern void dpm_noirq_begin(void); -extern int dpm_noirq_suspend_devices(pm_message_t state); extern int dpm_suspend_noirq(pm_message_t state); extern int dpm_suspend_late(pm_message_t state); extern int dpm_suspend(pm_message_t state); @@ -760,7 +756,6 @@ extern int pm_generic_poweroff_late(struct device *dev); extern int pm_generic_poweroff(struct device *dev); extern void pm_generic_complete(struct device *dev); -extern void dev_pm_skip_next_resume_phases(struct device *dev); extern bool dev_pm_may_skip_resume(struct device *dev); extern bool dev_pm_smart_suspend_and_suspended(struct device *dev); diff --git a/include/linux/pm_domain.h b/include/linux/pm_domain.h index 91d9bf497071..baf02ff91a31 100644 --- a/include/linux/pm_domain.h +++ b/include/linux/pm_domain.h @@ -197,9 +197,9 @@ static inline struct generic_pm_domain_data *dev_gpd_data(struct device *dev) int pm_genpd_add_device(struct generic_pm_domain *genpd, struct device *dev); int pm_genpd_remove_device(struct device *dev); int pm_genpd_add_subdomain(struct generic_pm_domain *genpd, - struct generic_pm_domain *new_subdomain); + struct generic_pm_domain *subdomain); int pm_genpd_remove_subdomain(struct generic_pm_domain *genpd, - struct generic_pm_domain *target); + struct generic_pm_domain *subdomain); int pm_genpd_init(struct generic_pm_domain *genpd, struct dev_power_governor *gov, bool is_off); int pm_genpd_remove(struct generic_pm_domain *genpd); @@ -226,12 +226,12 @@ static inline int pm_genpd_remove_device(struct device *dev) return -ENOSYS; } static inline int pm_genpd_add_subdomain(struct generic_pm_domain *genpd, - struct generic_pm_domain *new_sd) + struct generic_pm_domain *subdomain) { return -ENOSYS; } static inline int pm_genpd_remove_subdomain(struct generic_pm_domain *genpd, - struct generic_pm_domain *target) + struct generic_pm_domain *subdomain) { return -ENOSYS; } @@ -282,8 +282,8 @@ int of_genpd_add_provider_onecell(struct device_node *np, struct genpd_onecell_data *data); void of_genpd_del_provider(struct device_node *np); int of_genpd_add_device(struct of_phandle_args *args, struct device *dev); -int of_genpd_add_subdomain(struct of_phandle_args *parent, - struct of_phandle_args *new_subdomain); +int of_genpd_add_subdomain(struct of_phandle_args *parent_spec, + struct of_phandle_args *subdomain_spec); struct generic_pm_domain *of_genpd_remove_last(struct device_node *np); int of_genpd_parse_idle_states(struct device_node *dn, struct genpd_power_state **states, int *n); @@ -316,8 +316,8 @@ static inline int of_genpd_add_device(struct of_phandle_args *args, return -ENODEV; } -static inline int of_genpd_add_subdomain(struct of_phandle_args *parent, - struct of_phandle_args *new_subdomain) +static inline int of_genpd_add_subdomain(struct of_phandle_args *parent_spec, + struct of_phandle_args *subdomain_spec) { return -ENODEV; } diff --git a/include/linux/pm_opp.h b/include/linux/pm_opp.h index 5f3a1ee9c4c2..b8197ab014f2 100644 --- a/include/linux/pm_opp.h +++ b/include/linux/pm_opp.h @@ -96,6 +96,8 @@ unsigned long dev_pm_opp_get_suspend_opp_freq(struct device *dev); struct dev_pm_opp *dev_pm_opp_find_freq_exact(struct device *dev, unsigned long freq, bool available); +struct dev_pm_opp *dev_pm_opp_find_level_exact(struct device *dev, + unsigned int level); struct dev_pm_opp *dev_pm_opp_find_freq_floor(struct device *dev, unsigned long *freq); @@ -128,8 +130,8 @@ struct opp_table *dev_pm_opp_set_clkname(struct device *dev, const char * name); void dev_pm_opp_put_clkname(struct opp_table *opp_table); struct opp_table *dev_pm_opp_register_set_opp_helper(struct device *dev, int (*set_opp)(struct dev_pm_set_opp_data *data)); void dev_pm_opp_unregister_set_opp_helper(struct opp_table *opp_table); -struct opp_table *dev_pm_opp_set_genpd_virt_dev(struct device *dev, struct device *virt_dev, int index); -void dev_pm_opp_put_genpd_virt_dev(struct opp_table *opp_table, struct device *virt_dev); +struct opp_table *dev_pm_opp_attach_genpd(struct device *dev, const char **names, struct device ***virt_devs); +void dev_pm_opp_detach_genpd(struct opp_table *opp_table); int dev_pm_opp_xlate_performance_state(struct opp_table *src_table, struct opp_table *dst_table, unsigned int pstate); int dev_pm_opp_set_rate(struct device *dev, unsigned long target_freq); int dev_pm_opp_set_sharing_cpus(struct device *cpu_dev, const struct cpumask *cpumask); @@ -200,6 +202,12 @@ static inline struct dev_pm_opp *dev_pm_opp_find_freq_exact(struct device *dev, return ERR_PTR(-ENOTSUPP); } +static inline struct dev_pm_opp *dev_pm_opp_find_level_exact(struct device *dev, + unsigned int level) +{ + return ERR_PTR(-ENOTSUPP); +} + static inline struct dev_pm_opp *dev_pm_opp_find_freq_floor(struct device *dev, unsigned long *freq) { @@ -292,12 +300,12 @@ static inline struct opp_table *dev_pm_opp_set_clkname(struct device *dev, const static inline void dev_pm_opp_put_clkname(struct opp_table *opp_table) {} -static inline struct opp_table *dev_pm_opp_set_genpd_virt_dev(struct device *dev, struct device *virt_dev, int index) +static inline struct opp_table *dev_pm_opp_attach_genpd(struct device *dev, const char **names, struct device ***virt_devs) { return ERR_PTR(-ENOTSUPP); } -static inline void dev_pm_opp_put_genpd_virt_dev(struct opp_table *opp_table, struct device *virt_dev) {} +static inline void dev_pm_opp_detach_genpd(struct opp_table *opp_table) {} static inline int dev_pm_opp_xlate_performance_state(struct opp_table *src_table, struct opp_table *dst_table, unsigned int pstate) { diff --git a/include/linux/pm_qos.h b/include/linux/pm_qos.h index 6ea1ae373d77..222c3e01397c 100644 --- a/include/linux/pm_qos.h +++ b/include/linux/pm_qos.h @@ -13,9 +13,6 @@ enum { PM_QOS_RESERVED = 0, PM_QOS_CPU_DMA_LATENCY, - PM_QOS_NETWORK_LATENCY, - PM_QOS_NETWORK_THROUGHPUT, - PM_QOS_MEMORY_BANDWIDTH, /* insert new class ID */ PM_QOS_NUM_CLASSES, @@ -33,13 +30,12 @@ enum pm_qos_flags_status { #define PM_QOS_LATENCY_ANY_NS ((s64)PM_QOS_LATENCY_ANY * NSEC_PER_USEC) #define PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE (2000 * USEC_PER_SEC) -#define PM_QOS_NETWORK_LAT_DEFAULT_VALUE (2000 * USEC_PER_SEC) -#define PM_QOS_NETWORK_THROUGHPUT_DEFAULT_VALUE 0 -#define PM_QOS_MEMORY_BANDWIDTH_DEFAULT_VALUE 0 #define PM_QOS_RESUME_LATENCY_DEFAULT_VALUE PM_QOS_LATENCY_ANY #define PM_QOS_RESUME_LATENCY_NO_CONSTRAINT PM_QOS_LATENCY_ANY #define PM_QOS_RESUME_LATENCY_NO_CONSTRAINT_NS PM_QOS_LATENCY_ANY_NS #define PM_QOS_LATENCY_TOLERANCE_DEFAULT_VALUE 0 +#define PM_QOS_MIN_FREQUENCY_DEFAULT_VALUE 0 +#define PM_QOS_MAX_FREQUENCY_DEFAULT_VALUE (-1) #define PM_QOS_LATENCY_TOLERANCE_NO_CONSTRAINT (-1) #define PM_QOS_FLAG_NO_POWER_OFF (1 << 0) @@ -58,6 +54,8 @@ struct pm_qos_flags_request { enum dev_pm_qos_req_type { DEV_PM_QOS_RESUME_LATENCY = 1, DEV_PM_QOS_LATENCY_TOLERANCE, + DEV_PM_QOS_MIN_FREQUENCY, + DEV_PM_QOS_MAX_FREQUENCY, DEV_PM_QOS_FLAGS, }; @@ -99,10 +97,14 @@ struct pm_qos_flags { struct dev_pm_qos { struct pm_qos_constraints resume_latency; struct pm_qos_constraints latency_tolerance; + struct pm_qos_constraints min_frequency; + struct pm_qos_constraints max_frequency; struct pm_qos_flags flags; struct dev_pm_qos_request *resume_latency_req; struct dev_pm_qos_request *latency_tolerance_req; struct dev_pm_qos_request *flags_req; + struct dev_pm_qos_request *min_frequency_req; + struct dev_pm_qos_request *max_frequency_req; }; /* Action requested to pm_qos_update_target */ @@ -139,16 +141,18 @@ s32 pm_qos_read_value(struct pm_qos_constraints *c); #ifdef CONFIG_PM enum pm_qos_flags_status __dev_pm_qos_flags(struct device *dev, s32 mask); enum pm_qos_flags_status dev_pm_qos_flags(struct device *dev, s32 mask); -s32 __dev_pm_qos_read_value(struct device *dev); -s32 dev_pm_qos_read_value(struct device *dev); +s32 __dev_pm_qos_resume_latency(struct device *dev); +s32 dev_pm_qos_read_value(struct device *dev, enum dev_pm_qos_req_type type); int dev_pm_qos_add_request(struct device *dev, struct dev_pm_qos_request *req, enum dev_pm_qos_req_type type, s32 value); int dev_pm_qos_update_request(struct dev_pm_qos_request *req, s32 new_value); int dev_pm_qos_remove_request(struct dev_pm_qos_request *req); int dev_pm_qos_add_notifier(struct device *dev, - struct notifier_block *notifier); + struct notifier_block *notifier, + enum dev_pm_qos_req_type type); int dev_pm_qos_remove_notifier(struct device *dev, - struct notifier_block *notifier); + struct notifier_block *notifier, + enum dev_pm_qos_req_type type); void dev_pm_qos_constraints_init(struct device *dev); void dev_pm_qos_constraints_destroy(struct device *dev); int dev_pm_qos_add_ancestor_request(struct device *dev, @@ -174,7 +178,7 @@ static inline s32 dev_pm_qos_requested_flags(struct device *dev) return dev->power.qos->flags_req->data.flr.flags; } -static inline s32 dev_pm_qos_raw_read_value(struct device *dev) +static inline s32 dev_pm_qos_raw_resume_latency(struct device *dev) { return IS_ERR_OR_NULL(dev->power.qos) ? PM_QOS_RESUME_LATENCY_NO_CONSTRAINT : @@ -187,10 +191,24 @@ static inline enum pm_qos_flags_status __dev_pm_qos_flags(struct device *dev, static inline enum pm_qos_flags_status dev_pm_qos_flags(struct device *dev, s32 mask) { return PM_QOS_FLAGS_UNDEFINED; } -static inline s32 __dev_pm_qos_read_value(struct device *dev) - { return PM_QOS_RESUME_LATENCY_NO_CONSTRAINT; } -static inline s32 dev_pm_qos_read_value(struct device *dev) +static inline s32 __dev_pm_qos_resume_latency(struct device *dev) { return PM_QOS_RESUME_LATENCY_NO_CONSTRAINT; } +static inline s32 dev_pm_qos_read_value(struct device *dev, + enum dev_pm_qos_req_type type) +{ + switch (type) { + case DEV_PM_QOS_RESUME_LATENCY: + return PM_QOS_RESUME_LATENCY_NO_CONSTRAINT; + case DEV_PM_QOS_MIN_FREQUENCY: + return PM_QOS_MIN_FREQUENCY_DEFAULT_VALUE; + case DEV_PM_QOS_MAX_FREQUENCY: + return PM_QOS_MAX_FREQUENCY_DEFAULT_VALUE; + default: + WARN_ON(1); + return 0; + } +} + static inline int dev_pm_qos_add_request(struct device *dev, struct dev_pm_qos_request *req, enum dev_pm_qos_req_type type, @@ -202,10 +220,12 @@ static inline int dev_pm_qos_update_request(struct dev_pm_qos_request *req, static inline int dev_pm_qos_remove_request(struct dev_pm_qos_request *req) { return 0; } static inline int dev_pm_qos_add_notifier(struct device *dev, - struct notifier_block *notifier) + struct notifier_block *notifier, + enum dev_pm_qos_req_type type) { return 0; } static inline int dev_pm_qos_remove_notifier(struct device *dev, - struct notifier_block *notifier) + struct notifier_block *notifier, + enum dev_pm_qos_req_type type) { return 0; } static inline void dev_pm_qos_constraints_init(struct device *dev) { @@ -241,7 +261,7 @@ static inline s32 dev_pm_qos_requested_resume_latency(struct device *dev) return PM_QOS_RESUME_LATENCY_NO_CONSTRAINT; } static inline s32 dev_pm_qos_requested_flags(struct device *dev) { return 0; } -static inline s32 dev_pm_qos_raw_read_value(struct device *dev) +static inline s32 dev_pm_qos_raw_resume_latency(struct device *dev) { return PM_QOS_RESUME_LATENCY_NO_CONSTRAINT; } diff --git a/include/linux/pm_wakeup.h b/include/linux/pm_wakeup.h index ce57771fab9b..661efa029c96 100644 --- a/include/linux/pm_wakeup.h +++ b/include/linux/pm_wakeup.h @@ -21,6 +21,7 @@ struct wake_irq; * struct wakeup_source - Representation of wakeup sources * * @name: Name of the wakeup source + * @id: Wakeup source id * @entry: Wakeup source list entry * @lock: Wakeup source lock * @wakeirq: Optional device specific wakeirq @@ -35,11 +36,13 @@ struct wake_irq; * @relax_count: Number of times the wakeup source was deactivated. * @expire_count: Number of times the wakeup source's timeout has expired. * @wakeup_count: Number of times the wakeup source might abort suspend. + * @dev: Struct device for sysfs statistics about the wakeup source. * @active: Status of the wakeup source. - * @has_timeout: The wakeup source has been activated with a timeout. + * @autosleep_enabled: Autosleep is active, so update @prevent_sleep_time. */ struct wakeup_source { const char *name; + int id; struct list_head entry; spinlock_t lock; struct wake_irq *wakeirq; @@ -55,6 +58,7 @@ struct wakeup_source { unsigned long relax_count; unsigned long expire_count; unsigned long wakeup_count; + struct device *dev; bool active:1; bool autosleep_enabled:1; }; @@ -81,12 +85,12 @@ static inline void device_set_wakeup_path(struct device *dev) } /* drivers/base/power/wakeup.c */ -extern void wakeup_source_prepare(struct wakeup_source *ws, const char *name); extern struct wakeup_source *wakeup_source_create(const char *name); extern void wakeup_source_destroy(struct wakeup_source *ws); extern void wakeup_source_add(struct wakeup_source *ws); extern void wakeup_source_remove(struct wakeup_source *ws); -extern struct wakeup_source *wakeup_source_register(const char *name); +extern struct wakeup_source *wakeup_source_register(struct device *dev, + const char *name); extern void wakeup_source_unregister(struct wakeup_source *ws); extern int device_wakeup_enable(struct device *dev); extern int device_wakeup_disable(struct device *dev); @@ -112,9 +116,6 @@ static inline bool device_can_wakeup(struct device *dev) return dev->power.can_wakeup; } -static inline void wakeup_source_prepare(struct wakeup_source *ws, - const char *name) {} - static inline struct wakeup_source *wakeup_source_create(const char *name) { return NULL; @@ -126,7 +127,8 @@ static inline void wakeup_source_add(struct wakeup_source *ws) {} static inline void wakeup_source_remove(struct wakeup_source *ws) {} -static inline struct wakeup_source *wakeup_source_register(const char *name) +static inline struct wakeup_source *wakeup_source_register(struct device *dev, + const char *name) { return NULL; } @@ -181,13 +183,6 @@ static inline void pm_wakeup_dev_event(struct device *dev, unsigned int msec, #endif /* !CONFIG_PM_SLEEP */ -static inline void wakeup_source_init(struct wakeup_source *ws, - const char *name) -{ - wakeup_source_prepare(ws, name); - wakeup_source_add(ws); -} - static inline void __pm_wakeup_event(struct wakeup_source *ws, unsigned int msec) { return pm_wakeup_ws_event(ws, msec, false); diff --git a/include/linux/poison.h b/include/linux/poison.h index d6d980a681c7..df34330b4e34 100644 --- a/include/linux/poison.h +++ b/include/linux/poison.h @@ -21,7 +21,7 @@ * non-initialized list entries. */ #define LIST_POISON1 ((void *) 0x100 + POISON_POINTER_DELTA) -#define LIST_POISON2 ((void *) 0x200 + POISON_POINTER_DELTA) +#define LIST_POISON2 ((void *) 0x122 + POISON_POINTER_DELTA) /********** include/linux/timer.h **********/ /* diff --git a/include/linux/posix-timers.h b/include/linux/posix-timers.h index b20798fc5191..3d10c84a97a9 100644 --- a/include/linux/posix-timers.h +++ b/include/linux/posix-timers.h @@ -4,18 +4,11 @@ #include <linux/spinlock.h> #include <linux/list.h> -#include <linux/sched.h> -#include <linux/timex.h> #include <linux/alarmtimer.h> +#include <linux/timerqueue.h> -struct siginfo; - -struct cpu_timer_list { - struct list_head entry; - u64 expires; - struct task_struct *task; - int firing; -}; +struct kernel_siginfo; +struct task_struct; /* * Bit fields within a clockid: @@ -63,6 +56,115 @@ static inline int clockid_to_fd(const clockid_t clk) return ~(clk >> 3); } +#ifdef CONFIG_POSIX_TIMERS + +/** + * cpu_timer - Posix CPU timer representation for k_itimer + * @node: timerqueue node to queue in the task/sig + * @head: timerqueue head on which this timer is queued + * @task: Pointer to target task + * @elist: List head for the expiry list + * @firing: Timer is currently firing + */ +struct cpu_timer { + struct timerqueue_node node; + struct timerqueue_head *head; + struct task_struct *task; + struct list_head elist; + int firing; +}; + +static inline bool cpu_timer_enqueue(struct timerqueue_head *head, + struct cpu_timer *ctmr) +{ + ctmr->head = head; + return timerqueue_add(head, &ctmr->node); +} + +static inline void cpu_timer_dequeue(struct cpu_timer *ctmr) +{ + if (ctmr->head) { + timerqueue_del(ctmr->head, &ctmr->node); + ctmr->head = NULL; + } +} + +static inline u64 cpu_timer_getexpires(struct cpu_timer *ctmr) +{ + return ctmr->node.expires; +} + +static inline void cpu_timer_setexpires(struct cpu_timer *ctmr, u64 exp) +{ + ctmr->node.expires = exp; +} + +/** + * posix_cputimer_base - Container per posix CPU clock + * @nextevt: Earliest-expiration cache + * @tqhead: timerqueue head for cpu_timers + */ +struct posix_cputimer_base { + u64 nextevt; + struct timerqueue_head tqhead; +}; + +/** + * posix_cputimers - Container for posix CPU timer related data + * @bases: Base container for posix CPU clocks + * @timers_active: Timers are queued. + * @expiry_active: Timer expiry is active. Used for + * process wide timers to avoid multiple + * task trying to handle expiry concurrently + * + * Used in task_struct and signal_struct + */ +struct posix_cputimers { + struct posix_cputimer_base bases[CPUCLOCK_MAX]; + unsigned int timers_active; + unsigned int expiry_active; +}; + +static inline void posix_cputimers_init(struct posix_cputimers *pct) +{ + memset(pct, 0, sizeof(*pct)); + pct->bases[0].nextevt = U64_MAX; + pct->bases[1].nextevt = U64_MAX; + pct->bases[2].nextevt = U64_MAX; +} + +void posix_cputimers_group_init(struct posix_cputimers *pct, u64 cpu_limit); + +static inline void posix_cputimers_rt_watchdog(struct posix_cputimers *pct, + u64 runtime) +{ + pct->bases[CPUCLOCK_SCHED].nextevt = runtime; +} + +/* Init task static initializer */ +#define INIT_CPU_TIMERBASE(b) { \ + .nextevt = U64_MAX, \ +} + +#define INIT_CPU_TIMERBASES(b) { \ + INIT_CPU_TIMERBASE(b[0]), \ + INIT_CPU_TIMERBASE(b[1]), \ + INIT_CPU_TIMERBASE(b[2]), \ +} + +#define INIT_CPU_TIMERS(s) \ + .posix_cputimers = { \ + .bases = INIT_CPU_TIMERBASES(s.posix_cputimers.bases), \ + }, +#else +struct posix_cputimers { }; +struct cpu_timer { }; +#define INIT_CPU_TIMERS(s) +static inline void posix_cputimers_init(struct posix_cputimers *pct) { } +static inline void posix_cputimers_group_init(struct posix_cputimers *pct, + u64 cpu_limit) { } +#endif + #define REQUEUE_PENDING 1 /** @@ -85,7 +187,8 @@ static inline int clockid_to_fd(const clockid_t clk) * @it_process: The task to wakeup on clock_nanosleep (CPU timers) * @sigq: Pointer to preallocated sigqueue * @it: Union representing the various posix timer type - * internals. Also used for rcu freeing the timer. + * internals. + * @rcu: RCU head for freeing the timer. */ struct k_itimer { struct list_head list; @@ -110,15 +213,15 @@ struct k_itimer { struct { struct hrtimer timer; } real; - struct cpu_timer_list cpu; + struct cpu_timer cpu; struct { struct alarm alarmtimer; } alarm; - struct rcu_head rcu; } it; + struct rcu_head rcu; }; -void run_posix_cpu_timers(struct task_struct *task); +void run_posix_cpu_timers(void); void posix_cpu_timers_exit(struct task_struct *task); void posix_cpu_timers_exit_group(struct task_struct *task); void set_process_cpu_timer(struct task_struct *task, unsigned int clock_idx, diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h index 6f348b3ee2e0..28413f737e7d 100644 --- a/include/linux/power_supply.h +++ b/include/linux/power_supply.h @@ -128,6 +128,8 @@ enum power_supply_property { POWER_SUPPLY_PROP_CHARGE_CONTROL_START_THRESHOLD, /* in percents! */ POWER_SUPPLY_PROP_CHARGE_CONTROL_END_THRESHOLD, /* in percents! */ POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT, + POWER_SUPPLY_PROP_INPUT_VOLTAGE_LIMIT, + POWER_SUPPLY_PROP_INPUT_POWER_LIMIT, POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN, POWER_SUPPLY_PROP_ENERGY_EMPTY_DESIGN, POWER_SUPPLY_PROP_ENERGY_FULL, @@ -480,4 +482,17 @@ static inline bool power_supply_is_watt_property(enum power_supply_property psp) return 0; } +#ifdef CONFIG_POWER_SUPPLY_HWMON +int power_supply_add_hwmon_sysfs(struct power_supply *psy); +void power_supply_remove_hwmon_sysfs(struct power_supply *psy); +#else +static inline int power_supply_add_hwmon_sysfs(struct power_supply *psy) +{ + return 0; +} + +static inline +void power_supply_remove_hwmon_sysfs(struct power_supply *psy) {} +#endif + #endif /* __LINUX_POWER_SUPPLY_H__ */ diff --git a/include/linux/preempt.h b/include/linux/preempt.h index dd92b1a93919..bbb68dba37cc 100644 --- a/include/linux/preempt.h +++ b/include/linux/preempt.h @@ -182,7 +182,7 @@ do { \ #define preemptible() (preempt_count() == 0 && !irqs_disabled()) -#ifdef CONFIG_PREEMPT +#ifdef CONFIG_PREEMPTION #define preempt_enable() \ do { \ barrier(); \ @@ -203,7 +203,7 @@ do { \ __preempt_schedule(); \ } while (0) -#else /* !CONFIG_PREEMPT */ +#else /* !CONFIG_PREEMPTION */ #define preempt_enable() \ do { \ barrier(); \ @@ -217,7 +217,7 @@ do { \ } while (0) #define preempt_check_resched() do { } while (0) -#endif /* CONFIG_PREEMPT */ +#endif /* CONFIG_PREEMPTION */ #define preempt_disable_notrace() \ do { \ diff --git a/include/linux/printk.h b/include/linux/printk.h index cefd374c47b1..c09d67edda3a 100644 --- a/include/linux/printk.h +++ b/include/linux/printk.h @@ -488,13 +488,6 @@ extern int hex_dump_to_buffer(const void *buf, size_t len, int rowsize, extern void print_hex_dump(const char *level, const char *prefix_str, int prefix_type, int rowsize, int groupsize, const void *buf, size_t len, bool ascii); -#if defined(CONFIG_DYNAMIC_DEBUG) -#define print_hex_dump_bytes(prefix_str, prefix_type, buf, len) \ - dynamic_hex_dump(prefix_str, prefix_type, 16, 1, buf, len, true) -#else -extern void print_hex_dump_bytes(const char *prefix_str, int prefix_type, - const void *buf, size_t len); -#endif /* defined(CONFIG_DYNAMIC_DEBUG) */ #else static inline void print_hex_dump(const char *level, const char *prefix_str, int prefix_type, int rowsize, int groupsize, @@ -526,4 +519,19 @@ static inline void print_hex_dump_debug(const char *prefix_str, int prefix_type, } #endif +/** + * print_hex_dump_bytes - shorthand form of print_hex_dump() with default params + * @prefix_str: string to prefix each line with; + * caller supplies trailing spaces for alignment if desired + * @prefix_type: controls whether prefix of an offset, address, or none + * is printed (%DUMP_PREFIX_OFFSET, %DUMP_PREFIX_ADDRESS, %DUMP_PREFIX_NONE) + * @buf: data blob to dump + * @len: number of bytes in the @buf + * + * Calls print_hex_dump(), with log level of KERN_DEBUG, + * rowsize of 16, groupsize of 1, and ASCII output included. + */ +#define print_hex_dump_bytes(prefix_str, prefix_type, buf, len) \ + print_hex_dump_debug(prefix_str, prefix_type, 16, 1, buf, len, true) + #endif diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h index 52a283ba0465..a705aa2d03f9 100644 --- a/include/linux/proc_fs.h +++ b/include/linux/proc_fs.h @@ -75,6 +75,15 @@ struct proc_dir_entry *proc_create_net_single_write(const char *name, umode_t mo void *data); extern struct pid *tgid_pidfd_to_pid(const struct file *file); +#ifdef CONFIG_PROC_PID_ARCH_STATUS +/* + * The architecture which selects CONFIG_PROC_PID_ARCH_STATUS must + * provide proc_pid_arch_status() definition. + */ +int proc_pid_arch_status(struct seq_file *m, struct pid_namespace *ns, + struct pid *pid, struct task_struct *task); +#endif /* CONFIG_PROC_PID_ARCH_STATUS */ + #else /* CONFIG_PROC_FS */ static inline void proc_root_init(void) diff --git a/include/linux/processor.h b/include/linux/processor.h index dbc952eec869..dc78bdc7079a 100644 --- a/include/linux/processor.h +++ b/include/linux/processor.h @@ -32,15 +32,6 @@ #define spin_cpu_relax() cpu_relax() #endif -/* - * spin_cpu_yield may be called to yield (undirected) to the hypervisor if - * necessary. This should be used if the wait is expected to take longer - * than context switch overhead, but we can't sleep or do a directed yield. - */ -#ifndef spin_cpu_yield -#define spin_cpu_yield() cpu_relax_yield() -#endif - #ifndef spin_end #define spin_end() #endif diff --git a/include/linux/property.h b/include/linux/property.h index e9caa290cda5..9b3d4ca3a73a 100644 --- a/include/linux/property.h +++ b/include/linux/property.h @@ -76,6 +76,10 @@ int fwnode_property_get_reference_args(const struct fwnode_handle *fwnode, unsigned int nargs, unsigned int index, struct fwnode_reference_args *args); +struct fwnode_handle *fwnode_find_reference(const struct fwnode_handle *fwnode, + const char *name, + unsigned int index); + struct fwnode_handle *fwnode_get_parent(const struct fwnode_handle *fwnode); struct fwnode_handle *fwnode_get_next_parent( struct fwnode_handle *fwnode); @@ -141,6 +145,26 @@ static inline int device_property_read_u64(struct device *dev, return device_property_read_u64_array(dev, propname, val, 1); } +static inline int device_property_count_u8(struct device *dev, const char *propname) +{ + return device_property_read_u8_array(dev, propname, NULL, 0); +} + +static inline int device_property_count_u16(struct device *dev, const char *propname) +{ + return device_property_read_u16_array(dev, propname, NULL, 0); +} + +static inline int device_property_count_u32(struct device *dev, const char *propname) +{ + return device_property_read_u32_array(dev, propname, NULL, 0); +} + +static inline int device_property_count_u64(struct device *dev, const char *propname) +{ + return device_property_read_u64_array(dev, propname, NULL, 0); +} + static inline bool fwnode_property_read_bool(const struct fwnode_handle *fwnode, const char *propname) { @@ -171,6 +195,30 @@ static inline int fwnode_property_read_u64(const struct fwnode_handle *fwnode, return fwnode_property_read_u64_array(fwnode, propname, val, 1); } +static inline int fwnode_property_count_u8(const struct fwnode_handle *fwnode, + const char *propname) +{ + return fwnode_property_read_u8_array(fwnode, propname, NULL, 0); +} + +static inline int fwnode_property_count_u16(const struct fwnode_handle *fwnode, + const char *propname) +{ + return fwnode_property_read_u16_array(fwnode, propname, NULL, 0); +} + +static inline int fwnode_property_count_u32(const struct fwnode_handle *fwnode, + const char *propname) +{ + return fwnode_property_read_u32_array(fwnode, propname, NULL, 0); +} + +static inline int fwnode_property_count_u64(const struct fwnode_handle *fwnode, + const char *propname) +{ + return fwnode_property_read_u64_array(fwnode, propname, NULL, 0); +} + /** * struct property_entry - "Built-in" device property representation. * @name: Name of the property. @@ -329,7 +377,58 @@ int fwnode_graph_parse_endpoint(const struct fwnode_handle *fwnode, /* -------------------------------------------------------------------------- */ /* Software fwnode support - when HW description is incomplete or missing */ +struct software_node; + +/** + * struct software_node_ref_args - Reference with additional arguments + * @node: Reference to a software node + * @nargs: Number of elements in @args array + * @args: Integer arguments + */ +struct software_node_ref_args { + const struct software_node *node; + unsigned int nargs; + u64 args[NR_FWNODE_REFERENCE_ARGS]; +}; + +/** + * struct software_node_reference - Named software node reference property + * @name: Name of the property + * @nrefs: Number of elements in @refs array + * @refs: Array of references with optional arguments + */ +struct software_node_reference { + const char *name; + unsigned int nrefs; + const struct software_node_ref_args *refs; +}; + +/** + * struct software_node - Software node description + * @name: Name of the software node + * @parent: Parent of the software node + * @properties: Array of device properties + * @references: Array of software node reference properties + */ +struct software_node { + const char *name; + const struct software_node *parent; + const struct property_entry *properties; + const struct software_node_reference *references; +}; + bool is_software_node(const struct fwnode_handle *fwnode); +const struct software_node *to_software_node(struct fwnode_handle *fwnode); +struct fwnode_handle *software_node_fwnode(const struct software_node *node); + +const struct software_node * +software_node_find_by_name(const struct software_node *parent, + const char *name); + +int software_node_register_nodes(const struct software_node *nodes); +void software_node_unregister_nodes(const struct software_node *nodes); + +int software_node_register(const struct software_node *node); int software_node_notify(struct device *dev, unsigned long action); diff --git a/include/linux/psci.h b/include/linux/psci.h index a8a15613c157..e2bacc6fd2f2 100644 --- a/include/linux/psci.h +++ b/include/linux/psci.h @@ -15,8 +15,8 @@ bool psci_tos_resident_on(int cpu); -int psci_cpu_init_idle(unsigned int cpu); -int psci_cpu_suspend_enter(unsigned long index); +int psci_cpu_suspend_enter(u32 state); +bool psci_power_state_is_valid(u32 state); enum psci_conduit { PSCI_CONDUIT_NONE, diff --git a/include/linux/pseudo_fs.h b/include/linux/pseudo_fs.h new file mode 100644 index 000000000000..eceda1d1407a --- /dev/null +++ b/include/linux/pseudo_fs.h @@ -0,0 +1,16 @@ +#ifndef __LINUX_PSEUDO_FS__ +#define __LINUX_PSEUDO_FS__ + +#include <linux/fs_context.h> + +struct pseudo_fs_context { + const struct super_operations *ops; + const struct xattr_handler **xattr; + const struct dentry_operations *dops; + unsigned long magic; +}; + +struct pseudo_fs_context *init_pseudo(struct fs_context *fc, + unsigned long magic); + +#endif diff --git a/include/linux/ptp_clock_kernel.h b/include/linux/ptp_clock_kernel.h index 28eb9c792522..93cc4f1d444a 100644 --- a/include/linux/ptp_clock_kernel.h +++ b/include/linux/ptp_clock_kernel.h @@ -213,6 +213,14 @@ extern void ptp_clock_event(struct ptp_clock *ptp, extern int ptp_clock_index(struct ptp_clock *ptp); /** + * scaled_ppm_to_ppb() - convert scaled ppm to ppb + * + * @ppm: Parts per million, but with a 16 bit binary fractional field + */ + +extern s32 scaled_ppm_to_ppb(long ppm); + +/** * ptp_find_pin() - obtain the pin index of a given auxiliary function * * @ptp: The clock obtained from ptp_clock_register(). diff --git a/include/linux/ptrace.h b/include/linux/ptrace.h index d5084ebd9f03..2a9df80ea887 100644 --- a/include/linux/ptrace.h +++ b/include/linux/ptrace.h @@ -355,7 +355,7 @@ static inline void user_single_step_report(struct pt_regs *regs) info.si_code = SI_USER; info.si_pid = 0; info.si_uid = 0; - force_sig_info(info.si_signo, &info, current); + force_sig_info(&info); } #endif diff --git a/include/linux/pwm.h b/include/linux/pwm.h index eaa5c6e3fc9f..b2c9c460947d 100644 --- a/include/linux/pwm.h +++ b/include/linux/pwm.h @@ -262,7 +262,7 @@ struct pwm_ops { int (*capture)(struct pwm_chip *chip, struct pwm_device *pwm, struct pwm_capture *result, unsigned long timeout); int (*apply)(struct pwm_chip *chip, struct pwm_device *pwm, - struct pwm_state *state); + const struct pwm_state *state); void (*get_state)(struct pwm_chip *chip, struct pwm_device *pwm, struct pwm_state *state); struct module *owner; @@ -316,7 +316,7 @@ struct pwm_capture { /* PWM user APIs */ struct pwm_device *pwm_request(int pwm_id, const char *label); void pwm_free(struct pwm_device *pwm); -int pwm_apply_state(struct pwm_device *pwm, struct pwm_state *state); +int pwm_apply_state(struct pwm_device *pwm, const struct pwm_state *state); int pwm_adjust_config(struct pwm_device *pwm); /** @@ -405,12 +405,16 @@ struct pwm_device *of_pwm_xlate_with_flags(struct pwm_chip *pc, const struct of_phandle_args *args); struct pwm_device *pwm_get(struct device *dev, const char *con_id); -struct pwm_device *of_pwm_get(struct device_node *np, const char *con_id); +struct pwm_device *of_pwm_get(struct device *dev, struct device_node *np, + const char *con_id); void pwm_put(struct pwm_device *pwm); struct pwm_device *devm_pwm_get(struct device *dev, const char *con_id); struct pwm_device *devm_of_pwm_get(struct device *dev, struct device_node *np, const char *con_id); +struct pwm_device *devm_fwnode_pwm_get(struct device *dev, + struct fwnode_handle *fwnode, + const char *con_id); void devm_pwm_put(struct device *dev, struct pwm_device *pwm); #else static inline struct pwm_device *pwm_request(int pwm_id, const char *label) @@ -493,7 +497,8 @@ static inline struct pwm_device *pwm_get(struct device *dev, return ERR_PTR(-ENODEV); } -static inline struct pwm_device *of_pwm_get(struct device_node *np, +static inline struct pwm_device *of_pwm_get(struct device *dev, + struct device_node *np, const char *con_id) { return ERR_PTR(-ENODEV); @@ -516,6 +521,13 @@ static inline struct pwm_device *devm_of_pwm_get(struct device *dev, return ERR_PTR(-ENODEV); } +static inline struct pwm_device * +devm_fwnode_pwm_get(struct device *dev, struct fwnode_handle *fwnode, + const char *con_id) +{ + return ERR_PTR(-ENODEV); +} + static inline void devm_pwm_put(struct device *dev, struct pwm_device *pwm) { } diff --git a/include/linux/qcom_scm.h b/include/linux/qcom_scm.h index 3f12cc77fb58..2d5eff506e13 100644 --- a/include/linux/qcom_scm.h +++ b/include/linux/qcom_scm.h @@ -49,8 +49,9 @@ extern int qcom_scm_pas_mem_setup(u32 peripheral, phys_addr_t addr, extern int qcom_scm_pas_auth_and_reset(u32 peripheral); extern int qcom_scm_pas_shutdown(u32 peripheral); extern int qcom_scm_assign_mem(phys_addr_t mem_addr, size_t mem_sz, - unsigned int *src, struct qcom_scm_vmperm *newvm, - int dest_cnt); + unsigned int *src, + const struct qcom_scm_vmperm *newvm, + unsigned int dest_cnt); extern void qcom_scm_cpu_power_down(u32 flags); extern u32 qcom_scm_get_version(void); extern int qcom_scm_set_remote_state(u32 state, u32 id); @@ -87,8 +88,8 @@ qcom_scm_pas_auth_and_reset(u32 peripheral) { return -ENODEV; } static inline int qcom_scm_pas_shutdown(u32 peripheral) { return -ENODEV; } static inline int qcom_scm_assign_mem(phys_addr_t mem_addr, size_t mem_sz, unsigned int *src, - struct qcom_scm_vmperm *newvm, - int dest_cnt) { return -ENODEV; } + const struct qcom_scm_vmperm *newvm, + unsigned int dest_cnt) { return -ENODEV; } static inline void qcom_scm_cpu_power_down(u32 flags) {} static inline u32 qcom_scm_get_version(void) { return 0; } static inline u32 diff --git a/include/linux/qed/qed_if.h b/include/linux/qed/qed_if.h index 48841e5dab90..b5db1ee96d78 100644 --- a/include/linux/qed/qed_if.h +++ b/include/linux/qed/qed_if.h @@ -689,7 +689,7 @@ enum qed_link_mode_bits { QED_LM_40000baseLR4_Full_BIT = BIT(9), QED_LM_50000baseKR2_Full_BIT = BIT(10), QED_LM_100000baseKR4_Full_BIT = BIT(11), - QED_LM_2500baseX_Full_BIT = BIT(12), + QED_LM_TP_BIT = BIT(12), QED_LM_Backplane_BIT = BIT(13), QED_LM_1000baseKX_Full_BIT = BIT(14), QED_LM_10000baseKX4_Full_BIT = BIT(15), @@ -804,6 +804,7 @@ enum qed_nvm_flash_cmd { QED_NVM_FLASH_CMD_FILE_DATA = 0x2, QED_NVM_FLASH_CMD_FILE_START = 0x3, QED_NVM_FLASH_CMD_NVM_CHANGE = 0x4, + QED_NVM_FLASH_CMD_NVM_CFG_ID = 0x5, QED_NVM_FLASH_CMD_NVM_MAX, }; @@ -907,7 +908,8 @@ struct qed_common_ops { u32 (*sb_release)(struct qed_dev *cdev, struct qed_sb_info *sb_info, - u16 sb_id); + u16 sb_id, + enum qed_sb_type type); void (*simd_handler_config)(struct qed_dev *cdev, void *token, @@ -1123,6 +1125,41 @@ struct qed_common_ops { */ int (*read_module_eeprom)(struct qed_dev *cdev, char *buf, u8 dev_addr, u32 offset, u32 len); + +/** + * @brief get_affin_hwfn_idx + * + * @param cdev + */ + u8 (*get_affin_hwfn_idx)(struct qed_dev *cdev); + +/** + * @brief read_nvm_cfg - Read NVM config attribute value. + * @param cdev + * @param buf - buffer + * @param cmd - NVM CFG command id + * @param entity_id - Entity id + * + */ + int (*read_nvm_cfg)(struct qed_dev *cdev, u8 **buf, u32 cmd, + u32 entity_id); +/** + * @brief read_nvm_cfg - Read NVM config attribute value. + * @param cdev + * @param cmd - NVM CFG command id + * + * @return config id length, 0 on error. + */ + int (*read_nvm_cfg_len)(struct qed_dev *cdev, u32 cmd); + +/** + * @brief set_grc_config - Configure value for grc config id. + * @param cdev + * @param cfg_id - grc config id + * @param val - grc config value + * + */ + int (*set_grc_config)(struct qed_dev *cdev, u32 cfg_id, u32 val); }; #define MASK_FIELD(_name, _value) \ diff --git a/include/linux/qed/qed_rdma_if.h b/include/linux/qed/qed_rdma_if.h index d15f8e4815e3..74efca15fde7 100644 --- a/include/linux/qed/qed_rdma_if.h +++ b/include/linux/qed/qed_rdma_if.h @@ -225,7 +225,7 @@ struct qed_rdma_start_in_params { struct qed_rdma_add_user_out_params { u16 dpi; - u64 dpi_addr; + void __iomem *dpi_addr; u64 dpi_phys_addr; u32 dpi_size; u16 wid_count; @@ -670,6 +670,8 @@ struct qed_rdma_ops { int (*ll2_set_mac_filter)(struct qed_dev *cdev, u8 *old_mac_address, u8 *new_mac_address); + int (*iwarp_set_engine_affin)(struct qed_dev *cdev, bool b_reset); + int (*iwarp_connect)(void *rdma_cxt, struct qed_iwarp_connect_in *iparams, struct qed_iwarp_connect_out *oparams); diff --git a/include/linux/quicklist.h b/include/linux/quicklist.h deleted file mode 100644 index 034982c98c8b..000000000000 --- a/include/linux/quicklist.h +++ /dev/null @@ -1,94 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef LINUX_QUICKLIST_H -#define LINUX_QUICKLIST_H -/* - * Fast allocations and disposal of pages. Pages must be in the condition - * as needed after allocation when they are freed. Per cpu lists of pages - * are kept that only contain node local pages. - * - * (C) 2007, SGI. Christoph Lameter <cl@linux.com> - */ -#include <linux/kernel.h> -#include <linux/gfp.h> -#include <linux/percpu.h> - -#ifdef CONFIG_QUICKLIST - -struct quicklist { - void *page; - int nr_pages; -}; - -DECLARE_PER_CPU(struct quicklist, quicklist)[CONFIG_NR_QUICK]; - -/* - * The two key functions quicklist_alloc and quicklist_free are inline so - * that they may be custom compiled for the platform. - * Specifying a NULL ctor can remove constructor support. Specifying - * a constant quicklist allows the determination of the exact address - * in the per cpu area. - * - * The fast patch in quicklist_alloc touched only a per cpu cacheline and - * the first cacheline of the page itself. There is minmal overhead involved. - */ -static inline void *quicklist_alloc(int nr, gfp_t flags, void (*ctor)(void *)) -{ - struct quicklist *q; - void **p = NULL; - - q =&get_cpu_var(quicklist)[nr]; - p = q->page; - if (likely(p)) { - q->page = p[0]; - p[0] = NULL; - q->nr_pages--; - } - put_cpu_var(quicklist); - if (likely(p)) - return p; - - p = (void *)__get_free_page(flags | __GFP_ZERO); - if (ctor && p) - ctor(p); - return p; -} - -static inline void __quicklist_free(int nr, void (*dtor)(void *), void *p, - struct page *page) -{ - struct quicklist *q; - - q = &get_cpu_var(quicklist)[nr]; - *(void **)p = q->page; - q->page = p; - q->nr_pages++; - put_cpu_var(quicklist); -} - -static inline void quicklist_free(int nr, void (*dtor)(void *), void *pp) -{ - __quicklist_free(nr, dtor, pp, virt_to_page(pp)); -} - -static inline void quicklist_free_page(int nr, void (*dtor)(void *), - struct page *page) -{ - __quicklist_free(nr, dtor, page_address(page), page); -} - -void quicklist_trim(int nr, void (*dtor)(void *), - unsigned long min_pages, unsigned long max_free); - -unsigned long quicklist_total_size(void); - -#else - -static inline unsigned long quicklist_total_size(void) -{ - return 0; -} - -#endif - -#endif /* LINUX_QUICKLIST_H */ - diff --git a/include/linux/quotaops.h b/include/linux/quotaops.h index dc905a4ff8d7..185d94829701 100644 --- a/include/linux/quotaops.h +++ b/include/linux/quotaops.h @@ -22,7 +22,7 @@ static inline struct quota_info *sb_dqopt(struct super_block *sb) /* i_mutex must being held */ static inline bool is_quota_modification(struct inode *inode, struct iattr *ia) { - return (ia->ia_valid & ATTR_SIZE && ia->ia_size != inode->i_size) || + return (ia->ia_valid & ATTR_SIZE) || (ia->ia_valid & ATTR_UID && !uid_eq(ia->ia_uid, inode->i_uid)) || (ia->ia_valid & ATTR_GID && !gid_eq(ia->ia_gid, inode->i_gid)); } diff --git a/include/linux/ramfs.h b/include/linux/ramfs.h index 5ef7d54caac2..b806a0ff6554 100644 --- a/include/linux/ramfs.h +++ b/include/linux/ramfs.h @@ -4,8 +4,7 @@ struct inode *ramfs_get_inode(struct super_block *sb, const struct inode *dir, umode_t mode, dev_t dev); -extern struct dentry *ramfs_mount(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data); +extern int ramfs_init_fs_context(struct fs_context *fc); #ifdef CONFIG_MMU static inline int @@ -17,10 +16,8 @@ ramfs_nommu_expand_for_mapping(struct inode *inode, size_t newsize) extern int ramfs_nommu_expand_for_mapping(struct inode *inode, size_t newsize); #endif +extern const struct fs_parameter_description ramfs_fs_parameters; extern const struct file_operations ramfs_file_operations; extern const struct vm_operations_struct generic_file_vm_ops; -extern int __init init_ramfs_fs(void); - -int ramfs_fill_super(struct super_block *sb, void *data, int silent); #endif diff --git a/include/linux/random.h b/include/linux/random.h index 1f7dced2bba6..f189c927fdea 100644 --- a/include/linux/random.h +++ b/include/linux/random.h @@ -19,6 +19,7 @@ struct random_ready_callback { }; extern void add_device_randomness(const void *, unsigned int); +extern void add_bootloader_randomness(const void *, unsigned int); #if defined(LATENT_ENTROPY_PLUGIN) && !defined(__CHECKER__) static inline void add_latent_entropy(void) diff --git a/include/linux/rbtree.h b/include/linux/rbtree.h index e6337fce08f2..1fd61a9af45c 100644 --- a/include/linux/rbtree.h +++ b/include/linux/rbtree.h @@ -32,25 +32,9 @@ struct rb_root { struct rb_node *rb_node; }; -/* - * Leftmost-cached rbtrees. - * - * We do not cache the rightmost node based on footprint - * size vs number of potential users that could benefit - * from O(1) rb_last(). Just not worth it, users that want - * this feature can always implement the logic explicitly. - * Furthermore, users that want to cache both pointers may - * find it a bit asymmetric, but that's ok. - */ -struct rb_root_cached { - struct rb_root rb_root; - struct rb_node *rb_leftmost; -}; - #define rb_parent(r) ((struct rb_node *)((r)->__rb_parent_color & ~3)) #define RB_ROOT (struct rb_root) { NULL, } -#define RB_ROOT_CACHED (struct rb_root_cached) { {NULL, }, NULL } #define rb_entry(ptr, type, member) container_of(ptr, type, member) #define RB_EMPTY_ROOT(root) (READ_ONCE((root)->rb_node) == NULL) @@ -72,12 +56,6 @@ extern struct rb_node *rb_prev(const struct rb_node *); extern struct rb_node *rb_first(const struct rb_root *); extern struct rb_node *rb_last(const struct rb_root *); -extern void rb_insert_color_cached(struct rb_node *, - struct rb_root_cached *, bool); -extern void rb_erase_cached(struct rb_node *node, struct rb_root_cached *); -/* Same as rb_first(), but O(1) */ -#define rb_first_cached(root) (root)->rb_leftmost - /* Postorder iteration - always visit the parent after its children */ extern struct rb_node *rb_first_postorder(const struct rb_root *); extern struct rb_node *rb_next_postorder(const struct rb_node *); @@ -87,8 +65,6 @@ extern void rb_replace_node(struct rb_node *victim, struct rb_node *new, struct rb_root *root); extern void rb_replace_node_rcu(struct rb_node *victim, struct rb_node *new, struct rb_root *root); -extern void rb_replace_node_cached(struct rb_node *victim, struct rb_node *new, - struct rb_root_cached *root); static inline void rb_link_node(struct rb_node *node, struct rb_node *parent, struct rb_node **rb_link) @@ -136,4 +112,50 @@ static inline void rb_link_node_rcu(struct rb_node *node, struct rb_node *parent typeof(*pos), field); 1; }); \ pos = n) +/* + * Leftmost-cached rbtrees. + * + * We do not cache the rightmost node based on footprint + * size vs number of potential users that could benefit + * from O(1) rb_last(). Just not worth it, users that want + * this feature can always implement the logic explicitly. + * Furthermore, users that want to cache both pointers may + * find it a bit asymmetric, but that's ok. + */ +struct rb_root_cached { + struct rb_root rb_root; + struct rb_node *rb_leftmost; +}; + +#define RB_ROOT_CACHED (struct rb_root_cached) { {NULL, }, NULL } + +/* Same as rb_first(), but O(1) */ +#define rb_first_cached(root) (root)->rb_leftmost + +static inline void rb_insert_color_cached(struct rb_node *node, + struct rb_root_cached *root, + bool leftmost) +{ + if (leftmost) + root->rb_leftmost = node; + rb_insert_color(node, &root->rb_root); +} + +static inline void rb_erase_cached(struct rb_node *node, + struct rb_root_cached *root) +{ + if (root->rb_leftmost == node) + root->rb_leftmost = rb_next(node); + rb_erase(node, &root->rb_root); +} + +static inline void rb_replace_node_cached(struct rb_node *victim, + struct rb_node *new, + struct rb_root_cached *root) +{ + if (root->rb_leftmost == victim) + root->rb_leftmost = new; + rb_replace_node(victim, new, &root->rb_root); +} + #endif /* _LINUX_RBTREE_H */ diff --git a/include/linux/rbtree_augmented.h b/include/linux/rbtree_augmented.h index 0f902ccb48b0..fdd421b8d9ae 100644 --- a/include/linux/rbtree_augmented.h +++ b/include/linux/rbtree_augmented.h @@ -30,10 +30,9 @@ struct rb_augment_callbacks { void (*rotate)(struct rb_node *old, struct rb_node *new); }; -extern void __rb_insert_augmented(struct rb_node *node, - struct rb_root *root, - bool newleft, struct rb_node **leftmost, +extern void __rb_insert_augmented(struct rb_node *node, struct rb_root *root, void (*augment_rotate)(struct rb_node *old, struct rb_node *new)); + /* * Fixup the rbtree and update the augmented information when rebalancing. * @@ -48,7 +47,7 @@ static inline void rb_insert_augmented(struct rb_node *node, struct rb_root *root, const struct rb_augment_callbacks *augment) { - __rb_insert_augmented(node, root, false, NULL, augment->rotate); + __rb_insert_augmented(node, root, augment->rotate); } static inline void @@ -56,45 +55,92 @@ rb_insert_augmented_cached(struct rb_node *node, struct rb_root_cached *root, bool newleft, const struct rb_augment_callbacks *augment) { - __rb_insert_augmented(node, &root->rb_root, - newleft, &root->rb_leftmost, augment->rotate); + if (newleft) + root->rb_leftmost = node; + rb_insert_augmented(node, &root->rb_root, augment); } -#define RB_DECLARE_CALLBACKS(rbstatic, rbname, rbstruct, rbfield, \ - rbtype, rbaugmented, rbcompute) \ +/* + * Template for declaring augmented rbtree callbacks (generic case) + * + * RBSTATIC: 'static' or empty + * RBNAME: name of the rb_augment_callbacks structure + * RBSTRUCT: struct type of the tree nodes + * RBFIELD: name of struct rb_node field within RBSTRUCT + * RBAUGMENTED: name of field within RBSTRUCT holding data for subtree + * RBCOMPUTE: name of function that recomputes the RBAUGMENTED data + */ + +#define RB_DECLARE_CALLBACKS(RBSTATIC, RBNAME, \ + RBSTRUCT, RBFIELD, RBAUGMENTED, RBCOMPUTE) \ static inline void \ -rbname ## _propagate(struct rb_node *rb, struct rb_node *stop) \ +RBNAME ## _propagate(struct rb_node *rb, struct rb_node *stop) \ { \ while (rb != stop) { \ - rbstruct *node = rb_entry(rb, rbstruct, rbfield); \ - rbtype augmented = rbcompute(node); \ - if (node->rbaugmented == augmented) \ + RBSTRUCT *node = rb_entry(rb, RBSTRUCT, RBFIELD); \ + if (RBCOMPUTE(node, true)) \ break; \ - node->rbaugmented = augmented; \ - rb = rb_parent(&node->rbfield); \ + rb = rb_parent(&node->RBFIELD); \ } \ } \ static inline void \ -rbname ## _copy(struct rb_node *rb_old, struct rb_node *rb_new) \ +RBNAME ## _copy(struct rb_node *rb_old, struct rb_node *rb_new) \ { \ - rbstruct *old = rb_entry(rb_old, rbstruct, rbfield); \ - rbstruct *new = rb_entry(rb_new, rbstruct, rbfield); \ - new->rbaugmented = old->rbaugmented; \ + RBSTRUCT *old = rb_entry(rb_old, RBSTRUCT, RBFIELD); \ + RBSTRUCT *new = rb_entry(rb_new, RBSTRUCT, RBFIELD); \ + new->RBAUGMENTED = old->RBAUGMENTED; \ } \ static void \ -rbname ## _rotate(struct rb_node *rb_old, struct rb_node *rb_new) \ +RBNAME ## _rotate(struct rb_node *rb_old, struct rb_node *rb_new) \ { \ - rbstruct *old = rb_entry(rb_old, rbstruct, rbfield); \ - rbstruct *new = rb_entry(rb_new, rbstruct, rbfield); \ - new->rbaugmented = old->rbaugmented; \ - old->rbaugmented = rbcompute(old); \ + RBSTRUCT *old = rb_entry(rb_old, RBSTRUCT, RBFIELD); \ + RBSTRUCT *new = rb_entry(rb_new, RBSTRUCT, RBFIELD); \ + new->RBAUGMENTED = old->RBAUGMENTED; \ + RBCOMPUTE(old, false); \ } \ -rbstatic const struct rb_augment_callbacks rbname = { \ - .propagate = rbname ## _propagate, \ - .copy = rbname ## _copy, \ - .rotate = rbname ## _rotate \ +RBSTATIC const struct rb_augment_callbacks RBNAME = { \ + .propagate = RBNAME ## _propagate, \ + .copy = RBNAME ## _copy, \ + .rotate = RBNAME ## _rotate \ }; +/* + * Template for declaring augmented rbtree callbacks, + * computing RBAUGMENTED scalar as max(RBCOMPUTE(node)) for all subtree nodes. + * + * RBSTATIC: 'static' or empty + * RBNAME: name of the rb_augment_callbacks structure + * RBSTRUCT: struct type of the tree nodes + * RBFIELD: name of struct rb_node field within RBSTRUCT + * RBTYPE: type of the RBAUGMENTED field + * RBAUGMENTED: name of RBTYPE field within RBSTRUCT holding data for subtree + * RBCOMPUTE: name of function that returns the per-node RBTYPE scalar + */ + +#define RB_DECLARE_CALLBACKS_MAX(RBSTATIC, RBNAME, RBSTRUCT, RBFIELD, \ + RBTYPE, RBAUGMENTED, RBCOMPUTE) \ +static inline bool RBNAME ## _compute_max(RBSTRUCT *node, bool exit) \ +{ \ + RBSTRUCT *child; \ + RBTYPE max = RBCOMPUTE(node); \ + if (node->RBFIELD.rb_left) { \ + child = rb_entry(node->RBFIELD.rb_left, RBSTRUCT, RBFIELD); \ + if (child->RBAUGMENTED > max) \ + max = child->RBAUGMENTED; \ + } \ + if (node->RBFIELD.rb_right) { \ + child = rb_entry(node->RBFIELD.rb_right, RBSTRUCT, RBFIELD); \ + if (child->RBAUGMENTED > max) \ + max = child->RBAUGMENTED; \ + } \ + if (exit && node->RBAUGMENTED == max) \ + return true; \ + node->RBAUGMENTED = max; \ + return false; \ +} \ +RB_DECLARE_CALLBACKS(RBSTATIC, RBNAME, \ + RBSTRUCT, RBFIELD, RBAUGMENTED, RBNAME ## _compute_max) + #define RB_RED 0 #define RB_BLACK 1 @@ -150,7 +196,6 @@ extern void __rb_erase_color(struct rb_node *parent, struct rb_root *root, static __always_inline struct rb_node * __rb_erase_augmented(struct rb_node *node, struct rb_root *root, - struct rb_node **leftmost, const struct rb_augment_callbacks *augment) { struct rb_node *child = node->rb_right; @@ -158,9 +203,6 @@ __rb_erase_augmented(struct rb_node *node, struct rb_root *root, struct rb_node *parent, *rebalance; unsigned long pc; - if (leftmost && node == *leftmost) - *leftmost = rb_next(node); - if (!tmp) { /* * Case 1: node to erase has no more than 1 child (easy!) @@ -260,8 +302,7 @@ static __always_inline void rb_erase_augmented(struct rb_node *node, struct rb_root *root, const struct rb_augment_callbacks *augment) { - struct rb_node *rebalance = __rb_erase_augmented(node, root, - NULL, augment); + struct rb_node *rebalance = __rb_erase_augmented(node, root, augment); if (rebalance) __rb_erase_color(rebalance, root, augment->rotate); } @@ -270,11 +311,9 @@ static __always_inline void rb_erase_augmented_cached(struct rb_node *node, struct rb_root_cached *root, const struct rb_augment_callbacks *augment) { - struct rb_node *rebalance = __rb_erase_augmented(node, &root->rb_root, - &root->rb_leftmost, - augment); - if (rebalance) - __rb_erase_color(rebalance, &root->rb_root, augment->rotate); + if (root->rb_leftmost == node) + root->rb_leftmost = rb_next(node); + rb_erase_augmented(node, &root->rb_root, augment); } #endif /* _LINUX_RBTREE_AUGMENTED_H */ diff --git a/include/linux/rcu_segcblist.h b/include/linux/rcu_segcblist.h index 87404cb015f1..646759042333 100644 --- a/include/linux/rcu_segcblist.h +++ b/include/linux/rcu_segcblist.h @@ -14,6 +14,9 @@ #ifndef __INCLUDE_LINUX_RCU_SEGCBLIST_H #define __INCLUDE_LINUX_RCU_SEGCBLIST_H +#include <linux/types.h> +#include <linux/atomic.h> + /* Simple unsegmented callback lists. */ struct rcu_cblist { struct rcu_head *head; @@ -65,8 +68,14 @@ struct rcu_segcblist { struct rcu_head *head; struct rcu_head **tails[RCU_CBLIST_NSEGS]; unsigned long gp_seq[RCU_CBLIST_NSEGS]; +#ifdef CONFIG_RCU_NOCB_CPU + atomic_long_t len; +#else long len; +#endif long len_lazy; + u8 enabled; + u8 offloaded; }; #define RCU_SEGCBLIST_INITIALIZER(n) \ diff --git a/include/linux/rcu_sync.h b/include/linux/rcu_sync.h index 6fc53a1345b3..0027d4c8087c 100644 --- a/include/linux/rcu_sync.h +++ b/include/linux/rcu_sync.h @@ -13,62 +13,42 @@ #include <linux/wait.h> #include <linux/rcupdate.h> -enum rcu_sync_type { RCU_SYNC, RCU_SCHED_SYNC, RCU_BH_SYNC }; - /* Structure to mediate between updaters and fastpath-using readers. */ struct rcu_sync { int gp_state; int gp_count; wait_queue_head_t gp_wait; - int cb_state; struct rcu_head cb_head; - - enum rcu_sync_type gp_type; }; -extern void rcu_sync_lockdep_assert(struct rcu_sync *); - /** * rcu_sync_is_idle() - Are readers permitted to use their fastpaths? * @rsp: Pointer to rcu_sync structure to use for synchronization * - * Returns true if readers are permitted to use their fastpaths. - * Must be invoked within an RCU read-side critical section whose - * flavor matches that of the rcu_sync struture. + * Returns true if readers are permitted to use their fastpaths. Must be + * invoked within some flavor of RCU read-side critical section. */ static inline bool rcu_sync_is_idle(struct rcu_sync *rsp) { -#ifdef CONFIG_PROVE_RCU - rcu_sync_lockdep_assert(rsp); -#endif - return !rsp->gp_state; /* GP_IDLE */ + RCU_LOCKDEP_WARN(!rcu_read_lock_any_held(), + "suspicious rcu_sync_is_idle() usage"); + return !READ_ONCE(rsp->gp_state); /* GP_IDLE */ } -extern void rcu_sync_init(struct rcu_sync *, enum rcu_sync_type); +extern void rcu_sync_init(struct rcu_sync *); extern void rcu_sync_enter_start(struct rcu_sync *); extern void rcu_sync_enter(struct rcu_sync *); extern void rcu_sync_exit(struct rcu_sync *); extern void rcu_sync_dtor(struct rcu_sync *); -#define __RCU_SYNC_INITIALIZER(name, type) { \ +#define __RCU_SYNC_INITIALIZER(name) { \ .gp_state = 0, \ .gp_count = 0, \ .gp_wait = __WAIT_QUEUE_HEAD_INITIALIZER(name.gp_wait), \ - .cb_state = 0, \ - .gp_type = type, \ } -#define __DEFINE_RCU_SYNC(name, type) \ - struct rcu_sync_struct name = __RCU_SYNC_INITIALIZER(name, type) - -#define DEFINE_RCU_SYNC(name) \ - __DEFINE_RCU_SYNC(name, RCU_SYNC) - -#define DEFINE_RCU_SCHED_SYNC(name) \ - __DEFINE_RCU_SYNC(name, RCU_SCHED_SYNC) - -#define DEFINE_RCU_BH_SYNC(name) \ - __DEFINE_RCU_SYNC(name, RCU_BH_SYNC) +#define DEFINE_RCU_SYNC(name) \ + struct rcu_sync name = __RCU_SYNC_INITIALIZER(name) #endif /* _LINUX_RCU_SYNC_H_ */ diff --git a/include/linux/rculist.h b/include/linux/rculist.h index e91ec9ddcd30..4158b7212936 100644 --- a/include/linux/rculist.h +++ b/include/linux/rculist.h @@ -41,6 +41,24 @@ static inline void INIT_LIST_HEAD_RCU(struct list_head *list) #define list_next_rcu(list) (*((struct list_head __rcu **)(&(list)->next))) /* + * Check during list traversal that we are within an RCU reader + */ + +#define check_arg_count_one(dummy) + +#ifdef CONFIG_PROVE_RCU_LIST +#define __list_check_rcu(dummy, cond, extra...) \ + ({ \ + check_arg_count_one(extra); \ + RCU_LOCKDEP_WARN(!cond && !rcu_read_lock_any_held(), \ + "RCU-list traversed in non-reader section!"); \ + }) +#else +#define __list_check_rcu(dummy, cond, extra...) \ + ({ check_arg_count_one(extra); }) +#endif + +/* * Insert a new entry between two known consecutive entries. * * This is only for internal list manipulation where we know @@ -343,14 +361,16 @@ static inline void list_splice_tail_init_rcu(struct list_head *list, * @pos: the type * to use as a loop cursor. * @head: the head for your list. * @member: the name of the list_head within the struct. + * @cond: optional lockdep expression if called from non-RCU protection. * * This list-traversal primitive may safely run concurrently with * the _rcu list-mutation primitives such as list_add_rcu() * as long as the traversal is guarded by rcu_read_lock(). */ -#define list_for_each_entry_rcu(pos, head, member) \ - for (pos = list_entry_rcu((head)->next, typeof(*pos), member); \ - &pos->member != (head); \ +#define list_for_each_entry_rcu(pos, head, member, cond...) \ + for (__list_check_rcu(dummy, ## cond, 0), \ + pos = list_entry_rcu((head)->next, typeof(*pos), member); \ + &pos->member != (head); \ pos = list_entry_rcu(pos->member.next, typeof(*pos), member)) /** @@ -616,13 +636,15 @@ static inline void hlist_add_behind_rcu(struct hlist_node *n, * @pos: the type * to use as a loop cursor. * @head: the head for your list. * @member: the name of the hlist_node within the struct. + * @cond: optional lockdep expression if called from non-RCU protection. * * This list-traversal primitive may safely run concurrently with * the _rcu list-mutation primitives such as hlist_add_head_rcu() * as long as the traversal is guarded by rcu_read_lock(). */ -#define hlist_for_each_entry_rcu(pos, head, member) \ - for (pos = hlist_entry_safe (rcu_dereference_raw(hlist_first_rcu(head)),\ +#define hlist_for_each_entry_rcu(pos, head, member, cond...) \ + for (__list_check_rcu(dummy, ## cond, 0), \ + pos = hlist_entry_safe(rcu_dereference_raw(hlist_first_rcu(head)),\ typeof(*(pos)), member); \ pos; \ pos = hlist_entry_safe(rcu_dereference_raw(hlist_next_rcu(\ @@ -642,10 +664,10 @@ static inline void hlist_add_behind_rcu(struct hlist_node *n, * not do any RCU debugging or tracing. */ #define hlist_for_each_entry_rcu_notrace(pos, head, member) \ - for (pos = hlist_entry_safe (rcu_dereference_raw_notrace(hlist_first_rcu(head)),\ + for (pos = hlist_entry_safe(rcu_dereference_raw_check(hlist_first_rcu(head)),\ typeof(*(pos)), member); \ pos; \ - pos = hlist_entry_safe(rcu_dereference_raw_notrace(hlist_next_rcu(\ + pos = hlist_entry_safe(rcu_dereference_raw_check(hlist_next_rcu(\ &(pos)->member)), typeof(*(pos)), member)) /** diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h index b25d20822e75..75a2eded7aa2 100644 --- a/include/linux/rcupdate.h +++ b/include/linux/rcupdate.h @@ -221,6 +221,7 @@ int debug_lockdep_rcu_enabled(void); int rcu_read_lock_held(void); int rcu_read_lock_bh_held(void); int rcu_read_lock_sched_held(void); +int rcu_read_lock_any_held(void); #else /* #ifdef CONFIG_DEBUG_LOCK_ALLOC */ @@ -241,6 +242,12 @@ static inline int rcu_read_lock_sched_held(void) { return !preemptible(); } + +static inline int rcu_read_lock_any_held(void) +{ + return !preemptible(); +} + #endif /* #else #ifdef CONFIG_DEBUG_LOCK_ALLOC */ #ifdef CONFIG_PROVE_RCU @@ -365,16 +372,15 @@ static inline void rcu_preempt_sleep_check(void) { } * other macros that it invokes. */ #define rcu_assign_pointer(p, v) \ -({ \ +do { \ uintptr_t _r_a_p__v = (uintptr_t)(v); \ - rcu_check_sparse(p, __rcu); \ + rcu_check_sparse(p, __rcu); \ \ if (__builtin_constant_p(v) && (_r_a_p__v) == (uintptr_t)NULL) \ WRITE_ONCE((p), (typeof(p))(_r_a_p__v)); \ else \ smp_store_release(&p, RCU_INITIALIZER((typeof(p))_r_a_p__v)); \ - _r_a_p__v; \ -}) +} while (0) /** * rcu_swap_protected() - swap an RCU and a regular pointer @@ -477,7 +483,7 @@ static inline void rcu_preempt_sleep_check(void) { } * The no-tracing version of rcu_dereference_raw() must not call * rcu_read_lock_held(). */ -#define rcu_dereference_raw_notrace(p) __rcu_dereference_check((p), 1, __rcu) +#define rcu_dereference_raw_check(p) __rcu_dereference_check((p), 1, __rcu) /** * rcu_dereference_protected() - fetch RCU pointer when updates prevented @@ -579,14 +585,14 @@ static inline void rcu_preempt_sleep_check(void) { } * * In non-preemptible RCU implementations (TREE_RCU and TINY_RCU), * it is illegal to block while in an RCU read-side critical section. - * In preemptible RCU implementations (PREEMPT_RCU) in CONFIG_PREEMPT + * In preemptible RCU implementations (PREEMPT_RCU) in CONFIG_PREEMPTION * kernel builds, RCU read-side critical sections may be preempted, * but explicit blocking is illegal. Finally, in preemptible RCU * implementations in real-time (with -rt patchset) kernel builds, RCU * read-side critical sections may be preempted and they may also block, but * only when acquiring spinlocks that are subject to priority inheritance. */ -static inline void rcu_read_lock(void) +static __always_inline void rcu_read_lock(void) { __rcu_read_lock(); __acquire(RCU); @@ -803,7 +809,7 @@ static inline notrace void rcu_read_unlock_sched_notrace(void) /** * kfree_rcu() - kfree an object after a grace period. * @ptr: pointer to kfree - * @rcu_head: the name of the struct rcu_head within the type of @ptr. + * @rhf: the name of the struct rcu_head within the type of @ptr. * * Many rcu callbacks functions just call kfree() on the base structure. * These functions are trivial, but their size adds up, and furthermore @@ -826,9 +832,13 @@ static inline notrace void rcu_read_unlock_sched_notrace(void) * The BUILD_BUG_ON check must not involve any function calls, hence the * checks are done in macros here. */ -#define kfree_rcu(ptr, rcu_head) \ - __kfree_rcu(&((ptr)->rcu_head), offsetof(typeof(*(ptr)), rcu_head)) - +#define kfree_rcu(ptr, rhf) \ +do { \ + typeof (ptr) ___p = (ptr); \ + \ + if (___p) \ + __kfree_rcu(&((___p)->rhf), offsetof(typeof(*(ptr)), rhf)); \ +} while (0) /* * Place this after a lock-acquisition primitive to guarantee that diff --git a/include/linux/rcutiny.h b/include/linux/rcutiny.h index 8e727f57d814..9bf1dfe7781f 100644 --- a/include/linux/rcutiny.h +++ b/include/linux/rcutiny.h @@ -12,7 +12,7 @@ #ifndef __LINUX_TINY_H #define __LINUX_TINY_H -#include <linux/ktime.h> +#include <asm/param.h> /* for HZ */ /* Never flag non-existent other CPUs! */ static inline bool rcu_eqs_special_set(int cpu) { return false; } diff --git a/include/linux/rcutree.h b/include/linux/rcutree.h index 735601ac27d3..18b1ed9864b0 100644 --- a/include/linux/rcutree.h +++ b/include/linux/rcutree.h @@ -53,7 +53,7 @@ void rcu_scheduler_starting(void); extern int rcu_scheduler_active __read_mostly; void rcu_end_inkernel_boot(void); bool rcu_is_watching(void); -#ifndef CONFIG_PREEMPT +#ifndef CONFIG_PREEMPTION void rcu_all_qs(void); #endif diff --git a/include/linux/regmap.h b/include/linux/regmap.h index d3dea823af8e..dfe493ac692d 100644 --- a/include/linux/regmap.h +++ b/include/linux/regmap.h @@ -22,6 +22,7 @@ struct module; struct clk; struct device; struct i2c_client; +struct i3c_device; struct irq_domain; struct slim_device; struct spi_device; @@ -109,7 +110,7 @@ struct reg_sequence { * @cond: Break condition (usually involving @val) * @sleep_us: Maximum time to sleep between reads in us (0 * tight-loops). Should be less than ~20ms since usleep_range - * is used (see Documentation/timers/timers-howto.txt). + * is used (see Documentation/timers/timers-howto.rst). * @timeout_us: Timeout in us, 0 means never timeout * * Returns 0 on success and -ETIMEDOUT upon a timeout or the regmap_read @@ -151,7 +152,7 @@ struct reg_sequence { * @cond: Break condition (usually involving @val) * @sleep_us: Maximum time to sleep between reads in us (0 * tight-loops). Should be less than ~20ms since usleep_range - * is used (see Documentation/timers/timers-howto.txt). + * is used (see Documentation/timers/timers-howto.rst). * @timeout_us: Timeout in us, 0 means never timeout * * Returns 0 on success and -ETIMEDOUT upon a timeout or the regmap_field_read @@ -621,6 +622,10 @@ struct regmap *__devm_regmap_init_slimbus(struct slim_device *slimbus, const struct regmap_config *config, struct lock_class_key *lock_key, const char *lock_name); +struct regmap *__devm_regmap_init_i3c(struct i3c_device *i3c, + const struct regmap_config *config, + struct lock_class_key *lock_key, + const char *lock_name); /* * Wrapper for regmap_init macros to include a unique lockdep key and name * for each call. No-op if CONFIG_LOCKDEP is not set. @@ -979,6 +984,21 @@ bool regmap_ac97_default_volatile(struct device *dev, unsigned int reg); #define devm_regmap_init_slimbus(slimbus, config) \ __regmap_lockdep_wrapper(__devm_regmap_init_slimbus, #config, \ slimbus, config) + +/** + * devm_regmap_init_i3c() - Initialise managed register map + * + * @i3c: Device that will be interacted with + * @config: Configuration for register map + * + * The return value will be an ERR_PTR() on error or a valid pointer + * to a struct regmap. The regmap will be automatically freed by the + * device management code. + */ +#define devm_regmap_init_i3c(i3c, config) \ + __regmap_lockdep_wrapper(__devm_regmap_init_i3c, #config, \ + i3c, config) + int regmap_mmio_attach_clk(struct regmap *map, struct clk *clk); void regmap_mmio_detach_clk(struct regmap *map); void regmap_exit(struct regmap *map); diff --git a/include/linux/regulator/consumer.h b/include/linux/regulator/consumer.h index 815983419375..337a46391527 100644 --- a/include/linux/regulator/consumer.h +++ b/include/linux/regulator/consumer.h @@ -281,6 +281,12 @@ void devm_regulator_unregister_notifier(struct regulator *regulator, void *regulator_get_drvdata(struct regulator *regulator); void regulator_set_drvdata(struct regulator *regulator, void *data); +/* misc helpers */ + +void regulator_bulk_set_supply_names(struct regulator_bulk_data *consumers, + const char *const *supply_names, + unsigned int num_supplies); + #else /* @@ -580,6 +586,13 @@ static inline int regulator_list_voltage(struct regulator *regulator, unsigned s return -EINVAL; } +static inline void +regulator_bulk_set_supply_names(struct regulator_bulk_data *consumers, + const char *const *supply_names, + unsigned int num_supplies) +{ +} + #endif static inline int regulator_set_voltage_triplet(struct regulator *regulator, diff --git a/include/linux/regulator/coupler.h b/include/linux/regulator/coupler.h new file mode 100644 index 000000000000..0212d6255e4e --- /dev/null +++ b/include/linux/regulator/coupler.h @@ -0,0 +1,97 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * coupler.h -- SoC Regulator support, coupler API. + * + * Regulator Coupler Interface. + */ + +#ifndef __LINUX_REGULATOR_COUPLER_H_ +#define __LINUX_REGULATOR_COUPLER_H_ + +#include <linux/kernel.h> +#include <linux/suspend.h> + +struct regulator_coupler; +struct regulator_dev; + +/** + * struct regulator_coupler - customized regulator's coupler + * + * Regulator's coupler allows to customize coupling algorithm. + * + * @list: couplers list entry + * @attach_regulator: Callback invoked on creation of a coupled regulator, + * couples are unresolved at this point. The callee should + * check that it could handle the regulator and return 0 on + * success, -errno on failure and 1 if given regulator is + * not suitable for this coupler (case of having multiple + * regulators in a system). Callback shall be implemented. + * @detach_regulator: Callback invoked on destruction of a coupled regulator. + * This callback is optional and could be NULL. + * @balance_voltage: Callback invoked when voltage of a coupled regulator is + * changing. Called with all of the coupled rdev's being held + * under "consumer lock". The callee should perform voltage + * balancing, changing voltage of the coupled regulators as + * needed. It's up to the coupler to verify the voltage + * before changing it in hardware, i.e. coupler should + * check consumer's min/max and etc. This callback is + * optional and could be NULL, in which case a generic + * voltage balancer will be used. + */ +struct regulator_coupler { + struct list_head list; + + int (*attach_regulator)(struct regulator_coupler *coupler, + struct regulator_dev *rdev); + int (*detach_regulator)(struct regulator_coupler *coupler, + struct regulator_dev *rdev); + int (*balance_voltage)(struct regulator_coupler *coupler, + struct regulator_dev *rdev, + suspend_state_t state); +}; + +#ifdef CONFIG_REGULATOR +int regulator_coupler_register(struct regulator_coupler *coupler); +const char *rdev_get_name(struct regulator_dev *rdev); +int regulator_check_consumers(struct regulator_dev *rdev, + int *min_uV, int *max_uV, + suspend_state_t state); +int regulator_check_voltage(struct regulator_dev *rdev, + int *min_uV, int *max_uV); +int regulator_get_voltage_rdev(struct regulator_dev *rdev); +int regulator_set_voltage_rdev(struct regulator_dev *rdev, + int min_uV, int max_uV, + suspend_state_t state); +#else +static inline int regulator_coupler_register(struct regulator_coupler *coupler) +{ + return 0; +} +static inline const char *rdev_get_name(struct regulator_dev *rdev) +{ + return NULL; +} +static inline int regulator_check_consumers(struct regulator_dev *rdev, + int *min_uV, int *max_uV, + suspend_state_t state) +{ + return -EINVAL; +} +static inline int regulator_check_voltage(struct regulator_dev *rdev, + int *min_uV, int *max_uV) +{ + return -EINVAL; +} +static inline int regulator_get_voltage_rdev(struct regulator_dev *rdev) +{ + return -EINVAL; +} +static inline int regulator_set_voltage_rdev(struct regulator_dev *rdev, + int min_uV, int max_uV, + suspend_state_t state) +{ + return -EINVAL; +} +#endif + +#endif diff --git a/include/linux/regulator/driver.h b/include/linux/regulator/driver.h index d45ab52c91c9..9a911bb5fb61 100644 --- a/include/linux/regulator/driver.h +++ b/include/linux/regulator/driver.h @@ -12,8 +12,6 @@ #ifndef __LINUX_REGULATOR_DRIVER_H_ #define __LINUX_REGULATOR_DRIVER_H_ -#define MAX_COUPLED 2 - #include <linux/device.h> #include <linux/notifier.h> #include <linux/regulator/consumer.h> @@ -283,6 +281,11 @@ enum regulator_type { * @vsel_range_mask: Mask for register bitfield used for range selector * @vsel_reg: Register for selector when using regulator_regmap_X_voltage_ * @vsel_mask: Mask for register bitfield used for selector + * @vsel_step: Specify the resolution of selector stepping when setting + * voltage. If 0, then no stepping is done (requested selector is + * set directly), if >0 then the regulator API will ramp the + * voltage up/down gradually each time increasing/decreasing the + * selector by the specified step value. * @csel_reg: Register for current limit selector using regmap set_current_limit * @csel_mask: Mask for register bitfield used for current limit selector * @apply_reg: Register for initiate voltage change on the output when @@ -357,6 +360,7 @@ struct regulator_desc { unsigned int vsel_range_mask; unsigned int vsel_reg; unsigned int vsel_mask; + unsigned int vsel_step; unsigned int csel_reg; unsigned int csel_mask; unsigned int apply_reg; @@ -423,7 +427,8 @@ struct regulator_config { * incremented. */ struct coupling_desc { - struct regulator_dev *coupled_rdevs[MAX_COUPLED]; + struct regulator_dev **coupled_rdevs; + struct regulator_coupler *coupler; int n_resolved; int n_coupled; }; @@ -549,4 +554,5 @@ void regulator_unlock(struct regulator_dev *rdev); */ int regulator_desc_list_voltage_linear_range(const struct regulator_desc *desc, unsigned int selector); + #endif diff --git a/include/linux/regulator/machine.h b/include/linux/regulator/machine.h index 5539efa76d26..a84cc8879c3e 100644 --- a/include/linux/regulator/machine.h +++ b/include/linux/regulator/machine.h @@ -153,7 +153,7 @@ struct regulation_constraints { int system_load; /* used for coupled regulators */ - int max_spread; + u32 *max_spread; /* used for changing voltage in steps */ int max_uV_step; diff --git a/include/linux/regulator/max8952.h b/include/linux/regulator/max8952.h index ebd99d2e62ad..8712c091abf0 100644 --- a/include/linux/regulator/max8952.h +++ b/include/linux/regulator/max8952.h @@ -105,9 +105,6 @@ enum { #define MAX8952_NUM_DVS_MODE 4 struct max8952_platform_data { - int gpio_vid0; - int gpio_vid1; - u32 default_mode; u32 dvs_mode[MAX8952_NUM_DVS_MODE]; /* MAX8952_DVS_MODEx_XXXXmV */ diff --git a/include/linux/regulator/mt6358-regulator.h b/include/linux/regulator/mt6358-regulator.h new file mode 100644 index 000000000000..1cc304946d09 --- /dev/null +++ b/include/linux/regulator/mt6358-regulator.h @@ -0,0 +1,56 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2019 MediaTek Inc. + */ + +#ifndef __LINUX_REGULATOR_MT6358_H +#define __LINUX_REGULATOR_MT6358_H + +enum { + MT6358_ID_VDRAM1 = 0, + MT6358_ID_VCORE, + MT6358_ID_VPA, + MT6358_ID_VPROC11, + MT6358_ID_VPROC12, + MT6358_ID_VGPU, + MT6358_ID_VS2, + MT6358_ID_VMODEM, + MT6358_ID_VS1, + MT6358_ID_VDRAM2 = 9, + MT6358_ID_VSIM1, + MT6358_ID_VIBR, + MT6358_ID_VRF12, + MT6358_ID_VIO18, + MT6358_ID_VUSB, + MT6358_ID_VCAMIO, + MT6358_ID_VCAMD, + MT6358_ID_VCN18, + MT6358_ID_VFE28, + MT6358_ID_VSRAM_PROC11, + MT6358_ID_VCN28, + MT6358_ID_VSRAM_OTHERS, + MT6358_ID_VSRAM_GPU, + MT6358_ID_VXO22, + MT6358_ID_VEFUSE, + MT6358_ID_VAUX18, + MT6358_ID_VMCH, + MT6358_ID_VBIF28, + MT6358_ID_VSRAM_PROC12, + MT6358_ID_VCAMA1, + MT6358_ID_VEMC, + MT6358_ID_VIO28, + MT6358_ID_VA12, + MT6358_ID_VRF18, + MT6358_ID_VCN33_BT, + MT6358_ID_VCN33_WIFI, + MT6358_ID_VCAMA2, + MT6358_ID_VMC, + MT6358_ID_VLDO28, + MT6358_ID_VAUD28, + MT6358_ID_VSIM2, + MT6358_ID_RG_MAX, +}; + +#define MT6358_MAX_REGULATOR MT6358_ID_RG_MAX + +#endif /* __LINUX_REGULATOR_MT6358_H */ diff --git a/include/linux/remoteproc.h b/include/linux/remoteproc.h index 04d04709f2bd..16ad66683ad0 100644 --- a/include/linux/remoteproc.h +++ b/include/linux/remoteproc.h @@ -100,7 +100,9 @@ struct fw_rsc_hdr { * the remote processor will be writing logs. * @RSC_VDEV: declare support for a virtio device, and serve as its * virtio header. - * @RSC_LAST: just keep this one at the end + * @RSC_LAST: just keep this one at the end of standard resources + * @RSC_VENDOR_START: start of the vendor specific resource types range + * @RSC_VENDOR_END: end of the vendor specific resource types range * * For more details regarding a specific resource type, please see its * dedicated structure below. @@ -111,11 +113,13 @@ struct fw_rsc_hdr { * please update it as needed. */ enum fw_resource_type { - RSC_CARVEOUT = 0, - RSC_DEVMEM = 1, - RSC_TRACE = 2, - RSC_VDEV = 3, - RSC_LAST = 4, + RSC_CARVEOUT = 0, + RSC_DEVMEM = 1, + RSC_TRACE = 2, + RSC_VDEV = 3, + RSC_LAST = 4, + RSC_VENDOR_START = 128, + RSC_VENDOR_END = 512, }; #define FW_RSC_ADDR_ANY (-1) @@ -340,12 +344,26 @@ struct rproc_mem_entry { struct firmware; /** + * enum rsc_handling_status - return status of rproc_ops handle_rsc hook + * @RSC_HANDLED: resource was handled + * @RSC_IGNORED: resource was ignored + */ +enum rsc_handling_status { + RSC_HANDLED = 0, + RSC_IGNORED = 1, +}; + +/** * struct rproc_ops - platform-specific device handlers * @start: power on the device and boot it * @stop: power off the device * @kick: kick a virtqueue (virtqueue id given as a parameter) * @da_to_va: optional platform hook to perform address translations * @parse_fw: parse firmware to extract information (e.g. resource table) + * @handle_rsc: optional platform hook to handle vendor resources. Should return + * RSC_HANDLED if resource was handled, RSC_IGNORED if not handled and a + * negative value on error + * @load_rsc_table: load resource table from firmware image * @find_loaded_rsc_table: find the loaded resouce table * @load: load firmware to memory, where the remote processor * expects to find it @@ -358,6 +376,8 @@ struct rproc_ops { void (*kick)(struct rproc *rproc, int vqid); void * (*da_to_va)(struct rproc *rproc, u64 da, int len); int (*parse_fw)(struct rproc *rproc, const struct firmware *fw); + int (*handle_rsc)(struct rproc *rproc, u32 rsc_type, void *rsc, + int offset, int avail); struct resource_table *(*find_loaded_rsc_table)( struct rproc *rproc, const struct firmware *fw); int (*load)(struct rproc *rproc, const struct firmware *fw); diff --git a/include/linux/rhashtable.h b/include/linux/rhashtable.h index 9f8bc06d4136..beb9a9da1699 100644 --- a/include/linux/rhashtable.h +++ b/include/linux/rhashtable.h @@ -352,37 +352,38 @@ static inline void rht_unlock(struct bucket_table *tbl, static inline struct rhash_head __rcu *__rht_ptr( struct rhash_lock_head *const *bkt) { - return (struct rhash_head __rcu *)((unsigned long)*bkt & ~BIT(0)); + return (struct rhash_head __rcu *) + ((unsigned long)*bkt & ~BIT(0) ?: + (unsigned long)RHT_NULLS_MARKER(bkt)); } /* * Where 'bkt' is a bucket and might be locked: - * rht_ptr() dereferences that pointer and clears the lock bit. + * rht_ptr_rcu() dereferences that pointer and clears the lock bit. + * rht_ptr() dereferences in a context where the bucket is locked. * rht_ptr_exclusive() dereferences in a context where exclusive * access is guaranteed, such as when destroying the table. */ +static inline struct rhash_head *rht_ptr_rcu( + struct rhash_lock_head *const *bkt) +{ + struct rhash_head __rcu *p = __rht_ptr(bkt); + + return rcu_dereference(p); +} + static inline struct rhash_head *rht_ptr( struct rhash_lock_head *const *bkt, struct bucket_table *tbl, unsigned int hash) { - struct rhash_head __rcu *p = __rht_ptr(bkt); - - if (!p) - return RHT_NULLS_MARKER(bkt); - - return rht_dereference_bucket_rcu(p, tbl, hash); + return rht_dereference_bucket(__rht_ptr(bkt), tbl, hash); } static inline struct rhash_head *rht_ptr_exclusive( struct rhash_lock_head *const *bkt) { - struct rhash_head __rcu *p = __rht_ptr(bkt); - - if (!p) - return RHT_NULLS_MARKER(bkt); - - return rcu_dereference_protected(p, 1); + return rcu_dereference_protected(__rht_ptr(bkt), 1); } static inline void rht_assign_locked(struct rhash_lock_head **bkt, @@ -509,7 +510,7 @@ static inline void rht_assign_unlock(struct bucket_table *tbl, */ #define rht_for_each_rcu(pos, tbl, hash) \ for (({barrier(); }), \ - pos = rht_ptr(rht_bucket(tbl, hash), tbl, hash); \ + pos = rht_ptr_rcu(rht_bucket(tbl, hash)); \ !rht_is_a_nulls(pos); \ pos = rcu_dereference_raw(pos->next)) @@ -546,8 +547,7 @@ static inline void rht_assign_unlock(struct bucket_table *tbl, */ #define rht_for_each_entry_rcu(tpos, pos, tbl, hash, member) \ rht_for_each_entry_rcu_from(tpos, pos, \ - rht_ptr(rht_bucket(tbl, hash), \ - tbl, hash), \ + rht_ptr_rcu(rht_bucket(tbl, hash)), \ tbl, hash, member) /** @@ -603,7 +603,7 @@ restart: hash = rht_key_hashfn(ht, tbl, key, params); bkt = rht_bucket(tbl, hash); do { - rht_for_each_rcu_from(he, rht_ptr(bkt, tbl, hash), tbl, hash) { + rht_for_each_rcu_from(he, rht_ptr_rcu(bkt), tbl, hash) { if (params.obj_cmpfn ? params.obj_cmpfn(&arg, rht_obj(ht, he)) : rhashtable_compare(&arg, rht_obj(ht, he))) diff --git a/include/linux/root_dev.h b/include/linux/root_dev.h index bab671b0782f..4e78651371ba 100644 --- a/include/linux/root_dev.h +++ b/include/linux/root_dev.h @@ -8,6 +8,7 @@ enum { Root_NFS = MKDEV(UNNAMED_MAJOR, 255), + Root_CIFS = MKDEV(UNNAMED_MAJOR, 254), Root_RAM0 = MKDEV(RAMDISK_MAJOR, 0), Root_RAM1 = MKDEV(RAMDISK_MAJOR, 1), Root_FD0 = MKDEV(FLOPPY_MAJOR, 0), diff --git a/include/linux/rwsem.h b/include/linux/rwsem.h index 2ea18a3def04..00d6054687dd 100644 --- a/include/linux/rwsem.h +++ b/include/linux/rwsem.h @@ -34,26 +34,30 @@ */ struct rw_semaphore { atomic_long_t count; -#ifdef CONFIG_RWSEM_SPIN_ON_OWNER /* - * Write owner. Used as a speculative check to see - * if the owner is running on the cpu. + * Write owner or one of the read owners as well flags regarding + * the current state of the rwsem. Can be used as a speculative + * check to see if the write owner is running on the cpu. */ - struct task_struct *owner; + atomic_long_t owner; +#ifdef CONFIG_RWSEM_SPIN_ON_OWNER struct optimistic_spin_queue osq; /* spinner MCS lock */ #endif raw_spinlock_t wait_lock; struct list_head wait_list; +#ifdef CONFIG_DEBUG_RWSEMS + void *magic; +#endif #ifdef CONFIG_DEBUG_LOCK_ALLOC struct lockdep_map dep_map; #endif }; /* - * Setting bit 1 of the owner field but not bit 0 will indicate + * Setting all bits of the owner field except bit 0 will indicate * that the rwsem is writer-owned with an unknown owner. */ -#define RWSEM_OWNER_UNKNOWN ((struct task_struct *)-2L) +#define RWSEM_OWNER_UNKNOWN (-2L) /* In all implementations count != 0 means locked */ static inline int rwsem_is_locked(struct rw_semaphore *sem) @@ -72,17 +76,25 @@ static inline int rwsem_is_locked(struct rw_semaphore *sem) # define __RWSEM_DEP_MAP_INIT(lockname) #endif +#ifdef CONFIG_DEBUG_RWSEMS +# define __DEBUG_RWSEM_INITIALIZER(lockname) , .magic = &lockname +#else +# define __DEBUG_RWSEM_INITIALIZER(lockname) +#endif + #ifdef CONFIG_RWSEM_SPIN_ON_OWNER -#define __RWSEM_OPT_INIT(lockname) , .osq = OSQ_LOCK_UNLOCKED, .owner = NULL +#define __RWSEM_OPT_INIT(lockname) , .osq = OSQ_LOCK_UNLOCKED #else #define __RWSEM_OPT_INIT(lockname) #endif #define __RWSEM_INITIALIZER(name) \ { __RWSEM_INIT_COUNT(name), \ + .owner = ATOMIC_LONG_INIT(0), \ .wait_list = LIST_HEAD_INIT((name).wait_list), \ .wait_lock = __RAW_SPIN_LOCK_UNLOCKED(name.wait_lock) \ __RWSEM_OPT_INIT(name) \ + __DEBUG_RWSEM_INITIALIZER(name) \ __RWSEM_DEP_MAP_INIT(name) } #define DECLARE_RWSEM(name) \ @@ -158,7 +170,7 @@ extern void downgrade_write(struct rw_semaphore *sem); * static then another method for expressing nested locking is * the explicit definition of lock class keys and the use of * lockdep_set_class() at lock initialization time. - * See Documentation/locking/lockdep-design.txt for more details.) + * See Documentation/locking/lockdep-design.rst for more details.) */ extern void down_read_nested(struct rw_semaphore *sem, int subclass); extern void down_write_nested(struct rw_semaphore *sem, int subclass); diff --git a/include/linux/scatterlist.h b/include/linux/scatterlist.h index 30a9a55c28ba..6eec50fb36c8 100644 --- a/include/linux/scatterlist.h +++ b/include/linux/scatterlist.h @@ -266,10 +266,11 @@ int sg_split(struct scatterlist *in, const int in_mapped_nents, typedef struct scatterlist *(sg_alloc_fn)(unsigned int, gfp_t); typedef void (sg_free_fn)(struct scatterlist *, unsigned int); -void __sg_free_table(struct sg_table *, unsigned int, bool, sg_free_fn *); +void __sg_free_table(struct sg_table *, unsigned int, unsigned int, + sg_free_fn *); void sg_free_table(struct sg_table *); int __sg_alloc_table(struct sg_table *, unsigned int, unsigned int, - struct scatterlist *, gfp_t, sg_alloc_fn *); + struct scatterlist *, unsigned int, gfp_t, sg_alloc_fn *); int sg_alloc_table(struct sg_table *, unsigned int, gfp_t); int __sg_alloc_table_from_pages(struct sg_table *sgt, struct page **pages, unsigned int n_pages, unsigned int offset, @@ -331,9 +332,11 @@ size_t sg_zero_buffer(struct scatterlist *sgl, unsigned int nents, #endif #ifdef CONFIG_SG_POOL -void sg_free_table_chained(struct sg_table *table, bool first_chunk); +void sg_free_table_chained(struct sg_table *table, + unsigned nents_first_chunk); int sg_alloc_table_chained(struct sg_table *table, int nents, - struct scatterlist *first_chunk); + struct scatterlist *first_chunk, + unsigned nents_first_chunk); #endif /* diff --git a/include/linux/sched.h b/include/linux/sched.h index 11837410690f..70db597d6fd4 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -25,9 +25,11 @@ #include <linux/resource.h> #include <linux/latencytop.h> #include <linux/sched/prio.h> +#include <linux/sched/types.h> #include <linux/signal_types.h> #include <linux/mm_types_task.h> #include <linux/task_io_accounting.h> +#include <linux/posix-timers.h> #include <linux/rseq.h> /* task_struct member predeclarations (sorted alphabetically): */ @@ -35,6 +37,7 @@ struct audit_context; struct backing_dev_info; struct bio_list; struct blk_plug; +struct capture_control; struct cfs_rq; struct fs_struct; struct futex_pi_state; @@ -47,8 +50,9 @@ struct pid_namespace; struct pipe_inode_info; struct rcu_node; struct reclaim_state; -struct capture_control; struct robust_list_head; +struct root_domain; +struct rq; struct sched_attr; struct sched_param; struct seq_file; @@ -242,27 +246,6 @@ struct prev_cputime { #endif }; -/** - * struct task_cputime - collected CPU time counts - * @utime: time spent in user mode, in nanoseconds - * @stime: time spent in kernel mode, in nanoseconds - * @sum_exec_runtime: total time spent on the CPU, in nanoseconds - * - * This structure groups together three kinds of CPU time that are tracked for - * threads and thread groups. Most things considering CPU time want to group - * these counts together and treat all three of them in parallel. - */ -struct task_cputime { - u64 utime; - u64 stime; - unsigned long long sum_exec_runtime; -}; - -/* Alternate field names when used on cache expirations: */ -#define virt_exp utime -#define prof_exp stime -#define sched_exp sum_exec_runtime - enum vtime_state { /* Task is sleeping or running in a CPU with VTIME inactive: */ VTIME_INACTIVE = 0, @@ -281,6 +264,23 @@ struct vtime { u64 gtime; }; +/* + * Utilization clamp constraints. + * @UCLAMP_MIN: Minimum utilization + * @UCLAMP_MAX: Maximum utilization + * @UCLAMP_CNT: Utilization clamp constraints count + */ +enum uclamp_id { + UCLAMP_MIN = 0, + UCLAMP_MAX, + UCLAMP_CNT +}; + +#ifdef CONFIG_SMP +extern struct root_domain def_root_domain; +extern struct mutex sched_domains_mutex; +#endif + struct sched_info { #ifdef CONFIG_SCHED_INFO /* Cumulative counters: */ @@ -312,6 +312,10 @@ struct sched_info { # define SCHED_FIXEDPOINT_SHIFT 10 # define SCHED_FIXEDPOINT_SCALE (1L << SCHED_FIXEDPOINT_SHIFT) +/* Increase resolution of cpu_capacity calculations */ +# define SCHED_CAPACITY_SHIFT SCHED_FIXEDPOINT_SHIFT +# define SCHED_CAPACITY_SCALE (1L << SCHED_CAPACITY_SHIFT) + struct load_weight { unsigned long weight; u32 inv_weight; @@ -560,12 +564,47 @@ struct sched_dl_entity { struct hrtimer inactive_timer; }; +#ifdef CONFIG_UCLAMP_TASK +/* Number of utilization clamp buckets (shorter alias) */ +#define UCLAMP_BUCKETS CONFIG_UCLAMP_BUCKETS_COUNT + +/* + * Utilization clamp for a scheduling entity + * @value: clamp value "assigned" to a se + * @bucket_id: bucket index corresponding to the "assigned" value + * @active: the se is currently refcounted in a rq's bucket + * @user_defined: the requested clamp value comes from user-space + * + * The bucket_id is the index of the clamp bucket matching the clamp value + * which is pre-computed and stored to avoid expensive integer divisions from + * the fast path. + * + * The active bit is set whenever a task has got an "effective" value assigned, + * which can be different from the clamp value "requested" from user-space. + * This allows to know a task is refcounted in the rq's bucket corresponding + * to the "effective" bucket_id. + * + * The user_defined bit is set whenever a task has got a task-specific clamp + * value requested from userspace, i.e. the system defaults apply to this task + * just as a restriction. This allows to relax default clamps when a less + * restrictive task-specific value has been requested, thus allowing to + * implement a "nice" semantic. For example, a task running with a 20% + * default boost can still drop its own boosting to 0%. + */ +struct uclamp_se { + unsigned int value : bits_per(SCHED_CAPACITY_SCALE); + unsigned int bucket_id : bits_per(UCLAMP_BUCKETS); + unsigned int active : 1; + unsigned int user_defined : 1; +}; +#endif /* CONFIG_UCLAMP_TASK */ + union rcu_special { struct { u8 blocked; u8 need_qs; u8 exp_hint; /* Hint for performance. */ - u8 pad; /* No garbage from compiler! */ + u8 deferred_qs; } b; /* Bits. */ u32 s; /* Set of bits. */ }; @@ -640,6 +679,13 @@ struct task_struct { #endif struct sched_dl_entity dl; +#ifdef CONFIG_UCLAMP_TASK + /* Clamp values requested for a scheduling entity */ + struct uclamp_se uclamp_req[UCLAMP_CNT]; + /* Effective clamp values used for a scheduling entity */ + struct uclamp_se uclamp[UCLAMP_CNT]; +#endif + #ifdef CONFIG_PREEMPT_NOTIFIERS /* List of struct preempt_notifier: */ struct hlist_head preempt_notifiers; @@ -651,7 +697,8 @@ struct task_struct { unsigned int policy; int nr_cpus_allowed; - cpumask_t cpus_allowed; + const cpumask_t *cpus_ptr; + cpumask_t cpus_mask; #ifdef CONFIG_PREEMPT_RCU int rcu_read_lock_nesting; @@ -815,10 +862,8 @@ struct task_struct { unsigned long min_flt; unsigned long maj_flt; -#ifdef CONFIG_POSIX_TIMERS - struct task_cputime cputime_expires; - struct list_head cpu_timers[3]; -#endif + /* Empty if CONFIG_POSIX_CPUTIMERS=n */ + struct posix_cputimers posix_cputimers; /* Process credentials: */ @@ -831,6 +876,11 @@ struct task_struct { /* Effective (overridable) subjective task credentials (COW): */ const struct cred __rcu *cred; +#ifdef CONFIG_KEYS + /* Cached requested key. */ + struct key *cached_requested_key; +#endif + /* * executable name, excluding path. * @@ -908,6 +958,10 @@ struct task_struct { struct mutex_waiter *blocked_on; #endif +#ifdef CONFIG_DEBUG_ATOMIC_SLEEP + int non_block_count; +#endif + #ifdef CONFIG_TRACE_IRQFLAGS unsigned int irq_events; unsigned long hardirq_enable_ip; @@ -1026,7 +1080,15 @@ struct task_struct { u64 last_sum_exec_runtime; struct callback_head numa_work; - struct numa_group *numa_group; + /* + * This pointer is only modified for current in syscall and + * pagefault context (and for tasks being destroyed), so it can be read + * from any of the following contexts: + * - RCU read-side critical section + * - current->numa_group from everywhere + * - task's runqueue locked, task not running + */ + struct numa_group __rcu *numa_group; /* * numa_faults is an array split into four regions: @@ -1399,7 +1461,7 @@ extern struct pid *cad_pid; #define PF_SWAPWRITE 0x00800000 /* Allowed to write to swap */ #define PF_MEMSTALL 0x01000000 /* Stalled due to lack of memory */ #define PF_UMH 0x02000000 /* I'm an Usermodehelper process */ -#define PF_NO_SETAFFINITY 0x04000000 /* Userland is not allowed to meddle with cpus_allowed */ +#define PF_NO_SETAFFINITY 0x04000000 /* Userland is not allowed to meddle with cpus_mask */ #define PF_MCE_EARLY 0x08000000 /* Early kill for mce process policy */ #define PF_MEMALLOC_NOCMA 0x10000000 /* All allocation request will have _GFP_MOVABLE cleared */ #define PF_FREEZER_SKIP 0x40000000 /* Freezer should not count it as freezable */ @@ -1518,10 +1580,6 @@ static inline int set_cpus_allowed_ptr(struct task_struct *p, const struct cpuma } #endif -#ifndef cpu_relax_yield -#define cpu_relax_yield() cpu_relax() -#endif - extern int yield_to(struct task_struct *p, bool preempt); extern void set_user_nice(struct task_struct *p, long nice); extern int task_prio(const struct task_struct *p); @@ -1697,7 +1755,7 @@ static inline int test_tsk_need_resched(struct task_struct *tsk) * value indicates whether a reschedule was done in fact. * cond_resched_lock() will drop the spinlock before scheduling, */ -#ifndef CONFIG_PREEMPT +#ifndef CONFIG_PREEMPTION extern int _cond_resched(void); #else static inline int _cond_resched(void) { return 0; } @@ -1726,12 +1784,12 @@ static inline void cond_resched_rcu(void) /* * Does a critical section need to be broken due to another - * task waiting?: (technically does not depend on CONFIG_PREEMPT, + * task waiting?: (technically does not depend on CONFIG_PREEMPTION, * but a general need for low latency) */ static inline int spin_needbreak(spinlock_t *lock) { -#ifdef CONFIG_PREEMPT +#ifdef CONFIG_PREEMPTION return spin_is_contended(lock); #else return 0; @@ -1919,4 +1977,16 @@ static inline void rseq_syscall(struct pt_regs *regs) #endif +const struct sched_avg *sched_trace_cfs_rq_avg(struct cfs_rq *cfs_rq); +char *sched_trace_cfs_rq_path(struct cfs_rq *cfs_rq, char *str, int len); +int sched_trace_cfs_rq_cpu(struct cfs_rq *cfs_rq); + +const struct sched_avg *sched_trace_rq_avg_rt(struct rq *rq); +const struct sched_avg *sched_trace_rq_avg_dl(struct rq *rq); +const struct sched_avg *sched_trace_rq_avg_irq(struct rq *rq); + +int sched_trace_rq_cpu(struct rq *rq); + +const struct cpumask *sched_trace_rd_span(struct root_domain *rd); + #endif diff --git a/include/linux/sched/cputime.h b/include/linux/sched/cputime.h index 53f883f5a2fd..6c9f19a33865 100644 --- a/include/linux/sched/cputime.h +++ b/include/linux/sched/cputime.h @@ -61,8 +61,7 @@ extern void cputime_adjust(struct task_cputime *curr, struct prev_cputime *prev, * Thread group CPU time accounting. */ void thread_group_cputime(struct task_struct *tsk, struct task_cputime *times); -void thread_group_cputimer(struct task_struct *tsk, struct task_cputime *times); - +void thread_group_sample_cputime(struct task_struct *tsk, u64 *samples); /* * The following are functions that support scheduler-internal time accounting. @@ -71,7 +70,7 @@ void thread_group_cputimer(struct task_struct *tsk, struct task_cputime *times); */ /** - * get_running_cputimer - return &tsk->signal->cputimer if cputimer is running + * get_running_cputimer - return &tsk->signal->cputimer if cputimers are active * * @tsk: Pointer to target task. */ @@ -81,8 +80,11 @@ struct thread_group_cputimer *get_running_cputimer(struct task_struct *tsk) { struct thread_group_cputimer *cputimer = &tsk->signal->cputimer; - /* Check if cputimer isn't running. This is accessed without locking. */ - if (!READ_ONCE(cputimer->running)) + /* + * Check whether posix CPU timers are active. If not the thread + * group accounting is not active either. Lockless check. + */ + if (!READ_ONCE(tsk->signal->posix_cputimers.timers_active)) return NULL; /* diff --git a/include/linux/sched/deadline.h b/include/linux/sched/deadline.h index 0cb034331cbb..1aff00b65f3c 100644 --- a/include/linux/sched/deadline.h +++ b/include/linux/sched/deadline.h @@ -24,3 +24,11 @@ static inline bool dl_time_before(u64 a, u64 b) { return (s64)(a - b) < 0; } + +#ifdef CONFIG_SMP + +struct root_domain; +extern void dl_add_task_root_domain(struct task_struct *p); +extern void dl_clear_root_domain(struct root_domain *rd); + +#endif /* CONFIG_SMP */ diff --git a/include/linux/sched/isolation.h b/include/linux/sched/isolation.h index b0fb1446fe04..6c8512d3be88 100644 --- a/include/linux/sched/isolation.h +++ b/include/linux/sched/isolation.h @@ -19,6 +19,7 @@ enum hk_flags { DECLARE_STATIC_KEY_FALSE(housekeeping_overridden); extern int housekeeping_any_cpu(enum hk_flags flags); extern const struct cpumask *housekeeping_cpumask(enum hk_flags flags); +extern bool housekeeping_enabled(enum hk_flags flags); extern void housekeeping_affine(struct task_struct *t, enum hk_flags flags); extern bool housekeeping_test_cpu(int cpu, enum hk_flags flags); extern void __init housekeeping_init(void); @@ -35,6 +36,11 @@ static inline const struct cpumask *housekeeping_cpumask(enum hk_flags flags) return cpu_possible_mask; } +static inline bool housekeeping_enabled(enum hk_flags flags) +{ + return false; +} + static inline void housekeeping_affine(struct task_struct *t, enum hk_flags flags) { } static inline void housekeeping_init(void) { } diff --git a/include/linux/sched/nohz.h b/include/linux/sched/nohz.h index b36f4cf38111..1abe91ff6e4a 100644 --- a/include/linux/sched/nohz.h +++ b/include/linux/sched/nohz.h @@ -7,14 +7,6 @@ */ #if defined(CONFIG_SMP) && defined(CONFIG_NO_HZ_COMMON) -extern void cpu_load_update_nohz_start(void); -extern void cpu_load_update_nohz_stop(void); -#else -static inline void cpu_load_update_nohz_start(void) { } -static inline void cpu_load_update_nohz_stop(void) { } -#endif - -#if defined(CONFIG_SMP) && defined(CONFIG_NO_HZ_COMMON) extern void nohz_balance_enter_idle(int cpu); extern int get_nohz_timer_target(void); #else diff --git a/include/linux/sched/numa_balancing.h b/include/linux/sched/numa_balancing.h index e7dd04a84ba8..3988762efe15 100644 --- a/include/linux/sched/numa_balancing.h +++ b/include/linux/sched/numa_balancing.h @@ -19,7 +19,7 @@ extern void task_numa_fault(int last_node, int node, int pages, int flags); extern pid_t task_numa_group_id(struct task_struct *p); extern void set_numabalancing_state(bool enabled); -extern void task_numa_free(struct task_struct *p); +extern void task_numa_free(struct task_struct *p, bool final); extern bool should_numa_migrate_memory(struct task_struct *p, struct page *page, int src_nid, int dst_cpu); #else @@ -34,7 +34,7 @@ static inline pid_t task_numa_group_id(struct task_struct *p) static inline void set_numabalancing_state(bool enabled) { } -static inline void task_numa_free(struct task_struct *p) +static inline void task_numa_free(struct task_struct *p, bool final) { } static inline bool should_numa_migrate_memory(struct task_struct *p, diff --git a/include/linux/sched/signal.h b/include/linux/sched/signal.h index 38a0f0785323..88050259c466 100644 --- a/include/linux/sched/signal.h +++ b/include/linux/sched/signal.h @@ -9,16 +9,17 @@ #include <linux/sched/task.h> #include <linux/cred.h> #include <linux/refcount.h> +#include <linux/posix-timers.h> /* * Types defining task->signal and task->sighand and APIs using them: */ struct sighand_struct { - refcount_t count; - struct k_sigaction action[_NSIG]; spinlock_t siglock; + refcount_t count; wait_queue_head_t signalfd_wqh; + struct k_sigaction action[_NSIG]; }; /* @@ -56,18 +57,12 @@ struct task_cputime_atomic { /** * struct thread_group_cputimer - thread group interval timer counts * @cputime_atomic: atomic thread group interval timers. - * @running: true when there are timers running and - * @cputime_atomic receives updates. - * @checking_timer: true when a thread in the group is in the - * process of checking for thread group timers. * * This structure contains the version of task_cputime, above, that is * used for thread group CPU timer calculations. */ struct thread_group_cputimer { struct task_cputime_atomic cputime_atomic; - bool running; - bool checking_timer; }; struct multiprocess_signals { @@ -148,12 +143,9 @@ struct signal_struct { */ struct thread_group_cputimer cputimer; - /* Earliest-expiration cache. */ - struct task_cputime cputime_expires; - - struct list_head cpu_timers[3]; - #endif + /* Empty if CONFIG_POSIX_TIMERS=n */ + struct posix_cputimers posix_cputimers; /* PID/PID hash table linkage. */ struct pid *pids[PIDTYPE_MAX]; @@ -307,16 +299,19 @@ static inline void kernel_signal_stop(void) # define ___ARCH_SI_IA64(_a1, _a2, _a3) #endif -int force_sig_fault(int sig, int code, void __user *addr +int force_sig_fault_to_task(int sig, int code, void __user *addr ___ARCH_SI_TRAPNO(int trapno) ___ARCH_SI_IA64(int imm, unsigned int flags, unsigned long isr) , struct task_struct *t); +int force_sig_fault(int sig, int code, void __user *addr + ___ARCH_SI_TRAPNO(int trapno) + ___ARCH_SI_IA64(int imm, unsigned int flags, unsigned long isr)); int send_sig_fault(int sig, int code, void __user *addr ___ARCH_SI_TRAPNO(int trapno) ___ARCH_SI_IA64(int imm, unsigned int flags, unsigned long isr) , struct task_struct *t); -int force_sig_mceerr(int code, void __user *, short, struct task_struct *); +int force_sig_mceerr(int code, void __user *, short); int send_sig_mceerr(int code, void __user *, short, struct task_struct *); int force_sig_bnderr(void __user *addr, void __user *lower, void __user *upper); @@ -325,17 +320,17 @@ int force_sig_pkuerr(void __user *addr, u32 pkey); int force_sig_ptrace_errno_trap(int errno, void __user *addr); extern int send_sig_info(int, struct kernel_siginfo *, struct task_struct *); -extern void force_sigsegv(int sig, struct task_struct *p); -extern int force_sig_info(int, struct kernel_siginfo *, struct task_struct *); +extern void force_sigsegv(int sig); +extern int force_sig_info(struct kernel_siginfo *); extern int __kill_pgrp_info(int sig, struct kernel_siginfo *info, struct pid *pgrp); extern int kill_pid_info(int sig, struct kernel_siginfo *info, struct pid *pid); -extern int kill_pid_info_as_cred(int, struct kernel_siginfo *, struct pid *, +extern int kill_pid_usb_asyncio(int sig, int errno, sigval_t addr, struct pid *, const struct cred *); extern int kill_pgrp(struct pid *pid, int sig, int priv); extern int kill_pid(struct pid *pid, int sig, int priv); extern __must_check bool do_notify_parent(struct task_struct *, int); extern void __wake_up_parent(struct task_struct *p, struct task_struct *parent); -extern void force_sig(int, struct task_struct *); +extern void force_sig(int); extern int send_sig(int, struct task_struct *, int); extern int zap_other_threads(struct task_struct *p); extern struct sigqueue *sigqueue_alloc(void); @@ -417,7 +412,6 @@ void task_join_group_stop(struct task_struct *task); static inline void set_restore_sigmask(void) { set_thread_flag(TIF_RESTORE_SIGMASK); - WARN_ON(!test_thread_flag(TIF_SIGPENDING)); } static inline void clear_tsk_restore_sigmask(struct task_struct *task) @@ -448,7 +442,6 @@ static inline bool test_and_clear_restore_sigmask(void) static inline void set_restore_sigmask(void) { current->restore_sigmask = true; - WARN_ON(!test_thread_flag(TIF_SIGPENDING)); } static inline void clear_tsk_restore_sigmask(struct task_struct *task) { @@ -481,6 +474,16 @@ static inline void restore_saved_sigmask(void) __set_current_blocked(¤t->saved_sigmask); } +extern int set_user_sigmask(const sigset_t __user *umask, size_t sigsetsize); + +static inline void restore_saved_sigmask_unless(bool interrupted) +{ + if (interrupted) + WARN_ON(!test_thread_flag(TIF_SIGPENDING)); + else + restore_saved_sigmask(); +} + static inline sigset_t *sigmask_to_save(void) { sigset_t *res = ¤t->blocked; diff --git a/include/linux/sched/sysctl.h b/include/linux/sched/sysctl.h index 99ce6d728df7..d4f6215ee03f 100644 --- a/include/linux/sched/sysctl.h +++ b/include/linux/sched/sysctl.h @@ -56,6 +56,11 @@ int sched_proc_update_handler(struct ctl_table *table, int write, extern unsigned int sysctl_sched_rt_period; extern int sysctl_sched_rt_runtime; +#ifdef CONFIG_UCLAMP_TASK +extern unsigned int sysctl_sched_uclamp_util_min; +extern unsigned int sysctl_sched_uclamp_util_max; +#endif + #ifdef CONFIG_CFS_BANDWIDTH extern unsigned int sysctl_sched_cfs_bandwidth_slice; #endif @@ -75,6 +80,12 @@ extern int sched_rt_handler(struct ctl_table *table, int write, void __user *buffer, size_t *lenp, loff_t *ppos); +#ifdef CONFIG_UCLAMP_TASK +extern int sysctl_sched_uclamp_handler(struct ctl_table *table, int write, + void __user *buffer, size_t *lenp, + loff_t *ppos); +#endif + extern int sysctl_numa_balancing(struct ctl_table *table, int write, void __user *buffer, size_t *lenp, loff_t *ppos); diff --git a/include/linux/sched/task.h b/include/linux/sched/task.h index f1227f2c38a4..3d90ed8f75f0 100644 --- a/include/linux/sched/task.h +++ b/include/linux/sched/task.h @@ -8,11 +8,26 @@ */ #include <linux/sched.h> +#include <linux/uaccess.h> struct task_struct; struct rusage; union thread_union; +/* All the bits taken by the old clone syscall. */ +#define CLONE_LEGACY_FLAGS 0xffffffffULL + +struct kernel_clone_args { + u64 flags; + int __user *pidfd; + int __user *child_tid; + int __user *parent_tid; + int exit_signal; + unsigned long stack; + unsigned long stack_size; + unsigned long tls; +}; + /* * This serializes "schedule()" and also protects * the run-queue from deletions/modifications (but @@ -73,7 +88,8 @@ extern void do_group_exit(int); extern void exit_files(struct task_struct *); extern void exit_itimers(struct signal_struct *); -extern long _do_fork(unsigned long, unsigned long, unsigned long, int __user *, int __user *, unsigned long); +extern long _do_fork(struct kernel_clone_args *kargs); +extern bool legacy_clone_args_valid(const struct kernel_clone_args *kargs); extern long do_fork(unsigned long, unsigned long, unsigned long, int __user *, int __user *); struct task_struct *fork_idle(int); struct mm_struct *copy_init_mm(void); @@ -89,7 +105,11 @@ extern void sched_exec(void); #define sched_exec() {} #endif -#define get_task_struct(tsk) do { refcount_inc(&(tsk)->usage); } while(0) +static inline struct task_struct *get_task_struct(struct task_struct *t) +{ + refcount_inc(&t->usage); + return t; +} extern void __put_task_struct(struct task_struct *t); diff --git a/include/linux/sched/topology.h b/include/linux/sched/topology.h index cfc0a89a7159..f341163fedc9 100644 --- a/include/linux/sched/topology.h +++ b/include/linux/sched/topology.h @@ -7,12 +7,6 @@ #include <linux/sched/idle.h> /* - * Increase resolution of cpu_capacity calculations - */ -#define SCHED_CAPACITY_SHIFT SCHED_FIXEDPOINT_SHIFT -#define SCHED_CAPACITY_SCALE (1L << SCHED_CAPACITY_SHIFT) - -/* * sched-domains (multiprocessor balancing) declarations: */ #ifdef CONFIG_SMP @@ -84,11 +78,6 @@ struct sched_domain { unsigned int busy_factor; /* less balancing by factor if busy */ unsigned int imbalance_pct; /* No balance until over watermark */ unsigned int cache_nice_tries; /* Leave cache hot tasks for # tries */ - unsigned int busy_idx; - unsigned int idle_idx; - unsigned int newidle_idx; - unsigned int wake_idx; - unsigned int forkexec_idx; int nohz_idle; /* NOHZ IDLE status */ int flags; /* See SD_* */ @@ -161,6 +150,10 @@ static inline struct cpumask *sched_domain_span(struct sched_domain *sd) return to_cpumask(sd->span); } +extern void partition_sched_domains_locked(int ndoms_new, + cpumask_var_t doms_new[], + struct sched_domain_attr *dattr_new); + extern void partition_sched_domains(int ndoms_new, cpumask_var_t doms_new[], struct sched_domain_attr *dattr_new); @@ -201,19 +194,17 @@ extern void set_sched_topology(struct sched_domain_topology_level *tl); # define SD_INIT_NAME(type) #endif -#ifndef arch_scale_cpu_capacity -static __always_inline -unsigned long arch_scale_cpu_capacity(struct sched_domain *sd, int cpu) -{ - return SCHED_CAPACITY_SCALE; -} -#endif - #else /* CONFIG_SMP */ struct sched_domain_attr; static inline void +partition_sched_domains_locked(int ndoms_new, cpumask_var_t doms_new[], + struct sched_domain_attr *dattr_new) +{ +} + +static inline void partition_sched_domains(int ndoms_new, cpumask_var_t doms_new[], struct sched_domain_attr *dattr_new) { @@ -224,16 +215,16 @@ static inline bool cpus_share_cache(int this_cpu, int that_cpu) return true; } +#endif /* !CONFIG_SMP */ + #ifndef arch_scale_cpu_capacity static __always_inline -unsigned long arch_scale_cpu_capacity(void __always_unused *sd, int cpu) +unsigned long arch_scale_cpu_capacity(int cpu) { return SCHED_CAPACITY_SCALE; } #endif -#endif /* !CONFIG_SMP */ - static inline int task_node(const struct task_struct *p) { return cpu_to_node(task_cpu(p)); diff --git a/include/linux/sched/types.h b/include/linux/sched/types.h new file mode 100644 index 000000000000..3c3e049224ae --- /dev/null +++ b/include/linux/sched/types.h @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _LINUX_SCHED_TYPES_H +#define _LINUX_SCHED_TYPES_H + +#include <linux/types.h> + +/** + * struct task_cputime - collected CPU time counts + * @stime: time spent in kernel mode, in nanoseconds + * @utime: time spent in user mode, in nanoseconds + * @sum_exec_runtime: total time spent on the CPU, in nanoseconds + * + * This structure groups together three kinds of CPU time that are tracked for + * threads and thread groups. Most things considering CPU time want to group + * these counts together and treat all three of them in parallel. + */ +struct task_cputime { + u64 stime; + u64 utime; + unsigned long long sum_exec_runtime; +}; + +#endif diff --git a/include/linux/sched/user.h b/include/linux/sched/user.h index 468d2565a9fe..917d88edb7b9 100644 --- a/include/linux/sched/user.h +++ b/include/linux/sched/user.h @@ -7,8 +7,6 @@ #include <linux/refcount.h> #include <linux/ratelimit.h> -struct key; - /* * Some day this will be a full-fledged user tracking system.. */ @@ -30,18 +28,6 @@ struct user_struct { unsigned long unix_inflight; /* How many files in flight in unix sockets */ atomic_long_t pipe_bufs; /* how many pages are allocated in pipe buffers */ -#ifdef CONFIG_KEYS - /* - * These pointers can only change from NULL to a non-NULL value once. - * Writes are protected by key_user_keyring_mutex. - * Unlocked readers should use READ_ONCE() unless they know that - * install_user_keyrings() has been called successfully (which sets - * these members to non-NULL values, preventing further modifications). - */ - struct key *uid_keyring; /* UID specific keyring */ - struct key *session_keyring; /* UID's default session keyring */ -#endif - /* Hash table maintenance information */ struct hlist_node uidhash_node; kuid_t uid; diff --git a/include/linux/sched/wake_q.h b/include/linux/sched/wake_q.h index ad826d2a4557..26a2013ac39c 100644 --- a/include/linux/sched/wake_q.h +++ b/include/linux/sched/wake_q.h @@ -51,6 +51,11 @@ static inline void wake_q_init(struct wake_q_head *head) head->lastp = &head->first; } +static inline bool wake_q_empty(struct wake_q_head *head) +{ + return head->first == WAKE_Q_TAIL; +} + extern void wake_q_add(struct wake_q_head *head, struct task_struct *task); extern void wake_q_add_safe(struct wake_q_head *head, struct task_struct *task); extern void wake_up_q(struct wake_q_head *head); diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h index 3105055c00a7..881fea47c83d 100644 --- a/include/linux/scmi_protocol.h +++ b/include/linux/scmi_protocol.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0-only */ /* * SCMI Message Protocol driver header * @@ -71,7 +71,7 @@ struct scmi_clk_ops { int (*rate_get)(const struct scmi_handle *handle, u32 clk_id, u64 *rate); int (*rate_set)(const struct scmi_handle *handle, u32 clk_id, - u32 config, u64 rate); + u64 rate); int (*enable)(const struct scmi_handle *handle, u32 clk_id); int (*disable)(const struct scmi_handle *handle, u32 clk_id); }; @@ -144,6 +144,9 @@ struct scmi_power_ops { struct scmi_sensor_info { u32 id; u8 type; + s8 scale; + u8 num_trip_points; + bool async; char name[SCMI_MAX_STR_SIZE]; }; @@ -166,9 +169,9 @@ enum scmi_sensor_class { * * @count_get: get the count of sensors provided by SCMI * @info_get: get the information of the specified sensor - * @configuration_set: control notifications on cross-over events for + * @trip_point_notify: control notifications on cross-over events for * the trip-points - * @trip_point_set: selects and configures a trip-point of interest + * @trip_point_config: selects and configures a trip-point of interest * @reading_get: gets the current value of the sensor */ struct scmi_sensor_ops { @@ -176,12 +179,32 @@ struct scmi_sensor_ops { const struct scmi_sensor_info *(*info_get) (const struct scmi_handle *handle, u32 sensor_id); - int (*configuration_set)(const struct scmi_handle *handle, - u32 sensor_id); - int (*trip_point_set)(const struct scmi_handle *handle, u32 sensor_id, - u8 trip_id, u64 trip_value); + int (*trip_point_notify)(const struct scmi_handle *handle, + u32 sensor_id, bool enable); + int (*trip_point_config)(const struct scmi_handle *handle, + u32 sensor_id, u8 trip_id, u64 trip_value); int (*reading_get)(const struct scmi_handle *handle, u32 sensor_id, - bool async, u64 *value); + u64 *value); +}; + +/** + * struct scmi_reset_ops - represents the various operations provided + * by SCMI Reset Protocol + * + * @num_domains_get: get the count of reset domains provided by SCMI + * @name_get: gets the name of a reset domain + * @latency_get: gets the reset latency for the specified reset domain + * @reset: resets the specified reset domain + * @assert: explicitly assert reset signal of the specified reset domain + * @deassert: explicitly deassert reset signal of the specified reset domain + */ +struct scmi_reset_ops { + int (*num_domains_get)(const struct scmi_handle *handle); + char *(*name_get)(const struct scmi_handle *handle, u32 domain); + int (*latency_get)(const struct scmi_handle *handle, u32 domain); + int (*reset)(const struct scmi_handle *handle, u32 domain); + int (*assert)(const struct scmi_handle *handle, u32 domain); + int (*deassert)(const struct scmi_handle *handle, u32 domain); }; /** @@ -193,6 +216,7 @@ struct scmi_sensor_ops { * @perf_ops: pointer to set of performance protocol operations * @clk_ops: pointer to set of clock protocol operations * @sensor_ops: pointer to set of sensor protocol operations + * @reset_ops: pointer to set of reset protocol operations * @perf_priv: pointer to private data structure specific to performance * protocol(for internal use only) * @clk_priv: pointer to private data structure specific to clock @@ -201,6 +225,8 @@ struct scmi_sensor_ops { * protocol(for internal use only) * @sensor_priv: pointer to private data structure specific to sensors * protocol(for internal use only) + * @reset_priv: pointer to private data structure specific to reset + * protocol(for internal use only) */ struct scmi_handle { struct device *dev; @@ -209,11 +235,13 @@ struct scmi_handle { struct scmi_clk_ops *clk_ops; struct scmi_power_ops *power_ops; struct scmi_sensor_ops *sensor_ops; + struct scmi_reset_ops *reset_ops; /* for protocol internal use */ void *perf_priv; void *clk_priv; void *power_priv; void *sensor_priv; + void *reset_priv; }; enum scmi_std_protocol { @@ -223,6 +251,7 @@ enum scmi_std_protocol { SCMI_PROTOCOL_PERF = 0x13, SCMI_PROTOCOL_CLOCK = 0x14, SCMI_PROTOCOL_SENSOR = 0x15, + SCMI_PROTOCOL_RESET = 0x16, }; struct scmi_device { diff --git a/include/linux/security.h b/include/linux/security.h index 429f9f03372b..a8d59d612d27 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -237,9 +237,9 @@ static inline const char *kernel_load_data_id_str(enum kernel_load_data_id id) #ifdef CONFIG_SECURITY -int call_lsm_notifier(enum lsm_event event, void *data); -int register_lsm_notifier(struct notifier_block *nb); -int unregister_lsm_notifier(struct notifier_block *nb); +int call_blocking_lsm_notifier(enum lsm_event event, void *data); +int register_blocking_lsm_notifier(struct notifier_block *nb); +int unregister_blocking_lsm_notifier(struct notifier_block *nb); /* prototypes */ extern int security_init(void); @@ -308,7 +308,8 @@ int security_dentry_create_files_as(struct dentry *dentry, int mode, struct qstr *name, const struct cred *old, struct cred *new); - +int security_path_notify(const struct path *path, u64 mask, + unsigned int obj_type); int security_inode_alloc(struct inode *inode); void security_inode_free(struct inode *inode); int security_inode_init_security(struct inode *inode, struct inode *dir, @@ -436,7 +437,6 @@ int security_ismaclabel(const char *name); int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen); int security_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid); void security_release_secctx(char *secdata, u32 seclen); - void security_inode_invalidate_secctx(struct inode *inode); int security_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen); int security_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen); @@ -444,17 +444,17 @@ int security_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen); int security_locked_down(enum lockdown_reason what); #else /* CONFIG_SECURITY */ -static inline int call_lsm_notifier(enum lsm_event event, void *data) +static inline int call_blocking_lsm_notifier(enum lsm_event event, void *data) { return 0; } -static inline int register_lsm_notifier(struct notifier_block *nb) +static inline int register_blocking_lsm_notifier(struct notifier_block *nb) { return 0; } -static inline int unregister_lsm_notifier(struct notifier_block *nb) +static inline int unregister_blocking_lsm_notifier(struct notifier_block *nb) { return 0; } @@ -676,6 +676,12 @@ static inline int security_move_mount(const struct path *from_path, return 0; } +static inline int security_path_notify(const struct path *path, u64 mask, + unsigned int obj_type) +{ + return 0; +} + static inline int security_inode_alloc(struct inode *inode) { return 0; diff --git a/include/linux/sed-opal.h b/include/linux/sed-opal.h index 3e76b6d7d97f..53c28d750a45 100644 --- a/include/linux/sed-opal.h +++ b/include/linux/sed-opal.h @@ -39,6 +39,9 @@ static inline bool is_sed_ioctl(unsigned int cmd) case IOC_OPAL_ENABLE_DISABLE_MBR: case IOC_OPAL_ERASE_LR: case IOC_OPAL_SECURE_ERASE_LR: + case IOC_OPAL_PSID_REVERT_TPR: + case IOC_OPAL_MBR_DONE: + case IOC_OPAL_WRITE_SHADOW_MBR: return true; } return false; diff --git a/include/linux/seq_file.h b/include/linux/seq_file.h index a121982af0f5..5998e1f4ff06 100644 --- a/include/linux/seq_file.h +++ b/include/linux/seq_file.h @@ -127,6 +127,7 @@ void seq_put_hex_ll(struct seq_file *m, const char *delimiter, unsigned long long v, unsigned int width); void seq_escape(struct seq_file *m, const char *s, const char *esc); +void seq_escape_mem_ascii(struct seq_file *m, const char *src, size_t isz); void seq_hex_dump(struct seq_file *m, const char *prefix_str, int prefix_type, int rowsize, int groupsize, const void *buf, size_t len, diff --git a/include/linux/serial_8250.h b/include/linux/serial_8250.h index 5e0b59422a68..bb2bc99388ca 100644 --- a/include/linux/serial_8250.h +++ b/include/linux/serial_8250.h @@ -110,6 +110,7 @@ struct uart_8250_port { * if no_console_suspend */ unsigned char probe; + struct mctrl_gpios *gpios; #define UART_PROBE_RSA (1 << 0) /* diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index 05b179015d6c..2b78cc734719 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h @@ -32,7 +32,7 @@ struct device; /* * This structure describes all the operations that can be done on the - * physical hardware. See Documentation/serial/driver.rst for details. + * physical hardware. See Documentation/driver-api/serial/driver.rst for details. */ struct uart_ops { unsigned int (*tx_empty)(struct uart_port *); diff --git a/include/linux/sfp.h b/include/linux/sfp.h index d9d9de3fcf8e..1c35428e98bc 100644 --- a/include/linux/sfp.h +++ b/include/linux/sfp.h @@ -464,11 +464,14 @@ enum { struct fwnode_handle; struct ethtool_eeprom; struct ethtool_modinfo; -struct net_device; struct sfp_bus; /** * struct sfp_upstream_ops - upstream operations structure + * @attach: called when the sfp socket driver is bound to the upstream + * (mandatory). + * @detach: called when the sfp socket driver is unbound from the upstream + * (mandatory). * @module_insert: called after a module has been detected to determine * whether the module is supported for the upstream device. * @module_remove: called after the module has been removed. @@ -481,6 +484,8 @@ struct sfp_bus; * been removed. */ struct sfp_upstream_ops { + void (*attach)(void *priv, struct sfp_bus *bus); + void (*detach)(void *priv, struct sfp_bus *bus); int (*module_insert)(void *priv, const struct sfp_eeprom_id *id); void (*module_remove)(void *priv); void (*link_down)(void *priv); @@ -504,7 +509,7 @@ int sfp_get_module_eeprom(struct sfp_bus *bus, struct ethtool_eeprom *ee, void sfp_upstream_start(struct sfp_bus *bus); void sfp_upstream_stop(struct sfp_bus *bus); struct sfp_bus *sfp_register_upstream(struct fwnode_handle *fwnode, - struct net_device *ndev, void *upstream, + void *upstream, const struct sfp_upstream_ops *ops); void sfp_unregister_upstream(struct sfp_bus *bus); #else @@ -549,8 +554,7 @@ static inline void sfp_upstream_stop(struct sfp_bus *bus) } static inline struct sfp_bus *sfp_register_upstream( - struct fwnode_handle *fwnode, - struct net_device *ndev, void *upstream, + struct fwnode_handle *fwnode, void *upstream, const struct sfp_upstream_ops *ops) { return (struct sfp_bus *)-1; diff --git a/include/linux/sha256.h b/include/linux/sha256.h deleted file mode 100644 index 26972b9e92db..000000000000 --- a/include/linux/sha256.h +++ /dev/null @@ -1,28 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Copyright (C) 2014 Red Hat Inc. - * - * Author: Vivek Goyal <vgoyal@redhat.com> - */ - -#ifndef SHA256_H -#define SHA256_H - -#include <linux/types.h> -#include <crypto/sha.h> - -/* - * Stand-alone implementation of the SHA256 algorithm. It is designed to - * have as little dependencies as possible so it can be used in the - * kexec_file purgatory. In other cases you should use the implementation in - * crypto/. - * - * For details see lib/sha256.c - */ - -extern int sha256_init(struct sha256_state *sctx); -extern int sha256_update(struct sha256_state *sctx, const u8 *input, - unsigned int length); -extern int sha256_final(struct sha256_state *sctx, u8 *hash); - -#endif /* SHA256_H */ diff --git a/include/linux/shmem_fs.h b/include/linux/shmem_fs.h index 20d815a33145..de8e4b71e3ba 100644 --- a/include/linux/shmem_fs.h +++ b/include/linux/shmem_fs.h @@ -49,8 +49,9 @@ static inline struct shmem_inode_info *SHMEM_I(struct inode *inode) /* * Functions in mm/shmem.c called directly from elsewhere: */ +extern const struct fs_parameter_description shmem_fs_parameters; extern int shmem_init(void); -extern int shmem_fill_super(struct super_block *sb, void *data, int silent); +extern int shmem_init_fs_context(struct fs_context *fc); extern struct file *shmem_file_setup(const char *name, loff_t size, unsigned long flags); extern struct file *shmem_kernel_file_setup(const char *name, loff_t size, diff --git a/include/linux/shrinker.h b/include/linux/shrinker.h index 9443cafd1969..0f80123650e2 100644 --- a/include/linux/shrinker.h +++ b/include/linux/shrinker.h @@ -69,7 +69,7 @@ struct shrinker { /* These are for internal use */ struct list_head list; -#ifdef CONFIG_MEMCG_KMEM +#ifdef CONFIG_MEMCG /* ID in shrinker_idr */ int id; #endif @@ -81,6 +81,11 @@ struct shrinker { /* Flags */ #define SHRINKER_NUMA_AWARE (1 << 0) #define SHRINKER_MEMCG_AWARE (1 << 1) +/* + * It just makes sense when the shrinker is also MEMCG_AWARE for now, + * non-MEMCG_AWARE shrinker should not have this flag set. + */ +#define SHRINKER_NONSLAB (1 << 2) extern int prealloc_shrinker(struct shrinker *shrinker); extern void register_shrinker_prepared(struct shrinker *shrinker); diff --git a/include/linux/signal.h b/include/linux/signal.h index 78c2bb376954..1a5f88316b08 100644 --- a/include/linux/signal.h +++ b/include/linux/signal.h @@ -273,10 +273,6 @@ extern int group_send_sig_info(int sig, struct kernel_siginfo *info, struct task_struct *p, enum pid_type type); extern int __group_send_sig_info(int, struct kernel_siginfo *, struct task_struct *); extern int sigprocmask(int, sigset_t *, sigset_t *); -extern int set_user_sigmask(const sigset_t __user *usigmask, sigset_t *set, - sigset_t *oldset, size_t sigsetsize); -extern void restore_user_sigmask(const void __user *usigmask, - sigset_t *sigsaved, bool interrupted); extern void set_current_blocked(sigset_t *); extern void __set_current_blocked(const sigset_t *); extern int show_unhandled_signals; @@ -286,6 +282,9 @@ extern void signal_setup_done(int failed, struct ksignal *ksig, int stepping); extern void exit_signals(struct task_struct *tsk); extern void kernel_sigaction(int, __sighandler_t); +#define SIG_KTHREAD ((__force __sighandler_t)2) +#define SIG_KTHREAD_KERNEL ((__force __sighandler_t)3) + static inline void allow_signal(int sig) { /* @@ -293,7 +292,17 @@ static inline void allow_signal(int sig) * know it'll be handled, so that they don't get converted to * SIGKILL or just silently dropped. */ - kernel_sigaction(sig, (__force __sighandler_t)2); + kernel_sigaction(sig, SIG_KTHREAD); +} + +static inline void allow_kernel_signal(int sig) +{ + /* + * Kernel threads handle their own signals. Let the signal code + * know signals sent by the kernel will be handled, so that they + * don't get silently dropped. + */ + kernel_sigaction(sig, SIG_KTHREAD_KERNEL); } static inline void disallow_signal(int sig) diff --git a/include/linux/siox.h b/include/linux/siox.h index a860cb8c1f9d..da7225bf1877 100644 --- a/include/linux/siox.h +++ b/include/linux/siox.h @@ -72,3 +72,13 @@ static inline void siox_driver_unregister(struct siox_driver *sdriver) { return driver_unregister(&sdriver->driver); } + +/* + * module_siox_driver() - Helper macro for drivers that don't do + * anything special in module init/exit. This eliminates a lot of + * boilerplate. Each module may only use this macro once, and + * calling it replaces module_init() and module_exit() + */ +#define module_siox_driver(__siox_driver) \ + module_driver(__siox_driver, siox_driver_register, \ + siox_driver_unregister) diff --git a/include/linux/sizes.h b/include/linux/sizes.h index 1cbb4c4d016e..9874f6f67537 100644 --- a/include/linux/sizes.h +++ b/include/linux/sizes.h @@ -44,5 +44,6 @@ #define SZ_2G 0x80000000 #define SZ_4G _AC(0x100000000, ULL) +#define SZ_64T _AC(0x400000000000, ULL) #endif /* __LINUX_SIZES_H__ */ diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 056f557d5194..907209c0794e 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -14,6 +14,7 @@ #include <linux/compiler.h> #include <linux/time.h> #include <linux/bug.h> +#include <linux/bvec.h> #include <linux/cache.h> #include <linux/rbtree.h> #include <linux/socket.h> @@ -36,6 +37,9 @@ #include <linux/in6.h> #include <linux/if_packet.h> #include <net/flow.h> +#if IS_ENABLED(CONFIG_NF_CONNTRACK) +#include <linux/netfilter/nf_conntrack_common.h> +#endif /* The interface for checksum offload between the stack and networking drivers * is as follows... @@ -243,12 +247,6 @@ struct bpf_prog; union bpf_attr; struct skb_ext; -#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) -struct nf_conntrack { - atomic_t use; -}; -#endif - #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER) struct nf_bridge_info { enum { @@ -278,6 +276,16 @@ struct nf_bridge_info { }; #endif +#if IS_ENABLED(CONFIG_NET_TC_SKB_EXT) +/* Chain in tc_skb_ext will be used to share the tc chain with + * ovs recirc_id. It will be set to the current chain by tc + * and read by ovs to recirc_id. + */ +struct tc_skb_ext { + __u32 chain; +}; +#endif + struct sk_buff_head { /* These two members must be first. */ struct sk_buff *next; @@ -308,58 +316,45 @@ extern int sysctl_max_skb_frags; */ #define GSO_BY_FRAGS 0xFFFF -typedef struct skb_frag_struct skb_frag_t; - -struct skb_frag_struct { - struct { - struct page *p; - } page; -#if (BITS_PER_LONG > 32) || (PAGE_SIZE >= 65536) - __u32 page_offset; - __u32 size; -#else - __u16 page_offset; - __u16 size; -#endif -}; +typedef struct bio_vec skb_frag_t; /** - * skb_frag_size - Returns the size of a skb fragment + * skb_frag_size() - Returns the size of a skb fragment * @frag: skb fragment */ static inline unsigned int skb_frag_size(const skb_frag_t *frag) { - return frag->size; + return frag->bv_len; } /** - * skb_frag_size_set - Sets the size of a skb fragment + * skb_frag_size_set() - Sets the size of a skb fragment * @frag: skb fragment * @size: size of fragment */ static inline void skb_frag_size_set(skb_frag_t *frag, unsigned int size) { - frag->size = size; + frag->bv_len = size; } /** - * skb_frag_size_add - Incrementes the size of a skb fragment by %delta + * skb_frag_size_add() - Increments the size of a skb fragment by @delta * @frag: skb fragment * @delta: value to add */ static inline void skb_frag_size_add(skb_frag_t *frag, int delta) { - frag->size += delta; + frag->bv_len += delta; } /** - * skb_frag_size_sub - Decrements the size of a skb fragment by %delta + * skb_frag_size_sub() - Decrements the size of a skb fragment by @delta * @frag: skb fragment * @delta: value to subtract */ static inline void skb_frag_size_sub(skb_frag_t *frag, int delta) { - frag->size -= delta; + frag->bv_len -= delta; } /** @@ -379,7 +374,7 @@ static inline bool skb_frag_must_loop(struct page *p) * skb_frag_foreach_page - loop over pages in a fragment * * @f: skb frag to operate on - * @f_off: offset from start of f->page.p + * @f_off: offset from start of f->bv_page * @f_len: length from f_off to loop over * @p: (temp var) current page * @p_off: (temp var) offset from start of current page, @@ -916,7 +911,6 @@ static inline bool skb_pfmemalloc(const struct sk_buff *skb) #define SKB_DST_NOREF 1UL #define SKB_DST_PTRMASK ~(SKB_DST_NOREF) -#define SKB_NFCT_PTRMASK ~(7UL) /** * skb_dst - returns skb dst_entry * @skb: buffer @@ -1024,6 +1018,7 @@ static inline bool skb_unref(struct sk_buff *skb) void skb_release_head_state(struct sk_buff *skb); void kfree_skb(struct sk_buff *skb); void kfree_skb_list(struct sk_buff *segs); +void skb_dump(const char *level, const struct sk_buff *skb, bool full_pkt); void skb_tx_error(struct sk_buff *skb); void consume_skb(struct sk_buff *skb); void __consume_stateless_skb(struct sk_buff *skb); @@ -1059,6 +1054,7 @@ struct sk_buff *alloc_skb_with_frags(unsigned long header_len, int max_page_order, int *errcode, gfp_t gfp_mask); +struct sk_buff *alloc_skb_for_msg(struct sk_buff *first); /* Layout of fast clones : [skb1][skb2][fclone_ref] */ struct sk_buff_fclones { @@ -1281,7 +1277,7 @@ static inline int skb_flow_dissector_bpf_prog_detach(const union bpf_attr *attr) struct bpf_flow_dissector; bool bpf_flow_dissect(struct bpf_prog *prog, struct bpf_flow_dissector *ctx, - __be16 proto, int nhoff, int hlen); + __be16 proto, int nhoff, int hlen, unsigned int flags); bool __skb_flow_dissect(const struct net *net, const struct sk_buff *skb, @@ -1319,6 +1315,20 @@ skb_flow_dissect_flow_keys_basic(const struct net *net, data, proto, nhoff, hlen, flags); } +void skb_flow_dissect_meta(const struct sk_buff *skb, + struct flow_dissector *flow_dissector, + void *target_container); + +/* Gets a skb connection tracking info, ctinfo map should be a + * a map of mapsize to translate enum ip_conntrack_info states + * to user states. + */ +void +skb_flow_dissect_ct(const struct sk_buff *skb, + struct flow_dissector *flow_dissector, + void *target_container, + u16 *ctinfo_map, + size_t mapsize); void skb_flow_dissect_tunnel_info(const struct sk_buff *skb, struct flow_dissector *flow_dissector, @@ -1358,6 +1368,14 @@ static inline void skb_copy_hash(struct sk_buff *to, const struct sk_buff *from) to->l4_hash = from->l4_hash; }; +static inline void skb_copy_decrypted(struct sk_buff *to, + const struct sk_buff *from) +{ +#ifdef CONFIG_TLS_DEVICE + to->decrypted = from->decrypted; +#endif +} + #ifdef NET_SKBUFF_DATA_USES_OFFSET static inline unsigned char *skb_end_pointer(const struct sk_buff *skb) { @@ -2073,8 +2091,8 @@ static inline void __skb_fill_page_desc(struct sk_buff *skb, int i, * that not all callers have unique ownership of the page but rely * on page_is_pfmemalloc doing the right thing(tm). */ - frag->page.p = page; - frag->page_offset = off; + frag->bv_page = page; + frag->bv_offset = off; skb_frag_size_set(frag, size); page = compound_head(page); @@ -2854,6 +2872,46 @@ static inline void skb_propagate_pfmemalloc(struct page *page, } /** + * skb_frag_off() - Returns the offset of a skb fragment + * @frag: the paged fragment + */ +static inline unsigned int skb_frag_off(const skb_frag_t *frag) +{ + return frag->bv_offset; +} + +/** + * skb_frag_off_add() - Increments the offset of a skb fragment by @delta + * @frag: skb fragment + * @delta: value to add + */ +static inline void skb_frag_off_add(skb_frag_t *frag, int delta) +{ + frag->bv_offset += delta; +} + +/** + * skb_frag_off_set() - Sets the offset of a skb fragment + * @frag: skb fragment + * @offset: offset of fragment + */ +static inline void skb_frag_off_set(skb_frag_t *frag, unsigned int offset) +{ + frag->bv_offset = offset; +} + +/** + * skb_frag_off_copy() - Sets the offset of a skb fragment from another fragment + * @fragto: skb fragment where offset is set + * @fragfrom: skb fragment offset is copied from + */ +static inline void skb_frag_off_copy(skb_frag_t *fragto, + const skb_frag_t *fragfrom) +{ + fragto->bv_offset = fragfrom->bv_offset; +} + +/** * skb_frag_page - retrieve the page referred to by a paged fragment * @frag: the paged fragment * @@ -2861,7 +2919,7 @@ static inline void skb_propagate_pfmemalloc(struct page *page, */ static inline struct page *skb_frag_page(const skb_frag_t *frag) { - return frag->page.p; + return frag->bv_page; } /** @@ -2919,7 +2977,7 @@ static inline void skb_frag_unref(struct sk_buff *skb, int f) */ static inline void *skb_frag_address(const skb_frag_t *frag) { - return page_address(skb_frag_page(frag)) + frag->page_offset; + return page_address(skb_frag_page(frag)) + skb_frag_off(frag); } /** @@ -2935,7 +2993,18 @@ static inline void *skb_frag_address_safe(const skb_frag_t *frag) if (unlikely(!ptr)) return NULL; - return ptr + frag->page_offset; + return ptr + skb_frag_off(frag); +} + +/** + * skb_frag_page_copy() - sets the page in a fragment from another fragment + * @fragto: skb fragment where page is set + * @fragfrom: skb fragment page is copied from + */ +static inline void skb_frag_page_copy(skb_frag_t *fragto, + const skb_frag_t *fragfrom) +{ + fragto->bv_page = fragfrom->bv_page; } /** @@ -2947,7 +3016,7 @@ static inline void *skb_frag_address_safe(const skb_frag_t *frag) */ static inline void __skb_frag_set_page(skb_frag_t *frag, struct page *page) { - frag->page.p = page; + frag->bv_page = page; } /** @@ -2983,7 +3052,7 @@ static inline dma_addr_t skb_frag_dma_map(struct device *dev, enum dma_data_direction dir) { return dma_map_page(dev, skb_frag_page(frag), - frag->page_offset + offset, size, dir); + skb_frag_off(frag) + offset, size, dir); } static inline struct sk_buff *pskb_copy(struct sk_buff *skb, @@ -3150,10 +3219,10 @@ static inline bool skb_can_coalesce(struct sk_buff *skb, int i, if (skb_zcopy(skb)) return false; if (i) { - const struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[i - 1]; + const skb_frag_t *frag = &skb_shinfo(skb)->frags[i - 1]; return page == skb_frag_page(frag) && - off == frag->page_offset + skb_frag_size(frag); + off == skb_frag_off(frag) + skb_frag_size(frag); } return false; } @@ -3441,6 +3510,10 @@ int skb_ensure_writable(struct sk_buff *skb, int write_len); int __skb_vlan_pop(struct sk_buff *skb, u16 *vlan_tci); int skb_vlan_pop(struct sk_buff *skb); int skb_vlan_push(struct sk_buff *skb, __be16 vlan_proto, u16 vlan_tci); +int skb_mpls_push(struct sk_buff *skb, __be32 mpls_lse, __be16 mpls_proto); +int skb_mpls_pop(struct sk_buff *skb, __be16 next_proto); +int skb_mpls_update_lse(struct sk_buff *skb, __be32 mpls_lse); +int skb_mpls_dec_ttl(struct sk_buff *skb); struct sk_buff *pskb_extract(struct sk_buff *skb, int off, int to_copy, gfp_t gfp); @@ -3914,18 +3987,16 @@ static inline bool __skb_checksum_convert_check(struct sk_buff *skb) return (skb->ip_summed == CHECKSUM_NONE && skb->csum_valid); } -static inline void __skb_checksum_convert(struct sk_buff *skb, - __sum16 check, __wsum pseudo) +static inline void __skb_checksum_convert(struct sk_buff *skb, __wsum pseudo) { skb->csum = ~pseudo; skb->ip_summed = CHECKSUM_COMPLETE; } -#define skb_checksum_try_convert(skb, proto, check, compute_pseudo) \ +#define skb_checksum_try_convert(skb, proto, compute_pseudo) \ do { \ if (__skb_checksum_convert_check(skb)) \ - __skb_checksum_convert(skb, check, \ - compute_pseudo(skb, proto)); \ + __skb_checksum_convert(skb, compute_pseudo(skb, proto)); \ } while (0) static inline void skb_remcsum_adjust_partial(struct sk_buff *skb, void *ptr, @@ -3965,25 +4036,27 @@ static inline void skb_remcsum_process(struct sk_buff *skb, void *ptr, static inline struct nf_conntrack *skb_nfct(const struct sk_buff *skb) { #if IS_ENABLED(CONFIG_NF_CONNTRACK) - return (void *)(skb->_nfct & SKB_NFCT_PTRMASK); + return (void *)(skb->_nfct & NFCT_PTRMASK); #else return NULL; #endif } -#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) -void nf_conntrack_destroy(struct nf_conntrack *nfct); -static inline void nf_conntrack_put(struct nf_conntrack *nfct) +static inline unsigned long skb_get_nfct(const struct sk_buff *skb) { - if (nfct && atomic_dec_and_test(&nfct->use)) - nf_conntrack_destroy(nfct); +#if IS_ENABLED(CONFIG_NF_CONNTRACK) + return skb->_nfct; +#else + return 0UL; +#endif } -static inline void nf_conntrack_get(struct nf_conntrack *nfct) + +static inline void skb_set_nfct(struct sk_buff *skb, unsigned long nfct) { - if (nfct) - atomic_inc(&nfct->use); -} +#if IS_ENABLED(CONFIG_NF_CONNTRACK) + skb->_nfct = nfct; #endif +} #ifdef CONFIG_SKB_EXTENSIONS enum skb_ext_id { @@ -3993,6 +4066,9 @@ enum skb_ext_id { #ifdef CONFIG_XFRM SKB_EXT_SEC_PATH, #endif +#if IS_ENABLED(CONFIG_NET_TC_SKB_EXT) + TC_SKB_EXT, +#endif SKB_EXT_NUM, /* must be last */ }; diff --git a/include/linux/skmsg.h b/include/linux/skmsg.h index 50ced8aba9db..e4b3fb4bb77c 100644 --- a/include/linux/skmsg.h +++ b/include/linux/skmsg.h @@ -354,7 +354,13 @@ static inline void sk_psock_restore_proto(struct sock *sk, sk->sk_write_space = psock->saved_write_space; if (psock->sk_proto) { - sk->sk_prot = psock->sk_proto; + struct inet_connection_sock *icsk = inet_csk(sk); + bool has_ulp = !!icsk->icsk_ulp_data; + + if (has_ulp) + tcp_update_ulp(sk, psock->sk_proto); + else + sk->sk_prot = psock->sk_proto; psock->sk_proto = NULL; } } diff --git a/include/linux/slab.h b/include/linux/slab.h index 9449b19c5f10..ab2b98ad76e1 100644 --- a/include/linux/slab.h +++ b/include/linux/slab.h @@ -16,6 +16,7 @@ #include <linux/overflow.h> #include <linux/types.h> #include <linux/workqueue.h> +#include <linux/percpu-refcount.h> /* @@ -115,6 +116,10 @@ /* Objects are reclaimable */ #define SLAB_RECLAIM_ACCOUNT ((slab_flags_t __force)0x00020000U) #define SLAB_TEMPORARY SLAB_RECLAIM_ACCOUNT /* Objects are short-lived */ + +/* Slab deactivation flag */ +#define SLAB_DEACTIVATED ((slab_flags_t __force)0x10000000U) + /* * ZERO_SIZE_PTR will be returned for zero sized kmalloc requests. * @@ -151,8 +156,7 @@ void kmem_cache_destroy(struct kmem_cache *); int kmem_cache_shrink(struct kmem_cache *); void memcg_create_kmem_cache(struct mem_cgroup *, struct kmem_cache *); -void memcg_deactivate_kmem_caches(struct mem_cgroup *); -void memcg_destroy_kmem_caches(struct mem_cgroup *); +void memcg_deactivate_kmem_caches(struct mem_cgroup *, struct mem_cgroup *); /* * Please use this macro to create slab caches. Simply specify the @@ -184,6 +188,7 @@ void * __must_check __krealloc(const void *, size_t, gfp_t); void * __must_check krealloc(const void *, size_t, gfp_t); void kfree(const void *); void kzfree(const void *); +size_t __ksize(const void *); size_t ksize(const void *); #ifdef CONFIG_HAVE_HARDENED_USERCOPY_ALLOCATOR @@ -590,67 +595,6 @@ static __always_inline void *kmalloc_node(size_t size, gfp_t flags, int node) return __kmalloc_node(size, flags, node); } -struct memcg_cache_array { - struct rcu_head rcu; - struct kmem_cache *entries[0]; -}; - -/* - * This is the main placeholder for memcg-related information in kmem caches. - * Both the root cache and the child caches will have it. For the root cache, - * this will hold a dynamically allocated array large enough to hold - * information about the currently limited memcgs in the system. To allow the - * array to be accessed without taking any locks, on relocation we free the old - * version only after a grace period. - * - * Root and child caches hold different metadata. - * - * @root_cache: Common to root and child caches. NULL for root, pointer to - * the root cache for children. - * - * The following fields are specific to root caches. - * - * @memcg_caches: kmemcg ID indexed table of child caches. This table is - * used to index child cachces during allocation and cleared - * early during shutdown. - * - * @root_caches_node: List node for slab_root_caches list. - * - * @children: List of all child caches. While the child caches are also - * reachable through @memcg_caches, a child cache remains on - * this list until it is actually destroyed. - * - * The following fields are specific to child caches. - * - * @memcg: Pointer to the memcg this cache belongs to. - * - * @children_node: List node for @root_cache->children list. - * - * @kmem_caches_node: List node for @memcg->kmem_caches list. - */ -struct memcg_cache_params { - struct kmem_cache *root_cache; - union { - struct { - struct memcg_cache_array __rcu *memcg_caches; - struct list_head __root_caches_node; - struct list_head children; - bool dying; - }; - struct { - struct mem_cgroup *memcg; - struct list_head children_node; - struct list_head kmem_caches_node; - - void (*deact_fn)(struct kmem_cache *); - union { - struct rcu_head deact_rcu_head; - struct work_struct deact_work; - }; - }; - }; -}; - int memcg_update_all_caches(int num_memcgs); /** diff --git a/include/linux/smp.h b/include/linux/smp.h index a56f08ff3097..6fc856c9eda5 100644 --- a/include/linux/smp.h +++ b/include/linux/smp.h @@ -35,7 +35,7 @@ int smp_call_function_single(int cpuid, smp_call_func_t func, void *info, /* * Call a function on all processors */ -int on_each_cpu(smp_call_func_t func, void *info, int wait); +void on_each_cpu(smp_call_func_t func, void *info, int wait); /* * Call a function on processors specified by mask, which might include @@ -101,7 +101,7 @@ extern void smp_cpus_done(unsigned int max_cpus); /* * Call a function on all other processors */ -int smp_call_function(smp_call_func_t func, void *info, int wait); +void smp_call_function(smp_call_func_t func, void *info, int wait); void smp_call_function_many(const struct cpumask *mask, smp_call_func_t func, void *info, bool wait); @@ -144,9 +144,8 @@ static inline void smp_send_stop(void) { } * These macros fold the SMP functionality into a single CPU system */ #define raw_smp_processor_id() 0 -static inline int up_smp_call_function(smp_call_func_t func, void *info) +static inline void up_smp_call_function(smp_call_func_t func, void *info) { - return 0; } #define smp_call_function(func, info, wait) \ (up_smp_call_function(func, info)) @@ -181,29 +180,46 @@ static inline int get_boot_cpu_id(void) #endif /* !SMP */ -/* - * smp_processor_id(): get the current CPU ID. +/** + * raw_processor_id() - get the current (unstable) CPU id + * + * For then you know what you are doing and need an unstable + * CPU id. + */ + +/** + * smp_processor_id() - get the current (stable) CPU id + * + * This is the normal accessor to the CPU id and should be used + * whenever possible. * - * if DEBUG_PREEMPT is enabled then we check whether it is - * used in a preemption-safe way. (smp_processor_id() is safe - * if it's used in a preemption-off critical section, or in - * a thread that is bound to the current CPU.) + * The CPU id is stable when: * - * NOTE: raw_smp_processor_id() is for internal use only - * (smp_processor_id() is the preferred variant), but in rare - * instances it might also be used to turn off false positives - * (i.e. smp_processor_id() use that the debugging code reports but - * which use for some reason is legal). Don't use this to hack around - * the warning message, as your code might not work under PREEMPT. + * - IRQs are disabled; + * - preemption is disabled; + * - the task is CPU affine. + * + * When CONFIG_DEBUG_PREEMPT; we verify these assumption and WARN + * when smp_processor_id() is used when the CPU id is not stable. + */ + +/* + * Allow the architecture to differentiate between a stable and unstable read. + * For example, x86 uses an IRQ-safe asm-volatile read for the unstable but a + * regular asm read for the stable. */ +#ifndef __smp_processor_id +#define __smp_processor_id(x) raw_smp_processor_id(x) +#endif + #ifdef CONFIG_DEBUG_PREEMPT extern unsigned int debug_smp_processor_id(void); # define smp_processor_id() debug_smp_processor_id() #else -# define smp_processor_id() raw_smp_processor_id() +# define smp_processor_id() __smp_processor_id() #endif -#define get_cpu() ({ preempt_disable(); smp_processor_id(); }) +#define get_cpu() ({ preempt_disable(); __smp_processor_id(); }) #define put_cpu() preempt_enable() /* diff --git a/include/linux/soc/amlogic/meson-canvas.h b/include/linux/soc/amlogic/meson-canvas.h index b4dde2fbeb3f..0cb2a6050d1f 100644 --- a/include/linux/soc/amlogic/meson-canvas.h +++ b/include/linux/soc/amlogic/meson-canvas.h @@ -20,6 +20,7 @@ #define MESON_CANVAS_ENDIAN_SWAP64 0x7 #define MESON_CANVAS_ENDIAN_SWAP128 0xf +struct device; struct meson_canvas; /** diff --git a/include/linux/soc/mediatek/mtk-cmdq.h b/include/linux/soc/mediatek/mtk-cmdq.h index 54ade13a9b15..9618debb9ceb 100644 --- a/include/linux/soc/mediatek/mtk-cmdq.h +++ b/include/linux/soc/mediatek/mtk-cmdq.h @@ -13,9 +13,6 @@ #define CMDQ_NO_TIMEOUT 0xffffffffu -/** cmdq event maximum */ -#define CMDQ_MAX_EVENT 0x3ff - struct cmdq_pkt; struct cmdq_client { @@ -63,26 +60,26 @@ void cmdq_pkt_destroy(struct cmdq_pkt *pkt); /** * cmdq_pkt_write() - append write command to the CMDQ packet * @pkt: the CMDQ packet - * @value: the specified target register value * @subsys: the CMDQ sub system code * @offset: register offset from CMDQ sub system + * @value: the specified target register value * * Return: 0 for success; else the error code is returned */ -int cmdq_pkt_write(struct cmdq_pkt *pkt, u32 value, u32 subsys, u32 offset); +int cmdq_pkt_write(struct cmdq_pkt *pkt, u8 subsys, u16 offset, u32 value); /** * cmdq_pkt_write_mask() - append write command with mask to the CMDQ packet * @pkt: the CMDQ packet - * @value: the specified target register value * @subsys: the CMDQ sub system code * @offset: register offset from CMDQ sub system + * @value: the specified target register value * @mask: the specified target register mask * * Return: 0 for success; else the error code is returned */ -int cmdq_pkt_write_mask(struct cmdq_pkt *pkt, u32 value, - u32 subsys, u32 offset, u32 mask); +int cmdq_pkt_write_mask(struct cmdq_pkt *pkt, u8 subsys, + u16 offset, u32 value, u32 mask); /** * cmdq_pkt_wfe() - append wait for event command to the CMDQ packet @@ -91,7 +88,7 @@ int cmdq_pkt_write_mask(struct cmdq_pkt *pkt, u32 value, * * Return: 0 for success; else the error code is returned */ -int cmdq_pkt_wfe(struct cmdq_pkt *pkt, u32 event); +int cmdq_pkt_wfe(struct cmdq_pkt *pkt, u16 event); /** * cmdq_pkt_clear_event() - append clear event command to the CMDQ packet @@ -100,7 +97,7 @@ int cmdq_pkt_wfe(struct cmdq_pkt *pkt, u32 event); * * Return: 0 for success; else the error code is returned */ -int cmdq_pkt_clear_event(struct cmdq_pkt *pkt, u32 event); +int cmdq_pkt_clear_event(struct cmdq_pkt *pkt, u16 event); /** * cmdq_pkt_flush_async() - trigger CMDQ to asynchronously execute the CMDQ diff --git a/include/linux/soc/nxp/lpc32xx-misc.h b/include/linux/soc/nxp/lpc32xx-misc.h new file mode 100644 index 000000000000..699c6f1e3aab --- /dev/null +++ b/include/linux/soc/nxp/lpc32xx-misc.h @@ -0,0 +1,33 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Author: Kevin Wells <kevin.wells@nxp.com> + * + * Copyright (C) 2010 NXP Semiconductors + */ + +#ifndef __SOC_LPC32XX_MISC_H +#define __SOC_LPC32XX_MISC_H + +#include <linux/types.h> +#include <linux/phy.h> + +#ifdef CONFIG_ARCH_LPC32XX +extern u32 lpc32xx_return_iram(void __iomem **mapbase, dma_addr_t *dmaaddr); +extern void lpc32xx_set_phy_interface_mode(phy_interface_t mode); +extern void lpc32xx_loopback_set(resource_size_t mapbase, int state); +#else +static inline u32 lpc32xx_return_iram(void __iomem **mapbase, dma_addr_t *dmaaddr) +{ + *mapbase = NULL; + *dmaaddr = 0; + return 0; +} +static inline void lpc32xx_set_phy_interface_mode(phy_interface_t mode) +{ +} +static inline void lpc32xx_loopback_set(resource_size_t mapbase, int state) +{ +} +#endif + +#endif /* __SOC_LPC32XX_MISC_H */ diff --git a/include/linux/soc/qcom/mdt_loader.h b/include/linux/soc/qcom/mdt_loader.h index 944b06aefb0f..e600baec6825 100644 --- a/include/linux/soc/qcom/mdt_loader.h +++ b/include/linux/soc/qcom/mdt_loader.h @@ -21,4 +21,6 @@ int qcom_mdt_load_no_init(struct device *dev, const struct firmware *fw, const char *fw_name, int pas_id, void *mem_region, phys_addr_t mem_phys, size_t mem_size, phys_addr_t *reloc_base); +void *qcom_mdt_read_metadata(const struct firmware *fw, size_t *data_len); + #endif diff --git a/include/linux/soc/samsung/exynos-chipid.h b/include/linux/soc/samsung/exynos-chipid.h new file mode 100644 index 000000000000..8bca6763f99c --- /dev/null +++ b/include/linux/soc/samsung/exynos-chipid.h @@ -0,0 +1,52 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2018 Samsung Electronics Co., Ltd. + * http://www.samsung.com/ + * + * Exynos - CHIPID support + */ +#ifndef __LINUX_SOC_EXYNOS_CHIPID_H +#define __LINUX_SOC_EXYNOS_CHIPID_H + +#define EXYNOS_CHIPID_REG_PRO_ID 0x00 +#define EXYNOS_SUBREV_MASK (0xf << 4) +#define EXYNOS_MAINREV_MASK (0xf << 0) +#define EXYNOS_REV_MASK (EXYNOS_SUBREV_MASK | \ + EXYNOS_MAINREV_MASK) +#define EXYNOS_MASK 0xfffff000 + +#define EXYNOS_CHIPID_REG_PKG_ID 0x04 +/* Bit field definitions for EXYNOS_CHIPID_REG_PKG_ID register */ +#define EXYNOS5422_IDS_OFFSET 24 +#define EXYNOS5422_IDS_MASK 0xff +#define EXYNOS5422_USESG_OFFSET 3 +#define EXYNOS5422_USESG_MASK 0x01 +#define EXYNOS5422_SG_OFFSET 0 +#define EXYNOS5422_SG_MASK 0x07 +#define EXYNOS5422_TABLE_OFFSET 8 +#define EXYNOS5422_TABLE_MASK 0x03 +#define EXYNOS5422_SG_A_OFFSET 17 +#define EXYNOS5422_SG_A_MASK 0x0f +#define EXYNOS5422_SG_B_OFFSET 21 +#define EXYNOS5422_SG_B_MASK 0x03 +#define EXYNOS5422_SG_BSIGN_OFFSET 23 +#define EXYNOS5422_SG_BSIGN_MASK 0x01 +#define EXYNOS5422_BIN2_OFFSET 12 +#define EXYNOS5422_BIN2_MASK 0x01 + +#define EXYNOS_CHIPID_REG_LOT_ID 0x14 + +#define EXYNOS_CHIPID_REG_AUX_INFO 0x1c +/* Bit field definitions for EXYNOS_CHIPID_REG_AUX_INFO register */ +#define EXYNOS5422_TMCB_OFFSET 0 +#define EXYNOS5422_TMCB_MASK 0x7f +#define EXYNOS5422_ARM_UP_OFFSET 8 +#define EXYNOS5422_ARM_UP_MASK 0x03 +#define EXYNOS5422_ARM_DN_OFFSET 10 +#define EXYNOS5422_ARM_DN_MASK 0x03 +#define EXYNOS5422_KFC_UP_OFFSET 12 +#define EXYNOS5422_KFC_UP_MASK 0x03 +#define EXYNOS5422_KFC_DN_OFFSET 14 +#define EXYNOS5422_KFC_DN_MASK 0x03 + +#endif /*__LINUX_SOC_EXYNOS_CHIPID_H */ diff --git a/include/linux/soc/ti/ti_sci_protocol.h b/include/linux/soc/ti/ti_sci_protocol.h index 568722a041bf..9531ec823298 100644 --- a/include/linux/soc/ti/ti_sci_protocol.h +++ b/include/linux/soc/ti/ti_sci_protocol.h @@ -97,7 +97,10 @@ struct ti_sci_core_ops { */ struct ti_sci_dev_ops { int (*get_device)(const struct ti_sci_handle *handle, u32 id); + int (*get_device_exclusive)(const struct ti_sci_handle *handle, u32 id); int (*idle_device)(const struct ti_sci_handle *handle, u32 id); + int (*idle_device_exclusive)(const struct ti_sci_handle *handle, + u32 id); int (*put_device)(const struct ti_sci_handle *handle, u32 id); int (*is_valid)(const struct ti_sci_handle *handle, u32 id); int (*get_context_loss_count)(const struct ti_sci_handle *handle, @@ -166,29 +169,29 @@ struct ti_sci_dev_ops { * managed by driver for that purpose. */ struct ti_sci_clk_ops { - int (*get_clock)(const struct ti_sci_handle *handle, u32 did, u8 cid, + int (*get_clock)(const struct ti_sci_handle *handle, u32 did, u32 cid, bool needs_ssc, bool can_change_freq, bool enable_input_term); - int (*idle_clock)(const struct ti_sci_handle *handle, u32 did, u8 cid); - int (*put_clock)(const struct ti_sci_handle *handle, u32 did, u8 cid); - int (*is_auto)(const struct ti_sci_handle *handle, u32 did, u8 cid, + int (*idle_clock)(const struct ti_sci_handle *handle, u32 did, u32 cid); + int (*put_clock)(const struct ti_sci_handle *handle, u32 did, u32 cid); + int (*is_auto)(const struct ti_sci_handle *handle, u32 did, u32 cid, bool *req_state); - int (*is_on)(const struct ti_sci_handle *handle, u32 did, u8 cid, + int (*is_on)(const struct ti_sci_handle *handle, u32 did, u32 cid, bool *req_state, bool *current_state); - int (*is_off)(const struct ti_sci_handle *handle, u32 did, u8 cid, + int (*is_off)(const struct ti_sci_handle *handle, u32 did, u32 cid, bool *req_state, bool *current_state); - int (*set_parent)(const struct ti_sci_handle *handle, u32 did, u8 cid, - u8 parent_id); - int (*get_parent)(const struct ti_sci_handle *handle, u32 did, u8 cid, - u8 *parent_id); + int (*set_parent)(const struct ti_sci_handle *handle, u32 did, u32 cid, + u32 parent_id); + int (*get_parent)(const struct ti_sci_handle *handle, u32 did, u32 cid, + u32 *parent_id); int (*get_num_parents)(const struct ti_sci_handle *handle, u32 did, - u8 cid, u8 *num_parents); + u32 cid, u32 *num_parents); int (*get_best_match_freq)(const struct ti_sci_handle *handle, u32 did, - u8 cid, u64 min_freq, u64 target_freq, + u32 cid, u64 min_freq, u64 target_freq, u64 max_freq, u64 *match_freq); - int (*set_freq)(const struct ti_sci_handle *handle, u32 did, u8 cid, + int (*set_freq)(const struct ti_sci_handle *handle, u32 did, u32 cid, u64 min_freq, u64 target_freq, u64 max_freq); - int (*get_freq)(const struct ti_sci_handle *handle, u32 did, u8 cid, + int (*get_freq)(const struct ti_sci_handle *handle, u32 did, u32 cid, u64 *current_freq); }; @@ -241,12 +244,254 @@ struct ti_sci_rm_irq_ops { u16 global_event, u8 vint_status_bit); }; +/* RA config.addr_lo parameter is valid for RM ring configure TI_SCI message */ +#define TI_SCI_MSG_VALUE_RM_RING_ADDR_LO_VALID BIT(0) +/* RA config.addr_hi parameter is valid for RM ring configure TI_SCI message */ +#define TI_SCI_MSG_VALUE_RM_RING_ADDR_HI_VALID BIT(1) + /* RA config.count parameter is valid for RM ring configure TI_SCI message */ +#define TI_SCI_MSG_VALUE_RM_RING_COUNT_VALID BIT(2) +/* RA config.mode parameter is valid for RM ring configure TI_SCI message */ +#define TI_SCI_MSG_VALUE_RM_RING_MODE_VALID BIT(3) +/* RA config.size parameter is valid for RM ring configure TI_SCI message */ +#define TI_SCI_MSG_VALUE_RM_RING_SIZE_VALID BIT(4) +/* RA config.order_id parameter is valid for RM ring configure TISCI message */ +#define TI_SCI_MSG_VALUE_RM_RING_ORDER_ID_VALID BIT(5) + +#define TI_SCI_MSG_VALUE_RM_ALL_NO_ORDER \ + (TI_SCI_MSG_VALUE_RM_RING_ADDR_LO_VALID | \ + TI_SCI_MSG_VALUE_RM_RING_ADDR_HI_VALID | \ + TI_SCI_MSG_VALUE_RM_RING_COUNT_VALID | \ + TI_SCI_MSG_VALUE_RM_RING_MODE_VALID | \ + TI_SCI_MSG_VALUE_RM_RING_SIZE_VALID) + +/** + * struct ti_sci_rm_ringacc_ops - Ring Accelerator Management operations + * @config: configure the SoC Navigator Subsystem Ring Accelerator ring + * @get_config: get the SoC Navigator Subsystem Ring Accelerator ring + * configuration + */ +struct ti_sci_rm_ringacc_ops { + int (*config)(const struct ti_sci_handle *handle, + u32 valid_params, u16 nav_id, u16 index, + u32 addr_lo, u32 addr_hi, u32 count, u8 mode, + u8 size, u8 order_id + ); + int (*get_config)(const struct ti_sci_handle *handle, + u32 nav_id, u32 index, u8 *mode, + u32 *addr_lo, u32 *addr_hi, u32 *count, + u8 *size, u8 *order_id); +}; + +/** + * struct ti_sci_rm_psil_ops - PSI-L thread operations + * @pair: pair PSI-L source thread to a destination thread. + * If the src_thread is mapped to UDMA tchan, the corresponding channel's + * TCHAN_THRD_ID register is updated. + * If the dst_thread is mapped to UDMA rchan, the corresponding channel's + * RCHAN_THRD_ID register is updated. + * @unpair: unpair PSI-L source thread from a destination thread. + * If the src_thread is mapped to UDMA tchan, the corresponding channel's + * TCHAN_THRD_ID register is cleared. + * If the dst_thread is mapped to UDMA rchan, the corresponding channel's + * RCHAN_THRD_ID register is cleared. + */ +struct ti_sci_rm_psil_ops { + int (*pair)(const struct ti_sci_handle *handle, u32 nav_id, + u32 src_thread, u32 dst_thread); + int (*unpair)(const struct ti_sci_handle *handle, u32 nav_id, + u32 src_thread, u32 dst_thread); +}; + +/* UDMAP channel types */ +#define TI_SCI_RM_UDMAP_CHAN_TYPE_PKT_PBRR 2 +#define TI_SCI_RM_UDMAP_CHAN_TYPE_PKT_PBRR_SB 3 /* RX only */ +#define TI_SCI_RM_UDMAP_CHAN_TYPE_3RDP_PBRR 10 +#define TI_SCI_RM_UDMAP_CHAN_TYPE_3RDP_PBVR 11 +#define TI_SCI_RM_UDMAP_CHAN_TYPE_3RDP_BCOPY_PBRR 12 +#define TI_SCI_RM_UDMAP_CHAN_TYPE_3RDP_BCOPY_PBVR 13 + +#define TI_SCI_RM_UDMAP_RX_FLOW_DESC_HOST 0 +#define TI_SCI_RM_UDMAP_RX_FLOW_DESC_MONO 2 + +#define TI_SCI_RM_UDMAP_CHAN_BURST_SIZE_64_BYTES 1 +#define TI_SCI_RM_UDMAP_CHAN_BURST_SIZE_128_BYTES 2 +#define TI_SCI_RM_UDMAP_CHAN_BURST_SIZE_256_BYTES 3 + +/* UDMAP TX/RX channel valid_params common declarations */ +#define TI_SCI_MSG_VALUE_RM_UDMAP_CH_PAUSE_ON_ERR_VALID BIT(0) +#define TI_SCI_MSG_VALUE_RM_UDMAP_CH_ATYPE_VALID BIT(1) +#define TI_SCI_MSG_VALUE_RM_UDMAP_CH_CHAN_TYPE_VALID BIT(2) +#define TI_SCI_MSG_VALUE_RM_UDMAP_CH_FETCH_SIZE_VALID BIT(3) +#define TI_SCI_MSG_VALUE_RM_UDMAP_CH_CQ_QNUM_VALID BIT(4) +#define TI_SCI_MSG_VALUE_RM_UDMAP_CH_PRIORITY_VALID BIT(5) +#define TI_SCI_MSG_VALUE_RM_UDMAP_CH_QOS_VALID BIT(6) +#define TI_SCI_MSG_VALUE_RM_UDMAP_CH_ORDER_ID_VALID BIT(7) +#define TI_SCI_MSG_VALUE_RM_UDMAP_CH_SCHED_PRIORITY_VALID BIT(8) +#define TI_SCI_MSG_VALUE_RM_UDMAP_CH_BURST_SIZE_VALID BIT(14) + +/** + * Configures a Navigator Subsystem UDMAP transmit channel + * + * Configures a Navigator Subsystem UDMAP transmit channel registers. + * See @ti_sci_msg_rm_udmap_tx_ch_cfg_req + */ +struct ti_sci_msg_rm_udmap_tx_ch_cfg { + u32 valid_params; +#define TI_SCI_MSG_VALUE_RM_UDMAP_CH_TX_FILT_EINFO_VALID BIT(9) +#define TI_SCI_MSG_VALUE_RM_UDMAP_CH_TX_FILT_PSWORDS_VALID BIT(10) +#define TI_SCI_MSG_VALUE_RM_UDMAP_CH_TX_SUPR_TDPKT_VALID BIT(11) +#define TI_SCI_MSG_VALUE_RM_UDMAP_CH_TX_CREDIT_COUNT_VALID BIT(12) +#define TI_SCI_MSG_VALUE_RM_UDMAP_CH_TX_FDEPTH_VALID BIT(13) + u16 nav_id; + u16 index; + u8 tx_pause_on_err; + u8 tx_filt_einfo; + u8 tx_filt_pswords; + u8 tx_atype; + u8 tx_chan_type; + u8 tx_supr_tdpkt; + u16 tx_fetch_size; + u8 tx_credit_count; + u16 txcq_qnum; + u8 tx_priority; + u8 tx_qos; + u8 tx_orderid; + u16 fdepth; + u8 tx_sched_priority; + u8 tx_burst_size; +}; + +/** + * Configures a Navigator Subsystem UDMAP receive channel + * + * Configures a Navigator Subsystem UDMAP receive channel registers. + * See @ti_sci_msg_rm_udmap_rx_ch_cfg_req + */ +struct ti_sci_msg_rm_udmap_rx_ch_cfg { + u32 valid_params; +#define TI_SCI_MSG_VALUE_RM_UDMAP_CH_RX_FLOWID_START_VALID BIT(9) +#define TI_SCI_MSG_VALUE_RM_UDMAP_CH_RX_FLOWID_CNT_VALID BIT(10) +#define TI_SCI_MSG_VALUE_RM_UDMAP_CH_RX_IGNORE_SHORT_VALID BIT(11) +#define TI_SCI_MSG_VALUE_RM_UDMAP_CH_RX_IGNORE_LONG_VALID BIT(12) + u16 nav_id; + u16 index; + u16 rx_fetch_size; + u16 rxcq_qnum; + u8 rx_priority; + u8 rx_qos; + u8 rx_orderid; + u8 rx_sched_priority; + u16 flowid_start; + u16 flowid_cnt; + u8 rx_pause_on_err; + u8 rx_atype; + u8 rx_chan_type; + u8 rx_ignore_short; + u8 rx_ignore_long; + u8 rx_burst_size; +}; + +/** + * Configures a Navigator Subsystem UDMAP receive flow + * + * Configures a Navigator Subsystem UDMAP receive flow's registers. + * See @tis_ci_msg_rm_udmap_flow_cfg_req + */ +struct ti_sci_msg_rm_udmap_flow_cfg { + u32 valid_params; +#define TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_EINFO_PRESENT_VALID BIT(0) +#define TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_PSINFO_PRESENT_VALID BIT(1) +#define TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_ERROR_HANDLING_VALID BIT(2) +#define TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_DESC_TYPE_VALID BIT(3) +#define TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_SOP_OFFSET_VALID BIT(4) +#define TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_DEST_QNUM_VALID BIT(5) +#define TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_SRC_TAG_HI_VALID BIT(6) +#define TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_SRC_TAG_LO_VALID BIT(7) +#define TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_DEST_TAG_HI_VALID BIT(8) +#define TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_DEST_TAG_LO_VALID BIT(9) +#define TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_SRC_TAG_HI_SEL_VALID BIT(10) +#define TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_SRC_TAG_LO_SEL_VALID BIT(11) +#define TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_DEST_TAG_HI_SEL_VALID BIT(12) +#define TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_DEST_TAG_LO_SEL_VALID BIT(13) +#define TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_FDQ0_SZ0_QNUM_VALID BIT(14) +#define TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_FDQ1_QNUM_VALID BIT(15) +#define TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_FDQ2_QNUM_VALID BIT(16) +#define TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_FDQ3_QNUM_VALID BIT(17) +#define TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_PS_LOCATION_VALID BIT(18) + u16 nav_id; + u16 flow_index; + u8 rx_einfo_present; + u8 rx_psinfo_present; + u8 rx_error_handling; + u8 rx_desc_type; + u16 rx_sop_offset; + u16 rx_dest_qnum; + u8 rx_src_tag_hi; + u8 rx_src_tag_lo; + u8 rx_dest_tag_hi; + u8 rx_dest_tag_lo; + u8 rx_src_tag_hi_sel; + u8 rx_src_tag_lo_sel; + u8 rx_dest_tag_hi_sel; + u8 rx_dest_tag_lo_sel; + u16 rx_fdq0_sz0_qnum; + u16 rx_fdq1_qnum; + u16 rx_fdq2_qnum; + u16 rx_fdq3_qnum; + u8 rx_ps_location; +}; + +/** + * struct ti_sci_rm_udmap_ops - UDMA Management operations + * @tx_ch_cfg: configure SoC Navigator Subsystem UDMA transmit channel. + * @rx_ch_cfg: configure SoC Navigator Subsystem UDMA receive channel. + * @rx_flow_cfg1: configure SoC Navigator Subsystem UDMA receive flow. + */ +struct ti_sci_rm_udmap_ops { + int (*tx_ch_cfg)(const struct ti_sci_handle *handle, + const struct ti_sci_msg_rm_udmap_tx_ch_cfg *params); + int (*rx_ch_cfg)(const struct ti_sci_handle *handle, + const struct ti_sci_msg_rm_udmap_rx_ch_cfg *params); + int (*rx_flow_cfg)(const struct ti_sci_handle *handle, + const struct ti_sci_msg_rm_udmap_flow_cfg *params); +}; + +/** + * struct ti_sci_proc_ops - Processor Control operations + * @request: Request to control a physical processor. The requesting host + * should be in the processor access list + * @release: Relinquish a physical processor control + * @handover: Handover a physical processor control to another host + * in the permitted list + * @set_config: Set base configuration of a processor + * @set_control: Setup limited control flags in specific cases + * @get_status: Get the state of physical processor + * + * NOTE: The following paramteres are generic in nature for all these ops, + * -handle: Pointer to TI SCI handle as retrieved by *ti_sci_get_handle + * -pid: Processor ID + * -hid: Host ID + */ +struct ti_sci_proc_ops { + int (*request)(const struct ti_sci_handle *handle, u8 pid); + int (*release)(const struct ti_sci_handle *handle, u8 pid); + int (*handover)(const struct ti_sci_handle *handle, u8 pid, u8 hid); + int (*set_config)(const struct ti_sci_handle *handle, u8 pid, + u64 boot_vector, u32 cfg_set, u32 cfg_clr); + int (*set_control)(const struct ti_sci_handle *handle, u8 pid, + u32 ctrl_set, u32 ctrl_clr); + int (*get_status)(const struct ti_sci_handle *handle, u8 pid, + u64 *boot_vector, u32 *cfg_flags, u32 *ctrl_flags, + u32 *status_flags); +}; + /** * struct ti_sci_ops - Function support for TI SCI * @dev_ops: Device specific operations * @clk_ops: Clock specific operations * @rm_core_ops: Resource management core operations. * @rm_irq_ops: IRQ management specific operations + * @proc_ops: Processor Control specific operations */ struct ti_sci_ops { struct ti_sci_core_ops core_ops; @@ -254,6 +499,10 @@ struct ti_sci_ops { struct ti_sci_clk_ops clk_ops; struct ti_sci_rm_core_ops rm_core_ops; struct ti_sci_rm_irq_ops rm_irq_ops; + struct ti_sci_rm_ringacc_ops rm_ring_ops; + struct ti_sci_rm_psil_ops rm_psil_ops; + struct ti_sci_rm_udmap_ops rm_udmap_ops; + struct ti_sci_proc_ops proc_ops; }; /** diff --git a/include/linux/socket.h b/include/linux/socket.h index b57cd8bf96e2..fc0bed59fc84 100644 --- a/include/linux/socket.h +++ b/include/linux/socket.h @@ -12,6 +12,7 @@ struct pid; struct cred; +struct socket; #define __sockaddr_check_size(size) \ BUILD_BUG_ON(((size) > sizeof(struct __kernel_sockaddr_storage))) @@ -291,6 +292,9 @@ struct ucred { #define MSG_BATCH 0x40000 /* sendmmsg(): more messages coming */ #define MSG_EOF MSG_FIN #define MSG_NO_SHARED_FRAGS 0x80000 /* sendpage() internal : page frags are not shared */ +#define MSG_SENDPAGE_DECRYPTED 0x100000 /* sendpage() internal : page may carry + * plain text and require encryption + */ #define MSG_ZEROCOPY 0x4000000 /* Use user data in kernel path */ #define MSG_FASTOPEN 0x20000000 /* Send data in TCP SYN */ @@ -374,6 +378,12 @@ extern int __sys_recvmmsg(int fd, struct mmsghdr __user *mmsg, extern int __sys_sendmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen, unsigned int flags, bool forbid_cmsg_compat); +extern long __sys_sendmsg_sock(struct socket *sock, + struct user_msghdr __user *msg, + unsigned int flags); +extern long __sys_recvmsg_sock(struct socket *sock, + struct user_msghdr __user *msg, + unsigned int flags); /* helpers which do the actual work for syscalls */ extern int __sys_recvfrom(int fd, void __user *ubuf, size_t size, diff --git a/include/linux/sort.h b/include/linux/sort.h index 2b99a5dd073d..61b96d0ebc44 100644 --- a/include/linux/sort.h +++ b/include/linux/sort.h @@ -4,6 +4,11 @@ #include <linux/types.h> +void sort_r(void *base, size_t num, size_t size, + int (*cmp)(const void *, const void *, const void *), + void (*swap)(void *, void *, int), + const void *priv); + void sort(void *base, size_t num, size_t size, int (*cmp)(const void *, const void *), void (*swap)(void *, void *, int)); diff --git a/include/linux/soundwire/sdw.h b/include/linux/soundwire/sdw.h index 35662d9c2c62..ea787201c3ac 100644 --- a/include/linux/soundwire/sdw.h +++ b/include/linux/soundwire/sdw.h @@ -4,6 +4,8 @@ #ifndef __SOUNDWIRE_H #define __SOUNDWIRE_H +#include <linux/mod_devicetable.h> + struct sdw_bus; struct sdw_slave; @@ -41,6 +43,31 @@ struct sdw_slave; #define SDW_DAI_ID_RANGE_START 100 #define SDW_DAI_ID_RANGE_END 200 +enum { + SDW_PORT_DIRN_SINK = 0, + SDW_PORT_DIRN_SOURCE, + SDW_PORT_DIRN_MAX, +}; + +/* + * constants for flow control, ports and transport + * + * these are bit masks as devices can have multiple capabilities + */ + +/* + * flow modes for SDW port. These can be isochronous, tx controlled, + * rx controlled or async + */ +#define SDW_PORT_FLOW_MODE_ISOCH 0 +#define SDW_PORT_FLOW_MODE_TX_CNTRL BIT(0) +#define SDW_PORT_FLOW_MODE_RX_CNTRL BIT(1) +#define SDW_PORT_FLOW_MODE_ASYNC GENMASK(1, 0) + +/* sample packaging for block. It can be per port or per channel */ +#define SDW_BLOCK_PACKG_PER_PORT BIT(0) +#define SDW_BLOCK_PACKG_PER_CH BIT(1) + /** * enum sdw_slave_status - Slave status * @SDW_SLAVE_UNATTACHED: Slave is not attached with the bus. @@ -76,6 +103,14 @@ enum sdw_command_response { SDW_CMD_FAIL_OTHER = 4, }; +/* block group count enum */ +enum sdw_dpn_grouping { + SDW_BLK_GRP_CNT_1 = 0, + SDW_BLK_GRP_CNT_2 = 1, + SDW_BLK_GRP_CNT_3 = 2, + SDW_BLK_GRP_CNT_4 = 3, +}; + /** * enum sdw_stream_type: data stream type * @@ -100,6 +135,26 @@ enum sdw_data_direction { SDW_DATA_DIR_TX = 1, }; +/** + * enum sdw_port_data_mode: Data Port mode + * + * @SDW_PORT_DATA_MODE_NORMAL: Normal data mode where audio data is received + * and transmitted. + * @SDW_PORT_DATA_MODE_STATIC_1: Simple test mode which uses static value of + * logic 1. The encoding will result in signal transitions at every bitslot + * owned by this Port + * @SDW_PORT_DATA_MODE_STATIC_0: Simple test mode which uses static value of + * logic 0. The encoding will result in no signal transitions + * @SDW_PORT_DATA_MODE_PRBS: Test mode which uses a PRBS generator to produce + * a pseudo random data pattern that is transferred + */ +enum sdw_port_data_mode { + SDW_PORT_DATA_MODE_NORMAL = 0, + SDW_PORT_DATA_MODE_STATIC_1 = 1, + SDW_PORT_DATA_MODE_STATIC_0 = 2, + SDW_PORT_DATA_MODE_PRBS = 3, +}; + /* * SDW properties, defined in MIPI DisCo spec v1.0 */ @@ -153,10 +208,11 @@ enum sdw_clk_stop_mode { * (inclusive) * @num_words: number of wordlengths supported * @words: wordlengths supported - * @flow_controlled: Slave implementation results in an OK_NotReady + * @BRA_flow_controlled: Slave implementation results in an OK_NotReady * response * @simple_ch_prep_sm: If channel prepare sequence is required - * @device_interrupts: If implementation-defined interrupts are supported + * @imp_def_interrupts: If set, each bit corresponds to support for + * implementation-defined interrupts * * The wordlengths are specified by Spec as max, min AND number of * discrete values, implementation can define based on the wordlengths they @@ -167,9 +223,9 @@ struct sdw_dp0_prop { u32 min_word; u32 num_words; u32 *words; - bool flow_controlled; + bool BRA_flow_controlled; bool simple_ch_prep_sm; - bool device_interrupts; + bool imp_def_interrupts; }; /** @@ -219,7 +275,7 @@ struct sdw_dpn_audio_mode { * @simple_ch_prep_sm: If the port supports simplified channel prepare state * machine * @ch_prep_timeout: Port-specific timeout value, in milliseconds - * @device_interrupts: If set, each bit corresponds to support for + * @imp_def_interrupts: If set, each bit corresponds to support for * implementation-defined interrupts * @max_ch: Maximum channels supported * @min_ch: Minimum channels supported @@ -244,7 +300,7 @@ struct sdw_dpn_prop { u32 max_grouping; bool simple_ch_prep_sm; u32 ch_prep_timeout; - u32 device_interrupts; + u32 imp_def_interrupts; u32 max_ch; u32 min_ch; u32 num_ch; @@ -311,36 +367,36 @@ struct sdw_slave_prop { /** * struct sdw_master_prop - Master properties * @revision: MIPI spec version of the implementation - * @master_count: Number of masters - * @clk_stop_mode: Bitmap for Clock Stop modes supported - * @max_freq: Maximum Bus clock frequency, in Hz + * @clk_stop_modes: Bitmap, bit N set when clock-stop-modeN supported + * @max_clk_freq: Maximum Bus clock frequency, in Hz * @num_clk_gears: Number of clock gears supported * @clk_gears: Clock gears supported - * @num_freq: Number of clock frequencies supported, in Hz - * @freq: Clock frequencies supported, in Hz + * @num_clk_freq: Number of clock frequencies supported, in Hz + * @clk_freq: Clock frequencies supported, in Hz * @default_frame_rate: Controller default Frame rate, in Hz * @default_row: Number of rows * @default_col: Number of columns - * @dynamic_frame: Dynamic frame supported + * @dynamic_frame: Dynamic frame shape supported * @err_threshold: Number of times that software may retry sending a single * command - * @dpn_prop: Data Port N properties + * @mclk_freq: clock reference passed to SoundWire Master, in Hz. + * @hw_disabled: if true, the Master is not functional, typically due to pin-mux */ struct sdw_master_prop { u32 revision; - u32 master_count; - enum sdw_clk_stop_mode clk_stop_mode; - u32 max_freq; + u32 clk_stop_modes; + u32 max_clk_freq; u32 num_clk_gears; u32 *clk_gears; - u32 num_freq; - u32 *freq; + u32 num_clk_freq; + u32 *clk_freq; u32 default_frame_rate; u32 default_row; u32 default_col; bool dynamic_frame; u32 err_threshold; - struct sdw_dpn_prop *dpn_prop; + u32 mclk_freq; + bool hw_disabled; }; int sdw_master_read_prop(struct sdw_bus *bus); @@ -488,6 +544,7 @@ struct sdw_slave_ops { * @bus: Bus handle * @ops: Slave callback ops * @prop: Slave properties + * @debugfs: Slave debugfs * @node: node for bus list * @port_ready: Port ready completion flag for each Slave port * @dev_num: Device Number assigned by Bus @@ -499,6 +556,9 @@ struct sdw_slave { struct sdw_bus *bus; const struct sdw_slave_ops *ops; struct sdw_slave_prop prop; +#ifdef CONFIG_DEBUG_FS + struct dentry *debugfs; +#endif struct list_head node; struct completion *port_ready; u16 dev_num; @@ -668,6 +728,7 @@ struct sdw_master_ops { * Bit set implies used number, bit clear implies unused number. * @bus_lock: bus lock * @msg_lock: message lock + * @compute_params: points to Bus resource management implementation * @ops: Master callback ops * @port_ops: Master port callback ops * @params: Current bus parameters @@ -675,6 +736,7 @@ struct sdw_master_ops { * @m_rt_list: List of Master instance of all stream(s) running on Bus. This * is used to compute and program bus bandwidth, clock, frame shape, * transport and port parameters + * @debugfs: Bus debugfs * @defer_msg: Defer message * @clk_stop_timeout: Clock stop timeout computed * @bank_switch_timeout: Bank switch timeout computed @@ -689,11 +751,15 @@ struct sdw_bus { DECLARE_BITMAP(assigned, SDW_MAX_DEVICES); struct mutex bus_lock; struct mutex msg_lock; + int (*compute_params)(struct sdw_bus *bus); const struct sdw_master_ops *ops; const struct sdw_master_port_ops *port_ops; struct sdw_bus_params params; struct sdw_master_prop prop; struct list_head m_rt_list; +#ifdef CONFIG_DEBUG_FS + struct dentry *debugfs; +#endif struct sdw_defer defer_msg; unsigned int clk_stop_timeout; u32 bank_switch_timeout; @@ -778,7 +844,7 @@ struct sdw_stream_params { * @m_rt_count: Count of Master runtime(s) in this stream */ struct sdw_stream_runtime { - char *name; + const char *name; struct sdw_stream_params params; enum sdw_stream_state state; enum sdw_stream_type type; @@ -786,7 +852,7 @@ struct sdw_stream_runtime { int m_rt_count; }; -struct sdw_stream_runtime *sdw_alloc_stream(char *stream_name); +struct sdw_stream_runtime *sdw_alloc_stream(const char *stream_name); void sdw_release_stream(struct sdw_stream_runtime *stream); int sdw_stream_add_master(struct sdw_bus *bus, struct sdw_stream_config *stream_config, diff --git a/include/linux/soundwire/sdw_intel.h b/include/linux/soundwire/sdw_intel.h index 4d70da45363d..c9427cb6020b 100644 --- a/include/linux/soundwire/sdw_intel.h +++ b/include/linux/soundwire/sdw_intel.h @@ -8,6 +8,7 @@ * struct sdw_intel_ops: Intel audio driver callback ops * * @config_stream: configure the stream with the hw_params + * the first argument containing the context is mandatory */ struct sdw_intel_ops { int (*config_stream)(void *arg, void *substream, diff --git a/include/linux/soundwire/sdw_type.h b/include/linux/soundwire/sdw_type.h index 9c756b5a0dfe..aaa7f4267c14 100644 --- a/include/linux/soundwire/sdw_type.h +++ b/include/linux/soundwire/sdw_type.h @@ -16,4 +16,15 @@ void sdw_unregister_driver(struct sdw_driver *drv); int sdw_slave_modalias(const struct sdw_slave *slave, char *buf, size_t size); +/** + * module_sdw_driver() - Helper macro for registering a Soundwire driver + * @__sdw_driver: soundwire slave driver struct + * + * Helper macro for Soundwire drivers which do not do anything special in + * module init/exit. This eliminates a lot of boilerplate. Each module may only + * use this macro once, and calling it replaces module_init() and module_exit() + */ +#define module_sdw_driver(__sdw_driver) \ + module_driver(__sdw_driver, sdw_register_driver, \ + sdw_unregister_driver) #endif /* __SOUNDWIRE_TYPES_H */ diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h index 053abd22ad31..af4f265d0f67 100644 --- a/include/linux/spi/spi.h +++ b/include/linux/spi/spi.h @@ -109,6 +109,7 @@ void spi_statistics_add_transfer_stats(struct spi_statistics *stats, * This may be changed by the device's driver, or left at the * default (0) indicating protocol words are eight bit bytes. * The spi_transfer.bits_per_word can override this for each transfer. + * @rt: Make the pump thread real time priority. * @irq: Negative, or the number passed to request_irq() to receive * interrupts from this device. * @controller_state: Controller's runtime state @@ -143,6 +144,7 @@ struct spi_device { u32 max_speed_hz; u8 chip_select; u8 bits_per_word; + bool rt; u32 mode; #define SPI_CPHA 0x01 /* clock phase */ #define SPI_CPOL 0x02 /* clock polarity */ @@ -735,6 +737,9 @@ extern void spi_res_release(struct spi_controller *ctlr, * @bits_per_word: select a bits_per_word other than the device default * for this transfer. If 0 the default (from @spi_device) is used. * @cs_change: affects chipselect after this transfer completes + * @cs_change_delay: delay between cs deassert and assert when + * @cs_change is set and @spi_transfer is not the last in @spi_message + * @cs_change_delay_unit: unit of cs_change_delay * @delay_usecs: microseconds to delay after this transfer before * (optionally) changing the chipselect status, then starting * the next transfer or completing this @spi_message. @@ -742,6 +747,9 @@ extern void spi_res_release(struct spi_controller *ctlr, * (set by bits_per_word) transmission. * @word_delay: clock cycles to inter word delay after each word size * (set by bits_per_word) transmission. + * @effective_speed_hz: the effective SCK-speed that was used to + * transfer this transfer. Set to 0 if the spi bus driver does + * not support it. * @transfer_list: transfers are sequenced through @spi_message.transfers * @tx_sg: Scatterlist for transmit, currently not for client use * @rx_sg: Scatterlist for receive, currently not for client use @@ -824,9 +832,16 @@ struct spi_transfer { u8 bits_per_word; u8 word_delay_usecs; u16 delay_usecs; + u16 cs_change_delay; + u8 cs_change_delay_unit; +#define SPI_DELAY_UNIT_USECS 0 +#define SPI_DELAY_UNIT_NSECS 1 +#define SPI_DELAY_UNIT_SCK 2 u32 speed_hz; u16 word_delay; + u32 effective_speed_hz; + struct list_head transfer_list; }; @@ -967,6 +982,8 @@ static inline void spi_message_free(struct spi_message *m) kfree(m); } +extern void spi_set_cs_timing(struct spi_device *spi, u8 setup, u8 hold, u8 inactive_dly); + extern int spi_setup(struct spi_device *spi); extern int spi_async(struct spi_device *spi, struct spi_message *message); extern int spi_async_locked(struct spi_device *spi, @@ -997,6 +1014,26 @@ spi_max_transfer_size(struct spi_device *spi) return min(tr_max, msg_max); } +/** + * spi_is_bpw_supported - Check if bits per word is supported + * @spi: SPI device + * @bpw: Bits per word + * + * This function checks to see if the SPI controller supports @bpw. + * + * Returns: + * True if @bpw is supported, false otherwise. + */ +static inline bool spi_is_bpw_supported(struct spi_device *spi, u32 bpw) +{ + u32 bpw_mask = spi->master->bits_per_word_mask; + + if (bpw == 8 || (bpw <= 32 && bpw_mask & SPI_BPW_MASK(bpw))) + return true; + + return false; +} + /*---------------------------------------------------------------------------*/ /* SPI transfer replacement methods which make use of spi_res */ diff --git a/include/linux/spinlock.h b/include/linux/spinlock.h index ed7c4d6b8235..031ce8617df8 100644 --- a/include/linux/spinlock.h +++ b/include/linux/spinlock.h @@ -214,7 +214,7 @@ static inline void do_raw_spin_unlock(raw_spinlock_t *lock) __releases(lock) /* * Define the various spin_lock methods. Note we define these - * regardless of whether CONFIG_SMP or CONFIG_PREEMPT are set. The + * regardless of whether CONFIG_SMP or CONFIG_PREEMPTION are set. The * various methods are defined as nops in the case they are not * required. */ diff --git a/include/linux/spinlock_api_smp.h b/include/linux/spinlock_api_smp.h index 42dfab89e740..b762eaba4cdf 100644 --- a/include/linux/spinlock_api_smp.h +++ b/include/linux/spinlock_api_smp.h @@ -96,7 +96,7 @@ static inline int __raw_spin_trylock(raw_spinlock_t *lock) /* * If lockdep is enabled then we use the non-preemption spin-ops - * even on CONFIG_PREEMPT, because lockdep assumes that interrupts are + * even on CONFIG_PREEMPTION, because lockdep assumes that interrupts are * not re-enabled during lock-acquire (which the preempt-spin-ops do): */ #if !defined(CONFIG_GENERIC_LOCKBREAK) || defined(CONFIG_DEBUG_LOCK_ALLOC) diff --git a/include/linux/srcutree.h b/include/linux/srcutree.h index 7f7c8c050f63..9cfcc8a756ae 100644 --- a/include/linux/srcutree.h +++ b/include/linux/srcutree.h @@ -120,9 +120,17 @@ struct srcu_struct { * * See include/linux/percpu-defs.h for the rules on per-CPU variables. */ -#define __DEFINE_SRCU(name, is_static) \ - static DEFINE_PER_CPU(struct srcu_data, name##_srcu_data);\ - is_static struct srcu_struct name = __SRCU_STRUCT_INIT(name, name##_srcu_data) +#ifdef MODULE +# define __DEFINE_SRCU(name, is_static) \ + is_static struct srcu_struct name; \ + struct srcu_struct * const __srcu_struct_##name \ + __section("___srcu_struct_ptrs") = &name +#else +# define __DEFINE_SRCU(name, is_static) \ + static DEFINE_PER_CPU(struct srcu_data, name##_srcu_data); \ + is_static struct srcu_struct name = \ + __SRCU_STRUCT_INIT(name, name##_srcu_data) +#endif #define DEFINE_SRCU(name) __DEFINE_SRCU(name, /* not static */) #define DEFINE_STATIC_SRCU(name) __DEFINE_SRCU(name, static) diff --git a/include/linux/stacktrace.h b/include/linux/stacktrace.h index f0cfd12cb45e..83bd8cb475d7 100644 --- a/include/linux/stacktrace.h +++ b/include/linux/stacktrace.h @@ -9,9 +9,9 @@ struct task_struct; struct pt_regs; #ifdef CONFIG_STACKTRACE -void stack_trace_print(unsigned long *trace, unsigned int nr_entries, +void stack_trace_print(const unsigned long *trace, unsigned int nr_entries, int spaces); -int stack_trace_snprint(char *buf, size_t size, unsigned long *entries, +int stack_trace_snprint(char *buf, size_t size, const unsigned long *entries, unsigned int nr_entries, int spaces); unsigned int stack_trace_save(unsigned long *store, unsigned int size, unsigned int skipnr); diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h index 1a0bb622cf10..dc60d03c4b60 100644 --- a/include/linux/stmmac.h +++ b/include/linux/stmmac.h @@ -78,14 +78,10 @@ /* Platfrom data for platform device structure's platform_data field */ struct stmmac_mdio_bus_data { - int (*phy_reset)(void *priv); unsigned int phy_mask; int *irqs; int probed_phy_irq; -#ifdef CONFIG_OF - int reset_gpio, active_low; - u32 delays[3]; -#endif + bool needs_reset; }; struct stmmac_dma_cfg { @@ -135,8 +131,10 @@ struct plat_stmmacenet_data { int bus_id; int phy_addr; int interface; + int phy_interface; struct stmmac_mdio_bus_data *mdio_bus_data; struct device_node *phy_node; + struct device_node *phylink_node; struct device_node *mdio_node; struct stmmac_dma_cfg *dma_cfg; int clk_csr; @@ -171,11 +169,13 @@ struct plat_stmmacenet_data { struct clk *clk_ptp_ref; unsigned int clk_ptp_rate; unsigned int clk_ref_rate; + s32 ptp_max_adj; struct reset_control *stmmac_rst; struct stmmac_axi *axi; int has_gmac4; bool has_sun8i; bool tso_en; + int rss_en; int mac_port_sel_speed; bool en_tx_lpi_clockgating; int has_xgmac; diff --git a/include/linux/stop_machine.h b/include/linux/stop_machine.h index 6d3635c86dbe..f9a0c6189852 100644 --- a/include/linux/stop_machine.h +++ b/include/linux/stop_machine.h @@ -36,6 +36,7 @@ int stop_cpus(const struct cpumask *cpumask, cpu_stop_fn_t fn, void *arg); int try_stop_cpus(const struct cpumask *cpumask, cpu_stop_fn_t fn, void *arg); void stop_machine_park(int cpu); void stop_machine_unpark(int cpu); +void stop_machine_yield(const struct cpumask *cpumask); #else /* CONFIG_SMP */ diff --git a/include/linux/string.h b/include/linux/string.h index 4deb11f7976b..b2f9df7f0761 100644 --- a/include/linux/string.h +++ b/include/linux/string.h @@ -474,8 +474,9 @@ static inline void memcpy_and_pad(void *dest, size_t dest_len, * But this can lead to bugs due to typos, or if prefix is a pointer * and not a constant. Instead use str_has_prefix(). * - * Returns: 0 if @str does not start with @prefix - strlen(@prefix) if @str does start with @prefix + * Returns: + * * strlen(@prefix) if @str starts with @prefix + * * 0 if @str does not start with @prefix */ static __always_inline size_t str_has_prefix(const char *str, const char *prefix) { diff --git a/include/linux/string_helpers.h b/include/linux/string_helpers.h index d23c5030901a..c28955132234 100644 --- a/include/linux/string_helpers.h +++ b/include/linux/string_helpers.h @@ -54,6 +54,9 @@ static inline int string_unescape_any_inplace(char *buf) int string_escape_mem(const char *src, size_t isz, char *dst, size_t osz, unsigned int flags, const char *only); +int string_escape_mem_ascii(const char *src, size_t isz, char *dst, + size_t osz); + static inline int string_escape_mem_any_np(const char *src, size_t isz, char *dst, size_t osz, const char *only) { diff --git a/include/linux/sudmac.h b/include/linux/sudmac.h deleted file mode 100644 index cccc0a665d26..000000000000 --- a/include/linux/sudmac.h +++ /dev/null @@ -1,49 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Header for the SUDMAC driver - * - * Copyright (C) 2013 Renesas Solutions Corp. - */ -#ifndef SUDMAC_H -#define SUDMAC_H - -#include <linux/dmaengine.h> -#include <linux/shdma-base.h> -#include <linux/types.h> - -/* Used by slave DMA clients to request DMA to/from a specific peripheral */ -struct sudmac_slave { - struct shdma_slave shdma_slave; /* Set by the platform */ -}; - -/* - * Supplied by platforms to specify, how a DMA channel has to be configured for - * a certain peripheral - */ -struct sudmac_slave_config { - int slave_id; -}; - -struct sudmac_channel { - unsigned long offset; - unsigned long config; - unsigned long wait; /* The configuable range is 0 to 3 */ - unsigned long dint_end_bit; -}; - -struct sudmac_pdata { - const struct sudmac_slave_config *slave; - int slave_num; - const struct sudmac_channel *channel; - int channel_num; -}; - -/* Definitions for the sudmac_channel.config */ -#define SUDMAC_TX_BUFFER_MODE BIT(0) -#define SUDMAC_RX_END_MODE BIT(1) - -/* Definitions for the sudmac_channel.dint_end_bit */ -#define SUDMAC_DMA_BIT_CH0 BIT(0) -#define SUDMAC_DMA_BIT_CH1 BIT(1) - -#endif diff --git a/include/linux/sunrpc/bc_xprt.h b/include/linux/sunrpc/bc_xprt.h index d4229a78524a..87d27e13d885 100644 --- a/include/linux/sunrpc/bc_xprt.h +++ b/include/linux/sunrpc/bc_xprt.h @@ -43,6 +43,7 @@ void xprt_destroy_backchannel(struct rpc_xprt *, unsigned int max_reqs); int xprt_setup_bc(struct rpc_xprt *xprt, unsigned int min_reqs); void xprt_destroy_bc(struct rpc_xprt *xprt, unsigned int max_reqs); void xprt_free_bc_rqst(struct rpc_rqst *req); +unsigned int xprt_bc_max_slots(struct rpc_xprt *xprt); /* * Determine if a shared backchannel is in use diff --git a/include/linux/sunrpc/cache.h b/include/linux/sunrpc/cache.h index c7f38e897174..f8603724fbee 100644 --- a/include/linux/sunrpc/cache.h +++ b/include/linux/sunrpc/cache.h @@ -87,6 +87,7 @@ struct cache_detail { int has_died); struct cache_head * (*alloc)(void); + void (*flush)(void); int (*match)(struct cache_head *orig, struct cache_head *new); void (*init)(struct cache_head *orig, struct cache_head *new); void (*update)(struct cache_head *orig, struct cache_head *new); @@ -107,9 +108,9 @@ struct cache_detail { /* fields for communication over channel */ struct list_head queue; - atomic_t readers; /* how many time is /chennel open */ - time_t last_close; /* if no readers, when did last close */ - time_t last_warn; /* when we last warned about no readers */ + atomic_t writers; /* how many time is /channel open */ + time_t last_close; /* if no writers, when did last close */ + time_t last_warn; /* when we last warned about no writers */ union { struct proc_dir_entry *procfs; diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h index 6e8073140a5d..abc63bd1be2b 100644 --- a/include/linux/sunrpc/clnt.h +++ b/include/linux/sunrpc/clnt.h @@ -124,6 +124,7 @@ struct rpc_create_args { u32 prognumber; /* overrides program->number */ u32 version; rpc_authflavor_t authflavor; + u32 nconnect; unsigned long flags; char *client_name; struct svc_xprt *bc_xprt; /* NFSv4.1 backchannel */ @@ -163,6 +164,8 @@ void rpc_shutdown_client(struct rpc_clnt *); void rpc_release_client(struct rpc_clnt *); void rpc_task_release_transport(struct rpc_task *); void rpc_task_release_client(struct rpc_task *); +struct rpc_xprt *rpc_task_get_xprt(struct rpc_clnt *clnt, + struct rpc_xprt *xprt); int rpcb_create_local(struct net *); void rpcb_put_local(struct net *); @@ -191,6 +194,7 @@ void rpc_setbufsize(struct rpc_clnt *, unsigned int, unsigned int); struct net * rpc_net_ns(struct rpc_clnt *); size_t rpc_max_payload(struct rpc_clnt *); size_t rpc_max_bc_payload(struct rpc_clnt *); +unsigned int rpc_num_bc_slots(struct rpc_clnt *); void rpc_force_rebind(struct rpc_clnt *); size_t rpc_peeraddr(struct rpc_clnt *, struct sockaddr *, size_t); const char *rpc_peeraddr2str(struct rpc_clnt *, enum rpc_display_format_t); diff --git a/include/linux/sunrpc/metrics.h b/include/linux/sunrpc/metrics.h index 1b3751327575..0ee3f7052846 100644 --- a/include/linux/sunrpc/metrics.h +++ b/include/linux/sunrpc/metrics.h @@ -30,7 +30,7 @@ #include <linux/ktime.h> #include <linux/spinlock.h> -#define RPC_IOSTATS_VERS "1.0" +#define RPC_IOSTATS_VERS "1.1" struct rpc_iostats { spinlock_t om_lock; @@ -66,6 +66,11 @@ struct rpc_iostats { ktime_t om_queue, /* queued for xmit */ om_rtt, /* RPC RTT */ om_execute; /* RPC execution */ + /* + * The count of operations that complete with tk_status < 0. + * These statuses usually indicate error conditions. + */ + unsigned long om_error_status; } ____cacheline_aligned; struct rpc_task; diff --git a/include/linux/sunrpc/sched.h b/include/linux/sunrpc/sched.h index d0e451868f02..a6ef35184ef1 100644 --- a/include/linux/sunrpc/sched.h +++ b/include/linux/sunrpc/sched.h @@ -98,7 +98,6 @@ typedef void (*rpc_action)(struct rpc_task *); struct rpc_call_ops { void (*rpc_call_prepare)(struct rpc_task *, void *); - void (*rpc_call_prepare_transmit)(struct rpc_task *, void *); void (*rpc_call_done)(struct rpc_task *, void *); void (*rpc_count_stats)(struct rpc_task *, void *); void (*rpc_release)(void *); @@ -126,6 +125,7 @@ struct rpc_task_setup { #define RPC_CALL_MAJORSEEN 0x0020 /* major timeout seen */ #define RPC_TASK_ROOTCREDS 0x0040 /* force root creds */ #define RPC_TASK_DYNAMIC 0x0080 /* task was kmalloc'ed */ +#define RPC_TASK_NO_ROUND_ROBIN 0x0100 /* send requests on "main" xprt */ #define RPC_TASK_SOFT 0x0200 /* Use soft timeouts */ #define RPC_TASK_SOFTCONN 0x0400 /* Fail if can't connect */ #define RPC_TASK_SENT 0x0800 /* message was sent */ @@ -183,8 +183,9 @@ struct rpc_task_setup { #define RPC_NR_PRIORITY (1 + RPC_PRIORITY_PRIVILEGED - RPC_PRIORITY_LOW) struct rpc_timer { - struct timer_list timer; struct list_head list; + unsigned long expires; + struct delayed_work dwork; }; /* @@ -241,9 +242,6 @@ void rpc_sleep_on_priority_timeout(struct rpc_wait_queue *queue, void rpc_sleep_on_priority(struct rpc_wait_queue *, struct rpc_task *, int priority); -void rpc_wake_up_queued_task_on_wq(struct workqueue_struct *wq, - struct rpc_wait_queue *queue, - struct rpc_task *task); void rpc_wake_up_queued_task(struct rpc_wait_queue *, struct rpc_task *); void rpc_wake_up_queued_task_set_status(struct rpc_wait_queue *, diff --git a/include/linux/sunrpc/svc_rdma.h b/include/linux/sunrpc/svc_rdma.h index 981f0d726ad4..40f65888dd38 100644 --- a/include/linux/sunrpc/svc_rdma.h +++ b/include/linux/sunrpc/svc_rdma.h @@ -42,6 +42,7 @@ #ifndef SVC_RDMA_H #define SVC_RDMA_H +#include <linux/llist.h> #include <linux/sunrpc/xdr.h> #include <linux/sunrpc/svcsock.h> #include <linux/sunrpc/rpc_rdma.h> @@ -107,8 +108,7 @@ struct svcxprt_rdma { struct list_head sc_read_complete_q; struct work_struct sc_work; - spinlock_t sc_recv_lock; - struct list_head sc_recv_ctxts; + struct llist_head sc_recv_ctxts; }; /* sc_flags */ #define RDMAXPRT_CONN_PENDING 3 @@ -125,6 +125,7 @@ enum { #define RPCSVC_MAXPAYLOAD_RDMA RPCSVC_MAXPAYLOAD struct svc_rdma_recv_ctxt { + struct llist_node rc_node; struct list_head rc_list; struct ib_recv_wr rc_recv_wr; struct ib_cqe rc_cqe; @@ -200,7 +201,6 @@ extern struct svc_xprt_class svc_rdma_bc_class; #endif /* svc_rdma.c */ -extern struct workqueue_struct *svc_rdma_wq; extern int svc_rdma_init(void); extern void svc_rdma_cleanup(void); diff --git a/include/linux/sunrpc/xdr.h b/include/linux/sunrpc/xdr.h index 9ee3970ba59c..f33e5013bdfb 100644 --- a/include/linux/sunrpc/xdr.h +++ b/include/linux/sunrpc/xdr.h @@ -164,6 +164,13 @@ xdr_decode_opaque_fixed(__be32 *p, void *ptr, unsigned int len) return p + XDR_QUADLEN(len); } +static inline void xdr_netobj_dup(struct xdr_netobj *dst, + struct xdr_netobj *src, gfp_t gfp_mask) +{ + dst->data = kmemdup(src->data, src->len, gfp_mask); + dst->len = src->len; +} + /* * Adjust kvec to reflect end of xdr'ed data (RPC client XDR) */ @@ -179,7 +186,7 @@ xdr_adjust_iovec(struct kvec *iov, __be32 *p) extern void xdr_shift_buf(struct xdr_buf *, size_t); extern void xdr_buf_from_iov(struct kvec *, struct xdr_buf *); extern int xdr_buf_subsegment(struct xdr_buf *, struct xdr_buf *, unsigned int, unsigned int); -extern int xdr_buf_read_netobj(struct xdr_buf *, struct xdr_netobj *, unsigned int); +extern int xdr_buf_read_mic(struct xdr_buf *, struct xdr_netobj *, unsigned int); extern int read_bytes_from_xdr_buf(struct xdr_buf *, unsigned int, void *, unsigned int); extern int write_bytes_to_xdr_buf(struct xdr_buf *, unsigned int, void *, unsigned int); diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h index a6d9fce7f20e..d783e15ba898 100644 --- a/include/linux/sunrpc/xprt.h +++ b/include/linux/sunrpc/xprt.h @@ -158,6 +158,7 @@ struct rpc_xprt_ops { int (*bc_setup)(struct rpc_xprt *xprt, unsigned int min_reqs); size_t (*bc_maxpayload)(struct rpc_xprt *xprt); + unsigned int (*bc_num_slots)(struct rpc_xprt *xprt); void (*bc_free_rqst)(struct rpc_rqst *rqst); void (*bc_destroy)(struct rpc_xprt *xprt, unsigned int max_reqs); @@ -238,6 +239,7 @@ struct rpc_xprt { /* * Send stuff */ + atomic_long_t queuelen; spinlock_t transport_lock; /* lock transport info */ spinlock_t reserve_lock; /* lock slot table */ spinlock_t queue_lock; /* send/receive queue lock */ @@ -250,8 +252,9 @@ struct rpc_xprt { #if defined(CONFIG_SUNRPC_BACKCHANNEL) struct svc_serv *bc_serv; /* The RPC service which will */ /* process the callback */ - int bc_alloc_count; /* Total number of preallocs */ - atomic_t bc_free_slots; + unsigned int bc_alloc_max; + unsigned int bc_alloc_count; /* Total number of preallocs */ + atomic_t bc_slot_count; /* Number of allocated slots */ spinlock_t bc_pa_lock; /* Protects the preallocated * items */ struct list_head bc_pa_list; /* List of preallocated @@ -334,6 +337,9 @@ struct xprt_class { */ struct rpc_xprt *xprt_create_transport(struct xprt_create *args); void xprt_connect(struct rpc_task *task); +unsigned long xprt_reconnect_delay(const struct rpc_xprt *xprt); +void xprt_reconnect_backoff(struct rpc_xprt *xprt, + unsigned long init_to); void xprt_reserve(struct rpc_task *task); void xprt_retry_reserve(struct rpc_task *task); int xprt_reserve_xprt(struct rpc_xprt *xprt, struct rpc_task *task); @@ -346,6 +352,7 @@ bool xprt_prepare_transmit(struct rpc_task *task); void xprt_request_enqueue_transmit(struct rpc_task *task); void xprt_request_enqueue_receive(struct rpc_task *task); void xprt_request_wait_receive(struct rpc_task *task); +void xprt_request_dequeue_xprt(struct rpc_task *task); bool xprt_request_need_retransmit(struct rpc_task *task); void xprt_transmit(struct rpc_task *task); void xprt_end_transmit(struct rpc_task *task); diff --git a/include/linux/sunrpc/xprtmultipath.h b/include/linux/sunrpc/xprtmultipath.h index af1257c030d2..c6cce3fbf29d 100644 --- a/include/linux/sunrpc/xprtmultipath.h +++ b/include/linux/sunrpc/xprtmultipath.h @@ -15,6 +15,8 @@ struct rpc_xprt_switch { struct kref xps_kref; unsigned int xps_nxprts; + unsigned int xps_nactive; + atomic_long_t xps_queuelen; struct list_head xps_xprt_list; struct net * xps_net; diff --git a/include/linux/sunrpc/xprtrdma.h b/include/linux/sunrpc/xprtrdma.h index 86fc38ff0355..16c239e0d6dd 100644 --- a/include/linux/sunrpc/xprtrdma.h +++ b/include/linux/sunrpc/xprtrdma.h @@ -49,9 +49,9 @@ * fully-chunked NFS message (read chunks are the largest). Note only * a single chunk type per message is supported currently. */ -#define RPCRDMA_MIN_SLOT_TABLE (2U) +#define RPCRDMA_MIN_SLOT_TABLE (4U) #define RPCRDMA_DEF_SLOT_TABLE (128U) -#define RPCRDMA_MAX_SLOT_TABLE (256U) +#define RPCRDMA_MAX_SLOT_TABLE (16384U) #define RPCRDMA_MIN_INLINE (1024) /* min inline thresh */ #define RPCRDMA_DEF_INLINE (4096) /* default inline thresh */ diff --git a/include/linux/sunrpc/xprtsock.h b/include/linux/sunrpc/xprtsock.h index b81d0b3e0799..7638dbe7bc50 100644 --- a/include/linux/sunrpc/xprtsock.h +++ b/include/linux/sunrpc/xprtsock.h @@ -56,6 +56,7 @@ struct sock_xprt { */ unsigned long sock_state; struct delayed_work connect_worker; + struct work_struct error_worker; struct work_struct recv_worker; struct mutex recv_mutex; struct sockaddr_storage srcaddr; @@ -84,6 +85,10 @@ struct sock_xprt { #define XPRT_SOCK_CONNECTING 1U #define XPRT_SOCK_DATA_READY (2) #define XPRT_SOCK_UPD_TIMEOUT (3) +#define XPRT_SOCK_WAKE_ERROR (4) +#define XPRT_SOCK_WAKE_WRITE (5) +#define XPRT_SOCK_WAKE_PENDING (6) +#define XPRT_SOCK_WAKE_DISCONNECT (7) #endif /* __KERNEL__ */ diff --git a/include/linux/suspend.h b/include/linux/suspend.h index f0d262ad7b78..6fc8843f1c9e 100644 --- a/include/linux/suspend.h +++ b/include/linux/suspend.h @@ -190,8 +190,9 @@ struct platform_suspend_ops { struct platform_s2idle_ops { int (*begin)(void); int (*prepare)(void); + int (*prepare_late)(void); void (*wake)(void); - void (*sync)(void); + void (*restore_early)(void); void (*restore)(void); void (*end)(void); }; @@ -304,7 +305,7 @@ static inline bool idle_should_enter_s2idle(void) return unlikely(s2idle_state == S2IDLE_STATE_ENTER); } -extern bool pm_suspend_via_s2idle(void); +extern bool pm_suspend_default_s2idle(void); extern void __init pm_states_init(void); extern void s2idle_set_ops(const struct platform_s2idle_ops *ops); extern void s2idle_wake(void); @@ -336,7 +337,8 @@ static inline void pm_set_suspend_via_firmware(void) {} static inline void pm_set_resume_via_firmware(void) {} static inline bool pm_suspend_via_firmware(void) { return false; } static inline bool pm_resume_via_firmware(void) { return false; } -static inline bool pm_suspend_via_s2idle(void) { return false; } +static inline bool pm_suspend_no_platform(void) { return false; } +static inline bool pm_suspend_default_s2idle(void) { return false; } static inline void suspend_set_ops(const struct platform_suspend_ops *ops) {} static inline int pm_suspend(suspend_state_t state) { return -ENOSYS; } @@ -448,6 +450,7 @@ extern bool system_entering_hibernation(void); extern bool hibernation_available(void); asmlinkage int swsusp_save(void); extern struct pbe *restore_pblist; +int pfn_is_nosave(unsigned long pfn); #else /* CONFIG_HIBERNATION */ static inline void register_nosave_region(unsigned long b, unsigned long e) {} static inline void register_nosave_region_late(unsigned long b, unsigned long e) {} diff --git a/include/linux/swap.h b/include/linux/swap.h index 4bfb5c4ac108..063c0c1e112b 100644 --- a/include/linux/swap.h +++ b/include/linux/swap.h @@ -148,7 +148,7 @@ struct zone; * We always assume that blocks are of size PAGE_SIZE. */ struct swap_extent { - struct list_head list; + struct rb_node rb_node; pgoff_t start_page; pgoff_t nr_pages; sector_t start_block; @@ -175,8 +175,9 @@ enum { SWP_PAGE_DISCARD = (1 << 10), /* freed swap page-cluster discards */ SWP_STABLE_WRITES = (1 << 11), /* no overwrite PG_writeback pages */ SWP_SYNCHRONOUS_IO = (1 << 12), /* synchronous IO is efficient */ + SWP_VALID = (1 << 13), /* swap is valid to be operated on? */ /* add others here before... */ - SWP_SCANNING = (1 << 13), /* refcount in scan_swap_map */ + SWP_SCANNING = (1 << 14), /* refcount in scan_swap_map */ }; #define SWAP_CLUSTER_MAX 32UL @@ -247,8 +248,7 @@ struct swap_info_struct { unsigned int cluster_next; /* likely index for next allocation */ unsigned int cluster_nr; /* countdown to next cluster search */ struct percpu_cluster __percpu *percpu_cluster; /* per cpu's swap location */ - struct swap_extent *curr_swap_extent; - struct swap_extent first_swap_extent; + struct rb_root swap_extent_root;/* root of the swap extent rbtree */ struct block_device *bdev; /* swap device or bdev of swap file */ struct file *swap_file; /* seldom referenced */ unsigned int old_block_size; /* seldom referenced */ @@ -340,6 +340,7 @@ extern void lru_add_drain_cpu(int cpu); extern void lru_add_drain_all(void); extern void rotate_reclaimable_page(struct page *page); extern void deactivate_file_page(struct page *page); +extern void deactivate_page(struct page *page); extern void mark_page_lazyfree(struct page *page); extern void swap_setup(void); @@ -364,6 +365,7 @@ extern int vm_swappiness; extern int remove_mapping(struct address_space *mapping, struct page *page); extern unsigned long vm_total_pages; +extern unsigned long reclaim_pages(struct list_head *page_list); #ifdef CONFIG_NUMA extern int node_reclaim_mode; extern int sysctl_min_unmapped_ratio; @@ -460,7 +462,7 @@ extern unsigned int count_swap_pages(int, int); extern sector_t map_swap_page(struct page *, struct block_device **); extern sector_t swapdev_block(int, pgoff_t); extern int page_swapcount(struct page *); -extern int __swap_count(struct swap_info_struct *si, swp_entry_t entry); +extern int __swap_count(swp_entry_t entry); extern int __swp_swapcount(swp_entry_t entry); extern int swp_swapcount(swp_entry_t entry); extern struct swap_info_struct *page_swap_info(struct page *); @@ -470,6 +472,12 @@ extern int try_to_free_swap(struct page *); struct backing_dev_info; extern int init_swap_address_space(unsigned int type, unsigned long nr_pages); extern void exit_swap_address_space(unsigned int type); +extern struct swap_info_struct *get_swap_device(swp_entry_t entry); + +static inline void put_swap_device(struct swap_info_struct *si) +{ + rcu_read_unlock(); +} #else /* CONFIG_SWAP */ @@ -576,7 +584,7 @@ static inline int page_swapcount(struct page *page) return 0; } -static inline int __swap_count(struct swap_info_struct *si, swp_entry_t entry) +static inline int __swap_count(swp_entry_t entry) { return 0; } diff --git a/include/linux/swapops.h b/include/linux/swapops.h index 4d961668e5fc..877fd239b6ff 100644 --- a/include/linux/swapops.h +++ b/include/linux/swapops.h @@ -6,6 +6,8 @@ #include <linux/bug.h> #include <linux/mm_types.h> +#ifdef CONFIG_MMU + /* * swapcache pages are stored in the swapper_space radix tree. We want to * get good packing density in that tree, so the index should be dense in @@ -50,13 +52,11 @@ static inline pgoff_t swp_offset(swp_entry_t entry) return entry.val & SWP_OFFSET_MASK; } -#ifdef CONFIG_MMU /* check whether a pte points to a swap entry */ static inline int is_swap_pte(pte_t pte) { return !pte_none(pte) && !pte_present(pte); } -#endif /* * Convert the arch-dependent pte representation of a swp_entry_t into an @@ -129,12 +129,6 @@ static inline struct page *device_private_entry_to_page(swp_entry_t entry) { return pfn_to_page(swp_offset(entry)); } - -vm_fault_t device_private_entry_fault(struct vm_area_struct *vma, - unsigned long addr, - swp_entry_t entry, - unsigned int flags, - pmd_t *pmdp); #else /* CONFIG_DEVICE_PRIVATE */ static inline swp_entry_t make_device_private_entry(struct page *page, bool write) { @@ -164,15 +158,6 @@ static inline struct page *device_private_entry_to_page(swp_entry_t entry) { return NULL; } - -static inline vm_fault_t device_private_entry_fault(struct vm_area_struct *vma, - unsigned long addr, - swp_entry_t entry, - unsigned int flags, - pmd_t *pmdp) -{ - return VM_FAULT_SIGBUS; -} #endif /* CONFIG_DEVICE_PRIVATE */ #ifdef CONFIG_MIGRATION @@ -375,4 +360,5 @@ static inline int non_swap_entry(swp_entry_t entry) } #endif +#endif /* CONFIG_MMU */ #endif /* _LINUX_SWAPOPS_H */ diff --git a/include/linux/swiotlb.h b/include/linux/swiotlb.h index 361f62bb4a8e..cde3dc18e21a 100644 --- a/include/linux/swiotlb.h +++ b/include/linux/swiotlb.h @@ -46,13 +46,17 @@ enum dma_sync_target { extern phys_addr_t swiotlb_tbl_map_single(struct device *hwdev, dma_addr_t tbl_dma_addr, - phys_addr_t phys, size_t size, + phys_addr_t phys, + size_t mapping_size, + size_t alloc_size, enum dma_data_direction dir, unsigned long attrs); extern void swiotlb_tbl_unmap_single(struct device *hwdev, phys_addr_t tlb_addr, - size_t size, enum dma_data_direction dir, + size_t mapping_size, + size_t alloc_size, + enum dma_data_direction dir, unsigned long attrs); extern void swiotlb_tbl_sync_single(struct device *hwdev, diff --git a/include/linux/sys_soc.h b/include/linux/sys_soc.h index b7c70c3e953f..48ceea867dd6 100644 --- a/include/linux/sys_soc.h +++ b/include/linux/sys_soc.h @@ -12,6 +12,7 @@ struct soc_device_attribute { const char *machine; const char *family; const char *revision; + const char *serial_number; const char *soc_id; const void *data; }; diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h index 2bcef4c70183..f7c561c4dcdd 100644 --- a/include/linux/syscalls.h +++ b/include/linux/syscalls.h @@ -68,6 +68,7 @@ struct sigaltstack; struct rseq; union bpf_attr; struct io_uring_params; +struct clone_args; #include <linux/types.h> #include <linux/aio_abi.h> @@ -264,7 +265,7 @@ static inline void addr_limit_user_check(void) if (CHECK_DATA_CORRUPTION(!segment_eq(get_fs(), USER_DS), "Invalid address limit on user-mode return")) - force_sig(SIGKILL, current); + force_sig(SIGKILL); #ifdef TIF_FSCHECK clear_thread_flag(TIF_FSCHECK); @@ -850,6 +851,9 @@ asmlinkage long sys_clone(unsigned long, unsigned long, int __user *, int __user *, unsigned long); #endif #endif + +asmlinkage long sys_clone3(struct clone_args __user *uargs, size_t size); + asmlinkage long sys_execve(const char __user *filename, const char __user *const __user *argv, const char __user *const __user *envp); @@ -927,6 +931,7 @@ asmlinkage long sys_clock_adjtime32(clockid_t which_clock, struct old_timex32 __user *tx); asmlinkage long sys_syncfs(int fd); asmlinkage long sys_setns(int fd, int nstype); +asmlinkage long sys_pidfd_open(pid_t pid, unsigned int flags); asmlinkage long sys_sendmmsg(int fd, struct mmsghdr __user *msg, unsigned int vlen, unsigned flags); asmlinkage long sys_process_vm_readv(pid_t pid, @@ -1226,8 +1231,8 @@ asmlinkage long sys_ni_syscall(void); * the ksys_xyzyyz() functions prototyped below. */ -int ksys_mount(char __user *dev_name, char __user *dir_name, char __user *type, - unsigned long flags, void __user *data); +int ksys_mount(const char __user *dev_name, const char __user *dir_name, + const char __user *type, unsigned long flags, void __user *data); int ksys_umount(char __user *name, int flags); int ksys_dup(unsigned int fildes); int ksys_chroot(const char __user *filename); @@ -1397,4 +1402,23 @@ static inline unsigned int ksys_personality(unsigned int personality) return old; } +/* for __ARCH_WANT_SYS_IPC */ +long ksys_semtimedop(int semid, struct sembuf __user *tsops, + unsigned int nsops, + const struct __kernel_timespec __user *timeout); +long ksys_semget(key_t key, int nsems, int semflg); +long ksys_old_semctl(int semid, int semnum, int cmd, unsigned long arg); +long ksys_msgget(key_t key, int msgflg); +long ksys_old_msgctl(int msqid, int cmd, struct msqid_ds __user *buf); +long ksys_msgrcv(int msqid, struct msgbuf __user *msgp, size_t msgsz, + long msgtyp, int msgflg); +long ksys_msgsnd(int msqid, struct msgbuf __user *msgp, size_t msgsz, + int msgflg); +long ksys_shmget(key_t key, size_t size, int shmflg); +long ksys_shmdt(char __user *shmaddr); +long ksys_old_shmctl(int shmid, int cmd, struct shmid_ds __user *buf); +long compat_ksys_semtimedop(int semid, struct sembuf __user *tsems, + unsigned int nsops, + const struct old_timespec32 __user *timeout); + #endif diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h index aadd310769d0..6df477329b76 100644 --- a/include/linux/sysctl.h +++ b/include/linux/sysctl.h @@ -37,6 +37,13 @@ struct ctl_table_root; struct ctl_table_header; struct ctl_dir; +/* Keep the same order as in fs/proc/proc_sysctl.c */ +#define SYSCTL_ZERO ((void *)&sysctl_vals[0]) +#define SYSCTL_ONE ((void *)&sysctl_vals[1]) +#define SYSCTL_INT_MAX ((void *)&sysctl_vals[2]) + +extern const int sysctl_vals[]; + typedef int proc_handler (struct ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos); diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h index 786816cf4aa5..5420817ed317 100644 --- a/include/linux/sysfs.h +++ b/include/linux/sysfs.h @@ -196,6 +196,12 @@ struct bin_attribute { .size = _size, \ } +#define __BIN_ATTR_WO(_name) { \ + .attr = { .name = __stringify(_name), .mode = 0200 }, \ + .store = _name##_store, \ + .size = _size, \ +} + #define __BIN_ATTR_RW(_name, _size) \ __BIN_ATTR(_name, 0644, _name##_read, _name##_write, _size) @@ -208,6 +214,9 @@ struct bin_attribute bin_attr_##_name = __BIN_ATTR(_name, _mode, _read, \ #define BIN_ATTR_RO(_name, _size) \ struct bin_attribute bin_attr_##_name = __BIN_ATTR_RO(_name, _size) +#define BIN_ATTR_WO(_name, _size) \ +struct bin_attribute bin_attr_##_name = __BIN_ATTR_WO(_name, _size) + #define BIN_ATTR_RW(_name, _size) \ struct bin_attribute bin_attr_##_name = __BIN_ATTR_RW(_name, _size) @@ -268,6 +277,8 @@ int __must_check sysfs_create_group(struct kobject *kobj, const struct attribute_group *grp); int __must_check sysfs_create_groups(struct kobject *kobj, const struct attribute_group **groups); +int __must_check sysfs_update_groups(struct kobject *kobj, + const struct attribute_group **groups); int sysfs_update_group(struct kobject *kobj, const struct attribute_group *grp); void sysfs_remove_group(struct kobject *kobj, @@ -433,6 +444,12 @@ static inline int sysfs_create_groups(struct kobject *kobj, return 0; } +static inline int sysfs_update_groups(struct kobject *kobj, + const struct attribute_group **groups) +{ + return 0; +} + static inline int sysfs_update_group(struct kobject *kobj, const struct attribute_group *grp) { diff --git a/include/linux/t10-pi.h b/include/linux/t10-pi.h index 3e2a80cc7b56..96305a64a5a7 100644 --- a/include/linux/t10-pi.h +++ b/include/linux/t10-pi.h @@ -53,18 +53,4 @@ extern const struct blk_integrity_profile t10_pi_type1_ip; extern const struct blk_integrity_profile t10_pi_type3_crc; extern const struct blk_integrity_profile t10_pi_type3_ip; -#ifdef CONFIG_BLK_DEV_INTEGRITY -extern void t10_pi_prepare(struct request *rq, u8 protection_type); -extern void t10_pi_complete(struct request *rq, u8 protection_type, - unsigned int intervals); -#else -static inline void t10_pi_complete(struct request *rq, u8 protection_type, - unsigned int intervals) -{ -} -static inline void t10_pi_prepare(struct request *rq, u8 protection_type) -{ -} -#endif - #endif diff --git a/include/linux/tcp.h b/include/linux/tcp.h index 9a478a0cd3a2..99617e528ea2 100644 --- a/include/linux/tcp.h +++ b/include/linux/tcp.h @@ -58,12 +58,7 @@ static inline unsigned int tcp_optlen(const struct sk_buff *skb) /* TCP Fast Open Cookie as stored in memory */ struct tcp_fastopen_cookie { - union { - u8 val[TCP_FASTOPEN_COOKIE_MAX]; -#if IS_ENABLED(CONFIG_IPV6) - struct in6_addr addr; -#endif - }; + __le64 val[DIV_ROUND_UP(TCP_FASTOPEN_COOKIE_MAX, sizeof(u64))]; s8 len; bool exp; /* In RFC6994 experimental option format */ }; @@ -245,6 +240,7 @@ struct tcp_sock { syn_smc:1; /* SYN includes SMC */ u32 tlp_high_seq; /* snd_nxt at the time of TLP retransmit. */ + u32 tcp_tx_delay; /* delay (in usec) added to TX packets */ u64 tcp_wstamp_ns; /* departure time for next sent data packet */ u64 tcp_clock_cache; /* cache last tcp_clock_ns() (see tcp_mstamp_refresh()) */ @@ -358,6 +354,8 @@ struct tcp_sock { #define BPF_SOCK_OPS_TEST_FLAG(TP, ARG) 0 #endif + u32 rcv_ooopack; /* Received out-of-order packets, for tcpinfo */ + /* Receiver side RTT estimation */ u32 rcv_rtt_last_tsecr; struct { @@ -436,6 +434,7 @@ struct tcp_timewait_sock { u32 tw_last_oow_ack_time; int tw_ts_recent_stamp; + u32 tw_tx_delay; #ifdef CONFIG_TCP_MD5SIG struct tcp_md5sig_key *tw_md5_key; #endif diff --git a/include/linux/thermal.h b/include/linux/thermal.h index 15a4ca5d7099..e45659c75920 100644 --- a/include/linux/thermal.h +++ b/include/linux/thermal.h @@ -251,7 +251,7 @@ struct thermal_bind_params { * platform characterization. This value is relative to the * rest of the weights so a cooling device whose weight is * double that of another cooling device is twice as - * effective. See Documentation/thermal/sysfs-api.txt for more + * effective. See Documentation/driver-api/thermal/sysfs-api.rst for more * information. */ int weight; @@ -259,7 +259,7 @@ struct thermal_bind_params { /* * This is a bit mask that gives the binding relation between this * thermal zone and cdev, for a particular trip point. - * See Documentation/thermal/sysfs-api.txt for more information. + * See Documentation/driver-api/thermal/sysfs-api.rst for more information. */ int trip_mask; diff --git a/include/linux/thread_info.h b/include/linux/thread_info.h index 8d8821b3689a..659a4400517b 100644 --- a/include/linux/thread_info.h +++ b/include/linux/thread_info.h @@ -134,7 +134,7 @@ static inline void copy_overflow(int size, unsigned long count) WARN(1, "Buffer overflow detected (%d < %lu)!\n", size, count); } -static __always_inline bool +static __always_inline __must_check bool check_copy_size(const void *addr, size_t bytes, bool is_source) { int sz = __compiletime_object_size(addr); diff --git a/include/linux/thunderbolt.h b/include/linux/thunderbolt.h index 2d7e012db03f..ece782ef5466 100644 --- a/include/linux/thunderbolt.h +++ b/include/linux/thunderbolt.h @@ -429,6 +429,7 @@ static inline struct tb_xdomain *tb_service_parent(struct tb_service *svc) * @lock: Must be held during ring creation/destruction. Is acquired by * interrupt_work when dispatching interrupts to individual rings. * @pdev: Pointer to the PCI device + * @ops: NHI specific optional ops * @iobase: MMIO space of the NHI * @tx_rings: All Tx rings available on this host controller * @rx_rings: All Rx rings available on this host controller @@ -442,6 +443,7 @@ static inline struct tb_xdomain *tb_service_parent(struct tb_service *svc) struct tb_nhi { spinlock_t lock; struct pci_dev *pdev; + const struct tb_nhi_ops *ops; void __iomem *iobase; struct tb_ring **tx_rings; struct tb_ring **rx_rings; diff --git a/include/linux/time64.h b/include/linux/time64.h index a620ee610b9f..19125489ae94 100644 --- a/include/linux/time64.h +++ b/include/linux/time64.h @@ -30,6 +30,8 @@ struct itimerspec64 { /* Located here for timespec[64]_valid_strict */ #define TIME64_MAX ((s64)~((u64)1 << 63)) +#define TIME64_MIN (-TIME64_MAX - 1) + #define KTIME_MAX ((s64)~((u64)1 << 63)) #define KTIME_SEC_MAX (KTIME_MAX / NSEC_PER_SEC) diff --git a/include/linux/timekeeper_internal.h b/include/linux/timekeeper_internal.h index 7acb953298a7..84ff2844df2a 100644 --- a/include/linux/timekeeper_internal.h +++ b/include/linux/timekeeper_internal.h @@ -57,6 +57,7 @@ struct tk_read_base { * @cs_was_changed_seq: The sequence number of clocksource change events * @next_leap_ktime: CLOCK_MONOTONIC time value of a pending leap-second * @raw_sec: CLOCK_MONOTONIC_RAW time in seconds + * @monotonic_to_boot: CLOCK_MONOTONIC to CLOCK_BOOTTIME offset * @cycle_interval: Number of clock cycles in one NTP interval * @xtime_interval: Number of clock shifted nano seconds in one NTP * interval. @@ -84,6 +85,9 @@ struct tk_read_base { * * wall_to_monotonic is no longer the boot time, getboottime must be * used instead. + * + * @monotonic_to_boottime is a timespec64 representation of @offs_boot to + * accelerate the VDSO update for CLOCK_BOOTTIME. */ struct timekeeper { struct tk_read_base tkr_mono; @@ -99,6 +103,7 @@ struct timekeeper { u8 cs_was_changed_seq; ktime_t next_leap_ktime; u64 raw_sec; + struct timespec64 monotonic_to_boot; /* The following members are for timekeeping internal use */ u64 cycle_interval; diff --git a/include/linux/timekeeping.h b/include/linux/timekeeping.h index a8ab0f143ac4..b27e2ffa96c1 100644 --- a/include/linux/timekeeping.h +++ b/include/linux/timekeeping.h @@ -113,6 +113,34 @@ static inline ktime_t ktime_get_coarse_clocktai(void) return ktime_get_coarse_with_offset(TK_OFFS_TAI); } +static inline ktime_t ktime_get_coarse(void) +{ + struct timespec64 ts; + + ktime_get_coarse_ts64(&ts); + return timespec64_to_ktime(ts); +} + +static inline u64 ktime_get_coarse_ns(void) +{ + return ktime_to_ns(ktime_get_coarse()); +} + +static inline u64 ktime_get_coarse_real_ns(void) +{ + return ktime_to_ns(ktime_get_coarse_real()); +} + +static inline u64 ktime_get_coarse_boottime_ns(void) +{ + return ktime_to_ns(ktime_get_coarse_boottime()); +} + +static inline u64 ktime_get_coarse_clocktai_ns(void) +{ + return ktime_to_ns(ktime_get_coarse_clocktai()); +} + /** * ktime_mono_to_real - Convert monotonic time to clock realtime */ @@ -131,12 +159,12 @@ static inline u64 ktime_get_real_ns(void) return ktime_to_ns(ktime_get_real()); } -static inline u64 ktime_get_boot_ns(void) +static inline u64 ktime_get_boottime_ns(void) { return ktime_to_ns(ktime_get_boottime()); } -static inline u64 ktime_get_tai_ns(void) +static inline u64 ktime_get_clocktai_ns(void) { return ktime_to_ns(ktime_get_clocktai()); } diff --git a/include/linux/timer.h b/include/linux/timer.h index 7b066fd38248..1e6650ed066d 100644 --- a/include/linux/timer.h +++ b/include/linux/timer.h @@ -36,19 +36,30 @@ struct timer_list { #define __TIMER_LOCKDEP_MAP_INITIALIZER(_kn) #endif -/* - * A deferrable timer will work normally when the system is busy, but - * will not cause a CPU to come out of idle just to service it; instead, - * the timer will be serviced when the CPU eventually wakes up with a - * subsequent non-deferrable timer. +/** + * @TIMER_DEFERRABLE: A deferrable timer will work normally when the + * system is busy, but will not cause a CPU to come out of idle just + * to service it; instead, the timer will be serviced when the CPU + * eventually wakes up with a subsequent non-deferrable timer. * - * An irqsafe timer is executed with IRQ disabled and it's safe to wait for - * the completion of the running instance from IRQ handlers, for example, - * by calling del_timer_sync(). + * @TIMER_IRQSAFE: An irqsafe timer is executed with IRQ disabled and + * it's safe to wait for the completion of the running instance from + * IRQ handlers, for example, by calling del_timer_sync(). * * Note: The irq disabled callback execution is a special case for * workqueue locking issues. It's not meant for executing random crap * with interrupts disabled. Abuse is monitored! + * + * @TIMER_PINNED: A pinned timer will not be affected by any timer + * placement heuristics (like, NOHZ) and will always expire on the CPU + * on which the timer was enqueued. + * + * Note: Because enqueuing of timers can migrate the timer from one + * CPU to another, pinned timers are not guaranteed to stay on the + * initialy selected CPU. They move to the CPU on which the enqueue + * function is invoked via mod_timer() or add_timer(). If the timer + * should be placed on a particular CPU, then add_timer_on() has to be + * used. */ #define TIMER_CPUMASK 0x0003FFFF #define TIMER_MIGRATING 0x00040000 @@ -172,7 +183,7 @@ extern void add_timer(struct timer_list *timer); extern int try_to_del_timer_sync(struct timer_list *timer); -#ifdef CONFIG_SMP +#if defined(CONFIG_SMP) || defined(CONFIG_PREEMPT_RT) extern int del_timer_sync(struct timer_list *timer); #else # define del_timer_sync(t) del_timer(t) diff --git a/include/linux/timeriomem-rng.h b/include/linux/timeriomem-rng.h index fd4a6e6ec831..672df7fbf6c1 100644 --- a/include/linux/timeriomem-rng.h +++ b/include/linux/timeriomem-rng.h @@ -5,6 +5,9 @@ * Copyright (c) 2009 Alexander Clouter <alex@digriz.org.uk> */ +#ifndef _LINUX_TIMERIOMEM_RNG_H +#define _LINUX_TIMERIOMEM_RNG_H + struct timeriomem_rng_data { void __iomem *address; @@ -14,3 +17,5 @@ struct timeriomem_rng_data { /* bits of entropy per 1024 bits read */ unsigned int quality; }; + +#endif /* _LINUX_TIMERIOMEM_RNG_H */ diff --git a/include/linux/timerqueue.h b/include/linux/timerqueue.h index 78b8cc73f12f..93884086f392 100644 --- a/include/linux/timerqueue.h +++ b/include/linux/timerqueue.h @@ -12,8 +12,7 @@ struct timerqueue_node { }; struct timerqueue_head { - struct rb_root head; - struct timerqueue_node *next; + struct rb_root_cached rb_root; }; @@ -29,13 +28,14 @@ extern struct timerqueue_node *timerqueue_iterate_next( * * @head: head of timerqueue * - * Returns a pointer to the timer node that has the - * earliest expiration time. + * Returns a pointer to the timer node that has the earliest expiration time. */ static inline struct timerqueue_node *timerqueue_getnext(struct timerqueue_head *head) { - return head->next; + struct rb_node *leftmost = rb_first_cached(&head->rb_root); + + return rb_entry(leftmost, struct timerqueue_node, node); } static inline void timerqueue_init(struct timerqueue_node *node) @@ -43,9 +43,18 @@ static inline void timerqueue_init(struct timerqueue_node *node) RB_CLEAR_NODE(&node->node); } +static inline bool timerqueue_node_queued(struct timerqueue_node *node) +{ + return !RB_EMPTY_NODE(&node->node); +} + +static inline bool timerqueue_node_expires(struct timerqueue_node *node) +{ + return node->expires; +} + static inline void timerqueue_init_head(struct timerqueue_head *head) { - head->head = RB_ROOT; - head->next = NULL; + head->rb_root = RB_ROOT_CACHED; } #endif /* _LINUX_TIMERQUEUE_H */ diff --git a/include/linux/tnum.h b/include/linux/tnum.h index c7dc2b5902c0..c17af77f3fae 100644 --- a/include/linux/tnum.h +++ b/include/linux/tnum.h @@ -5,6 +5,10 @@ * propagate the unknown bits such that the tnum result represents all the * possible results for possible values of the operands. */ + +#ifndef _LINUX_TNUM_H +#define _LINUX_TNUM_H + #include <linux/types.h> struct tnum { @@ -81,3 +85,5 @@ bool tnum_in(struct tnum a, struct tnum b); int tnum_strn(char *str, size_t size, struct tnum a); /* Format a tnum as tristate binary expansion */ int tnum_sbin(char *str, size_t size, struct tnum a); + +#endif /* _LINUX_TNUM_H */ diff --git a/include/linux/topology.h b/include/linux/topology.h index cb0775e1ee4b..eb2fe6edd73c 100644 --- a/include/linux/topology.h +++ b/include/linux/topology.h @@ -27,6 +27,7 @@ #ifndef _LINUX_TOPOLOGY_H #define _LINUX_TOPOLOGY_H +#include <linux/arch_topology.h> #include <linux/cpumask.h> #include <linux/bitops.h> #include <linux/mmzone.h> @@ -59,6 +60,20 @@ int arch_update_cpu_topology(void); */ #define RECLAIM_DISTANCE 30 #endif + +/* + * The following tunable allows platforms to override the default node + * reclaim distance (RECLAIM_DISTANCE) if remote memory accesses are + * sufficiently fast that the default value actually hurts + * performance. + * + * AMD EPYC machines use this because even though the 2-hop distance + * is 32 (3.2x slower than a local memory access) performance actually + * *improves* if allowed to reclaim memory and load balance tasks + * between NUMA nodes 2-hops apart. + */ +extern int __read_mostly node_reclaim_distance; + #ifndef PENALTY_FOR_NODE_WITH_CPUS #define PENALTY_FOR_NODE_WITH_CPUS (1) #endif @@ -184,6 +199,9 @@ static inline int cpu_to_mem(int cpu) #ifndef topology_physical_package_id #define topology_physical_package_id(cpu) ((void)(cpu), -1) #endif +#ifndef topology_die_id +#define topology_die_id(cpu) ((void)(cpu), -1) +#endif #ifndef topology_core_id #define topology_core_id(cpu) ((void)(cpu), 0) #endif @@ -193,6 +211,9 @@ static inline int cpu_to_mem(int cpu) #ifndef topology_core_cpumask #define topology_core_cpumask(cpu) cpumask_of(cpu) #endif +#ifndef topology_die_cpumask +#define topology_die_cpumask(cpu) cpumask_of(cpu) +#endif #ifdef CONFIG_SCHED_SMT static inline const struct cpumask *cpu_smt_mask(int cpu) diff --git a/include/linux/torture.h b/include/linux/torture.h index 23d80db426d7..6241f59e2d6f 100644 --- a/include/linux/torture.h +++ b/include/linux/torture.h @@ -66,7 +66,7 @@ int torture_shutdown_init(int ssecs, void (*cleanup)(void)); /* Task stuttering, which forces load/no-load transitions. */ bool stutter_wait(const char *title); -int torture_stutter_init(int s); +int torture_stutter_init(int s, int sgap); /* Initialization and cleanup. */ bool torture_init_begin(char *ttype, int v); @@ -86,7 +86,7 @@ void _torture_stop_kthread(char *m, struct task_struct **tp); #define torture_stop_kthread(n, tp) \ _torture_stop_kthread("Stopping " #n " task", &(tp)) -#ifdef CONFIG_PREEMPT +#ifdef CONFIG_PREEMPTION #define torture_preempt_schedule() preempt_schedule() #else #define torture_preempt_schedule() diff --git a/include/linux/tpm_eventlog.h b/include/linux/tpm_eventlog.h index 81519f163211..63238c84dc0b 100644 --- a/include/linux/tpm_eventlog.h +++ b/include/linux/tpm_eventlog.h @@ -112,4 +112,156 @@ struct tcg_pcr_event2_head { struct tpm_digest digests[]; } __packed; +struct tcg_algorithm_size { + u16 algorithm_id; + u16 algorithm_size; +}; + +struct tcg_algorithm_info { + u8 signature[16]; + u32 platform_class; + u8 spec_version_minor; + u8 spec_version_major; + u8 spec_errata; + u8 uintn_size; + u32 number_of_algorithms; + struct tcg_algorithm_size digest_sizes[]; +}; + +#ifndef TPM_MEMREMAP +#define TPM_MEMREMAP(start, size) NULL +#endif + +#ifndef TPM_MEMUNMAP +#define TPM_MEMUNMAP(start, size) do{} while(0) +#endif + +/** + * __calc_tpm2_event_size - calculate the size of a TPM2 event log entry + * @event: Pointer to the event whose size should be calculated + * @event_header: Pointer to the initial event containing the digest lengths + * @do_mapping: Whether or not the event needs to be mapped + * + * The TPM2 event log format can contain multiple digests corresponding to + * separate PCR banks, and also contains a variable length of the data that + * was measured. This requires knowledge of how long each digest type is, + * and this information is contained within the first event in the log. + * + * We calculate the length by examining the number of events, and then looking + * at each event in turn to determine how much space is used for events in + * total. Once we've done this we know the offset of the data length field, + * and can calculate the total size of the event. + * + * Return: size of the event on success, <0 on failure + */ + +static inline int __calc_tpm2_event_size(struct tcg_pcr_event2_head *event, + struct tcg_pcr_event *event_header, + bool do_mapping) +{ + struct tcg_efi_specid_event_head *efispecid; + struct tcg_event_field *event_field; + void *mapping = NULL; + int mapping_size; + void *marker; + void *marker_start; + u32 halg_size; + size_t size; + u16 halg; + int i; + int j; + + marker = event; + marker_start = marker; + marker = marker + sizeof(event->pcr_idx) + sizeof(event->event_type) + + sizeof(event->count); + + /* Map the event header */ + if (do_mapping) { + mapping_size = marker - marker_start; + mapping = TPM_MEMREMAP((unsigned long)marker_start, + mapping_size); + if (!mapping) { + size = 0; + goto out; + } + } else { + mapping = marker_start; + } + + event = (struct tcg_pcr_event2_head *)mapping; + + efispecid = (struct tcg_efi_specid_event_head *)event_header->event; + + /* Check if event is malformed. */ + if (event->count > efispecid->num_algs) { + size = 0; + goto out; + } + + for (i = 0; i < event->count; i++) { + halg_size = sizeof(event->digests[i].alg_id); + + /* Map the digest's algorithm identifier */ + if (do_mapping) { + TPM_MEMUNMAP(mapping, mapping_size); + mapping_size = halg_size; + mapping = TPM_MEMREMAP((unsigned long)marker, + mapping_size); + if (!mapping) { + size = 0; + goto out; + } + } else { + mapping = marker; + } + + memcpy(&halg, mapping, halg_size); + marker = marker + halg_size; + + for (j = 0; j < efispecid->num_algs; j++) { + if (halg == efispecid->digest_sizes[j].alg_id) { + marker += + efispecid->digest_sizes[j].digest_size; + break; + } + } + /* Algorithm without known length. Such event is unparseable. */ + if (j == efispecid->num_algs) { + size = 0; + goto out; + } + } + + /* + * Map the event size - we don't read from the event itself, so + * we don't need to map it + */ + if (do_mapping) { + TPM_MEMUNMAP(mapping, mapping_size); + mapping_size += sizeof(event_field->event_size); + mapping = TPM_MEMREMAP((unsigned long)marker, + mapping_size); + if (!mapping) { + size = 0; + goto out; + } + } else { + mapping = marker; + } + + event_field = (struct tcg_event_field *)mapping; + + marker = marker + sizeof(event_field->event_size) + + event_field->event_size; + size = marker - marker_start; + + if ((event->event_type == 0) && (event_field->event_size == 0)) + size = 0; +out: + if (do_mapping) + TPM_MEMUNMAP(mapping, mapping_size); + return size; +} + #endif diff --git a/include/linux/trace_events.h b/include/linux/trace_events.h index 8a62731673f7..30a8cdcfd4a4 100644 --- a/include/linux/trace_events.h +++ b/include/linux/trace_events.h @@ -142,6 +142,7 @@ enum print_line_t { enum print_line_t trace_handle_return(struct trace_seq *s); void tracing_generic_entry_update(struct trace_entry *entry, + unsigned short type, unsigned long flags, int pc); struct trace_event_file; @@ -317,6 +318,14 @@ trace_event_name(struct trace_event_call *call) return call->name; } +static inline struct list_head * +trace_get_fields(struct trace_event_call *event_call) +{ + if (!event_call->class->get_fields) + return &event_call->class->fields; + return event_call->class->get_fields(event_call); +} + struct trace_array; struct trace_subsystem_dir; @@ -539,6 +548,7 @@ extern int trace_event_get_offsets(struct trace_event_call *call); #define is_signed_type(type) (((type)(-1)) < (type)1) +int ftrace_set_clr_event(struct trace_array *tr, char *buf, int set); int trace_set_clr_event(const char *system, const char *event, int set); /* diff --git a/include/linux/tracehook.h b/include/linux/tracehook.h index 09d678433fc0..36fb3bbed6b2 100644 --- a/include/linux/tracehook.h +++ b/include/linux/tracehook.h @@ -54,13 +54,15 @@ struct linux_binprm; /* * ptrace report for syscall entry and exit looks identical. */ -static inline int ptrace_report_syscall(struct pt_regs *regs) +static inline int ptrace_report_syscall(struct pt_regs *regs, + unsigned long message) { int ptrace = current->ptrace; if (!(ptrace & PT_PTRACED)) return 0; + current->ptrace_message = message; ptrace_notify(SIGTRAP | ((ptrace & PT_TRACESYSGOOD) ? 0x80 : 0)); /* @@ -73,6 +75,7 @@ static inline int ptrace_report_syscall(struct pt_regs *regs) current->exit_code = 0; } + current->ptrace_message = 0; return fatal_signal_pending(current); } @@ -98,7 +101,7 @@ static inline int ptrace_report_syscall(struct pt_regs *regs) static inline __must_check int tracehook_report_syscall_entry( struct pt_regs *regs) { - return ptrace_report_syscall(regs); + return ptrace_report_syscall(regs, PTRACE_EVENTMSG_SYSCALL_ENTRY); } /** @@ -123,7 +126,7 @@ static inline void tracehook_report_syscall_exit(struct pt_regs *regs, int step) if (step) user_single_step_report(regs); else - ptrace_report_syscall(regs); + ptrace_report_syscall(regs, PTRACE_EVENTMSG_SYSCALL_EXIT); } /** @@ -184,6 +187,13 @@ static inline void tracehook_notify_resume(struct pt_regs *regs) if (unlikely(current->task_works)) task_work_run(); +#ifdef CONFIG_KEYS_REQUEST_CACHE + if (unlikely(current->cached_requested_key)) { + key_put(current->cached_requested_key); + current->cached_requested_key = NULL; + } +#endif + mem_cgroup_handle_over_high(); blkcg_maybe_throttle_current(); } diff --git a/include/linux/types.h b/include/linux/types.h index 231114ae38f4..05030f608be3 100644 --- a/include/linux/types.h +++ b/include/linux/types.h @@ -174,7 +174,7 @@ typedef struct { #ifdef CONFIG_64BIT typedef struct { - long counter; + s64 counter; } atomic64_t; #endif diff --git a/include/linux/uaccess.h b/include/linux/uaccess.h index 2b70130af585..70bbdc38dc37 100644 --- a/include/linux/uaccess.h +++ b/include/linux/uaccess.h @@ -55,7 +55,7 @@ * as usual) and both source and destination can trigger faults. */ -static __always_inline unsigned long +static __always_inline __must_check unsigned long __copy_from_user_inatomic(void *to, const void __user *from, unsigned long n) { kasan_check_write(to, n); @@ -63,7 +63,7 @@ __copy_from_user_inatomic(void *to, const void __user *from, unsigned long n) return raw_copy_from_user(to, from, n); } -static __always_inline unsigned long +static __always_inline __must_check unsigned long __copy_from_user(void *to, const void __user *from, unsigned long n) { might_fault(); @@ -85,7 +85,7 @@ __copy_from_user(void *to, const void __user *from, unsigned long n) * The caller should also make sure he pins the user space address * so that we don't result in page fault and sleep. */ -static __always_inline unsigned long +static __always_inline __must_check unsigned long __copy_to_user_inatomic(void __user *to, const void *from, unsigned long n) { kasan_check_read(from, n); @@ -93,7 +93,7 @@ __copy_to_user_inatomic(void __user *to, const void *from, unsigned long n) return raw_copy_to_user(to, from, n); } -static __always_inline unsigned long +static __always_inline __must_check unsigned long __copy_to_user(void __user *to, const void *from, unsigned long n) { might_fault(); @@ -103,7 +103,7 @@ __copy_to_user(void __user *to, const void *from, unsigned long n) } #ifdef INLINE_COPY_FROM_USER -static inline unsigned long +static inline __must_check unsigned long _copy_from_user(void *to, const void __user *from, unsigned long n) { unsigned long res = n; @@ -117,12 +117,12 @@ _copy_from_user(void *to, const void __user *from, unsigned long n) return res; } #else -extern unsigned long +extern __must_check unsigned long _copy_from_user(void *, const void __user *, unsigned long); #endif #ifdef INLINE_COPY_TO_USER -static inline unsigned long +static inline __must_check unsigned long _copy_to_user(void __user *to, const void *from, unsigned long n) { might_fault(); @@ -133,7 +133,7 @@ _copy_to_user(void __user *to, const void *from, unsigned long n) return n; } #else -extern unsigned long +extern __must_check unsigned long _copy_to_user(void __user *, const void *, unsigned long); #endif @@ -203,7 +203,10 @@ static inline void pagefault_enable(void) /* * Is the pagefault handler disabled? If so, user access methods will not sleep. */ -#define pagefault_disabled() (current->pagefault_disabled != 0) +static inline bool pagefault_disabled(void) +{ + return current->pagefault_disabled != 0; +} /* * The pagefault handler is in general disabled by pagefault_disable() or @@ -219,8 +222,9 @@ static inline void pagefault_enable(void) #ifndef ARCH_HAS_NOCACHE_UACCESS -static inline unsigned long __copy_from_user_inatomic_nocache(void *to, - const void __user *from, unsigned long n) +static inline __must_check unsigned long +__copy_from_user_inatomic_nocache(void *to, const void __user *from, + unsigned long n) { return __copy_from_user_inatomic(to, from, n); } @@ -240,6 +244,18 @@ extern long probe_kernel_read(void *dst, const void *src, size_t size); extern long __probe_kernel_read(void *dst, const void *src, size_t size); /* + * probe_user_read(): safely attempt to read from a location in user space + * @dst: pointer to the buffer that shall take the data + * @src: address to read from + * @size: size of the data chunk + * + * Safely read from address @src to the buffer at @dst. If a kernel fault + * happens, handle that and return -EFAULT. + */ +extern long probe_user_read(void *dst, const void __user *src, size_t size); +extern long __probe_user_read(void *dst, const void __user *src, size_t size); + +/* * probe_kernel_write(): safely attempt to write to a location * @dst: address to write to * @src: pointer to the data that shall be written @@ -252,6 +268,9 @@ extern long notrace probe_kernel_write(void *dst, const void *src, size_t size); extern long notrace __probe_kernel_write(void *dst, const void *src, size_t size); extern long strncpy_from_unsafe(char *dst, const void *unsafe_addr, long count); +extern long strncpy_from_unsafe_user(char *dst, const void __user *unsafe_addr, + long count); +extern long strnlen_unsafe_user(const void __user *unsafe_addr, long count); /** * probe_kernel_address(): safely attempt to read from a location diff --git a/include/linux/uio.h b/include/linux/uio.h index 2c90a0842ee8..ab5f523bc0df 100644 --- a/include/linux/uio.h +++ b/include/linux/uio.h @@ -19,9 +19,6 @@ struct kvec { }; enum iter_type { - /* set if ITER_BVEC doesn't hold a bv_page ref */ - ITER_BVEC_FLAG_NO_REF = 2, - /* iter types */ ITER_IOVEC = 4, ITER_KVEC = 8, @@ -56,7 +53,7 @@ struct iov_iter { static inline enum iter_type iov_iter_type(const struct iov_iter *i) { - return i->type & ~(READ | WRITE | ITER_BVEC_FLAG_NO_REF); + return i->type & ~(READ | WRITE); } static inline bool iter_is_iovec(const struct iov_iter *i) @@ -89,11 +86,6 @@ static inline unsigned char iov_iter_rw(const struct iov_iter *i) return i->type & (READ | WRITE); } -static inline bool iov_iter_bvec_no_ref(const struct iov_iter *i) -{ - return (i->type & ITER_BVEC_FLAG_NO_REF) != 0; -} - /* * Total number of bytes covered by an iovec. * @@ -275,13 +267,13 @@ bool csum_and_copy_from_iter_full(void *addr, size_t bytes, __wsum *csum, struct size_t hash_and_copy_to_iter(const void *addr, size_t bytes, void *hashp, struct iov_iter *i); -int import_iovec(int type, const struct iovec __user * uvector, +ssize_t import_iovec(int type, const struct iovec __user * uvector, unsigned nr_segs, unsigned fast_segs, struct iovec **iov, struct iov_iter *i); #ifdef CONFIG_COMPAT struct compat_iovec; -int compat_import_iovec(int type, const struct compat_iovec __user * uvector, +ssize_t compat_import_iovec(int type, const struct compat_iovec __user * uvector, unsigned nr_segs, unsigned fast_segs, struct iovec **iov, struct iov_iter *i); #endif diff --git a/include/linux/unicode.h b/include/linux/unicode.h index aec2c6d800aa..990aa97d8049 100644 --- a/include/linux/unicode.h +++ b/include/linux/unicode.h @@ -17,6 +17,9 @@ int utf8_strncmp(const struct unicode_map *um, int utf8_strncasecmp(const struct unicode_map *um, const struct qstr *s1, const struct qstr *s2); +int utf8_strncasecmp_folded(const struct unicode_map *um, + const struct qstr *cf, + const struct qstr *s1); int utf8_normalize(const struct unicode_map *um, const struct qstr *str, unsigned char *dest, size_t dlen); diff --git a/include/linux/usb.h b/include/linux/usb.h index ae82d9d1112b..e656e7b4b1e4 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h @@ -426,7 +426,6 @@ struct usb_bus { struct device *sysdev; /* as seen from firmware or bus */ int busnum; /* Bus number (in order of reg) */ const char *bus_name; /* stable id (PCI slot_name etc) */ - u8 uses_dma; /* Does the host controller use DMA? */ u8 uses_pio_for_control; /* * Does the host controller use PIO * for control transfers? @@ -578,6 +577,7 @@ struct usb3_lpm_parameters { * @bus_mA: Current available from the bus * @portnum: parent port number (origin 1) * @level: number of USB hub ancestors + * @devaddr: device address, XHCI: assigned by HW, others: same as devnum * @can_submit: URBs may be submitted * @persist_enabled: USB_PERSIST enabled for this device * @have_langid: whether string_langid is valid @@ -661,6 +661,7 @@ struct usb_device { unsigned short bus_mA; u8 portnum; u8 level; + u8 devaddr; unsigned can_submit:1; unsigned persist_enabled:1; @@ -1149,6 +1150,8 @@ struct usbdrv_wrap { * @id_table: USB drivers use ID table to support hotplugging. * Export this with MODULE_DEVICE_TABLE(usb,...). This must be set * or your driver's probe function will never get called. + * @dev_groups: Attributes attached to the device that will be created once it + * is bound to the driver. * @dynids: used internally to hold the list of dynamically added device * ids for this driver. * @drvwrap: Driver-model core structure wrapper. @@ -1196,6 +1199,7 @@ struct usb_driver { int (*post_reset)(struct usb_interface *intf); const struct usb_device_id *id_table; + const struct attribute_group **dev_groups; struct usb_dynids dynids; struct usbdrv_wrap drvwrap; @@ -1219,6 +1223,8 @@ struct usb_driver { * module is being unloaded. * @suspend: Called when the device is going to be suspended by the system. * @resume: Called when the device is being resumed by the system. + * @dev_groups: Attributes attached to the device that will be created once it + * is bound to the driver. * @drvwrap: Driver-model core structure wrapper. * @supports_autosuspend: if set to 0, the USB core will not allow autosuspend * for devices bound to this driver. @@ -1233,6 +1239,7 @@ struct usb_device_driver { int (*suspend) (struct usb_device *udev, pm_message_t message); int (*resume) (struct usb_device *udev, pm_message_t message); + const struct attribute_group **dev_groups; struct usbdrv_wrap drvwrap; unsigned int supports_autosuspend:1; }; @@ -1455,7 +1462,7 @@ typedef void (*usb_complete_t)(struct urb *); * field rather than determining a dma address themselves. * * Note that transfer_buffer must still be set if the controller - * does not support DMA (as indicated by bus.uses_dma) and when talking + * does not support DMA (as indicated by hcd_uses_dma()) and when talking * to root hub. If you have to trasfer between highmem zone and the device * on such controller, create a bounce buffer or bail out with an error. * If transfer_buffer cannot be set (is in highmem) and the controller is DMA diff --git a/include/linux/usb/association.h b/include/linux/usb/association.h deleted file mode 100644 index d7f3cb9b9db5..000000000000 --- a/include/linux/usb/association.h +++ /dev/null @@ -1,151 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Wireless USB - Cable Based Association - * - * Copyright (C) 2006 Intel Corporation - * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version - * 2 as published by the Free Software Foundation. - * - */ -#ifndef __LINUX_USB_ASSOCIATION_H -#define __LINUX_USB_ASSOCIATION_H - - -/* - * Association attributes - * - * Association Models Supplement to WUSB 1.0 T[3-1] - * - * Each field in the structures has it's ID, it's length and then the - * value. This is the actual definition of the field's ID and its - * length. - */ -struct wusb_am_attr { - __u8 id; - __u8 len; -}; - -/* Different fields defined by the spec */ -#define WUSB_AR_AssociationTypeId { .id = cpu_to_le16(0x0000), .len = cpu_to_le16(2) } -#define WUSB_AR_AssociationSubTypeId { .id = cpu_to_le16(0x0001), .len = cpu_to_le16(2) } -#define WUSB_AR_Length { .id = cpu_to_le16(0x0002), .len = cpu_to_le16(4) } -#define WUSB_AR_AssociationStatus { .id = cpu_to_le16(0x0004), .len = cpu_to_le16(4) } -#define WUSB_AR_LangID { .id = cpu_to_le16(0x0008), .len = cpu_to_le16(2) } -#define WUSB_AR_DeviceFriendlyName { .id = cpu_to_le16(0x000b), .len = cpu_to_le16(64) } /* max */ -#define WUSB_AR_HostFriendlyName { .id = cpu_to_le16(0x000c), .len = cpu_to_le16(64) } /* max */ -#define WUSB_AR_CHID { .id = cpu_to_le16(0x1000), .len = cpu_to_le16(16) } -#define WUSB_AR_CDID { .id = cpu_to_le16(0x1001), .len = cpu_to_le16(16) } -#define WUSB_AR_ConnectionContext { .id = cpu_to_le16(0x1002), .len = cpu_to_le16(48) } -#define WUSB_AR_BandGroups { .id = cpu_to_le16(0x1004), .len = cpu_to_le16(2) } - -/* CBAF Control Requests (AMS1.0[T4-1] */ -enum { - CBAF_REQ_GET_ASSOCIATION_INFORMATION = 0x01, - CBAF_REQ_GET_ASSOCIATION_REQUEST, - CBAF_REQ_SET_ASSOCIATION_RESPONSE -}; - -/* - * CBAF USB-interface defitions - * - * No altsettings, one optional interrupt endpoint. - */ -enum { - CBAF_IFACECLASS = 0xef, - CBAF_IFACESUBCLASS = 0x03, - CBAF_IFACEPROTOCOL = 0x01, -}; - -/* Association Information (AMS1.0[T4-3]) */ -struct wusb_cbaf_assoc_info { - __le16 Length; - __u8 NumAssociationRequests; - __le16 Flags; - __u8 AssociationRequestsArray[]; -} __attribute__((packed)); - -/* Association Request (AMS1.0[T4-4]) */ -struct wusb_cbaf_assoc_request { - __u8 AssociationDataIndex; - __u8 Reserved; - __le16 AssociationTypeId; - __le16 AssociationSubTypeId; - __le32 AssociationTypeInfoSize; -} __attribute__((packed)); - -enum { - AR_TYPE_WUSB = 0x0001, - AR_TYPE_WUSB_RETRIEVE_HOST_INFO = 0x0000, - AR_TYPE_WUSB_ASSOCIATE = 0x0001, -}; - -/* Association Attribute header (AMS1.0[3.8]) */ -struct wusb_cbaf_attr_hdr { - __le16 id; - __le16 len; -} __attribute__((packed)); - -/* Host Info (AMS1.0[T4-7]) (yeah, more headers and fields...) */ -struct wusb_cbaf_host_info { - struct wusb_cbaf_attr_hdr AssociationTypeId_hdr; - __le16 AssociationTypeId; - struct wusb_cbaf_attr_hdr AssociationSubTypeId_hdr; - __le16 AssociationSubTypeId; - struct wusb_cbaf_attr_hdr CHID_hdr; - struct wusb_ckhdid CHID; - struct wusb_cbaf_attr_hdr LangID_hdr; - __le16 LangID; - struct wusb_cbaf_attr_hdr HostFriendlyName_hdr; - __u8 HostFriendlyName[]; -} __attribute__((packed)); - -/* Device Info (AMS1.0[T4-8]) - * - * I still don't get this tag'n'header stuff for each goddamn - * field... - */ -struct wusb_cbaf_device_info { - struct wusb_cbaf_attr_hdr Length_hdr; - __le32 Length; - struct wusb_cbaf_attr_hdr CDID_hdr; - struct wusb_ckhdid CDID; - struct wusb_cbaf_attr_hdr BandGroups_hdr; - __le16 BandGroups; - struct wusb_cbaf_attr_hdr LangID_hdr; - __le16 LangID; - struct wusb_cbaf_attr_hdr DeviceFriendlyName_hdr; - __u8 DeviceFriendlyName[]; -} __attribute__((packed)); - -/* Connection Context; CC_DATA - Success case (AMS1.0[T4-9]) */ -struct wusb_cbaf_cc_data { - struct wusb_cbaf_attr_hdr AssociationTypeId_hdr; - __le16 AssociationTypeId; - struct wusb_cbaf_attr_hdr AssociationSubTypeId_hdr; - __le16 AssociationSubTypeId; - struct wusb_cbaf_attr_hdr Length_hdr; - __le32 Length; - struct wusb_cbaf_attr_hdr ConnectionContext_hdr; - struct wusb_ckhdid CHID; - struct wusb_ckhdid CDID; - struct wusb_ckhdid CK; - struct wusb_cbaf_attr_hdr BandGroups_hdr; - __le16 BandGroups; -} __attribute__((packed)); - -/* CC_DATA - Failure case (AMS1.0[T4-10]) */ -struct wusb_cbaf_cc_data_fail { - struct wusb_cbaf_attr_hdr AssociationTypeId_hdr; - __le16 AssociationTypeId; - struct wusb_cbaf_attr_hdr AssociationSubTypeId_hdr; - __le16 AssociationSubTypeId; - struct wusb_cbaf_attr_hdr Length_hdr; - __le16 Length; - struct wusb_cbaf_attr_hdr AssociationStatus_hdr; - __u32 AssociationStatus; -} __attribute__((packed)); - -#endif /* __LINUX_USB_ASSOCIATION_H */ diff --git a/include/linux/usb/ch9.h b/include/linux/usb/ch9.h index da82606be605..58b83066bea4 100644 --- a/include/linux/usb/ch9.h +++ b/include/linux/usb/ch9.h @@ -70,4 +70,31 @@ extern enum usb_device_speed usb_get_maximum_speed(struct device *dev); */ extern const char *usb_state_string(enum usb_device_state state); +#ifdef CONFIG_TRACING +/** + * usb_decode_ctrl - Returns human readable representation of control request. + * @str: buffer to return a human-readable representation of control request. + * This buffer should have about 200 bytes. + * @size: size of str buffer. + * @bRequestType: matches the USB bmRequestType field + * @bRequest: matches the USB bRequest field + * @wValue: matches the USB wValue field (CPU byte order) + * @wIndex: matches the USB wIndex field (CPU byte order) + * @wLength: matches the USB wLength field (CPU byte order) + * + * Function returns decoded, formatted and human-readable description of + * control request packet. + * + * The usage scenario for this is for tracepoints, so function as a return + * use the same value as in parameters. This approach allows to use this + * function in TP_printk + * + * Important: wValue, wIndex, wLength parameters before invoking this function + * should be processed by le16_to_cpu macro. + */ +extern const char *usb_decode_ctrl(char *str, size_t size, __u8 bRequestType, + __u8 bRequest, __u16 wValue, __u16 wIndex, + __u16 wLength); +#endif + #endif /* __LINUX_USB_CH9_H */ diff --git a/include/linux/usb/chipidea.h b/include/linux/usb/chipidea.h index 911e05af671e..edd89b7c8f18 100644 --- a/include/linux/usb/chipidea.h +++ b/include/linux/usb/chipidea.h @@ -61,6 +61,7 @@ struct ci_hdrc_platform_data { #define CI_HDRC_OVERRIDE_PHY_CONTROL BIT(12) /* Glue layer manages phy */ #define CI_HDRC_REQUIRES_ALIGNED_DMA BIT(13) #define CI_HDRC_IMX_IS_HSIC BIT(14) +#define CI_HDRC_PMQOS BIT(15) enum usb_dr_mode dr_mode; #define CI_HDRC_CONTROLLER_RESET_EVENT 0 #define CI_HDRC_CONTROLLER_STOPPED_EVENT 1 diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h index 7595056b96c1..124462d65eac 100644 --- a/include/linux/usb/gadget.h +++ b/include/linux/usb/gadget.h @@ -291,6 +291,9 @@ struct usb_dcd_config_params { #define USB_DEFAULT_U1_DEV_EXIT_LAT 0x01 /* Less then 1 microsec */ __le16 bU2DevExitLat; /* U2 Device exit Latency */ #define USB_DEFAULT_U2_DEV_EXIT_LAT 0x1F4 /* Less then 500 microsec */ + __u8 besl_baseline; /* Recommended baseline BESL (0-15) */ + __u8 besl_deep; /* Recommended deep BESL (0-15) */ +#define USB_DEFAULT_BESL_UNSPECIFIED 0xFF /* No recommended value */ }; @@ -310,7 +313,8 @@ struct usb_gadget_ops { int (*pullup) (struct usb_gadget *, int is_on); int (*ioctl)(struct usb_gadget *, unsigned code, unsigned long param); - void (*get_config_params)(struct usb_dcd_config_params *); + void (*get_config_params)(struct usb_gadget *, + struct usb_dcd_config_params *); int (*udc_start)(struct usb_gadget *, struct usb_gadget_driver *); int (*udc_stop)(struct usb_gadget *); diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h index bb57b5af4700..712b2a603645 100644 --- a/include/linux/usb/hcd.h +++ b/include/linux/usb/hcd.h @@ -216,6 +216,9 @@ struct usb_hcd { #define HC_IS_RUNNING(state) ((state) & __ACTIVE) #define HC_IS_SUSPENDED(state) ((state) & __SUSPEND) + /* memory pool for HCs having local memory, or %NULL */ + struct gen_pool *localmem_pool; + /* more shared queuing code would be good; it should support * smarter scheduling, handle transaction translators, etc; * input size of periodic table to an interrupt scheduler. @@ -253,7 +256,7 @@ struct hc_driver { int flags; #define HCD_MEMORY 0x0001 /* HC regs use memory (else I/O) */ -#define HCD_LOCAL_MEM 0x0002 /* HC needs local memory */ +#define HCD_DMA 0x0002 /* HC uses DMA */ #define HCD_SHARED 0x0004 /* Two (or more) usb_hcds share HW */ #define HCD_USB11 0x0010 /* USB 1.1 */ #define HCD_USB2 0x0020 /* USB 2.0 */ @@ -420,6 +423,11 @@ static inline bool hcd_periodic_completion_in_progress(struct usb_hcd *hcd, return hcd->high_prio_bh.completing_ep == ep; } +static inline bool hcd_uses_dma(struct usb_hcd *hcd) +{ + return IS_ENABLED(CONFIG_HAS_DMA) && (hcd->driver->flags & HCD_DMA); +} + extern int usb_hcd_link_urb_to_ep(struct usb_hcd *hcd, struct urb *urb); extern int usb_hcd_check_unlink_urb(struct usb_hcd *hcd, struct urb *urb, int status); @@ -461,6 +469,8 @@ extern int usb_add_hcd(struct usb_hcd *hcd, unsigned int irqnum, unsigned long irqflags); extern void usb_remove_hcd(struct usb_hcd *hcd); extern int usb_hcd_find_raw_port_number(struct usb_hcd *hcd, int port1); +int usb_hcd_setup_local_mem(struct usb_hcd *hcd, phys_addr_t phys_addr, + dma_addr_t dma, size_t size); struct platform_device; extern void usb_hcd_platform_shutdown(struct platform_device *dev); @@ -587,6 +597,10 @@ extern void usb_ep0_reinit(struct usb_device *); #define GetPortStatus HUB_CLASS_REQ(USB_DIR_IN, USB_RT_PORT, USB_REQ_GET_STATUS) #define SetHubFeature HUB_CLASS_REQ(USB_DIR_OUT, USB_RT_HUB, USB_REQ_SET_FEATURE) #define SetPortFeature HUB_CLASS_REQ(USB_DIR_OUT, USB_RT_PORT, USB_REQ_SET_FEATURE) +#define ClearTTBuffer HUB_CLASS_REQ(USB_DIR_OUT, USB_RT_PORT, HUB_CLEAR_TT_BUFFER) +#define ResetTT HUB_CLASS_REQ(USB_DIR_OUT, USB_RT_PORT, HUB_RESET_TT) +#define GetTTState HUB_CLASS_REQ(USB_DIR_IN, USB_RT_PORT, HUB_GET_TT_STATE) +#define StopTT HUB_CLASS_REQ(USB_DIR_OUT, USB_RT_PORT, HUB_STOP_TT) /*-------------------------------------------------------------------------*/ diff --git a/include/linux/usb/renesas_usbhs.h b/include/linux/usb/renesas_usbhs.h index 53924f8e840c..6914475bbc86 100644 --- a/include/linux/usb/renesas_usbhs.h +++ b/include/linux/usb/renesas_usbhs.h @@ -3,6 +3,7 @@ * Renesas USB * * Copyright (C) 2011 Renesas Solutions Corp. + * Copyright (C) 2019 Renesas Electronics Corporation * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> * * This program is distributed in the hope that it will be useful, @@ -33,17 +34,6 @@ enum { }; /* - * callback functions table for driver - * - * These functions are called from platform for driver. - * Callback function's pointer will be set before - * renesas_usbhs_platform_callback :: hardware_init was called - */ -struct renesas_usbhs_driver_callback { - int (*notify_hotplug)(struct platform_device *pdev); -}; - -/* * callback functions for platform * * These functions are called from driver for platform @@ -180,23 +170,20 @@ struct renesas_usbhs_driver_param { */ int pio_dma_border; /* default is 64byte */ - uintptr_t type; u32 enable_gpio; /* * option: */ - u32 has_otg:1; /* for controlling PWEN/EXTLP */ - u32 has_sudmac:1; /* for SUDMAC */ u32 has_usb_dmac:1; /* for USB-DMAC */ + u32 runtime_pwctrl:1; + u32 has_cnen:1; + u32 cfifo_byte_addr:1; /* CFIFO is byte addressable */ #define USBHS_USB_DMAC_XFER_SIZE 32 /* hardcode the xfer size */ + u32 multi_clks:1; + u32 has_new_pipe_configs:1; }; -#define USBHS_TYPE_RCAR_GEN2 1 -#define USBHS_TYPE_RCAR_GEN3 2 -#define USBHS_TYPE_RCAR_GEN3_WITH_PLL 3 -#define USBHS_TYPE_RZA1 4 - /* * option: * @@ -212,12 +199,6 @@ struct renesas_usbhs_platform_info { struct renesas_usbhs_platform_callback platform_callback; /* - * driver set these callback functions pointer. - * platform can use it on callback functions - */ - struct renesas_usbhs_driver_callback driver_callback; - - /* * option: * * driver use these param for some register @@ -230,12 +211,4 @@ struct renesas_usbhs_platform_info { */ #define renesas_usbhs_get_info(pdev)\ ((struct renesas_usbhs_platform_info *)(pdev)->dev.platform_data) - -#define renesas_usbhs_call_notify_hotplug(pdev) \ - ({ \ - struct renesas_usbhs_driver_callback *dc; \ - dc = &(renesas_usbhs_get_info(pdev)->driver_callback); \ - if (dc && dc->notify_hotplug) \ - dc->notify_hotplug(pdev); \ - }) #endif /* RENESAS_USB_H */ diff --git a/include/linux/usb/role.h b/include/linux/usb/role.h index c05ffa6abda9..2d77f97df72d 100644 --- a/include/linux/usb/role.h +++ b/include/linux/usb/role.h @@ -42,14 +42,51 @@ struct usb_role_switch_desc { bool allow_userspace_control; }; + +#if IS_ENABLED(CONFIG_USB_ROLE_SWITCH) int usb_role_switch_set_role(struct usb_role_switch *sw, enum usb_role role); enum usb_role usb_role_switch_get_role(struct usb_role_switch *sw); struct usb_role_switch *usb_role_switch_get(struct device *dev); +struct usb_role_switch *fwnode_usb_role_switch_get(struct fwnode_handle *node); void usb_role_switch_put(struct usb_role_switch *sw); struct usb_role_switch * usb_role_switch_register(struct device *parent, const struct usb_role_switch_desc *desc); void usb_role_switch_unregister(struct usb_role_switch *sw); +#else +static inline int usb_role_switch_set_role(struct usb_role_switch *sw, + enum usb_role role) +{ + return 0; +} + +static inline enum usb_role usb_role_switch_get_role(struct usb_role_switch *sw) +{ + return USB_ROLE_NONE; +} + +static inline struct usb_role_switch *usb_role_switch_get(struct device *dev) +{ + return ERR_PTR(-ENODEV); +} + +static inline struct usb_role_switch * +fwnode_usb_role_switch_get(struct fwnode_handle *node) +{ + return ERR_PTR(-ENODEV); +} + +static inline void usb_role_switch_put(struct usb_role_switch *sw) { } + +static inline struct usb_role_switch * +usb_role_switch_register(struct device *parent, + const struct usb_role_switch_desc *desc) +{ + return ERR_PTR(-ENODEV); +} + +static inline void usb_role_switch_unregister(struct usb_role_switch *sw) { } +#endif #endif /* __LINUX_USB_ROLE_H */ diff --git a/include/linux/usb/samsung_usb_phy.h b/include/linux/usb/samsung_usb_phy.h deleted file mode 100644 index dc0071741695..000000000000 --- a/include/linux/usb/samsung_usb_phy.h +++ /dev/null @@ -1,17 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Copyright (C) 2012 Samsung Electronics Co.Ltd - * http://www.samsung.com/ - * - * Defines phy types for samsung usb phy controllers - HOST or DEIVCE. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - */ - -enum samsung_usb_phy_type { - USB_PHY_TYPE_DEVICE, - USB_PHY_TYPE_HOST, -}; diff --git a/include/linux/usb/typec_mux.h b/include/linux/usb/typec_mux.h index 43f40685e53c..873ace5b0cf8 100644 --- a/include/linux/usb/typec_mux.h +++ b/include/linux/usb/typec_mux.h @@ -3,54 +3,48 @@ #ifndef __USB_TYPEC_MUX #define __USB_TYPEC_MUX -#include <linux/list.h> #include <linux/usb/typec.h> struct device; +struct typec_mux; +struct typec_switch; +struct fwnode_handle; -/** - * struct typec_switch - USB Type-C cable orientation switch - * @dev: Switch device - * @entry: List entry - * @set: Callback to the driver for setting the orientation - * - * USB Type-C pin flipper switch routing the correct data pairs from the - * connector to the USB controller depending on the orientation of the cable - * plug. - */ -struct typec_switch { - struct device *dev; - struct list_head entry; - - int (*set)(struct typec_switch *sw, enum typec_orientation orientation); -}; +typedef int (*typec_switch_set_fn_t)(struct typec_switch *sw, + enum typec_orientation orientation); -/** - * struct typec_switch - USB Type-C connector pin mux - * @dev: Mux device - * @entry: List entry - * @set: Callback to the driver for setting the state of the mux - * - * Pin Multiplexer/DeMultiplexer switch routing the USB Type-C connector pins to - * different components depending on the requested mode of operation. Used with - * Accessory/Alternate modes. - */ -struct typec_mux { - struct device *dev; - struct list_head entry; - - int (*set)(struct typec_mux *mux, int state); +struct typec_switch_desc { + struct fwnode_handle *fwnode; + typec_switch_set_fn_t set; + void *drvdata; }; struct typec_switch *typec_switch_get(struct device *dev); void typec_switch_put(struct typec_switch *sw); -int typec_switch_register(struct typec_switch *sw); +struct typec_switch * +typec_switch_register(struct device *parent, + const struct typec_switch_desc *desc); void typec_switch_unregister(struct typec_switch *sw); +void typec_switch_set_drvdata(struct typec_switch *sw, void *data); +void *typec_switch_get_drvdata(struct typec_switch *sw); + +typedef int (*typec_mux_set_fn_t)(struct typec_mux *mux, int state); + +struct typec_mux_desc { + struct fwnode_handle *fwnode; + typec_mux_set_fn_t set; + void *drvdata; +}; + struct typec_mux * typec_mux_get(struct device *dev, const struct typec_altmode_desc *desc); void typec_mux_put(struct typec_mux *mux); -int typec_mux_register(struct typec_mux *mux); +struct typec_mux * +typec_mux_register(struct device *parent, const struct typec_mux_desc *desc); void typec_mux_unregister(struct typec_mux *mux); +void typec_mux_set_drvdata(struct typec_mux *mux, void *data); +void *typec_mux_get_drvdata(struct typec_mux *mux); + #endif /* __USB_TYPEC_MUX */ diff --git a/include/linux/usb/usb338x.h b/include/linux/usb/usb338x.h index 7189e3387bf9..20020c1336d5 100644 --- a/include/linux/usb/usb338x.h +++ b/include/linux/usb/usb338x.h @@ -113,7 +113,10 @@ struct usb338x_ll_regs { u32 ll_ltssm_ctrl1; u32 ll_ltssm_ctrl2; u32 ll_ltssm_ctrl3; - u32 unused[2]; + u32 unused1; + + /* 0x710 */ + u32 unused2; u32 ll_general_ctrl0; u32 ll_general_ctrl1; #define PM_U3_AUTO_EXIT 29 @@ -136,29 +139,41 @@ struct usb338x_ll_regs { u32 ll_general_ctrl2; #define SELECT_INVERT_LANE_POLARITY 7 #define FORCE_INVERT_LANE_POLARITY 6 + + /* 0x720 */ u32 ll_general_ctrl3; u32 ll_general_ctrl4; u32 ll_error_gen; -} __packed; + u32 unused3; + + /* 0x730 */ + u32 unused4[4]; -struct usb338x_ll_lfps_regs { - /* offset 0x748 */ + /* 0x740 */ + u32 unused5[2]; u32 ll_lfps_5; #define TIMER_LFPS_6US 16 u32 ll_lfps_6; #define TIMER_LFPS_80US 0 -} __packed; -struct usb338x_ll_tsn_regs { - /* offset 0x77C */ + /* 0x750 */ + u32 unused6[8]; + + /* 0x770 */ + u32 unused7[3]; u32 ll_tsn_counters_2; #define HOT_TX_NORESET_TS2 24 + + /* 0x780 */ u32 ll_tsn_counters_3; #define HOT_RX_RESET_TS2 0 -} __packed; + u32 unused8[3]; -struct usb338x_ll_chi_regs { - /* offset 0x79C */ + /* 0x790 */ + u32 unused9; + u32 ll_lfps_timers_2; +#define LFPS_TIMERS_2_WORKAROUND_VALUE 0x084d + u32 unused10; u32 ll_tsn_chicken_bit; #define RECOVERY_IDLE_TO_RECOVER_FMW 3 } __packed; diff --git a/include/linux/usb/wusb-wa.h b/include/linux/usb/wusb-wa.h deleted file mode 100644 index 64a840b5106e..000000000000 --- a/include/linux/usb/wusb-wa.h +++ /dev/null @@ -1,304 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Wireless USB Wire Adapter constants and structures. - * - * Copyright (C) 2005-2006 Intel Corporation. - * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version - * 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * - * FIXME: docs - * FIXME: organize properly, group logically - * - * All the event structures are defined in uwb/spec.h, as they are - * common to the WHCI and WUSB radio control interfaces. - * - * References: - * [WUSB] Wireless Universal Serial Bus Specification, revision 1.0, ch8 - */ -#ifndef __LINUX_USB_WUSB_WA_H -#define __LINUX_USB_WUSB_WA_H - -/** - * Radio Command Request for the Radio Control Interface - * - * Radio Control Interface command and event codes are the same as - * WHCI, and listed in include/linux/uwb.h:UWB_RC_{CMD,EVT}_* - */ -enum { - WA_EXEC_RC_CMD = 40, /* Radio Control command Request */ -}; - -/* Wireless Adapter Requests ([WUSB] table 8-51) */ -enum { - WUSB_REQ_ADD_MMC_IE = 20, - WUSB_REQ_REMOVE_MMC_IE = 21, - WUSB_REQ_SET_NUM_DNTS = 22, - WUSB_REQ_SET_CLUSTER_ID = 23, - WUSB_REQ_SET_DEV_INFO = 24, - WUSB_REQ_GET_TIME = 25, - WUSB_REQ_SET_STREAM_IDX = 26, - WUSB_REQ_SET_WUSB_MAS = 27, - WUSB_REQ_CHAN_STOP = 28, -}; - - -/* Wireless Adapter WUSB Channel Time types ([WUSB] table 8-52) */ -enum { - WUSB_TIME_ADJ = 0, - WUSB_TIME_BPST = 1, - WUSB_TIME_WUSB = 2, -}; - -enum { - WA_ENABLE = 0x01, - WA_RESET = 0x02, - RPIPE_PAUSE = 0x1, - RPIPE_STALL = 0x2, -}; - -/* Responses from Get Status request ([WUSB] section 8.3.1.6) */ -enum { - WA_STATUS_ENABLED = 0x01, - WA_STATUS_RESETTING = 0x02 -}; - -enum rpipe_crs { - RPIPE_CRS_CTL = 0x01, - RPIPE_CRS_ISO = 0x02, - RPIPE_CRS_BULK = 0x04, - RPIPE_CRS_INTR = 0x08 -}; - -/** - * RPipe descriptor ([WUSB] section 8.5.2.11) - * - * FIXME: explain rpipes - */ -struct usb_rpipe_descriptor { - u8 bLength; - u8 bDescriptorType; - __le16 wRPipeIndex; - __le16 wRequests; - __le16 wBlocks; /* rw if 0 */ - __le16 wMaxPacketSize; /* rw */ - union { - u8 dwa_bHSHubAddress; /* rw: DWA. */ - u8 hwa_bMaxBurst; /* rw: HWA. */ - }; - union { - u8 dwa_bHSHubPort; /* rw: DWA. */ - u8 hwa_bDeviceInfoIndex; /* rw: HWA. */ - }; - u8 bSpeed; /* rw: xfer rate 'enum uwb_phy_rate' */ - union { - u8 dwa_bDeviceAddress; /* rw: DWA Target device address. */ - u8 hwa_reserved; /* rw: HWA. */ - }; - u8 bEndpointAddress; /* rw: Target EP address */ - u8 bDataSequence; /* ro: Current Data sequence */ - __le32 dwCurrentWindow; /* ro */ - u8 bMaxDataSequence; /* ro?: max supported seq */ - u8 bInterval; /* rw: */ - u8 bOverTheAirInterval; /* rw: */ - u8 bmAttribute; /* ro? */ - u8 bmCharacteristics; /* ro? enum rpipe_attr, supported xsactions */ - u8 bmRetryOptions; /* rw? */ - __le16 wNumTransactionErrors; /* rw */ -} __attribute__ ((packed)); - -/** - * Wire Adapter Notification types ([WUSB] sections 8.4.5 & 8.5.4) - * - * These are the notifications coming on the notification endpoint of - * an HWA and a DWA. - */ -enum wa_notif_type { - DWA_NOTIF_RWAKE = 0x91, - DWA_NOTIF_PORTSTATUS = 0x92, - WA_NOTIF_TRANSFER = 0x93, - HWA_NOTIF_BPST_ADJ = 0x94, - HWA_NOTIF_DN = 0x95, -}; - -/** - * Wire Adapter notification header - * - * Notifications coming from a wire adapter use a common header - * defined in [WUSB] sections 8.4.5 & 8.5.4. - */ -struct wa_notif_hdr { - u8 bLength; - u8 bNotifyType; /* enum wa_notif_type */ -} __packed; - -/** - * HWA DN Received notification [(WUSB] section 8.5.4.2) - * - * The DNData is specified in WUSB1.0[7.6]. For each device - * notification we received, we just need to dispatch it. - * - * @dndata: this is really an array of notifications, but all start - * with the same header. - */ -struct hwa_notif_dn { - struct wa_notif_hdr hdr; - u8 bSourceDeviceAddr; /* from errata 2005/07 */ - u8 bmAttributes; - struct wusb_dn_hdr dndata[]; -} __packed; - -/* [WUSB] section 8.3.3 */ -enum wa_xfer_type { - WA_XFER_TYPE_CTL = 0x80, - WA_XFER_TYPE_BI = 0x81, /* bulk/interrupt */ - WA_XFER_TYPE_ISO = 0x82, - WA_XFER_RESULT = 0x83, - WA_XFER_ABORT = 0x84, - WA_XFER_ISO_PACKET_INFO = 0xA0, - WA_XFER_ISO_PACKET_STATUS = 0xA1, -}; - -/* [WUSB] section 8.3.3 */ -struct wa_xfer_hdr { - u8 bLength; /* 0x18 */ - u8 bRequestType; /* 0x80 WA_REQUEST_TYPE_CTL */ - __le16 wRPipe; /* RPipe index */ - __le32 dwTransferID; /* Host-assigned ID */ - __le32 dwTransferLength; /* Length of data to xfer */ - u8 bTransferSegment; -} __packed; - -struct wa_xfer_ctl { - struct wa_xfer_hdr hdr; - u8 bmAttribute; - __le16 wReserved; - struct usb_ctrlrequest baSetupData; -} __packed; - -struct wa_xfer_bi { - struct wa_xfer_hdr hdr; - u8 bReserved; - __le16 wReserved; -} __packed; - -/* [WUSB] section 8.5.5 */ -struct wa_xfer_hwaiso { - struct wa_xfer_hdr hdr; - u8 bReserved; - __le16 wPresentationTime; - __le32 dwNumOfPackets; -} __packed; - -struct wa_xfer_packet_info_hwaiso { - __le16 wLength; - u8 bPacketType; - u8 bReserved; - __le16 PacketLength[0]; -} __packed; - -struct wa_xfer_packet_status_len_hwaiso { - __le16 PacketLength; - __le16 PacketStatus; -} __packed; - -struct wa_xfer_packet_status_hwaiso { - __le16 wLength; - u8 bPacketType; - u8 bReserved; - struct wa_xfer_packet_status_len_hwaiso PacketStatus[0]; -} __packed; - -/* [WUSB] section 8.3.3.5 */ -struct wa_xfer_abort { - u8 bLength; - u8 bRequestType; - __le16 wRPipe; /* RPipe index */ - __le32 dwTransferID; /* Host-assigned ID */ -} __packed; - -/** - * WA Transfer Complete notification ([WUSB] section 8.3.3.3) - * - */ -struct wa_notif_xfer { - struct wa_notif_hdr hdr; - u8 bEndpoint; - u8 Reserved; -} __packed; - -/** Transfer result basic codes [WUSB] table 8-15 */ -enum { - WA_XFER_STATUS_SUCCESS, - WA_XFER_STATUS_HALTED, - WA_XFER_STATUS_DATA_BUFFER_ERROR, - WA_XFER_STATUS_BABBLE, - WA_XFER_RESERVED, - WA_XFER_STATUS_NOT_FOUND, - WA_XFER_STATUS_INSUFFICIENT_RESOURCE, - WA_XFER_STATUS_TRANSACTION_ERROR, - WA_XFER_STATUS_ABORTED, - WA_XFER_STATUS_RPIPE_NOT_READY, - WA_XFER_INVALID_FORMAT, - WA_XFER_UNEXPECTED_SEGMENT_NUMBER, - WA_XFER_STATUS_RPIPE_TYPE_MISMATCH, -}; - -/** [WUSB] section 8.3.3.4 */ -struct wa_xfer_result { - struct wa_notif_hdr hdr; - __le32 dwTransferID; - __le32 dwTransferLength; - u8 bTransferSegment; - u8 bTransferStatus; - __le32 dwNumOfPackets; -} __packed; - -/** - * Wire Adapter Class Descriptor ([WUSB] section 8.5.2.7). - * - * NOTE: u16 fields are read Little Endian from the hardware. - * - * @bNumPorts is the original max number of devices that the host can - * connect; we might chop this so the stack can handle - * it. In case you need to access it, use wusbhc->ports_max - * if it is a Wireless USB WA. - */ -struct usb_wa_descriptor { - u8 bLength; - u8 bDescriptorType; - __le16 bcdWAVersion; - u8 bNumPorts; /* don't use!! */ - u8 bmAttributes; /* Reserved == 0 */ - __le16 wNumRPipes; - __le16 wRPipeMaxBlock; - u8 bRPipeBlockSize; - u8 bPwrOn2PwrGood; - u8 bNumMMCIEs; - u8 DeviceRemovable; /* FIXME: in DWA this is up to 16 bytes */ -} __packed; - -/** - * HWA Device Information Buffer (WUSB1.0[T8.54]) - */ -struct hwa_dev_info { - u8 bmDeviceAvailability[32]; /* FIXME: ignored for now */ - u8 bDeviceAddress; - __le16 wPHYRates; - u8 bmDeviceAttribute; -} __packed; - -#endif /* #ifndef __LINUX_USB_WUSB_WA_H */ diff --git a/include/linux/usb/wusb.h b/include/linux/usb/wusb.h deleted file mode 100644 index 65adee629106..000000000000 --- a/include/linux/usb/wusb.h +++ /dev/null @@ -1,362 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Wireless USB Standard Definitions - * Event Size Tables - * - * Copyright (C) 2005-2006 Intel Corporation - * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version - * 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * - * FIXME: docs - * FIXME: organize properly, group logically - * - * All the event structures are defined in uwb/spec.h, as they are - * common to the WHCI and WUSB radio control interfaces. - */ - -#ifndef __WUSB_H__ -#define __WUSB_H__ - -#include <linux/types.h> -#include <linux/kernel.h> -#include <linux/uwb/spec.h> -#include <linux/usb/ch9.h> -#include <linux/param.h> - -/** - * WUSB Information Element header - * - * I don't know why, they decided to make it different to the MBOA MAC - * IE Header; beats me. - */ -struct wuie_hdr { - u8 bLength; - u8 bIEIdentifier; -} __attribute__((packed)); - -enum { - WUIE_ID_WCTA = 0x80, - WUIE_ID_CONNECTACK, - WUIE_ID_HOST_INFO, - WUIE_ID_CHANGE_ANNOUNCE, - WUIE_ID_DEVICE_DISCONNECT, - WUIE_ID_HOST_DISCONNECT, - WUIE_ID_KEEP_ALIVE = 0x89, - WUIE_ID_ISOCH_DISCARD, - WUIE_ID_RESET_DEVICE, -}; - -/** - * Maximum number of array elements in a WUSB IE. - * - * WUSB1.0[7.5 before table 7-38] says that in WUSB IEs that - * are "arrays" have to limited to 4 elements. So we define it - * like that to ease up and submit only the neeed size. - */ -#define WUIE_ELT_MAX 4 - -/** - * Wrapper for the data that defines a CHID, a CDID or a CK - * - * WUSB defines that CHIDs, CDIDs and CKs are a 16 byte string of - * data. In order to avoid confusion and enforce types, we wrap it. - * - * Make it packed, as we use it in some hw definitions. - */ -struct wusb_ckhdid { - u8 data[16]; -} __attribute__((packed)); - -static const struct wusb_ckhdid wusb_ckhdid_zero = { .data = { 0 } }; - -#define WUSB_CKHDID_STRSIZE (3 * sizeof(struct wusb_ckhdid) + 1) - -/** - * WUSB IE: Host Information (WUSB1.0[7.5.2]) - * - * Used to provide information about the host to the Wireless USB - * devices in range (CHID can be used as an ASCII string). - */ -struct wuie_host_info { - struct wuie_hdr hdr; - __le16 attributes; - struct wusb_ckhdid CHID; -} __attribute__((packed)); - -/** - * WUSB IE: Connect Ack (WUSB1.0[7.5.1]) - * - * Used to acknowledge device connect requests. See note for - * WUIE_ELT_MAX. - */ -struct wuie_connect_ack { - struct wuie_hdr hdr; - struct { - struct wusb_ckhdid CDID; - u8 bDeviceAddress; /* 0 means unused */ - u8 bReserved; - } blk[WUIE_ELT_MAX]; -} __attribute__((packed)); - -/** - * WUSB IE Host Information Element, Connect Availability - * - * WUSB1.0[7.5.2], bmAttributes description - */ -enum { - WUIE_HI_CAP_RECONNECT = 0, - WUIE_HI_CAP_LIMITED, - WUIE_HI_CAP_RESERVED, - WUIE_HI_CAP_ALL, -}; - -/** - * WUSB IE: Channel Stop (WUSB1.0[7.5.8]) - * - * Tells devices the host is going to stop sending MMCs and will disappear. - */ -struct wuie_channel_stop { - struct wuie_hdr hdr; - u8 attributes; - u8 timestamp[3]; -} __attribute__((packed)); - -/** - * WUSB IE: Keepalive (WUSB1.0[7.5.9]) - * - * Ask device(s) to send keepalives. - */ -struct wuie_keep_alive { - struct wuie_hdr hdr; - u8 bDeviceAddress[WUIE_ELT_MAX]; -} __attribute__((packed)); - -/** - * WUSB IE: Reset device (WUSB1.0[7.5.11]) - * - * Tell device to reset; in all truth, we can fit 4 CDIDs, but we only - * use it for one at the time... - * - * In any case, this request is a wee bit silly: why don't they target - * by address?? - */ -struct wuie_reset { - struct wuie_hdr hdr; - struct wusb_ckhdid CDID; -} __attribute__((packed)); - -/** - * WUSB IE: Disconnect device (WUSB1.0[7.5.11]) - * - * Tell device to disconnect; we can fit 4 addresses, but we only use - * it for one at the time... - */ -struct wuie_disconnect { - struct wuie_hdr hdr; - u8 bDeviceAddress; - u8 padding; -} __attribute__((packed)); - -/** - * WUSB IE: Host disconnect ([WUSB] section 7.5.5) - * - * Tells all connected devices to disconnect. - */ -struct wuie_host_disconnect { - struct wuie_hdr hdr; -} __attribute__((packed)); - -/** - * WUSB Device Notification header (WUSB1.0[7.6]) - */ -struct wusb_dn_hdr { - u8 bType; - u8 notifdata[]; -} __attribute__((packed)); - -/** Device Notification codes (WUSB1.0[Table 7-54]) */ -enum WUSB_DN { - WUSB_DN_CONNECT = 0x01, - WUSB_DN_DISCONNECT = 0x02, - WUSB_DN_EPRDY = 0x03, - WUSB_DN_MASAVAILCHANGED = 0x04, - WUSB_DN_RWAKE = 0x05, - WUSB_DN_SLEEP = 0x06, - WUSB_DN_ALIVE = 0x07, -}; - -/** WUSB Device Notification Connect */ -struct wusb_dn_connect { - struct wusb_dn_hdr hdr; - __le16 attributes; - struct wusb_ckhdid CDID; -} __attribute__((packed)); - -static inline int wusb_dn_connect_prev_dev_addr(const struct wusb_dn_connect *dn) -{ - return le16_to_cpu(dn->attributes) & 0xff; -} - -static inline int wusb_dn_connect_new_connection(const struct wusb_dn_connect *dn) -{ - return (le16_to_cpu(dn->attributes) >> 8) & 0x1; -} - -static inline int wusb_dn_connect_beacon_behavior(const struct wusb_dn_connect *dn) -{ - return (le16_to_cpu(dn->attributes) >> 9) & 0x03; -} - -/** Device is alive (aka: pong) (WUSB1.0[7.6.7]) */ -struct wusb_dn_alive { - struct wusb_dn_hdr hdr; -} __attribute__((packed)); - -/** Device is disconnecting (WUSB1.0[7.6.2]) */ -struct wusb_dn_disconnect { - struct wusb_dn_hdr hdr; -} __attribute__((packed)); - -/* General constants */ -enum { - WUSB_TRUST_TIMEOUT_MS = 4000, /* [WUSB] section 4.15.1 */ -}; - -/* - * WUSB Crypto stuff (WUSB1.0[6]) - */ - -extern const char *wusb_et_name(u8); - -/** - * WUSB key index WUSB1.0[7.3.2.4], for usage when setting keys for - * the host or the device. - */ -static inline u8 wusb_key_index(int index, int type, int originator) -{ - return (originator << 6) | (type << 4) | index; -} - -#define WUSB_KEY_INDEX_TYPE_PTK 0 /* for HWA only */ -#define WUSB_KEY_INDEX_TYPE_ASSOC 1 -#define WUSB_KEY_INDEX_TYPE_GTK 2 -#define WUSB_KEY_INDEX_ORIGINATOR_HOST 0 -#define WUSB_KEY_INDEX_ORIGINATOR_DEVICE 1 -/* bits 0-3 used for the key index. */ -#define WUSB_KEY_INDEX_MAX 15 - -/* A CCM Nonce, defined in WUSB1.0[6.4.1] */ -struct aes_ccm_nonce { - u8 sfn[6]; /* Little Endian */ - u8 tkid[3]; /* LE */ - struct uwb_dev_addr dest_addr; - struct uwb_dev_addr src_addr; -} __attribute__((packed)); - -/* A CCM operation label, defined on WUSB1.0[6.5.x] */ -struct aes_ccm_label { - u8 data[14]; -} __attribute__((packed)); - -/* - * Input to the key derivation sequence defined in - * WUSB1.0[6.5.1]. Rest of the data is in the CCM Nonce passed to the - * PRF function. - */ -struct wusb_keydvt_in { - u8 hnonce[16]; - u8 dnonce[16]; -} __attribute__((packed)); - -/* - * Output from the key derivation sequence defined in - * WUSB1.0[6.5.1]. - */ -struct wusb_keydvt_out { - u8 kck[16]; - u8 ptk[16]; -} __attribute__((packed)); - -/* Pseudo Random Function WUSB1.0[6.5] */ -extern int wusb_crypto_init(void); -extern void wusb_crypto_exit(void); -extern ssize_t wusb_prf(void *out, size_t out_size, - const u8 key[16], const struct aes_ccm_nonce *_n, - const struct aes_ccm_label *a, - const void *b, size_t blen, size_t len); - -static inline int wusb_prf_64(void *out, size_t out_size, const u8 key[16], - const struct aes_ccm_nonce *n, - const struct aes_ccm_label *a, - const void *b, size_t blen) -{ - return wusb_prf(out, out_size, key, n, a, b, blen, 64); -} - -static inline int wusb_prf_128(void *out, size_t out_size, const u8 key[16], - const struct aes_ccm_nonce *n, - const struct aes_ccm_label *a, - const void *b, size_t blen) -{ - return wusb_prf(out, out_size, key, n, a, b, blen, 128); -} - -static inline int wusb_prf_256(void *out, size_t out_size, const u8 key[16], - const struct aes_ccm_nonce *n, - const struct aes_ccm_label *a, - const void *b, size_t blen) -{ - return wusb_prf(out, out_size, key, n, a, b, blen, 256); -} - -/* Key derivation WUSB1.0[6.5.1] */ -static inline int wusb_key_derive(struct wusb_keydvt_out *keydvt_out, - const u8 key[16], - const struct aes_ccm_nonce *n, - const struct wusb_keydvt_in *keydvt_in) -{ - const struct aes_ccm_label a = { .data = "Pair-wise keys" }; - return wusb_prf_256(keydvt_out, sizeof(*keydvt_out), key, n, &a, - keydvt_in, sizeof(*keydvt_in)); -} - -/* - * Out-of-band MIC Generation WUSB1.0[6.5.2] - * - * Compute the MIC over @key, @n and @hs and place it in @mic_out. - * - * @mic_out: Where to place the 8 byte MIC tag - * @key: KCK from the derivation process - * @n: CCM nonce, n->sfn == 0, TKID as established in the - * process. - * @hs: Handshake struct for phase 2 of the 4-way. - * hs->bStatus and hs->bReserved are zero. - * hs->bMessageNumber is 2 (WUSB1.0[7.3.2.5.2] - * hs->dest_addr is the device's USB address padded with 0 - * hs->src_addr is the hosts's UWB device address - * hs->mic is ignored (as we compute that value). - */ -static inline int wusb_oob_mic(u8 mic_out[8], const u8 key[16], - const struct aes_ccm_nonce *n, - const struct usb_handshake *hs) -{ - const struct aes_ccm_label a = { .data = "out-of-bandMIC" }; - return wusb_prf_64(mic_out, 8, key, n, &a, - hs, sizeof(*hs) - sizeof(hs->MIC)); -} - -#endif /* #ifndef __WUSB_H__ */ diff --git a/include/linux/user_namespace.h b/include/linux/user_namespace.h index d6b74b91096b..fb9f4f799554 100644 --- a/include/linux/user_namespace.h +++ b/include/linux/user_namespace.h @@ -64,10 +64,20 @@ struct user_namespace { struct ns_common ns; unsigned long flags; +#ifdef CONFIG_KEYS + /* List of joinable keyrings in this namespace. Modification access of + * these pointers is controlled by keyring_sem. Once + * user_keyring_register is set, it won't be changed, so it can be + * accessed directly with READ_ONCE(). + */ + struct list_head keyring_name_list; + struct key *user_keyring_register; + struct rw_semaphore keyring_sem; +#endif + /* Register of per-UID persistent keyrings for this namespace */ #ifdef CONFIG_PERSISTENT_KEYRINGS struct key *persistent_keyring_register; - struct rw_semaphore persistent_keyring_register_sem; #endif struct work_struct work; #ifdef CONFIG_SYSCTL diff --git a/include/linux/uwb.h b/include/linux/uwb.h deleted file mode 100644 index 6918a61e1ac1..000000000000 --- a/include/linux/uwb.h +++ /dev/null @@ -1,817 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Ultra Wide Band - * UWB API - * - * Copyright (C) 2005-2006 Intel Corporation - * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com> - * - * FIXME: doc: overview of the API, different parts and pointers - */ - -#ifndef __LINUX__UWB_H__ -#define __LINUX__UWB_H__ - -#include <linux/limits.h> -#include <linux/device.h> -#include <linux/mutex.h> -#include <linux/timer.h> -#include <linux/wait.h> -#include <linux/workqueue.h> -#include <linux/uwb/spec.h> -#include <asm/page.h> - -struct uwb_dev; -struct uwb_beca_e; -struct uwb_rc; -struct uwb_rsv; -struct uwb_dbg; - -/** - * struct uwb_dev - a UWB Device - * @rc: UWB Radio Controller that discovered the device (kind of its - * parent). - * @bce: a beacon cache entry for this device; or NULL if the device - * is a local radio controller. - * @mac_addr: the EUI-48 address of this device. - * @dev_addr: the current DevAddr used by this device. - * @beacon_slot: the slot number the beacon is using. - * @streams: bitmap of streams allocated to reservations targeted at - * this device. For an RC, this is the streams allocated for - * reservations targeted at DevAddrs. - * - * A UWB device may either by a neighbor or part of a local radio - * controller. - */ -struct uwb_dev { - struct mutex mutex; - struct list_head list_node; - struct device dev; - struct uwb_rc *rc; /* radio controller */ - struct uwb_beca_e *bce; /* Beacon Cache Entry */ - - struct uwb_mac_addr mac_addr; - struct uwb_dev_addr dev_addr; - int beacon_slot; - DECLARE_BITMAP(streams, UWB_NUM_STREAMS); - DECLARE_BITMAP(last_availability_bm, UWB_NUM_MAS); -}; -#define to_uwb_dev(d) container_of(d, struct uwb_dev, dev) - -/** - * UWB HWA/WHCI Radio Control {Command|Event} Block context IDs - * - * RC[CE]Bs have a 'context ID' field that matches the command with - * the event received to confirm it. - * - * Maximum number of context IDs - */ -enum { UWB_RC_CTX_MAX = 256 }; - - -/** Notification chain head for UWB generated events to listeners */ -struct uwb_notifs_chain { - struct list_head list; - struct mutex mutex; -}; - -/* Beacon cache list */ -struct uwb_beca { - struct list_head list; - size_t entries; - struct mutex mutex; -}; - -/* Event handling thread. */ -struct uwbd { - int pid; - struct task_struct *task; - wait_queue_head_t wq; - struct list_head event_list; - spinlock_t event_list_lock; -}; - -/** - * struct uwb_mas_bm - a bitmap of all MAS in a superframe - * @bm: a bitmap of length #UWB_NUM_MAS - */ -struct uwb_mas_bm { - DECLARE_BITMAP(bm, UWB_NUM_MAS); - DECLARE_BITMAP(unsafe_bm, UWB_NUM_MAS); - int safe; - int unsafe; -}; - -/** - * uwb_rsv_state - UWB Reservation state. - * - * NONE - reservation is not active (no DRP IE being transmitted). - * - * Owner reservation states: - * - * INITIATED - owner has sent an initial DRP request. - * PENDING - target responded with pending Reason Code. - * MODIFIED - reservation manager is modifying an established - * reservation with a different MAS allocation. - * ESTABLISHED - the reservation has been successfully negotiated. - * - * Target reservation states: - * - * DENIED - request is denied. - * ACCEPTED - request is accepted. - * PENDING - PAL has yet to make a decision to whether to accept or - * deny. - * - * FIXME: further target states TBD. - */ -enum uwb_rsv_state { - UWB_RSV_STATE_NONE = 0, - UWB_RSV_STATE_O_INITIATED, - UWB_RSV_STATE_O_PENDING, - UWB_RSV_STATE_O_MODIFIED, - UWB_RSV_STATE_O_ESTABLISHED, - UWB_RSV_STATE_O_TO_BE_MOVED, - UWB_RSV_STATE_O_MOVE_EXPANDING, - UWB_RSV_STATE_O_MOVE_COMBINING, - UWB_RSV_STATE_O_MOVE_REDUCING, - UWB_RSV_STATE_T_ACCEPTED, - UWB_RSV_STATE_T_DENIED, - UWB_RSV_STATE_T_CONFLICT, - UWB_RSV_STATE_T_PENDING, - UWB_RSV_STATE_T_EXPANDING_ACCEPTED, - UWB_RSV_STATE_T_EXPANDING_CONFLICT, - UWB_RSV_STATE_T_EXPANDING_PENDING, - UWB_RSV_STATE_T_EXPANDING_DENIED, - UWB_RSV_STATE_T_RESIZED, - - UWB_RSV_STATE_LAST, -}; - -enum uwb_rsv_target_type { - UWB_RSV_TARGET_DEV, - UWB_RSV_TARGET_DEVADDR, -}; - -/** - * struct uwb_rsv_target - the target of a reservation. - * - * Reservations unicast and targeted at a single device - * (UWB_RSV_TARGET_DEV); or (e.g., in the case of WUSB) targeted at a - * specific (private) DevAddr (UWB_RSV_TARGET_DEVADDR). - */ -struct uwb_rsv_target { - enum uwb_rsv_target_type type; - union { - struct uwb_dev *dev; - struct uwb_dev_addr devaddr; - }; -}; - -struct uwb_rsv_move { - struct uwb_mas_bm final_mas; - struct uwb_ie_drp *companion_drp_ie; - struct uwb_mas_bm companion_mas; -}; - -/* - * Number of streams reserved for reservations targeted at DevAddrs. - */ -#define UWB_NUM_GLOBAL_STREAMS 1 - -typedef void (*uwb_rsv_cb_f)(struct uwb_rsv *rsv); - -/** - * struct uwb_rsv - a DRP reservation - * - * Data structure management: - * - * @rc: the radio controller this reservation is for - * (as target or owner) - * @rc_node: a list node for the RC - * @pal_node: a list node for the PAL - * - * Owner and target parameters: - * - * @owner: the UWB device owning this reservation - * @target: the target UWB device - * @type: reservation type - * - * Owner parameters: - * - * @max_mas: maxiumum number of MAS - * @min_mas: minimum number of MAS - * @sparsity: owner selected sparsity - * @is_multicast: true iff multicast - * - * @callback: callback function when the reservation completes - * @pal_priv: private data for the PAL making the reservation - * - * Reservation status: - * - * @status: negotiation status - * @stream: stream index allocated for this reservation - * @tiebreaker: conflict tiebreaker for this reservation - * @mas: reserved MAS - * @drp_ie: the DRP IE - * @ie_valid: true iff the DRP IE matches the reservation parameters - * - * DRP reservations are uniquely identified by the owner, target and - * stream index. However, when using a DevAddr as a target (e.g., for - * a WUSB cluster reservation) the responses may be received from - * devices with different DevAddrs. In this case, reservations are - * uniquely identified by just the stream index. A number of stream - * indexes (UWB_NUM_GLOBAL_STREAMS) are reserved for this. - */ -struct uwb_rsv { - struct uwb_rc *rc; - struct list_head rc_node; - struct list_head pal_node; - struct kref kref; - - struct uwb_dev *owner; - struct uwb_rsv_target target; - enum uwb_drp_type type; - int max_mas; - int min_mas; - int max_interval; - bool is_multicast; - - uwb_rsv_cb_f callback; - void *pal_priv; - - enum uwb_rsv_state state; - bool needs_release_companion_mas; - u8 stream; - u8 tiebreaker; - struct uwb_mas_bm mas; - struct uwb_ie_drp *drp_ie; - struct uwb_rsv_move mv; - bool ie_valid; - struct timer_list timer; - struct work_struct handle_timeout_work; -}; - -static const -struct uwb_mas_bm uwb_mas_bm_zero = { .bm = { 0 } }; - -static inline void uwb_mas_bm_copy_le(void *dst, const struct uwb_mas_bm *mas) -{ - bitmap_copy_le(dst, mas->bm, UWB_NUM_MAS); -} - -/** - * struct uwb_drp_avail - a radio controller's view of MAS usage - * @global: MAS unused by neighbors (excluding reservations targeted - * or owned by the local radio controller) or the beaon period - * @local: MAS unused by local established reservations - * @pending: MAS unused by local pending reservations - * @ie: DRP Availability IE to be included in the beacon - * @ie_valid: true iff @ie is valid and does not need to regenerated from - * @global and @local - * - * Each radio controller maintains a view of MAS usage or - * availability. MAS available for a new reservation are determined - * from the intersection of @global, @local, and @pending. - * - * The radio controller must transmit a DRP Availability IE that's the - * intersection of @global and @local. - * - * A set bit indicates the MAS is unused and available. - * - * rc->rsvs_mutex should be held before accessing this data structure. - * - * [ECMA-368] section 17.4.3. - */ -struct uwb_drp_avail { - DECLARE_BITMAP(global, UWB_NUM_MAS); - DECLARE_BITMAP(local, UWB_NUM_MAS); - DECLARE_BITMAP(pending, UWB_NUM_MAS); - struct uwb_ie_drp_avail ie; - bool ie_valid; -}; - -struct uwb_drp_backoff_win { - u8 window; - u8 n; - int total_expired; - struct timer_list timer; - bool can_reserve_extra_mases; -}; - -const char *uwb_rsv_state_str(enum uwb_rsv_state state); -const char *uwb_rsv_type_str(enum uwb_drp_type type); - -struct uwb_rsv *uwb_rsv_create(struct uwb_rc *rc, uwb_rsv_cb_f cb, - void *pal_priv); -void uwb_rsv_destroy(struct uwb_rsv *rsv); - -int uwb_rsv_establish(struct uwb_rsv *rsv); -int uwb_rsv_modify(struct uwb_rsv *rsv, - int max_mas, int min_mas, int sparsity); -void uwb_rsv_terminate(struct uwb_rsv *rsv); - -void uwb_rsv_accept(struct uwb_rsv *rsv, uwb_rsv_cb_f cb, void *pal_priv); - -void uwb_rsv_get_usable_mas(struct uwb_rsv *orig_rsv, struct uwb_mas_bm *mas); - -/** - * Radio Control Interface instance - * - * - * Life cycle rules: those of the UWB Device. - * - * @index: an index number for this radio controller, as used in the - * device name. - * @version: version of protocol supported by this device - * @priv: Backend implementation; rw with uwb_dev.dev.sem taken. - * @cmd: Backend implementation to execute commands; rw and call - * only with uwb_dev.dev.sem taken. - * @reset: Hardware reset of radio controller and any PAL controllers. - * @filter: Backend implementation to manipulate data to and from device - * to be compliant to specification assumed by driver (WHCI - * 0.95). - * - * uwb_dev.dev.mutex is used to execute commands and update - * the corresponding structures; can't use a spinlock - * because rc->cmd() can sleep. - * @ies: This is a dynamically allocated array cacheing the - * IEs (settable by the host) that the beacon of this - * radio controller is currently sending. - * - * In reality, we store here the full command we set to - * the radio controller (which is basically a command - * prefix followed by all the IEs the beacon currently - * contains). This way we don't have to realloc and - * memcpy when setting it. - * - * We set this up in uwb_rc_ie_setup(), where we alloc - * this struct, call get_ie() [so we know which IEs are - * currently being sent, if any]. - * - * @ies_capacity:Amount of space (in bytes) allocated in @ies. The - * amount used is given by sizeof(*ies) plus ies->wIELength - * (which is a little endian quantity all the time). - * @ies_mutex: protect the IE cache - * @dbg: information for the debug interface - */ -struct uwb_rc { - struct uwb_dev uwb_dev; - int index; - u16 version; - - struct module *owner; - void *priv; - int (*start)(struct uwb_rc *rc); - void (*stop)(struct uwb_rc *rc); - int (*cmd)(struct uwb_rc *, const struct uwb_rccb *, size_t); - int (*reset)(struct uwb_rc *rc); - int (*filter_cmd)(struct uwb_rc *, struct uwb_rccb **, size_t *); - int (*filter_event)(struct uwb_rc *, struct uwb_rceb **, const size_t, - size_t *, size_t *); - - spinlock_t neh_lock; /* protects neh_* and ctx_* */ - struct list_head neh_list; /* Open NE handles */ - unsigned long ctx_bm[UWB_RC_CTX_MAX / 8 / sizeof(unsigned long)]; - u8 ctx_roll; - - int beaconing; /* Beaconing state [channel number] */ - int beaconing_forced; - int scanning; - enum uwb_scan_type scan_type:3; - unsigned ready:1; - struct uwb_notifs_chain notifs_chain; - struct uwb_beca uwb_beca; - - struct uwbd uwbd; - - struct uwb_drp_backoff_win bow; - struct uwb_drp_avail drp_avail; - struct list_head reservations; - struct list_head cnflt_alien_list; - struct uwb_mas_bm cnflt_alien_bitmap; - struct mutex rsvs_mutex; - spinlock_t rsvs_lock; - struct workqueue_struct *rsv_workq; - - struct delayed_work rsv_update_work; - struct delayed_work rsv_alien_bp_work; - int set_drp_ie_pending; - struct mutex ies_mutex; - struct uwb_rc_cmd_set_ie *ies; - size_t ies_capacity; - - struct list_head pals; - int active_pals; - - struct uwb_dbg *dbg; -}; - - -/** - * struct uwb_pal - a UWB PAL - * @name: descriptive name for this PAL (wusbhc, wlp, etc.). - * @device: a device for the PAL. Used to link the PAL and the radio - * controller in sysfs. - * @rc: the radio controller the PAL uses. - * @channel_changed: called when the channel used by the radio changes. - * A channel of -1 means the channel has been stopped. - * @new_rsv: called when a peer requests a reservation (may be NULL if - * the PAL cannot accept reservation requests). - * @channel: channel being used by the PAL; 0 if the PAL isn't using - * the radio; -1 if the PAL wishes to use the radio but - * cannot. - * @debugfs_dir: a debugfs directory which the PAL can use for its own - * debugfs files. - * - * A Protocol Adaptation Layer (PAL) is a user of the WiMedia UWB - * radio platform (e.g., WUSB, WLP or Bluetooth UWB AMP). - * - * The PALs using a radio controller must register themselves to - * permit the UWB stack to coordinate usage of the radio between the - * various PALs or to allow PALs to response to certain requests from - * peers. - * - * A struct uwb_pal should be embedded in a containing structure - * belonging to the PAL and initialized with uwb_pal_init()). Fields - * should be set appropriately by the PAL before registering the PAL - * with uwb_pal_register(). - */ -struct uwb_pal { - struct list_head node; - const char *name; - struct device *device; - struct uwb_rc *rc; - - void (*channel_changed)(struct uwb_pal *pal, int channel); - void (*new_rsv)(struct uwb_pal *pal, struct uwb_rsv *rsv); - - int channel; - struct dentry *debugfs_dir; -}; - -void uwb_pal_init(struct uwb_pal *pal); -int uwb_pal_register(struct uwb_pal *pal); -void uwb_pal_unregister(struct uwb_pal *pal); - -int uwb_radio_start(struct uwb_pal *pal); -void uwb_radio_stop(struct uwb_pal *pal); - -/* - * General public API - * - * This API can be used by UWB device drivers or by those implementing - * UWB Radio Controllers - */ -struct uwb_dev *uwb_dev_get_by_devaddr(struct uwb_rc *rc, - const struct uwb_dev_addr *devaddr); -struct uwb_dev *uwb_dev_get_by_rc(struct uwb_dev *, struct uwb_rc *); -static inline void uwb_dev_get(struct uwb_dev *uwb_dev) -{ - get_device(&uwb_dev->dev); -} -static inline void uwb_dev_put(struct uwb_dev *uwb_dev) -{ - put_device(&uwb_dev->dev); -} -struct uwb_dev *uwb_dev_try_get(struct uwb_rc *rc, struct uwb_dev *uwb_dev); - -/** - * Callback function for 'uwb_{dev,rc}_foreach()'. - * - * @dev: Linux device instance - * 'uwb_dev = container_of(dev, struct uwb_dev, dev)' - * @priv: Data passed by the caller to 'uwb_{dev,rc}_foreach()'. - * - * @returns: 0 to continue the iterations, any other val to stop - * iterating and return the value to the caller of - * _foreach(). - */ -typedef int (*uwb_dev_for_each_f)(struct device *dev, void *priv); -int uwb_dev_for_each(struct uwb_rc *rc, uwb_dev_for_each_f func, void *priv); - -struct uwb_rc *uwb_rc_alloc(void); -struct uwb_rc *uwb_rc_get_by_dev(const struct uwb_dev_addr *); -struct uwb_rc *uwb_rc_get_by_grandpa(const struct device *); -void uwb_rc_put(struct uwb_rc *rc); - -typedef void (*uwb_rc_cmd_cb_f)(struct uwb_rc *rc, void *arg, - struct uwb_rceb *reply, ssize_t reply_size); - -int uwb_rc_cmd_async(struct uwb_rc *rc, const char *cmd_name, - struct uwb_rccb *cmd, size_t cmd_size, - u8 expected_type, u16 expected_event, - uwb_rc_cmd_cb_f cb, void *arg); -ssize_t uwb_rc_cmd(struct uwb_rc *rc, const char *cmd_name, - struct uwb_rccb *cmd, size_t cmd_size, - struct uwb_rceb *reply, size_t reply_size); -ssize_t uwb_rc_vcmd(struct uwb_rc *rc, const char *cmd_name, - struct uwb_rccb *cmd, size_t cmd_size, - u8 expected_type, u16 expected_event, - struct uwb_rceb **preply); - -size_t __uwb_addr_print(char *, size_t, const unsigned char *, int); - -int uwb_rc_dev_addr_set(struct uwb_rc *, const struct uwb_dev_addr *); -int uwb_rc_dev_addr_get(struct uwb_rc *, struct uwb_dev_addr *); -int uwb_rc_mac_addr_set(struct uwb_rc *, const struct uwb_mac_addr *); -int uwb_rc_mac_addr_get(struct uwb_rc *, struct uwb_mac_addr *); -int __uwb_mac_addr_assigned_check(struct device *, void *); -int __uwb_dev_addr_assigned_check(struct device *, void *); - -/* Print in @buf a pretty repr of @addr */ -static inline size_t uwb_dev_addr_print(char *buf, size_t buf_size, - const struct uwb_dev_addr *addr) -{ - return __uwb_addr_print(buf, buf_size, addr->data, 0); -} - -/* Print in @buf a pretty repr of @addr */ -static inline size_t uwb_mac_addr_print(char *buf, size_t buf_size, - const struct uwb_mac_addr *addr) -{ - return __uwb_addr_print(buf, buf_size, addr->data, 1); -} - -/* @returns 0 if device addresses @addr2 and @addr1 are equal */ -static inline int uwb_dev_addr_cmp(const struct uwb_dev_addr *addr1, - const struct uwb_dev_addr *addr2) -{ - return memcmp(addr1, addr2, sizeof(*addr1)); -} - -/* @returns 0 if MAC addresses @addr2 and @addr1 are equal */ -static inline int uwb_mac_addr_cmp(const struct uwb_mac_addr *addr1, - const struct uwb_mac_addr *addr2) -{ - return memcmp(addr1, addr2, sizeof(*addr1)); -} - -/* @returns !0 if a MAC @addr is a broadcast address */ -static inline int uwb_mac_addr_bcast(const struct uwb_mac_addr *addr) -{ - struct uwb_mac_addr bcast = { - .data = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } - }; - return !uwb_mac_addr_cmp(addr, &bcast); -} - -/* @returns !0 if a MAC @addr is all zeroes*/ -static inline int uwb_mac_addr_unset(const struct uwb_mac_addr *addr) -{ - struct uwb_mac_addr unset = { - .data = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } - }; - return !uwb_mac_addr_cmp(addr, &unset); -} - -/* @returns !0 if the address is in use. */ -static inline unsigned __uwb_dev_addr_assigned(struct uwb_rc *rc, - struct uwb_dev_addr *addr) -{ - return uwb_dev_for_each(rc, __uwb_dev_addr_assigned_check, addr); -} - -/* - * UWB Radio Controller API - * - * This API is used (in addition to the general API) to implement UWB - * Radio Controllers. - */ -void uwb_rc_init(struct uwb_rc *); -int uwb_rc_add(struct uwb_rc *, struct device *dev, void *rc_priv); -void uwb_rc_rm(struct uwb_rc *); -void uwb_rc_neh_grok(struct uwb_rc *, void *, size_t); -void uwb_rc_neh_error(struct uwb_rc *, int); -void uwb_rc_reset_all(struct uwb_rc *rc); -void uwb_rc_pre_reset(struct uwb_rc *rc); -int uwb_rc_post_reset(struct uwb_rc *rc); - -/** - * uwb_rsv_is_owner - is the owner of this reservation the RC? - * @rsv: the reservation - */ -static inline bool uwb_rsv_is_owner(struct uwb_rsv *rsv) -{ - return rsv->owner == &rsv->rc->uwb_dev; -} - -/** - * enum uwb_notifs - UWB events that can be passed to any listeners - * @UWB_NOTIF_ONAIR: a new neighbour has joined the beacon group. - * @UWB_NOTIF_OFFAIR: a neighbour has left the beacon group. - * - * Higher layers can register callback functions with the radio - * controller using uwb_notifs_register(). The radio controller - * maintains a list of all registered handlers and will notify all - * nodes when an event occurs. - */ -enum uwb_notifs { - UWB_NOTIF_ONAIR, - UWB_NOTIF_OFFAIR, -}; - -/* Callback function registered with UWB */ -struct uwb_notifs_handler { - struct list_head list_node; - void (*cb)(void *, struct uwb_dev *, enum uwb_notifs); - void *data; -}; - -int uwb_notifs_register(struct uwb_rc *, struct uwb_notifs_handler *); -int uwb_notifs_deregister(struct uwb_rc *, struct uwb_notifs_handler *); - - -/** - * UWB radio controller Event Size Entry (for creating entry tables) - * - * WUSB and WHCI define events and notifications, and they might have - * fixed or variable size. - * - * Each event/notification has a size which is not necessarily known - * in advance based on the event code. As well, vendor specific - * events/notifications will have a size impossible to determine - * unless we know about the device's specific details. - * - * It was way too smart of the spec writers not to think that it would - * be impossible for a generic driver to skip over vendor specific - * events/notifications if there are no LENGTH fields in the HEADER of - * each message...the transaction size cannot be counted on as the - * spec does not forbid to pack more than one event in a single - * transaction. - * - * Thus, we guess sizes with tables (or for events, when you know the - * size ahead of time you can use uwb_rc_neh_extra_size*()). We - * register tables with the known events and their sizes, and then we - * traverse those tables. For those with variable length, we provide a - * way to lookup the size inside the event/notification's - * payload. This allows device-specific event size tables to be - * registered. - * - * @size: Size of the payload - * - * @offset: if != 0, at offset @offset-1 starts a field with a length - * that has to be added to @size. The format of the field is - * given by @type. - * - * @type: Type and length of the offset field. Most common is LE 16 - * bits (that's why that is zero); others are there mostly to - * cover for bugs and weirdos. - */ -struct uwb_est_entry { - size_t size; - unsigned offset; - enum { UWB_EST_16 = 0, UWB_EST_8 = 1 } type; -}; - -int uwb_est_register(u8 type, u8 code_high, u16 vendor, u16 product, - const struct uwb_est_entry *, size_t entries); -int uwb_est_unregister(u8 type, u8 code_high, u16 vendor, u16 product, - const struct uwb_est_entry *, size_t entries); -ssize_t uwb_est_find_size(struct uwb_rc *rc, const struct uwb_rceb *rceb, - size_t len); - -/* -- Misc */ - -enum { - EDC_MAX_ERRORS = 10, - EDC_ERROR_TIMEFRAME = HZ, -}; - -/* error density counter */ -struct edc { - unsigned long timestart; - u16 errorcount; -}; - -static inline -void edc_init(struct edc *edc) -{ - edc->timestart = jiffies; -} - -/* Called when an error occurred. - * This is way to determine if the number of acceptable errors per time - * period has been exceeded. It is not accurate as there are cases in which - * this scheme will not work, for example if there are periodic occurrences - * of errors that straddle updates to the start time. This scheme is - * sufficient for our usage. - * - * @returns 1 if maximum acceptable errors per timeframe has been exceeded. - */ -static inline int edc_inc(struct edc *err_hist, u16 max_err, u16 timeframe) -{ - unsigned long now; - - now = jiffies; - if (now - err_hist->timestart > timeframe) { - err_hist->errorcount = 1; - err_hist->timestart = now; - } else if (++err_hist->errorcount > max_err) { - err_hist->errorcount = 0; - err_hist->timestart = now; - return 1; - } - return 0; -} - - -/* Information Element handling */ - -struct uwb_ie_hdr *uwb_ie_next(void **ptr, size_t *len); -int uwb_rc_ie_add(struct uwb_rc *uwb_rc, const struct uwb_ie_hdr *ies, size_t size); -int uwb_rc_ie_rm(struct uwb_rc *uwb_rc, enum uwb_ie element_id); - -/* - * Transmission statistics - * - * UWB uses LQI and RSSI (one byte values) for reporting radio signal - * strength and line quality indication. We do quick and dirty - * averages of those. They are signed values, btw. - * - * For 8 bit quantities, we keep the min, the max, an accumulator - * (@sigma) and a # of samples. When @samples gets to 255, we compute - * the average (@sigma / @samples), place it in @sigma and reset - * @samples to 1 (so we use it as the first sample). - * - * Now, statistically speaking, probably I am kicking the kidneys of - * some books I have in my shelves collecting dust, but I just want to - * get an approx, not the Nobel. - * - * LOCKING: there is no locking per se, but we try to keep a lockless - * schema. Only _add_samples() modifies the values--as long as you - * have other locking on top that makes sure that no two calls of - * _add_sample() happen at the same time, then we are fine. Now, for - * resetting the values we just set @samples to 0 and that makes the - * next _add_sample() to start with defaults. Reading the values in - * _show() currently can race, so you need to make sure the calls are - * under the same lock that protects calls to _add_sample(). FIXME: - * currently unlocked (It is not ultraprecise but does the trick. Bite - * me). - */ -struct stats { - s8 min, max; - s16 sigma; - atomic_t samples; -}; - -static inline -void stats_init(struct stats *stats) -{ - atomic_set(&stats->samples, 0); - wmb(); -} - -static inline -void stats_add_sample(struct stats *stats, s8 sample) -{ - s8 min, max; - s16 sigma; - unsigned samples = atomic_read(&stats->samples); - if (samples == 0) { /* it was zero before, so we initialize */ - min = 127; - max = -128; - sigma = 0; - } else { - min = stats->min; - max = stats->max; - sigma = stats->sigma; - } - - if (sample < min) /* compute new values */ - min = sample; - else if (sample > max) - max = sample; - sigma += sample; - - stats->min = min; /* commit */ - stats->max = max; - stats->sigma = sigma; - if (atomic_add_return(1, &stats->samples) > 255) { - /* wrapped around! reset */ - stats->sigma = sigma / 256; - atomic_set(&stats->samples, 1); - } -} - -static inline ssize_t stats_show(struct stats *stats, char *buf) -{ - int min, max, avg; - int samples = atomic_read(&stats->samples); - if (samples == 0) - min = max = avg = 0; - else { - min = stats->min; - max = stats->max; - avg = stats->sigma / samples; - } - return scnprintf(buf, PAGE_SIZE, "%d %d %d\n", min, max, avg); -} - -static inline ssize_t stats_store(struct stats *stats, const char *buf, - size_t size) -{ - stats_init(stats); - return size; -} - -#endif /* #ifndef __LINUX__UWB_H__ */ diff --git a/include/linux/uwb/debug-cmd.h b/include/linux/uwb/debug-cmd.h deleted file mode 100644 index f97db6c3bcc0..000000000000 --- a/include/linux/uwb/debug-cmd.h +++ /dev/null @@ -1,57 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Ultra Wide Band - * Debug interface commands - * - * Copyright (C) 2008 Cambridge Silicon Radio Ltd. - */ -#ifndef __LINUX__UWB__DEBUG_CMD_H__ -#define __LINUX__UWB__DEBUG_CMD_H__ - -#include <linux/types.h> - -/* - * Debug interface commands - * - * UWB_DBG_CMD_RSV_ESTABLISH: Establish a new unicast reservation. - * - * UWB_DBG_CMD_RSV_TERMINATE: Terminate the Nth reservation. - */ - -enum uwb_dbg_cmd_type { - UWB_DBG_CMD_RSV_ESTABLISH = 1, - UWB_DBG_CMD_RSV_TERMINATE = 2, - UWB_DBG_CMD_IE_ADD = 3, - UWB_DBG_CMD_IE_RM = 4, - UWB_DBG_CMD_RADIO_START = 5, - UWB_DBG_CMD_RADIO_STOP = 6, -}; - -struct uwb_dbg_cmd_rsv_establish { - __u8 target[6]; - __u8 type; - __u16 max_mas; - __u16 min_mas; - __u8 max_interval; -}; - -struct uwb_dbg_cmd_rsv_terminate { - int index; -}; - -struct uwb_dbg_cmd_ie { - __u8 data[128]; - int len; -}; - -struct uwb_dbg_cmd { - __u32 type; - union { - struct uwb_dbg_cmd_rsv_establish rsv_establish; - struct uwb_dbg_cmd_rsv_terminate rsv_terminate; - struct uwb_dbg_cmd_ie ie_add; - struct uwb_dbg_cmd_ie ie_rm; - }; -}; - -#endif /* #ifndef __LINUX__UWB__DEBUG_CMD_H__ */ diff --git a/include/linux/uwb/spec.h b/include/linux/uwb/spec.h deleted file mode 100644 index 5f75caf7b4ba..000000000000 --- a/include/linux/uwb/spec.h +++ /dev/null @@ -1,767 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Ultra Wide Band - * UWB Standard definitions - * - * Copyright (C) 2005-2006 Intel Corporation - * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com> - * - * All these definitions are based on the ECMA-368 standard. - * - * Note all definitions are Little Endian in the wire, and we will - * convert them to host order before operating on the bitfields (that - * yes, we use extensively). - */ - -#ifndef __LINUX__UWB_SPEC_H__ -#define __LINUX__UWB_SPEC_H__ - -#include <linux/types.h> -#include <linux/bitmap.h> -#include <linux/if_ether.h> - -#define i1480_FW 0x00000303 -/* #define i1480_FW 0x00000302 */ - -/** - * Number of Medium Access Slots in a superframe. - * - * UWB divides time in SuperFrames, each one divided in 256 pieces, or - * Medium Access Slots. See MBOA MAC[5.4.5] for details. The MAS is the - * basic bandwidth allocation unit in UWB. - */ -enum { UWB_NUM_MAS = 256 }; - -/** - * Number of Zones in superframe. - * - * UWB divides the superframe into zones with numbering starting from BPST. - * See MBOA MAC[16.8.6] - */ -enum { UWB_NUM_ZONES = 16 }; - -/* - * Number of MAS in a zone. - */ -#define UWB_MAS_PER_ZONE (UWB_NUM_MAS / UWB_NUM_ZONES) - -/* - * Number of MAS required before a row can be considered available. - */ -#define UWB_USABLE_MAS_PER_ROW (UWB_NUM_ZONES - 1) - -/* - * Number of streams per DRP reservation between a pair of devices. - * - * [ECMA-368] section 16.8.6. - */ -enum { UWB_NUM_STREAMS = 8 }; - -/* - * mMasLength - * - * The length of a MAS in microseconds. - * - * [ECMA-368] section 17.16. - */ -enum { UWB_MAS_LENGTH_US = 256 }; - -/* - * mBeaconSlotLength - * - * The length of the beacon slot in microseconds. - * - * [ECMA-368] section 17.16 - */ -enum { UWB_BEACON_SLOT_LENGTH_US = 85 }; - -/* - * mMaxLostBeacons - * - * The number beacons missing in consecutive superframes before a - * device can be considered as unreachable. - * - * [ECMA-368] section 17.16 - */ -enum { UWB_MAX_LOST_BEACONS = 3 }; - -/* - * mDRPBackOffWinMin - * - * The minimum number of superframes to wait before trying to reserve - * extra MAS. - * - * [ECMA-368] section 17.16 - */ -enum { UWB_DRP_BACKOFF_WIN_MIN = 2 }; - -/* - * mDRPBackOffWinMax - * - * The maximum number of superframes to wait before trying to reserve - * extra MAS. - * - * [ECMA-368] section 17.16 - */ -enum { UWB_DRP_BACKOFF_WIN_MAX = 16 }; - -/* - * Length of a superframe in microseconds. - */ -#define UWB_SUPERFRAME_LENGTH_US (UWB_MAS_LENGTH_US * UWB_NUM_MAS) - -/** - * UWB MAC address - * - * It is *imperative* that this struct is exactly 6 packed bytes (as - * it is also used to define headers sent down and up the wire/radio). - */ -struct uwb_mac_addr { - u8 data[ETH_ALEN]; -} __attribute__((packed)); - - -/** - * UWB device address - * - * It is *imperative* that this struct is exactly 6 packed bytes (as - * it is also used to define headers sent down and up the wire/radio). - */ -struct uwb_dev_addr { - u8 data[2]; -} __attribute__((packed)); - - -/** - * Types of UWB addresses - * - * Order matters (by size). - */ -enum uwb_addr_type { - UWB_ADDR_DEV = 0, - UWB_ADDR_MAC = 1, -}; - - -/** Size of a char buffer for printing a MAC/device address */ -enum { UWB_ADDR_STRSIZE = 32 }; - - -/** UWB WiMedia protocol IDs. */ -enum uwb_prid { - UWB_PRID_WLP_RESERVED = 0x0000, - UWB_PRID_WLP = 0x0001, - UWB_PRID_WUSB_BOT = 0x0010, - UWB_PRID_WUSB = 0x0010, - UWB_PRID_WUSB_TOP = 0x001F, -}; - - -/** PHY Rate (MBOA MAC[7.8.12, Table 61]) */ -enum uwb_phy_rate { - UWB_PHY_RATE_53 = 0, - UWB_PHY_RATE_80, - UWB_PHY_RATE_106, - UWB_PHY_RATE_160, - UWB_PHY_RATE_200, - UWB_PHY_RATE_320, - UWB_PHY_RATE_400, - UWB_PHY_RATE_480, - UWB_PHY_RATE_INVALID -}; - - -/** - * Different ways to scan (MBOA MAC[6.2.2, Table 8], WUSB[Table 8-78]) - */ -enum uwb_scan_type { - UWB_SCAN_ONLY = 0, - UWB_SCAN_OUTSIDE_BP, - UWB_SCAN_WHILE_INACTIVE, - UWB_SCAN_DISABLED, - UWB_SCAN_ONLY_STARTTIME, - UWB_SCAN_TOP -}; - - -/** ACK Policy types (MBOA MAC[7.2.1.3]) */ -enum uwb_ack_pol { - UWB_ACK_NO = 0, - UWB_ACK_INM = 1, - UWB_ACK_B = 2, - UWB_ACK_B_REQ = 3, -}; - - -/** DRP reservation types ([ECMA-368 table 106) */ -enum uwb_drp_type { - UWB_DRP_TYPE_ALIEN_BP = 0, - UWB_DRP_TYPE_HARD, - UWB_DRP_TYPE_SOFT, - UWB_DRP_TYPE_PRIVATE, - UWB_DRP_TYPE_PCA, -}; - - -/** DRP Reason Codes ([ECMA-368] table 107) */ -enum uwb_drp_reason { - UWB_DRP_REASON_ACCEPTED = 0, - UWB_DRP_REASON_CONFLICT, - UWB_DRP_REASON_PENDING, - UWB_DRP_REASON_DENIED, - UWB_DRP_REASON_MODIFIED, -}; - -/** Relinquish Request Reason Codes ([ECMA-368] table 113) */ -enum uwb_relinquish_req_reason { - UWB_RELINQUISH_REQ_REASON_NON_SPECIFIC = 0, - UWB_RELINQUISH_REQ_REASON_OVER_ALLOCATION, -}; - -/** - * DRP Notification Reason Codes (WHCI 0.95 [3.1.4.9]) - */ -enum uwb_drp_notif_reason { - UWB_DRP_NOTIF_DRP_IE_RCVD = 0, - UWB_DRP_NOTIF_CONFLICT, - UWB_DRP_NOTIF_TERMINATE, -}; - - -/** Allocation of MAS slots in a DRP request MBOA MAC[7.8.7] */ -struct uwb_drp_alloc { - __le16 zone_bm; - __le16 mas_bm; -} __attribute__((packed)); - - -/** General MAC Header format (ECMA-368[16.2]) */ -struct uwb_mac_frame_hdr { - __le16 Frame_Control; - struct uwb_dev_addr DestAddr; - struct uwb_dev_addr SrcAddr; - __le16 Sequence_Control; - __le16 Access_Information; -} __attribute__((packed)); - - -/** - * uwb_beacon_frame - a beacon frame including MAC headers - * - * [ECMA] section 16.3. - */ -struct uwb_beacon_frame { - struct uwb_mac_frame_hdr hdr; - struct uwb_mac_addr Device_Identifier; /* may be a NULL EUI-48 */ - u8 Beacon_Slot_Number; - u8 Device_Control; - u8 IEData[]; -} __attribute__((packed)); - - -/** Information Element codes (MBOA MAC[T54]) */ -enum uwb_ie { - UWB_PCA_AVAILABILITY = 2, - UWB_IE_DRP_AVAILABILITY = 8, - UWB_IE_DRP = 9, - UWB_BP_SWITCH_IE = 11, - UWB_MAC_CAPABILITIES_IE = 12, - UWB_PHY_CAPABILITIES_IE = 13, - UWB_APP_SPEC_PROBE_IE = 15, - UWB_IDENTIFICATION_IE = 19, - UWB_MASTER_KEY_ID_IE = 20, - UWB_RELINQUISH_REQUEST_IE = 21, - UWB_IE_WLP = 250, /* WiMedia Logical Link Control Protocol WLP 0.99 */ - UWB_APP_SPEC_IE = 255, -}; - - -/** - * Header common to all Information Elements (IEs) - */ -struct uwb_ie_hdr { - u8 element_id; /* enum uwb_ie */ - u8 length; -} __attribute__((packed)); - - -/** Dynamic Reservation Protocol IE (MBOA MAC[7.8.6]) */ -struct uwb_ie_drp { - struct uwb_ie_hdr hdr; - __le16 drp_control; - struct uwb_dev_addr dev_addr; - struct uwb_drp_alloc allocs[]; -} __attribute__((packed)); - -static inline int uwb_ie_drp_type(struct uwb_ie_drp *ie) -{ - return (le16_to_cpu(ie->drp_control) >> 0) & 0x7; -} - -static inline int uwb_ie_drp_stream_index(struct uwb_ie_drp *ie) -{ - return (le16_to_cpu(ie->drp_control) >> 3) & 0x7; -} - -static inline int uwb_ie_drp_reason_code(struct uwb_ie_drp *ie) -{ - return (le16_to_cpu(ie->drp_control) >> 6) & 0x7; -} - -static inline int uwb_ie_drp_status(struct uwb_ie_drp *ie) -{ - return (le16_to_cpu(ie->drp_control) >> 9) & 0x1; -} - -static inline int uwb_ie_drp_owner(struct uwb_ie_drp *ie) -{ - return (le16_to_cpu(ie->drp_control) >> 10) & 0x1; -} - -static inline int uwb_ie_drp_tiebreaker(struct uwb_ie_drp *ie) -{ - return (le16_to_cpu(ie->drp_control) >> 11) & 0x1; -} - -static inline int uwb_ie_drp_unsafe(struct uwb_ie_drp *ie) -{ - return (le16_to_cpu(ie->drp_control) >> 12) & 0x1; -} - -static inline void uwb_ie_drp_set_type(struct uwb_ie_drp *ie, enum uwb_drp_type type) -{ - u16 drp_control = le16_to_cpu(ie->drp_control); - drp_control = (drp_control & ~(0x7 << 0)) | (type << 0); - ie->drp_control = cpu_to_le16(drp_control); -} - -static inline void uwb_ie_drp_set_stream_index(struct uwb_ie_drp *ie, int stream_index) -{ - u16 drp_control = le16_to_cpu(ie->drp_control); - drp_control = (drp_control & ~(0x7 << 3)) | (stream_index << 3); - ie->drp_control = cpu_to_le16(drp_control); -} - -static inline void uwb_ie_drp_set_reason_code(struct uwb_ie_drp *ie, - enum uwb_drp_reason reason_code) -{ - u16 drp_control = le16_to_cpu(ie->drp_control); - drp_control = (ie->drp_control & ~(0x7 << 6)) | (reason_code << 6); - ie->drp_control = cpu_to_le16(drp_control); -} - -static inline void uwb_ie_drp_set_status(struct uwb_ie_drp *ie, int status) -{ - u16 drp_control = le16_to_cpu(ie->drp_control); - drp_control = (drp_control & ~(0x1 << 9)) | (status << 9); - ie->drp_control = cpu_to_le16(drp_control); -} - -static inline void uwb_ie_drp_set_owner(struct uwb_ie_drp *ie, int owner) -{ - u16 drp_control = le16_to_cpu(ie->drp_control); - drp_control = (drp_control & ~(0x1 << 10)) | (owner << 10); - ie->drp_control = cpu_to_le16(drp_control); -} - -static inline void uwb_ie_drp_set_tiebreaker(struct uwb_ie_drp *ie, int tiebreaker) -{ - u16 drp_control = le16_to_cpu(ie->drp_control); - drp_control = (drp_control & ~(0x1 << 11)) | (tiebreaker << 11); - ie->drp_control = cpu_to_le16(drp_control); -} - -static inline void uwb_ie_drp_set_unsafe(struct uwb_ie_drp *ie, int unsafe) -{ - u16 drp_control = le16_to_cpu(ie->drp_control); - drp_control = (drp_control & ~(0x1 << 12)) | (unsafe << 12); - ie->drp_control = cpu_to_le16(drp_control); -} - -/** Dynamic Reservation Protocol IE (MBOA MAC[7.8.7]) */ -struct uwb_ie_drp_avail { - struct uwb_ie_hdr hdr; - DECLARE_BITMAP(bmp, UWB_NUM_MAS); -} __attribute__((packed)); - -/* Relinqish Request IE ([ECMA-368] section 16.8.19). */ -struct uwb_relinquish_request_ie { - struct uwb_ie_hdr hdr; - __le16 relinquish_req_control; - struct uwb_dev_addr dev_addr; - struct uwb_drp_alloc allocs[]; -} __attribute__((packed)); - -static inline int uwb_ie_relinquish_req_reason_code(struct uwb_relinquish_request_ie *ie) -{ - return (le16_to_cpu(ie->relinquish_req_control) >> 0) & 0xf; -} - -static inline void uwb_ie_relinquish_req_set_reason_code(struct uwb_relinquish_request_ie *ie, - int reason_code) -{ - u16 ctrl = le16_to_cpu(ie->relinquish_req_control); - ctrl = (ctrl & ~(0xf << 0)) | (reason_code << 0); - ie->relinquish_req_control = cpu_to_le16(ctrl); -} - -/** - * The Vendor ID is set to an OUI that indicates the vendor of the device. - * ECMA-368 [16.8.10] - */ -struct uwb_vendor_id { - u8 data[3]; -} __attribute__((packed)); - -/** - * The device type ID - * FIXME: clarify what this means - * ECMA-368 [16.8.10] - */ -struct uwb_device_type_id { - u8 data[3]; -} __attribute__((packed)); - - -/** - * UWB device information types - * ECMA-368 [16.8.10] - */ -enum uwb_dev_info_type { - UWB_DEV_INFO_VENDOR_ID = 0, - UWB_DEV_INFO_VENDOR_TYPE, - UWB_DEV_INFO_NAME, -}; - -/** - * UWB device information found in Identification IE - * ECMA-368 [16.8.10] - */ -struct uwb_dev_info { - u8 type; /* enum uwb_dev_info_type */ - u8 length; - u8 data[]; -} __attribute__((packed)); - -/** - * UWB Identification IE - * ECMA-368 [16.8.10] - */ -struct uwb_identification_ie { - struct uwb_ie_hdr hdr; - struct uwb_dev_info info[]; -} __attribute__((packed)); - -/* - * UWB Radio Controller - * - * These definitions are common to the Radio Control layers as - * exported by the WUSB1.0 HWA and WHCI interfaces. - */ - -/** Radio Control Command Block (WUSB1.0[Table 8-65] and WHCI 0.95) */ -struct uwb_rccb { - u8 bCommandType; /* enum hwa_cet */ - __le16 wCommand; /* Command code */ - u8 bCommandContext; /* Context ID */ -} __attribute__((packed)); - - -/** Radio Control Event Block (WUSB[table 8-66], WHCI 0.95) */ -struct uwb_rceb { - u8 bEventType; /* enum hwa_cet */ - __le16 wEvent; /* Event code */ - u8 bEventContext; /* Context ID */ -} __attribute__((packed)); - - -enum { - UWB_RC_CET_GENERAL = 0, /* General Command/Event type */ - UWB_RC_CET_EX_TYPE_1 = 1, /* Extended Type 1 Command/Event type */ -}; - -/* Commands to the radio controller */ -enum uwb_rc_cmd { - UWB_RC_CMD_CHANNEL_CHANGE = 16, - UWB_RC_CMD_DEV_ADDR_MGMT = 17, /* Device Address Management */ - UWB_RC_CMD_GET_IE = 18, /* GET Information Elements */ - UWB_RC_CMD_RESET = 19, - UWB_RC_CMD_SCAN = 20, /* Scan management */ - UWB_RC_CMD_SET_BEACON_FILTER = 21, - UWB_RC_CMD_SET_DRP_IE = 22, /* Dynamic Reservation Protocol IEs */ - UWB_RC_CMD_SET_IE = 23, /* Information Element management */ - UWB_RC_CMD_SET_NOTIFICATION_FILTER = 24, - UWB_RC_CMD_SET_TX_POWER = 25, - UWB_RC_CMD_SLEEP = 26, - UWB_RC_CMD_START_BEACON = 27, - UWB_RC_CMD_STOP_BEACON = 28, - UWB_RC_CMD_BP_MERGE = 29, - UWB_RC_CMD_SEND_COMMAND_FRAME = 30, - UWB_RC_CMD_SET_ASIE_NOTIF = 31, -}; - -/* Notifications from the radio controller */ -enum uwb_rc_evt { - UWB_RC_EVT_IE_RCV = 0, - UWB_RC_EVT_BEACON = 1, - UWB_RC_EVT_BEACON_SIZE = 2, - UWB_RC_EVT_BPOIE_CHANGE = 3, - UWB_RC_EVT_BP_SLOT_CHANGE = 4, - UWB_RC_EVT_BP_SWITCH_IE_RCV = 5, - UWB_RC_EVT_DEV_ADDR_CONFLICT = 6, - UWB_RC_EVT_DRP_AVAIL = 7, - UWB_RC_EVT_DRP = 8, - UWB_RC_EVT_BP_SWITCH_STATUS = 9, - UWB_RC_EVT_CMD_FRAME_RCV = 10, - UWB_RC_EVT_CHANNEL_CHANGE_IE_RCV = 11, - /* Events (command responses) use the same code as the command */ - UWB_RC_EVT_UNKNOWN_CMD_RCV = 65535, -}; - -enum uwb_rc_extended_type_1_cmd { - UWB_RC_SET_DAA_ENERGY_MASK = 32, - UWB_RC_SET_NOTIFICATION_FILTER_EX = 33, -}; - -enum uwb_rc_extended_type_1_evt { - UWB_RC_DAA_ENERGY_DETECTED = 0, -}; - -/* Radio Control Result Code. [WHCI] table 3-3. */ -enum { - UWB_RC_RES_SUCCESS = 0, - UWB_RC_RES_FAIL, - UWB_RC_RES_FAIL_HARDWARE, - UWB_RC_RES_FAIL_NO_SLOTS, - UWB_RC_RES_FAIL_BEACON_TOO_LARGE, - UWB_RC_RES_FAIL_INVALID_PARAMETER, - UWB_RC_RES_FAIL_UNSUPPORTED_PWR_LEVEL, - UWB_RC_RES_FAIL_INVALID_IE_DATA, - UWB_RC_RES_FAIL_BEACON_SIZE_EXCEEDED, - UWB_RC_RES_FAIL_CANCELLED, - UWB_RC_RES_FAIL_INVALID_STATE, - UWB_RC_RES_FAIL_INVALID_SIZE, - UWB_RC_RES_FAIL_ACK_NOT_RECEIVED, - UWB_RC_RES_FAIL_NO_MORE_ASIE_NOTIF, - UWB_RC_RES_FAIL_TIME_OUT = 255, -}; - -/* Confirm event. [WHCI] section 3.1.3.1 etc. */ -struct uwb_rc_evt_confirm { - struct uwb_rceb rceb; - u8 bResultCode; -} __attribute__((packed)); - -/* Device Address Management event. [WHCI] section 3.1.3.2. */ -struct uwb_rc_evt_dev_addr_mgmt { - struct uwb_rceb rceb; - u8 baAddr[ETH_ALEN]; - u8 bResultCode; -} __attribute__((packed)); - - -/* Get IE Event. [WHCI] section 3.1.3.3. */ -struct uwb_rc_evt_get_ie { - struct uwb_rceb rceb; - __le16 wIELength; - u8 IEData[]; -} __attribute__((packed)); - -/* Set DRP IE Event. [WHCI] section 3.1.3.7. */ -struct uwb_rc_evt_set_drp_ie { - struct uwb_rceb rceb; - __le16 wRemainingSpace; - u8 bResultCode; -} __attribute__((packed)); - -/* Set IE Event. [WHCI] section 3.1.3.8. */ -struct uwb_rc_evt_set_ie { - struct uwb_rceb rceb; - __le16 RemainingSpace; - u8 bResultCode; -} __attribute__((packed)); - -/* Scan command. [WHCI] 3.1.3.5. */ -struct uwb_rc_cmd_scan { - struct uwb_rccb rccb; - u8 bChannelNumber; - u8 bScanState; - __le16 wStartTime; -} __attribute__((packed)); - -/* Set DRP IE command. [WHCI] section 3.1.3.7. */ -struct uwb_rc_cmd_set_drp_ie { - struct uwb_rccb rccb; - __le16 wIELength; - struct uwb_ie_drp IEData[]; -} __attribute__((packed)); - -/* Set IE command. [WHCI] section 3.1.3.8. */ -struct uwb_rc_cmd_set_ie { - struct uwb_rccb rccb; - __le16 wIELength; - u8 IEData[]; -} __attribute__((packed)); - -/* Set DAA Energy Mask event. [WHCI 0.96] section 3.1.3.17. */ -struct uwb_rc_evt_set_daa_energy_mask { - struct uwb_rceb rceb; - __le16 wLength; - u8 result; -} __attribute__((packed)); - -/* Set Notification Filter Extended event. [WHCI 0.96] section 3.1.3.18. */ -struct uwb_rc_evt_set_notification_filter_ex { - struct uwb_rceb rceb; - __le16 wLength; - u8 result; -} __attribute__((packed)); - -/* IE Received notification. [WHCI] section 3.1.4.1. */ -struct uwb_rc_evt_ie_rcv { - struct uwb_rceb rceb; - struct uwb_dev_addr SrcAddr; - __le16 wIELength; - u8 IEData[]; -} __attribute__((packed)); - -/* Type of the received beacon. [WHCI] section 3.1.4.2. */ -enum uwb_rc_beacon_type { - UWB_RC_BEACON_TYPE_SCAN = 0, - UWB_RC_BEACON_TYPE_NEIGHBOR, - UWB_RC_BEACON_TYPE_OL_ALIEN, - UWB_RC_BEACON_TYPE_NOL_ALIEN, -}; - -/* Beacon received notification. [WHCI] 3.1.4.2. */ -struct uwb_rc_evt_beacon { - struct uwb_rceb rceb; - u8 bChannelNumber; - u8 bBeaconType; - __le16 wBPSTOffset; - u8 bLQI; - u8 bRSSI; - __le16 wBeaconInfoLength; - u8 BeaconInfo[]; -} __attribute__((packed)); - - -/* Beacon Size Change notification. [WHCI] section 3.1.4.3 */ -struct uwb_rc_evt_beacon_size { - struct uwb_rceb rceb; - __le16 wNewBeaconSize; -} __attribute__((packed)); - - -/* BPOIE Change notification. [WHCI] section 3.1.4.4. */ -struct uwb_rc_evt_bpoie_change { - struct uwb_rceb rceb; - __le16 wBPOIELength; - u8 BPOIE[]; -} __attribute__((packed)); - - -/* Beacon Slot Change notification. [WHCI] section 3.1.4.5. */ -struct uwb_rc_evt_bp_slot_change { - struct uwb_rceb rceb; - u8 slot_info; -} __attribute__((packed)); - -static inline int uwb_rc_evt_bp_slot_change_slot_num( - const struct uwb_rc_evt_bp_slot_change *evt) -{ - return evt->slot_info & 0x7f; -} - -static inline int uwb_rc_evt_bp_slot_change_no_slot( - const struct uwb_rc_evt_bp_slot_change *evt) -{ - return (evt->slot_info & 0x80) >> 7; -} - -/* BP Switch IE Received notification. [WHCI] section 3.1.4.6. */ -struct uwb_rc_evt_bp_switch_ie_rcv { - struct uwb_rceb rceb; - struct uwb_dev_addr wSrcAddr; - __le16 wIELength; - u8 IEData[]; -} __attribute__((packed)); - -/* DevAddr Conflict notification. [WHCI] section 3.1.4.7. */ -struct uwb_rc_evt_dev_addr_conflict { - struct uwb_rceb rceb; -} __attribute__((packed)); - -/* DRP notification. [WHCI] section 3.1.4.9. */ -struct uwb_rc_evt_drp { - struct uwb_rceb rceb; - struct uwb_dev_addr src_addr; - u8 reason; - u8 beacon_slot_number; - __le16 ie_length; - u8 ie_data[]; -} __attribute__((packed)); - -static inline enum uwb_drp_notif_reason uwb_rc_evt_drp_reason(struct uwb_rc_evt_drp *evt) -{ - return evt->reason & 0x0f; -} - - -/* DRP Availability Change notification. [WHCI] section 3.1.4.8. */ -struct uwb_rc_evt_drp_avail { - struct uwb_rceb rceb; - DECLARE_BITMAP(bmp, UWB_NUM_MAS); -} __attribute__((packed)); - -/* BP switch status notification. [WHCI] section 3.1.4.10. */ -struct uwb_rc_evt_bp_switch_status { - struct uwb_rceb rceb; - u8 status; - u8 slot_offset; - __le16 bpst_offset; - u8 move_countdown; -} __attribute__((packed)); - -/* Command Frame Received notification. [WHCI] section 3.1.4.11. */ -struct uwb_rc_evt_cmd_frame_rcv { - struct uwb_rceb rceb; - __le16 receive_time; - struct uwb_dev_addr wSrcAddr; - struct uwb_dev_addr wDstAddr; - __le16 control; - __le16 reserved; - __le16 dataLength; - u8 data[]; -} __attribute__((packed)); - -/* Channel Change IE Received notification. [WHCI] section 3.1.4.12. */ -struct uwb_rc_evt_channel_change_ie_rcv { - struct uwb_rceb rceb; - struct uwb_dev_addr wSrcAddr; - __le16 wIELength; - u8 IEData[]; -} __attribute__((packed)); - -/* DAA Energy Detected notification. [WHCI 0.96] section 3.1.4.14. */ -struct uwb_rc_evt_daa_energy_detected { - struct uwb_rceb rceb; - __le16 wLength; - u8 bandID; - u8 reserved; - u8 toneBmp[16]; -} __attribute__((packed)); - - -/** - * Radio Control Interface Class Descriptor - * - * WUSB 1.0 [8.6.1.2] - */ -struct uwb_rc_control_intf_class_desc { - u8 bLength; - u8 bDescriptorType; - __le16 bcdRCIVersion; -} __attribute__((packed)); - -#endif /* #ifndef __LINUX__UWB_SPEC_H__ */ diff --git a/include/linux/uwb/umc.h b/include/linux/uwb/umc.h deleted file mode 100644 index ddbceb39ad15..000000000000 --- a/include/linux/uwb/umc.h +++ /dev/null @@ -1,192 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * UWB Multi-interface Controller support. - * - * Copyright (C) 2007 Cambridge Silicon Radio Ltd. - * - * UMC (UWB Multi-interface Controller) capabilities (e.g., radio - * controller, host controller) are presented as devices on the "umc" - * bus. - * - * The radio controller is not strictly a UMC capability but it's - * useful to present it as such. - * - * References: - * - * [WHCI] Wireless Host Controller Interface Specification for - * Certified Wireless Universal Serial Bus, revision 0.95. - * - * How this works is kind of convoluted but simple. The whci.ko driver - * loads when WHCI devices are detected. These WHCI devices expose - * many devices in the same PCI function (they couldn't have reused - * functions, no), so for each PCI function that exposes these many - * devices, whci ceates a umc_dev [whci_probe() -> whci_add_cap()] - * with umc_device_create() and adds it to the bus with - * umc_device_register(). - * - * umc_device_register() calls device_register() which will push the - * bus management code to load your UMC driver's somehting_probe() - * that you have registered for that capability code. - * - * Now when the WHCI device is removed, whci_remove() will go over - * each umc_dev assigned to each of the PCI function's capabilities - * and through whci_del_cap() call umc_device_unregister() each - * created umc_dev. Of course, if you are bound to the device, your - * driver's something_remove() will be called. - */ - -#ifndef _LINUX_UWB_UMC_H_ -#define _LINUX_UWB_UMC_H_ - -#include <linux/device.h> -#include <linux/pci.h> - -/* - * UMC capability IDs. - * - * 0x00 is reserved so use it for the radio controller device. - * - * [WHCI] table 2-8 - */ -#define UMC_CAP_ID_WHCI_RC 0x00 /* radio controller */ -#define UMC_CAP_ID_WHCI_WUSB_HC 0x01 /* WUSB host controller */ - -/** - * struct umc_dev - UMC capability device - * - * @version: version of the specification this capability conforms to. - * @cap_id: capability ID. - * @bar: PCI Bar (64 bit) where the resource lies - * @resource: register space resource. - * @irq: interrupt line. - */ -struct umc_dev { - u16 version; - u8 cap_id; - u8 bar; - struct resource resource; - unsigned irq; - struct device dev; -}; - -#define to_umc_dev(d) container_of(d, struct umc_dev, dev) - -/** - * struct umc_driver - UMC capability driver - * @cap_id: supported capability ID. - * @match: driver specific capability matching function. - * @match_data: driver specific data for match() (e.g., a - * table of pci_device_id's if umc_match_pci_id() is used). - */ -struct umc_driver { - char *name; - u8 cap_id; - int (*match)(struct umc_driver *, struct umc_dev *); - const void *match_data; - - int (*probe)(struct umc_dev *); - void (*remove)(struct umc_dev *); - int (*pre_reset)(struct umc_dev *); - int (*post_reset)(struct umc_dev *); - - struct device_driver driver; -}; - -#define to_umc_driver(d) container_of(d, struct umc_driver, driver) - -extern struct bus_type umc_bus_type; - -struct umc_dev *umc_device_create(struct device *parent, int n); -int __must_check umc_device_register(struct umc_dev *umc); -void umc_device_unregister(struct umc_dev *umc); - -int __must_check __umc_driver_register(struct umc_driver *umc_drv, - struct module *mod, - const char *mod_name); - -/** - * umc_driver_register - register a UMC capabiltity driver. - * @umc_drv: pointer to the driver. - */ -#define umc_driver_register(umc_drv) \ - __umc_driver_register(umc_drv, THIS_MODULE, KBUILD_MODNAME) - -void umc_driver_unregister(struct umc_driver *umc_drv); - -/* - * Utility function you can use to match (umc_driver->match) against a - * null-terminated array of 'struct pci_device_id' in - * umc_driver->match_data. - */ -int umc_match_pci_id(struct umc_driver *umc_drv, struct umc_dev *umc); - -/** - * umc_parent_pci_dev - return the UMC's parent PCI device or NULL if none - * @umc_dev: UMC device whose parent PCI device we are looking for - * - * DIRTY!!! DON'T RELY ON THIS - * - * FIXME: This is as dirty as it gets, but we need some way to check - * the correct type of umc_dev->parent (so that for example, we can - * cast to pci_dev). Casting to pci_dev is necessary because at some - * point we need to request resources from the device. Mapping is - * easily over come (ioremap and stuff are bus agnostic), but hooking - * up to some error handlers (such as pci error handlers) might need - * this. - * - * THIS might (probably will) be removed in the future, so don't count - * on it. - */ -static inline struct pci_dev *umc_parent_pci_dev(struct umc_dev *umc_dev) -{ - struct pci_dev *pci_dev = NULL; - if (dev_is_pci(umc_dev->dev.parent)) - pci_dev = to_pci_dev(umc_dev->dev.parent); - return pci_dev; -} - -/** - * umc_dev_get() - reference a UMC device. - * @umc_dev: Pointer to UMC device. - * - * NOTE: we are assuming in this whole scheme that the parent device - * is referenced at _probe() time and unreferenced at _remove() - * time by the parent's subsystem. - */ -static inline struct umc_dev *umc_dev_get(struct umc_dev *umc_dev) -{ - get_device(&umc_dev->dev); - return umc_dev; -} - -/** - * umc_dev_put() - unreference a UMC device. - * @umc_dev: Pointer to UMC device. - */ -static inline void umc_dev_put(struct umc_dev *umc_dev) -{ - put_device(&umc_dev->dev); -} - -/** - * umc_set_drvdata - set UMC device's driver data. - * @umc_dev: Pointer to UMC device. - * @data: Data to set. - */ -static inline void umc_set_drvdata(struct umc_dev *umc_dev, void *data) -{ - dev_set_drvdata(&umc_dev->dev, data); -} - -/** - * umc_get_drvdata - recover UMC device's driver data. - * @umc_dev: Pointer to UMC device. - */ -static inline void *umc_get_drvdata(struct umc_dev *umc_dev) -{ - return dev_get_drvdata(&umc_dev->dev); -} - -int umc_controller_reset(struct umc_dev *umc); - -#endif /* #ifndef _LINUX_UWB_UMC_H_ */ diff --git a/include/linux/uwb/whci.h b/include/linux/uwb/whci.h deleted file mode 100644 index 1a5c2cc2b008..000000000000 --- a/include/linux/uwb/whci.h +++ /dev/null @@ -1,102 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Wireless Host Controller Interface for Ultra-Wide-Band and Wireless USB - * - * Copyright (C) 2005-2006 Intel Corporation - * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com> - * - * References: - * [WHCI] Wireless Host Controller Interface Specification for - * Certified Wireless Universal Serial Bus, revision 0.95. - */ -#ifndef _LINUX_UWB_WHCI_H_ -#define _LINUX_UWB_WHCI_H_ - -#include <linux/pci.h> - -/* - * UWB interface capability registers (offsets from UWBBASE) - * - * [WHCI] section 2.2 - */ -#define UWBCAPINFO 0x00 /* == UWBCAPDATA(0) */ -# define UWBCAPINFO_TO_N_CAPS(c) (((c) >> 0) & 0xFull) -#define UWBCAPDATA(n) (8*(n)) -# define UWBCAPDATA_TO_VERSION(c) (((c) >> 32) & 0xFFFFull) -# define UWBCAPDATA_TO_OFFSET(c) (((c) >> 18) & 0x3FFFull) -# define UWBCAPDATA_TO_BAR(c) (((c) >> 16) & 0x3ull) -# define UWBCAPDATA_TO_SIZE(c) ((((c) >> 8) & 0xFFull) * sizeof(u32)) -# define UWBCAPDATA_TO_CAP_ID(c) (((c) >> 0) & 0xFFull) - -/* Size of the WHCI capability data (including the RC capability) for - a device with n capabilities. */ -#define UWBCAPDATA_SIZE(n) (8 + 8*(n)) - - -/* - * URC registers (offsets from URCBASE) - * - * [WHCI] section 2.3 - */ -#define URCCMD 0x00 -# define URCCMD_RESET (1 << 31) /* UMC Hardware reset */ -# define URCCMD_RS (1 << 30) /* Run/Stop */ -# define URCCMD_EARV (1 << 29) /* Event Address Register Valid */ -# define URCCMD_ACTIVE (1 << 15) /* Command is active */ -# define URCCMD_IWR (1 << 14) /* Interrupt When Ready */ -# define URCCMD_SIZE_MASK 0x00000fff /* Command size mask */ -#define URCSTS 0x04 -# define URCSTS_EPS (1 << 17) /* Event Processing Status */ -# define URCSTS_HALTED (1 << 16) /* RC halted */ -# define URCSTS_HSE (1 << 10) /* Host System Error...fried */ -# define URCSTS_ER (1 << 9) /* Event Ready */ -# define URCSTS_RCI (1 << 8) /* Ready for Command Interrupt */ -# define URCSTS_INT_MASK 0x00000700 /* URC interrupt sources */ -# define URCSTS_ISI 0x000000ff /* Interrupt Source Identification */ -#define URCINTR 0x08 -# define URCINTR_EN_ALL 0x000007ff /* Enable all interrupt sources */ -#define URCCMDADDR 0x10 -#define URCEVTADDR 0x18 -# define URCEVTADDR_OFFSET_MASK 0xfff /* Event pointer offset mask */ - - -/** Write 32 bit @value to little endian register at @addr */ -static inline -void le_writel(u32 value, void __iomem *addr) -{ - iowrite32(value, addr); -} - - -/** Read from 32 bit little endian register at @addr */ -static inline -u32 le_readl(void __iomem *addr) -{ - return ioread32(addr); -} - - -/** Write 64 bit @value to little endian register at @addr */ -static inline -void le_writeq(u64 value, void __iomem *addr) -{ - iowrite32(value, addr); - iowrite32(value >> 32, addr + 4); -} - - -/** Read from 64 bit little endian register at @addr */ -static inline -u64 le_readq(void __iomem *addr) -{ - u64 value; - value = ioread32(addr); - value |= (u64)ioread32(addr + 4) << 32; - return value; -} - -extern int whci_wait_for(struct device *dev, u32 __iomem *reg, - u32 mask, u32 result, - unsigned long max_ms, const char *tag); - -#endif /* #ifndef _LINUX_UWB_WHCI_H_ */ diff --git a/include/linux/verification.h b/include/linux/verification.h index 32d990d163c4..911ab7c2b1ab 100644 --- a/include/linux/verification.h +++ b/include/linux/verification.h @@ -32,6 +32,7 @@ extern const char *const key_being_used_for[NR__KEY_BEING_USED_FOR]; #ifdef CONFIG_SYSTEM_DATA_VERIFICATION struct key; +struct pkcs7_message; extern int verify_pkcs7_signature(const void *data, size_t len, const void *raw_pkcs7, size_t pkcs7_len, @@ -41,6 +42,15 @@ extern int verify_pkcs7_signature(const void *data, size_t len, const void *data, size_t len, size_t asn1hdrlen), void *ctx); +extern int verify_pkcs7_message_sig(const void *data, size_t len, + struct pkcs7_message *pkcs7, + struct key *trusted_keys, + enum key_being_used_for usage, + int (*view_content)(void *ctx, + const void *data, + size_t len, + size_t asn1hdrlen), + void *ctx); #ifdef CONFIG_SIGNED_PE_FILE_VERIFICATION extern int verify_pefile_signature(const void *pebuf, unsigned pelen, diff --git a/include/linux/vermagic.h b/include/linux/vermagic.h index bae807eb2933..9aced11e9000 100644 --- a/include/linux/vermagic.h +++ b/include/linux/vermagic.h @@ -9,6 +9,8 @@ #endif #ifdef CONFIG_PREEMPT #define MODULE_VERMAGIC_PREEMPT "preempt " +#elif defined(CONFIG_PREEMPT_RT) +#define MODULE_VERMAGIC_PREEMPT "preempt_rt " #else #define MODULE_VERMAGIC_PREEMPT "" #endif diff --git a/include/linux/virtio_vsock.h b/include/linux/virtio_vsock.h index e223e2632edd..4c7781f4b29b 100644 --- a/include/linux/virtio_vsock.h +++ b/include/linux/virtio_vsock.h @@ -35,13 +35,14 @@ struct virtio_vsock_sock { /* Protected by tx_lock */ u32 tx_cnt; - u32 buf_alloc; u32 peer_fwd_cnt; u32 peer_buf_alloc; /* Protected by rx_lock */ u32 fwd_cnt; + u32 last_fwd_cnt; u32 rx_bytes; + u32 buf_alloc; struct list_head rx_queue; }; @@ -52,6 +53,7 @@ struct virtio_vsock_pkt { /* socket refcnt not held, only use for cancellation */ struct vsock_sock *vsk; void *buf; + u32 buf_len; u32 len; u32 off; bool reply; diff --git a/include/linux/vmalloc.h b/include/linux/vmalloc.h index 51e131245379..4e7809408073 100644 --- a/include/linux/vmalloc.h +++ b/include/linux/vmalloc.h @@ -18,6 +18,7 @@ struct notifier_block; /* in notifier.h */ #define VM_ALLOC 0x00000002 /* vmalloc() */ #define VM_MAP 0x00000004 /* vmap()ed pages */ #define VM_USERMAP 0x00000008 /* suitable for remap_vmalloc_range */ +#define VM_DMA_COHERENT 0x00000010 /* dma_alloc_coherent */ #define VM_UNINITIALIZED 0x00000020 /* vm_struct is not fully initialized */ #define VM_NO_GUARD 0x00000040 /* don't add guard page */ #define VM_KASAN 0x00000080 /* has allocated kasan shadow memory */ @@ -26,6 +27,7 @@ struct notifier_block; /* in notifier.h */ * vfree_atomic(). */ #define VM_FLUSH_RESET_PERMS 0x00000100 /* Reset direct map and flush TLB on unmap */ + /* bits [20..32] reserved for arch specific ioremap internals */ /* @@ -51,15 +53,21 @@ struct vmap_area { unsigned long va_start; unsigned long va_end; - /* - * Largest available free size in subtree. - */ - unsigned long subtree_max_size; - unsigned long flags; struct rb_node rb_node; /* address sorted rbtree */ struct list_head list; /* address sorted list */ - struct llist_node purge_list; /* "lazy purge" list */ - struct vm_struct *vm; + + /* + * The following three variables can be packed, because + * a vmap_area object is always one of the three states: + * 1) in "free" tree (root is vmap_area_root) + * 2) in "busy" tree (root is free_vmap_area_root) + * 3) in purge list (head is vmap_purge_list) + */ + union { + unsigned long subtree_max_size; /* in "free" tree */ + struct vm_struct *vm; /* in "busy" tree */ + struct llist_node purge_list; /* in purge list */ + }; }; /* @@ -72,10 +80,12 @@ extern void vm_unmap_aliases(void); #ifdef CONFIG_MMU extern void __init vmalloc_init(void); +extern unsigned long vmalloc_nr_pages(void); #else static inline void vmalloc_init(void) { } +static inline unsigned long vmalloc_nr_pages(void) { return 0; } #endif extern void *vmalloc(unsigned long size); diff --git a/include/linux/vmpressure.h b/include/linux/vmpressure.h index 61e6fddfb26f..6d28bc433c1c 100644 --- a/include/linux/vmpressure.h +++ b/include/linux/vmpressure.h @@ -17,7 +17,7 @@ struct vmpressure { unsigned long tree_scanned; unsigned long tree_reclaimed; /* The lock is used to keep the scanned/reclaimed above in sync. */ - struct spinlock sr_lock; + spinlock_t sr_lock; /* The list of vmpressure_event structs. */ struct list_head events; diff --git a/include/linux/vmw_vmci_defs.h b/include/linux/vmw_vmci_defs.h index 77ac9c7b9483..fefb5292403b 100644 --- a/include/linux/vmw_vmci_defs.h +++ b/include/linux/vmw_vmci_defs.h @@ -62,9 +62,18 @@ enum { /* * A single VMCI device has an upper limit of 128MB on the amount of - * memory that can be used for queue pairs. + * memory that can be used for queue pairs. Since each queue pair + * consists of at least two pages, the memory limit also dictates the + * number of queue pairs a guest can create. */ #define VMCI_MAX_GUEST_QP_MEMORY (128 * 1024 * 1024) +#define VMCI_MAX_GUEST_QP_COUNT (VMCI_MAX_GUEST_QP_MEMORY / PAGE_SIZE / 2) + +/* + * There can be at most PAGE_SIZE doorbells since there is one doorbell + * per byte in the doorbell bitmap page. + */ +#define VMCI_MAX_GUEST_DOORBELL_COUNT PAGE_SIZE /* * Queues with pre-mapped data pages must be small, so that we don't pin @@ -430,8 +439,8 @@ enum { struct vmci_queue_header { /* All fields are 64bit and aligned. */ struct vmci_handle handle; /* Identifier. */ - atomic64_t producer_tail; /* Offset in this queue. */ - atomic64_t consumer_head; /* Offset in peer queue. */ + u64 producer_tail; /* Offset in this queue. */ + u64 consumer_head; /* Offset in peer queue. */ }; /* @@ -732,13 +741,9 @@ static inline void *vmci_event_data_payload(struct vmci_event_data *ev_data) * prefix will be used, so correctness isn't an issue, but using a * 64bit operation still adds unnecessary overhead. */ -static inline u64 vmci_q_read_pointer(atomic64_t *var) +static inline u64 vmci_q_read_pointer(u64 *var) { -#if defined(CONFIG_X86_32) - return atomic_read((atomic_t *)var); -#else - return atomic64_read(var); -#endif + return READ_ONCE(*(unsigned long *)var); } /* @@ -747,23 +752,17 @@ static inline u64 vmci_q_read_pointer(atomic64_t *var) * never exceeds a 32bit value in this case. On 32bit SMP, using a * locked cmpxchg8b adds unnecessary overhead. */ -static inline void vmci_q_set_pointer(atomic64_t *var, - u64 new_val) +static inline void vmci_q_set_pointer(u64 *var, u64 new_val) { -#if defined(CONFIG_X86_32) - return atomic_set((atomic_t *)var, (u32)new_val); -#else - return atomic64_set(var, new_val); -#endif + /* XXX buggered on big-endian */ + WRITE_ONCE(*(unsigned long *)var, (unsigned long)new_val); } /* * Helper to add a given offset to a head or tail pointer. Wraps the * value of the pointer around the max size of the queue. */ -static inline void vmci_qp_add_pointer(atomic64_t *var, - size_t add, - u64 size) +static inline void vmci_qp_add_pointer(u64 *var, size_t add, u64 size) { u64 new_val = vmci_q_read_pointer(var); @@ -840,8 +839,8 @@ static inline void vmci_q_header_init(struct vmci_queue_header *q_header, const struct vmci_handle handle) { q_header->handle = handle; - atomic64_set(&q_header->producer_tail, 0); - atomic64_set(&q_header->consumer_head, 0); + q_header->producer_tail = 0; + q_header->consumer_head = 0; } /* diff --git a/include/linux/w1.h b/include/linux/w1.h index e0b5156f78fd..7da0c7588e04 100644 --- a/include/linux/w1.h +++ b/include/linux/w1.h @@ -118,6 +118,9 @@ typedef void (*w1_slave_found_callback)(struct w1_master *, u64); * w1_master* is passed to the slave found callback. * u8 is search_type, W1_SEARCH or W1_ALARM_SEARCH * + * @dev_id: Optional device id string, which w1 slaves could use for + * creating names, which then give a connection to the w1 master + * * Note: read_bit and write_bit are very low level functions and should only * be used with hardware that doesn't really support 1-wire operations, * like a parallel/serial port. @@ -150,6 +153,8 @@ struct w1_bus_master { void (*search)(void *, struct w1_master *, u8, w1_slave_found_callback); + + char *dev_id; }; /** diff --git a/include/linux/wait.h b/include/linux/wait.h index b6f77cf60dd7..3eb7cae8206c 100644 --- a/include/linux/wait.h +++ b/include/linux/wait.h @@ -127,6 +127,19 @@ static inline int waitqueue_active(struct wait_queue_head *wq_head) } /** + * wq_has_single_sleeper - check if there is only one sleeper + * @wq_head: wait queue head + * + * Returns true of wq_head has only one sleeper on the list. + * + * Please refer to the comment for waitqueue_active. + */ +static inline bool wq_has_single_sleeper(struct wait_queue_head *wq_head) +{ + return list_is_singular(&wq_head->head); +} + +/** * wq_has_sleeper - check if there are any waiting processes * @wq_head: wait queue head * @@ -488,8 +501,8 @@ do { \ int __ret = 0; \ struct hrtimer_sleeper __t; \ \ - hrtimer_init_on_stack(&__t.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); \ - hrtimer_init_sleeper(&__t, current); \ + hrtimer_init_sleeper_on_stack(&__t, CLOCK_MONOTONIC, \ + HRTIMER_MODE_REL); \ if ((timeout) != KTIME_MAX) \ hrtimer_start_range_ns(&__t.timer, timeout, \ current->timer_slack_ns, \ diff --git a/include/linux/wanrouter.h b/include/linux/wanrouter.h deleted file mode 100644 index f6358558f9f5..000000000000 --- a/include/linux/wanrouter.h +++ /dev/null @@ -1,11 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * wanrouter.h Legacy declarations kept around until X25 is removed - */ - -#ifndef _ROUTER_H -#define _ROUTER_H - -#include <uapi/linux/wanrouter.h> - -#endif /* _ROUTER_H */ diff --git a/include/linux/wimax/debug.h b/include/linux/wimax/debug.h index 7cb63e4ec0ae..4dd2c1cea6a9 100644 --- a/include/linux/wimax/debug.h +++ b/include/linux/wimax/debug.h @@ -98,9 +98,7 @@ * To manipulate from user space the levels, create a debugfs dentry * and then register each submodule with: * - * result = d_level_register_debugfs("PREFIX_", submodule_X, parent); - * if (result < 0) - * goto error; + * d_level_register_debugfs("PREFIX_", submodule_X, parent); * * Where PREFIX_ is a name of your chosing. This will create debugfs * file with a single numeric value that can be use to tweak it. To @@ -408,25 +406,13 @@ do { \ * @submodule: name of submodule (not a string, just the name) * @dentry: debugfs parent dentry * - * Returns: 0 if ok, < 0 errno on error. - * * For removing, just use debugfs_remove_recursive() on the parent. */ #define d_level_register_debugfs(prefix, name, parent) \ ({ \ - int rc; \ - struct dentry *fd; \ - struct dentry *verify_parent_type = parent; \ - fd = debugfs_create_u8( \ - prefix #name, 0600, verify_parent_type, \ + debugfs_create_u8( \ + prefix #name, 0600, parent, \ &(D_LEVEL[__D_SUBMODULE_ ## name].level)); \ - rc = PTR_ERR(fd); \ - if (IS_ERR(fd) && rc != -ENODEV) \ - printk(KERN_ERR "%s: Can't create debugfs entry %s: " \ - "%d\n", __func__, prefix #name, rc); \ - else \ - rc = 0; \ - rc; \ }) diff --git a/include/linux/wmi.h b/include/linux/wmi.h index fcc9d029f67a..8ef7e7faea1e 100644 --- a/include/linux/wmi.h +++ b/include/linux/wmi.h @@ -36,7 +36,7 @@ struct wmi_driver { struct device_driver driver; const struct wmi_device_id *id_table; - int (*probe)(struct wmi_device *wdev); + int (*probe)(struct wmi_device *wdev, const void *context); int (*remove)(struct wmi_device *wdev); void (*notify)(struct wmi_device *device, union acpi_object *data); long (*filter_callback)(struct wmi_device *wdev, unsigned int cmd, diff --git a/include/linux/workqueue.h b/include/linux/workqueue.h index d59525fca4d3..4261d1c6e87b 100644 --- a/include/linux/workqueue.h +++ b/include/linux/workqueue.h @@ -435,7 +435,7 @@ struct workqueue_struct *alloc_workqueue(const char *fmt, extern void destroy_workqueue(struct workqueue_struct *wq); -struct workqueue_attrs *alloc_workqueue_attrs(gfp_t gfp_mask); +struct workqueue_attrs *alloc_workqueue_attrs(void); void free_workqueue_attrs(struct workqueue_attrs *attrs); int apply_workqueue_attrs(struct workqueue_struct *wq, const struct workqueue_attrs *attrs); diff --git a/include/linux/writeback.h b/include/linux/writeback.h index 738a0c24874f..a19d845dd7eb 100644 --- a/include/linux/writeback.h +++ b/include/linux/writeback.h @@ -11,6 +11,7 @@ #include <linux/flex_proportions.h> #include <linux/backing-dev-defs.h> #include <linux/blk_types.h> +#include <linux/blk-cgroup.h> struct bio; @@ -68,6 +69,17 @@ struct writeback_control { unsigned for_reclaim:1; /* Invoked from the page allocator */ unsigned range_cyclic:1; /* range_start is cyclic */ unsigned for_sync:1; /* sync(2) WB_SYNC_ALL writeback */ + + /* + * When writeback IOs are bounced through async layers, only the + * initial synchronous phase should be accounted towards inode + * cgroup ownership arbitration to avoid confusion. Later stages + * can set the following flag to disable the accounting. + */ + unsigned no_cgroup_owner:1; + + unsigned punt_to_cgroup:1; /* cgrp punting, see __REQ_CGROUP_PUNT */ + #ifdef CONFIG_CGROUP_WRITEBACK struct bdi_writeback *wb; /* wb this writeback is issued under */ struct inode *inode; /* inode being written out */ @@ -84,12 +96,27 @@ struct writeback_control { static inline int wbc_to_write_flags(struct writeback_control *wbc) { + int flags = 0; + + if (wbc->punt_to_cgroup) + flags = REQ_CGROUP_PUNT; + if (wbc->sync_mode == WB_SYNC_ALL) - return REQ_SYNC; + flags |= REQ_SYNC; else if (wbc->for_kupdate || wbc->for_background) - return REQ_BACKGROUND; + flags |= REQ_BACKGROUND; - return 0; + return flags; +} + +static inline struct cgroup_subsys_state * +wbc_blkcg_css(struct writeback_control *wbc) +{ +#ifdef CONFIG_CGROUP_WRITEBACK + if (wbc->wb) + return wbc->wb->blkcg_css; +#endif + return blkcg_root_css; } /* @@ -188,8 +215,10 @@ void wbc_attach_and_unlock_inode(struct writeback_control *wbc, struct inode *inode) __releases(&inode->i_lock); void wbc_detach_inode(struct writeback_control *wbc); -void wbc_account_io(struct writeback_control *wbc, struct page *page, - size_t bytes); +void wbc_account_cgroup_owner(struct writeback_control *wbc, struct page *page, + size_t bytes); +int cgroup_writeback_by_id(u64 bdi_id, int memcg_id, unsigned long nr_pages, + enum wb_reason reason, struct wb_completion *done); void cgroup_writeback_umount(void); /** @@ -291,8 +320,8 @@ static inline void wbc_init_bio(struct writeback_control *wbc, struct bio *bio) { } -static inline void wbc_account_io(struct writeback_control *wbc, - struct page *page, size_t bytes) +static inline void wbc_account_cgroup_owner(struct writeback_control *wbc, + struct page *page, size_t bytes) { } diff --git a/include/linux/zpool.h b/include/linux/zpool.h index 7238865e75b0..51bf43076165 100644 --- a/include/linux/zpool.h +++ b/include/linux/zpool.h @@ -46,6 +46,8 @@ const char *zpool_get_type(struct zpool *pool); void zpool_destroy_pool(struct zpool *pool); +bool zpool_malloc_support_movable(struct zpool *pool); + int zpool_malloc(struct zpool *pool, size_t size, gfp_t gfp, unsigned long *handle); @@ -90,6 +92,7 @@ struct zpool_driver { struct zpool *zpool); void (*destroy)(void *pool); + bool malloc_support_movable; int (*malloc)(void *pool, size_t size, gfp_t gfp, unsigned long *handle); void (*free)(void *pool, unsigned long handle); |