Linux 6.0-rc6
-----BEGIN PGP SIGNATURE----- iQFSBAABCAA8FiEEq68RxlopcLEwq+PEeb4+QwBBGIYFAmMngx4eHHRvcnZhbGRz QGxpbnV4LWZvdW5kYXRpb24ub3JnAAoJEHm+PkMAQRiGQ1AH/1p4oOT4iqaoTueO MaTQhyvFFcTSLL4y1qejtytNXe4ZEJHyf03jrwtYlfx8RROkZFMJh15G1uWu2deu 43XsUuSWpJ18/C7hRNl1LUazBbuQe30d09zLe7dvD64IAABU6/iQCIorxheTl4EU NXsda2egJUIbTwn2zdFSgMMJPNORxq8KHgvNY/psIEteC+lFln2l2ZXZ21JAIdBj lcTbvx6JpJC0AqX1UuO6NsN4nUnEEh110UtYF6lxQ7olkQKwRaUjQIVuWOFLz75n wDrJxPlVGbDR5zeitDaHkKqWn8LNcqHpDIuAKMxTjT0N/1/sUwHNkyGZXyy1EDJu e0+SX1c= =ITjo -----END PGP SIGNATURE----- Merge tag 'v6.0-rc6' into locking/core, to refresh the branch Signed-off-by: Ingo Molnar <mingo@kernel.org>
This commit is contained in:
commit
74656d03ac
13386 changed files with 1361646 additions and 268321 deletions
|
|
@ -764,6 +764,7 @@ static inline u64 acpi_arch_get_root_pointer(void)
|
|||
#endif
|
||||
|
||||
int acpi_get_local_address(acpi_handle handle, u32 *addr);
|
||||
const char *acpi_get_subsystem_id(acpi_handle handle);
|
||||
|
||||
#else /* !CONFIG_ACPI */
|
||||
|
||||
|
|
@ -1025,6 +1026,11 @@ static inline int acpi_get_local_address(acpi_handle handle, u32 *addr)
|
|||
return -ENODEV;
|
||||
}
|
||||
|
||||
static inline const char *acpi_get_subsystem_id(acpi_handle handle)
|
||||
{
|
||||
return ERR_PTR(-ENODEV);
|
||||
}
|
||||
|
||||
static inline int acpi_register_wakeup_handler(int wake_irq,
|
||||
bool (*wakeup)(void *context), void *context)
|
||||
{
|
||||
|
|
@ -1245,7 +1251,7 @@ static inline bool acpi_dev_has_props(const struct acpi_device *adev)
|
|||
|
||||
struct acpi_device_properties *
|
||||
acpi_data_add_props(struct acpi_device_data *data, const guid_t *guid,
|
||||
const union acpi_object *properties);
|
||||
union acpi_object *properties);
|
||||
|
||||
int acpi_node_prop_get(const struct fwnode_handle *fwnode, const char *propname,
|
||||
void **valptr);
|
||||
|
|
@ -1431,7 +1437,6 @@ int find_acpi_cpu_topology(unsigned int cpu, int level);
|
|||
int find_acpi_cpu_topology_cluster(unsigned int cpu);
|
||||
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)
|
||||
{
|
||||
|
|
@ -1453,10 +1458,6 @@ 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;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ACPI_PCC
|
||||
|
|
|
|||
|
|
@ -33,10 +33,14 @@ struct irq_domain *iort_get_device_domain(struct device *dev, u32 id,
|
|||
enum irq_domain_bus_token bus_token);
|
||||
void acpi_configure_pmsi_domain(struct device *dev);
|
||||
int iort_pmsi_get_dev_id(struct device *dev, u32 *dev_id);
|
||||
void iort_get_rmr_sids(struct fwnode_handle *iommu_fwnode,
|
||||
struct list_head *head);
|
||||
void iort_put_rmr_sids(struct fwnode_handle *iommu_fwnode,
|
||||
struct list_head *head);
|
||||
/* IOMMU interface */
|
||||
int iort_dma_get_ranges(struct device *dev, u64 *size);
|
||||
int iort_iommu_configure_id(struct device *dev, const u32 *id_in);
|
||||
int iort_iommu_msi_get_resv_regions(struct device *dev, struct list_head *head);
|
||||
void iort_iommu_get_resv_regions(struct device *dev, struct list_head *head);
|
||||
phys_addr_t acpi_iort_dma_get_max_cpu_address(void);
|
||||
#else
|
||||
static inline void acpi_iort_init(void) { }
|
||||
|
|
@ -46,14 +50,18 @@ static inline struct irq_domain *iort_get_device_domain(
|
|||
struct device *dev, u32 id, enum irq_domain_bus_token bus_token)
|
||||
{ return NULL; }
|
||||
static inline void acpi_configure_pmsi_domain(struct device *dev) { }
|
||||
static inline
|
||||
void iort_get_rmr_sids(struct fwnode_handle *iommu_fwnode, struct list_head *head) { }
|
||||
static inline
|
||||
void iort_put_rmr_sids(struct fwnode_handle *iommu_fwnode, struct list_head *head) { }
|
||||
/* IOMMU interface */
|
||||
static inline int iort_dma_get_ranges(struct device *dev, u64 *size)
|
||||
{ return -ENODEV; }
|
||||
static inline int iort_iommu_configure_id(struct device *dev, const u32 *id_in)
|
||||
{ return -ENODEV; }
|
||||
static inline
|
||||
int iort_iommu_msi_get_resv_regions(struct device *dev, struct list_head *head)
|
||||
{ return 0; }
|
||||
void iort_iommu_get_resv_regions(struct device *dev, struct list_head *head)
|
||||
{ }
|
||||
|
||||
static inline phys_addr_t acpi_iort_dma_get_max_cpu_address(void)
|
||||
{ return PHYS_ADDR_MAX; }
|
||||
|
|
|
|||
|
|
@ -6,9 +6,11 @@
|
|||
#include <linux/acpi.h>
|
||||
|
||||
#ifdef CONFIG_ACPI_VIOT
|
||||
void __init acpi_viot_early_init(void);
|
||||
void __init acpi_viot_init(void);
|
||||
int viot_iommu_configure(struct device *dev);
|
||||
#else
|
||||
static inline void acpi_viot_early_init(void) {}
|
||||
static inline void acpi_viot_init(void) {}
|
||||
static inline int viot_iommu_configure(struct device *dev)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -67,6 +67,7 @@ struct amba_device {
|
|||
struct clk *pclk;
|
||||
struct device_dma_parameters dma_parms;
|
||||
unsigned int periphid;
|
||||
struct mutex periphid_lock;
|
||||
unsigned int cid;
|
||||
struct amba_cs_uci_id uci;
|
||||
unsigned int irq[AMBA_NR_IRQS];
|
||||
|
|
|
|||
|
|
@ -206,4 +206,8 @@ int amd_iommu_pc_get_reg(struct amd_iommu *iommu, u8 bank, u8 cntr, u8 fxn,
|
|||
u64 *value);
|
||||
struct amd_iommu *get_amd_iommu(unsigned int idx);
|
||||
|
||||
#ifdef CONFIG_AMD_MEM_ENCRYPT
|
||||
int amd_iommu_snp_enable(void);
|
||||
#endif
|
||||
|
||||
#endif /* _ASM_X86_AMD_IOMMU_H */
|
||||
|
|
|
|||
56
include/linux/aperture.h
Normal file
56
include/linux/aperture.h
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
/* SPDX-License-Identifier: MIT */
|
||||
|
||||
#ifndef _LINUX_APERTURE_H_
|
||||
#define _LINUX_APERTURE_H_
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
struct pci_dev;
|
||||
struct platform_device;
|
||||
|
||||
#if defined(CONFIG_APERTURE_HELPERS)
|
||||
int devm_aperture_acquire_for_platform_device(struct platform_device *pdev,
|
||||
resource_size_t base,
|
||||
resource_size_t size);
|
||||
|
||||
int aperture_remove_conflicting_devices(resource_size_t base, resource_size_t size,
|
||||
bool primary, const char *name);
|
||||
|
||||
int aperture_remove_conflicting_pci_devices(struct pci_dev *pdev, const char *name);
|
||||
#else
|
||||
static inline int devm_aperture_acquire_for_platform_device(struct platform_device *pdev,
|
||||
resource_size_t base,
|
||||
resource_size_t size)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int aperture_remove_conflicting_devices(resource_size_t base, resource_size_t size,
|
||||
bool primary, const char *name)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int aperture_remove_conflicting_pci_devices(struct pci_dev *pdev, const char *name)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* aperture_remove_all_conflicting_devices - remove all existing framebuffers
|
||||
* @primary: also kick vga16fb if present; only relevant for VGA devices
|
||||
* @name: a descriptive name of the requesting driver
|
||||
*
|
||||
* This function removes all graphics device drivers. Use this function on systems
|
||||
* that can have their framebuffer located anywhere in memory.
|
||||
*
|
||||
* Returns:
|
||||
* 0 on success, or a negative errno code otherwise
|
||||
*/
|
||||
static inline int aperture_remove_all_conflicting_devices(bool primary, const char *name)
|
||||
{
|
||||
return aperture_remove_conflicting_devices(0, (resource_size_t)-1, primary, name);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -68,7 +68,6 @@ struct cpu_topology {
|
|||
int core_id;
|
||||
int cluster_id;
|
||||
int package_id;
|
||||
int llc_id;
|
||||
cpumask_t thread_sibling;
|
||||
cpumask_t core_sibling;
|
||||
cpumask_t cluster_sibling;
|
||||
|
|
|
|||
|
|
@ -9,6 +9,8 @@
|
|||
|
||||
#include <uapi/linux/atm_tcp.h>
|
||||
|
||||
struct atm_vcc;
|
||||
struct module;
|
||||
|
||||
struct atm_tcp_ops {
|
||||
int (*attach)(struct atm_vcc *vcc,int itf);
|
||||
|
|
|
|||
|
|
@ -119,8 +119,6 @@ enum audit_nfcfgop {
|
|||
AUDIT_NFT_OP_INVALID,
|
||||
};
|
||||
|
||||
extern int is_audit_feature_set(int which);
|
||||
|
||||
extern int __init audit_register_class(int class, unsigned *list);
|
||||
extern int audit_classify_syscall(int abi, unsigned syscall);
|
||||
extern int audit_classify_arch(int arch);
|
||||
|
|
@ -287,7 +285,6 @@ static inline int audit_signal_info(int sig, struct task_struct *t)
|
|||
/* These are defined in auditsc.c */
|
||||
/* Public API */
|
||||
extern int audit_alloc(struct task_struct *task);
|
||||
extern int audit_alloc_kernel(struct task_struct *task);
|
||||
extern void __audit_free(struct task_struct *task);
|
||||
extern void __audit_uring_entry(u8 op);
|
||||
extern void __audit_uring_exit(int success, long code);
|
||||
|
|
@ -580,10 +577,6 @@ static inline int audit_alloc(struct task_struct *task)
|
|||
{
|
||||
return 0;
|
||||
}
|
||||
static inline int audit_alloc_kernel(struct task_struct *task)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static inline void audit_free(struct task_struct *task)
|
||||
{ }
|
||||
static inline void audit_uring_entry(u8 op)
|
||||
|
|
|
|||
|
|
@ -28,11 +28,6 @@ enum wb_state {
|
|||
WB_start_all, /* nr_pages == 0 (all) work pending */
|
||||
};
|
||||
|
||||
enum wb_congested_state {
|
||||
WB_async_congested, /* The async (write) queue is getting full */
|
||||
WB_sync_congested, /* The sync queue is getting full */
|
||||
};
|
||||
|
||||
enum wb_stat_item {
|
||||
WB_RECLAIMABLE,
|
||||
WB_WRITEBACK,
|
||||
|
|
@ -122,8 +117,6 @@ struct bdi_writeback {
|
|||
atomic_t writeback_inodes; /* number of inodes under writeback */
|
||||
struct percpu_counter stat[NR_WB_STAT_ITEMS];
|
||||
|
||||
unsigned long congested; /* WB_[a]sync_congested flags */
|
||||
|
||||
unsigned long bw_time_stamp; /* last time write bw is updated */
|
||||
unsigned long dirtied_stamp;
|
||||
unsigned long written_stamp; /* pages written at bw_time_stamp */
|
||||
|
|
|
|||
|
|
@ -140,12 +140,6 @@ static inline bool mapping_can_writeback(struct address_space *mapping)
|
|||
return inode_to_bdi(mapping->host)->capabilities & BDI_CAP_WRITEBACK;
|
||||
}
|
||||
|
||||
static inline int bdi_sched_wait(void *word)
|
||||
{
|
||||
schedule();
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_CGROUP_WRITEBACK
|
||||
|
||||
struct bdi_writeback *wb_get_lookup(struct backing_dev_info *bdi,
|
||||
|
|
@ -235,18 +229,6 @@ wb_get_create_current(struct backing_dev_info *bdi, gfp_t gfp)
|
|||
return wb;
|
||||
}
|
||||
|
||||
/**
|
||||
* inode_to_wb_is_valid - test whether an inode has a wb associated
|
||||
* @inode: inode of interest
|
||||
*
|
||||
* Returns %true if @inode has a wb associated. May be called without any
|
||||
* locking.
|
||||
*/
|
||||
static inline bool inode_to_wb_is_valid(struct inode *inode)
|
||||
{
|
||||
return inode->i_wb;
|
||||
}
|
||||
|
||||
/**
|
||||
* inode_to_wb - determine the wb of an inode
|
||||
* @inode: inode of interest
|
||||
|
|
@ -345,11 +327,6 @@ wb_get_create_current(struct backing_dev_info *bdi, gfp_t gfp)
|
|||
return &bdi->wb;
|
||||
}
|
||||
|
||||
static inline bool inode_to_wb_is_valid(struct inode *inode)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline struct bdi_writeback *inode_to_wb(struct inode *inode)
|
||||
{
|
||||
return &inode_to_bdi(inode)->wb;
|
||||
|
|
|
|||
|
|
@ -57,7 +57,6 @@ struct balloon_dev_info {
|
|||
struct list_head pages; /* Pages enqueued & handled to Host */
|
||||
int (*migratepage)(struct balloon_dev_info *, struct page *newpage,
|
||||
struct page *page, enum migrate_mode mode);
|
||||
struct inode *inode;
|
||||
};
|
||||
|
||||
extern struct page *balloon_page_alloc(void);
|
||||
|
|
@ -75,11 +74,10 @@ static inline void balloon_devinfo_init(struct balloon_dev_info *balloon)
|
|||
spin_lock_init(&balloon->pages_lock);
|
||||
INIT_LIST_HEAD(&balloon->pages);
|
||||
balloon->migratepage = NULL;
|
||||
balloon->inode = NULL;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_BALLOON_COMPACTION
|
||||
extern const struct address_space_operations balloon_aops;
|
||||
extern const struct movable_operations balloon_mops;
|
||||
|
||||
/*
|
||||
* balloon_page_insert - insert a page into the balloon's page list and make
|
||||
|
|
@ -94,7 +92,7 @@ static inline void balloon_page_insert(struct balloon_dev_info *balloon,
|
|||
struct page *page)
|
||||
{
|
||||
__SetPageOffline(page);
|
||||
__SetPageMovable(page, balloon->inode->i_mapping);
|
||||
__SetPageMovable(page, &balloon_mops);
|
||||
set_page_private(page, (unsigned long)balloon);
|
||||
list_add(&page->lru, &balloon->pages);
|
||||
}
|
||||
|
|
|
|||
16
include/linux/base64.h
Normal file
16
include/linux/base64.h
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* base64 encoding, lifted from fs/crypto/fname.c.
|
||||
*/
|
||||
|
||||
#ifndef _LINUX_BASE64_H
|
||||
#define _LINUX_BASE64_H
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
#define BASE64_CHARS(nbytes) DIV_ROUND_UP((nbytes) * 4, 3)
|
||||
|
||||
int base64_encode(const u8 *src, int len, char *dst);
|
||||
int base64_decode(const char *src, int len, u8 *dst);
|
||||
|
||||
#endif /* _LINUX_BASE64_H */
|
||||
|
|
@ -405,7 +405,7 @@ extern void bioset_exit(struct bio_set *);
|
|||
extern int biovec_init_pool(mempool_t *pool, int pool_entries);
|
||||
|
||||
struct bio *bio_alloc_bioset(struct block_device *bdev, unsigned short nr_vecs,
|
||||
unsigned int opf, gfp_t gfp_mask,
|
||||
blk_opf_t opf, gfp_t gfp_mask,
|
||||
struct bio_set *bs);
|
||||
struct bio *bio_kmalloc(unsigned short nr_vecs, gfp_t gfp_mask);
|
||||
extern void bio_put(struct bio *);
|
||||
|
|
@ -418,7 +418,7 @@ int bio_init_clone(struct block_device *bdev, struct bio *bio,
|
|||
extern struct bio_set fs_bio_set;
|
||||
|
||||
static inline struct bio *bio_alloc(struct block_device *bdev,
|
||||
unsigned short nr_vecs, unsigned int opf, gfp_t gfp_mask)
|
||||
unsigned short nr_vecs, blk_opf_t opf, gfp_t gfp_mask)
|
||||
{
|
||||
return bio_alloc_bioset(bdev, nr_vecs, opf, gfp_mask, &fs_bio_set);
|
||||
}
|
||||
|
|
@ -456,9 +456,9 @@ struct request_queue;
|
|||
|
||||
extern int submit_bio_wait(struct bio *bio);
|
||||
void bio_init(struct bio *bio, struct block_device *bdev, struct bio_vec *table,
|
||||
unsigned short max_vecs, unsigned int opf);
|
||||
unsigned short max_vecs, blk_opf_t opf);
|
||||
extern void bio_uninit(struct bio *);
|
||||
void bio_reset(struct bio *bio, struct block_device *bdev, unsigned int opf);
|
||||
void bio_reset(struct bio *bio, struct block_device *bdev, blk_opf_t opf);
|
||||
void bio_chain(struct bio *, struct bio *);
|
||||
|
||||
int bio_add_page(struct bio *, struct page *, unsigned len, unsigned off);
|
||||
|
|
@ -789,6 +789,6 @@ static inline void bio_clear_polled(struct bio *bio)
|
|||
}
|
||||
|
||||
struct bio *blk_next_bio(struct bio *bio, struct block_device *bdev,
|
||||
unsigned int nr_pages, unsigned int opf, gfp_t gfp);
|
||||
unsigned int nr_pages, blk_opf_t opf, gfp_t gfp);
|
||||
|
||||
#endif /* __LINUX_BIO_H */
|
||||
|
|
|
|||
|
|
@ -71,9 +71,9 @@ struct device;
|
|||
* bitmap_release_region(bitmap, pos, order) Free specified bit region
|
||||
* bitmap_allocate_region(bitmap, pos, order) Allocate specified bit region
|
||||
* bitmap_from_arr32(dst, buf, nbits) Copy nbits from u32[] buf to dst
|
||||
* bitmap_from_arr64(dst, buf, nbits) Copy nbits from u64[] buf to dst
|
||||
* bitmap_to_arr32(buf, src, nbits) Copy nbits from buf to u32[] dst
|
||||
* bitmap_to_arr64(buf, src, nbits) Copy nbits from buf to u64[] dst
|
||||
* bitmap_to_arr64(buf, src, nbits) Copy nbits from buf to u64[] dst
|
||||
* bitmap_get_value8(map, start) Get 8bit value from map at start
|
||||
* bitmap_set_value8(map, value, start) Set 8bit value to map at start
|
||||
*
|
||||
|
|
@ -148,13 +148,13 @@ void __bitmap_shift_left(unsigned long *dst, const unsigned long *src,
|
|||
unsigned int shift, unsigned int nbits);
|
||||
void bitmap_cut(unsigned long *dst, const unsigned long *src,
|
||||
unsigned int first, unsigned int cut, unsigned int nbits);
|
||||
int __bitmap_and(unsigned long *dst, const unsigned long *bitmap1,
|
||||
bool __bitmap_and(unsigned long *dst, const unsigned long *bitmap1,
|
||||
const unsigned long *bitmap2, unsigned int nbits);
|
||||
void __bitmap_or(unsigned long *dst, const unsigned long *bitmap1,
|
||||
const unsigned long *bitmap2, unsigned int nbits);
|
||||
void __bitmap_xor(unsigned long *dst, const unsigned long *bitmap1,
|
||||
const unsigned long *bitmap2, unsigned int nbits);
|
||||
int __bitmap_andnot(unsigned long *dst, const unsigned long *bitmap1,
|
||||
bool __bitmap_andnot(unsigned long *dst, const unsigned long *bitmap1,
|
||||
const unsigned long *bitmap2, unsigned int nbits);
|
||||
void __bitmap_replace(unsigned long *dst,
|
||||
const unsigned long *old, const unsigned long *new,
|
||||
|
|
@ -163,7 +163,7 @@ bool __bitmap_intersects(const unsigned long *bitmap1,
|
|||
const unsigned long *bitmap2, unsigned int nbits);
|
||||
bool __bitmap_subset(const unsigned long *bitmap1,
|
||||
const unsigned long *bitmap2, unsigned int nbits);
|
||||
int __bitmap_weight(const unsigned long *bitmap, unsigned int nbits);
|
||||
unsigned int __bitmap_weight(const unsigned long *bitmap, unsigned int nbits);
|
||||
void __bitmap_set(unsigned long *map, unsigned int start, int len);
|
||||
void __bitmap_clear(unsigned long *map, unsigned int start, int len);
|
||||
|
||||
|
|
@ -238,20 +238,32 @@ extern int bitmap_print_list_to_buf(char *buf, const unsigned long *maskp,
|
|||
static inline void bitmap_zero(unsigned long *dst, unsigned int nbits)
|
||||
{
|
||||
unsigned int len = BITS_TO_LONGS(nbits) * sizeof(unsigned long);
|
||||
memset(dst, 0, len);
|
||||
|
||||
if (small_const_nbits(nbits))
|
||||
*dst = 0;
|
||||
else
|
||||
memset(dst, 0, len);
|
||||
}
|
||||
|
||||
static inline void bitmap_fill(unsigned long *dst, unsigned int nbits)
|
||||
{
|
||||
unsigned int len = BITS_TO_LONGS(nbits) * sizeof(unsigned long);
|
||||
memset(dst, 0xff, len);
|
||||
|
||||
if (small_const_nbits(nbits))
|
||||
*dst = ~0UL;
|
||||
else
|
||||
memset(dst, 0xff, len);
|
||||
}
|
||||
|
||||
static inline void bitmap_copy(unsigned long *dst, const unsigned long *src,
|
||||
unsigned int nbits)
|
||||
{
|
||||
unsigned int len = BITS_TO_LONGS(nbits) * sizeof(unsigned long);
|
||||
memcpy(dst, src, len);
|
||||
|
||||
if (small_const_nbits(nbits))
|
||||
*dst = *src;
|
||||
else
|
||||
memcpy(dst, src, len);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -303,7 +315,7 @@ void bitmap_to_arr64(u64 *buf, const unsigned long *bitmap, unsigned int nbits);
|
|||
bitmap_copy_clear_tail((unsigned long *)(buf), (const unsigned long *)(bitmap), (nbits))
|
||||
#endif
|
||||
|
||||
static inline int bitmap_and(unsigned long *dst, const unsigned long *src1,
|
||||
static inline bool bitmap_and(unsigned long *dst, const unsigned long *src1,
|
||||
const unsigned long *src2, unsigned int nbits)
|
||||
{
|
||||
if (small_const_nbits(nbits))
|
||||
|
|
@ -329,7 +341,7 @@ static inline void bitmap_xor(unsigned long *dst, const unsigned long *src1,
|
|||
__bitmap_xor(dst, src1, src2, nbits);
|
||||
}
|
||||
|
||||
static inline int bitmap_andnot(unsigned long *dst, const unsigned long *src1,
|
||||
static inline bool bitmap_andnot(unsigned long *dst, const unsigned long *src1,
|
||||
const unsigned long *src2, unsigned int nbits)
|
||||
{
|
||||
if (small_const_nbits(nbits))
|
||||
|
|
@ -419,7 +431,8 @@ static inline bool bitmap_full(const unsigned long *src, unsigned int nbits)
|
|||
return find_first_zero_bit(src, nbits) == nbits;
|
||||
}
|
||||
|
||||
static __always_inline int bitmap_weight(const unsigned long *src, unsigned int nbits)
|
||||
static __always_inline
|
||||
unsigned int bitmap_weight(const unsigned long *src, unsigned int nbits)
|
||||
{
|
||||
if (small_const_nbits(nbits))
|
||||
return hweight_long(*src & BITMAP_LAST_WORD_MASK(nbits));
|
||||
|
|
@ -431,6 +444,8 @@ static __always_inline void bitmap_set(unsigned long *map, unsigned int start,
|
|||
{
|
||||
if (__builtin_constant_p(nbits) && nbits == 1)
|
||||
__set_bit(start, map);
|
||||
else if (small_const_nbits(start + nbits))
|
||||
*map |= GENMASK(start + nbits - 1, start);
|
||||
else if (__builtin_constant_p(start & BITMAP_MEM_MASK) &&
|
||||
IS_ALIGNED(start, BITMAP_MEM_ALIGNMENT) &&
|
||||
__builtin_constant_p(nbits & BITMAP_MEM_MASK) &&
|
||||
|
|
@ -445,6 +460,8 @@ static __always_inline void bitmap_clear(unsigned long *map, unsigned int start,
|
|||
{
|
||||
if (__builtin_constant_p(nbits) && nbits == 1)
|
||||
__clear_bit(start, map);
|
||||
else if (small_const_nbits(start + nbits))
|
||||
*map &= ~GENMASK(start + nbits - 1, start);
|
||||
else if (__builtin_constant_p(start & BITMAP_MEM_MASK) &&
|
||||
IS_ALIGNED(start, BITMAP_MEM_ALIGNMENT) &&
|
||||
__builtin_constant_p(nbits & BITMAP_MEM_MASK) &&
|
||||
|
|
|
|||
|
|
@ -26,12 +26,63 @@ extern unsigned int __sw_hweight16(unsigned int w);
|
|||
extern unsigned int __sw_hweight32(unsigned int w);
|
||||
extern unsigned long __sw_hweight64(__u64 w);
|
||||
|
||||
/*
|
||||
* Defined here because those may be needed by architecture-specific static
|
||||
* inlines.
|
||||
*/
|
||||
|
||||
#include <asm-generic/bitops/generic-non-atomic.h>
|
||||
|
||||
/*
|
||||
* Many architecture-specific non-atomic bitops contain inline asm code and due
|
||||
* to that the compiler can't optimize them to compile-time expressions or
|
||||
* constants. In contrary, generic_*() helpers are defined in pure C and
|
||||
* compilers optimize them just well.
|
||||
* Therefore, to make `unsigned long foo = 0; __set_bit(BAR, &foo)` effectively
|
||||
* equal to `unsigned long foo = BIT(BAR)`, pick the generic C alternative when
|
||||
* the arguments can be resolved at compile time. That expression itself is a
|
||||
* constant and doesn't bring any functional changes to the rest of cases.
|
||||
* The casts to `uintptr_t` are needed to mitigate `-Waddress` warnings when
|
||||
* passing a bitmap from .bss or .data (-> `!!addr` is always true).
|
||||
*/
|
||||
#define bitop(op, nr, addr) \
|
||||
((__builtin_constant_p(nr) && \
|
||||
__builtin_constant_p((uintptr_t)(addr) != (uintptr_t)NULL) && \
|
||||
(uintptr_t)(addr) != (uintptr_t)NULL && \
|
||||
__builtin_constant_p(*(const unsigned long *)(addr))) ? \
|
||||
const##op(nr, addr) : op(nr, addr))
|
||||
|
||||
#define __set_bit(nr, addr) bitop(___set_bit, nr, addr)
|
||||
#define __clear_bit(nr, addr) bitop(___clear_bit, nr, addr)
|
||||
#define __change_bit(nr, addr) bitop(___change_bit, nr, addr)
|
||||
#define __test_and_set_bit(nr, addr) bitop(___test_and_set_bit, nr, addr)
|
||||
#define __test_and_clear_bit(nr, addr) bitop(___test_and_clear_bit, nr, addr)
|
||||
#define __test_and_change_bit(nr, addr) bitop(___test_and_change_bit, nr, addr)
|
||||
#define test_bit(nr, addr) bitop(_test_bit, nr, addr)
|
||||
#define test_bit_acquire(nr, addr) bitop(_test_bit_acquire, nr, addr)
|
||||
|
||||
/*
|
||||
* Include this here because some architectures need generic_ffs/fls in
|
||||
* scope
|
||||
*/
|
||||
#include <asm/bitops.h>
|
||||
|
||||
/* Check that the bitops prototypes are sane */
|
||||
#define __check_bitop_pr(name) \
|
||||
static_assert(__same_type(arch_##name, generic_##name) && \
|
||||
__same_type(const_##name, generic_##name) && \
|
||||
__same_type(_##name, generic_##name))
|
||||
|
||||
__check_bitop_pr(__set_bit);
|
||||
__check_bitop_pr(__clear_bit);
|
||||
__check_bitop_pr(__change_bit);
|
||||
__check_bitop_pr(__test_and_set_bit);
|
||||
__check_bitop_pr(__test_and_clear_bit);
|
||||
__check_bitop_pr(__test_and_change_bit);
|
||||
__check_bitop_pr(test_bit);
|
||||
|
||||
#undef __check_bitop_pr
|
||||
|
||||
static inline int get_bitmask_order(unsigned int count)
|
||||
{
|
||||
int order;
|
||||
|
|
|
|||
|
|
@ -57,6 +57,7 @@ typedef __u32 __bitwise req_flags_t;
|
|||
#define RQF_TIMED_OUT ((__force req_flags_t)(1 << 21))
|
||||
/* queue has elevator attached */
|
||||
#define RQF_ELV ((__force req_flags_t)(1 << 22))
|
||||
#define RQF_RESV ((__force req_flags_t)(1 << 23))
|
||||
|
||||
/* flags that prevent us from merging requests: */
|
||||
#define RQF_NOMERGE_FLAGS \
|
||||
|
|
@ -79,7 +80,7 @@ struct request {
|
|||
struct blk_mq_ctx *mq_ctx;
|
||||
struct blk_mq_hw_ctx *mq_hctx;
|
||||
|
||||
unsigned int cmd_flags; /* op and common flags */
|
||||
blk_opf_t cmd_flags; /* op and common flags */
|
||||
req_flags_t rq_flags;
|
||||
|
||||
int tag;
|
||||
|
|
@ -197,8 +198,10 @@ struct request {
|
|||
void *end_io_data;
|
||||
};
|
||||
|
||||
#define req_op(req) \
|
||||
((req)->cmd_flags & REQ_OP_MASK)
|
||||
static inline enum req_op req_op(const struct request *req)
|
||||
{
|
||||
return req->cmd_flags & REQ_OP_MASK;
|
||||
}
|
||||
|
||||
static inline bool blk_rq_is_passthrough(struct request *rq)
|
||||
{
|
||||
|
|
@ -519,7 +522,7 @@ struct blk_mq_queue_data {
|
|||
bool last;
|
||||
};
|
||||
|
||||
typedef bool (busy_tag_iter_fn)(struct request *, void *, bool);
|
||||
typedef bool (busy_tag_iter_fn)(struct request *, void *);
|
||||
|
||||
/**
|
||||
* struct blk_mq_ops - Callback functions that implements block driver
|
||||
|
|
@ -574,7 +577,7 @@ struct blk_mq_ops {
|
|||
/**
|
||||
* @timeout: Called on request timeout.
|
||||
*/
|
||||
enum blk_eh_timer_return (*timeout)(struct request *, bool);
|
||||
enum blk_eh_timer_return (*timeout)(struct request *);
|
||||
|
||||
/**
|
||||
* @poll: Called to poll for completion of a specific tag.
|
||||
|
|
@ -686,10 +689,12 @@ struct gendisk *__blk_mq_alloc_disk(struct blk_mq_tag_set *set, void *queuedata,
|
|||
\
|
||||
__blk_mq_alloc_disk(set, queuedata, &__key); \
|
||||
})
|
||||
struct gendisk *blk_mq_alloc_disk_for_queue(struct request_queue *q,
|
||||
struct lock_class_key *lkclass);
|
||||
struct request_queue *blk_mq_init_queue(struct blk_mq_tag_set *);
|
||||
int blk_mq_init_allocated_queue(struct blk_mq_tag_set *set,
|
||||
struct request_queue *q);
|
||||
void blk_mq_unregister_dev(struct device *, struct request_queue *);
|
||||
void blk_mq_destroy_queue(struct request_queue *);
|
||||
|
||||
int blk_mq_alloc_tag_set(struct blk_mq_tag_set *set);
|
||||
int blk_mq_alloc_sq_tag_set(struct blk_mq_tag_set *set,
|
||||
|
|
@ -710,10 +715,10 @@ enum {
|
|||
BLK_MQ_REQ_PM = (__force blk_mq_req_flags_t)(1 << 2),
|
||||
};
|
||||
|
||||
struct request *blk_mq_alloc_request(struct request_queue *q, unsigned int op,
|
||||
struct request *blk_mq_alloc_request(struct request_queue *q, blk_opf_t opf,
|
||||
blk_mq_req_flags_t flags);
|
||||
struct request *blk_mq_alloc_request_hctx(struct request_queue *q,
|
||||
unsigned int op, blk_mq_req_flags_t flags,
|
||||
blk_opf_t opf, blk_mq_req_flags_t flags,
|
||||
unsigned int hctx_idx);
|
||||
|
||||
/*
|
||||
|
|
@ -823,6 +828,11 @@ static inline bool blk_mq_need_time_stamp(struct request *rq)
|
|||
return (rq->rq_flags & (RQF_IO_STAT | RQF_STATS | RQF_ELV));
|
||||
}
|
||||
|
||||
static inline bool blk_mq_is_reserved_rq(struct request *rq)
|
||||
{
|
||||
return rq->rq_flags & RQF_RESV;
|
||||
}
|
||||
|
||||
/*
|
||||
* Batched completions only work when there is no I/O error and no special
|
||||
* ->end_io handler.
|
||||
|
|
@ -847,7 +857,6 @@ void blk_mq_kick_requeue_list(struct request_queue *q);
|
|||
void blk_mq_delay_kick_requeue_list(struct request_queue *q, unsigned long msecs);
|
||||
void blk_mq_complete_request(struct request *rq);
|
||||
bool blk_mq_complete_request_remote(struct request *rq);
|
||||
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);
|
||||
void blk_mq_stop_hw_queues(struct request_queue *q);
|
||||
|
|
@ -1121,12 +1130,12 @@ void blk_dump_rq_flags(struct request *, char *);
|
|||
#ifdef CONFIG_BLK_DEV_ZONED
|
||||
static inline unsigned int blk_rq_zone_no(struct request *rq)
|
||||
{
|
||||
return blk_queue_zone_no(rq->q, blk_rq_pos(rq));
|
||||
return disk_zone_no(rq->q->disk, blk_rq_pos(rq));
|
||||
}
|
||||
|
||||
static inline unsigned int blk_rq_zone_is_seq(struct request *rq)
|
||||
{
|
||||
return blk_queue_zone_is_seq(rq->q, blk_rq_pos(rq));
|
||||
return disk_zone_is_seq(rq->q->disk, blk_rq_pos(rq));
|
||||
}
|
||||
|
||||
bool blk_req_needs_zone_write_lock(struct request *rq);
|
||||
|
|
@ -1148,8 +1157,8 @@ static inline void blk_req_zone_write_unlock(struct request *rq)
|
|||
|
||||
static inline bool blk_req_zone_is_write_locked(struct request *rq)
|
||||
{
|
||||
return rq->q->seq_zones_wlock &&
|
||||
test_bit(blk_rq_zone_no(rq), rq->q->seq_zones_wlock);
|
||||
return rq->q->disk->seq_zones_wlock &&
|
||||
test_bit(blk_rq_zone_no(rq), rq->q->disk->seq_zones_wlock);
|
||||
}
|
||||
|
||||
static inline bool blk_req_can_dispatch_to_zone(struct request *rq)
|
||||
|
|
|
|||
|
|
@ -240,6 +240,8 @@ static inline void bio_issue_init(struct bio_issue *issue,
|
|||
((u64)size << BIO_ISSUE_SIZE_SHIFT));
|
||||
}
|
||||
|
||||
typedef __u32 __bitwise blk_opf_t;
|
||||
|
||||
typedef unsigned int blk_qc_t;
|
||||
#define BLK_QC_T_NONE -1U
|
||||
|
||||
|
|
@ -250,7 +252,7 @@ typedef unsigned int blk_qc_t;
|
|||
struct bio {
|
||||
struct bio *bi_next; /* request queue link */
|
||||
struct block_device *bi_bdev;
|
||||
unsigned int bi_opf; /* bottom bits REQ_OP, top bits
|
||||
blk_opf_t bi_opf; /* bottom bits REQ_OP, top bits
|
||||
* req_flags.
|
||||
*/
|
||||
unsigned short bi_flags; /* BIO_* below */
|
||||
|
|
@ -337,8 +339,12 @@ enum {
|
|||
|
||||
typedef __u32 __bitwise blk_mq_req_flags_t;
|
||||
|
||||
/*
|
||||
* Operations and flags common to the bio and request structures.
|
||||
#define REQ_OP_BITS 8
|
||||
#define REQ_OP_MASK (__force blk_opf_t)((1 << REQ_OP_BITS) - 1)
|
||||
#define REQ_FLAG_BITS 24
|
||||
|
||||
/**
|
||||
* enum req_op - Operations common to the bio and request structures.
|
||||
* We use 8 bits for encoding the operation, and the remaining 24 for flags.
|
||||
*
|
||||
* The least significant bit of the operation number indicates the data
|
||||
|
|
@ -350,41 +356,37 @@ typedef __u32 __bitwise blk_mq_req_flags_t;
|
|||
* If a operation does not transfer data the least significant bit has no
|
||||
* meaning.
|
||||
*/
|
||||
#define REQ_OP_BITS 8
|
||||
#define REQ_OP_MASK ((1 << REQ_OP_BITS) - 1)
|
||||
#define REQ_FLAG_BITS 24
|
||||
|
||||
enum req_opf {
|
||||
enum req_op {
|
||||
/* read sectors from the device */
|
||||
REQ_OP_READ = 0,
|
||||
REQ_OP_READ = (__force blk_opf_t)0,
|
||||
/* write sectors to the device */
|
||||
REQ_OP_WRITE = 1,
|
||||
REQ_OP_WRITE = (__force blk_opf_t)1,
|
||||
/* flush the volatile write cache */
|
||||
REQ_OP_FLUSH = 2,
|
||||
REQ_OP_FLUSH = (__force blk_opf_t)2,
|
||||
/* discard sectors */
|
||||
REQ_OP_DISCARD = 3,
|
||||
REQ_OP_DISCARD = (__force blk_opf_t)3,
|
||||
/* securely erase sectors */
|
||||
REQ_OP_SECURE_ERASE = 5,
|
||||
REQ_OP_SECURE_ERASE = (__force blk_opf_t)5,
|
||||
/* write the zero filled sector many times */
|
||||
REQ_OP_WRITE_ZEROES = 9,
|
||||
REQ_OP_WRITE_ZEROES = (__force blk_opf_t)9,
|
||||
/* Open a zone */
|
||||
REQ_OP_ZONE_OPEN = 10,
|
||||
REQ_OP_ZONE_OPEN = (__force blk_opf_t)10,
|
||||
/* Close a zone */
|
||||
REQ_OP_ZONE_CLOSE = 11,
|
||||
REQ_OP_ZONE_CLOSE = (__force blk_opf_t)11,
|
||||
/* Transition a zone to full */
|
||||
REQ_OP_ZONE_FINISH = 12,
|
||||
REQ_OP_ZONE_FINISH = (__force blk_opf_t)12,
|
||||
/* write data at the current zone write pointer */
|
||||
REQ_OP_ZONE_APPEND = 13,
|
||||
REQ_OP_ZONE_APPEND = (__force blk_opf_t)13,
|
||||
/* reset a zone write pointer */
|
||||
REQ_OP_ZONE_RESET = 15,
|
||||
REQ_OP_ZONE_RESET = (__force blk_opf_t)15,
|
||||
/* reset all the zone present on the device */
|
||||
REQ_OP_ZONE_RESET_ALL = 17,
|
||||
REQ_OP_ZONE_RESET_ALL = (__force blk_opf_t)17,
|
||||
|
||||
/* Driver private requests */
|
||||
REQ_OP_DRV_IN = 34,
|
||||
REQ_OP_DRV_OUT = 35,
|
||||
REQ_OP_DRV_IN = (__force blk_opf_t)34,
|
||||
REQ_OP_DRV_OUT = (__force blk_opf_t)35,
|
||||
|
||||
REQ_OP_LAST,
|
||||
REQ_OP_LAST = (__force blk_opf_t)36,
|
||||
};
|
||||
|
||||
enum req_flag_bits {
|
||||
|
|
@ -425,28 +427,31 @@ enum req_flag_bits {
|
|||
__REQ_NR_BITS, /* stops here */
|
||||
};
|
||||
|
||||
#define REQ_FAILFAST_DEV (1ULL << __REQ_FAILFAST_DEV)
|
||||
#define REQ_FAILFAST_TRANSPORT (1ULL << __REQ_FAILFAST_TRANSPORT)
|
||||
#define REQ_FAILFAST_DRIVER (1ULL << __REQ_FAILFAST_DRIVER)
|
||||
#define REQ_SYNC (1ULL << __REQ_SYNC)
|
||||
#define REQ_META (1ULL << __REQ_META)
|
||||
#define REQ_PRIO (1ULL << __REQ_PRIO)
|
||||
#define REQ_NOMERGE (1ULL << __REQ_NOMERGE)
|
||||
#define REQ_IDLE (1ULL << __REQ_IDLE)
|
||||
#define REQ_INTEGRITY (1ULL << __REQ_INTEGRITY)
|
||||
#define REQ_FUA (1ULL << __REQ_FUA)
|
||||
#define REQ_PREFLUSH (1ULL << __REQ_PREFLUSH)
|
||||
#define REQ_RAHEAD (1ULL << __REQ_RAHEAD)
|
||||
#define REQ_BACKGROUND (1ULL << __REQ_BACKGROUND)
|
||||
#define REQ_NOWAIT (1ULL << __REQ_NOWAIT)
|
||||
#define REQ_CGROUP_PUNT (1ULL << __REQ_CGROUP_PUNT)
|
||||
#define REQ_FAILFAST_DEV \
|
||||
(__force blk_opf_t)(1ULL << __REQ_FAILFAST_DEV)
|
||||
#define REQ_FAILFAST_TRANSPORT \
|
||||
(__force blk_opf_t)(1ULL << __REQ_FAILFAST_TRANSPORT)
|
||||
#define REQ_FAILFAST_DRIVER \
|
||||
(__force blk_opf_t)(1ULL << __REQ_FAILFAST_DRIVER)
|
||||
#define REQ_SYNC (__force blk_opf_t)(1ULL << __REQ_SYNC)
|
||||
#define REQ_META (__force blk_opf_t)(1ULL << __REQ_META)
|
||||
#define REQ_PRIO (__force blk_opf_t)(1ULL << __REQ_PRIO)
|
||||
#define REQ_NOMERGE (__force blk_opf_t)(1ULL << __REQ_NOMERGE)
|
||||
#define REQ_IDLE (__force blk_opf_t)(1ULL << __REQ_IDLE)
|
||||
#define REQ_INTEGRITY (__force blk_opf_t)(1ULL << __REQ_INTEGRITY)
|
||||
#define REQ_FUA (__force blk_opf_t)(1ULL << __REQ_FUA)
|
||||
#define REQ_PREFLUSH (__force blk_opf_t)(1ULL << __REQ_PREFLUSH)
|
||||
#define REQ_RAHEAD (__force blk_opf_t)(1ULL << __REQ_RAHEAD)
|
||||
#define REQ_BACKGROUND (__force blk_opf_t)(1ULL << __REQ_BACKGROUND)
|
||||
#define REQ_NOWAIT (__force blk_opf_t)(1ULL << __REQ_NOWAIT)
|
||||
#define REQ_CGROUP_PUNT (__force blk_opf_t)(1ULL << __REQ_CGROUP_PUNT)
|
||||
|
||||
#define REQ_NOUNMAP (1ULL << __REQ_NOUNMAP)
|
||||
#define REQ_POLLED (1ULL << __REQ_POLLED)
|
||||
#define REQ_ALLOC_CACHE (1ULL << __REQ_ALLOC_CACHE)
|
||||
#define REQ_NOUNMAP (__force blk_opf_t)(1ULL << __REQ_NOUNMAP)
|
||||
#define REQ_POLLED (__force blk_opf_t)(1ULL << __REQ_POLLED)
|
||||
#define REQ_ALLOC_CACHE (__force blk_opf_t)(1ULL << __REQ_ALLOC_CACHE)
|
||||
|
||||
#define REQ_DRV (1ULL << __REQ_DRV)
|
||||
#define REQ_SWAP (1ULL << __REQ_SWAP)
|
||||
#define REQ_DRV (__force blk_opf_t)(1ULL << __REQ_DRV)
|
||||
#define REQ_SWAP (__force blk_opf_t)(1ULL << __REQ_SWAP)
|
||||
|
||||
#define REQ_FAILFAST_MASK \
|
||||
(REQ_FAILFAST_DEV | REQ_FAILFAST_TRANSPORT | REQ_FAILFAST_DRIVER)
|
||||
|
|
@ -463,26 +468,28 @@ enum stat_group {
|
|||
NR_STAT_GROUPS
|
||||
};
|
||||
|
||||
#define bio_op(bio) \
|
||||
((bio)->bi_opf & REQ_OP_MASK)
|
||||
static inline enum req_op bio_op(const struct bio *bio)
|
||||
{
|
||||
return bio->bi_opf & REQ_OP_MASK;
|
||||
}
|
||||
|
||||
/* obsolete, don't use in new code */
|
||||
static inline void bio_set_op_attrs(struct bio *bio, unsigned op,
|
||||
unsigned op_flags)
|
||||
static inline void bio_set_op_attrs(struct bio *bio, enum req_op op,
|
||||
blk_opf_t op_flags)
|
||||
{
|
||||
bio->bi_opf = op | op_flags;
|
||||
}
|
||||
|
||||
static inline bool op_is_write(unsigned int op)
|
||||
static inline bool op_is_write(blk_opf_t op)
|
||||
{
|
||||
return (op & 1);
|
||||
return !!(op & (__force blk_opf_t)1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if the bio or request is one that needs special treatment in the
|
||||
* flush state machine.
|
||||
*/
|
||||
static inline bool op_is_flush(unsigned int op)
|
||||
static inline bool op_is_flush(blk_opf_t op)
|
||||
{
|
||||
return op & (REQ_FUA | REQ_PREFLUSH);
|
||||
}
|
||||
|
|
@ -492,13 +499,13 @@ static inline bool op_is_flush(unsigned int op)
|
|||
* PREFLUSH flag. Other operations may be marked as synchronous using the
|
||||
* REQ_SYNC flag.
|
||||
*/
|
||||
static inline bool op_is_sync(unsigned int op)
|
||||
static inline bool op_is_sync(blk_opf_t op)
|
||||
{
|
||||
return (op & REQ_OP_MASK) == REQ_OP_READ ||
|
||||
(op & (REQ_SYNC | REQ_FUA | REQ_PREFLUSH));
|
||||
}
|
||||
|
||||
static inline bool op_is_discard(unsigned int op)
|
||||
static inline bool op_is_discard(blk_opf_t op)
|
||||
{
|
||||
return (op & REQ_OP_MASK) == REQ_OP_DISCARD;
|
||||
}
|
||||
|
|
@ -509,7 +516,7 @@ static inline bool op_is_discard(unsigned int op)
|
|||
* due to its different handling in the block layer and device response in
|
||||
* case of command failure.
|
||||
*/
|
||||
static inline bool op_is_zone_mgmt(enum req_opf op)
|
||||
static inline bool op_is_zone_mgmt(enum req_op op)
|
||||
{
|
||||
switch (op & REQ_OP_MASK) {
|
||||
case REQ_OP_ZONE_RESET:
|
||||
|
|
@ -522,7 +529,7 @@ static inline bool op_is_zone_mgmt(enum req_opf op)
|
|||
}
|
||||
}
|
||||
|
||||
static inline int op_stat_group(unsigned int op)
|
||||
static inline int op_stat_group(enum req_op op)
|
||||
{
|
||||
if (op_is_discard(op))
|
||||
return STAT_DISCARD;
|
||||
|
|
|
|||
|
|
@ -140,6 +140,8 @@ struct gendisk {
|
|||
struct request_queue *queue;
|
||||
void *private_data;
|
||||
|
||||
struct bio_set bio_split;
|
||||
|
||||
int flags;
|
||||
unsigned long state;
|
||||
#define GD_NEED_PART_SCAN 0
|
||||
|
|
@ -148,6 +150,7 @@ struct gendisk {
|
|||
#define GD_NATIVE_CAPACITY 3
|
||||
#define GD_ADDED 4
|
||||
#define GD_SUPPRESS_PART_SCAN 5
|
||||
#define GD_OWNS_QUEUE 6
|
||||
|
||||
struct mutex open_mutex; /* open/close mutex */
|
||||
unsigned open_partitions; /* number of open partitions */
|
||||
|
|
@ -163,6 +166,29 @@ struct gendisk {
|
|||
#ifdef CONFIG_BLK_DEV_INTEGRITY
|
||||
struct kobject integrity_kobj;
|
||||
#endif /* CONFIG_BLK_DEV_INTEGRITY */
|
||||
|
||||
#ifdef CONFIG_BLK_DEV_ZONED
|
||||
/*
|
||||
* Zoned block device information for request dispatch control.
|
||||
* nr_zones is the total number of zones of the device. This is always
|
||||
* 0 for regular block devices. conv_zones_bitmap is a bitmap of nr_zones
|
||||
* bits which indicates if a zone is conventional (bit set) or
|
||||
* sequential (bit clear). seq_zones_wlock is a bitmap of nr_zones
|
||||
* bits which indicates if a zone is write locked, that is, if a write
|
||||
* request targeting the zone was dispatched.
|
||||
*
|
||||
* Reads of this information must be protected with blk_queue_enter() /
|
||||
* blk_queue_exit(). Modifying this information is only allowed while
|
||||
* no requests are being processed. See also blk_mq_freeze_queue() and
|
||||
* blk_mq_unfreeze_queue().
|
||||
*/
|
||||
unsigned int nr_zones;
|
||||
unsigned int max_open_zones;
|
||||
unsigned int max_active_zones;
|
||||
unsigned long *conv_zones_bitmap;
|
||||
unsigned long *seq_zones_wlock;
|
||||
#endif /* CONFIG_BLK_DEV_ZONED */
|
||||
|
||||
#if IS_ENABLED(CONFIG_CDROM)
|
||||
struct cdrom_device_info *cdi;
|
||||
#endif
|
||||
|
|
@ -170,6 +196,12 @@ struct gendisk {
|
|||
struct badblocks *bb;
|
||||
struct lockdep_map lockdep_map;
|
||||
u64 diskseq;
|
||||
|
||||
/*
|
||||
* Independent sector access ranges. This is always NULL for
|
||||
* devices that do not have multiple independent access ranges.
|
||||
*/
|
||||
struct blk_independent_access_ranges *ia_ranges;
|
||||
};
|
||||
|
||||
static inline bool disk_live(struct gendisk *disk)
|
||||
|
|
@ -220,7 +252,7 @@ static inline int blk_validate_block_size(unsigned long bsize)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static inline bool blk_op_is_passthrough(unsigned int op)
|
||||
static inline bool blk_op_is_passthrough(blk_opf_t op)
|
||||
{
|
||||
op &= REQ_OP_MASK;
|
||||
return op == REQ_OP_DRV_IN || op == REQ_OP_DRV_OUT;
|
||||
|
|
@ -284,15 +316,15 @@ struct queue_limits {
|
|||
typedef int (*report_zones_cb)(struct blk_zone *zone, unsigned int idx,
|
||||
void *data);
|
||||
|
||||
void blk_queue_set_zoned(struct gendisk *disk, enum blk_zoned_model model);
|
||||
void disk_set_zoned(struct gendisk *disk, enum blk_zoned_model model);
|
||||
|
||||
#ifdef CONFIG_BLK_DEV_ZONED
|
||||
|
||||
#define BLK_ALL_ZONES ((unsigned int)-1)
|
||||
int blkdev_report_zones(struct block_device *bdev, sector_t sector,
|
||||
unsigned int nr_zones, report_zones_cb cb, void *data);
|
||||
unsigned int blkdev_nr_zones(struct gendisk *disk);
|
||||
extern int blkdev_zone_mgmt(struct block_device *bdev, enum req_opf op,
|
||||
unsigned int bdev_nr_zones(struct block_device *bdev);
|
||||
extern int blkdev_zone_mgmt(struct block_device *bdev, enum req_op op,
|
||||
sector_t sectors, sector_t nr_sectors,
|
||||
gfp_t gfp_mask);
|
||||
int blk_revalidate_disk_zones(struct gendisk *disk,
|
||||
|
|
@ -305,7 +337,7 @@ extern int blkdev_zone_mgmt_ioctl(struct block_device *bdev, fmode_t mode,
|
|||
|
||||
#else /* CONFIG_BLK_DEV_ZONED */
|
||||
|
||||
static inline unsigned int blkdev_nr_zones(struct gendisk *disk)
|
||||
static inline unsigned int bdev_nr_zones(struct block_device *bdev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -424,6 +456,11 @@ struct request_queue {
|
|||
unsigned long nr_requests; /* Max # of requests */
|
||||
|
||||
unsigned int dma_pad_mask;
|
||||
/*
|
||||
* Drivers that set dma_alignment to less than 511 must be prepared to
|
||||
* handle individual bvec's that are not a multiple of a SECTOR_SIZE
|
||||
* due to possible offsets.
|
||||
*/
|
||||
unsigned int dma_alignment;
|
||||
|
||||
#ifdef CONFIG_BLK_INLINE_ENCRYPTION
|
||||
|
|
@ -455,31 +492,6 @@ struct request_queue {
|
|||
|
||||
unsigned int required_elevator_features;
|
||||
|
||||
#ifdef CONFIG_BLK_DEV_ZONED
|
||||
/*
|
||||
* Zoned block device information for request dispatch control.
|
||||
* nr_zones is the total number of zones of the device. This is always
|
||||
* 0 for regular block devices. conv_zones_bitmap is a bitmap of nr_zones
|
||||
* bits which indicates if a zone is conventional (bit set) or
|
||||
* sequential (bit clear). seq_zones_wlock is a bitmap of nr_zones
|
||||
* bits which indicates if a zone is write locked, that is, if a write
|
||||
* request targeting the zone was dispatched. All three fields are
|
||||
* initialized by the low level device driver (e.g. scsi/sd.c).
|
||||
* Stacking drivers (device mappers) may or may not initialize
|
||||
* these fields.
|
||||
*
|
||||
* Reads of this information must be protected with blk_queue_enter() /
|
||||
* blk_queue_exit(). Modifying this information is only allowed while
|
||||
* no requests are being processed. See also blk_mq_freeze_queue() and
|
||||
* blk_mq_unfreeze_queue().
|
||||
*/
|
||||
unsigned int nr_zones;
|
||||
unsigned long *conv_zones_bitmap;
|
||||
unsigned long *seq_zones_wlock;
|
||||
unsigned int max_open_zones;
|
||||
unsigned int max_active_zones;
|
||||
#endif /* CONFIG_BLK_DEV_ZONED */
|
||||
|
||||
int node;
|
||||
#ifdef CONFIG_BLK_DEV_IO_TRACE
|
||||
struct blk_trace __rcu *blk_trace;
|
||||
|
|
@ -521,7 +533,6 @@ struct request_queue {
|
|||
|
||||
struct blk_mq_tag_set *tag_set;
|
||||
struct list_head tag_set_list;
|
||||
struct bio_set bio_split;
|
||||
|
||||
struct dentry *debugfs_dir;
|
||||
struct dentry *sched_debugfs_dir;
|
||||
|
|
@ -533,12 +544,6 @@ struct request_queue {
|
|||
|
||||
bool mq_sysfs_init_done;
|
||||
|
||||
/*
|
||||
* Independent sector access ranges. This is always NULL for
|
||||
* devices that do not have multiple independent access ranges.
|
||||
*/
|
||||
struct blk_independent_access_ranges *ia_ranges;
|
||||
|
||||
/**
|
||||
* @srcu: Sleepable RCU. Use as lock when type of the request queue
|
||||
* is blocking (BLK_MQ_F_BLOCKING). Must be the last member
|
||||
|
|
@ -559,7 +564,6 @@ struct request_queue {
|
|||
#define QUEUE_FLAG_NOXMERGES 9 /* No extended merges */
|
||||
#define QUEUE_FLAG_ADD_RANDOM 10 /* Contributes to random pool */
|
||||
#define QUEUE_FLAG_SAME_FORCE 12 /* force complete on same CPU */
|
||||
#define QUEUE_FLAG_DEAD 13 /* queue tear-down finished */
|
||||
#define QUEUE_FLAG_INIT_DONE 14 /* queue is initialized */
|
||||
#define QUEUE_FLAG_STABLE_WRITES 15 /* don't modify blks until WB is done */
|
||||
#define QUEUE_FLAG_POLL 16 /* IO polling enabled if set */
|
||||
|
|
@ -587,7 +591,6 @@ bool blk_queue_flag_test_and_set(unsigned int flag, struct request_queue *q);
|
|||
#define blk_queue_stopped(q) test_bit(QUEUE_FLAG_STOPPED, &(q)->queue_flags)
|
||||
#define blk_queue_dying(q) test_bit(QUEUE_FLAG_DYING, &(q)->queue_flags)
|
||||
#define blk_queue_has_srcu(q) test_bit(QUEUE_FLAG_HAS_SRCU, &(q)->queue_flags)
|
||||
#define blk_queue_dead(q) test_bit(QUEUE_FLAG_DEAD, &(q)->queue_flags)
|
||||
#define blk_queue_init_done(q) test_bit(QUEUE_FLAG_INIT_DONE, &(q)->queue_flags)
|
||||
#define blk_queue_nomerges(q) test_bit(QUEUE_FLAG_NOMERGES, &(q)->queue_flags)
|
||||
#define blk_queue_noxmerges(q) \
|
||||
|
|
@ -663,76 +666,69 @@ static inline bool blk_queue_is_zoned(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;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_BLK_DEV_ZONED
|
||||
static inline unsigned int blk_queue_nr_zones(struct request_queue *q)
|
||||
static inline unsigned int disk_nr_zones(struct gendisk *disk)
|
||||
{
|
||||
return blk_queue_is_zoned(q) ? q->nr_zones : 0;
|
||||
return blk_queue_is_zoned(disk->queue) ? disk->nr_zones : 0;
|
||||
}
|
||||
|
||||
static inline unsigned int blk_queue_zone_no(struct request_queue *q,
|
||||
sector_t sector)
|
||||
static inline unsigned int disk_zone_no(struct gendisk *disk, sector_t sector)
|
||||
{
|
||||
if (!blk_queue_is_zoned(q))
|
||||
if (!blk_queue_is_zoned(disk->queue))
|
||||
return 0;
|
||||
return sector >> ilog2(q->limits.chunk_sectors);
|
||||
return sector >> ilog2(disk->queue->limits.chunk_sectors);
|
||||
}
|
||||
|
||||
static inline bool blk_queue_zone_is_seq(struct request_queue *q,
|
||||
sector_t sector)
|
||||
static inline bool disk_zone_is_seq(struct gendisk *disk, sector_t sector)
|
||||
{
|
||||
if (!blk_queue_is_zoned(q))
|
||||
if (!blk_queue_is_zoned(disk->queue))
|
||||
return false;
|
||||
if (!q->conv_zones_bitmap)
|
||||
if (!disk->conv_zones_bitmap)
|
||||
return true;
|
||||
return !test_bit(blk_queue_zone_no(q, sector), q->conv_zones_bitmap);
|
||||
return !test_bit(disk_zone_no(disk, sector), disk->conv_zones_bitmap);
|
||||
}
|
||||
|
||||
static inline void blk_queue_max_open_zones(struct request_queue *q,
|
||||
static inline void disk_set_max_open_zones(struct gendisk *disk,
|
||||
unsigned int max_open_zones)
|
||||
{
|
||||
q->max_open_zones = max_open_zones;
|
||||
disk->max_open_zones = max_open_zones;
|
||||
}
|
||||
|
||||
static inline unsigned int queue_max_open_zones(const struct request_queue *q)
|
||||
{
|
||||
return q->max_open_zones;
|
||||
}
|
||||
|
||||
static inline void blk_queue_max_active_zones(struct request_queue *q,
|
||||
static inline void disk_set_max_active_zones(struct gendisk *disk,
|
||||
unsigned int max_active_zones)
|
||||
{
|
||||
q->max_active_zones = max_active_zones;
|
||||
disk->max_active_zones = max_active_zones;
|
||||
}
|
||||
|
||||
static inline unsigned int queue_max_active_zones(const struct request_queue *q)
|
||||
static inline unsigned int bdev_max_open_zones(struct block_device *bdev)
|
||||
{
|
||||
return q->max_active_zones;
|
||||
return bdev->bd_disk->max_open_zones;
|
||||
}
|
||||
|
||||
static inline unsigned int bdev_max_active_zones(struct block_device *bdev)
|
||||
{
|
||||
return bdev->bd_disk->max_active_zones;
|
||||
}
|
||||
|
||||
#else /* CONFIG_BLK_DEV_ZONED */
|
||||
static inline unsigned int blk_queue_nr_zones(struct request_queue *q)
|
||||
static inline unsigned int disk_nr_zones(struct gendisk *disk)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static inline bool blk_queue_zone_is_seq(struct request_queue *q,
|
||||
sector_t sector)
|
||||
static inline bool disk_zone_is_seq(struct gendisk *disk, sector_t sector)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
static inline unsigned int blk_queue_zone_no(struct request_queue *q,
|
||||
sector_t sector)
|
||||
static inline unsigned int disk_zone_no(struct gendisk *disk, sector_t sector)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static inline unsigned int queue_max_open_zones(const struct request_queue *q)
|
||||
static inline unsigned int bdev_max_open_zones(struct block_device *bdev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static inline unsigned int queue_max_active_zones(const struct request_queue *q)
|
||||
|
||||
static inline unsigned int bdev_max_active_zones(struct block_device *bdev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -812,8 +808,6 @@ static inline u64 sb_bdev_nr_blocks(struct super_block *sb)
|
|||
|
||||
int bdev_disk_changed(struct gendisk *disk, bool invalidate);
|
||||
|
||||
struct gendisk *__alloc_disk_node(struct request_queue *q, int node_id,
|
||||
struct lock_class_key *lkclass);
|
||||
void put_disk(struct gendisk *disk);
|
||||
struct gendisk *__blk_alloc_disk(int node, struct lock_class_key *lkclass);
|
||||
|
||||
|
|
@ -832,7 +826,6 @@ struct gendisk *__blk_alloc_disk(int node, struct lock_class_key *lkclass);
|
|||
\
|
||||
__blk_alloc_disk(node_id, &__key); \
|
||||
})
|
||||
void blk_cleanup_disk(struct gendisk *disk);
|
||||
|
||||
int __register_blkdev(unsigned int major, const char *name,
|
||||
void (*probe)(dev_t devt));
|
||||
|
|
@ -872,15 +865,15 @@ void blk_request_module(dev_t devt);
|
|||
extern int blk_register_queue(struct gendisk *disk);
|
||||
extern void blk_unregister_queue(struct gendisk *disk);
|
||||
void submit_bio_noacct(struct bio *bio);
|
||||
struct bio *bio_split_to_limits(struct bio *bio);
|
||||
|
||||
extern int blk_lld_busy(struct request_queue *q);
|
||||
extern void blk_queue_split(struct bio **);
|
||||
extern int blk_queue_enter(struct request_queue *q, blk_mq_req_flags_t flags);
|
||||
extern void blk_queue_exit(struct request_queue *q);
|
||||
extern void blk_sync_queue(struct request_queue *q);
|
||||
|
||||
/* Helper to convert REQ_OP_XXX to its string format XXX */
|
||||
extern const char *blk_op_str(unsigned int op);
|
||||
extern const char *blk_op_str(enum req_op op);
|
||||
|
||||
int blk_status_to_errno(blk_status_t status);
|
||||
blk_status_t errno_to_blk_status(int errno);
|
||||
|
|
@ -898,64 +891,33 @@ static inline struct request_queue *bdev_get_queue(struct block_device *bdev)
|
|||
return bdev->bd_queue; /* this is never NULL */
|
||||
}
|
||||
|
||||
#ifdef CONFIG_BLK_DEV_ZONED
|
||||
|
||||
/* Helper to convert BLK_ZONE_ZONE_XXX to its string format XXX */
|
||||
const char *blk_zone_cond_str(enum blk_zone_cond zone_cond);
|
||||
|
||||
static inline unsigned int bio_zone_no(struct bio *bio)
|
||||
{
|
||||
return blk_queue_zone_no(bdev_get_queue(bio->bi_bdev),
|
||||
bio->bi_iter.bi_sector);
|
||||
return disk_zone_no(bio->bi_bdev->bd_disk, bio->bi_iter.bi_sector);
|
||||
}
|
||||
|
||||
static inline unsigned int bio_zone_is_seq(struct bio *bio)
|
||||
{
|
||||
return blk_queue_zone_is_seq(bdev_get_queue(bio->bi_bdev),
|
||||
bio->bi_iter.bi_sector);
|
||||
}
|
||||
#endif /* CONFIG_BLK_DEV_ZONED */
|
||||
|
||||
static inline unsigned int blk_queue_get_max_sectors(struct request_queue *q,
|
||||
int op)
|
||||
{
|
||||
if (unlikely(op == REQ_OP_DISCARD || op == REQ_OP_SECURE_ERASE))
|
||||
return min(q->limits.max_discard_sectors,
|
||||
UINT_MAX >> SECTOR_SHIFT);
|
||||
|
||||
if (unlikely(op == REQ_OP_WRITE_ZEROES))
|
||||
return q->limits.max_write_zeroes_sectors;
|
||||
|
||||
return q->limits.max_sectors;
|
||||
return disk_zone_is_seq(bio->bi_bdev->bd_disk, bio->bi_iter.bi_sector);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return maximum size of a request at given offset. Only valid for
|
||||
* file system requests.
|
||||
* Return how much of the chunk is left to be used for I/O at a given offset.
|
||||
*/
|
||||
static inline unsigned int blk_max_size_offset(struct request_queue *q,
|
||||
sector_t offset,
|
||||
unsigned int chunk_sectors)
|
||||
static inline unsigned int blk_chunk_sectors_left(sector_t offset,
|
||||
unsigned int chunk_sectors)
|
||||
{
|
||||
if (!chunk_sectors) {
|
||||
if (q->limits.chunk_sectors)
|
||||
chunk_sectors = q->limits.chunk_sectors;
|
||||
else
|
||||
return q->limits.max_sectors;
|
||||
}
|
||||
|
||||
if (likely(is_power_of_2(chunk_sectors)))
|
||||
chunk_sectors -= offset & (chunk_sectors - 1);
|
||||
else
|
||||
chunk_sectors -= sector_div(offset, chunk_sectors);
|
||||
|
||||
return min(q->limits.max_sectors, chunk_sectors);
|
||||
if (unlikely(!is_power_of_2(chunk_sectors)))
|
||||
return chunk_sectors - sector_div(offset, chunk_sectors);
|
||||
return chunk_sectors - (offset & (chunk_sectors - 1));
|
||||
}
|
||||
|
||||
/*
|
||||
* Access functions for manipulating queue properties
|
||||
*/
|
||||
extern void blk_cleanup_queue(struct request_queue *);
|
||||
void blk_queue_bounce_limit(struct request_queue *q, enum blk_bounce limit);
|
||||
extern void blk_queue_max_hw_sectors(struct request_queue *, unsigned int);
|
||||
extern void blk_queue_chunk_sectors(struct request_queue *, unsigned int);
|
||||
|
|
@ -1206,6 +1168,11 @@ bdev_max_zone_append_sectors(struct block_device *bdev)
|
|||
return queue_max_zone_append_sectors(bdev_get_queue(bdev));
|
||||
}
|
||||
|
||||
static inline unsigned int bdev_max_segments(struct block_device *bdev)
|
||||
{
|
||||
return queue_max_segments(bdev_get_queue(bdev));
|
||||
}
|
||||
|
||||
static inline unsigned queue_logical_block_size(const struct request_queue *q)
|
||||
{
|
||||
int retval = 512;
|
||||
|
|
@ -1337,27 +1304,9 @@ static inline sector_t bdev_zone_sectors(struct block_device *bdev)
|
|||
{
|
||||
struct request_queue *q = bdev_get_queue(bdev);
|
||||
|
||||
if (q)
|
||||
return blk_queue_zone_sectors(q);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline unsigned int bdev_max_open_zones(struct block_device *bdev)
|
||||
{
|
||||
struct request_queue *q = bdev_get_queue(bdev);
|
||||
|
||||
if (q)
|
||||
return queue_max_open_zones(q);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline unsigned int bdev_max_active_zones(struct block_device *bdev)
|
||||
{
|
||||
struct request_queue *q = bdev_get_queue(bdev);
|
||||
|
||||
if (q)
|
||||
return queue_max_active_zones(q);
|
||||
return 0;
|
||||
if (!blk_queue_is_zoned(q))
|
||||
return 0;
|
||||
return q->limits.chunk_sectors;
|
||||
}
|
||||
|
||||
static inline int queue_dma_alignment(const struct request_queue *q)
|
||||
|
|
@ -1365,6 +1314,18 @@ static inline int queue_dma_alignment(const struct request_queue *q)
|
|||
return q ? q->dma_alignment : 511;
|
||||
}
|
||||
|
||||
static inline unsigned int bdev_dma_alignment(struct block_device *bdev)
|
||||
{
|
||||
return queue_dma_alignment(bdev_get_queue(bdev));
|
||||
}
|
||||
|
||||
static inline bool bdev_iter_is_aligned(struct block_device *bdev,
|
||||
struct iov_iter *iter)
|
||||
{
|
||||
return iov_iter_is_aligned(iter, bdev_dma_alignment(bdev),
|
||||
bdev_logical_block_size(bdev) - 1);
|
||||
}
|
||||
|
||||
static inline int blk_rq_aligned(struct request_queue *q, unsigned long addr,
|
||||
unsigned int len)
|
||||
{
|
||||
|
|
@ -1426,7 +1387,7 @@ struct block_device_operations {
|
|||
unsigned int flags);
|
||||
int (*open) (struct block_device *, fmode_t);
|
||||
void (*release) (struct gendisk *, fmode_t);
|
||||
int (*rw_page)(struct block_device *, sector_t, struct page *, unsigned int);
|
||||
int (*rw_page)(struct block_device *, sector_t, struct page *, enum req_op);
|
||||
int (*ioctl) (struct block_device *, fmode_t, unsigned, unsigned long);
|
||||
int (*compat_ioctl) (struct block_device *, fmode_t, unsigned, unsigned long);
|
||||
unsigned int (*check_events) (struct gendisk *disk,
|
||||
|
|
@ -1479,9 +1440,9 @@ static inline void blk_wake_io_task(struct task_struct *waiter)
|
|||
}
|
||||
|
||||
unsigned long bdev_start_io_acct(struct block_device *bdev,
|
||||
unsigned int sectors, unsigned int op,
|
||||
unsigned int sectors, enum req_op op,
|
||||
unsigned long start_time);
|
||||
void bdev_end_io_acct(struct block_device *bdev, unsigned int op,
|
||||
void bdev_end_io_acct(struct block_device *bdev, enum req_op op,
|
||||
unsigned long start_time);
|
||||
|
||||
void bio_start_io_acct_time(struct bio *bio, unsigned long start_time);
|
||||
|
|
@ -1502,7 +1463,6 @@ static inline void bio_end_io_acct(struct bio *bio, unsigned long start_time)
|
|||
int bdev_read_only(struct block_device *bdev);
|
||||
int set_blocksize(struct block_device *bdev, int size);
|
||||
|
||||
const char *bdevname(struct block_device *bdev, char *buffer);
|
||||
int lookup_bdev(const char *pathname, dev_t *dev);
|
||||
|
||||
void blkdev_show(struct seq_file *seqf, off_t offset);
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
#include <linux/compat.h>
|
||||
#include <uapi/linux/blktrace_api.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/blk_types.h>
|
||||
|
||||
#if defined(CONFIG_BLK_DEV_IO_TRACE)
|
||||
|
||||
|
|
@ -77,10 +78,6 @@ extern int blk_trace_setup(struct request_queue *q, char *name, dev_t dev,
|
|||
char __user *arg);
|
||||
extern int blk_trace_startstop(struct request_queue *q, int start);
|
||||
extern int blk_trace_remove(struct request_queue *q);
|
||||
extern void blk_trace_remove_sysfs(struct device *dev);
|
||||
extern int blk_trace_init_sysfs(struct device *dev);
|
||||
|
||||
extern struct attribute_group blk_trace_attr_group;
|
||||
|
||||
#else /* !CONFIG_BLK_DEV_IO_TRACE */
|
||||
# define blk_trace_ioctl(bdev, cmd, arg) (-ENOTTY)
|
||||
|
|
@ -91,13 +88,7 @@ extern struct attribute_group blk_trace_attr_group;
|
|||
# define blk_trace_remove(q) (-ENOTTY)
|
||||
# define blk_add_trace_msg(q, fmt, ...) do { } while (0)
|
||||
# define blk_add_cgroup_trace_msg(q, cg, fmt, ...) do { } while (0)
|
||||
# define blk_trace_remove_sysfs(dev) do { } while (0)
|
||||
# define blk_trace_note_message_enabled(q) (false)
|
||||
static inline int blk_trace_init_sysfs(struct device *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_BLK_DEV_IO_TRACE */
|
||||
|
||||
#ifdef CONFIG_COMPAT
|
||||
|
|
@ -115,7 +106,7 @@ struct compat_blk_user_trace_setup {
|
|||
|
||||
#endif
|
||||
|
||||
void blk_fill_rwbs(char *rwbs, unsigned int op);
|
||||
void blk_fill_rwbs(char *rwbs, blk_opf_t opf);
|
||||
|
||||
static inline sector_t blk_rq_trace_sector(struct request *rq)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -10,6 +10,13 @@
|
|||
|
||||
struct bpf_prog_array;
|
||||
|
||||
#ifdef CONFIG_BPF_LSM
|
||||
/* Maximum number of concurrently attachable per-cgroup LSM hooks. */
|
||||
#define CGROUP_LSM_NUM 10
|
||||
#else
|
||||
#define CGROUP_LSM_NUM 0
|
||||
#endif
|
||||
|
||||
enum cgroup_bpf_attach_type {
|
||||
CGROUP_BPF_ATTACH_TYPE_INVALID = -1,
|
||||
CGROUP_INET_INGRESS = 0,
|
||||
|
|
@ -35,6 +42,8 @@ enum cgroup_bpf_attach_type {
|
|||
CGROUP_INET4_GETSOCKNAME,
|
||||
CGROUP_INET6_GETSOCKNAME,
|
||||
CGROUP_INET_SOCK_RELEASE,
|
||||
CGROUP_LSM_START,
|
||||
CGROUP_LSM_END = CGROUP_LSM_START + CGROUP_LSM_NUM - 1,
|
||||
MAX_CGROUP_BPF_ATTACH_TYPE
|
||||
};
|
||||
|
||||
|
|
@ -47,8 +56,8 @@ struct cgroup_bpf {
|
|||
* have either zero or one element
|
||||
* when BPF_F_ALLOW_MULTI the list can have up to BPF_CGROUP_MAX_PROGS
|
||||
*/
|
||||
struct list_head progs[MAX_CGROUP_BPF_ATTACH_TYPE];
|
||||
u32 flags[MAX_CGROUP_BPF_ATTACH_TYPE];
|
||||
struct hlist_head progs[MAX_CGROUP_BPF_ATTACH_TYPE];
|
||||
u8 flags[MAX_CGROUP_BPF_ATTACH_TYPE];
|
||||
|
||||
/* list of cgroup shared storages */
|
||||
struct list_head storages;
|
||||
|
|
|
|||
|
|
@ -23,6 +23,13 @@ struct ctl_table;
|
|||
struct ctl_table_header;
|
||||
struct task_struct;
|
||||
|
||||
unsigned int __cgroup_bpf_run_lsm_sock(const void *ctx,
|
||||
const struct bpf_insn *insn);
|
||||
unsigned int __cgroup_bpf_run_lsm_socket(const void *ctx,
|
||||
const struct bpf_insn *insn);
|
||||
unsigned int __cgroup_bpf_run_lsm_current(const void *ctx,
|
||||
const struct bpf_insn *insn);
|
||||
|
||||
#ifdef CONFIG_CGROUP_BPF
|
||||
|
||||
#define CGROUP_ATYPE(type) \
|
||||
|
|
@ -95,7 +102,7 @@ struct bpf_cgroup_link {
|
|||
};
|
||||
|
||||
struct bpf_prog_list {
|
||||
struct list_head node;
|
||||
struct hlist_node node;
|
||||
struct bpf_prog *prog;
|
||||
struct bpf_cgroup_link *link;
|
||||
struct bpf_cgroup_storage *storage[MAX_BPF_CGROUP_STORAGE_TYPE];
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
#define _LINUX_BPF_H 1
|
||||
|
||||
#include <uapi/linux/bpf.h>
|
||||
#include <uapi/linux/filter.h>
|
||||
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/file.h>
|
||||
|
|
@ -22,8 +23,10 @@
|
|||
#include <linux/sched/mm.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/percpu-refcount.h>
|
||||
#include <linux/stddef.h>
|
||||
#include <linux/bpfptr.h>
|
||||
#include <linux/btf.h>
|
||||
#include <linux/rcupdate_trace.h>
|
||||
|
||||
struct bpf_verifier_env;
|
||||
struct bpf_verifier_log;
|
||||
|
|
@ -44,6 +47,7 @@ struct kobject;
|
|||
struct mem_cgroup;
|
||||
struct module;
|
||||
struct bpf_func_state;
|
||||
struct ftrace_ops;
|
||||
|
||||
extern struct idr btf_idr;
|
||||
extern spinlock_t btf_idr_lock;
|
||||
|
|
@ -53,6 +57,8 @@ typedef u64 (*bpf_callback_t)(u64, u64, u64, u64, u64);
|
|||
typedef int (*bpf_iter_init_seq_priv_t)(void *private_data,
|
||||
struct bpf_iter_aux_info *aux);
|
||||
typedef void (*bpf_iter_fini_seq_priv_t)(void *private_data);
|
||||
typedef unsigned int (*bpf_func_t)(const void *,
|
||||
const struct bpf_insn *);
|
||||
struct bpf_iter_seq_info {
|
||||
const struct seq_operations *seq_ops;
|
||||
bpf_iter_init_seq_priv_t init_seq_private;
|
||||
|
|
@ -216,7 +222,7 @@ struct bpf_map {
|
|||
u32 btf_vmlinux_value_type_id;
|
||||
struct btf *btf;
|
||||
#ifdef CONFIG_MEMCG_KMEM
|
||||
struct mem_cgroup *memcg;
|
||||
struct obj_cgroup *objcg;
|
||||
#endif
|
||||
char name[BPF_OBJ_NAME_LEN];
|
||||
struct bpf_map_off_arr *off_arr;
|
||||
|
|
@ -398,6 +404,9 @@ enum bpf_type_flag {
|
|||
/* DYNPTR points to a ringbuf record. */
|
||||
DYNPTR_TYPE_RINGBUF = BIT(9 + BPF_BASE_TYPE_BITS),
|
||||
|
||||
/* Size is known at compile time. */
|
||||
MEM_FIXED_SIZE = BIT(10 + BPF_BASE_TYPE_BITS),
|
||||
|
||||
__BPF_TYPE_FLAG_MAX,
|
||||
__BPF_TYPE_LAST_FLAG = __BPF_TYPE_FLAG_MAX - 1,
|
||||
};
|
||||
|
|
@ -461,6 +470,8 @@ enum bpf_arg_type {
|
|||
* all bytes or clear them in error case.
|
||||
*/
|
||||
ARG_PTR_TO_UNINIT_MEM = MEM_UNINIT | ARG_PTR_TO_MEM,
|
||||
/* Pointer to valid memory of size known at compile time. */
|
||||
ARG_PTR_TO_FIXED_SIZE_MEM = MEM_FIXED_SIZE | ARG_PTR_TO_MEM,
|
||||
|
||||
/* This must be the last entry. Its purpose is to ensure the enum is
|
||||
* wide enough to hold the higher bits reserved for bpf_type_flag.
|
||||
|
|
@ -526,6 +537,14 @@ struct bpf_func_proto {
|
|||
u32 *arg5_btf_id;
|
||||
};
|
||||
u32 *arg_btf_id[5];
|
||||
struct {
|
||||
size_t arg1_size;
|
||||
size_t arg2_size;
|
||||
size_t arg3_size;
|
||||
size_t arg4_size;
|
||||
size_t arg5_size;
|
||||
};
|
||||
size_t arg_size[5];
|
||||
};
|
||||
int *ret_btf_id; /* return value btf_id */
|
||||
bool (*allowed)(const struct bpf_prog *prog);
|
||||
|
|
@ -733,6 +752,16 @@ struct btf_func_model {
|
|||
/* Return the return value of fentry prog. Only used by bpf_struct_ops. */
|
||||
#define BPF_TRAMP_F_RET_FENTRY_RET BIT(4)
|
||||
|
||||
/* Get original function from stack instead of from provided direct address.
|
||||
* Makes sense for trampolines with fexit or fmod_ret programs.
|
||||
*/
|
||||
#define BPF_TRAMP_F_ORIG_STACK BIT(5)
|
||||
|
||||
/* This trampoline is on a function with another ftrace_ops with IPMODIFY,
|
||||
* e.g., a live patch. This flag is set and cleared by ftrace call backs,
|
||||
*/
|
||||
#define BPF_TRAMP_F_SHARE_IPMODIFY BIT(6)
|
||||
|
||||
/* Each call __bpf_prog_enter + call bpf_func + call __bpf_prog_exit is ~50
|
||||
* bytes on x86.
|
||||
*/
|
||||
|
|
@ -776,6 +805,10 @@ void notrace __bpf_prog_exit(struct bpf_prog *prog, u64 start, struct bpf_tramp_
|
|||
u64 notrace __bpf_prog_enter_sleepable(struct bpf_prog *prog, struct bpf_tramp_run_ctx *run_ctx);
|
||||
void notrace __bpf_prog_exit_sleepable(struct bpf_prog *prog, u64 start,
|
||||
struct bpf_tramp_run_ctx *run_ctx);
|
||||
u64 notrace __bpf_prog_enter_lsm_cgroup(struct bpf_prog *prog,
|
||||
struct bpf_tramp_run_ctx *run_ctx);
|
||||
void notrace __bpf_prog_exit_lsm_cgroup(struct bpf_prog *prog, u64 start,
|
||||
struct bpf_tramp_run_ctx *run_ctx);
|
||||
void notrace __bpf_tramp_enter(struct bpf_tramp_image *tr);
|
||||
void notrace __bpf_tramp_exit(struct bpf_tramp_image *tr);
|
||||
|
||||
|
|
@ -811,9 +844,11 @@ struct bpf_tramp_image {
|
|||
struct bpf_trampoline {
|
||||
/* hlist for trampoline_table */
|
||||
struct hlist_node hlist;
|
||||
struct ftrace_ops *fops;
|
||||
/* serializes access to fields of this trampoline */
|
||||
struct mutex mutex;
|
||||
refcount_t refcnt;
|
||||
u32 flags;
|
||||
u64 key;
|
||||
struct {
|
||||
struct btf_func_model model;
|
||||
|
|
@ -863,8 +898,7 @@ struct bpf_dispatcher {
|
|||
static __always_inline __nocfi unsigned int bpf_dispatcher_nop_func(
|
||||
const void *ctx,
|
||||
const struct bpf_insn *insnsi,
|
||||
unsigned int (*bpf_func)(const void *,
|
||||
const struct bpf_insn *))
|
||||
bpf_func_t bpf_func)
|
||||
{
|
||||
return bpf_func(ctx, insnsi);
|
||||
}
|
||||
|
|
@ -893,8 +927,7 @@ int arch_prepare_bpf_dispatcher(void *image, s64 *funcs, int num_funcs);
|
|||
noinline __nocfi unsigned int bpf_dispatcher_##name##_func( \
|
||||
const void *ctx, \
|
||||
const struct bpf_insn *insnsi, \
|
||||
unsigned int (*bpf_func)(const void *, \
|
||||
const struct bpf_insn *)) \
|
||||
bpf_func_t bpf_func) \
|
||||
{ \
|
||||
return bpf_func(ctx, insnsi); \
|
||||
} \
|
||||
|
|
@ -905,8 +938,7 @@ int arch_prepare_bpf_dispatcher(void *image, s64 *funcs, int num_funcs);
|
|||
unsigned int bpf_dispatcher_##name##_func( \
|
||||
const void *ctx, \
|
||||
const struct bpf_insn *insnsi, \
|
||||
unsigned int (*bpf_func)(const void *, \
|
||||
const struct bpf_insn *)); \
|
||||
bpf_func_t bpf_func); \
|
||||
extern struct bpf_dispatcher bpf_dispatcher_##name;
|
||||
#define BPF_DISPATCHER_FUNC(name) bpf_dispatcher_##name##_func
|
||||
#define BPF_DISPATCHER_PTR(name) (&bpf_dispatcher_##name)
|
||||
|
|
@ -1025,7 +1057,6 @@ struct bpf_prog_aux {
|
|||
bool sleepable;
|
||||
bool tail_call_reachable;
|
||||
bool xdp_has_frags;
|
||||
bool use_bpf_prog_pack;
|
||||
/* BTF_KIND_FUNC_PROTO for valid attach_btf_id */
|
||||
const struct btf_type *attach_func_proto;
|
||||
/* function name for valid attach_btf_id */
|
||||
|
|
@ -1045,6 +1076,7 @@ struct bpf_prog_aux {
|
|||
struct user_struct *user;
|
||||
u64 load_time; /* ns since boottime */
|
||||
u32 verified_insns;
|
||||
int cgroup_atype; /* enum cgroup_bpf_attach_type */
|
||||
struct bpf_map *cgroup_storage[MAX_BPF_CGROUP_STORAGE_TYPE];
|
||||
char name[BPF_OBJ_NAME_LEN];
|
||||
#ifdef CONFIG_SECURITY
|
||||
|
|
@ -1084,6 +1116,40 @@ struct bpf_prog_aux {
|
|||
};
|
||||
};
|
||||
|
||||
struct bpf_prog {
|
||||
u16 pages; /* Number of allocated pages */
|
||||
u16 jited:1, /* Is our filter JIT'ed? */
|
||||
jit_requested:1,/* archs need to JIT the prog */
|
||||
gpl_compatible:1, /* Is filter GPL compatible? */
|
||||
cb_access:1, /* Is control block accessed? */
|
||||
dst_needed:1, /* Do we need dst entry? */
|
||||
blinding_requested:1, /* needs constant blinding */
|
||||
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? */
|
||||
enforce_expected_attach_type:1, /* Enforce expected_attach_type checking at attach time */
|
||||
call_get_stack:1, /* Do we call bpf_get_stack() or bpf_get_stackid() */
|
||||
call_get_func_ip:1, /* Do we call get_func_ip() */
|
||||
tstamp_type_access:1; /* Accessed __sk_buff->tstamp_type */
|
||||
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 */
|
||||
u32 jited_len; /* Size of jited insns in bytes */
|
||||
u8 tag[BPF_TAG_SIZE];
|
||||
struct bpf_prog_stats __percpu *stats;
|
||||
int __percpu *active;
|
||||
unsigned int (*bpf_func)(const void *ctx,
|
||||
const struct bpf_insn *insn);
|
||||
struct bpf_prog_aux *aux; /* Auxiliary fields */
|
||||
struct sock_fprog_kern *orig_prog; /* Original BPF program */
|
||||
/* Instructions for interpreter */
|
||||
union {
|
||||
DECLARE_FLEX_ARRAY(struct sock_filter, insns);
|
||||
DECLARE_FLEX_ARRAY(struct bpf_insn, insnsi);
|
||||
};
|
||||
};
|
||||
|
||||
struct bpf_array_aux {
|
||||
/* Programs with direct jumps into programs part of this array. */
|
||||
struct list_head poke_progs;
|
||||
|
|
@ -1118,6 +1184,11 @@ struct bpf_tramp_link {
|
|||
u64 cookie;
|
||||
};
|
||||
|
||||
struct bpf_shim_tramp_link {
|
||||
struct bpf_tramp_link link;
|
||||
struct bpf_trampoline *trampoline;
|
||||
};
|
||||
|
||||
struct bpf_tracing_link {
|
||||
struct bpf_tramp_link link;
|
||||
enum bpf_attach_type attach_type;
|
||||
|
|
@ -1221,6 +1292,21 @@ static inline int bpf_struct_ops_map_sys_lookup_elem(struct bpf_map *map,
|
|||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_CGROUP_BPF) && defined(CONFIG_BPF_LSM)
|
||||
int bpf_trampoline_link_cgroup_shim(struct bpf_prog *prog,
|
||||
int cgroup_atype);
|
||||
void bpf_trampoline_unlink_cgroup_shim(struct bpf_prog *prog);
|
||||
#else
|
||||
static inline int bpf_trampoline_link_cgroup_shim(struct bpf_prog *prog,
|
||||
int cgroup_atype)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
static inline void bpf_trampoline_unlink_cgroup_shim(struct bpf_prog *prog)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
struct bpf_array {
|
||||
struct bpf_map map;
|
||||
u32 elem_size;
|
||||
|
|
@ -1236,6 +1322,9 @@ struct bpf_array {
|
|||
#define BPF_COMPLEXITY_LIMIT_INSNS 1000000 /* yes. 1M insns */
|
||||
#define MAX_TAIL_CALL_CNT 33
|
||||
|
||||
/* Maximum number of loops for bpf_loop */
|
||||
#define BPF_MAX_LOOPS BIT(23)
|
||||
|
||||
#define BPF_F_ACCESS_MASK (BPF_F_RDONLY | \
|
||||
BPF_F_RDONLY_PROG | \
|
||||
BPF_F_WRONLY | \
|
||||
|
|
@ -1336,6 +1425,8 @@ extern struct bpf_empty_prog_array bpf_empty_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 *progs);
|
||||
/* Use when traversal over the bpf_prog_array uses tasks_trace rcu */
|
||||
void bpf_prog_array_free_sleepable(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,
|
||||
|
|
@ -1427,6 +1518,55 @@ bpf_prog_run_array(const struct bpf_prog_array *array,
|
|||
return ret;
|
||||
}
|
||||
|
||||
/* Notes on RCU design for bpf_prog_arrays containing sleepable programs:
|
||||
*
|
||||
* We use the tasks_trace rcu flavor read section to protect the bpf_prog_array
|
||||
* overall. As a result, we must use the bpf_prog_array_free_sleepable
|
||||
* in order to use the tasks_trace rcu grace period.
|
||||
*
|
||||
* When a non-sleepable program is inside the array, we take the rcu read
|
||||
* section and disable preemption for that program alone, so it can access
|
||||
* rcu-protected dynamically sized maps.
|
||||
*/
|
||||
static __always_inline u32
|
||||
bpf_prog_run_array_sleepable(const struct bpf_prog_array __rcu *array_rcu,
|
||||
const void *ctx, bpf_prog_run_fn run_prog)
|
||||
{
|
||||
const struct bpf_prog_array_item *item;
|
||||
const struct bpf_prog *prog;
|
||||
const struct bpf_prog_array *array;
|
||||
struct bpf_run_ctx *old_run_ctx;
|
||||
struct bpf_trace_run_ctx run_ctx;
|
||||
u32 ret = 1;
|
||||
|
||||
might_fault();
|
||||
|
||||
rcu_read_lock_trace();
|
||||
migrate_disable();
|
||||
|
||||
array = rcu_dereference_check(array_rcu, rcu_read_lock_trace_held());
|
||||
if (unlikely(!array))
|
||||
goto out;
|
||||
old_run_ctx = bpf_set_run_ctx(&run_ctx.run_ctx);
|
||||
item = &array->items[0];
|
||||
while ((prog = READ_ONCE(item->prog))) {
|
||||
if (!prog->aux->sleepable)
|
||||
rcu_read_lock();
|
||||
|
||||
run_ctx.bpf_cookie = item->bpf_cookie;
|
||||
ret &= run_prog(prog, ctx);
|
||||
item++;
|
||||
|
||||
if (!prog->aux->sleepable)
|
||||
rcu_read_unlock();
|
||||
}
|
||||
bpf_reset_run_ctx(old_run_ctx);
|
||||
out:
|
||||
migrate_enable();
|
||||
rcu_read_unlock_trace();
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_BPF_SYSCALL
|
||||
DECLARE_PER_CPU(int, bpf_prog_active);
|
||||
extern struct mutex bpf_stats_enabled_mutex;
|
||||
|
|
@ -1797,7 +1937,8 @@ int btf_check_subprog_arg_match(struct bpf_verifier_env *env, int subprog,
|
|||
struct bpf_reg_state *regs);
|
||||
int btf_check_kfunc_arg_match(struct bpf_verifier_env *env,
|
||||
const struct btf *btf, u32 func_id,
|
||||
struct bpf_reg_state *regs);
|
||||
struct bpf_reg_state *regs,
|
||||
u32 kfunc_flags);
|
||||
int btf_prepare_func_args(struct bpf_verifier_env *env, int subprog,
|
||||
struct bpf_reg_state *reg);
|
||||
int btf_check_type_match(struct bpf_verifier_log *log, const struct bpf_prog *prog,
|
||||
|
|
@ -2104,6 +2245,7 @@ int sock_map_bpf_prog_query(const union bpf_attr *attr,
|
|||
union bpf_attr __user *uattr);
|
||||
|
||||
void sock_map_unhash(struct sock *sk);
|
||||
void sock_map_destroy(struct sock *sk);
|
||||
void sock_map_close(struct sock *sk, long timeout);
|
||||
#else
|
||||
static inline int bpf_prog_offload_init(struct bpf_prog *prog,
|
||||
|
|
@ -2261,12 +2403,13 @@ extern const struct bpf_func_proto bpf_for_each_map_elem_proto;
|
|||
extern const struct bpf_func_proto bpf_btf_find_by_name_kind_proto;
|
||||
extern const struct bpf_func_proto bpf_sk_setsockopt_proto;
|
||||
extern const struct bpf_func_proto bpf_sk_getsockopt_proto;
|
||||
extern const struct bpf_func_proto bpf_kallsyms_lookup_name_proto;
|
||||
extern const struct bpf_func_proto bpf_unlocked_sk_setsockopt_proto;
|
||||
extern const struct bpf_func_proto bpf_unlocked_sk_getsockopt_proto;
|
||||
extern const struct bpf_func_proto bpf_find_vma_proto;
|
||||
extern const struct bpf_func_proto bpf_loop_proto;
|
||||
extern const struct bpf_func_proto bpf_strncmp_proto;
|
||||
extern const struct bpf_func_proto bpf_copy_from_user_task_proto;
|
||||
extern const struct bpf_func_proto bpf_kptr_xchg_proto;
|
||||
extern const struct bpf_func_proto bpf_set_retval_proto;
|
||||
extern const struct bpf_func_proto bpf_get_retval_proto;
|
||||
|
||||
const struct bpf_func_proto *tracing_prog_func_proto(
|
||||
enum bpf_func_id func_id, const struct bpf_prog *prog);
|
||||
|
|
@ -2420,4 +2563,12 @@ void bpf_dynptr_init(struct bpf_dynptr_kern *ptr, void *data,
|
|||
void bpf_dynptr_set_null(struct bpf_dynptr_kern *ptr);
|
||||
int bpf_dynptr_check_size(u32 size);
|
||||
|
||||
#ifdef CONFIG_BPF_LSM
|
||||
void bpf_cgroup_atype_get(u32 attach_btf_id, int cgroup_atype);
|
||||
void bpf_cgroup_atype_put(int cgroup_atype);
|
||||
#else
|
||||
static inline void bpf_cgroup_atype_get(u32 attach_btf_id, int cgroup_atype) {}
|
||||
static inline void bpf_cgroup_atype_put(int cgroup_atype) {}
|
||||
#endif /* CONFIG_BPF_LSM */
|
||||
|
||||
#endif /* _LINUX_BPF_H */
|
||||
|
|
|
|||
|
|
@ -42,6 +42,8 @@ extern const struct bpf_func_proto bpf_inode_storage_get_proto;
|
|||
extern const struct bpf_func_proto bpf_inode_storage_delete_proto;
|
||||
void bpf_inode_storage_free(struct inode *inode);
|
||||
|
||||
void bpf_lsm_find_cgroup_shim(const struct bpf_prog *prog, bpf_func_t *bpf_func);
|
||||
|
||||
#else /* !CONFIG_BPF_LSM */
|
||||
|
||||
static inline bool bpf_lsm_is_sleepable_hook(u32 btf_id)
|
||||
|
|
@ -65,6 +67,11 @@ static inline void bpf_inode_storage_free(struct inode *inode)
|
|||
{
|
||||
}
|
||||
|
||||
static inline void bpf_lsm_find_cgroup_shim(const struct bpf_prog *prog,
|
||||
bpf_func_t *bpf_func)
|
||||
{
|
||||
}
|
||||
|
||||
#endif /* CONFIG_BPF_LSM */
|
||||
|
||||
#endif /* _LINUX_BPF_LSM_H */
|
||||
|
|
|
|||
|
|
@ -299,7 +299,7 @@ struct bpf_verifier_state {
|
|||
* 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
|
||||
* equivalency, 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().
|
||||
|
|
@ -344,6 +344,14 @@ struct bpf_verifier_state_list {
|
|||
int miss_cnt, hit_cnt;
|
||||
};
|
||||
|
||||
struct bpf_loop_inline_state {
|
||||
unsigned int initialized:1; /* set to true upon first entry */
|
||||
unsigned int fit_for_inline:1; /* true if callback function is the same
|
||||
* at each call and flags are always zero
|
||||
*/
|
||||
u32 callback_subprogno; /* valid when fit_for_inline is true */
|
||||
};
|
||||
|
||||
/* Possible states for alu_state member. */
|
||||
#define BPF_ALU_SANITIZE_SRC (1U << 0)
|
||||
#define BPF_ALU_SANITIZE_DST (1U << 1)
|
||||
|
|
@ -373,6 +381,10 @@ struct bpf_insn_aux_data {
|
|||
u32 mem_size; /* mem_size for non-struct typed var */
|
||||
};
|
||||
} btf_var;
|
||||
/* if instruction is a call to bpf_loop this field tracks
|
||||
* the state of the relevant registers to make decision about inlining
|
||||
*/
|
||||
struct bpf_loop_inline_state loop_inline_state;
|
||||
};
|
||||
u64 map_key_state; /* constant (32 bit) key tracking for maps */
|
||||
int ctx_field_size; /* the ctx field size for load insn, maybe 0 */
|
||||
|
|
|
|||
|
|
@ -49,7 +49,9 @@ static inline void bpfptr_add(bpfptr_t *bpfptr, size_t val)
|
|||
static inline int copy_from_bpfptr_offset(void *dst, bpfptr_t src,
|
||||
size_t offset, size_t size)
|
||||
{
|
||||
return copy_from_sockptr_offset(dst, (sockptr_t) src, offset, size);
|
||||
if (!bpfptr_is_kernel(src))
|
||||
return copy_from_user(dst, src.user + offset, size);
|
||||
return copy_from_kernel_nofault(dst, src.kernel + offset, size);
|
||||
}
|
||||
|
||||
static inline int copy_from_bpfptr(void *dst, bpfptr_t src, size_t size)
|
||||
|
|
@ -78,7 +80,9 @@ static inline void *kvmemdup_bpfptr(bpfptr_t src, size_t len)
|
|||
|
||||
static inline long strncpy_from_bpfptr(char *dst, bpfptr_t src, size_t count)
|
||||
{
|
||||
return strncpy_from_sockptr(dst, (sockptr_t) src, count);
|
||||
if (bpfptr_is_kernel(src))
|
||||
return strncpy_from_kernel_nofault(dst, src.kernel, count);
|
||||
return strncpy_from_user(dst, src.user, count);
|
||||
}
|
||||
|
||||
#endif /* _LINUX_BPFPTR_H */
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
#define PHY_ID_BCM5481 0x0143bca0
|
||||
#define PHY_ID_BCM5395 0x0143bcf0
|
||||
#define PHY_ID_BCM53125 0x03625f20
|
||||
#define PHY_ID_BCM53128 0x03625e10
|
||||
#define PHY_ID_BCM54810 0x03625d00
|
||||
#define PHY_ID_BCM54811 0x03625cc0
|
||||
#define PHY_ID_BCM5482 0x0143bcb0
|
||||
|
|
|
|||
|
|
@ -12,14 +12,43 @@
|
|||
#define BTF_TYPE_EMIT(type) ((void)(type *)0)
|
||||
#define BTF_TYPE_EMIT_ENUM(enum_val) ((void)enum_val)
|
||||
|
||||
enum btf_kfunc_type {
|
||||
BTF_KFUNC_TYPE_CHECK,
|
||||
BTF_KFUNC_TYPE_ACQUIRE,
|
||||
BTF_KFUNC_TYPE_RELEASE,
|
||||
BTF_KFUNC_TYPE_RET_NULL,
|
||||
BTF_KFUNC_TYPE_KPTR_ACQUIRE,
|
||||
BTF_KFUNC_TYPE_MAX,
|
||||
};
|
||||
/* These need to be macros, as the expressions are used in assembler input */
|
||||
#define KF_ACQUIRE (1 << 0) /* kfunc is an acquire function */
|
||||
#define KF_RELEASE (1 << 1) /* kfunc is a release function */
|
||||
#define KF_RET_NULL (1 << 2) /* kfunc returns a pointer that may be NULL */
|
||||
#define KF_KPTR_GET (1 << 3) /* kfunc returns reference to a kptr */
|
||||
/* Trusted arguments are those which are meant to be referenced arguments with
|
||||
* unchanged offset. It is used to enforce that pointers obtained from acquire
|
||||
* kfuncs remain unmodified when being passed to helpers taking trusted args.
|
||||
*
|
||||
* Consider
|
||||
* struct foo {
|
||||
* int data;
|
||||
* struct foo *next;
|
||||
* };
|
||||
*
|
||||
* struct bar {
|
||||
* int data;
|
||||
* struct foo f;
|
||||
* };
|
||||
*
|
||||
* struct foo *f = alloc_foo(); // Acquire kfunc
|
||||
* struct bar *b = alloc_bar(); // Acquire kfunc
|
||||
*
|
||||
* If a kfunc set_foo_data() wants to operate only on the allocated object, it
|
||||
* will set the KF_TRUSTED_ARGS flag, which will prevent unsafe usage like:
|
||||
*
|
||||
* set_foo_data(f, 42); // Allowed
|
||||
* set_foo_data(f->next, 42); // Rejected, non-referenced pointer
|
||||
* set_foo_data(&f->next, 42);// Rejected, referenced, but wrong type
|
||||
* set_foo_data(&b->f, 42); // Rejected, referenced, but bad offset
|
||||
*
|
||||
* In the final case, usually for the purposes of type matching, it is deduced
|
||||
* by looking at the type of the member at the offset, but due to the
|
||||
* requirement of trusted argument, this deduction will be strict and not done
|
||||
* for this case.
|
||||
*/
|
||||
#define KF_TRUSTED_ARGS (1 << 4) /* kfunc only takes trusted pointer arguments */
|
||||
|
||||
struct btf;
|
||||
struct btf_member;
|
||||
|
|
@ -30,16 +59,7 @@ struct btf_id_set;
|
|||
|
||||
struct btf_kfunc_id_set {
|
||||
struct module *owner;
|
||||
union {
|
||||
struct {
|
||||
struct btf_id_set *check_set;
|
||||
struct btf_id_set *acquire_set;
|
||||
struct btf_id_set *release_set;
|
||||
struct btf_id_set *ret_null_set;
|
||||
struct btf_id_set *kptr_acquire_set;
|
||||
};
|
||||
struct btf_id_set *sets[BTF_KFUNC_TYPE_MAX];
|
||||
};
|
||||
struct btf_id_set8 *set;
|
||||
};
|
||||
|
||||
struct btf_id_dtor_kfunc {
|
||||
|
|
@ -177,6 +197,19 @@ static inline bool btf_type_is_enum(const struct btf_type *t)
|
|||
return BTF_INFO_KIND(t->info) == BTF_KIND_ENUM;
|
||||
}
|
||||
|
||||
static inline bool btf_is_any_enum(const struct btf_type *t)
|
||||
{
|
||||
return BTF_INFO_KIND(t->info) == BTF_KIND_ENUM ||
|
||||
BTF_INFO_KIND(t->info) == BTF_KIND_ENUM64;
|
||||
}
|
||||
|
||||
static inline bool btf_kind_core_compat(const struct btf_type *t1,
|
||||
const struct btf_type *t2)
|
||||
{
|
||||
return BTF_INFO_KIND(t1->info) == BTF_INFO_KIND(t2->info) ||
|
||||
(btf_is_any_enum(t1) && btf_is_any_enum(t2));
|
||||
}
|
||||
|
||||
static inline bool str_is_empty(const char *s)
|
||||
{
|
||||
return !s || !s[0];
|
||||
|
|
@ -192,6 +225,16 @@ static inline bool btf_is_enum(const struct btf_type *t)
|
|||
return btf_kind(t) == BTF_KIND_ENUM;
|
||||
}
|
||||
|
||||
static inline bool btf_is_enum64(const struct btf_type *t)
|
||||
{
|
||||
return btf_kind(t) == BTF_KIND_ENUM64;
|
||||
}
|
||||
|
||||
static inline u64 btf_enum64_value(const struct btf_enum64 *e)
|
||||
{
|
||||
return ((u64)e->val_hi32 << 32) | e->val_lo32;
|
||||
}
|
||||
|
||||
static inline bool btf_is_composite(const struct btf_type *t)
|
||||
{
|
||||
u16 kind = btf_kind(t);
|
||||
|
|
@ -332,6 +375,11 @@ static inline struct btf_enum *btf_enum(const struct btf_type *t)
|
|||
return (struct btf_enum *)(t + 1);
|
||||
}
|
||||
|
||||
static inline struct btf_enum64 *btf_enum64(const struct btf_type *t)
|
||||
{
|
||||
return (struct btf_enum64 *)(t + 1);
|
||||
}
|
||||
|
||||
static inline const struct btf_var_secinfo *btf_type_var_secinfo(
|
||||
const struct btf_type *t)
|
||||
{
|
||||
|
|
@ -350,9 +398,9 @@ const struct btf_type *btf_type_by_id(const struct btf *btf, u32 type_id);
|
|||
const char *btf_name_by_offset(const struct btf *btf, u32 offset);
|
||||
struct btf *btf_parse_vmlinux(void);
|
||||
struct btf *bpf_prog_get_target_btf(const struct bpf_prog *prog);
|
||||
bool btf_kfunc_id_set_contains(const struct btf *btf,
|
||||
u32 *btf_kfunc_id_set_contains(const struct btf *btf,
|
||||
enum bpf_prog_type prog_type,
|
||||
enum btf_kfunc_type type, u32 kfunc_btf_id);
|
||||
u32 kfunc_btf_id);
|
||||
int register_btf_kfunc_id_set(enum bpf_prog_type prog_type,
|
||||
const struct btf_kfunc_id_set *s);
|
||||
s32 btf_find_dtor_kfunc(struct btf *btf, u32 btf_id);
|
||||
|
|
@ -369,12 +417,11 @@ static inline const char *btf_name_by_offset(const struct btf *btf,
|
|||
{
|
||||
return NULL;
|
||||
}
|
||||
static inline bool btf_kfunc_id_set_contains(const struct btf *btf,
|
||||
static inline u32 *btf_kfunc_id_set_contains(const struct btf *btf,
|
||||
enum bpf_prog_type prog_type,
|
||||
enum btf_kfunc_type type,
|
||||
u32 kfunc_btf_id)
|
||||
{
|
||||
return false;
|
||||
return NULL;
|
||||
}
|
||||
static inline int register_btf_kfunc_id_set(enum bpf_prog_type prog_type,
|
||||
const struct btf_kfunc_id_set *s)
|
||||
|
|
|
|||
|
|
@ -8,6 +8,15 @@ struct btf_id_set {
|
|||
u32 ids[];
|
||||
};
|
||||
|
||||
struct btf_id_set8 {
|
||||
u32 cnt;
|
||||
u32 flags;
|
||||
struct {
|
||||
u32 id;
|
||||
u32 flags;
|
||||
} pairs[];
|
||||
};
|
||||
|
||||
#ifdef CONFIG_DEBUG_INFO_BTF
|
||||
|
||||
#include <linux/compiler.h> /* for __PASTE */
|
||||
|
|
@ -25,7 +34,7 @@ struct btf_id_set {
|
|||
|
||||
#define BTF_IDS_SECTION ".BTF_ids"
|
||||
|
||||
#define ____BTF_ID(symbol) \
|
||||
#define ____BTF_ID(symbol, word) \
|
||||
asm( \
|
||||
".pushsection " BTF_IDS_SECTION ",\"a\"; \n" \
|
||||
".local " #symbol " ; \n" \
|
||||
|
|
@ -33,10 +42,11 @@ asm( \
|
|||
".size " #symbol ", 4; \n" \
|
||||
#symbol ": \n" \
|
||||
".zero 4 \n" \
|
||||
word \
|
||||
".popsection; \n");
|
||||
|
||||
#define __BTF_ID(symbol) \
|
||||
____BTF_ID(symbol)
|
||||
#define __BTF_ID(symbol, word) \
|
||||
____BTF_ID(symbol, word)
|
||||
|
||||
#define __ID(prefix) \
|
||||
__PASTE(prefix, __COUNTER__)
|
||||
|
|
@ -46,7 +56,14 @@ asm( \
|
|||
* to 4 zero bytes.
|
||||
*/
|
||||
#define BTF_ID(prefix, name) \
|
||||
__BTF_ID(__ID(__BTF_ID__##prefix##__##name##__))
|
||||
__BTF_ID(__ID(__BTF_ID__##prefix##__##name##__), "")
|
||||
|
||||
#define ____BTF_ID_FLAGS(prefix, name, flags) \
|
||||
__BTF_ID(__ID(__BTF_ID__##prefix##__##name##__), ".long " #flags "\n")
|
||||
#define __BTF_ID_FLAGS(prefix, name, flags, ...) \
|
||||
____BTF_ID_FLAGS(prefix, name, flags)
|
||||
#define BTF_ID_FLAGS(prefix, name, ...) \
|
||||
__BTF_ID_FLAGS(prefix, name, ##__VA_ARGS__, 0)
|
||||
|
||||
/*
|
||||
* The BTF_ID_LIST macro defines pure (unsorted) list
|
||||
|
|
@ -145,10 +162,51 @@ asm( \
|
|||
".popsection; \n"); \
|
||||
extern struct btf_id_set name;
|
||||
|
||||
/*
|
||||
* The BTF_SET8_START/END macros pair defines sorted list of
|
||||
* BTF IDs and their flags plus its members count, with the
|
||||
* following layout:
|
||||
*
|
||||
* BTF_SET8_START(list)
|
||||
* BTF_ID_FLAGS(type1, name1, flags)
|
||||
* BTF_ID_FLAGS(type2, name2, flags)
|
||||
* BTF_SET8_END(list)
|
||||
*
|
||||
* __BTF_ID__set8__list:
|
||||
* .zero 8
|
||||
* list:
|
||||
* __BTF_ID__type1__name1__3:
|
||||
* .zero 4
|
||||
* .word (1 << 0) | (1 << 2)
|
||||
* __BTF_ID__type2__name2__5:
|
||||
* .zero 4
|
||||
* .word (1 << 3) | (1 << 1) | (1 << 2)
|
||||
*
|
||||
*/
|
||||
#define __BTF_SET8_START(name, scope) \
|
||||
asm( \
|
||||
".pushsection " BTF_IDS_SECTION ",\"a\"; \n" \
|
||||
"." #scope " __BTF_ID__set8__" #name "; \n" \
|
||||
"__BTF_ID__set8__" #name ":; \n" \
|
||||
".zero 8 \n" \
|
||||
".popsection; \n");
|
||||
|
||||
#define BTF_SET8_START(name) \
|
||||
__BTF_ID_LIST(name, local) \
|
||||
__BTF_SET8_START(name, local)
|
||||
|
||||
#define BTF_SET8_END(name) \
|
||||
asm( \
|
||||
".pushsection " BTF_IDS_SECTION ",\"a\"; \n" \
|
||||
".size __BTF_ID__set8__" #name ", .-" #name " \n" \
|
||||
".popsection; \n"); \
|
||||
extern struct btf_id_set8 name;
|
||||
|
||||
#else
|
||||
|
||||
#define BTF_ID_LIST(name) static u32 __maybe_unused name[5];
|
||||
#define BTF_ID(prefix, name)
|
||||
#define BTF_ID_FLAGS(prefix, name, ...)
|
||||
#define BTF_ID_UNUSED
|
||||
#define BTF_ID_LIST_GLOBAL(name, n) u32 __maybe_unused name[n];
|
||||
#define BTF_ID_LIST_SINGLE(name, prefix, typename) static u32 __maybe_unused name[1];
|
||||
|
|
@ -156,6 +214,8 @@ extern struct btf_id_set name;
|
|||
#define BTF_SET_START(name) static struct btf_id_set __maybe_unused name = { 0 };
|
||||
#define BTF_SET_START_GLOBAL(name) static struct btf_id_set __maybe_unused name = { 0 };
|
||||
#define BTF_SET_END(name)
|
||||
#define BTF_SET8_START(name) static struct btf_id_set8 __maybe_unused name = { 0 };
|
||||
#define BTF_SET8_END(name)
|
||||
|
||||
#endif /* CONFIG_DEBUG_INFO_BTF */
|
||||
|
||||
|
|
@ -179,7 +239,8 @@ extern struct btf_id_set name;
|
|||
BTF_SOCK_TYPE(BTF_SOCK_TYPE_UDP, udp_sock) \
|
||||
BTF_SOCK_TYPE(BTF_SOCK_TYPE_UDP6, udp6_sock) \
|
||||
BTF_SOCK_TYPE(BTF_SOCK_TYPE_UNIX, unix_sock) \
|
||||
BTF_SOCK_TYPE(BTF_SOCK_TYPE_MPTCP, mptcp_sock)
|
||||
BTF_SOCK_TYPE(BTF_SOCK_TYPE_MPTCP, mptcp_sock) \
|
||||
BTF_SOCK_TYPE(BTF_SOCK_TYPE_SOCKET, socket)
|
||||
|
||||
enum {
|
||||
#define BTF_SOCK_TYPE(name, str) name,
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
#define _LINUX_BUFFER_HEAD_H
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/blk_types.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/linkage.h>
|
||||
#include <linux/pagemap.h>
|
||||
|
|
@ -117,7 +118,6 @@ static __always_inline int test_clear_buffer_##name(struct buffer_head *bh) \
|
|||
* of the form "mark_buffer_foo()". These are higher-level functions which
|
||||
* do something in addition to setting a b_state bit.
|
||||
*/
|
||||
BUFFER_FNS(Uptodate, uptodate)
|
||||
BUFFER_FNS(Dirty, dirty)
|
||||
TAS_BUFFER_FNS(Dirty, dirty)
|
||||
BUFFER_FNS(Lock, locked)
|
||||
|
|
@ -135,6 +135,41 @@ BUFFER_FNS(Meta, meta)
|
|||
BUFFER_FNS(Prio, prio)
|
||||
BUFFER_FNS(Defer_Completion, defer_completion)
|
||||
|
||||
static __always_inline void set_buffer_uptodate(struct buffer_head *bh)
|
||||
{
|
||||
/*
|
||||
* If somebody else already set this uptodate, they will
|
||||
* have done the memory barrier, and a reader will thus
|
||||
* see *some* valid buffer state.
|
||||
*
|
||||
* Any other serialization (with IO errors or whatever that
|
||||
* might clear the bit) has to come from other state (eg BH_Lock).
|
||||
*/
|
||||
if (test_bit(BH_Uptodate, &bh->b_state))
|
||||
return;
|
||||
|
||||
/*
|
||||
* make it consistent with folio_mark_uptodate
|
||||
* pairs with smp_load_acquire in buffer_uptodate
|
||||
*/
|
||||
smp_mb__before_atomic();
|
||||
set_bit(BH_Uptodate, &bh->b_state);
|
||||
}
|
||||
|
||||
static __always_inline void clear_buffer_uptodate(struct buffer_head *bh)
|
||||
{
|
||||
clear_bit(BH_Uptodate, &bh->b_state);
|
||||
}
|
||||
|
||||
static __always_inline int buffer_uptodate(const struct buffer_head *bh)
|
||||
{
|
||||
/*
|
||||
* make it consistent with folio_test_uptodate
|
||||
* pairs with smp_mb__before_atomic in set_buffer_uptodate
|
||||
*/
|
||||
return test_bit_acquire(BH_Uptodate, &bh->b_state);
|
||||
}
|
||||
|
||||
#define bh_offset(bh) ((unsigned long)(bh)->b_data & ~PAGE_MASK)
|
||||
|
||||
/* If we *know* page->private refers to buffer_heads */
|
||||
|
|
@ -201,11 +236,11 @@ struct buffer_head *alloc_buffer_head(gfp_t gfp_flags);
|
|||
void free_buffer_head(struct buffer_head * bh);
|
||||
void unlock_buffer(struct buffer_head *bh);
|
||||
void __lock_buffer(struct buffer_head *bh);
|
||||
void ll_rw_block(int, int, int, struct buffer_head * bh[]);
|
||||
void ll_rw_block(blk_opf_t, int, struct buffer_head * bh[]);
|
||||
int sync_dirty_buffer(struct buffer_head *bh);
|
||||
int __sync_dirty_buffer(struct buffer_head *bh, int op_flags);
|
||||
void write_dirty_buffer(struct buffer_head *bh, int op_flags);
|
||||
int submit_bh(int, int, struct buffer_head *);
|
||||
int __sync_dirty_buffer(struct buffer_head *bh, blk_opf_t op_flags);
|
||||
void write_dirty_buffer(struct buffer_head *bh, blk_opf_t op_flags);
|
||||
int submit_bh(blk_opf_t, struct buffer_head *);
|
||||
void write_boundary_block(struct block_device *bdev,
|
||||
sector_t bblock, unsigned blocksize);
|
||||
int bh_uptodate_or_lock(struct buffer_head *bh);
|
||||
|
|
@ -258,14 +293,16 @@ static inline vm_fault_t block_page_mkwrite_return(int err)
|
|||
}
|
||||
sector_t generic_block_bmap(struct address_space *, sector_t, get_block_t *);
|
||||
int block_truncate_page(struct address_space *, loff_t, get_block_t *);
|
||||
int nobh_write_begin(struct address_space *, loff_t, unsigned len,
|
||||
struct page **, void **, get_block_t*);
|
||||
int nobh_write_end(struct file *, struct address_space *,
|
||||
loff_t, unsigned, unsigned,
|
||||
struct page *, void *);
|
||||
int nobh_truncate_page(struct address_space *, loff_t, get_block_t *);
|
||||
int nobh_writepage(struct page *page, get_block_t *get_block,
|
||||
struct writeback_control *wbc);
|
||||
|
||||
#ifdef CONFIG_MIGRATION
|
||||
extern int buffer_migrate_folio(struct address_space *,
|
||||
struct folio *dst, struct folio *src, enum migrate_mode);
|
||||
extern int buffer_migrate_folio_norefs(struct address_space *,
|
||||
struct folio *dst, struct folio *src, enum migrate_mode);
|
||||
#else
|
||||
#define buffer_migrate_folio NULL
|
||||
#define buffer_migrate_folio_norefs NULL
|
||||
#endif
|
||||
|
||||
void buffer_init(void);
|
||||
|
||||
|
|
|
|||
|
|
@ -82,6 +82,9 @@ struct cpu_cacheinfo *get_cpu_cacheinfo(unsigned int cpu);
|
|||
int init_cache_level(unsigned int cpu);
|
||||
int populate_cache_leaves(unsigned int cpu);
|
||||
int cache_setup_acpi(unsigned int cpu);
|
||||
bool last_level_cache_is_valid(unsigned int cpu);
|
||||
bool last_level_cache_is_shared(unsigned int cpu_x, unsigned int cpu_y);
|
||||
int detect_cache_attributes(unsigned int cpu);
|
||||
#ifndef CONFIG_ACPI_PPTT
|
||||
/*
|
||||
* acpi_find_last_cache_level is only called on ACPI enabled
|
||||
|
|
|
|||
|
|
@ -11,6 +11,8 @@
|
|||
|
||||
#define CAN_SYNC_SEG 1
|
||||
|
||||
#define CAN_BITRATE_UNSET 0
|
||||
#define CAN_BITRATE_UNKNOWN (-1U)
|
||||
|
||||
#define CAN_CTRLMODE_TDC_MASK \
|
||||
(CAN_CTRLMODE_TDC_AUTO | CAN_CTRLMODE_TDC_MANUAL)
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
#include <linux/can/length.h>
|
||||
#include <linux/can/netlink.h>
|
||||
#include <linux/can/skb.h>
|
||||
#include <linux/ethtool.h>
|
||||
#include <linux/netdevice.h>
|
||||
|
||||
/*
|
||||
|
|
@ -162,6 +163,9 @@ struct can_priv *safe_candev_priv(struct net_device *dev);
|
|||
int open_candev(struct net_device *dev);
|
||||
void close_candev(struct net_device *dev);
|
||||
int can_change_mtu(struct net_device *dev, int new_mtu);
|
||||
int can_eth_ioctl_hwts(struct net_device *netdev, struct ifreq *ifr, int cmd);
|
||||
int can_ethtool_op_get_ts_info_hwts(struct net_device *dev,
|
||||
struct ethtool_ts_info *info);
|
||||
|
||||
int register_candev(struct net_device *dev);
|
||||
void unregister_candev(struct net_device *dev);
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ struct sk_buff *alloc_canfd_skb(struct net_device *dev,
|
|||
struct canfd_frame **cfd);
|
||||
struct sk_buff *alloc_can_err_skb(struct net_device *dev,
|
||||
struct can_frame **cf);
|
||||
bool can_dropped_invalid_skb(struct net_device *dev, struct sk_buff *skb);
|
||||
|
||||
/*
|
||||
* The struct can_skb_priv is used to transport additional information along
|
||||
|
|
@ -96,64 +97,6 @@ static inline struct sk_buff *can_create_echo_skb(struct sk_buff *skb)
|
|||
return nskb;
|
||||
}
|
||||
|
||||
/* Check for outgoing skbs that have not been created by the CAN subsystem */
|
||||
static inline bool can_skb_headroom_valid(struct net_device *dev,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
/* af_packet creates a headroom of HH_DATA_MOD bytes which is fine */
|
||||
if (WARN_ON_ONCE(skb_headroom(skb) < sizeof(struct can_skb_priv)))
|
||||
return false;
|
||||
|
||||
/* af_packet does not apply CAN skb specific settings */
|
||||
if (skb->ip_summed == CHECKSUM_NONE) {
|
||||
/* init headroom */
|
||||
can_skb_prv(skb)->ifindex = dev->ifindex;
|
||||
can_skb_prv(skb)->skbcnt = 0;
|
||||
|
||||
skb->ip_summed = CHECKSUM_UNNECESSARY;
|
||||
|
||||
/* perform proper loopback on capable devices */
|
||||
if (dev->flags & IFF_ECHO)
|
||||
skb->pkt_type = PACKET_LOOPBACK;
|
||||
else
|
||||
skb->pkt_type = PACKET_HOST;
|
||||
|
||||
skb_reset_mac_header(skb);
|
||||
skb_reset_network_header(skb);
|
||||
skb_reset_transport_header(skb);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Drop a given socketbuffer if it does not contain a valid CAN frame. */
|
||||
static inline bool can_dropped_invalid_skb(struct net_device *dev,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
const struct canfd_frame *cfd = (struct canfd_frame *)skb->data;
|
||||
|
||||
if (skb->protocol == htons(ETH_P_CAN)) {
|
||||
if (unlikely(skb->len != CAN_MTU ||
|
||||
cfd->len > CAN_MAX_DLEN))
|
||||
goto inval_skb;
|
||||
} else if (skb->protocol == htons(ETH_P_CANFD)) {
|
||||
if (unlikely(skb->len != CANFD_MTU ||
|
||||
cfd->len > CANFD_MAX_DLEN))
|
||||
goto inval_skb;
|
||||
} else
|
||||
goto inval_skb;
|
||||
|
||||
if (!can_skb_headroom_valid(dev, skb))
|
||||
goto inval_skb;
|
||||
|
||||
return false;
|
||||
|
||||
inval_skb:
|
||||
kfree_skb(skb);
|
||||
dev->stats.tx_dropped++;
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool can_is_canfd_skb(const struct sk_buff *skb)
|
||||
{
|
||||
/* the CAN specific type of skb is identified by its data length */
|
||||
|
|
|
|||
|
|
@ -433,9 +433,9 @@ union ceph_mds_request_args {
|
|||
__le32 stripe_unit; /* layout for newly created file */
|
||||
__le32 stripe_count; /* ... */
|
||||
__le32 object_size;
|
||||
__le32 file_replication;
|
||||
__le32 mask; /* CEPH_CAP_* */
|
||||
__le32 old_size;
|
||||
__le32 pool;
|
||||
__le32 mask; /* CEPH_CAP_* */
|
||||
__le64 old_size;
|
||||
} __attribute__ ((packed)) open;
|
||||
struct {
|
||||
__le32 flags;
|
||||
|
|
@ -768,7 +768,7 @@ struct ceph_mds_caps {
|
|||
__le32 xattr_len;
|
||||
__le64 xattr_version;
|
||||
|
||||
/* filelock */
|
||||
/* a union of non-export and export bodies. */
|
||||
__le64 size, max_size, truncate_size;
|
||||
__le32 truncate_seq;
|
||||
struct ceph_timespec mtime, atime, ctime;
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ struct ceph_mdsmap {
|
|||
u32 m_session_timeout; /* seconds */
|
||||
u32 m_session_autoclose; /* seconds */
|
||||
u64 m_max_file_size;
|
||||
u64 m_max_xattr_size; /* maximum size for xattrs blob */
|
||||
u32 m_max_mds; /* expected up:active mds number */
|
||||
u32 m_num_active_mds; /* actual up:active mds number */
|
||||
u32 possible_max_rank; /* possible max rank index */
|
||||
|
|
|
|||
|
|
@ -507,9 +507,8 @@ extern struct ceph_osd_request *ceph_osdc_new_request(struct ceph_osd_client *,
|
|||
extern void ceph_osdc_get_request(struct ceph_osd_request *req);
|
||||
extern void ceph_osdc_put_request(struct ceph_osd_request *req);
|
||||
|
||||
extern int ceph_osdc_start_request(struct ceph_osd_client *osdc,
|
||||
struct ceph_osd_request *req,
|
||||
bool nofail);
|
||||
void ceph_osdc_start_request(struct ceph_osd_client *osdc,
|
||||
struct ceph_osd_request *req);
|
||||
extern void ceph_osdc_cancel_request(struct ceph_osd_request *req);
|
||||
extern int ceph_osdc_wait_request(struct ceph_osd_client *osdc,
|
||||
struct ceph_osd_request *req);
|
||||
|
|
|
|||
|
|
@ -88,20 +88,33 @@ enum {
|
|||
*/
|
||||
CGRP_ROOT_NS_DELEGATE = (1 << 3),
|
||||
|
||||
/*
|
||||
* Reduce latencies on dynamic cgroup modifications such as task
|
||||
* migrations and controller on/offs by disabling percpu operation on
|
||||
* cgroup_threadgroup_rwsem. This makes hot path operations such as
|
||||
* forks and exits into the slow path and more expensive.
|
||||
*
|
||||
* The static usage pattern of creating a cgroup, enabling controllers,
|
||||
* and then seeding it with CLONE_INTO_CGROUP doesn't require write
|
||||
* locking cgroup_threadgroup_rwsem and thus doesn't benefit from
|
||||
* favordynmod.
|
||||
*/
|
||||
CGRP_ROOT_FAVOR_DYNMODS = (1 << 4),
|
||||
|
||||
/*
|
||||
* Enable cpuset controller in v1 cgroup to use v2 behavior.
|
||||
*/
|
||||
CGRP_ROOT_CPUSET_V2_MODE = (1 << 4),
|
||||
CGRP_ROOT_CPUSET_V2_MODE = (1 << 16),
|
||||
|
||||
/*
|
||||
* Enable legacy local memory.events.
|
||||
*/
|
||||
CGRP_ROOT_MEMORY_LOCAL_EVENTS = (1 << 5),
|
||||
CGRP_ROOT_MEMORY_LOCAL_EVENTS = (1 << 17),
|
||||
|
||||
/*
|
||||
* Enable recursive subtree protection
|
||||
*/
|
||||
CGRP_ROOT_MEMORY_RECURSIVE_PROT = (1 << 6),
|
||||
CGRP_ROOT_MEMORY_RECURSIVE_PROT = (1 << 18),
|
||||
};
|
||||
|
||||
/* cftype->flags */
|
||||
|
|
@ -480,7 +493,7 @@ struct cgroup {
|
|||
struct work_struct release_agent_work;
|
||||
|
||||
/* used to track pressure stalls */
|
||||
struct psi_group psi;
|
||||
struct psi_group *psi;
|
||||
|
||||
/* used to store eBPF programs */
|
||||
struct cgroup_bpf bpf;
|
||||
|
|
|
|||
|
|
@ -674,7 +674,7 @@ static inline void pr_cont_cgroup_path(struct cgroup *cgrp)
|
|||
|
||||
static inline struct psi_group *cgroup_psi(struct cgroup *cgrp)
|
||||
{
|
||||
return &cgrp->psi;
|
||||
return cgrp->psi;
|
||||
}
|
||||
|
||||
bool cgroup_psi_enabled(void);
|
||||
|
|
@ -734,11 +734,6 @@ static inline struct cgroup *cgroup_parent(struct cgroup *cgrp)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static inline struct psi_group *cgroup_psi(struct cgroup *cgrp)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline bool cgroup_psi_enabled(void)
|
||||
{
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -831,6 +831,25 @@ struct clk *clk_register_divider_table(struct device *dev, const char *name,
|
|||
__devm_clk_hw_register_divider((dev), NULL, (name), (parent_name), NULL, \
|
||||
NULL, (flags), (reg), (shift), (width), \
|
||||
(clk_divider_flags), NULL, (lock))
|
||||
/**
|
||||
* devm_clk_hw_register_divider_parent_hw - register a divider clock with the clock framework
|
||||
* @dev: device registering this clock
|
||||
* @name: name of this clock
|
||||
* @parent_hw: pointer to parent clk
|
||||
* @flags: framework-specific flags
|
||||
* @reg: register address to adjust divider
|
||||
* @shift: number of bits to shift the bitfield
|
||||
* @width: width of the bitfield
|
||||
* @clk_divider_flags: divider-specific flags for this clock
|
||||
* @lock: shared register lock for this clock
|
||||
*/
|
||||
#define devm_clk_hw_register_divider_parent_hw(dev, name, parent_hw, flags, \
|
||||
reg, shift, width, \
|
||||
clk_divider_flags, lock) \
|
||||
__devm_clk_hw_register_divider((dev), NULL, (name), NULL, \
|
||||
(parent_hw), NULL, (flags), (reg), \
|
||||
(shift), (width), (clk_divider_flags), \
|
||||
NULL, (lock))
|
||||
/**
|
||||
* devm_clk_hw_register_divider_table - register a table based divider clock
|
||||
* with the clock framework (devres variant)
|
||||
|
|
@ -961,6 +980,13 @@ struct clk *clk_register_mux_table(struct device *dev, const char *name,
|
|||
(parent_names), NULL, NULL, (flags), (reg), \
|
||||
(shift), BIT((width)) - 1, (clk_mux_flags), \
|
||||
NULL, (lock))
|
||||
#define devm_clk_hw_register_mux_parent_hws(dev, name, parent_hws, \
|
||||
num_parents, flags, reg, shift, \
|
||||
width, clk_mux_flags, lock) \
|
||||
__devm_clk_hw_register_mux((dev), NULL, (name), (num_parents), NULL, \
|
||||
(parent_hws), NULL, (flags), (reg), \
|
||||
(shift), BIT((width)) - 1, \
|
||||
(clk_mux_flags), NULL, (lock))
|
||||
|
||||
int clk_mux_val_to_index(struct clk_hw *hw, const u32 *table, unsigned int flags,
|
||||
unsigned int val);
|
||||
|
|
@ -1006,6 +1032,14 @@ struct clk_hw *devm_clk_hw_register_fixed_factor(struct device *dev,
|
|||
struct clk_hw *devm_clk_hw_register_fixed_factor_index(struct device *dev,
|
||||
const char *name, unsigned int index, unsigned long flags,
|
||||
unsigned int mult, unsigned int div);
|
||||
|
||||
struct clk_hw *devm_clk_hw_register_fixed_factor_parent_hw(struct device *dev,
|
||||
const char *name, const struct clk_hw *parent_hw,
|
||||
unsigned long flags, unsigned int mult, unsigned int div);
|
||||
|
||||
struct clk_hw *clk_hw_register_fixed_factor_parent_hw(struct device *dev,
|
||||
const char *name, const struct clk_hw *parent_hw,
|
||||
unsigned long flags, unsigned int mult, unsigned int div);
|
||||
/**
|
||||
* struct clk_fractional_divider - adjustable fractional divider clock
|
||||
*
|
||||
|
|
@ -1176,10 +1210,8 @@ int __must_check devm_clk_hw_register(struct device *dev, struct clk_hw *hw);
|
|||
int __must_check of_clk_hw_register(struct device_node *node, struct clk_hw *hw);
|
||||
|
||||
void clk_unregister(struct clk *clk);
|
||||
void devm_clk_unregister(struct device *dev, struct clk *clk);
|
||||
|
||||
void clk_hw_unregister(struct clk_hw *hw);
|
||||
void devm_clk_hw_unregister(struct device *dev, struct clk_hw *hw);
|
||||
|
||||
/* helper functions */
|
||||
const char *__clk_get_name(const struct clk *clk);
|
||||
|
|
|
|||
|
|
@ -443,32 +443,130 @@ int __must_check devm_clk_bulk_get_all(struct device *dev,
|
|||
* @dev: device for clock "consumer"
|
||||
* @id: clock consumer ID
|
||||
*
|
||||
* Returns a struct clk corresponding to the clock producer, or
|
||||
* Context: May sleep.
|
||||
*
|
||||
* Return: a struct clk corresponding to the clock producer, or
|
||||
* valid IS_ERR() condition containing errno. The implementation
|
||||
* uses @dev and @id to determine the clock consumer, and thereby
|
||||
* the clock producer. (IOW, @id may be identical strings, but
|
||||
* clk_get may return different clock producers depending on @dev.)
|
||||
*
|
||||
* Drivers must assume that the clock source is not enabled.
|
||||
*
|
||||
* devm_clk_get should not be called from within interrupt context.
|
||||
* Drivers must assume that the clock source is neither prepared nor
|
||||
* enabled.
|
||||
*
|
||||
* The clock will automatically be freed when the device is unbound
|
||||
* from the bus.
|
||||
*/
|
||||
struct clk *devm_clk_get(struct device *dev, const char *id);
|
||||
|
||||
/**
|
||||
* devm_clk_get_prepared - devm_clk_get() + clk_prepare()
|
||||
* @dev: device for clock "consumer"
|
||||
* @id: clock consumer ID
|
||||
*
|
||||
* Context: May sleep.
|
||||
*
|
||||
* Return: a struct clk corresponding to the clock producer, or
|
||||
* valid IS_ERR() condition containing errno. The implementation
|
||||
* uses @dev and @id to determine the clock consumer, and thereby
|
||||
* the clock producer. (IOW, @id may be identical strings, but
|
||||
* clk_get may return different clock producers depending on @dev.)
|
||||
*
|
||||
* The returned clk (if valid) is prepared. Drivers must however assume
|
||||
* that the clock is not enabled.
|
||||
*
|
||||
* The clock will automatically be unprepared and freed when the device
|
||||
* is unbound from the bus.
|
||||
*/
|
||||
struct clk *devm_clk_get_prepared(struct device *dev, const char *id);
|
||||
|
||||
/**
|
||||
* devm_clk_get_enabled - devm_clk_get() + clk_prepare_enable()
|
||||
* @dev: device for clock "consumer"
|
||||
* @id: clock consumer ID
|
||||
*
|
||||
* Context: May sleep.
|
||||
*
|
||||
* Return: a struct clk corresponding to the clock producer, or
|
||||
* valid IS_ERR() condition containing errno. The implementation
|
||||
* uses @dev and @id to determine the clock consumer, and thereby
|
||||
* the clock producer. (IOW, @id may be identical strings, but
|
||||
* clk_get may return different clock producers depending on @dev.)
|
||||
*
|
||||
* The returned clk (if valid) is prepared and enabled.
|
||||
*
|
||||
* The clock will automatically be disabled, unprepared and freed
|
||||
* when the device is unbound from the bus.
|
||||
*/
|
||||
struct clk *devm_clk_get_enabled(struct device *dev, const char *id);
|
||||
|
||||
/**
|
||||
* devm_clk_get_optional - lookup and obtain a managed reference to an optional
|
||||
* clock producer.
|
||||
* @dev: device for clock "consumer"
|
||||
* @id: clock consumer ID
|
||||
*
|
||||
* Behaves the same as devm_clk_get() except where there is no clock producer.
|
||||
* In this case, instead of returning -ENOENT, the function returns NULL.
|
||||
* Context: May sleep.
|
||||
*
|
||||
* Return: a struct clk corresponding to the clock producer, or
|
||||
* valid IS_ERR() condition containing errno. The implementation
|
||||
* uses @dev and @id to determine the clock consumer, and thereby
|
||||
* the clock producer. If no such clk is found, it returns NULL
|
||||
* which serves as a dummy clk. That's the only difference compared
|
||||
* to devm_clk_get().
|
||||
*
|
||||
* Drivers must assume that the clock source is neither prepared nor
|
||||
* enabled.
|
||||
*
|
||||
* The clock will automatically be freed when the device is unbound
|
||||
* from the bus.
|
||||
*/
|
||||
struct clk *devm_clk_get_optional(struct device *dev, const char *id);
|
||||
|
||||
/**
|
||||
* devm_clk_get_optional_prepared - devm_clk_get_optional() + clk_prepare()
|
||||
* @dev: device for clock "consumer"
|
||||
* @id: clock consumer ID
|
||||
*
|
||||
* Context: May sleep.
|
||||
*
|
||||
* Return: a struct clk corresponding to the clock producer, or
|
||||
* valid IS_ERR() condition containing errno. The implementation
|
||||
* uses @dev and @id to determine the clock consumer, and thereby
|
||||
* the clock producer. If no such clk is found, it returns NULL
|
||||
* which serves as a dummy clk. That's the only difference compared
|
||||
* to devm_clk_get_prepared().
|
||||
*
|
||||
* The returned clk (if valid) is prepared. Drivers must however
|
||||
* assume that the clock is not enabled.
|
||||
*
|
||||
* The clock will automatically be unprepared and freed when the
|
||||
* device is unbound from the bus.
|
||||
*/
|
||||
struct clk *devm_clk_get_optional_prepared(struct device *dev, const char *id);
|
||||
|
||||
/**
|
||||
* devm_clk_get_optional_enabled - devm_clk_get_optional() +
|
||||
* clk_prepare_enable()
|
||||
* @dev: device for clock "consumer"
|
||||
* @id: clock consumer ID
|
||||
*
|
||||
* Context: May sleep.
|
||||
*
|
||||
* Return: a struct clk corresponding to the clock producer, or
|
||||
* valid IS_ERR() condition containing errno. The implementation
|
||||
* uses @dev and @id to determine the clock consumer, and thereby
|
||||
* the clock producer. If no such clk is found, it returns NULL
|
||||
* which serves as a dummy clk. That's the only difference compared
|
||||
* to devm_clk_get_enabled().
|
||||
*
|
||||
* The returned clk (if valid) is prepared and enabled.
|
||||
*
|
||||
* The clock will automatically be disabled, unprepared and freed
|
||||
* when the device is unbound from the bus.
|
||||
*/
|
||||
struct clk *devm_clk_get_optional_enabled(struct device *dev, const char *id);
|
||||
|
||||
/**
|
||||
* devm_get_clk_from_child - lookup and obtain a managed reference to a
|
||||
* clock producer from child node.
|
||||
|
|
@ -813,12 +911,36 @@ static inline struct clk *devm_clk_get(struct device *dev, const char *id)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static inline struct clk *devm_clk_get_prepared(struct device *dev,
|
||||
const char *id)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline struct clk *devm_clk_get_enabled(struct device *dev,
|
||||
const char *id)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline struct clk *devm_clk_get_optional(struct device *dev,
|
||||
const char *id)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline struct clk *devm_clk_get_optional_prepared(struct device *dev,
|
||||
const char *id)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline struct clk *devm_clk_get_optional_enabled(struct device *dev,
|
||||
const char *id)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline int __must_check devm_clk_bulk_get(struct device *dev, int num_clks,
|
||||
struct clk_bulk_data *clks)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,16 +1,8 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* TI clock drivers support
|
||||
*
|
||||
* Copyright (C) 2013 Texas Instruments, 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.
|
||||
*
|
||||
* 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_CLK_TI_H__
|
||||
#define __LINUX_CLK_TI_H__
|
||||
|
|
|
|||
|
|
@ -66,17 +66,6 @@
|
|||
__builtin_unreachable(); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* GCC 'asm goto' miscompiles certain code sequences:
|
||||
*
|
||||
* http://gcc.gnu.org/bugzilla/show_bug.cgi?id=58670
|
||||
*
|
||||
* Work it around via a compiler barrier quirk suggested by Jakub Jelinek.
|
||||
*
|
||||
* (asm goto is automatically volatile - the naming reflects this.)
|
||||
*/
|
||||
#define asm_volatile_goto(x...) do { asm goto(x); asm (""); } while (0)
|
||||
|
||||
#if defined(CONFIG_ARCH_USE_BUILTIN_BSWAP)
|
||||
#define __HAVE_BUILTIN_BSWAP32__
|
||||
#define __HAVE_BUILTIN_BSWAP64__
|
||||
|
|
|
|||
|
|
@ -239,6 +239,12 @@ static inline void *offset_to_ptr(const int *off)
|
|||
/* &a[0] degrades to a pointer: a different type from an array */
|
||||
#define __must_be_array(a) BUILD_BUG_ON_ZERO(__same_type((a), &(a)[0]))
|
||||
|
||||
/*
|
||||
* Whether 'type' is a signed type or an unsigned type. Supports scalar types,
|
||||
* bool and also pointer types.
|
||||
*/
|
||||
#define is_signed_type(type) (((type)(-1)) < (__force type)1)
|
||||
|
||||
/*
|
||||
* This is needed in functions which generate the stack canary, see
|
||||
* arch/x86/kernel/smpboot.c::start_secondary() for an example.
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
#include <linux/vt.h>
|
||||
#include <linux/workqueue.h>
|
||||
|
||||
struct uni_pagedir;
|
||||
struct uni_pagedict;
|
||||
struct uni_screen;
|
||||
|
||||
#define NPAR 16
|
||||
|
|
@ -157,8 +157,8 @@ struct vc_data {
|
|||
unsigned int vc_bell_duration; /* Console bell duration */
|
||||
unsigned short vc_cur_blink_ms; /* Cursor blink duration */
|
||||
struct vc_data **vc_display_fg; /* [!] Ptr to var holding fg console for this display */
|
||||
struct uni_pagedir *vc_uni_pagedir;
|
||||
struct uni_pagedir **vc_uni_pagedir_loc; /* [!] Location of uni_pagedir variable for this console */
|
||||
struct uni_pagedict *uni_pagedict;
|
||||
struct uni_pagedict **uni_pagedict_loc; /* [!] Location of uni_pagedict variable for this console */
|
||||
struct uni_screen *vc_uni_screen; /* unicode screen content */
|
||||
/* additional information is in vt_kern.h */
|
||||
};
|
||||
|
|
|
|||
|
|
@ -7,30 +7,56 @@
|
|||
#ifndef __LINUX_CONSOLEMAP_H__
|
||||
#define __LINUX_CONSOLEMAP_H__
|
||||
|
||||
#define LAT1_MAP 0
|
||||
#define GRAF_MAP 1
|
||||
#define IBMPC_MAP 2
|
||||
#define USER_MAP 3
|
||||
enum translation_map {
|
||||
LAT1_MAP,
|
||||
GRAF_MAP,
|
||||
IBMPC_MAP,
|
||||
USER_MAP,
|
||||
|
||||
FIRST_MAP = LAT1_MAP,
|
||||
LAST_MAP = USER_MAP,
|
||||
};
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
#ifdef CONFIG_CONSOLE_TRANSLATIONS
|
||||
struct vc_data;
|
||||
|
||||
extern u16 inverse_translate(const struct vc_data *conp, int glyph,
|
||||
int use_unicode);
|
||||
extern unsigned short *set_translate(int m, struct vc_data *vc);
|
||||
extern int conv_uni_to_pc(struct vc_data *conp, long ucs);
|
||||
extern u32 conv_8bit_to_uni(unsigned char c);
|
||||
extern int conv_uni_to_8bit(u32 uni);
|
||||
#ifdef CONFIG_CONSOLE_TRANSLATIONS
|
||||
u16 inverse_translate(const struct vc_data *conp, u16 glyph, bool use_unicode);
|
||||
unsigned short *set_translate(enum translation_map m, struct vc_data *vc);
|
||||
int conv_uni_to_pc(struct vc_data *conp, long ucs);
|
||||
u32 conv_8bit_to_uni(unsigned char c);
|
||||
int conv_uni_to_8bit(u32 uni);
|
||||
void console_map_init(void);
|
||||
#else
|
||||
#define inverse_translate(conp, glyph, uni) ((uint16_t)glyph)
|
||||
#define set_translate(m, vc) ((unsigned short *)NULL)
|
||||
#define conv_uni_to_pc(conp, ucs) ((int) (ucs > 0xff ? -1: ucs))
|
||||
#define conv_8bit_to_uni(c) ((uint32_t)(c))
|
||||
#define conv_uni_to_8bit(c) ((int) ((c) & 0xff))
|
||||
#define console_map_init(c) do { ; } while (0)
|
||||
static inline u16 inverse_translate(const struct vc_data *conp, u16 glyph,
|
||||
bool use_unicode)
|
||||
{
|
||||
return glyph;
|
||||
}
|
||||
|
||||
static inline unsigned short *set_translate(enum translation_map m,
|
||||
struct vc_data *vc)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline int conv_uni_to_pc(struct vc_data *conp, long ucs)
|
||||
{
|
||||
return ucs > 0xff ? -1 : ucs;
|
||||
}
|
||||
|
||||
static inline u32 conv_8bit_to_uni(unsigned char c)
|
||||
{
|
||||
return c;
|
||||
}
|
||||
|
||||
static inline int conv_uni_to_8bit(u32 uni)
|
||||
{
|
||||
return uni & 0xff;
|
||||
}
|
||||
|
||||
static inline void console_map_init(void) { }
|
||||
#endif /* CONFIG_CONSOLE_TRANSLATIONS */
|
||||
|
||||
#endif /* __LINUX_CONSOLEMAP_H__ */
|
||||
|
|
|
|||
|
|
@ -10,71 +10,72 @@
|
|||
#include <asm/ptrace.h>
|
||||
|
||||
|
||||
#ifdef CONFIG_CONTEXT_TRACKING
|
||||
extern void context_tracking_cpu_set(int cpu);
|
||||
#ifdef CONFIG_CONTEXT_TRACKING_USER
|
||||
extern void ct_cpu_track_user(int cpu);
|
||||
|
||||
/* Called with interrupts disabled. */
|
||||
extern void __context_tracking_enter(enum ctx_state state);
|
||||
extern void __context_tracking_exit(enum ctx_state state);
|
||||
extern void __ct_user_enter(enum ctx_state state);
|
||||
extern void __ct_user_exit(enum ctx_state state);
|
||||
|
||||
extern void context_tracking_enter(enum ctx_state state);
|
||||
extern void context_tracking_exit(enum ctx_state state);
|
||||
extern void context_tracking_user_enter(void);
|
||||
extern void context_tracking_user_exit(void);
|
||||
extern void ct_user_enter(enum ctx_state state);
|
||||
extern void ct_user_exit(enum ctx_state state);
|
||||
|
||||
extern void user_enter_callable(void);
|
||||
extern void user_exit_callable(void);
|
||||
|
||||
static inline void user_enter(void)
|
||||
{
|
||||
if (context_tracking_enabled())
|
||||
context_tracking_enter(CONTEXT_USER);
|
||||
ct_user_enter(CONTEXT_USER);
|
||||
|
||||
}
|
||||
static inline void user_exit(void)
|
||||
{
|
||||
if (context_tracking_enabled())
|
||||
context_tracking_exit(CONTEXT_USER);
|
||||
ct_user_exit(CONTEXT_USER);
|
||||
}
|
||||
|
||||
/* Called with interrupts disabled. */
|
||||
static __always_inline void user_enter_irqoff(void)
|
||||
{
|
||||
if (context_tracking_enabled())
|
||||
__context_tracking_enter(CONTEXT_USER);
|
||||
__ct_user_enter(CONTEXT_USER);
|
||||
|
||||
}
|
||||
static __always_inline void user_exit_irqoff(void)
|
||||
{
|
||||
if (context_tracking_enabled())
|
||||
__context_tracking_exit(CONTEXT_USER);
|
||||
__ct_user_exit(CONTEXT_USER);
|
||||
}
|
||||
|
||||
static inline enum ctx_state exception_enter(void)
|
||||
{
|
||||
enum ctx_state prev_ctx;
|
||||
|
||||
if (IS_ENABLED(CONFIG_HAVE_CONTEXT_TRACKING_OFFSTACK) ||
|
||||
if (IS_ENABLED(CONFIG_HAVE_CONTEXT_TRACKING_USER_OFFSTACK) ||
|
||||
!context_tracking_enabled())
|
||||
return 0;
|
||||
|
||||
prev_ctx = this_cpu_read(context_tracking.state);
|
||||
prev_ctx = __ct_state();
|
||||
if (prev_ctx != CONTEXT_KERNEL)
|
||||
context_tracking_exit(prev_ctx);
|
||||
ct_user_exit(prev_ctx);
|
||||
|
||||
return prev_ctx;
|
||||
}
|
||||
|
||||
static inline void exception_exit(enum ctx_state prev_ctx)
|
||||
{
|
||||
if (!IS_ENABLED(CONFIG_HAVE_CONTEXT_TRACKING_OFFSTACK) &&
|
||||
if (!IS_ENABLED(CONFIG_HAVE_CONTEXT_TRACKING_USER_OFFSTACK) &&
|
||||
context_tracking_enabled()) {
|
||||
if (prev_ctx != CONTEXT_KERNEL)
|
||||
context_tracking_enter(prev_ctx);
|
||||
ct_user_enter(prev_ctx);
|
||||
}
|
||||
}
|
||||
|
||||
static __always_inline bool context_tracking_guest_enter(void)
|
||||
{
|
||||
if (context_tracking_enabled())
|
||||
__context_tracking_enter(CONTEXT_GUEST);
|
||||
__ct_user_enter(CONTEXT_GUEST);
|
||||
|
||||
return context_tracking_enabled_this_cpu();
|
||||
}
|
||||
|
|
@ -82,40 +83,56 @@ static __always_inline bool context_tracking_guest_enter(void)
|
|||
static __always_inline void context_tracking_guest_exit(void)
|
||||
{
|
||||
if (context_tracking_enabled())
|
||||
__context_tracking_exit(CONTEXT_GUEST);
|
||||
__ct_user_exit(CONTEXT_GUEST);
|
||||
}
|
||||
|
||||
/**
|
||||
* ct_state() - return the current context tracking state if known
|
||||
*
|
||||
* Returns the current cpu's context tracking state if context tracking
|
||||
* is enabled. If context tracking is disabled, returns
|
||||
* CONTEXT_DISABLED. This should be used primarily for debugging.
|
||||
*/
|
||||
static __always_inline enum ctx_state ct_state(void)
|
||||
{
|
||||
return context_tracking_enabled() ?
|
||||
this_cpu_read(context_tracking.state) : CONTEXT_DISABLED;
|
||||
}
|
||||
#define CT_WARN_ON(cond) WARN_ON(context_tracking_enabled() && (cond))
|
||||
|
||||
#else
|
||||
static inline void user_enter(void) { }
|
||||
static inline void user_exit(void) { }
|
||||
static inline void user_enter_irqoff(void) { }
|
||||
static inline void user_exit_irqoff(void) { }
|
||||
static inline enum ctx_state exception_enter(void) { return 0; }
|
||||
static inline int exception_enter(void) { return 0; }
|
||||
static inline void exception_exit(enum ctx_state prev_ctx) { }
|
||||
static inline enum ctx_state ct_state(void) { return CONTEXT_DISABLED; }
|
||||
static inline int ct_state(void) { return -1; }
|
||||
static __always_inline bool context_tracking_guest_enter(void) { return false; }
|
||||
static inline void context_tracking_guest_exit(void) { }
|
||||
#define CT_WARN_ON(cond) do { } while (0)
|
||||
#endif /* !CONFIG_CONTEXT_TRACKING_USER */
|
||||
|
||||
#endif /* !CONFIG_CONTEXT_TRACKING */
|
||||
|
||||
#define CT_WARN_ON(cond) WARN_ON(context_tracking_enabled() && (cond))
|
||||
|
||||
#ifdef CONFIG_CONTEXT_TRACKING_FORCE
|
||||
#ifdef CONFIG_CONTEXT_TRACKING_USER_FORCE
|
||||
extern void context_tracking_init(void);
|
||||
#else
|
||||
static inline void context_tracking_init(void) { }
|
||||
#endif /* CONFIG_CONTEXT_TRACKING_FORCE */
|
||||
#endif /* CONFIG_CONTEXT_TRACKING_USER_FORCE */
|
||||
|
||||
#ifdef CONFIG_CONTEXT_TRACKING_IDLE
|
||||
extern void ct_idle_enter(void);
|
||||
extern void ct_idle_exit(void);
|
||||
|
||||
/*
|
||||
* Is the current CPU in an extended quiescent state?
|
||||
*
|
||||
* No ordering, as we are sampling CPU-local information.
|
||||
*/
|
||||
static __always_inline bool rcu_dynticks_curr_cpu_in_eqs(void)
|
||||
{
|
||||
return !(arch_atomic_read(this_cpu_ptr(&context_tracking.state)) & RCU_DYNTICKS_IDX);
|
||||
}
|
||||
|
||||
/*
|
||||
* Increment the current CPU's context_tracking structure's ->state field
|
||||
* with ordering. Return the new value.
|
||||
*/
|
||||
static __always_inline unsigned long ct_state_inc(int incby)
|
||||
{
|
||||
return arch_atomic_add_return(incby, this_cpu_ptr(&context_tracking.state));
|
||||
}
|
||||
|
||||
#else
|
||||
static inline void ct_idle_enter(void) { }
|
||||
static inline void ct_idle_exit(void) { }
|
||||
#endif /* !CONFIG_CONTEXT_TRACKING_IDLE */
|
||||
|
||||
#endif
|
||||
|
|
|
|||
21
include/linux/context_tracking_irq.h
Normal file
21
include/linux/context_tracking_irq.h
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef _LINUX_CONTEXT_TRACKING_IRQ_H
|
||||
#define _LINUX_CONTEXT_TRACKING_IRQ_H
|
||||
|
||||
#ifdef CONFIG_CONTEXT_TRACKING_IDLE
|
||||
void ct_irq_enter(void);
|
||||
void ct_irq_exit(void);
|
||||
void ct_irq_enter_irqson(void);
|
||||
void ct_irq_exit_irqson(void);
|
||||
void ct_nmi_enter(void);
|
||||
void ct_nmi_exit(void);
|
||||
#else
|
||||
static inline void ct_irq_enter(void) { }
|
||||
static inline void ct_irq_exit(void) { }
|
||||
static inline void ct_irq_enter_irqson(void) { }
|
||||
static inline void ct_irq_exit_irqson(void) { }
|
||||
static inline void ct_nmi_enter(void) { }
|
||||
static inline void ct_nmi_exit(void) { }
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
@ -4,8 +4,28 @@
|
|||
|
||||
#include <linux/percpu.h>
|
||||
#include <linux/static_key.h>
|
||||
#include <linux/context_tracking_irq.h>
|
||||
|
||||
/* Offset to allow distinguishing irq vs. task-based idle entry/exit. */
|
||||
#define DYNTICK_IRQ_NONIDLE ((LONG_MAX / 2) + 1)
|
||||
|
||||
enum ctx_state {
|
||||
CONTEXT_DISABLED = -1, /* returned by ct_state() if unknown */
|
||||
CONTEXT_KERNEL = 0,
|
||||
CONTEXT_IDLE = 1,
|
||||
CONTEXT_USER = 2,
|
||||
CONTEXT_GUEST = 3,
|
||||
CONTEXT_MAX = 4,
|
||||
};
|
||||
|
||||
/* Even value for idle, else odd. */
|
||||
#define RCU_DYNTICKS_IDX CONTEXT_MAX
|
||||
|
||||
#define CT_STATE_MASK (CONTEXT_MAX - 1)
|
||||
#define CT_DYNTICKS_MASK (~CT_STATE_MASK)
|
||||
|
||||
struct context_tracking {
|
||||
#ifdef CONFIG_CONTEXT_TRACKING_USER
|
||||
/*
|
||||
* When active is false, probes are unset in order
|
||||
* to minimize overhead: TIF flags are cleared
|
||||
|
|
@ -14,18 +34,73 @@ struct context_tracking {
|
|||
*/
|
||||
bool active;
|
||||
int recursion;
|
||||
enum ctx_state {
|
||||
CONTEXT_DISABLED = -1, /* returned by ct_state() if unknown */
|
||||
CONTEXT_KERNEL = 0,
|
||||
CONTEXT_USER,
|
||||
CONTEXT_GUEST,
|
||||
} state;
|
||||
#endif
|
||||
#ifdef CONFIG_CONTEXT_TRACKING
|
||||
atomic_t state;
|
||||
#endif
|
||||
#ifdef CONFIG_CONTEXT_TRACKING_IDLE
|
||||
long dynticks_nesting; /* Track process nesting level. */
|
||||
long dynticks_nmi_nesting; /* Track irq/NMI nesting level. */
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef CONFIG_CONTEXT_TRACKING
|
||||
extern struct static_key_false context_tracking_key;
|
||||
DECLARE_PER_CPU(struct context_tracking, context_tracking);
|
||||
|
||||
static __always_inline int __ct_state(void)
|
||||
{
|
||||
return arch_atomic_read(this_cpu_ptr(&context_tracking.state)) & CT_STATE_MASK;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_CONTEXT_TRACKING_IDLE
|
||||
static __always_inline int ct_dynticks(void)
|
||||
{
|
||||
return atomic_read(this_cpu_ptr(&context_tracking.state)) & CT_DYNTICKS_MASK;
|
||||
}
|
||||
|
||||
static __always_inline int ct_dynticks_cpu(int cpu)
|
||||
{
|
||||
struct context_tracking *ct = per_cpu_ptr(&context_tracking, cpu);
|
||||
|
||||
return atomic_read(&ct->state) & CT_DYNTICKS_MASK;
|
||||
}
|
||||
|
||||
static __always_inline int ct_dynticks_cpu_acquire(int cpu)
|
||||
{
|
||||
struct context_tracking *ct = per_cpu_ptr(&context_tracking, cpu);
|
||||
|
||||
return atomic_read_acquire(&ct->state) & CT_DYNTICKS_MASK;
|
||||
}
|
||||
|
||||
static __always_inline long ct_dynticks_nesting(void)
|
||||
{
|
||||
return __this_cpu_read(context_tracking.dynticks_nesting);
|
||||
}
|
||||
|
||||
static __always_inline long ct_dynticks_nesting_cpu(int cpu)
|
||||
{
|
||||
struct context_tracking *ct = per_cpu_ptr(&context_tracking, cpu);
|
||||
|
||||
return ct->dynticks_nesting;
|
||||
}
|
||||
|
||||
static __always_inline long ct_dynticks_nmi_nesting(void)
|
||||
{
|
||||
return __this_cpu_read(context_tracking.dynticks_nmi_nesting);
|
||||
}
|
||||
|
||||
static __always_inline long ct_dynticks_nmi_nesting_cpu(int cpu)
|
||||
{
|
||||
struct context_tracking *ct = per_cpu_ptr(&context_tracking, cpu);
|
||||
|
||||
return ct->dynticks_nmi_nesting;
|
||||
}
|
||||
#endif /* #ifdef CONFIG_CONTEXT_TRACKING_IDLE */
|
||||
|
||||
#ifdef CONFIG_CONTEXT_TRACKING_USER
|
||||
extern struct static_key_false context_tracking_key;
|
||||
|
||||
static __always_inline bool context_tracking_enabled(void)
|
||||
{
|
||||
return static_branch_unlikely(&context_tracking_key);
|
||||
|
|
@ -41,15 +116,31 @@ static inline bool context_tracking_enabled_this_cpu(void)
|
|||
return context_tracking_enabled() && __this_cpu_read(context_tracking.active);
|
||||
}
|
||||
|
||||
static __always_inline bool context_tracking_in_user(void)
|
||||
/**
|
||||
* ct_state() - return the current context tracking state if known
|
||||
*
|
||||
* Returns the current cpu's context tracking state if context tracking
|
||||
* is enabled. If context tracking is disabled, returns
|
||||
* CONTEXT_DISABLED. This should be used primarily for debugging.
|
||||
*/
|
||||
static __always_inline int ct_state(void)
|
||||
{
|
||||
return __this_cpu_read(context_tracking.state) == CONTEXT_USER;
|
||||
int ret;
|
||||
|
||||
if (!context_tracking_enabled())
|
||||
return CONTEXT_DISABLED;
|
||||
|
||||
preempt_disable();
|
||||
ret = __ct_state();
|
||||
preempt_enable();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#else
|
||||
static __always_inline bool context_tracking_in_user(void) { return false; }
|
||||
static __always_inline bool context_tracking_enabled(void) { return false; }
|
||||
static __always_inline bool context_tracking_enabled_cpu(int cpu) { return false; }
|
||||
static __always_inline bool context_tracking_enabled_this_cpu(void) { return false; }
|
||||
#endif /* CONFIG_CONTEXT_TRACKING */
|
||||
#endif /* CONFIG_CONTEXT_TRACKING_USER */
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
* ETMv3.5/PTM doesn't define ETMCR config bits with prefix "ETM3_" and
|
||||
* directly use below macros as config bits.
|
||||
*/
|
||||
#define ETM_OPT_BRANCH_BROADCAST 8
|
||||
#define ETM_OPT_CYCACC 12
|
||||
#define ETM_OPT_CTXTID 14
|
||||
#define ETM_OPT_CTXTID2 15
|
||||
|
|
@ -25,6 +26,7 @@
|
|||
#define ETM_OPT_RETSTK 29
|
||||
|
||||
/* ETMv4 CONFIGR programming bits for the ETM OPTs */
|
||||
#define ETM4_CFG_BIT_BB 3
|
||||
#define ETM4_CFG_BIT_CYCACC 4
|
||||
#define ETM4_CFG_BIT_CTXTID 6
|
||||
#define ETM4_CFG_BIT_VMID 7
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@
|
|||
#include <linux/bitmap.h>
|
||||
#include <linux/atomic.h>
|
||||
#include <linux/bug.h>
|
||||
#include <linux/gfp_types.h>
|
||||
#include <linux/numa.h>
|
||||
|
||||
/* Don't assign or return these: may not be this big! */
|
||||
typedef struct cpumask { DECLARE_BITMAP(bits, NR_CPUS); } cpumask_t;
|
||||
|
|
@ -116,85 +118,6 @@ static __always_inline unsigned int cpumask_check(unsigned int cpu)
|
|||
return cpu;
|
||||
}
|
||||
|
||||
#if NR_CPUS == 1
|
||||
/* Uniprocessor. Assume all masks are "1". */
|
||||
static inline unsigned int cpumask_first(const struct cpumask *srcp)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline unsigned int cpumask_first_zero(const struct cpumask *srcp)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline unsigned int cpumask_first_and(const struct cpumask *srcp1,
|
||||
const struct cpumask *srcp2)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline unsigned int cpumask_last(const struct cpumask *srcp)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Valid inputs for n are -1 and 0. */
|
||||
static inline unsigned int cpumask_next(int n, const struct cpumask *srcp)
|
||||
{
|
||||
return n+1;
|
||||
}
|
||||
|
||||
static inline unsigned int cpumask_next_zero(int n, const struct cpumask *srcp)
|
||||
{
|
||||
return n+1;
|
||||
}
|
||||
|
||||
static inline unsigned int cpumask_next_and(int n,
|
||||
const struct cpumask *srcp,
|
||||
const struct cpumask *andp)
|
||||
{
|
||||
return n+1;
|
||||
}
|
||||
|
||||
static inline unsigned int cpumask_next_wrap(int n, const struct cpumask *mask,
|
||||
int start, bool wrap)
|
||||
{
|
||||
/* cpu0 unless stop condition, wrap and at cpu0, then nr_cpumask_bits */
|
||||
return (wrap && n == 0);
|
||||
}
|
||||
|
||||
/* cpu must be a valid cpu, ie 0, so there's no other choice. */
|
||||
static inline unsigned int cpumask_any_but(const struct cpumask *mask,
|
||||
unsigned int cpu)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline unsigned int cpumask_local_spread(unsigned int i, int node)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int cpumask_any_and_distribute(const struct cpumask *src1p,
|
||||
const struct cpumask *src2p) {
|
||||
return cpumask_first_and(src1p, src2p);
|
||||
}
|
||||
|
||||
static inline int cpumask_any_distribute(const struct cpumask *srcp)
|
||||
{
|
||||
return cpumask_first(srcp);
|
||||
}
|
||||
|
||||
#define for_each_cpu(cpu, mask) \
|
||||
for ((cpu) = 0; (cpu) < 1; (cpu)++, (void)mask)
|
||||
#define for_each_cpu_not(cpu, mask) \
|
||||
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, mask1, mask2) \
|
||||
for ((cpu) = 0; (cpu) < 1; (cpu)++, (void)mask1, (void)mask2)
|
||||
#else
|
||||
/**
|
||||
* cpumask_first - get the first cpu in a cpumask
|
||||
* @srcp: the cpumask pointer
|
||||
|
|
@ -241,7 +164,21 @@ static inline unsigned int cpumask_last(const struct cpumask *srcp)
|
|||
return find_last_bit(cpumask_bits(srcp), nr_cpumask_bits);
|
||||
}
|
||||
|
||||
unsigned int __pure cpumask_next(int n, const struct cpumask *srcp);
|
||||
/**
|
||||
* cpumask_next - get the next cpu in a cpumask
|
||||
* @n: the cpu prior to the place to search (ie. return will be > @n)
|
||||
* @srcp: the cpumask pointer
|
||||
*
|
||||
* Returns >= nr_cpu_ids if no further cpus set.
|
||||
*/
|
||||
static inline
|
||||
unsigned int cpumask_next(int n, const struct cpumask *srcp)
|
||||
{
|
||||
/* -1 is a legal arg here. */
|
||||
if (n != -1)
|
||||
cpumask_check(n);
|
||||
return find_next_bit(cpumask_bits(srcp), nr_cpumask_bits, n + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* cpumask_next_zero - get the next unset cpu in a cpumask
|
||||
|
|
@ -258,12 +195,48 @@ static inline unsigned int cpumask_next_zero(int n, const struct cpumask *srcp)
|
|||
return find_next_zero_bit(cpumask_bits(srcp), nr_cpumask_bits, n+1);
|
||||
}
|
||||
|
||||
int __pure cpumask_next_and(int n, const struct cpumask *, const struct cpumask *);
|
||||
int __pure cpumask_any_but(const struct cpumask *mask, unsigned int cpu);
|
||||
#if NR_CPUS == 1
|
||||
/* Uniprocessor: there is only one valid CPU */
|
||||
static inline unsigned int cpumask_local_spread(unsigned int i, int node)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline unsigned int cpumask_any_and_distribute(const struct cpumask *src1p,
|
||||
const struct cpumask *src2p)
|
||||
{
|
||||
return cpumask_first_and(src1p, src2p);
|
||||
}
|
||||
|
||||
static inline unsigned int cpumask_any_distribute(const struct cpumask *srcp)
|
||||
{
|
||||
return cpumask_first(srcp);
|
||||
}
|
||||
#else
|
||||
unsigned int cpumask_local_spread(unsigned int i, int node);
|
||||
int cpumask_any_and_distribute(const struct cpumask *src1p,
|
||||
unsigned int cpumask_any_and_distribute(const struct cpumask *src1p,
|
||||
const struct cpumask *src2p);
|
||||
int cpumask_any_distribute(const struct cpumask *srcp);
|
||||
unsigned int cpumask_any_distribute(const struct cpumask *srcp);
|
||||
#endif /* NR_CPUS */
|
||||
|
||||
/**
|
||||
* cpumask_next_and - get the next cpu in *src1p & *src2p
|
||||
* @n: the cpu prior to the place to search (ie. return will be > @n)
|
||||
* @src1p: the first cpumask pointer
|
||||
* @src2p: the second cpumask pointer
|
||||
*
|
||||
* Returns >= nr_cpu_ids if no further cpus set in both.
|
||||
*/
|
||||
static inline
|
||||
unsigned int cpumask_next_and(int n, const struct cpumask *src1p,
|
||||
const struct cpumask *src2p)
|
||||
{
|
||||
/* -1 is a legal arg here. */
|
||||
if (n != -1)
|
||||
cpumask_check(n);
|
||||
return find_next_and_bit(cpumask_bits(src1p), cpumask_bits(src2p),
|
||||
nr_cpumask_bits, n + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* for_each_cpu - iterate over every cpu in a mask
|
||||
|
|
@ -289,7 +262,26 @@ int cpumask_any_distribute(const struct cpumask *srcp);
|
|||
(cpu) = cpumask_next_zero((cpu), (mask)), \
|
||||
(cpu) < nr_cpu_ids;)
|
||||
|
||||
extern int cpumask_next_wrap(int n, const struct cpumask *mask, int start, bool wrap);
|
||||
#if NR_CPUS == 1
|
||||
static inline
|
||||
unsigned int cpumask_next_wrap(int n, const struct cpumask *mask, int start, bool wrap)
|
||||
{
|
||||
cpumask_check(start);
|
||||
if (n != -1)
|
||||
cpumask_check(n);
|
||||
|
||||
/*
|
||||
* Return the first available CPU when wrapping, or when starting before cpu0,
|
||||
* since there is only one valid option.
|
||||
*/
|
||||
if (wrap && n >= 0)
|
||||
return nr_cpumask_bits;
|
||||
|
||||
return cpumask_first(mask);
|
||||
}
|
||||
#else
|
||||
unsigned int __pure cpumask_next_wrap(int n, const struct cpumask *mask, int start, bool wrap);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* for_each_cpu_wrap - iterate over every cpu in a mask, starting at a specified location
|
||||
|
|
@ -324,7 +316,26 @@ extern int cpumask_next_wrap(int n, const struct cpumask *mask, int start, bool
|
|||
for ((cpu) = -1; \
|
||||
(cpu) = cpumask_next_and((cpu), (mask1), (mask2)), \
|
||||
(cpu) < nr_cpu_ids;)
|
||||
#endif /* SMP */
|
||||
|
||||
/**
|
||||
* cpumask_any_but - return a "random" in a cpumask, but not this one.
|
||||
* @mask: the cpumask to search
|
||||
* @cpu: the cpu to ignore.
|
||||
*
|
||||
* Often used to find any cpu but smp_processor_id() in a mask.
|
||||
* Returns >= nr_cpu_ids if no cpus set.
|
||||
*/
|
||||
static inline
|
||||
unsigned int cpumask_any_but(const struct cpumask *mask, unsigned int cpu)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
cpumask_check(cpu);
|
||||
for_each_cpu(i, mask)
|
||||
if (i != cpu)
|
||||
break;
|
||||
return i;
|
||||
}
|
||||
|
||||
#define CPU_BITS_NONE \
|
||||
{ \
|
||||
|
|
@ -372,9 +383,9 @@ static __always_inline void __cpumask_clear_cpu(int cpu, struct cpumask *dstp)
|
|||
* @cpu: cpu number (< nr_cpu_ids)
|
||||
* @cpumask: the cpumask pointer
|
||||
*
|
||||
* Returns 1 if @cpu is set in @cpumask, else returns 0
|
||||
* Returns true if @cpu is set in @cpumask, else returns false
|
||||
*/
|
||||
static __always_inline int cpumask_test_cpu(int cpu, const struct cpumask *cpumask)
|
||||
static __always_inline bool cpumask_test_cpu(int cpu, const struct cpumask *cpumask)
|
||||
{
|
||||
return test_bit(cpumask_check(cpu), cpumask_bits((cpumask)));
|
||||
}
|
||||
|
|
@ -384,11 +395,11 @@ static __always_inline int cpumask_test_cpu(int cpu, const struct cpumask *cpuma
|
|||
* @cpu: cpu number (< nr_cpu_ids)
|
||||
* @cpumask: the cpumask pointer
|
||||
*
|
||||
* Returns 1 if @cpu is set in old bitmap of @cpumask, else returns 0
|
||||
* Returns true if @cpu is set in old bitmap of @cpumask, else returns false
|
||||
*
|
||||
* test_and_set_bit wrapper for cpumasks.
|
||||
*/
|
||||
static __always_inline int cpumask_test_and_set_cpu(int cpu, struct cpumask *cpumask)
|
||||
static __always_inline bool cpumask_test_and_set_cpu(int cpu, struct cpumask *cpumask)
|
||||
{
|
||||
return test_and_set_bit(cpumask_check(cpu), cpumask_bits(cpumask));
|
||||
}
|
||||
|
|
@ -398,11 +409,11 @@ static __always_inline int cpumask_test_and_set_cpu(int cpu, struct cpumask *cpu
|
|||
* @cpu: cpu number (< nr_cpu_ids)
|
||||
* @cpumask: the cpumask pointer
|
||||
*
|
||||
* Returns 1 if @cpu is set in old bitmap of @cpumask, else returns 0
|
||||
* Returns true if @cpu is set in old bitmap of @cpumask, else returns false
|
||||
*
|
||||
* test_and_clear_bit wrapper for cpumasks.
|
||||
*/
|
||||
static __always_inline int cpumask_test_and_clear_cpu(int cpu, struct cpumask *cpumask)
|
||||
static __always_inline bool cpumask_test_and_clear_cpu(int cpu, struct cpumask *cpumask)
|
||||
{
|
||||
return test_and_clear_bit(cpumask_check(cpu), cpumask_bits(cpumask));
|
||||
}
|
||||
|
|
@ -431,9 +442,9 @@ static inline void cpumask_clear(struct cpumask *dstp)
|
|||
* @src1p: the first input
|
||||
* @src2p: the second input
|
||||
*
|
||||
* If *@dstp is empty, returns 0, else returns 1
|
||||
* If *@dstp is empty, returns false, else returns true
|
||||
*/
|
||||
static inline int cpumask_and(struct cpumask *dstp,
|
||||
static inline bool cpumask_and(struct cpumask *dstp,
|
||||
const struct cpumask *src1p,
|
||||
const struct cpumask *src2p)
|
||||
{
|
||||
|
|
@ -474,9 +485,9 @@ static inline void cpumask_xor(struct cpumask *dstp,
|
|||
* @src1p: the first input
|
||||
* @src2p: the second input
|
||||
*
|
||||
* If *@dstp is empty, returns 0, else returns 1
|
||||
* If *@dstp is empty, returns false, else returns true
|
||||
*/
|
||||
static inline int cpumask_andnot(struct cpumask *dstp,
|
||||
static inline bool cpumask_andnot(struct cpumask *dstp,
|
||||
const struct cpumask *src1p,
|
||||
const struct cpumask *src2p)
|
||||
{
|
||||
|
|
@ -539,9 +550,9 @@ static inline bool cpumask_intersects(const struct cpumask *src1p,
|
|||
* @src1p: the first input
|
||||
* @src2p: the second input
|
||||
*
|
||||
* Returns 1 if *@src1p is a subset of *@src2p, else returns 0
|
||||
* Returns true if *@src1p is a subset of *@src2p, else returns false
|
||||
*/
|
||||
static inline int cpumask_subset(const struct cpumask *src1p,
|
||||
static inline bool cpumask_subset(const struct cpumask *src1p,
|
||||
const struct cpumask *src2p)
|
||||
{
|
||||
return bitmap_subset(cpumask_bits(src1p), cpumask_bits(src2p),
|
||||
|
|
@ -743,9 +754,35 @@ typedef struct cpumask *cpumask_var_t;
|
|||
#define __cpumask_var_read_mostly __read_mostly
|
||||
|
||||
bool alloc_cpumask_var_node(cpumask_var_t *mask, gfp_t flags, int node);
|
||||
bool alloc_cpumask_var(cpumask_var_t *mask, gfp_t flags);
|
||||
bool zalloc_cpumask_var_node(cpumask_var_t *mask, gfp_t flags, int node);
|
||||
bool zalloc_cpumask_var(cpumask_var_t *mask, gfp_t flags);
|
||||
|
||||
static inline
|
||||
bool zalloc_cpumask_var_node(cpumask_var_t *mask, gfp_t flags, int node)
|
||||
{
|
||||
return alloc_cpumask_var_node(mask, flags | __GFP_ZERO, node);
|
||||
}
|
||||
|
||||
/**
|
||||
* alloc_cpumask_var - allocate a struct cpumask
|
||||
* @mask: pointer to cpumask_var_t where the cpumask is returned
|
||||
* @flags: GFP_ flags
|
||||
*
|
||||
* Only defined when CONFIG_CPUMASK_OFFSTACK=y, otherwise is
|
||||
* a nop returning a constant 1 (in <linux/cpumask.h>).
|
||||
*
|
||||
* See alloc_cpumask_var_node.
|
||||
*/
|
||||
static inline
|
||||
bool alloc_cpumask_var(cpumask_var_t *mask, gfp_t flags)
|
||||
{
|
||||
return alloc_cpumask_var_node(mask, flags, NUMA_NO_NODE);
|
||||
}
|
||||
|
||||
static inline
|
||||
bool zalloc_cpumask_var(cpumask_var_t *mask, gfp_t flags)
|
||||
{
|
||||
return alloc_cpumask_var(mask, flags | __GFP_ZERO);
|
||||
}
|
||||
|
||||
void alloc_bootmem_cpumask_var(cpumask_var_t *mask);
|
||||
void free_cpumask_var(cpumask_var_t mask);
|
||||
void free_bootmem_cpumask_var(cpumask_var_t mask);
|
||||
|
|
@ -811,9 +848,16 @@ extern const DECLARE_BITMAP(cpu_all_bits, NR_CPUS);
|
|||
/* First bits of cpu_bit_bitmap are in fact unset. */
|
||||
#define cpu_none_mask to_cpumask(cpu_bit_bitmap[0])
|
||||
|
||||
#if NR_CPUS == 1
|
||||
/* Uniprocessor: the possible/online/present masks are always "1" */
|
||||
#define for_each_possible_cpu(cpu) for ((cpu) = 0; (cpu) < 1; (cpu)++)
|
||||
#define for_each_online_cpu(cpu) for ((cpu) = 0; (cpu) < 1; (cpu)++)
|
||||
#define for_each_present_cpu(cpu) for ((cpu) = 0; (cpu) < 1; (cpu)++)
|
||||
#else
|
||||
#define for_each_possible_cpu(cpu) for_each_cpu((cpu), cpu_possible_mask)
|
||||
#define for_each_online_cpu(cpu) for_each_cpu((cpu), cpu_online_mask)
|
||||
#define for_each_present_cpu(cpu) for_each_cpu((cpu), cpu_present_mask)
|
||||
#endif
|
||||
|
||||
/* Wrappers for arch boot code to manipulate normally-constant masks */
|
||||
void init_cpu_present(const struct cpumask *src);
|
||||
|
|
@ -1071,4 +1115,22 @@ cpumap_print_list_to_buf(char *buf, const struct cpumask *mask,
|
|||
[0] = 1UL \
|
||||
} }
|
||||
|
||||
/*
|
||||
* Provide a valid theoretical max size for cpumap and cpulist sysfs files
|
||||
* to avoid breaking userspace which may allocate a buffer based on the size
|
||||
* reported by e.g. fstat.
|
||||
*
|
||||
* for cpumap NR_CPUS * 9/32 - 1 should be an exact length.
|
||||
*
|
||||
* For cpulist 7 is (ceil(log10(NR_CPUS)) + 1) allowing for NR_CPUS to be up
|
||||
* to 2 orders of magnitude larger than 8192. And then we divide by 2 to
|
||||
* cover a worst-case of every other cpu being on one of two nodes for a
|
||||
* very large NR_CPUS.
|
||||
*
|
||||
* Use PAGE_SIZE as a minimum for smaller configurations.
|
||||
*/
|
||||
#define CPUMAP_FILE_MAX_BYTES ((((NR_CPUS * 9)/32 - 1) > PAGE_SIZE) \
|
||||
? (NR_CPUS * 9)/32 - 1 : PAGE_SIZE)
|
||||
#define CPULIST_FILE_MAX_BYTES (((NR_CPUS * 7)/2 > PAGE_SIZE) ? (NR_CPUS * 7)/2 : PAGE_SIZE)
|
||||
|
||||
#endif /* __LINUX_CPUMASK_H */
|
||||
|
|
|
|||
|
|
@ -86,6 +86,8 @@ struct damon_target {
|
|||
* @DAMOS_PAGEOUT: Call ``madvise()`` for the region with MADV_PAGEOUT.
|
||||
* @DAMOS_HUGEPAGE: Call ``madvise()`` for the region with MADV_HUGEPAGE.
|
||||
* @DAMOS_NOHUGEPAGE: Call ``madvise()`` for the region with MADV_NOHUGEPAGE.
|
||||
* @DAMOS_LRU_PRIO: Prioritize the region on its LRU lists.
|
||||
* @DAMOS_LRU_DEPRIO: Deprioritize the region on its LRU lists.
|
||||
* @DAMOS_STAT: Do nothing but count the stat.
|
||||
* @NR_DAMOS_ACTIONS: Total number of DAMOS actions
|
||||
*/
|
||||
|
|
@ -95,6 +97,8 @@ enum damos_action {
|
|||
DAMOS_PAGEOUT,
|
||||
DAMOS_HUGEPAGE,
|
||||
DAMOS_NOHUGEPAGE,
|
||||
DAMOS_LRU_PRIO,
|
||||
DAMOS_LRU_DEPRIO,
|
||||
DAMOS_STAT, /* Do nothing but only record the stat */
|
||||
NR_DAMOS_ACTIONS,
|
||||
};
|
||||
|
|
@ -397,7 +401,6 @@ struct damon_callback {
|
|||
* detail.
|
||||
*
|
||||
* @kdamond: Kernel thread who does the monitoring.
|
||||
* @kdamond_stop: Notifies whether kdamond should stop.
|
||||
* @kdamond_lock: Mutex for the synchronizations with @kdamond.
|
||||
*
|
||||
* For each monitoring context, one kernel thread for the monitoring is
|
||||
|
|
@ -406,14 +409,14 @@ struct damon_callback {
|
|||
* Once started, the monitoring thread runs until explicitly required to be
|
||||
* terminated or every monitoring target is invalid. The validity of the
|
||||
* targets is checked via the &damon_operations.target_valid of @ops. The
|
||||
* termination can also be explicitly requested by writing non-zero to
|
||||
* @kdamond_stop. The thread sets @kdamond to NULL when it terminates.
|
||||
* Therefore, users can know whether the monitoring is ongoing or terminated by
|
||||
* reading @kdamond. Reads and writes to @kdamond and @kdamond_stop from
|
||||
* outside of the monitoring thread must be protected by @kdamond_lock.
|
||||
* termination can also be explicitly requested by calling damon_stop().
|
||||
* The thread sets @kdamond to NULL when it terminates. Therefore, users can
|
||||
* know whether the monitoring is ongoing or terminated by reading @kdamond.
|
||||
* Reads and writes to @kdamond from outside of the monitoring thread must
|
||||
* be protected by @kdamond_lock.
|
||||
*
|
||||
* Note that the monitoring thread protects only @kdamond and @kdamond_stop via
|
||||
* @kdamond_lock. Accesses to other fields must be protected by themselves.
|
||||
* Note that the monitoring thread protects only @kdamond via @kdamond_lock.
|
||||
* Accesses to other fields must be protected by themselves.
|
||||
*
|
||||
* @ops: Set of monitoring operations for given use cases.
|
||||
* @callback: Set of callbacks for monitoring events notifications.
|
||||
|
|
@ -526,6 +529,12 @@ bool damon_is_registered_ops(enum damon_ops_id id);
|
|||
int damon_register_ops(struct damon_operations *ops);
|
||||
int damon_select_ops(struct damon_ctx *ctx, enum damon_ops_id id);
|
||||
|
||||
static inline bool damon_target_has_pid(const struct damon_ctx *ctx)
|
||||
{
|
||||
return ctx->ops.id == DAMON_OPS_VADDR || ctx->ops.id == DAMON_OPS_FVADDR;
|
||||
}
|
||||
|
||||
|
||||
int damon_start(struct damon_ctx **ctxs, int nr_ctxs, bool exclusive);
|
||||
int damon_stop(struct damon_ctx **ctxs, int nr_ctxs);
|
||||
|
||||
|
|
|
|||
|
|
@ -43,8 +43,21 @@ struct dax_operations {
|
|||
void *addr, size_t bytes, struct iov_iter *iter);
|
||||
};
|
||||
|
||||
struct dax_holder_operations {
|
||||
/*
|
||||
* notify_failure - notify memory failure into inner holder device
|
||||
* @dax_dev: the dax device which contains the holder
|
||||
* @offset: offset on this dax device where memory failure occurs
|
||||
* @len: length of this memory failure event
|
||||
* @flags: action flags for memory failure handler
|
||||
*/
|
||||
int (*notify_failure)(struct dax_device *dax_dev, u64 offset,
|
||||
u64 len, int mf_flags);
|
||||
};
|
||||
|
||||
#if IS_ENABLED(CONFIG_DAX)
|
||||
struct dax_device *alloc_dax(void *private, const struct dax_operations *ops);
|
||||
void *dax_holder(struct dax_device *dax_dev);
|
||||
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);
|
||||
|
|
@ -66,6 +79,10 @@ static inline bool daxdev_mapping_supported(struct vm_area_struct *vma,
|
|||
return dax_synchronous(dax_dev);
|
||||
}
|
||||
#else
|
||||
static inline void *dax_holder(struct dax_device *dax_dev)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
static inline struct dax_device *alloc_dax(void *private,
|
||||
const struct dax_operations *ops)
|
||||
{
|
||||
|
|
@ -114,12 +131,9 @@ struct writeback_control;
|
|||
#if defined(CONFIG_BLOCK) && defined(CONFIG_FS_DAX)
|
||||
int dax_add_host(struct dax_device *dax_dev, struct gendisk *disk);
|
||||
void dax_remove_host(struct gendisk *disk);
|
||||
struct dax_device *fs_dax_get_by_bdev(struct block_device *bdev,
|
||||
u64 *start_off);
|
||||
static inline void fs_put_dax(struct dax_device *dax_dev)
|
||||
{
|
||||
put_dax(dax_dev);
|
||||
}
|
||||
struct dax_device *fs_dax_get_by_bdev(struct block_device *bdev, u64 *start_off,
|
||||
void *holder, const struct dax_holder_operations *ops);
|
||||
void fs_put_dax(struct dax_device *dax_dev, void *holder);
|
||||
#else
|
||||
static inline int dax_add_host(struct dax_device *dax_dev, struct gendisk *disk)
|
||||
{
|
||||
|
|
@ -129,11 +143,12 @@ static inline void dax_remove_host(struct gendisk *disk)
|
|||
{
|
||||
}
|
||||
static inline struct dax_device *fs_dax_get_by_bdev(struct block_device *bdev,
|
||||
u64 *start_off)
|
||||
u64 *start_off, void *holder,
|
||||
const struct dax_holder_operations *ops)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
static inline void fs_put_dax(struct dax_device *dax_dev)
|
||||
static inline void fs_put_dax(struct dax_device *dax_dev, void *holder)
|
||||
{
|
||||
}
|
||||
#endif /* CONFIG_BLOCK && CONFIG_FS_DAX */
|
||||
|
|
@ -146,6 +161,10 @@ struct page *dax_layout_busy_page(struct address_space *mapping);
|
|||
struct page *dax_layout_busy_page_range(struct address_space *mapping, loff_t start, loff_t end);
|
||||
dax_entry_t dax_lock_page(struct page *page);
|
||||
void dax_unlock_page(struct page *page, dax_entry_t cookie);
|
||||
dax_entry_t dax_lock_mapping_entry(struct address_space *mapping,
|
||||
unsigned long index, struct page **page);
|
||||
void dax_unlock_mapping_entry(struct address_space *mapping,
|
||||
unsigned long index, dax_entry_t cookie);
|
||||
#else
|
||||
static inline struct page *dax_layout_busy_page(struct address_space *mapping)
|
||||
{
|
||||
|
|
@ -173,6 +192,17 @@ static inline dax_entry_t dax_lock_page(struct page *page)
|
|||
static inline void dax_unlock_page(struct page *page, dax_entry_t cookie)
|
||||
{
|
||||
}
|
||||
|
||||
static inline dax_entry_t dax_lock_mapping_entry(struct address_space *mapping,
|
||||
unsigned long index, struct page **page)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void dax_unlock_mapping_entry(struct address_space *mapping,
|
||||
unsigned long index, dax_entry_t cookie)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
int dax_zero_range(struct inode *inode, loff_t pos, loff_t len, bool *did_zero,
|
||||
|
|
@ -203,6 +233,8 @@ size_t dax_copy_to_iter(struct dax_device *dax_dev, pgoff_t pgoff, void *addr,
|
|||
size_t bytes, struct iov_iter *i);
|
||||
int dax_zero_page_range(struct dax_device *dax_dev, pgoff_t pgoff,
|
||||
size_t nr_pages);
|
||||
int dax_holder_notify_failure(struct dax_device *dax_dev, u64 off, u64 len,
|
||||
int mf_flags);
|
||||
void dax_flush(struct dax_device *dax_dev, void *addr, size_t size);
|
||||
|
||||
ssize_t dax_iomap_rw(struct kiocb *iocb, struct iov_iter *iter,
|
||||
|
|
@ -214,6 +246,14 @@ vm_fault_t dax_finish_sync_fault(struct vm_fault *vmf,
|
|||
int dax_delete_mapping_entry(struct address_space *mapping, pgoff_t index);
|
||||
int dax_invalidate_mapping_entry_sync(struct address_space *mapping,
|
||||
pgoff_t index);
|
||||
int dax_dedupe_file_range_compare(struct inode *src, loff_t srcoff,
|
||||
struct inode *dest, loff_t destoff,
|
||||
loff_t len, bool *is_same,
|
||||
const struct iomap_ops *ops);
|
||||
int dax_remap_file_range_prep(struct file *file_in, loff_t pos_in,
|
||||
struct file *file_out, loff_t pos_out,
|
||||
loff_t *len, unsigned int remap_flags,
|
||||
const struct iomap_ops *ops);
|
||||
static inline bool dax_mapping(struct address_space *mapping)
|
||||
{
|
||||
return mapping->host && IS_DAX(mapping->host);
|
||||
|
|
|
|||
|
|
@ -233,6 +233,8 @@ extern struct dentry * d_alloc_parallel(struct dentry *, const struct qstr *,
|
|||
wait_queue_head_t *);
|
||||
extern struct dentry * d_splice_alias(struct inode *, struct dentry *);
|
||||
extern struct dentry * d_add_ci(struct dentry *, struct inode *, struct qstr *);
|
||||
extern bool d_same_name(const struct dentry *dentry, const struct dentry *parent,
|
||||
const struct qstr *name);
|
||||
extern struct dentry * d_exact_alias(struct dentry *, struct inode *);
|
||||
extern struct dentry *d_find_any_alias(struct inode *inode);
|
||||
extern struct dentry * d_obtain_alias(struct inode *);
|
||||
|
|
@ -349,7 +351,7 @@ static inline void dont_mount(struct dentry *dentry)
|
|||
spin_unlock(&dentry->d_lock);
|
||||
}
|
||||
|
||||
extern void __d_lookup_done(struct dentry *);
|
||||
extern void __d_lookup_unhash_wake(struct dentry *dentry);
|
||||
|
||||
static inline int d_in_lookup(const struct dentry *dentry)
|
||||
{
|
||||
|
|
@ -358,11 +360,8 @@ static inline int d_in_lookup(const struct dentry *dentry)
|
|||
|
||||
static inline void d_lookup_done(struct dentry *dentry)
|
||||
{
|
||||
if (unlikely(d_in_lookup(dentry))) {
|
||||
spin_lock(&dentry->d_lock);
|
||||
__d_lookup_done(dentry);
|
||||
spin_unlock(&dentry->d_lock);
|
||||
}
|
||||
if (unlikely(d_in_lookup(dentry)))
|
||||
__d_lookup_unhash_wake(dentry);
|
||||
}
|
||||
|
||||
extern void dput(struct dentry *);
|
||||
|
|
|
|||
|
|
@ -91,6 +91,8 @@ struct dentry *debugfs_create_automount(const char *name,
|
|||
void debugfs_remove(struct dentry *dentry);
|
||||
#define debugfs_remove_recursive debugfs_remove
|
||||
|
||||
void debugfs_lookup_and_remove(const char *name, struct dentry *parent);
|
||||
|
||||
const struct file_operations *debugfs_real_fops(const struct file *filp);
|
||||
|
||||
int debugfs_file_get(struct dentry *dentry);
|
||||
|
|
@ -225,6 +227,10 @@ static inline void debugfs_remove(struct dentry *dentry)
|
|||
static inline void debugfs_remove_recursive(struct dentry *dentry)
|
||||
{ }
|
||||
|
||||
static inline void debugfs_lookup_and_remove(const char *name,
|
||||
struct dentry *parent)
|
||||
{ }
|
||||
|
||||
const struct file_operations *debugfs_real_fops(const struct file *filp);
|
||||
|
||||
static inline int debugfs_file_get(struct dentry *dentry)
|
||||
|
|
|
|||
|
|
@ -373,6 +373,12 @@ struct dm_target {
|
|||
* after returning DM_MAPIO_SUBMITTED from its map function.
|
||||
*/
|
||||
bool accounts_remapped_io:1;
|
||||
|
||||
/*
|
||||
* Set if the target will submit the DM bio without first calling
|
||||
* bio_set_dev(). NOTE: ideally a target should _not_ need this.
|
||||
*/
|
||||
bool needs_bio_set_dev:1;
|
||||
};
|
||||
|
||||
void *dm_per_bio_data(struct bio *bio, size_t data_size);
|
||||
|
|
@ -561,7 +567,6 @@ void dm_sync_table(struct mapped_device *md);
|
|||
* Queries
|
||||
*/
|
||||
sector_t dm_table_get_size(struct dm_table *t);
|
||||
unsigned int dm_table_get_num_targets(struct dm_table *t);
|
||||
fmode_t dm_table_get_mode(struct dm_table *t);
|
||||
struct mapped_device *dm_table_get_md(struct dm_table *t);
|
||||
const char *dm_table_device_name(struct dm_table *t);
|
||||
|
|
|
|||
|
|
@ -905,6 +905,8 @@ struct device *device_find_child(struct device *dev, void *data,
|
|||
int (*match)(struct device *dev, void *data));
|
||||
struct device *device_find_child_by_name(struct device *parent,
|
||||
const char *name);
|
||||
struct device *device_find_any_child(struct device *parent);
|
||||
|
||||
int device_rename(struct device *dev, const char *new_name);
|
||||
int device_move(struct device *dev, struct device *new_parent,
|
||||
enum dpm_order dpm_order);
|
||||
|
|
|
|||
|
|
@ -129,6 +129,7 @@ extern struct device_driver *driver_find(const char *name,
|
|||
struct bus_type *bus);
|
||||
extern int driver_probe_done(void);
|
||||
extern void wait_for_device_probe(void);
|
||||
void __init wait_for_init_devices_probe(void);
|
||||
|
||||
/* sysfs interface for exporting driver attributes */
|
||||
|
||||
|
|
|
|||
|
|
@ -17,6 +17,11 @@
|
|||
struct dm_bufio_client;
|
||||
struct dm_buffer;
|
||||
|
||||
/*
|
||||
* Flags for dm_bufio_client_create
|
||||
*/
|
||||
#define DM_BUFIO_CLIENT_NO_SLEEP 0x1
|
||||
|
||||
/*
|
||||
* Create a buffered IO cache on a given device
|
||||
*/
|
||||
|
|
@ -24,7 +29,8 @@ struct dm_bufio_client *
|
|||
dm_bufio_client_create(struct block_device *bdev, unsigned block_size,
|
||||
unsigned reserved_buffers, unsigned aux_size,
|
||||
void (*alloc_callback)(struct dm_buffer *),
|
||||
void (*write_callback)(struct dm_buffer *));
|
||||
void (*write_callback)(struct dm_buffer *),
|
||||
unsigned int flags);
|
||||
|
||||
/*
|
||||
* Release a buffered IO cache.
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
#ifdef __KERNEL__
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/blk_types.h>
|
||||
|
||||
struct dm_io_region {
|
||||
struct block_device *bdev;
|
||||
|
|
@ -57,8 +58,7 @@ struct dm_io_notify {
|
|||
*/
|
||||
struct dm_io_client;
|
||||
struct dm_io_request {
|
||||
int bi_op; /* REQ_OP */
|
||||
int bi_op_flags; /* req_flag_bits */
|
||||
blk_opf_t bi_opf; /* Request type and flags */
|
||||
struct dm_io_memory mem; /* Memory to use for io */
|
||||
struct dm_io_notify notify; /* Synchronous if notify.fn is NULL */
|
||||
struct dm_io_client *client; /* Client memory handler */
|
||||
|
|
|
|||
27
include/linux/dm-verity-loadpin.h
Normal file
27
include/linux/dm-verity-loadpin.h
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
|
||||
#ifndef __LINUX_DM_VERITY_LOADPIN_H
|
||||
#define __LINUX_DM_VERITY_LOADPIN_H
|
||||
|
||||
#include <linux/list.h>
|
||||
|
||||
struct block_device;
|
||||
|
||||
extern struct list_head dm_verity_loadpin_trusted_root_digests;
|
||||
|
||||
struct dm_verity_loadpin_trusted_root_digest {
|
||||
struct list_head node;
|
||||
unsigned int len;
|
||||
u8 data[];
|
||||
};
|
||||
|
||||
#if IS_ENABLED(CONFIG_SECURITY_LOADPIN_VERITY)
|
||||
bool dm_verity_loadpin_is_bdev_trusted(struct block_device *bdev);
|
||||
#else
|
||||
static inline bool dm_verity_loadpin_is_bdev_trusted(struct block_device *bdev)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __LINUX_DM_VERITY_LOADPIN_H */
|
||||
|
|
@ -1,7 +1,5 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* fence-chain: chain fences together in a timeline
|
||||
*
|
||||
* Copyright (C) 2022 Advanced Micro Devices, Inc.
|
||||
* Authors:
|
||||
* Christian König <christian.koenig@amd.com>
|
||||
|
|
@ -10,8 +8,7 @@
|
|||
#ifndef __LINUX_DMA_FENCE_UNWRAP_H
|
||||
#define __LINUX_DMA_FENCE_UNWRAP_H
|
||||
|
||||
#include <linux/dma-fence-chain.h>
|
||||
#include <linux/dma-fence-array.h>
|
||||
struct dma_fence;
|
||||
|
||||
/**
|
||||
* struct dma_fence_unwrap - cursor into the container structure
|
||||
|
|
@ -33,50 +30,9 @@ struct dma_fence_unwrap {
|
|||
unsigned int index;
|
||||
};
|
||||
|
||||
/* Internal helper to start new array iteration, don't use directly */
|
||||
static inline struct dma_fence *
|
||||
__dma_fence_unwrap_array(struct dma_fence_unwrap * cursor)
|
||||
{
|
||||
cursor->array = dma_fence_chain_contained(cursor->chain);
|
||||
cursor->index = 0;
|
||||
return dma_fence_array_first(cursor->array);
|
||||
}
|
||||
|
||||
/**
|
||||
* dma_fence_unwrap_first - return the first fence from fence containers
|
||||
* @head: the entrypoint into the containers
|
||||
* @cursor: current position inside the containers
|
||||
*
|
||||
* Unwraps potential dma_fence_chain/dma_fence_array containers and return the
|
||||
* first fence.
|
||||
*/
|
||||
static inline struct dma_fence *
|
||||
dma_fence_unwrap_first(struct dma_fence *head, struct dma_fence_unwrap *cursor)
|
||||
{
|
||||
cursor->chain = dma_fence_get(head);
|
||||
return __dma_fence_unwrap_array(cursor);
|
||||
}
|
||||
|
||||
/**
|
||||
* dma_fence_unwrap_next - return the next fence from a fence containers
|
||||
* @cursor: current position inside the containers
|
||||
*
|
||||
* Continue unwrapping the dma_fence_chain/dma_fence_array containers and return
|
||||
* the next fence from them.
|
||||
*/
|
||||
static inline struct dma_fence *
|
||||
dma_fence_unwrap_next(struct dma_fence_unwrap *cursor)
|
||||
{
|
||||
struct dma_fence *tmp;
|
||||
|
||||
++cursor->index;
|
||||
tmp = dma_fence_array_next(cursor->array, cursor->index);
|
||||
if (tmp)
|
||||
return tmp;
|
||||
|
||||
cursor->chain = dma_fence_chain_walk(cursor->chain);
|
||||
return __dma_fence_unwrap_array(cursor);
|
||||
}
|
||||
struct dma_fence *dma_fence_unwrap_first(struct dma_fence *head,
|
||||
struct dma_fence_unwrap *cursor);
|
||||
struct dma_fence *dma_fence_unwrap_next(struct dma_fence_unwrap *cursor);
|
||||
|
||||
/**
|
||||
* dma_fence_unwrap_for_each - iterate over all fences in containers
|
||||
|
|
@ -92,4 +48,28 @@ dma_fence_unwrap_next(struct dma_fence_unwrap *cursor)
|
|||
for (fence = dma_fence_unwrap_first(head, cursor); fence; \
|
||||
fence = dma_fence_unwrap_next(cursor))
|
||||
|
||||
struct dma_fence *__dma_fence_unwrap_merge(unsigned int num_fences,
|
||||
struct dma_fence **fences,
|
||||
struct dma_fence_unwrap *cursors);
|
||||
|
||||
/**
|
||||
* dma_fence_unwrap_merge - unwrap and merge fences
|
||||
*
|
||||
* All fences given as parameters are unwrapped and merged back together as flat
|
||||
* dma_fence_array. Useful if multiple containers need to be merged together.
|
||||
*
|
||||
* Implemented as a macro to allocate the necessary arrays on the stack and
|
||||
* account the stack frame size to the caller.
|
||||
*
|
||||
* Returns NULL on memory allocation failure, a dma_fence object representing
|
||||
* all the given fences otherwise.
|
||||
*/
|
||||
#define dma_fence_unwrap_merge(...) \
|
||||
({ \
|
||||
struct dma_fence *__f[] = { __VA_ARGS__ }; \
|
||||
struct dma_fence_unwrap __c[ARRAY_SIZE(__f)]; \
|
||||
\
|
||||
__dma_fence_unwrap_merge(ARRAY_SIZE(__f), __f, __c); \
|
||||
})
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -11,7 +11,17 @@
|
|||
|
||||
struct cma;
|
||||
|
||||
/*
|
||||
* Values for struct dma_map_ops.flags:
|
||||
*
|
||||
* DMA_F_PCI_P2PDMA_SUPPORTED: Indicates the dma_map_ops implementation can
|
||||
* handle PCI P2PDMA pages in the map_sg/unmap_sg operation.
|
||||
*/
|
||||
#define DMA_F_PCI_P2PDMA_SUPPORTED (1 << 0)
|
||||
|
||||
struct dma_map_ops {
|
||||
unsigned int flags;
|
||||
|
||||
void *(*alloc)(struct device *dev, size_t size,
|
||||
dma_addr_t *dma_handle, gfp_t gfp,
|
||||
unsigned long attrs);
|
||||
|
|
@ -69,6 +79,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);
|
||||
size_t (*opt_mapping_size)(void);
|
||||
unsigned long (*get_merge_boundary)(struct device *dev);
|
||||
};
|
||||
|
||||
|
|
@ -166,6 +177,7 @@ static inline void dma_pernuma_cma_reserve(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_coherent_memory(struct device *dev);
|
||||
int dma_alloc_from_dev_coherent(struct device *dev, ssize_t size,
|
||||
dma_addr_t *dma_handle, void **ret);
|
||||
int dma_release_from_dev_coherent(struct device *dev, int order, void *vaddr);
|
||||
|
|
@ -177,9 +189,11 @@ static inline int dma_declare_coherent_memory(struct device *dev,
|
|||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
#define dma_alloc_from_dev_coherent(dev, size, handle, ret) (0)
|
||||
#define dma_release_from_dev_coherent(dev, order, vaddr) (0)
|
||||
#define dma_mmap_from_dev_coherent(dev, vma, vaddr, order, ret) (0)
|
||||
static inline void dma_release_coherent_memory(struct device *dev) { }
|
||||
#endif /* CONFIG_DMA_DECLARE_COHERENT */
|
||||
|
||||
#ifdef CONFIG_DMA_GLOBAL_POOL
|
||||
|
|
@ -379,4 +393,57 @@ static inline void debug_dma_dump_mappings(struct device *dev)
|
|||
|
||||
extern const struct dma_map_ops dma_dummy_ops;
|
||||
|
||||
enum pci_p2pdma_map_type {
|
||||
/*
|
||||
* PCI_P2PDMA_MAP_UNKNOWN: Used internally for indicating the mapping
|
||||
* type hasn't been calculated yet. Functions that return this enum
|
||||
* never return this value.
|
||||
*/
|
||||
PCI_P2PDMA_MAP_UNKNOWN = 0,
|
||||
|
||||
/*
|
||||
* PCI_P2PDMA_MAP_NOT_SUPPORTED: Indicates the transaction will
|
||||
* traverse the host bridge and the host bridge is not in the
|
||||
* allowlist. DMA Mapping routines should return an error when
|
||||
* this is returned.
|
||||
*/
|
||||
PCI_P2PDMA_MAP_NOT_SUPPORTED,
|
||||
|
||||
/*
|
||||
* PCI_P2PDMA_BUS_ADDR: Indicates that two devices can talk to
|
||||
* each other directly through a PCI switch and the transaction will
|
||||
* not traverse the host bridge. Such a mapping should program
|
||||
* the DMA engine with PCI bus addresses.
|
||||
*/
|
||||
PCI_P2PDMA_MAP_BUS_ADDR,
|
||||
|
||||
/*
|
||||
* PCI_P2PDMA_MAP_THRU_HOST_BRIDGE: Indicates two devices can talk
|
||||
* to each other, but the transaction traverses a host bridge on the
|
||||
* allowlist. In this case, a normal mapping either with CPU physical
|
||||
* addresses (in the case of dma-direct) or IOVA addresses (in the
|
||||
* case of IOMMUs) should be used to program the DMA engine.
|
||||
*/
|
||||
PCI_P2PDMA_MAP_THRU_HOST_BRIDGE,
|
||||
};
|
||||
|
||||
struct pci_p2pdma_map_state {
|
||||
struct dev_pagemap *pgmap;
|
||||
int map;
|
||||
u64 bus_off;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_PCI_P2PDMA
|
||||
enum pci_p2pdma_map_type
|
||||
pci_p2pdma_map_segment(struct pci_p2pdma_map_state *state, struct device *dev,
|
||||
struct scatterlist *sg);
|
||||
#else /* CONFIG_PCI_P2PDMA */
|
||||
static inline enum pci_p2pdma_map_type
|
||||
pci_p2pdma_map_segment(struct pci_p2pdma_map_state *state, struct device *dev,
|
||||
struct scatterlist *sg)
|
||||
{
|
||||
return PCI_P2PDMA_MAP_NOT_SUPPORTED;
|
||||
}
|
||||
#endif /* CONFIG_PCI_P2PDMA */
|
||||
|
||||
#endif /* _LINUX_DMA_MAP_OPS_H */
|
||||
|
|
|
|||
|
|
@ -139,11 +139,12 @@ 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);
|
||||
bool dma_pci_p2pdma_supported(struct device *dev);
|
||||
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);
|
||||
size_t dma_opt_mapping_size(struct device *dev);
|
||||
bool dma_need_sync(struct device *dev, dma_addr_t dma_addr);
|
||||
unsigned long dma_get_merge_boundary(struct device *dev);
|
||||
struct sg_table *dma_alloc_noncontiguous(struct device *dev, size_t size,
|
||||
|
|
@ -246,9 +247,9 @@ static inline bool dma_can_mmap(struct device *dev)
|
|||
{
|
||||
return false;
|
||||
}
|
||||
static inline int dma_supported(struct device *dev, u64 mask)
|
||||
static inline bool dma_pci_p2pdma_supported(struct device *dev)
|
||||
{
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
static inline int dma_set_mask(struct device *dev, u64 mask)
|
||||
{
|
||||
|
|
@ -266,6 +267,10 @@ static inline size_t dma_max_mapping_size(struct device *dev)
|
|||
{
|
||||
return 0;
|
||||
}
|
||||
static inline size_t dma_opt_mapping_size(struct device *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static inline bool dma_need_sync(struct device *dev, dma_addr_t dma_addr)
|
||||
{
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -12,19 +12,74 @@
|
|||
#include <linux/device.h>
|
||||
#include <linux/dmaengine.h>
|
||||
|
||||
#define EDMA_MAX_WR_CH 8
|
||||
#define EDMA_MAX_RD_CH 8
|
||||
|
||||
struct dw_edma;
|
||||
|
||||
struct dw_edma_region {
|
||||
phys_addr_t paddr;
|
||||
void __iomem *vaddr;
|
||||
size_t sz;
|
||||
};
|
||||
|
||||
struct dw_edma_core_ops {
|
||||
int (*irq_vector)(struct device *dev, unsigned int nr);
|
||||
};
|
||||
|
||||
enum dw_edma_map_format {
|
||||
EDMA_MF_EDMA_LEGACY = 0x0,
|
||||
EDMA_MF_EDMA_UNROLL = 0x1,
|
||||
EDMA_MF_HDMA_COMPAT = 0x5
|
||||
};
|
||||
|
||||
/**
|
||||
* enum dw_edma_chip_flags - Flags specific to an eDMA chip
|
||||
* @DW_EDMA_CHIP_LOCAL: eDMA is used locally by an endpoint
|
||||
*/
|
||||
enum dw_edma_chip_flags {
|
||||
DW_EDMA_CHIP_LOCAL = BIT(0),
|
||||
};
|
||||
|
||||
/**
|
||||
* 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()
|
||||
* @nr_irqs: total number of DMA IRQs
|
||||
* @ops DMA channel to IRQ number mapping
|
||||
* @flags dw_edma_chip_flags
|
||||
* @reg_base DMA register base address
|
||||
* @ll_wr_cnt DMA write link list count
|
||||
* @ll_rd_cnt DMA read link list count
|
||||
* @rg_region DMA register region
|
||||
* @ll_region_wr DMA descriptor link list memory for write channel
|
||||
* @ll_region_rd DMA descriptor link list memory for read channel
|
||||
* @dt_region_wr DMA data memory for write channel
|
||||
* @dt_region_rd DMA data memory for read channel
|
||||
* @mf DMA register map format
|
||||
* @dw: struct dw_edma that is filled by dw_edma_probe()
|
||||
*/
|
||||
struct dw_edma_chip {
|
||||
struct device *dev;
|
||||
int id;
|
||||
int irq;
|
||||
int nr_irqs;
|
||||
const struct dw_edma_core_ops *ops;
|
||||
u32 flags;
|
||||
|
||||
void __iomem *reg_base;
|
||||
|
||||
u16 ll_wr_cnt;
|
||||
u16 ll_rd_cnt;
|
||||
/* link list address */
|
||||
struct dw_edma_region ll_region_wr[EDMA_MAX_WR_CH];
|
||||
struct dw_edma_region ll_region_rd[EDMA_MAX_RD_CH];
|
||||
|
||||
/* data region */
|
||||
struct dw_edma_region dt_region_wr[EDMA_MAX_WR_CH];
|
||||
struct dw_edma_region dt_region_rd[EDMA_MAX_RD_CH];
|
||||
|
||||
enum dw_edma_map_format mf;
|
||||
|
||||
struct dw_edma *dw;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -70,6 +70,16 @@ static inline int imx_dma_is_general_purpose(struct dma_chan *chan)
|
|||
* struct sdma_peripheral_config - SDMA config for audio
|
||||
* @n_fifos_src: Number of FIFOs for recording
|
||||
* @n_fifos_dst: Number of FIFOs for playback
|
||||
* @stride_fifos_src: FIFO address stride for recording, 0 means all FIFOs are
|
||||
* continuous, 1 means 1 word stride between FIFOs. All stride
|
||||
* between FIFOs should be same.
|
||||
* @stride_fifos_dst: FIFO address stride for playback
|
||||
* @words_per_fifo: numbers of words per FIFO fetch/fill, 1 means
|
||||
* one channel per FIFO, 2 means 2 channels per FIFO..
|
||||
* If 'n_fifos_src = 4' and 'words_per_fifo = 2', it
|
||||
* means the first two words(channels) fetch from FIFO0
|
||||
* and then jump to FIFO1 for next two words, and so on
|
||||
* after the last FIFO3 fetched, roll back to FIFO0.
|
||||
* @sw_done: Use software done. Needed for PDM (micfil)
|
||||
*
|
||||
* Some i.MX Audio devices (SAI, micfil) have multiple successive FIFO
|
||||
|
|
@ -82,6 +92,9 @@ static inline int imx_dma_is_general_purpose(struct dma_chan *chan)
|
|||
struct sdma_peripheral_config {
|
||||
int n_fifos_src;
|
||||
int n_fifos_dst;
|
||||
int stride_fifos_src;
|
||||
int stride_fifos_dst;
|
||||
int words_per_fifo;
|
||||
bool sw_done;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ enum spi_transfer_cmd {
|
|||
* @clk_div: source clock divider
|
||||
* @clk_src: serial clock
|
||||
* @cmd: spi cmd
|
||||
* @fragmentation: keep CS assserted at end of sequence
|
||||
* @fragmentation: keep CS asserted at end of sequence
|
||||
* @cs: chip select toggle
|
||||
* @set_config: set peripheral config
|
||||
* @rx_len: receive length for buffer
|
||||
|
|
|
|||
|
|
@ -50,7 +50,6 @@ enum dma_status {
|
|||
*/
|
||||
enum dma_transaction_type {
|
||||
DMA_MEMCPY,
|
||||
DMA_MEMCPY_SG,
|
||||
DMA_XOR,
|
||||
DMA_PQ,
|
||||
DMA_XOR_VAL,
|
||||
|
|
@ -887,11 +886,6 @@ struct dma_device {
|
|||
struct dma_async_tx_descriptor *(*device_prep_dma_memcpy)(
|
||||
struct dma_chan *chan, dma_addr_t dst, dma_addr_t src,
|
||||
size_t len, unsigned long flags);
|
||||
struct dma_async_tx_descriptor *(*device_prep_dma_memcpy_sg)(
|
||||
struct dma_chan *chan,
|
||||
struct scatterlist *dst_sg, unsigned int dst_nents,
|
||||
struct scatterlist *src_sg, unsigned int src_nents,
|
||||
unsigned long flags);
|
||||
struct dma_async_tx_descriptor *(*device_prep_dma_xor)(
|
||||
struct dma_chan *chan, dma_addr_t dst, dma_addr_t *src,
|
||||
unsigned int src_cnt, size_t len, unsigned long flags);
|
||||
|
|
@ -1060,20 +1054,6 @@ static inline struct dma_async_tx_descriptor *dmaengine_prep_dma_memcpy(
|
|||
len, flags);
|
||||
}
|
||||
|
||||
static inline struct dma_async_tx_descriptor *dmaengine_prep_dma_memcpy_sg(
|
||||
struct dma_chan *chan,
|
||||
struct scatterlist *dst_sg, unsigned int dst_nents,
|
||||
struct scatterlist *src_sg, unsigned int src_nents,
|
||||
unsigned long flags)
|
||||
{
|
||||
if (!chan || !chan->device || !chan->device->device_prep_dma_memcpy_sg)
|
||||
return NULL;
|
||||
|
||||
return chan->device->device_prep_dma_memcpy_sg(chan, dst_sg, dst_nents,
|
||||
src_sg, src_nents,
|
||||
flags);
|
||||
}
|
||||
|
||||
static inline bool dmaengine_is_metadata_mode_supported(struct dma_chan *chan,
|
||||
enum dma_desc_metadata_mode mode)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -18,11 +18,7 @@
|
|||
|
||||
struct acpi_dmar_header;
|
||||
|
||||
#ifdef CONFIG_X86
|
||||
# define DMAR_UNITS_SUPPORTED MAX_IO_APICS
|
||||
#else
|
||||
# define DMAR_UNITS_SUPPORTED 64
|
||||
#endif
|
||||
#define DMAR_UNITS_SUPPORTED 1024
|
||||
|
||||
/* DMAR Flags */
|
||||
#define DMAR_INTR_REMAP 0x1
|
||||
|
|
@ -69,6 +65,7 @@ struct dmar_pci_notify_info {
|
|||
|
||||
extern struct rw_semaphore dmar_global_lock;
|
||||
extern struct list_head dmar_drhd_units;
|
||||
extern int intel_iommu_enabled;
|
||||
|
||||
#define for_each_drhd_unit(drhd) \
|
||||
list_for_each_entry_rcu(drhd, &dmar_drhd_units, list, \
|
||||
|
|
@ -92,7 +89,8 @@ extern struct list_head dmar_drhd_units;
|
|||
static inline bool dmar_rcu_check(void)
|
||||
{
|
||||
return rwsem_is_locked(&dmar_global_lock) ||
|
||||
system_state == SYSTEM_BOOTING;
|
||||
system_state == SYSTEM_BOOTING ||
|
||||
(IS_ENABLED(CONFIG_INTEL_IOMMU) && !intel_iommu_enabled);
|
||||
}
|
||||
|
||||
#define dmar_rcu_dereference(p) rcu_dereference_check((p), dmar_rcu_check())
|
||||
|
|
|
|||
|
|
@ -3,6 +3,11 @@
|
|||
#ifndef __TAG_QCA_H
|
||||
#define __TAG_QCA_H
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
struct dsa_switch;
|
||||
struct sk_buff;
|
||||
|
||||
#define QCA_HDR_LEN 2
|
||||
#define QCA_HDR_VERSION 0x2
|
||||
|
||||
|
|
|
|||
|
|
@ -872,6 +872,7 @@ static inline bool efi_rt_services_supported(unsigned int mask)
|
|||
{
|
||||
return (efi.runtime_supported_mask & mask) == mask;
|
||||
}
|
||||
extern void efi_find_mirror(void);
|
||||
#else
|
||||
static inline bool efi_enabled(int feature)
|
||||
{
|
||||
|
|
@ -889,6 +890,8 @@ static inline bool efi_rt_services_supported(unsigned int mask)
|
|||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline void efi_find_mirror(void) {}
|
||||
#endif
|
||||
|
||||
extern int efi_status_to_err(efi_status_t status);
|
||||
|
|
@ -1027,29 +1030,6 @@ struct efivars {
|
|||
|
||||
#define EFI_VAR_NAME_LEN 1024
|
||||
|
||||
struct efi_variable {
|
||||
efi_char16_t VariableName[EFI_VAR_NAME_LEN/sizeof(efi_char16_t)];
|
||||
efi_guid_t VendorGuid;
|
||||
unsigned long DataSize;
|
||||
__u8 Data[1024];
|
||||
efi_status_t Status;
|
||||
__u32 Attributes;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct efivar_entry {
|
||||
struct efi_variable var;
|
||||
struct list_head list;
|
||||
struct kobject kobj;
|
||||
bool scanning;
|
||||
bool deleting;
|
||||
};
|
||||
|
||||
static inline void
|
||||
efivar_unregister(struct efivar_entry *var)
|
||||
{
|
||||
kobject_put(&var->kobj);
|
||||
}
|
||||
|
||||
int efivars_register(struct efivars *efivars,
|
||||
const struct efivar_operations *ops,
|
||||
struct kobject *kobject);
|
||||
|
|
@ -1057,43 +1037,26 @@ int efivars_unregister(struct efivars *efivars);
|
|||
struct kobject *efivars_kobject(void);
|
||||
|
||||
int efivar_supports_writes(void);
|
||||
int efivar_init(int (*func)(efi_char16_t *, efi_guid_t, unsigned long, void *),
|
||||
void *data, bool duplicates, struct list_head *head);
|
||||
|
||||
int efivar_entry_add(struct efivar_entry *entry, struct list_head *head);
|
||||
int efivar_entry_remove(struct efivar_entry *entry);
|
||||
int efivar_lock(void);
|
||||
int efivar_trylock(void);
|
||||
void efivar_unlock(void);
|
||||
|
||||
int __efivar_entry_delete(struct efivar_entry *entry);
|
||||
int efivar_entry_delete(struct efivar_entry *entry);
|
||||
efi_status_t efivar_get_variable(efi_char16_t *name, efi_guid_t *vendor,
|
||||
u32 *attr, unsigned long *size, void *data);
|
||||
|
||||
int efivar_entry_size(struct efivar_entry *entry, unsigned long *size);
|
||||
int __efivar_entry_get(struct efivar_entry *entry, u32 *attributes,
|
||||
unsigned long *size, void *data);
|
||||
int efivar_entry_get(struct efivar_entry *entry, u32 *attributes,
|
||||
unsigned long *size, void *data);
|
||||
int efivar_entry_set(struct efivar_entry *entry, u32 attributes,
|
||||
unsigned long size, void *data, struct list_head *head);
|
||||
int efivar_entry_set_get_size(struct efivar_entry *entry, u32 attributes,
|
||||
unsigned long *size, void *data, bool *set);
|
||||
int efivar_entry_set_safe(efi_char16_t *name, efi_guid_t vendor, u32 attributes,
|
||||
bool block, unsigned long size, void *data);
|
||||
efi_status_t efivar_get_next_variable(unsigned long *name_size,
|
||||
efi_char16_t *name, efi_guid_t *vendor);
|
||||
|
||||
int efivar_entry_iter_begin(void);
|
||||
void efivar_entry_iter_end(void);
|
||||
efi_status_t efivar_set_variable_locked(efi_char16_t *name, efi_guid_t *vendor,
|
||||
u32 attr, unsigned long data_size,
|
||||
void *data, bool nonblocking);
|
||||
|
||||
int __efivar_entry_iter(int (*func)(struct efivar_entry *, void *),
|
||||
struct list_head *head, void *data,
|
||||
struct efivar_entry **prev);
|
||||
int efivar_entry_iter(int (*func)(struct efivar_entry *, void *),
|
||||
struct list_head *head, void *data);
|
||||
efi_status_t efivar_set_variable(efi_char16_t *name, efi_guid_t *vendor,
|
||||
u32 attr, unsigned long data_size, void *data);
|
||||
|
||||
struct efivar_entry *efivar_entry_find(efi_char16_t *name, efi_guid_t guid,
|
||||
struct list_head *head, bool remove);
|
||||
|
||||
bool efivar_validate(efi_guid_t vendor, efi_char16_t *var_name, u8 *data,
|
||||
unsigned long data_size);
|
||||
bool efivar_variable_is_removable(efi_guid_t vendor, const char *name,
|
||||
size_t len);
|
||||
efi_status_t check_var_size(u32 attributes, unsigned long size);
|
||||
efi_status_t check_var_size_nonblocking(u32 attributes, unsigned long size);
|
||||
|
||||
#if IS_ENABLED(CONFIG_EFI_CAPSULE_LOADER)
|
||||
extern bool efi_capsule_pending(int *reset_type);
|
||||
|
|
@ -1181,6 +1144,8 @@ static inline void efi_check_for_embedded_firmwares(void) { }
|
|||
|
||||
efi_status_t efi_random_get_seed(void);
|
||||
|
||||
#define arch_efi_call_virt(p, f, args...) ((p)->f(args))
|
||||
|
||||
/*
|
||||
* Arch code can implement the following three template macros, avoiding
|
||||
* reptition for the void/non-void return cases of {__,}efi_call_virt():
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ struct em_perf_domain {
|
|||
/*
|
||||
* em_perf_domain flags:
|
||||
*
|
||||
* EM_PERF_DOMAIN_MILLIWATTS: The power values are in milli-Watts or some
|
||||
* EM_PERF_DOMAIN_MICROWATTS: The power values are in micro-Watts or some
|
||||
* other scale.
|
||||
*
|
||||
* EM_PERF_DOMAIN_SKIP_INEFFICIENCIES: Skip inefficient states when estimating
|
||||
|
|
@ -71,7 +71,7 @@ struct em_perf_domain {
|
|||
* EM_PERF_DOMAIN_ARTIFICIAL: The power values are artificial and might be
|
||||
* created by platform missing real power information
|
||||
*/
|
||||
#define EM_PERF_DOMAIN_MILLIWATTS BIT(0)
|
||||
#define EM_PERF_DOMAIN_MICROWATTS BIT(0)
|
||||
#define EM_PERF_DOMAIN_SKIP_INEFFICIENCIES BIT(1)
|
||||
#define EM_PERF_DOMAIN_ARTIFICIAL BIT(2)
|
||||
|
||||
|
|
@ -79,22 +79,44 @@ struct em_perf_domain {
|
|||
#define em_is_artificial(em) ((em)->flags & EM_PERF_DOMAIN_ARTIFICIAL)
|
||||
|
||||
#ifdef CONFIG_ENERGY_MODEL
|
||||
#define EM_MAX_POWER 0xFFFF
|
||||
/*
|
||||
* The max power value in micro-Watts. The limit of 64 Watts is set as
|
||||
* a safety net to not overflow multiplications on 32bit platforms. The
|
||||
* 32bit value limit for total Perf Domain power implies a limit of
|
||||
* maximum CPUs in such domain to 64.
|
||||
*/
|
||||
#define EM_MAX_POWER (64000000) /* 64 Watts */
|
||||
|
||||
/*
|
||||
* Increase resolution of energy estimation calculations for 64-bit
|
||||
* architectures. The extra resolution improves decision made by EAS for the
|
||||
* task placement when two Performance Domains might provide similar energy
|
||||
* estimation values (w/o better resolution the values could be equal).
|
||||
*
|
||||
* We increase resolution only if we have enough bits to allow this increased
|
||||
* resolution (i.e. 64-bit). The costs for increasing resolution when 32-bit
|
||||
* are pretty high and the returns do not justify the increased costs.
|
||||
* To avoid possible energy estimation overflow on 32bit machines add
|
||||
* limits to number of CPUs in the Perf. Domain.
|
||||
* We are safe on 64bit machine, thus some big number.
|
||||
*/
|
||||
#ifdef CONFIG_64BIT
|
||||
#define em_scale_power(p) ((p) * 1000)
|
||||
#define EM_MAX_NUM_CPUS 4096
|
||||
#else
|
||||
#define em_scale_power(p) (p)
|
||||
#define EM_MAX_NUM_CPUS 16
|
||||
#endif
|
||||
|
||||
/*
|
||||
* To avoid an overflow on 32bit machines while calculating the energy
|
||||
* use a different order in the operation. First divide by the 'cpu_scale'
|
||||
* which would reduce big value stored in the 'cost' field, then multiply by
|
||||
* the 'sum_util'. This would allow to handle existing platforms, which have
|
||||
* e.g. power ~1.3 Watt at max freq, so the 'cost' value > 1mln micro-Watts.
|
||||
* In such scenario, where there are 4 CPUs in the Perf. Domain the 'sum_util'
|
||||
* could be 4096, then multiplication: 'cost' * 'sum_util' would overflow.
|
||||
* This reordering of operations has some limitations, we lose small
|
||||
* precision in the estimation (comparing to 64bit platform w/o reordering).
|
||||
*
|
||||
* We are safe on 64bit machine.
|
||||
*/
|
||||
#ifdef CONFIG_64BIT
|
||||
#define em_estimate_energy(cost, sum_util, scale_cpu) \
|
||||
(((cost) * (sum_util)) / (scale_cpu))
|
||||
#else
|
||||
#define em_estimate_energy(cost, sum_util, scale_cpu) \
|
||||
(((cost) / (scale_cpu)) * (sum_util))
|
||||
#endif
|
||||
|
||||
struct em_data_callback {
|
||||
|
|
@ -112,7 +134,7 @@ struct em_data_callback {
|
|||
* and frequency.
|
||||
*
|
||||
* In case of CPUs, the power is the one of a single CPU in the domain,
|
||||
* expressed in milli-Watts or an abstract scale. It is expected to
|
||||
* expressed in micro-Watts or an abstract scale. It is expected to
|
||||
* fit in the [0, EM_MAX_POWER] range.
|
||||
*
|
||||
* Return 0 on success.
|
||||
|
|
@ -148,7 +170,7 @@ struct em_perf_domain *em_cpu_get(int cpu);
|
|||
struct em_perf_domain *em_pd_get(struct device *dev);
|
||||
int em_dev_register_perf_domain(struct device *dev, unsigned int nr_states,
|
||||
struct em_data_callback *cb, cpumask_t *span,
|
||||
bool milliwatts);
|
||||
bool microwatts);
|
||||
void em_dev_unregister_perf_domain(struct device *dev);
|
||||
|
||||
/**
|
||||
|
|
@ -273,7 +295,7 @@ static inline unsigned long em_cpu_energy(struct em_perf_domain *pd,
|
|||
* pd_nrg = ------------------------ (4)
|
||||
* scale_cpu
|
||||
*/
|
||||
return ps->cost * sum_util / scale_cpu;
|
||||
return em_estimate_energy(ps->cost, sum_util, scale_cpu);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -297,7 +319,7 @@ struct em_data_callback {};
|
|||
static inline
|
||||
int em_dev_register_perf_domain(struct device *dev, unsigned int nr_states,
|
||||
struct em_data_callback *cb, cpumask_t *span,
|
||||
bool milliwatts)
|
||||
bool microwatts)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -357,7 +357,7 @@ void irqentry_exit_to_user_mode(struct pt_regs *regs);
|
|||
/**
|
||||
* struct irqentry_state - Opaque object for exception state storage
|
||||
* @exit_rcu: Used exclusively in the irqentry_*() calls; signals whether the
|
||||
* exit path has to invoke rcu_irq_exit().
|
||||
* exit path has to invoke ct_irq_exit().
|
||||
* @lockdep: Used exclusively in the irqentry_nmi_*() calls; ensures that
|
||||
* lockdep state is restored correctly on exit from nmi.
|
||||
*
|
||||
|
|
@ -395,12 +395,12 @@ typedef struct irqentry_state {
|
|||
*
|
||||
* For kernel mode entries RCU handling is done conditional. If RCU is
|
||||
* watching then the only RCU requirement is to check whether the tick has
|
||||
* to be restarted. If RCU is not watching then rcu_irq_enter() has to be
|
||||
* invoked on entry and rcu_irq_exit() on exit.
|
||||
* to be restarted. If RCU is not watching then ct_irq_enter() has to be
|
||||
* invoked on entry and ct_irq_exit() on exit.
|
||||
*
|
||||
* Avoiding the rcu_irq_enter/exit() calls is an optimization but also
|
||||
* Avoiding the ct_irq_enter/exit() calls is an optimization but also
|
||||
* solves the problem of kernel mode pagefaults which can schedule, which
|
||||
* is not possible after invoking rcu_irq_enter() without undoing it.
|
||||
* is not possible after invoking ct_irq_enter() without undoing it.
|
||||
*
|
||||
* For user mode entries irqentry_enter_from_user_mode() is invoked to
|
||||
* establish the proper context for NOHZ_FULL. Otherwise scheduling on exit
|
||||
|
|
|
|||
|
|
@ -76,6 +76,8 @@
|
|||
#define EXTCON_DISP_VGA 43 /* Video Graphics Array */
|
||||
#define EXTCON_DISP_DP 44 /* Display Port */
|
||||
#define EXTCON_DISP_HMD 45 /* Head-Mounted Display */
|
||||
#define EXTCON_DISP_CVBS 46 /* Composite Video Broadcast Signal */
|
||||
#define EXTCON_DISP_EDP 47 /* Embedded Display Port */
|
||||
|
||||
/* Miscellaneous external connector */
|
||||
#define EXTCON_DOCK 60
|
||||
|
|
|
|||
|
|
@ -511,7 +511,6 @@ struct fb_info {
|
|||
} *apertures;
|
||||
|
||||
bool skip_vt_switch; /* no VT switch on suspend/resume required */
|
||||
bool forced_out; /* set when being removed by another driver */
|
||||
};
|
||||
|
||||
static inline struct apertures_struct *alloc_apertures(unsigned int max_num) {
|
||||
|
|
|
|||
|
|
@ -559,40 +559,6 @@ struct bpf_prog_stats {
|
|||
struct u64_stats_sync syncp;
|
||||
} __aligned(2 * sizeof(u64));
|
||||
|
||||
struct bpf_prog {
|
||||
u16 pages; /* Number of allocated pages */
|
||||
u16 jited:1, /* Is our filter JIT'ed? */
|
||||
jit_requested:1,/* archs need to JIT the prog */
|
||||
gpl_compatible:1, /* Is filter GPL compatible? */
|
||||
cb_access:1, /* Is control block accessed? */
|
||||
dst_needed:1, /* Do we need dst entry? */
|
||||
blinding_requested:1, /* needs constant blinding */
|
||||
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? */
|
||||
enforce_expected_attach_type:1, /* Enforce expected_attach_type checking at attach time */
|
||||
call_get_stack:1, /* Do we call bpf_get_stack() or bpf_get_stackid() */
|
||||
call_get_func_ip:1, /* Do we call get_func_ip() */
|
||||
tstamp_type_access:1; /* Accessed __sk_buff->tstamp_type */
|
||||
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 */
|
||||
u32 jited_len; /* Size of jited insns in bytes */
|
||||
u8 tag[BPF_TAG_SIZE];
|
||||
struct bpf_prog_stats __percpu *stats;
|
||||
int __percpu *active;
|
||||
unsigned int (*bpf_func)(const void *ctx,
|
||||
const struct bpf_insn *insn);
|
||||
struct bpf_prog_aux *aux; /* Auxiliary fields */
|
||||
struct sock_fprog_kern *orig_prog; /* Original BPF program */
|
||||
/* Instructions for interpreter */
|
||||
union {
|
||||
DECLARE_FLEX_ARRAY(struct sock_filter, insns);
|
||||
DECLARE_FLEX_ARRAY(struct bpf_insn, insnsi);
|
||||
};
|
||||
};
|
||||
|
||||
struct sk_filter {
|
||||
refcount_t refcnt;
|
||||
struct rcu_head rcu;
|
||||
|
|
@ -948,6 +914,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_jit_supports_subprog_tailcalls(void);
|
||||
bool bpf_jit_supports_kfunc_call(void);
|
||||
bool bpf_helper_changes_pkt_data(void *func);
|
||||
|
||||
|
|
@ -1060,6 +1027,14 @@ u64 bpf_jit_alloc_exec_limit(void);
|
|||
void *bpf_jit_alloc_exec(unsigned long size);
|
||||
void bpf_jit_free_exec(void *addr);
|
||||
void bpf_jit_free(struct bpf_prog *fp);
|
||||
struct bpf_binary_header *
|
||||
bpf_jit_binary_pack_hdr(const struct bpf_prog *fp);
|
||||
|
||||
static inline bool bpf_prog_kallsyms_verify_off(const struct bpf_prog *fp)
|
||||
{
|
||||
return list_empty(&fp->aux->ksym.lnode) ||
|
||||
fp->aux->ksym.lnode.prev == LIST_POISON2;
|
||||
}
|
||||
|
||||
struct bpf_binary_header *
|
||||
bpf_jit_binary_pack_alloc(unsigned int proglen, u8 **ro_image,
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
#ifndef __CS_DSP_H
|
||||
#define __CS_DSP_H
|
||||
|
||||
#include <linux/bits.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/list.h>
|
||||
|
|
@ -34,6 +35,7 @@
|
|||
#define CS_ADSP2_REGION_ALL (CS_ADSP2_REGION_0 | CS_ADSP2_REGION_1_9)
|
||||
|
||||
#define CS_DSP_DATA_WORD_SIZE 3
|
||||
#define CS_DSP_DATA_WORD_BITS (3 * BITS_PER_BYTE)
|
||||
|
||||
#define CS_DSP_ACKED_CTL_TIMEOUT_MS 100
|
||||
#define CS_DSP_ACKED_CTL_N_QUICKPOLLS 10
|
||||
|
|
@ -189,7 +191,8 @@ struct cs_dsp {
|
|||
* @control_remove: Called under the pwr_lock when a control is destroyed
|
||||
* @pre_run: Called under the pwr_lock by cs_dsp_run() before the core is started
|
||||
* @post_run: Called under the pwr_lock by cs_dsp_run() after the core is started
|
||||
* @post_stop: Called under the pwr_lock by cs_dsp_stop()
|
||||
* @pre_stop: Called under the pwr_lock by cs_dsp_stop() before the core is stopped
|
||||
* @post_stop: Called under the pwr_lock by cs_dsp_stop() after the core is stopped
|
||||
* @watchdog_expired: Called when a watchdog expiry is detected
|
||||
*
|
||||
* These callbacks give the cs_dsp client an opportunity to respond to events
|
||||
|
|
@ -200,6 +203,7 @@ struct cs_dsp_client_ops {
|
|||
void (*control_remove)(struct cs_dsp_coeff_ctl *ctl);
|
||||
int (*pre_run)(struct cs_dsp *dsp);
|
||||
int (*post_run)(struct cs_dsp *dsp);
|
||||
void (*pre_stop)(struct cs_dsp *dsp);
|
||||
void (*post_stop)(struct cs_dsp *dsp);
|
||||
void (*watchdog_expired)(struct cs_dsp *dsp);
|
||||
};
|
||||
|
|
@ -250,4 +254,75 @@ struct cs_dsp_alg_region *cs_dsp_find_alg_region(struct cs_dsp *dsp,
|
|||
|
||||
const char *cs_dsp_mem_region_name(unsigned int type);
|
||||
|
||||
/**
|
||||
* struct cs_dsp_chunk - Describes a buffer holding data formatted for the DSP
|
||||
* @data: Pointer to underlying buffer memory
|
||||
* @max: Pointer to end of the buffer memory
|
||||
* @bytes: Number of bytes read/written into the memory chunk
|
||||
* @cache: Temporary holding data as it is formatted
|
||||
* @cachebits: Number of bits of data currently in cache
|
||||
*/
|
||||
struct cs_dsp_chunk {
|
||||
u8 *data;
|
||||
u8 *max;
|
||||
int bytes;
|
||||
|
||||
u32 cache;
|
||||
int cachebits;
|
||||
};
|
||||
|
||||
/**
|
||||
* cs_dsp_chunk() - Create a DSP memory chunk
|
||||
* @data: Pointer to the buffer that will be used to store data
|
||||
* @size: Size of the buffer in bytes
|
||||
*
|
||||
* Return: A cs_dsp_chunk structure
|
||||
*/
|
||||
static inline struct cs_dsp_chunk cs_dsp_chunk(void *data, int size)
|
||||
{
|
||||
struct cs_dsp_chunk ch = {
|
||||
.data = data,
|
||||
.max = data + size,
|
||||
};
|
||||
|
||||
return ch;
|
||||
}
|
||||
|
||||
/**
|
||||
* cs_dsp_chunk_end() - Check if a DSP memory chunk is full
|
||||
* @ch: Pointer to the chunk structure
|
||||
*
|
||||
* Return: True if the whole buffer has been read/written
|
||||
*/
|
||||
static inline bool cs_dsp_chunk_end(struct cs_dsp_chunk *ch)
|
||||
{
|
||||
return ch->data == ch->max;
|
||||
}
|
||||
|
||||
/**
|
||||
* cs_dsp_chunk_bytes() - Number of bytes written/read from a DSP memory chunk
|
||||
* @ch: Pointer to the chunk structure
|
||||
*
|
||||
* Return: Number of bytes read/written to the buffer
|
||||
*/
|
||||
static inline int cs_dsp_chunk_bytes(struct cs_dsp_chunk *ch)
|
||||
{
|
||||
return ch->bytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* cs_dsp_chunk_valid_addr() - Check if an address is in a DSP memory chunk
|
||||
* @ch: Pointer to the chunk structure
|
||||
*
|
||||
* Return: True if the given address is within the buffer
|
||||
*/
|
||||
static inline bool cs_dsp_chunk_valid_addr(struct cs_dsp_chunk *ch, void *addr)
|
||||
{
|
||||
return (u8 *)addr >= ch->data && (u8 *)addr < ch->max;
|
||||
}
|
||||
|
||||
int cs_dsp_chunk_write(struct cs_dsp_chunk *ch, int nbits, u32 val);
|
||||
int cs_dsp_chunk_flush(struct cs_dsp_chunk *ch);
|
||||
int cs_dsp_chunk_read(struct cs_dsp_chunk *ch, int nbits);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -403,6 +403,52 @@ INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_FPGA_CONFIG_COMPLETED_WRITE)
|
|||
#define INTEL_SIP_SMC_RSU_MAX_RETRY \
|
||||
INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_RSU_MAX_RETRY)
|
||||
|
||||
/**
|
||||
* Request INTEL_SIP_SMC_RSU_DCMF_STATUS
|
||||
*
|
||||
* Sync call used by service driver at EL1 to query DCMF status from FW
|
||||
*
|
||||
* Call register usage:
|
||||
* a0 INTEL_SIP_SMC_RSU_DCMF_STATUS
|
||||
* a1-7 not used
|
||||
*
|
||||
* Return status
|
||||
* a0 INTEL_SIP_SMC_STATUS_OK
|
||||
* a1 dcmf3 | dcmf2 | dcmf1 | dcmf0
|
||||
*
|
||||
* Or
|
||||
*
|
||||
* a0 INTEL_SIP_SMC_RSU_ERROR
|
||||
*/
|
||||
#define INTEL_SIP_SMC_FUNCID_RSU_DCMF_STATUS 20
|
||||
#define INTEL_SIP_SMC_RSU_DCMF_STATUS \
|
||||
INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_RSU_DCMF_STATUS)
|
||||
|
||||
/**
|
||||
* Request INTEL_SIP_SMC_SERVICE_COMPLETED
|
||||
* Sync call to check if the secure world have completed service request
|
||||
* or not.
|
||||
*
|
||||
* Call register usage:
|
||||
* a0: INTEL_SIP_SMC_SERVICE_COMPLETED
|
||||
* a1: this register is optional. If used, it is the physical address for
|
||||
* secure firmware to put output data
|
||||
* a2: this register is optional. If used, it is the size of output data
|
||||
* a3-a7: not used
|
||||
*
|
||||
* Return status:
|
||||
* a0: INTEL_SIP_SMC_STATUS_OK, INTEL_SIP_SMC_STATUS_ERROR,
|
||||
* INTEL_SIP_SMC_REJECTED or INTEL_SIP_SMC_STATUS_BUSY
|
||||
* a1: mailbox error if a0 is INTEL_SIP_SMC_STATUS_ERROR
|
||||
* a2: physical address containing the process info
|
||||
* for FCS certificate -- the data contains the certificate status
|
||||
* for FCS cryption -- the data contains the actual data size FW processes
|
||||
* a3: output data size
|
||||
*/
|
||||
#define INTEL_SIP_SMC_FUNCID_SERVICE_COMPLETED 30
|
||||
#define INTEL_SIP_SMC_SERVICE_COMPLETED \
|
||||
INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_SERVICE_COMPLETED)
|
||||
|
||||
/**
|
||||
* Request INTEL_SIP_SMC_FIRMWARE_VERSION
|
||||
*
|
||||
|
|
@ -420,4 +466,133 @@ INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_FPGA_CONFIG_COMPLETED_WRITE)
|
|||
#define INTEL_SIP_SMC_FIRMWARE_VERSION \
|
||||
INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_FIRMWARE_VERSION)
|
||||
|
||||
/**
|
||||
* Request INTEL_SIP_SMC_SVC_VERSION
|
||||
*
|
||||
* Sync call used to query the SIP SMC API Version
|
||||
*
|
||||
* Call register usage:
|
||||
* a0 INTEL_SIP_SMC_SVC_VERSION
|
||||
* a1-a7 not used
|
||||
*
|
||||
* Return status:
|
||||
* a0 INTEL_SIP_SMC_STATUS_OK
|
||||
* a1 Major
|
||||
* a2 Minor
|
||||
*/
|
||||
#define INTEL_SIP_SMC_SVC_FUNCID_VERSION 512
|
||||
#define INTEL_SIP_SMC_SVC_VERSION \
|
||||
INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_SVC_FUNCID_VERSION)
|
||||
|
||||
/**
|
||||
* SMC call protocol for FPGA Crypto Service (FCS)
|
||||
* FUNCID starts from 90
|
||||
*/
|
||||
|
||||
/**
|
||||
* Request INTEL_SIP_SMC_FCS_RANDOM_NUMBER
|
||||
*
|
||||
* Sync call used to query the random number generated by the firmware
|
||||
*
|
||||
* Call register usage:
|
||||
* a0 INTEL_SIP_SMC_FCS_RANDOM_NUMBER
|
||||
* a1 the physical address for firmware to write generated random data
|
||||
* a2-a7 not used
|
||||
*
|
||||
* Return status:
|
||||
* a0 INTEL_SIP_SMC_STATUS_OK, INTEL_SIP_SMC_FCS_ERROR or
|
||||
* INTEL_SIP_SMC_FCS_REJECTED
|
||||
* a1 mailbox error
|
||||
* a2 the physical address of generated random number
|
||||
* a3 size
|
||||
*/
|
||||
#define INTEL_SIP_SMC_FUNCID_FCS_RANDOM_NUMBER 90
|
||||
#define INTEL_SIP_SMC_FCS_RANDOM_NUMBER \
|
||||
INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_FCS_RANDOM_NUMBER)
|
||||
|
||||
/**
|
||||
* Request INTEL_SIP_SMC_FCS_CRYPTION
|
||||
* Async call for data encryption and HMAC signature generation, or for
|
||||
* data decryption and HMAC verification.
|
||||
*
|
||||
* Call INTEL_SIP_SMC_SERVICE_COMPLETED to get the output encrypted or
|
||||
* decrypted data
|
||||
*
|
||||
* Call register usage:
|
||||
* a0 INTEL_SIP_SMC_FCS_CRYPTION
|
||||
* a1 cryption mode (1 for encryption and 0 for decryption)
|
||||
* a2 physical address which stores to be encrypted or decrypted data
|
||||
* a3 input data size
|
||||
* a4 physical address which will hold the encrypted or decrypted output data
|
||||
* a5 output data size
|
||||
* a6-a7 not used
|
||||
*
|
||||
* Return status:
|
||||
* a0 INTEL_SIP_SMC_STATUS_OK, INTEL_SIP_SMC_STATUS_ERROR or
|
||||
* INTEL_SIP_SMC_STATUS_REJECTED
|
||||
* a1-3 not used
|
||||
*/
|
||||
#define INTEL_SIP_SMC_FUNCID_FCS_CRYPTION 91
|
||||
#define INTEL_SIP_SMC_FCS_CRYPTION \
|
||||
INTEL_SIP_SMC_STD_CALL_VAL(INTEL_SIP_SMC_FUNCID_FCS_CRYPTION)
|
||||
|
||||
/**
|
||||
* Request INTEL_SIP_SMC_FCS_SERVICE_REQUEST
|
||||
* Async call for authentication service of HPS software
|
||||
*
|
||||
* Call register usage:
|
||||
* a0 INTEL_SIP_SMC_FCS_SERVICE_REQUEST
|
||||
* a1 the physical address of data block
|
||||
* a2 size of data block
|
||||
* a3-a7 not used
|
||||
*
|
||||
* Return status:
|
||||
* a0 INTEL_SIP_SMC_STATUS_OK, INTEL_SIP_SMC_ERROR or
|
||||
* INTEL_SIP_SMC_REJECTED
|
||||
* a1-a3 not used
|
||||
*/
|
||||
#define INTEL_SIP_SMC_FUNCID_FCS_SERVICE_REQUEST 92
|
||||
#define INTEL_SIP_SMC_FCS_SERVICE_REQUEST \
|
||||
INTEL_SIP_SMC_STD_CALL_VAL(INTEL_SIP_SMC_FUNCID_FCS_SERVICE_REQUEST)
|
||||
|
||||
/**
|
||||
* Request INTEL_SIP_SMC_FUNCID_FCS_SEND_CERTIFICATE
|
||||
* Sync call to send a signed certificate
|
||||
*
|
||||
* Call register usage:
|
||||
* a0 INTEL_SIP_SMC_FCS_SEND_CERTIFICATE
|
||||
* a1 the physical address of CERTIFICATE block
|
||||
* a2 size of data block
|
||||
* a3-a7 not used
|
||||
*
|
||||
* Return status:
|
||||
* a0 INTEL_SIP_SMC_STATUS_OK or INTEL_SIP_SMC_FCS_REJECTED
|
||||
* a1-a3 not used
|
||||
*/
|
||||
#define INTEL_SIP_SMC_FUNCID_FCS_SEND_CERTIFICATE 93
|
||||
#define INTEL_SIP_SMC_FCS_SEND_CERTIFICATE \
|
||||
INTEL_SIP_SMC_STD_CALL_VAL(INTEL_SIP_SMC_FUNCID_FCS_SEND_CERTIFICATE)
|
||||
|
||||
/**
|
||||
* Request INTEL_SIP_SMC_FCS_GET_PROVISION_DATA
|
||||
* Sync call to dump all the fuses and key hashes
|
||||
*
|
||||
* Call register usage:
|
||||
* a0 INTEL_SIP_SMC_FCS_GET_PROVISION_DATA
|
||||
* a1 the physical address for firmware to write structure of fuse and
|
||||
* key hashes
|
||||
* a2-a7 not used
|
||||
*
|
||||
* Return status:
|
||||
* a0 INTEL_SIP_SMC_STATUS_OK, INTEL_SIP_SMC_FCS_ERROR or
|
||||
* INTEL_SIP_SMC_FCS_REJECTED
|
||||
* a1 mailbox error
|
||||
* a2 physical address for the structure of fuse and key hashes
|
||||
* a3 the size of structure
|
||||
*
|
||||
*/
|
||||
#define INTEL_SIP_SMC_FUNCID_FCS_GET_PROVISION_DATA 94
|
||||
#define INTEL_SIP_SMC_FCS_GET_PROVISION_DATA \
|
||||
INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_FCS_GET_PROVISION_DATA)
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@
|
|||
*/
|
||||
#define SVC_CLIENT_FPGA "fpga"
|
||||
#define SVC_CLIENT_RSU "rsu"
|
||||
#define SVC_CLIENT_FCS "fcs"
|
||||
|
||||
/*
|
||||
* Status of the sent command, in bit number
|
||||
|
|
@ -49,6 +50,7 @@
|
|||
#define SVC_STATUS_BUSY 4
|
||||
#define SVC_STATUS_ERROR 5
|
||||
#define SVC_STATUS_NO_SUPPORT 6
|
||||
#define SVC_STATUS_INVALID_PARAM 7
|
||||
|
||||
/*
|
||||
* Flag bit for COMMAND_RECONFIG
|
||||
|
|
@ -66,6 +68,8 @@
|
|||
#define SVC_RECONFIG_REQUEST_TIMEOUT_MS 300
|
||||
#define SVC_RECONFIG_BUFFER_TIMEOUT_MS 720
|
||||
#define SVC_RSU_REQUEST_TIMEOUT_MS 300
|
||||
#define SVC_FCS_REQUEST_TIMEOUT_MS 2000
|
||||
#define SVC_COMPLETED_TIMEOUT_MS 30000
|
||||
|
||||
struct stratix10_svc_chan;
|
||||
|
||||
|
|
@ -105,34 +109,79 @@ struct stratix10_svc_chan;
|
|||
* @COMMAND_RSU_DCMF_VERSION: query firmware for the DCMF version, return status
|
||||
* is SVC_STATUS_OK or SVC_STATUS_ERROR
|
||||
*
|
||||
* @COMMAND_POLL_SERVICE_STATUS: poll if the service request is complete,
|
||||
* return statis is SVC_STATUS_OK, SVC_STATUS_ERROR or SVC_STATUS_BUSY
|
||||
*
|
||||
* @COMMAND_FIRMWARE_VERSION: query running firmware version, return status
|
||||
* is SVC_STATUS_OK or SVC_STATUS_ERROR
|
||||
*
|
||||
* @COMMAND_SMC_SVC_VERSION: Non-mailbox SMC SVC API Version,
|
||||
* return status is SVC_STATUS_OK
|
||||
*
|
||||
* @COMMAND_RSU_DCMF_STATUS: query firmware for the DCMF status
|
||||
* return status is SVC_STATUS_OK or SVC_STATUS_ERROR
|
||||
*
|
||||
* @COMMAND_FCS_REQUEST_SERVICE: request validation of image from firmware,
|
||||
* return status is SVC_STATUS_OK, SVC_STATUS_INVALID_PARAM
|
||||
*
|
||||
* @COMMAND_FCS_SEND_CERTIFICATE: send a certificate, return status is
|
||||
* SVC_STATUS_OK, SVC_STATUS_INVALID_PARAM, SVC_STATUS_ERROR
|
||||
*
|
||||
* @COMMAND_FCS_GET_PROVISION_DATA: read the provisioning data, return status is
|
||||
* SVC_STATUS_OK, SVC_STATUS_INVALID_PARAM, SVC_STATUS_ERROR
|
||||
*
|
||||
* @COMMAND_FCS_DATA_ENCRYPTION: encrypt the data, return status is
|
||||
* SVC_STATUS_OK, SVC_STATUS_INVALID_PARAM, SVC_STATUS_ERROR
|
||||
*
|
||||
* @COMMAND_FCS_DATA_DECRYPTION: decrypt the data, return status is
|
||||
* SVC_STATUS_OK, SVC_STATUS_INVALID_PARAM, SVC_STATUS_ERROR
|
||||
*
|
||||
* @COMMAND_FCS_RANDOM_NUMBER_GEN: generate a random number, return status
|
||||
* is SVC_STATUS_OK, SVC_STATUS_ERROR
|
||||
*/
|
||||
enum stratix10_svc_command_code {
|
||||
/* for FPGA */
|
||||
COMMAND_NOOP = 0,
|
||||
COMMAND_RECONFIG,
|
||||
COMMAND_RECONFIG_DATA_SUBMIT,
|
||||
COMMAND_RECONFIG_DATA_CLAIM,
|
||||
COMMAND_RECONFIG_STATUS,
|
||||
COMMAND_RSU_STATUS,
|
||||
/* for RSU */
|
||||
COMMAND_RSU_STATUS = 10,
|
||||
COMMAND_RSU_UPDATE,
|
||||
COMMAND_RSU_NOTIFY,
|
||||
COMMAND_RSU_RETRY,
|
||||
COMMAND_RSU_MAX_RETRY,
|
||||
COMMAND_RSU_DCMF_VERSION,
|
||||
COMMAND_RSU_DCMF_STATUS,
|
||||
COMMAND_FIRMWARE_VERSION,
|
||||
/* for FCS */
|
||||
COMMAND_FCS_REQUEST_SERVICE = 20,
|
||||
COMMAND_FCS_SEND_CERTIFICATE,
|
||||
COMMAND_FCS_GET_PROVISION_DATA,
|
||||
COMMAND_FCS_DATA_ENCRYPTION,
|
||||
COMMAND_FCS_DATA_DECRYPTION,
|
||||
COMMAND_FCS_RANDOM_NUMBER_GEN,
|
||||
/* for general status poll */
|
||||
COMMAND_POLL_SERVICE_STATUS = 40,
|
||||
/* Non-mailbox SMC Call */
|
||||
COMMAND_SMC_SVC_VERSION = 200,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct stratix10_svc_client_msg - message sent by client to service
|
||||
* @payload: starting address of data need be processed
|
||||
* @payload_length: data size in bytes
|
||||
* @payload_length: to be processed data size in bytes
|
||||
* @payload_output: starting address of processed data
|
||||
* @payload_length_output: processed data size in bytes
|
||||
* @command: service command
|
||||
* @arg: args to be passed via registers and not physically mapped buffers
|
||||
*/
|
||||
struct stratix10_svc_client_msg {
|
||||
void *payload;
|
||||
size_t payload_length;
|
||||
void *payload_output;
|
||||
size_t payload_length_output;
|
||||
enum stratix10_svc_command_code command;
|
||||
u64 arg[3];
|
||||
};
|
||||
|
|
|
|||
|
|
@ -71,12 +71,16 @@ static inline void register_trusted_foundations(
|
|||
|
||||
static inline void of_register_trusted_foundations(void)
|
||||
{
|
||||
struct device_node *np = of_find_compatible_node(NULL, NULL, "tlm,trusted-foundations");
|
||||
|
||||
if (!np)
|
||||
return;
|
||||
of_node_put(np);
|
||||
/*
|
||||
* If we find the target should enable TF but does not support it,
|
||||
* fail as the system won't be able to do much anyway
|
||||
*/
|
||||
if (of_find_compatible_node(NULL, NULL, "tlm,trusted-foundations"))
|
||||
register_trusted_foundations(NULL);
|
||||
register_trusted_foundations(NULL);
|
||||
}
|
||||
|
||||
static inline bool trusted_foundations_registered(void)
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@
|
|||
#define PM_API_VERSION_2 2
|
||||
|
||||
/* ATF only commands */
|
||||
#define TF_A_PM_REGISTER_SGI 0xa04
|
||||
#define PM_GET_TRUSTZONE_VERSION 0xa03
|
||||
#define PM_SET_SUSPEND_MODE 0xa02
|
||||
#define GET_CALLBACK_DATA 0xa01
|
||||
|
|
@ -368,6 +369,11 @@ enum pm_pinctrl_drive_strength {
|
|||
PM_PINCTRL_DRIVE_STRENGTH_12MA = 3,
|
||||
};
|
||||
|
||||
enum pm_pinctrl_tri_state {
|
||||
PM_PINCTRL_TRI_STATE_DISABLE = 0,
|
||||
PM_PINCTRL_TRI_STATE_ENABLE = 1,
|
||||
};
|
||||
|
||||
enum zynqmp_pm_shutdown_type {
|
||||
ZYNQMP_PM_SHUTDOWN_TYPE_SHUTDOWN = 0,
|
||||
ZYNQMP_PM_SHUTDOWN_TYPE_RESET = 1,
|
||||
|
|
@ -468,6 +474,7 @@ int zynqmp_pm_feature(const u32 api_id);
|
|||
int zynqmp_pm_is_function_supported(const u32 api_id, const u32 id);
|
||||
int zynqmp_pm_set_feature_config(enum pm_feature_config_id id, u32 value);
|
||||
int zynqmp_pm_get_feature_config(enum pm_feature_config_id id, u32 *payload);
|
||||
int zynqmp_pm_register_sgi(u32 sgi_num, u32 reset);
|
||||
#else
|
||||
static inline int zynqmp_pm_get_api_version(u32 *version)
|
||||
{
|
||||
|
|
@ -733,6 +740,11 @@ static inline int zynqmp_pm_get_feature_config(enum pm_feature_config_id id,
|
|||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static inline int zynqmp_pm_register_sgi(u32 sgi_num, u32 reset)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __FIRMWARE_ZYNQMP_H__ */
|
||||
|
|
|
|||
|
|
@ -22,6 +22,8 @@ struct sg_table;
|
|||
* @FPGA_MGR_STATE_RESET: FPGA in reset state
|
||||
* @FPGA_MGR_STATE_FIRMWARE_REQ: firmware request in progress
|
||||
* @FPGA_MGR_STATE_FIRMWARE_REQ_ERR: firmware request failed
|
||||
* @FPGA_MGR_STATE_PARSE_HEADER: parse FPGA image header
|
||||
* @FPGA_MGR_STATE_PARSE_HEADER_ERR: Error during PARSE_HEADER stage
|
||||
* @FPGA_MGR_STATE_WRITE_INIT: preparing FPGA for programming
|
||||
* @FPGA_MGR_STATE_WRITE_INIT_ERR: Error during WRITE_INIT stage
|
||||
* @FPGA_MGR_STATE_WRITE: writing image to FPGA
|
||||
|
|
@ -41,7 +43,9 @@ enum fpga_mgr_states {
|
|||
FPGA_MGR_STATE_FIRMWARE_REQ,
|
||||
FPGA_MGR_STATE_FIRMWARE_REQ_ERR,
|
||||
|
||||
/* write sequence: init, write, complete */
|
||||
/* write sequence: parse header, init, write, complete */
|
||||
FPGA_MGR_STATE_PARSE_HEADER,
|
||||
FPGA_MGR_STATE_PARSE_HEADER_ERR,
|
||||
FPGA_MGR_STATE_WRITE_INIT,
|
||||
FPGA_MGR_STATE_WRITE_INIT_ERR,
|
||||
FPGA_MGR_STATE_WRITE,
|
||||
|
|
@ -85,6 +89,9 @@ enum fpga_mgr_states {
|
|||
* @sgt: scatter/gather table containing FPGA image
|
||||
* @buf: contiguous buffer containing FPGA image
|
||||
* @count: size of buf
|
||||
* @header_size: size of image header.
|
||||
* @data_size: size of image data to be sent to the device. If not specified,
|
||||
* whole image will be used. Header may be skipped in either case.
|
||||
* @region_id: id of target region
|
||||
* @dev: device that owns this
|
||||
* @overlay: Device Tree overlay
|
||||
|
|
@ -98,6 +105,8 @@ struct fpga_image_info {
|
|||
struct sg_table *sgt;
|
||||
const char *buf;
|
||||
size_t count;
|
||||
size_t header_size;
|
||||
size_t data_size;
|
||||
int region_id;
|
||||
struct device *dev;
|
||||
#ifdef CONFIG_OF
|
||||
|
|
@ -137,9 +146,16 @@ struct fpga_manager_info {
|
|||
|
||||
/**
|
||||
* struct fpga_manager_ops - ops for low level fpga manager drivers
|
||||
* @initial_header_size: Maximum number of bytes that should be passed into write_init
|
||||
* @initial_header_size: minimum number of bytes that should be passed into
|
||||
* parse_header and write_init.
|
||||
* @skip_header: bool flag to tell fpga-mgr core whether it should skip
|
||||
* info->header_size part at the beginning of the image when invoking
|
||||
* write callback.
|
||||
* @state: returns an enum value of the FPGA's state
|
||||
* @status: returns status of the FPGA, including reconfiguration error code
|
||||
* @parse_header: parse FPGA image header to set info->header_size and
|
||||
* info->data_size. In case the input buffer is not large enough, set
|
||||
* required size to info->header_size and return -EAGAIN.
|
||||
* @write_init: prepare the FPGA to receive configuration data
|
||||
* @write: write count bytes of configuration data to the FPGA
|
||||
* @write_sg: write the scatter list of configuration data to the FPGA
|
||||
|
|
@ -153,8 +169,12 @@ struct fpga_manager_info {
|
|||
*/
|
||||
struct fpga_manager_ops {
|
||||
size_t initial_header_size;
|
||||
bool skip_header;
|
||||
enum fpga_mgr_states (*state)(struct fpga_manager *mgr);
|
||||
u64 (*status)(struct fpga_manager *mgr);
|
||||
int (*parse_header)(struct fpga_manager *mgr,
|
||||
struct fpga_image_info *info,
|
||||
const char *buf, size_t count);
|
||||
int (*write_init)(struct fpga_manager *mgr,
|
||||
struct fpga_image_info *info,
|
||||
const char *buf, size_t count);
|
||||
|
|
|
|||
|
|
@ -74,6 +74,7 @@ struct fsverity_operations;
|
|||
struct fs_context;
|
||||
struct fs_parameter_spec;
|
||||
struct fileattr;
|
||||
struct iomap_ops;
|
||||
|
||||
extern void __init inode_init(void);
|
||||
extern void __init inode_init_early(void);
|
||||
|
|
@ -180,6 +181,9 @@ typedef int (dio_iodone_t)(struct kiocb *iocb, loff_t offset,
|
|||
/* File supports async buffered reads */
|
||||
#define FMODE_BUF_RASYNC ((__force fmode_t)0x40000000)
|
||||
|
||||
/* File supports async nowait buffered writes */
|
||||
#define FMODE_BUF_WASYNC ((__force fmode_t)0x80000000)
|
||||
|
||||
/*
|
||||
* Attribute flags. These should be or-ed together to figure out what
|
||||
* has been changed!
|
||||
|
|
@ -336,17 +340,12 @@ enum rw_hint {
|
|||
|
||||
struct kiocb {
|
||||
struct file *ki_filp;
|
||||
|
||||
/* The 'ki_filp' pointer is shared in a union for aio */
|
||||
randomized_struct_fields_start
|
||||
|
||||
loff_t ki_pos;
|
||||
void (*ki_complete)(struct kiocb *iocb, long ret);
|
||||
void *private;
|
||||
int ki_flags;
|
||||
u16 ki_ioprio; /* See linux/ioprio.h */
|
||||
struct wait_page_queue *ki_waitq; /* for async buffered IO */
|
||||
randomized_struct_fields_end
|
||||
};
|
||||
|
||||
static inline bool is_sync_kiocb(struct kiocb *kiocb)
|
||||
|
|
@ -380,13 +379,11 @@ struct address_space_operations {
|
|||
void (*free_folio)(struct folio *folio);
|
||||
ssize_t (*direct_IO)(struct kiocb *, struct iov_iter *iter);
|
||||
/*
|
||||
* migrate the contents of a page to the specified target. If
|
||||
* migrate the contents of a folio to the specified target. If
|
||||
* migrate_mode is MIGRATE_ASYNC, it must not block.
|
||||
*/
|
||||
int (*migratepage) (struct address_space *,
|
||||
struct page *, struct page *, enum migrate_mode);
|
||||
bool (*isolate_page)(struct page *, isolate_mode_t);
|
||||
void (*putback_page)(struct page *);
|
||||
int (*migrate_folio)(struct address_space *, struct folio *dst,
|
||||
struct folio *src, enum migrate_mode);
|
||||
int (*launder_folio)(struct folio *);
|
||||
bool (*is_partially_uptodate) (struct folio *, size_t from,
|
||||
size_t count);
|
||||
|
|
@ -942,9 +939,10 @@ static inline int ra_has_index(struct file_ra_state *ra, pgoff_t index)
|
|||
|
||||
struct file {
|
||||
union {
|
||||
struct llist_node fu_llist;
|
||||
struct rcu_head fu_rcuhead;
|
||||
} f_u;
|
||||
struct llist_node f_llist;
|
||||
struct rcu_head f_rcuhead;
|
||||
unsigned int f_iocb_flags;
|
||||
};
|
||||
struct path f_path;
|
||||
struct inode *f_inode; /* cached value */
|
||||
const struct file_operations *f_op;
|
||||
|
|
@ -1430,6 +1428,7 @@ extern int send_sigurg(struct fown_struct *fown);
|
|||
#define SB_I_SKIP_SYNC 0x00000100 /* Skip superblock at global sync */
|
||||
#define SB_I_PERSB_BDI 0x00000200 /* has a per-sb bdi */
|
||||
#define SB_I_TS_EXPIRY_WARNED 0x00000400 /* warned about timestamp range expiry */
|
||||
#define SB_I_RETIRED 0x00000800 /* superblock shouldn't be reused */
|
||||
|
||||
/* Possible states of 'frozen' field */
|
||||
enum {
|
||||
|
|
@ -2031,6 +2030,8 @@ extern long compat_ptr_ioctl(struct file *file, unsigned int cmd,
|
|||
void inode_init_owner(struct user_namespace *mnt_userns, struct inode *inode,
|
||||
const struct inode *dir, umode_t mode);
|
||||
extern bool may_open_dev(const struct path *path);
|
||||
umode_t mode_strip_sgid(struct user_namespace *mnt_userns,
|
||||
const struct inode *dir, umode_t mode);
|
||||
|
||||
/*
|
||||
* This is the "filldir" function type, used by readdir() to let
|
||||
|
|
@ -2198,10 +2199,13 @@ extern ssize_t vfs_copy_file_range(struct file *, loff_t , struct file *,
|
|||
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,
|
||||
unsigned int remap_flags);
|
||||
int __generic_remap_file_range_prep(struct file *file_in, loff_t pos_in,
|
||||
struct file *file_out, loff_t pos_out,
|
||||
loff_t *len, unsigned int remap_flags,
|
||||
const struct iomap_ops *dax_read_ops);
|
||||
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, unsigned int remap_flags);
|
||||
extern loff_t do_clone_file_range(struct file *file_in, loff_t pos_in,
|
||||
struct file *file_out, loff_t pos_out,
|
||||
loff_t len, unsigned int remap_flags);
|
||||
|
|
@ -2327,13 +2331,11 @@ static inline bool HAS_UNMAPPED_ID(struct user_namespace *mnt_userns,
|
|||
!vfsgid_valid(i_gid_into_vfsgid(mnt_userns, inode));
|
||||
}
|
||||
|
||||
static inline int iocb_flags(struct file *file);
|
||||
|
||||
static inline void init_sync_kiocb(struct kiocb *kiocb, struct file *filp)
|
||||
{
|
||||
*kiocb = (struct kiocb) {
|
||||
.ki_filp = filp,
|
||||
.ki_flags = iocb_flags(filp),
|
||||
.ki_flags = filp->f_iocb_flags,
|
||||
.ki_ioprio = get_current_ioprio(),
|
||||
};
|
||||
}
|
||||
|
|
@ -2515,6 +2517,7 @@ static inline void file_accessed(struct file *file)
|
|||
}
|
||||
|
||||
extern int file_modified(struct file *file);
|
||||
int kiocb_modified(struct kiocb *iocb);
|
||||
|
||||
int sync_inode_metadata(struct inode *inode, int wait);
|
||||
|
||||
|
|
@ -2560,6 +2563,7 @@ extern struct dentry *mount_nodev(struct file_system_type *fs_type,
|
|||
int flags, void *data,
|
||||
int (*fill_super)(struct super_block *, void *, int));
|
||||
extern struct dentry *mount_subtree(struct vfsmount *mnt, const char *path);
|
||||
void retire_super(struct super_block *sb);
|
||||
void generic_shutdown_super(struct super_block *sb);
|
||||
void kill_block_super(struct super_block *sb);
|
||||
void kill_anon_super(struct super_block *sb);
|
||||
|
|
@ -2848,6 +2852,12 @@ extern int vfs_fsync(struct file *file, int datasync);
|
|||
extern int sync_file_range(struct file *file, loff_t offset, loff_t nbytes,
|
||||
unsigned int flags);
|
||||
|
||||
static inline bool iocb_is_dsync(const struct kiocb *iocb)
|
||||
{
|
||||
return (iocb->ki_flags & IOCB_DSYNC) ||
|
||||
IS_SYNC(iocb->ki_filp->f_mapping->host);
|
||||
}
|
||||
|
||||
/*
|
||||
* Sync the bytes written if this was a synchronous write. Expect ki_pos
|
||||
* to already be updated for the write, and will return either the amount
|
||||
|
|
@ -2855,7 +2865,7 @@ extern int sync_file_range(struct file *file, loff_t offset, loff_t nbytes,
|
|||
*/
|
||||
static inline ssize_t generic_write_sync(struct kiocb *iocb, ssize_t count)
|
||||
{
|
||||
if (iocb->ki_flags & IOCB_DSYNC) {
|
||||
if (iocb_is_dsync(iocb)) {
|
||||
int ret = vfs_fsync_range(iocb->ki_filp,
|
||||
iocb->ki_pos - count, iocb->ki_pos - 1,
|
||||
(iocb->ki_flags & IOCB_SYNC) ? 0 : 1);
|
||||
|
|
@ -3150,7 +3160,7 @@ extern long do_splice_direct(struct file *in, loff_t *ppos, struct file *out,
|
|||
extern void
|
||||
file_ra_state_init(struct file_ra_state *ra, struct address_space *mapping);
|
||||
extern loff_t noop_llseek(struct file *file, loff_t offset, int whence);
|
||||
extern loff_t no_llseek(struct file *file, loff_t offset, int whence);
|
||||
#define no_llseek NULL
|
||||
extern loff_t vfs_setpos(struct file *file, loff_t offset, loff_t maxsize);
|
||||
extern loff_t generic_file_llseek(struct file *file, loff_t offset, int whence);
|
||||
extern loff_t generic_file_llseek_size(struct file *file, loff_t offset,
|
||||
|
|
@ -3343,18 +3353,6 @@ extern int generic_check_addressable(unsigned, u64);
|
|||
|
||||
extern void generic_set_encrypted_ci_d_ops(struct dentry *dentry);
|
||||
|
||||
#ifdef CONFIG_MIGRATION
|
||||
extern int buffer_migrate_page(struct address_space *,
|
||||
struct page *, struct page *,
|
||||
enum migrate_mode);
|
||||
extern int buffer_migrate_page_norefs(struct address_space *,
|
||||
struct page *, struct page *,
|
||||
enum migrate_mode);
|
||||
#else
|
||||
#define buffer_migrate_page NULL
|
||||
#define buffer_migrate_page_norefs NULL
|
||||
#endif
|
||||
|
||||
int may_setattr(struct user_namespace *mnt_userns, struct inode *inode,
|
||||
unsigned int ia_valid);
|
||||
int setattr_prepare(struct user_namespace *, struct dentry *, struct iattr *);
|
||||
|
|
@ -3390,7 +3388,7 @@ static inline int iocb_flags(struct file *file)
|
|||
res |= IOCB_APPEND;
|
||||
if (file->f_flags & O_DIRECT)
|
||||
res |= IOCB_DIRECT;
|
||||
if ((file->f_flags & O_DSYNC) || IS_SYNC(file->f_mapping->host))
|
||||
if (file->f_flags & O_DSYNC)
|
||||
res |= IOCB_DSYNC;
|
||||
if (file->f_flags & __O_SYNC)
|
||||
res |= IOCB_SYNC;
|
||||
|
|
|
|||
|
|
@ -258,7 +258,7 @@ struct fscache_cookie *fscache_acquire_cookie(struct fscache_volume *volume,
|
|||
|
||||
/**
|
||||
* fscache_use_cookie - Request usage of cookie attached to an object
|
||||
* @object: Object description
|
||||
* @cookie: The cookie representing the cache object
|
||||
* @will_modify: If cache is expected to be modified locally
|
||||
*
|
||||
* Request usage of the cookie attached to an object. The caller should tell
|
||||
|
|
@ -274,7 +274,7 @@ static inline void fscache_use_cookie(struct fscache_cookie *cookie,
|
|||
|
||||
/**
|
||||
* fscache_unuse_cookie - Cease usage of cookie attached to an object
|
||||
* @object: Object description
|
||||
* @cookie: The cookie representing the cache object
|
||||
* @aux_data: Updated auxiliary data (or NULL)
|
||||
* @object_size: Revised size of the object (or NULL)
|
||||
*
|
||||
|
|
@ -379,7 +379,7 @@ void fscache_update_cookie(struct fscache_cookie *cookie, const void *aux_data,
|
|||
*
|
||||
* Request that the size of an object be changed.
|
||||
*
|
||||
* See Documentation/filesystems/caching/netfs-api.txt for a complete
|
||||
* See Documentation/filesystems/caching/netfs-api.rst for a complete
|
||||
* description.
|
||||
*/
|
||||
static inline
|
||||
|
|
|
|||
|
|
@ -284,6 +284,7 @@ int fscrypt_ioctl_get_policy(struct file *filp, void __user *arg);
|
|||
int fscrypt_ioctl_get_policy_ex(struct file *filp, void __user *arg);
|
||||
int fscrypt_ioctl_get_nonce(struct file *filp, void __user *arg);
|
||||
int fscrypt_has_permitted_context(struct inode *parent, struct inode *child);
|
||||
int fscrypt_context_for_new_inode(void *ctx, struct inode *inode);
|
||||
int fscrypt_set_context(struct inode *inode, void *fs_data);
|
||||
|
||||
struct fscrypt_dummy_policy {
|
||||
|
|
@ -327,6 +328,10 @@ void fscrypt_free_inode(struct inode *inode);
|
|||
int fscrypt_drop_inode(struct inode *inode);
|
||||
|
||||
/* fname.c */
|
||||
int fscrypt_fname_encrypt(const struct inode *inode, const struct qstr *iname,
|
||||
u8 *out, unsigned int olen);
|
||||
bool fscrypt_fname_encrypted_size(const struct inode *inode, u32 orig_len,
|
||||
u32 max_len, u32 *encrypted_len_ret);
|
||||
int fscrypt_setup_filename(struct inode *inode, const struct qstr *iname,
|
||||
int lookup, struct fscrypt_name *fname);
|
||||
|
||||
|
|
|
|||
|
|
@ -208,6 +208,43 @@ enum {
|
|||
FTRACE_OPS_FL_DIRECT = BIT(17),
|
||||
};
|
||||
|
||||
/*
|
||||
* FTRACE_OPS_CMD_* commands allow the ftrace core logic to request changes
|
||||
* to a ftrace_ops. Note, the requests may fail.
|
||||
*
|
||||
* ENABLE_SHARE_IPMODIFY_SELF - enable a DIRECT ops to work on the same
|
||||
* function as an ops with IPMODIFY. Called
|
||||
* when the DIRECT ops is being registered.
|
||||
* This is called with both direct_mutex and
|
||||
* ftrace_lock are locked.
|
||||
*
|
||||
* ENABLE_SHARE_IPMODIFY_PEER - enable a DIRECT ops to work on the same
|
||||
* function as an ops with IPMODIFY. Called
|
||||
* when the other ops (the one with IPMODIFY)
|
||||
* is being registered.
|
||||
* This is called with direct_mutex locked.
|
||||
*
|
||||
* DISABLE_SHARE_IPMODIFY_PEER - disable a DIRECT ops to work on the same
|
||||
* function as an ops with IPMODIFY. Called
|
||||
* when the other ops (the one with IPMODIFY)
|
||||
* is being unregistered.
|
||||
* This is called with direct_mutex locked.
|
||||
*/
|
||||
enum ftrace_ops_cmd {
|
||||
FTRACE_OPS_CMD_ENABLE_SHARE_IPMODIFY_SELF,
|
||||
FTRACE_OPS_CMD_ENABLE_SHARE_IPMODIFY_PEER,
|
||||
FTRACE_OPS_CMD_DISABLE_SHARE_IPMODIFY_PEER,
|
||||
};
|
||||
|
||||
/*
|
||||
* For most ftrace_ops_cmd,
|
||||
* Returns:
|
||||
* 0 - Success.
|
||||
* Negative on failure. The return value is dependent on the
|
||||
* callback.
|
||||
*/
|
||||
typedef int (*ftrace_ops_func_t)(struct ftrace_ops *op, enum ftrace_ops_cmd cmd);
|
||||
|
||||
#ifdef CONFIG_DYNAMIC_FTRACE
|
||||
/* The hash used to know what functions callbacks trace */
|
||||
struct ftrace_ops_hash {
|
||||
|
|
@ -250,6 +287,7 @@ struct ftrace_ops {
|
|||
unsigned long trampoline;
|
||||
unsigned long trampoline_size;
|
||||
struct list_head list;
|
||||
ftrace_ops_func_t ops_func;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
|
@ -340,6 +378,7 @@ unsigned long ftrace_find_rec_direct(unsigned long ip);
|
|||
int register_ftrace_direct_multi(struct ftrace_ops *ops, unsigned long addr);
|
||||
int unregister_ftrace_direct_multi(struct ftrace_ops *ops, unsigned long addr);
|
||||
int modify_ftrace_direct_multi(struct ftrace_ops *ops, unsigned long addr);
|
||||
int modify_ftrace_direct_multi_nolock(struct ftrace_ops *ops, unsigned long addr);
|
||||
|
||||
#else
|
||||
struct ftrace_ops;
|
||||
|
|
@ -384,6 +423,10 @@ static inline int modify_ftrace_direct_multi(struct ftrace_ops *ops, unsigned lo
|
|||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
static inline int modify_ftrace_direct_multi_nolock(struct ftrace_ops *ops, unsigned long addr)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
#endif /* CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS */
|
||||
|
||||
#ifndef CONFIG_HAVE_DYNAMIC_FTRACE_WITH_DIRECT_CALLS
|
||||
|
|
|
|||
|
|
@ -27,11 +27,15 @@ struct device;
|
|||
* driver needs its child devices to be bound with
|
||||
* their respective drivers as soon as they are
|
||||
* added.
|
||||
* BEST_EFFORT: The fwnode/device needs to probe early and might be missing some
|
||||
* suppliers. Only enforce ordering with suppliers that have
|
||||
* drivers.
|
||||
*/
|
||||
#define FWNODE_FLAG_LINKS_ADDED BIT(0)
|
||||
#define FWNODE_FLAG_NOT_DEVICE BIT(1)
|
||||
#define FWNODE_FLAG_INITIALIZED BIT(2)
|
||||
#define FWNODE_FLAG_NEEDS_CHILD_BOUND_ON_ADD BIT(3)
|
||||
#define FWNODE_FLAG_BEST_EFFORT BIT(4)
|
||||
|
||||
struct fwnode_handle {
|
||||
struct fwnode_handle *secondary;
|
||||
|
|
|
|||
|
|
@ -2,357 +2,13 @@
|
|||
#ifndef __LINUX_GFP_H
|
||||
#define __LINUX_GFP_H
|
||||
|
||||
#include <linux/mmdebug.h>
|
||||
#include <linux/gfp_types.h>
|
||||
|
||||
#include <linux/mmzone.h>
|
||||
#include <linux/stddef.h>
|
||||
#include <linux/linkage.h>
|
||||
#include <linux/topology.h>
|
||||
|
||||
/* The typedef is in types.h but we want the documentation here */
|
||||
#if 0
|
||||
/**
|
||||
* typedef gfp_t - Memory allocation flags.
|
||||
*
|
||||
* GFP flags are commonly used throughout Linux to indicate how memory
|
||||
* should be allocated. The GFP acronym stands for get_free_pages(),
|
||||
* the underlying memory allocation function. Not every GFP flag is
|
||||
* supported by every function which may allocate memory. Most users
|
||||
* will want to use a plain ``GFP_KERNEL``.
|
||||
*/
|
||||
typedef unsigned int __bitwise gfp_t;
|
||||
#endif
|
||||
|
||||
struct vm_area_struct;
|
||||
|
||||
/*
|
||||
* In case of changes, please don't forget to update
|
||||
* include/trace/events/mmflags.h and tools/perf/builtin-kmem.c
|
||||
*/
|
||||
|
||||
/* Plain integer GFP bitmasks. Do not use this directly. */
|
||||
#define ___GFP_DMA 0x01u
|
||||
#define ___GFP_HIGHMEM 0x02u
|
||||
#define ___GFP_DMA32 0x04u
|
||||
#define ___GFP_MOVABLE 0x08u
|
||||
#define ___GFP_RECLAIMABLE 0x10u
|
||||
#define ___GFP_HIGH 0x20u
|
||||
#define ___GFP_IO 0x40u
|
||||
#define ___GFP_FS 0x80u
|
||||
#define ___GFP_ZERO 0x100u
|
||||
#define ___GFP_ATOMIC 0x200u
|
||||
#define ___GFP_DIRECT_RECLAIM 0x400u
|
||||
#define ___GFP_KSWAPD_RECLAIM 0x800u
|
||||
#define ___GFP_WRITE 0x1000u
|
||||
#define ___GFP_NOWARN 0x2000u
|
||||
#define ___GFP_RETRY_MAYFAIL 0x4000u
|
||||
#define ___GFP_NOFAIL 0x8000u
|
||||
#define ___GFP_NORETRY 0x10000u
|
||||
#define ___GFP_MEMALLOC 0x20000u
|
||||
#define ___GFP_COMP 0x40000u
|
||||
#define ___GFP_NOMEMALLOC 0x80000u
|
||||
#define ___GFP_HARDWALL 0x100000u
|
||||
#define ___GFP_THISNODE 0x200000u
|
||||
#define ___GFP_ACCOUNT 0x400000u
|
||||
#define ___GFP_ZEROTAGS 0x800000u
|
||||
#ifdef CONFIG_KASAN_HW_TAGS
|
||||
#define ___GFP_SKIP_ZERO 0x1000000u
|
||||
#define ___GFP_SKIP_KASAN_UNPOISON 0x2000000u
|
||||
#define ___GFP_SKIP_KASAN_POISON 0x4000000u
|
||||
#else
|
||||
#define ___GFP_SKIP_ZERO 0
|
||||
#define ___GFP_SKIP_KASAN_UNPOISON 0
|
||||
#define ___GFP_SKIP_KASAN_POISON 0
|
||||
#endif
|
||||
#ifdef CONFIG_LOCKDEP
|
||||
#define ___GFP_NOLOCKDEP 0x8000000u
|
||||
#else
|
||||
#define ___GFP_NOLOCKDEP 0
|
||||
#endif
|
||||
/* If the above are modified, __GFP_BITS_SHIFT may need updating */
|
||||
|
||||
/*
|
||||
* Physical address zone modifiers (see linux/mmzone.h - low four bits)
|
||||
*
|
||||
* Do not put any conditional on these. If necessary modify the definitions
|
||||
* without the underscores and use them consistently. The definitions here may
|
||||
* be used in bit comparisons.
|
||||
*/
|
||||
#define __GFP_DMA ((__force gfp_t)___GFP_DMA)
|
||||
#define __GFP_HIGHMEM ((__force gfp_t)___GFP_HIGHMEM)
|
||||
#define __GFP_DMA32 ((__force gfp_t)___GFP_DMA32)
|
||||
#define __GFP_MOVABLE ((__force gfp_t)___GFP_MOVABLE) /* ZONE_MOVABLE allowed */
|
||||
#define GFP_ZONEMASK (__GFP_DMA|__GFP_HIGHMEM|__GFP_DMA32|__GFP_MOVABLE)
|
||||
|
||||
/**
|
||||
* DOC: Page mobility and placement hints
|
||||
*
|
||||
* Page mobility and placement hints
|
||||
* ---------------------------------
|
||||
*
|
||||
* These flags provide hints about how mobile the page is. Pages with similar
|
||||
* mobility are placed within the same pageblocks to minimise problems due
|
||||
* to external fragmentation.
|
||||
*
|
||||
* %__GFP_MOVABLE (also a zone modifier) indicates that the page can be
|
||||
* moved by page migration during memory compaction or can be reclaimed.
|
||||
*
|
||||
* %__GFP_RECLAIMABLE is used for slab allocations that specify
|
||||
* SLAB_RECLAIM_ACCOUNT and whose pages can be freed via shrinkers.
|
||||
*
|
||||
* %__GFP_WRITE indicates the caller intends to dirty the page. Where possible,
|
||||
* these pages will be spread between local zones to avoid all the dirty
|
||||
* pages being in one zone (fair zone allocation policy).
|
||||
*
|
||||
* %__GFP_HARDWALL enforces the cpuset memory allocation policy.
|
||||
*
|
||||
* %__GFP_THISNODE forces the allocation to be satisfied from the requested
|
||||
* node with no fallbacks or placement policy enforcements.
|
||||
*
|
||||
* %__GFP_ACCOUNT causes the allocation to be accounted to kmemcg.
|
||||
*/
|
||||
#define __GFP_RECLAIMABLE ((__force gfp_t)___GFP_RECLAIMABLE)
|
||||
#define __GFP_WRITE ((__force gfp_t)___GFP_WRITE)
|
||||
#define __GFP_HARDWALL ((__force gfp_t)___GFP_HARDWALL)
|
||||
#define __GFP_THISNODE ((__force gfp_t)___GFP_THISNODE)
|
||||
#define __GFP_ACCOUNT ((__force gfp_t)___GFP_ACCOUNT)
|
||||
|
||||
/**
|
||||
* DOC: Watermark modifiers
|
||||
*
|
||||
* Watermark modifiers -- controls access to emergency reserves
|
||||
* ------------------------------------------------------------
|
||||
*
|
||||
* %__GFP_HIGH indicates that the caller is high-priority and that granting
|
||||
* the request is necessary before the system can make forward progress.
|
||||
* For example, creating an IO context to clean pages.
|
||||
*
|
||||
* %__GFP_ATOMIC indicates that the caller cannot reclaim or sleep and is
|
||||
* high priority. Users are typically interrupt handlers. This may be
|
||||
* used in conjunction with %__GFP_HIGH
|
||||
*
|
||||
* %__GFP_MEMALLOC allows access to all memory. This should only be used when
|
||||
* the caller guarantees the allocation will allow more memory to be freed
|
||||
* very shortly e.g. process exiting or swapping. Users either should
|
||||
* be the MM or co-ordinating closely with the VM (e.g. swap over NFS).
|
||||
* Users of this flag have to be extremely careful to not deplete the reserve
|
||||
* completely and implement a throttling mechanism which controls the
|
||||
* consumption of the reserve based on the amount of freed memory.
|
||||
* Usage of a pre-allocated pool (e.g. mempool) should be always considered
|
||||
* before using this flag.
|
||||
*
|
||||
* %__GFP_NOMEMALLOC is used to explicitly forbid access to emergency reserves.
|
||||
* This takes precedence over the %__GFP_MEMALLOC flag if both are set.
|
||||
*/
|
||||
#define __GFP_ATOMIC ((__force gfp_t)___GFP_ATOMIC)
|
||||
#define __GFP_HIGH ((__force gfp_t)___GFP_HIGH)
|
||||
#define __GFP_MEMALLOC ((__force gfp_t)___GFP_MEMALLOC)
|
||||
#define __GFP_NOMEMALLOC ((__force gfp_t)___GFP_NOMEMALLOC)
|
||||
|
||||
/**
|
||||
* DOC: Reclaim modifiers
|
||||
*
|
||||
* Reclaim modifiers
|
||||
* -----------------
|
||||
* Please note that all the following flags are only applicable to sleepable
|
||||
* allocations (e.g. %GFP_NOWAIT and %GFP_ATOMIC will ignore them).
|
||||
*
|
||||
* %__GFP_IO can start physical IO.
|
||||
*
|
||||
* %__GFP_FS can call down to the low-level FS. Clearing the flag avoids the
|
||||
* allocator recursing into the filesystem which might already be holding
|
||||
* locks.
|
||||
*
|
||||
* %__GFP_DIRECT_RECLAIM indicates that the caller may enter direct reclaim.
|
||||
* This flag can be cleared to avoid unnecessary delays when a fallback
|
||||
* option is available.
|
||||
*
|
||||
* %__GFP_KSWAPD_RECLAIM indicates that the caller wants to wake kswapd when
|
||||
* the low watermark is reached and have it reclaim pages until the high
|
||||
* watermark is reached. A caller may wish to clear this flag when fallback
|
||||
* options are available and the reclaim is likely to disrupt the system. The
|
||||
* canonical example is THP allocation where a fallback is cheap but
|
||||
* reclaim/compaction may cause indirect stalls.
|
||||
*
|
||||
* %__GFP_RECLAIM is shorthand to allow/forbid both direct and kswapd reclaim.
|
||||
*
|
||||
* The default allocator behavior depends on the request size. We have a concept
|
||||
* of so called costly allocations (with order > %PAGE_ALLOC_COSTLY_ORDER).
|
||||
* !costly allocations are too essential to fail so they are implicitly
|
||||
* non-failing by default (with some exceptions like OOM victims might fail so
|
||||
* the caller still has to check for failures) while costly requests try to be
|
||||
* not disruptive and back off even without invoking the OOM killer.
|
||||
* The following three modifiers might be used to override some of these
|
||||
* implicit rules
|
||||
*
|
||||
* %__GFP_NORETRY: The VM implementation will try only very lightweight
|
||||
* memory direct reclaim to get some memory under memory pressure (thus
|
||||
* it can sleep). It will avoid disruptive actions like OOM killer. The
|
||||
* caller must handle the failure which is quite likely to happen under
|
||||
* heavy memory pressure. The flag is suitable when failure can easily be
|
||||
* handled at small cost, such as reduced throughput
|
||||
*
|
||||
* %__GFP_RETRY_MAYFAIL: The VM implementation will retry memory reclaim
|
||||
* procedures that have previously failed if there is some indication
|
||||
* that progress has been made else where. It can wait for other
|
||||
* tasks to attempt high level approaches to freeing memory such as
|
||||
* compaction (which removes fragmentation) and page-out.
|
||||
* There is still a definite limit to the number of retries, but it is
|
||||
* a larger limit than with %__GFP_NORETRY.
|
||||
* Allocations with this flag may fail, but only when there is
|
||||
* genuinely little unused memory. While these allocations do not
|
||||
* directly trigger the OOM killer, their failure indicates that
|
||||
* the system is likely to need to use the OOM killer soon. The
|
||||
* caller must handle failure, but can reasonably do so by failing
|
||||
* a higher-level request, or completing it only in a much less
|
||||
* efficient manner.
|
||||
* If the allocation does fail, and the caller is in a position to
|
||||
* free some non-essential memory, doing so could benefit the system
|
||||
* as a whole.
|
||||
*
|
||||
* %__GFP_NOFAIL: The VM implementation _must_ retry infinitely: the caller
|
||||
* cannot handle allocation failures. The allocation could block
|
||||
* indefinitely but will never return with failure. Testing for
|
||||
* failure is pointless.
|
||||
* New users should be evaluated carefully (and the flag should be
|
||||
* used only when there is no reasonable failure policy) but it is
|
||||
* definitely preferable to use the flag rather than opencode endless
|
||||
* loop around allocator.
|
||||
* Using this flag for costly allocations is _highly_ discouraged.
|
||||
*/
|
||||
#define __GFP_IO ((__force gfp_t)___GFP_IO)
|
||||
#define __GFP_FS ((__force gfp_t)___GFP_FS)
|
||||
#define __GFP_DIRECT_RECLAIM ((__force gfp_t)___GFP_DIRECT_RECLAIM) /* Caller can reclaim */
|
||||
#define __GFP_KSWAPD_RECLAIM ((__force gfp_t)___GFP_KSWAPD_RECLAIM) /* kswapd can wake */
|
||||
#define __GFP_RECLAIM ((__force gfp_t)(___GFP_DIRECT_RECLAIM|___GFP_KSWAPD_RECLAIM))
|
||||
#define __GFP_RETRY_MAYFAIL ((__force gfp_t)___GFP_RETRY_MAYFAIL)
|
||||
#define __GFP_NOFAIL ((__force gfp_t)___GFP_NOFAIL)
|
||||
#define __GFP_NORETRY ((__force gfp_t)___GFP_NORETRY)
|
||||
|
||||
/**
|
||||
* DOC: Action modifiers
|
||||
*
|
||||
* Action modifiers
|
||||
* ----------------
|
||||
*
|
||||
* %__GFP_NOWARN suppresses allocation failure reports.
|
||||
*
|
||||
* %__GFP_COMP address compound page metadata.
|
||||
*
|
||||
* %__GFP_ZERO returns a zeroed page on success.
|
||||
*
|
||||
* %__GFP_ZEROTAGS zeroes memory tags at allocation time if the memory itself
|
||||
* is being zeroed (either via __GFP_ZERO or via init_on_alloc, provided that
|
||||
* __GFP_SKIP_ZERO is not set). This flag is intended for optimization: setting
|
||||
* memory tags at the same time as zeroing memory has minimal additional
|
||||
* performace impact.
|
||||
*
|
||||
* %__GFP_SKIP_KASAN_UNPOISON makes KASAN skip unpoisoning on page allocation.
|
||||
* Only effective in HW_TAGS mode.
|
||||
*
|
||||
* %__GFP_SKIP_KASAN_POISON makes KASAN skip poisoning on page deallocation.
|
||||
* Typically, used for userspace pages. Only effective in HW_TAGS mode.
|
||||
*/
|
||||
#define __GFP_NOWARN ((__force gfp_t)___GFP_NOWARN)
|
||||
#define __GFP_COMP ((__force gfp_t)___GFP_COMP)
|
||||
#define __GFP_ZERO ((__force gfp_t)___GFP_ZERO)
|
||||
#define __GFP_ZEROTAGS ((__force gfp_t)___GFP_ZEROTAGS)
|
||||
#define __GFP_SKIP_ZERO ((__force gfp_t)___GFP_SKIP_ZERO)
|
||||
#define __GFP_SKIP_KASAN_UNPOISON ((__force gfp_t)___GFP_SKIP_KASAN_UNPOISON)
|
||||
#define __GFP_SKIP_KASAN_POISON ((__force gfp_t)___GFP_SKIP_KASAN_POISON)
|
||||
|
||||
/* Disable lockdep for GFP context tracking */
|
||||
#define __GFP_NOLOCKDEP ((__force gfp_t)___GFP_NOLOCKDEP)
|
||||
|
||||
/* Room for N __GFP_FOO bits */
|
||||
#define __GFP_BITS_SHIFT (27 + IS_ENABLED(CONFIG_LOCKDEP))
|
||||
#define __GFP_BITS_MASK ((__force gfp_t)((1 << __GFP_BITS_SHIFT) - 1))
|
||||
|
||||
/**
|
||||
* DOC: Useful GFP flag combinations
|
||||
*
|
||||
* Useful GFP flag combinations
|
||||
* ----------------------------
|
||||
*
|
||||
* Useful GFP flag combinations that are commonly used. It is recommended
|
||||
* that subsystems start with one of these combinations and then set/clear
|
||||
* %__GFP_FOO flags as necessary.
|
||||
*
|
||||
* %GFP_ATOMIC users can not sleep and need the allocation to succeed. A lower
|
||||
* watermark is applied to allow access to "atomic reserves".
|
||||
* The current implementation doesn't support NMI and few other strict
|
||||
* non-preemptive contexts (e.g. raw_spin_lock). The same applies to %GFP_NOWAIT.
|
||||
*
|
||||
* %GFP_KERNEL is typical for kernel-internal allocations. The caller requires
|
||||
* %ZONE_NORMAL or a lower zone for direct access but can direct reclaim.
|
||||
*
|
||||
* %GFP_KERNEL_ACCOUNT is the same as GFP_KERNEL, except the allocation is
|
||||
* accounted to kmemcg.
|
||||
*
|
||||
* %GFP_NOWAIT is for kernel allocations that should not stall for direct
|
||||
* reclaim, start physical IO or use any filesystem callback.
|
||||
*
|
||||
* %GFP_NOIO will use direct reclaim to discard clean pages or slab pages
|
||||
* that do not require the starting of any physical IO.
|
||||
* Please try to avoid using this flag directly and instead use
|
||||
* memalloc_noio_{save,restore} to mark the whole scope which cannot
|
||||
* perform any IO with a short explanation why. All allocation requests
|
||||
* will inherit GFP_NOIO implicitly.
|
||||
*
|
||||
* %GFP_NOFS will use direct reclaim but will not use any filesystem interfaces.
|
||||
* Please try to avoid using this flag directly and instead use
|
||||
* memalloc_nofs_{save,restore} to mark the whole scope which cannot/shouldn't
|
||||
* recurse into the FS layer with a short explanation why. All allocation
|
||||
* requests will inherit GFP_NOFS implicitly.
|
||||
*
|
||||
* %GFP_USER is for userspace allocations that also need to be directly
|
||||
* accessibly by the kernel or hardware. It is typically used by hardware
|
||||
* for buffers that are mapped to userspace (e.g. graphics) that hardware
|
||||
* still must DMA to. cpuset limits are enforced for these allocations.
|
||||
*
|
||||
* %GFP_DMA exists for historical reasons and should be avoided where possible.
|
||||
* The flags indicates that the caller requires that the lowest zone be
|
||||
* used (%ZONE_DMA or 16M on x86-64). Ideally, this would be removed but
|
||||
* it would require careful auditing as some users really require it and
|
||||
* others use the flag to avoid lowmem reserves in %ZONE_DMA and treat the
|
||||
* lowest zone as a type of emergency reserve.
|
||||
*
|
||||
* %GFP_DMA32 is similar to %GFP_DMA except that the caller requires a 32-bit
|
||||
* address. Note that kmalloc(..., GFP_DMA32) does not return DMA32 memory
|
||||
* because the DMA32 kmalloc cache array is not implemented.
|
||||
* (Reason: there is no such user in kernel).
|
||||
*
|
||||
* %GFP_HIGHUSER is for userspace allocations that may be mapped to userspace,
|
||||
* do not need to be directly accessible by the kernel but that cannot
|
||||
* move once in use. An example may be a hardware allocation that maps
|
||||
* data directly into userspace but has no addressing limitations.
|
||||
*
|
||||
* %GFP_HIGHUSER_MOVABLE is for userspace allocations that the kernel does not
|
||||
* need direct access to but can use kmap() when access is required. They
|
||||
* are expected to be movable via page reclaim or page migration. Typically,
|
||||
* pages on the LRU would also be allocated with %GFP_HIGHUSER_MOVABLE.
|
||||
*
|
||||
* %GFP_TRANSHUGE and %GFP_TRANSHUGE_LIGHT are used for THP allocations. They
|
||||
* are compound allocations that will generally fail quickly if memory is not
|
||||
* available and will not wake kswapd/kcompactd on failure. The _LIGHT
|
||||
* version does not attempt reclaim/compaction at all and is by default used
|
||||
* in page fault path, while the non-light is used by khugepaged.
|
||||
*/
|
||||
#define GFP_ATOMIC (__GFP_HIGH|__GFP_ATOMIC|__GFP_KSWAPD_RECLAIM)
|
||||
#define GFP_KERNEL (__GFP_RECLAIM | __GFP_IO | __GFP_FS)
|
||||
#define GFP_KERNEL_ACCOUNT (GFP_KERNEL | __GFP_ACCOUNT)
|
||||
#define GFP_NOWAIT (__GFP_KSWAPD_RECLAIM)
|
||||
#define GFP_NOIO (__GFP_RECLAIM)
|
||||
#define GFP_NOFS (__GFP_RECLAIM | __GFP_IO)
|
||||
#define GFP_USER (__GFP_RECLAIM | __GFP_IO | __GFP_FS | __GFP_HARDWALL)
|
||||
#define GFP_DMA __GFP_DMA
|
||||
#define GFP_DMA32 __GFP_DMA32
|
||||
#define GFP_HIGHUSER (GFP_USER | __GFP_HIGHMEM)
|
||||
#define GFP_HIGHUSER_MOVABLE (GFP_HIGHUSER | __GFP_MOVABLE | \
|
||||
__GFP_SKIP_KASAN_POISON | __GFP_SKIP_KASAN_UNPOISON)
|
||||
#define GFP_TRANSHUGE_LIGHT ((GFP_HIGHUSER_MOVABLE | __GFP_COMP | \
|
||||
__GFP_NOMEMALLOC | __GFP_NOWARN) & ~__GFP_RECLAIM)
|
||||
#define GFP_TRANSHUGE (GFP_TRANSHUGE_LIGHT | __GFP_DIRECT_RECLAIM)
|
||||
|
||||
/* Convert GFP flags to their corresponding migrate type */
|
||||
#define GFP_MOVABLE_MASK (__GFP_RECLAIMABLE|__GFP_MOVABLE)
|
||||
#define GFP_MOVABLE_SHIFT 3
|
||||
|
|
|
|||
348
include/linux/gfp_types.h
Normal file
348
include/linux/gfp_types.h
Normal file
|
|
@ -0,0 +1,348 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef __LINUX_GFP_TYPES_H
|
||||
#define __LINUX_GFP_TYPES_H
|
||||
|
||||
/* The typedef is in types.h but we want the documentation here */
|
||||
#if 0
|
||||
/**
|
||||
* typedef gfp_t - Memory allocation flags.
|
||||
*
|
||||
* GFP flags are commonly used throughout Linux to indicate how memory
|
||||
* should be allocated. The GFP acronym stands for get_free_pages(),
|
||||
* the underlying memory allocation function. Not every GFP flag is
|
||||
* supported by every function which may allocate memory. Most users
|
||||
* will want to use a plain ``GFP_KERNEL``.
|
||||
*/
|
||||
typedef unsigned int __bitwise gfp_t;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* In case of changes, please don't forget to update
|
||||
* include/trace/events/mmflags.h and tools/perf/builtin-kmem.c
|
||||
*/
|
||||
|
||||
/* Plain integer GFP bitmasks. Do not use this directly. */
|
||||
#define ___GFP_DMA 0x01u
|
||||
#define ___GFP_HIGHMEM 0x02u
|
||||
#define ___GFP_DMA32 0x04u
|
||||
#define ___GFP_MOVABLE 0x08u
|
||||
#define ___GFP_RECLAIMABLE 0x10u
|
||||
#define ___GFP_HIGH 0x20u
|
||||
#define ___GFP_IO 0x40u
|
||||
#define ___GFP_FS 0x80u
|
||||
#define ___GFP_ZERO 0x100u
|
||||
#define ___GFP_ATOMIC 0x200u
|
||||
#define ___GFP_DIRECT_RECLAIM 0x400u
|
||||
#define ___GFP_KSWAPD_RECLAIM 0x800u
|
||||
#define ___GFP_WRITE 0x1000u
|
||||
#define ___GFP_NOWARN 0x2000u
|
||||
#define ___GFP_RETRY_MAYFAIL 0x4000u
|
||||
#define ___GFP_NOFAIL 0x8000u
|
||||
#define ___GFP_NORETRY 0x10000u
|
||||
#define ___GFP_MEMALLOC 0x20000u
|
||||
#define ___GFP_COMP 0x40000u
|
||||
#define ___GFP_NOMEMALLOC 0x80000u
|
||||
#define ___GFP_HARDWALL 0x100000u
|
||||
#define ___GFP_THISNODE 0x200000u
|
||||
#define ___GFP_ACCOUNT 0x400000u
|
||||
#define ___GFP_ZEROTAGS 0x800000u
|
||||
#ifdef CONFIG_KASAN_HW_TAGS
|
||||
#define ___GFP_SKIP_ZERO 0x1000000u
|
||||
#define ___GFP_SKIP_KASAN_UNPOISON 0x2000000u
|
||||
#define ___GFP_SKIP_KASAN_POISON 0x4000000u
|
||||
#else
|
||||
#define ___GFP_SKIP_ZERO 0
|
||||
#define ___GFP_SKIP_KASAN_UNPOISON 0
|
||||
#define ___GFP_SKIP_KASAN_POISON 0
|
||||
#endif
|
||||
#ifdef CONFIG_LOCKDEP
|
||||
#define ___GFP_NOLOCKDEP 0x8000000u
|
||||
#else
|
||||
#define ___GFP_NOLOCKDEP 0
|
||||
#endif
|
||||
/* If the above are modified, __GFP_BITS_SHIFT may need updating */
|
||||
|
||||
/*
|
||||
* Physical address zone modifiers (see linux/mmzone.h - low four bits)
|
||||
*
|
||||
* Do not put any conditional on these. If necessary modify the definitions
|
||||
* without the underscores and use them consistently. The definitions here may
|
||||
* be used in bit comparisons.
|
||||
*/
|
||||
#define __GFP_DMA ((__force gfp_t)___GFP_DMA)
|
||||
#define __GFP_HIGHMEM ((__force gfp_t)___GFP_HIGHMEM)
|
||||
#define __GFP_DMA32 ((__force gfp_t)___GFP_DMA32)
|
||||
#define __GFP_MOVABLE ((__force gfp_t)___GFP_MOVABLE) /* ZONE_MOVABLE allowed */
|
||||
#define GFP_ZONEMASK (__GFP_DMA|__GFP_HIGHMEM|__GFP_DMA32|__GFP_MOVABLE)
|
||||
|
||||
/**
|
||||
* DOC: Page mobility and placement hints
|
||||
*
|
||||
* Page mobility and placement hints
|
||||
* ---------------------------------
|
||||
*
|
||||
* These flags provide hints about how mobile the page is. Pages with similar
|
||||
* mobility are placed within the same pageblocks to minimise problems due
|
||||
* to external fragmentation.
|
||||
*
|
||||
* %__GFP_MOVABLE (also a zone modifier) indicates that the page can be
|
||||
* moved by page migration during memory compaction or can be reclaimed.
|
||||
*
|
||||
* %__GFP_RECLAIMABLE is used for slab allocations that specify
|
||||
* SLAB_RECLAIM_ACCOUNT and whose pages can be freed via shrinkers.
|
||||
*
|
||||
* %__GFP_WRITE indicates the caller intends to dirty the page. Where possible,
|
||||
* these pages will be spread between local zones to avoid all the dirty
|
||||
* pages being in one zone (fair zone allocation policy).
|
||||
*
|
||||
* %__GFP_HARDWALL enforces the cpuset memory allocation policy.
|
||||
*
|
||||
* %__GFP_THISNODE forces the allocation to be satisfied from the requested
|
||||
* node with no fallbacks or placement policy enforcements.
|
||||
*
|
||||
* %__GFP_ACCOUNT causes the allocation to be accounted to kmemcg.
|
||||
*/
|
||||
#define __GFP_RECLAIMABLE ((__force gfp_t)___GFP_RECLAIMABLE)
|
||||
#define __GFP_WRITE ((__force gfp_t)___GFP_WRITE)
|
||||
#define __GFP_HARDWALL ((__force gfp_t)___GFP_HARDWALL)
|
||||
#define __GFP_THISNODE ((__force gfp_t)___GFP_THISNODE)
|
||||
#define __GFP_ACCOUNT ((__force gfp_t)___GFP_ACCOUNT)
|
||||
|
||||
/**
|
||||
* DOC: Watermark modifiers
|
||||
*
|
||||
* Watermark modifiers -- controls access to emergency reserves
|
||||
* ------------------------------------------------------------
|
||||
*
|
||||
* %__GFP_HIGH indicates that the caller is high-priority and that granting
|
||||
* the request is necessary before the system can make forward progress.
|
||||
* For example, creating an IO context to clean pages.
|
||||
*
|
||||
* %__GFP_ATOMIC indicates that the caller cannot reclaim or sleep and is
|
||||
* high priority. Users are typically interrupt handlers. This may be
|
||||
* used in conjunction with %__GFP_HIGH
|
||||
*
|
||||
* %__GFP_MEMALLOC allows access to all memory. This should only be used when
|
||||
* the caller guarantees the allocation will allow more memory to be freed
|
||||
* very shortly e.g. process exiting or swapping. Users either should
|
||||
* be the MM or co-ordinating closely with the VM (e.g. swap over NFS).
|
||||
* Users of this flag have to be extremely careful to not deplete the reserve
|
||||
* completely and implement a throttling mechanism which controls the
|
||||
* consumption of the reserve based on the amount of freed memory.
|
||||
* Usage of a pre-allocated pool (e.g. mempool) should be always considered
|
||||
* before using this flag.
|
||||
*
|
||||
* %__GFP_NOMEMALLOC is used to explicitly forbid access to emergency reserves.
|
||||
* This takes precedence over the %__GFP_MEMALLOC flag if both are set.
|
||||
*/
|
||||
#define __GFP_ATOMIC ((__force gfp_t)___GFP_ATOMIC)
|
||||
#define __GFP_HIGH ((__force gfp_t)___GFP_HIGH)
|
||||
#define __GFP_MEMALLOC ((__force gfp_t)___GFP_MEMALLOC)
|
||||
#define __GFP_NOMEMALLOC ((__force gfp_t)___GFP_NOMEMALLOC)
|
||||
|
||||
/**
|
||||
* DOC: Reclaim modifiers
|
||||
*
|
||||
* Reclaim modifiers
|
||||
* -----------------
|
||||
* Please note that all the following flags are only applicable to sleepable
|
||||
* allocations (e.g. %GFP_NOWAIT and %GFP_ATOMIC will ignore them).
|
||||
*
|
||||
* %__GFP_IO can start physical IO.
|
||||
*
|
||||
* %__GFP_FS can call down to the low-level FS. Clearing the flag avoids the
|
||||
* allocator recursing into the filesystem which might already be holding
|
||||
* locks.
|
||||
*
|
||||
* %__GFP_DIRECT_RECLAIM indicates that the caller may enter direct reclaim.
|
||||
* This flag can be cleared to avoid unnecessary delays when a fallback
|
||||
* option is available.
|
||||
*
|
||||
* %__GFP_KSWAPD_RECLAIM indicates that the caller wants to wake kswapd when
|
||||
* the low watermark is reached and have it reclaim pages until the high
|
||||
* watermark is reached. A caller may wish to clear this flag when fallback
|
||||
* options are available and the reclaim is likely to disrupt the system. The
|
||||
* canonical example is THP allocation where a fallback is cheap but
|
||||
* reclaim/compaction may cause indirect stalls.
|
||||
*
|
||||
* %__GFP_RECLAIM is shorthand to allow/forbid both direct and kswapd reclaim.
|
||||
*
|
||||
* The default allocator behavior depends on the request size. We have a concept
|
||||
* of so called costly allocations (with order > %PAGE_ALLOC_COSTLY_ORDER).
|
||||
* !costly allocations are too essential to fail so they are implicitly
|
||||
* non-failing by default (with some exceptions like OOM victims might fail so
|
||||
* the caller still has to check for failures) while costly requests try to be
|
||||
* not disruptive and back off even without invoking the OOM killer.
|
||||
* The following three modifiers might be used to override some of these
|
||||
* implicit rules
|
||||
*
|
||||
* %__GFP_NORETRY: The VM implementation will try only very lightweight
|
||||
* memory direct reclaim to get some memory under memory pressure (thus
|
||||
* it can sleep). It will avoid disruptive actions like OOM killer. The
|
||||
* caller must handle the failure which is quite likely to happen under
|
||||
* heavy memory pressure. The flag is suitable when failure can easily be
|
||||
* handled at small cost, such as reduced throughput
|
||||
*
|
||||
* %__GFP_RETRY_MAYFAIL: The VM implementation will retry memory reclaim
|
||||
* procedures that have previously failed if there is some indication
|
||||
* that progress has been made else where. It can wait for other
|
||||
* tasks to attempt high level approaches to freeing memory such as
|
||||
* compaction (which removes fragmentation) and page-out.
|
||||
* There is still a definite limit to the number of retries, but it is
|
||||
* a larger limit than with %__GFP_NORETRY.
|
||||
* Allocations with this flag may fail, but only when there is
|
||||
* genuinely little unused memory. While these allocations do not
|
||||
* directly trigger the OOM killer, their failure indicates that
|
||||
* the system is likely to need to use the OOM killer soon. The
|
||||
* caller must handle failure, but can reasonably do so by failing
|
||||
* a higher-level request, or completing it only in a much less
|
||||
* efficient manner.
|
||||
* If the allocation does fail, and the caller is in a position to
|
||||
* free some non-essential memory, doing so could benefit the system
|
||||
* as a whole.
|
||||
*
|
||||
* %__GFP_NOFAIL: The VM implementation _must_ retry infinitely: the caller
|
||||
* cannot handle allocation failures. The allocation could block
|
||||
* indefinitely but will never return with failure. Testing for
|
||||
* failure is pointless.
|
||||
* New users should be evaluated carefully (and the flag should be
|
||||
* used only when there is no reasonable failure policy) but it is
|
||||
* definitely preferable to use the flag rather than opencode endless
|
||||
* loop around allocator.
|
||||
* Using this flag for costly allocations is _highly_ discouraged.
|
||||
*/
|
||||
#define __GFP_IO ((__force gfp_t)___GFP_IO)
|
||||
#define __GFP_FS ((__force gfp_t)___GFP_FS)
|
||||
#define __GFP_DIRECT_RECLAIM ((__force gfp_t)___GFP_DIRECT_RECLAIM) /* Caller can reclaim */
|
||||
#define __GFP_KSWAPD_RECLAIM ((__force gfp_t)___GFP_KSWAPD_RECLAIM) /* kswapd can wake */
|
||||
#define __GFP_RECLAIM ((__force gfp_t)(___GFP_DIRECT_RECLAIM|___GFP_KSWAPD_RECLAIM))
|
||||
#define __GFP_RETRY_MAYFAIL ((__force gfp_t)___GFP_RETRY_MAYFAIL)
|
||||
#define __GFP_NOFAIL ((__force gfp_t)___GFP_NOFAIL)
|
||||
#define __GFP_NORETRY ((__force gfp_t)___GFP_NORETRY)
|
||||
|
||||
/**
|
||||
* DOC: Action modifiers
|
||||
*
|
||||
* Action modifiers
|
||||
* ----------------
|
||||
*
|
||||
* %__GFP_NOWARN suppresses allocation failure reports.
|
||||
*
|
||||
* %__GFP_COMP address compound page metadata.
|
||||
*
|
||||
* %__GFP_ZERO returns a zeroed page on success.
|
||||
*
|
||||
* %__GFP_ZEROTAGS zeroes memory tags at allocation time if the memory itself
|
||||
* is being zeroed (either via __GFP_ZERO or via init_on_alloc, provided that
|
||||
* __GFP_SKIP_ZERO is not set). This flag is intended for optimization: setting
|
||||
* memory tags at the same time as zeroing memory has minimal additional
|
||||
* performace impact.
|
||||
*
|
||||
* %__GFP_SKIP_KASAN_UNPOISON makes KASAN skip unpoisoning on page allocation.
|
||||
* Only effective in HW_TAGS mode.
|
||||
*
|
||||
* %__GFP_SKIP_KASAN_POISON makes KASAN skip poisoning on page deallocation.
|
||||
* Typically, used for userspace pages. Only effective in HW_TAGS mode.
|
||||
*/
|
||||
#define __GFP_NOWARN ((__force gfp_t)___GFP_NOWARN)
|
||||
#define __GFP_COMP ((__force gfp_t)___GFP_COMP)
|
||||
#define __GFP_ZERO ((__force gfp_t)___GFP_ZERO)
|
||||
#define __GFP_ZEROTAGS ((__force gfp_t)___GFP_ZEROTAGS)
|
||||
#define __GFP_SKIP_ZERO ((__force gfp_t)___GFP_SKIP_ZERO)
|
||||
#define __GFP_SKIP_KASAN_UNPOISON ((__force gfp_t)___GFP_SKIP_KASAN_UNPOISON)
|
||||
#define __GFP_SKIP_KASAN_POISON ((__force gfp_t)___GFP_SKIP_KASAN_POISON)
|
||||
|
||||
/* Disable lockdep for GFP context tracking */
|
||||
#define __GFP_NOLOCKDEP ((__force gfp_t)___GFP_NOLOCKDEP)
|
||||
|
||||
/* Room for N __GFP_FOO bits */
|
||||
#define __GFP_BITS_SHIFT (27 + IS_ENABLED(CONFIG_LOCKDEP))
|
||||
#define __GFP_BITS_MASK ((__force gfp_t)((1 << __GFP_BITS_SHIFT) - 1))
|
||||
|
||||
/**
|
||||
* DOC: Useful GFP flag combinations
|
||||
*
|
||||
* Useful GFP flag combinations
|
||||
* ----------------------------
|
||||
*
|
||||
* Useful GFP flag combinations that are commonly used. It is recommended
|
||||
* that subsystems start with one of these combinations and then set/clear
|
||||
* %__GFP_FOO flags as necessary.
|
||||
*
|
||||
* %GFP_ATOMIC users can not sleep and need the allocation to succeed. A lower
|
||||
* watermark is applied to allow access to "atomic reserves".
|
||||
* The current implementation doesn't support NMI and few other strict
|
||||
* non-preemptive contexts (e.g. raw_spin_lock). The same applies to %GFP_NOWAIT.
|
||||
*
|
||||
* %GFP_KERNEL is typical for kernel-internal allocations. The caller requires
|
||||
* %ZONE_NORMAL or a lower zone for direct access but can direct reclaim.
|
||||
*
|
||||
* %GFP_KERNEL_ACCOUNT is the same as GFP_KERNEL, except the allocation is
|
||||
* accounted to kmemcg.
|
||||
*
|
||||
* %GFP_NOWAIT is for kernel allocations that should not stall for direct
|
||||
* reclaim, start physical IO or use any filesystem callback.
|
||||
*
|
||||
* %GFP_NOIO will use direct reclaim to discard clean pages or slab pages
|
||||
* that do not require the starting of any physical IO.
|
||||
* Please try to avoid using this flag directly and instead use
|
||||
* memalloc_noio_{save,restore} to mark the whole scope which cannot
|
||||
* perform any IO with a short explanation why. All allocation requests
|
||||
* will inherit GFP_NOIO implicitly.
|
||||
*
|
||||
* %GFP_NOFS will use direct reclaim but will not use any filesystem interfaces.
|
||||
* Please try to avoid using this flag directly and instead use
|
||||
* memalloc_nofs_{save,restore} to mark the whole scope which cannot/shouldn't
|
||||
* recurse into the FS layer with a short explanation why. All allocation
|
||||
* requests will inherit GFP_NOFS implicitly.
|
||||
*
|
||||
* %GFP_USER is for userspace allocations that also need to be directly
|
||||
* accessibly by the kernel or hardware. It is typically used by hardware
|
||||
* for buffers that are mapped to userspace (e.g. graphics) that hardware
|
||||
* still must DMA to. cpuset limits are enforced for these allocations.
|
||||
*
|
||||
* %GFP_DMA exists for historical reasons and should be avoided where possible.
|
||||
* The flags indicates that the caller requires that the lowest zone be
|
||||
* used (%ZONE_DMA or 16M on x86-64). Ideally, this would be removed but
|
||||
* it would require careful auditing as some users really require it and
|
||||
* others use the flag to avoid lowmem reserves in %ZONE_DMA and treat the
|
||||
* lowest zone as a type of emergency reserve.
|
||||
*
|
||||
* %GFP_DMA32 is similar to %GFP_DMA except that the caller requires a 32-bit
|
||||
* address. Note that kmalloc(..., GFP_DMA32) does not return DMA32 memory
|
||||
* because the DMA32 kmalloc cache array is not implemented.
|
||||
* (Reason: there is no such user in kernel).
|
||||
*
|
||||
* %GFP_HIGHUSER is for userspace allocations that may be mapped to userspace,
|
||||
* do not need to be directly accessible by the kernel but that cannot
|
||||
* move once in use. An example may be a hardware allocation that maps
|
||||
* data directly into userspace but has no addressing limitations.
|
||||
*
|
||||
* %GFP_HIGHUSER_MOVABLE is for userspace allocations that the kernel does not
|
||||
* need direct access to but can use kmap() when access is required. They
|
||||
* are expected to be movable via page reclaim or page migration. Typically,
|
||||
* pages on the LRU would also be allocated with %GFP_HIGHUSER_MOVABLE.
|
||||
*
|
||||
* %GFP_TRANSHUGE and %GFP_TRANSHUGE_LIGHT are used for THP allocations. They
|
||||
* are compound allocations that will generally fail quickly if memory is not
|
||||
* available and will not wake kswapd/kcompactd on failure. The _LIGHT
|
||||
* version does not attempt reclaim/compaction at all and is by default used
|
||||
* in page fault path, while the non-light is used by khugepaged.
|
||||
*/
|
||||
#define GFP_ATOMIC (__GFP_HIGH|__GFP_ATOMIC|__GFP_KSWAPD_RECLAIM)
|
||||
#define GFP_KERNEL (__GFP_RECLAIM | __GFP_IO | __GFP_FS)
|
||||
#define GFP_KERNEL_ACCOUNT (GFP_KERNEL | __GFP_ACCOUNT)
|
||||
#define GFP_NOWAIT (__GFP_KSWAPD_RECLAIM)
|
||||
#define GFP_NOIO (__GFP_RECLAIM)
|
||||
#define GFP_NOFS (__GFP_RECLAIM | __GFP_IO)
|
||||
#define GFP_USER (__GFP_RECLAIM | __GFP_IO | __GFP_FS | __GFP_HARDWALL)
|
||||
#define GFP_DMA __GFP_DMA
|
||||
#define GFP_DMA32 __GFP_DMA32
|
||||
#define GFP_HIGHUSER (GFP_USER | __GFP_HIGHMEM)
|
||||
#define GFP_HIGHUSER_MOVABLE (GFP_HIGHUSER | __GFP_MOVABLE | \
|
||||
__GFP_SKIP_KASAN_POISON | __GFP_SKIP_KASAN_UNPOISON)
|
||||
#define GFP_TRANSHUGE_LIGHT ((GFP_HIGHUSER_MOVABLE | __GFP_COMP | \
|
||||
__GFP_NOMEMALLOC | __GFP_NOWARN) & ~__GFP_RECLAIM)
|
||||
#define GFP_TRANSHUGE (GFP_TRANSHUGE_LIGHT | __GFP_DIRECT_RECLAIM)
|
||||
|
||||
#endif /* __LINUX_GFP_TYPES_H */
|
||||
|
|
@ -95,7 +95,6 @@ struct device;
|
|||
int devm_gpio_request(struct device *dev, unsigned gpio, const char *label);
|
||||
int devm_gpio_request_one(struct device *dev, unsigned gpio,
|
||||
unsigned long flags, const char *label);
|
||||
void devm_gpio_free(struct device *dev, unsigned int gpio);
|
||||
|
||||
#else /* ! CONFIG_GPIOLIB */
|
||||
|
||||
|
|
@ -240,11 +239,6 @@ static inline int devm_gpio_request_one(struct device *dev, unsigned gpio,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
static inline void devm_gpio_free(struct device *dev, unsigned int gpio)
|
||||
{
|
||||
WARN_ON(1);
|
||||
}
|
||||
|
||||
#endif /* ! CONFIG_GPIOLIB */
|
||||
|
||||
#endif /* __LINUX_GPIO_H */
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ enum gpio_lookup_flags {
|
|||
GPIO_TRANSITORY = (1 << 3),
|
||||
GPIO_PULL_UP = (1 << 4),
|
||||
GPIO_PULL_DOWN = (1 << 5),
|
||||
GPIO_PULL_DISABLE = (1 << 6),
|
||||
|
||||
GPIO_LOOKUP_FLAGS_DEFAULT = GPIO_ACTIVE_HIGH | GPIO_PERSISTENT,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -92,14 +92,6 @@ void irq_exit_rcu(void);
|
|||
#define arch_nmi_exit() do { } while (0)
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_TINY_RCU
|
||||
static inline void rcu_nmi_enter(void) { }
|
||||
static inline void rcu_nmi_exit(void) { }
|
||||
#else
|
||||
extern void rcu_nmi_enter(void);
|
||||
extern void rcu_nmi_exit(void);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* NMI vs Tracing
|
||||
* --------------
|
||||
|
|
@ -124,7 +116,7 @@ extern void rcu_nmi_exit(void);
|
|||
do { \
|
||||
__nmi_enter(); \
|
||||
lockdep_hardirq_enter(); \
|
||||
rcu_nmi_enter(); \
|
||||
ct_nmi_enter(); \
|
||||
instrumentation_begin(); \
|
||||
ftrace_nmi_enter(); \
|
||||
instrumentation_end(); \
|
||||
|
|
@ -143,7 +135,7 @@ extern void rcu_nmi_exit(void);
|
|||
instrumentation_begin(); \
|
||||
ftrace_nmi_exit(); \
|
||||
instrumentation_end(); \
|
||||
rcu_nmi_exit(); \
|
||||
ct_nmi_exit(); \
|
||||
lockdep_hardirq_exit(); \
|
||||
__nmi_exit(); \
|
||||
} while (0)
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
#ifdef CONFIG_KMAP_LOCAL
|
||||
void *__kmap_local_pfn_prot(unsigned long pfn, pgprot_t prot);
|
||||
void *__kmap_local_page_prot(struct page *page, pgprot_t prot);
|
||||
void kunmap_local_indexed(void *vaddr);
|
||||
void kunmap_local_indexed(const void *vaddr);
|
||||
void kmap_local_fork(struct task_struct *tsk);
|
||||
void __kmap_local_sched_out(void);
|
||||
void __kmap_local_sched_in(void);
|
||||
|
|
@ -89,7 +89,7 @@ static inline void *kmap_local_pfn(unsigned long pfn)
|
|||
return __kmap_local_pfn_prot(pfn, kmap_prot);
|
||||
}
|
||||
|
||||
static inline void __kunmap_local(void *vaddr)
|
||||
static inline void __kunmap_local(const void *vaddr)
|
||||
{
|
||||
kunmap_local_indexed(vaddr);
|
||||
}
|
||||
|
|
@ -121,7 +121,7 @@ static inline void *kmap_atomic_pfn(unsigned long pfn)
|
|||
return __kmap_local_pfn_prot(pfn, kmap_prot);
|
||||
}
|
||||
|
||||
static inline void __kunmap_atomic(void *addr)
|
||||
static inline void __kunmap_atomic(const void *addr)
|
||||
{
|
||||
kunmap_local_indexed(addr);
|
||||
pagefault_enable();
|
||||
|
|
@ -197,7 +197,7 @@ static inline void *kmap_local_pfn(unsigned long pfn)
|
|||
return kmap_local_page(pfn_to_page(pfn));
|
||||
}
|
||||
|
||||
static inline void __kunmap_local(void *addr)
|
||||
static inline void __kunmap_local(const void *addr)
|
||||
{
|
||||
#ifdef ARCH_HAS_FLUSH_ON_KUNMAP
|
||||
kunmap_flush_on_unmap(addr);
|
||||
|
|
@ -224,7 +224,7 @@ static inline void *kmap_atomic_pfn(unsigned long pfn)
|
|||
return kmap_atomic(pfn_to_page(pfn));
|
||||
}
|
||||
|
||||
static inline void __kunmap_atomic(void *addr)
|
||||
static inline void __kunmap_atomic(const void *addr)
|
||||
{
|
||||
#ifdef ARCH_HAS_FLUSH_ON_KUNMAP
|
||||
kunmap_flush_on_unmap(addr);
|
||||
|
|
|
|||
|
|
@ -60,11 +60,11 @@ static inline void kmap_flush_unused(void);
|
|||
|
||||
/**
|
||||
* kmap_local_page - Map a page for temporary usage
|
||||
* @page: Pointer to the page to be mapped
|
||||
* @page: Pointer to the page to be mapped
|
||||
*
|
||||
* Returns: The virtual address of the mapping
|
||||
*
|
||||
* Can be invoked from any context.
|
||||
* Can be invoked from any context, including interrupts.
|
||||
*
|
||||
* Requires careful handling when nesting multiple mappings because the map
|
||||
* management is stack based. The unmap has to be in the reverse order of
|
||||
|
|
@ -86,8 +86,7 @@ static inline void kmap_flush_unused(void);
|
|||
* temporarily mapped.
|
||||
*
|
||||
* While it is significantly faster than kmap() for the higmem case it
|
||||
* comes with restrictions about the pointer validity. Only use when really
|
||||
* necessary.
|
||||
* comes with restrictions about the pointer validity.
|
||||
*
|
||||
* On HIGHMEM enabled systems mapping a highmem page has the side effect of
|
||||
* disabling migration in order to keep the virtual address stable across
|
||||
|
|
@ -243,6 +242,16 @@ static inline void clear_highpage(struct page *page)
|
|||
kunmap_local(kaddr);
|
||||
}
|
||||
|
||||
static inline void clear_highpage_kasan_tagged(struct page *page)
|
||||
{
|
||||
u8 tag;
|
||||
|
||||
tag = page_kasan_tag(page);
|
||||
page_kasan_tag_reset(page);
|
||||
clear_highpage(page);
|
||||
page_kasan_tag_set(page, tag);
|
||||
}
|
||||
|
||||
#ifndef __HAVE_ARCH_TAG_CLEAR_HIGHPAGE
|
||||
|
||||
static inline void tag_clear_highpage(struct page *page)
|
||||
|
|
@ -336,19 +345,6 @@ static inline void memcpy_page(struct page *dst_page, size_t dst_off,
|
|||
kunmap_local(dst);
|
||||
}
|
||||
|
||||
static inline void memmove_page(struct page *dst_page, size_t dst_off,
|
||||
struct page *src_page, size_t src_off,
|
||||
size_t len)
|
||||
{
|
||||
char *dst = kmap_local_page(dst_page);
|
||||
char *src = kmap_local_page(src_page);
|
||||
|
||||
VM_BUG_ON(dst_off + len > PAGE_SIZE || src_off + len > PAGE_SIZE);
|
||||
memmove(dst + dst_off, src + src_off, len);
|
||||
kunmap_local(src);
|
||||
kunmap_local(dst);
|
||||
}
|
||||
|
||||
static inline void memset_page(struct page *page, size_t offset, int val,
|
||||
size_t len)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -23,6 +23,10 @@
|
|||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
struct neigh_parms;
|
||||
struct net_device;
|
||||
struct sk_buff;
|
||||
|
||||
struct hippi_cb {
|
||||
__u32 ifield;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -265,6 +265,12 @@ struct hisi_qm_list {
|
|||
void (*unregister_from_crypto)(struct hisi_qm *qm);
|
||||
};
|
||||
|
||||
struct hisi_qm_poll_data {
|
||||
struct hisi_qm *qm;
|
||||
struct work_struct work;
|
||||
u16 *qp_finish_id;
|
||||
};
|
||||
|
||||
struct hisi_qm {
|
||||
enum qm_hw_ver ver;
|
||||
enum qm_fun_type fun_type;
|
||||
|
|
@ -302,6 +308,7 @@ struct hisi_qm {
|
|||
struct rw_semaphore qps_lock;
|
||||
struct idr qp_idr;
|
||||
struct hisi_qp *qp_array;
|
||||
struct hisi_qm_poll_data *poll_data;
|
||||
|
||||
struct mutex mailbox_lock;
|
||||
|
||||
|
|
@ -312,7 +319,6 @@ struct hisi_qm {
|
|||
u32 error_mask;
|
||||
|
||||
struct workqueue_struct *wq;
|
||||
struct work_struct work;
|
||||
struct work_struct rst_work;
|
||||
struct work_struct cmd_process;
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
*
|
||||
* Authors: Jérôme Glisse <jglisse@redhat.com>
|
||||
*
|
||||
* See Documentation/vm/hmm.rst for reasons and overview of what HMM is.
|
||||
* See Documentation/mm/hmm.rst for reasons and overview of what HMM is.
|
||||
*/
|
||||
#ifndef LINUX_HMM_H
|
||||
#define LINUX_HMM_H
|
||||
|
|
@ -100,7 +100,7 @@ struct hmm_range {
|
|||
};
|
||||
|
||||
/*
|
||||
* Please see Documentation/vm/hmm.rst for how to use the range API.
|
||||
* Please see Documentation/mm/hmm.rst for how to use the range API.
|
||||
*/
|
||||
int hmm_range_fault(struct hmm_range *range);
|
||||
|
||||
|
|
|
|||
|
|
@ -327,6 +327,14 @@ struct host1x_job {
|
|||
|
||||
/* Whether host1x-side firewall should be ran for this job or not */
|
||||
bool enable_firewall;
|
||||
|
||||
/* Options for configuring engine data stream ID */
|
||||
/* Context device to use for job */
|
||||
struct host1x_memory_context *memory_context;
|
||||
/* Stream ID to use if context isolation is disabled (!memory_context) */
|
||||
u32 engine_fallback_streamid;
|
||||
/* Engine offset to program stream ID to */
|
||||
u32 engine_streamid_offset;
|
||||
};
|
||||
|
||||
struct host1x_job *host1x_job_alloc(struct host1x_channel *ch,
|
||||
|
|
@ -446,4 +454,38 @@ int tegra_mipi_disable(struct tegra_mipi_device *device);
|
|||
int tegra_mipi_start_calibration(struct tegra_mipi_device *device);
|
||||
int tegra_mipi_finish_calibration(struct tegra_mipi_device *device);
|
||||
|
||||
/* host1x memory contexts */
|
||||
|
||||
struct host1x_memory_context {
|
||||
struct host1x *host;
|
||||
|
||||
refcount_t ref;
|
||||
struct pid *owner;
|
||||
|
||||
struct device dev;
|
||||
u64 dma_mask;
|
||||
u32 stream_id;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_IOMMU_API
|
||||
struct host1x_memory_context *host1x_memory_context_alloc(struct host1x *host1x,
|
||||
struct pid *pid);
|
||||
void host1x_memory_context_get(struct host1x_memory_context *cd);
|
||||
void host1x_memory_context_put(struct host1x_memory_context *cd);
|
||||
#else
|
||||
static inline struct host1x_memory_context *host1x_memory_context_alloc(struct host1x *host1x,
|
||||
struct pid *pid)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline void host1x_memory_context_get(struct host1x_memory_context *cd)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void host1x_memory_context_put(struct host1x_memory_context *cd)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -180,7 +180,7 @@ switch (val) { \
|
|||
|
||||
#define HP_SDC_CMD_SET_IM 0x40 /* 010xxxxx == set irq mask */
|
||||
|
||||
/* The documents provided do not explicitly state that all registers betweem
|
||||
/* The documents provided do not explicitly state that all registers between
|
||||
* 0x01 and 0x1f inclusive can be read by sending their register index as a
|
||||
* command, but this is implied and appears to be the case.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -116,9 +116,30 @@ extern struct kobj_attribute shmem_enabled_attr;
|
|||
|
||||
extern unsigned long transparent_hugepage_flags;
|
||||
|
||||
#define hugepage_flags_enabled() \
|
||||
(transparent_hugepage_flags & \
|
||||
((1<<TRANSPARENT_HUGEPAGE_FLAG) | \
|
||||
(1<<TRANSPARENT_HUGEPAGE_REQ_MADV_FLAG)))
|
||||
#define hugepage_flags_always() \
|
||||
(transparent_hugepage_flags & \
|
||||
(1<<TRANSPARENT_HUGEPAGE_FLAG))
|
||||
|
||||
/*
|
||||
* Do the below checks:
|
||||
* - For file vma, check if the linear page offset of vma is
|
||||
* HPAGE_PMD_NR aligned within the file. The hugepage is
|
||||
* guaranteed to be hugepage-aligned within the file, but we must
|
||||
* check that the PMD-aligned addresses in the VMA map to
|
||||
* PMD-aligned offsets within the file, else the hugepage will
|
||||
* not be PMD-mappable.
|
||||
* - For all vmas, check if the haddr is in an aligned HPAGE_PMD_SIZE
|
||||
* area.
|
||||
*/
|
||||
static inline bool transhuge_vma_suitable(struct vm_area_struct *vma,
|
||||
unsigned long haddr)
|
||||
unsigned long addr)
|
||||
{
|
||||
unsigned long haddr;
|
||||
|
||||
/* Don't have to check pgoff for anonymous vma */
|
||||
if (!vma_is_anonymous(vma)) {
|
||||
if (!IS_ALIGNED((vma->vm_start >> PAGE_SHIFT) - vma->vm_pgoff,
|
||||
|
|
@ -126,53 +147,13 @@ static inline bool transhuge_vma_suitable(struct vm_area_struct *vma,
|
|||
return false;
|
||||
}
|
||||
|
||||
haddr = addr & HPAGE_PMD_MASK;
|
||||
|
||||
if (haddr < vma->vm_start || haddr + HPAGE_PMD_SIZE > vma->vm_end)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool transhuge_vma_enabled(struct vm_area_struct *vma,
|
||||
unsigned long vm_flags)
|
||||
{
|
||||
/* Explicitly disabled through madvise. */
|
||||
if ((vm_flags & VM_NOHUGEPAGE) ||
|
||||
test_bit(MMF_DISABLE_THP, &vma->vm_mm->flags))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* to be used on vmas which are known to support THP.
|
||||
* Use transparent_hugepage_active otherwise
|
||||
*/
|
||||
static inline bool __transparent_hugepage_enabled(struct vm_area_struct *vma)
|
||||
{
|
||||
|
||||
/*
|
||||
* If the hardware/firmware marked hugepage support disabled.
|
||||
*/
|
||||
if (transparent_hugepage_flags & (1 << TRANSPARENT_HUGEPAGE_NEVER_DAX))
|
||||
return false;
|
||||
|
||||
if (!transhuge_vma_enabled(vma, vma->vm_flags))
|
||||
return false;
|
||||
|
||||
if (vma_is_temporary_stack(vma))
|
||||
return false;
|
||||
|
||||
if (transparent_hugepage_flags & (1 << TRANSPARENT_HUGEPAGE_FLAG))
|
||||
return true;
|
||||
|
||||
if (vma_is_dax(vma))
|
||||
return true;
|
||||
|
||||
if (transparent_hugepage_flags &
|
||||
(1 << TRANSPARENT_HUGEPAGE_REQ_MADV_FLAG))
|
||||
return !!(vma->vm_flags & VM_HUGEPAGE);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline bool file_thp_enabled(struct vm_area_struct *vma)
|
||||
{
|
||||
struct inode *inode;
|
||||
|
|
@ -187,7 +168,9 @@ static inline bool file_thp_enabled(struct vm_area_struct *vma)
|
|||
!inode_is_open_for_write(inode) && S_ISREG(inode->i_mode);
|
||||
}
|
||||
|
||||
bool transparent_hugepage_active(struct vm_area_struct *vma);
|
||||
bool hugepage_vma_check(struct vm_area_struct *vma,
|
||||
unsigned long vm_flags,
|
||||
bool smaps, bool in_pf);
|
||||
|
||||
#define transparent_hugepage_use_zero_page() \
|
||||
(transparent_hugepage_flags & \
|
||||
|
|
@ -290,7 +273,7 @@ static inline bool is_huge_zero_page(struct page *page)
|
|||
|
||||
static inline bool is_huge_zero_pmd(pmd_t pmd)
|
||||
{
|
||||
return READ_ONCE(huge_zero_pfn) == pmd_pfn(pmd) && pmd_present(pmd);
|
||||
return pmd_present(pmd) && READ_ONCE(huge_zero_pfn) == pmd_pfn(pmd);
|
||||
}
|
||||
|
||||
static inline bool is_huge_zero_pud(pud_t pud)
|
||||
|
|
@ -311,8 +294,8 @@ static inline bool thp_migration_supported(void)
|
|||
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.
|
||||
* See organization of tail pages of compound page in
|
||||
* "struct page" definition.
|
||||
*/
|
||||
return &page[2].deferred_list;
|
||||
}
|
||||
|
|
@ -331,24 +314,15 @@ static inline bool folio_test_pmd_mappable(struct folio *folio)
|
|||
return false;
|
||||
}
|
||||
|
||||
static inline bool __transparent_hugepage_enabled(struct vm_area_struct *vma)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline bool transparent_hugepage_active(struct vm_area_struct *vma)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline bool transhuge_vma_suitable(struct vm_area_struct *vma,
|
||||
unsigned long haddr)
|
||||
unsigned long addr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline bool transhuge_vma_enabled(struct vm_area_struct *vma,
|
||||
unsigned long vm_flags)
|
||||
static inline bool hugepage_vma_check(struct vm_area_struct *vma,
|
||||
unsigned long vm_flags,
|
||||
bool smaps, bool in_pf)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue