Merge branch 'main' into zstd-linus
This commit is contained in:
commit
4f2c0a4acf
34342 changed files with 4140524 additions and 1072502 deletions
|
|
@ -1,18 +0,0 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef __A_OUT_GNU_H__
|
||||
#define __A_OUT_GNU_H__
|
||||
|
||||
#include <uapi/linux/a.out.h>
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
#ifdef linux
|
||||
#include <asm/page.h>
|
||||
#if defined(__i386__) || defined(__mc68000__)
|
||||
#else
|
||||
#ifndef SEGMENT_SIZE
|
||||
#define SEGMENT_SIZE PAGE_SIZE
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#endif /*__ASSEMBLY__ */
|
||||
#endif /* __A_OUT_GNU_H__ */
|
||||
|
|
@ -21,7 +21,6 @@
|
|||
|
||||
#ifdef CONFIG_BSD_PROCESS_ACCT
|
||||
struct pid_namespace;
|
||||
extern int acct_parm[]; /* for sysctl */
|
||||
extern void acct_collect(long exitcode, int group_dead);
|
||||
extern void acct_process(void);
|
||||
extern void acct_exit_ns(struct pid_namespace *);
|
||||
|
|
|
|||
|
|
@ -105,6 +105,7 @@ enum acpi_irq_model_id {
|
|||
ACPI_IRQ_MODEL_IOSAPIC,
|
||||
ACPI_IRQ_MODEL_PLATFORM,
|
||||
ACPI_IRQ_MODEL_GIC,
|
||||
ACPI_IRQ_MODEL_LPIC,
|
||||
ACPI_IRQ_MODEL_COUNT
|
||||
};
|
||||
|
||||
|
|
@ -278,14 +279,17 @@ acpi_numa_processor_affinity_init(struct acpi_srat_cpu_affinity *pa) { }
|
|||
|
||||
void acpi_numa_x2apic_affinity_init(struct acpi_srat_x2apic_cpu_affinity *pa);
|
||||
|
||||
#if defined(CONFIG_ARM64) || defined(CONFIG_LOONGARCH)
|
||||
void acpi_arch_dma_setup(struct device *dev);
|
||||
#else
|
||||
static inline void acpi_arch_dma_setup(struct device *dev) { }
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ARM64
|
||||
void acpi_numa_gicc_affinity_init(struct acpi_srat_gicc_affinity *pa);
|
||||
void acpi_arch_dma_setup(struct device *dev, u64 *dma_addr, u64 *dma_size);
|
||||
#else
|
||||
static inline void
|
||||
acpi_numa_gicc_affinity_init(struct acpi_srat_gicc_affinity *pa) { }
|
||||
static inline void
|
||||
acpi_arch_dma_setup(struct device *dev, u64 *dma_addr, u64 *dma_size) { }
|
||||
#endif
|
||||
|
||||
int acpi_numa_memory_affinity_init (struct acpi_srat_mem_affinity *ma);
|
||||
|
|
@ -356,7 +360,8 @@ int acpi_gsi_to_irq (u32 gsi, unsigned int *irq);
|
|||
int acpi_isa_irq_to_gsi (unsigned isa_irq, u32 *gsi);
|
||||
|
||||
void acpi_set_irq_model(enum acpi_irq_model_id model,
|
||||
struct fwnode_handle *fwnode);
|
||||
struct fwnode_handle *(*)(u32));
|
||||
void acpi_set_gsi_to_irq_fallback(u32 (*)(u32));
|
||||
|
||||
struct irq_domain *acpi_irq_create_hierarchy(unsigned int flags,
|
||||
unsigned int size,
|
||||
|
|
@ -493,7 +498,7 @@ bool acpi_dev_resource_address_space(struct acpi_resource *ares,
|
|||
struct resource_win *win);
|
||||
bool acpi_dev_resource_ext_address_space(struct acpi_resource *ares,
|
||||
struct resource_win *win);
|
||||
unsigned long acpi_dev_irq_flags(u8 triggering, u8 polarity, u8 shareable);
|
||||
unsigned long acpi_dev_irq_flags(u8 triggering, u8 polarity, u8 shareable, u8 wake_capable);
|
||||
unsigned int acpi_dev_get_irq_type(int triggering, int polarity);
|
||||
bool acpi_dev_resource_interrupt(struct acpi_resource *ares, int index,
|
||||
struct resource *res);
|
||||
|
|
@ -504,6 +509,7 @@ int acpi_dev_get_resources(struct acpi_device *adev, struct list_head *list,
|
|||
void *preproc_data);
|
||||
int acpi_dev_get_dma_resources(struct acpi_device *adev,
|
||||
struct list_head *list);
|
||||
int acpi_dev_get_memory_resources(struct acpi_device *adev, struct list_head *list);
|
||||
int acpi_dev_filter_resource_type(struct acpi_resource *ares,
|
||||
unsigned long types);
|
||||
|
||||
|
|
@ -520,13 +526,10 @@ int acpi_check_resource_conflict(const struct resource *res);
|
|||
int acpi_check_region(resource_size_t start, resource_size_t n,
|
||||
const char *name);
|
||||
|
||||
acpi_status acpi_release_memory(acpi_handle handle, struct resource *res,
|
||||
u32 level);
|
||||
|
||||
int acpi_resources_are_enforced(void);
|
||||
|
||||
#ifdef CONFIG_HIBERNATION
|
||||
void __init acpi_check_s4_hw_signature(int check);
|
||||
extern int acpi_check_s4_hw_signature;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
|
|
@ -550,10 +553,16 @@ struct acpi_osc_context {
|
|||
|
||||
acpi_status acpi_run_osc(acpi_handle handle, struct acpi_osc_context *context);
|
||||
|
||||
/* Indexes into _OSC Capabilities Buffer (DWORDs 2 & 3 are device-specific) */
|
||||
/* Number of _OSC capability DWORDS depends on bridge type */
|
||||
#define OSC_PCI_CAPABILITY_DWORDS 3
|
||||
#define OSC_CXL_CAPABILITY_DWORDS 5
|
||||
|
||||
/* Indexes into _OSC Capabilities Buffer (DWORDs 2 to 5 are device-specific) */
|
||||
#define OSC_QUERY_DWORD 0 /* DWORD 1 */
|
||||
#define OSC_SUPPORT_DWORD 1 /* DWORD 2 */
|
||||
#define OSC_CONTROL_DWORD 2 /* DWORD 3 */
|
||||
#define OSC_EXT_SUPPORT_DWORD 3 /* DWORD 4 */
|
||||
#define OSC_EXT_CONTROL_DWORD 4 /* DWORD 5 */
|
||||
|
||||
/* _OSC Capabilities DWORD 1: Query/Control and Error Returns (generic) */
|
||||
#define OSC_QUERY_ENABLE 0x00000001 /* input */
|
||||
|
|
@ -574,12 +583,15 @@ acpi_status acpi_run_osc(acpi_handle handle, struct acpi_osc_context *context);
|
|||
#define OSC_SB_OSLPI_SUPPORT 0x00000100
|
||||
#define OSC_SB_CPC_DIVERSE_HIGH_SUPPORT 0x00001000
|
||||
#define OSC_SB_GENERIC_INITIATOR_SUPPORT 0x00002000
|
||||
#define OSC_SB_CPC_FLEXIBLE_ADR_SPACE 0x00004000
|
||||
#define OSC_SB_NATIVE_USB4_SUPPORT 0x00040000
|
||||
#define OSC_SB_PRM_SUPPORT 0x00200000
|
||||
|
||||
extern bool osc_sb_apei_support_acked;
|
||||
extern bool osc_pc_lpi_support_confirmed;
|
||||
extern bool osc_sb_native_usb4_support_confirmed;
|
||||
extern bool osc_sb_cppc2_support_acked;
|
||||
extern bool osc_cpc_flexible_adr_space_confirmed;
|
||||
|
||||
/* USB4 Capabilities */
|
||||
#define OSC_USB_USB3_TUNNELING 0x00000001
|
||||
|
|
@ -607,6 +619,29 @@ extern u32 osc_sb_native_usb4_control;
|
|||
#define OSC_PCI_EXPRESS_LTR_CONTROL 0x00000020
|
||||
#define OSC_PCI_EXPRESS_DPC_CONTROL 0x00000080
|
||||
|
||||
/* CXL _OSC: Capabilities DWORD 4: Support Field */
|
||||
#define OSC_CXL_1_1_PORT_REG_ACCESS_SUPPORT 0x00000001
|
||||
#define OSC_CXL_2_0_PORT_DEV_REG_ACCESS_SUPPORT 0x00000002
|
||||
#define OSC_CXL_PROTOCOL_ERR_REPORTING_SUPPORT 0x00000004
|
||||
#define OSC_CXL_NATIVE_HP_SUPPORT 0x00000008
|
||||
|
||||
/* CXL _OSC: Capabilities DWORD 5: Control Field */
|
||||
#define OSC_CXL_ERROR_REPORTING_CONTROL 0x00000001
|
||||
|
||||
static inline u32 acpi_osc_ctx_get_pci_control(struct acpi_osc_context *context)
|
||||
{
|
||||
u32 *ret = context->ret.pointer;
|
||||
|
||||
return ret[OSC_CONTROL_DWORD];
|
||||
}
|
||||
|
||||
static inline u32 acpi_osc_ctx_get_cxl_control(struct acpi_osc_context *context)
|
||||
{
|
||||
u32 *ret = context->ret.pointer;
|
||||
|
||||
return ret[OSC_EXT_CONTROL_DWORD];
|
||||
}
|
||||
|
||||
#define ACPI_GSB_ACCESS_ATTRIB_QUICK 0x00000002
|
||||
#define ACPI_GSB_ACCESS_ATTRIB_SEND_RCV 0x00000004
|
||||
#define ACPI_GSB_ACCESS_ATTRIB_BYTE 0x00000006
|
||||
|
|
@ -691,7 +726,7 @@ int acpi_device_uevent_modalias(struct device *, struct kobj_uevent_env *);
|
|||
int acpi_device_modalias(struct device *, char *, int);
|
||||
|
||||
struct platform_device *acpi_create_platform_device(struct acpi_device *,
|
||||
struct property_entry *);
|
||||
const struct property_entry *);
|
||||
#define ACPI_PTR(_ptr) (_ptr)
|
||||
|
||||
static inline void acpi_device_set_enumerated(struct acpi_device *adev)
|
||||
|
|
@ -733,6 +768,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 */
|
||||
|
||||
|
|
@ -766,6 +802,11 @@ acpi_dev_hid_uid_match(struct acpi_device *adev, const char *hid2, const char *u
|
|||
return false;
|
||||
}
|
||||
|
||||
static inline int acpi_dev_uid_to_integer(struct acpi_device *adev, u64 *integer)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static inline struct acpi_device *
|
||||
acpi_dev_get_first_match_dev(const char *hid, const char *uid, s64 hrv)
|
||||
{
|
||||
|
|
@ -930,7 +971,7 @@ static inline int acpi_device_modalias(struct device *dev,
|
|||
|
||||
static inline struct platform_device *
|
||||
acpi_create_platform_device(struct acpi_device *adev,
|
||||
struct property_entry *properties)
|
||||
const struct property_entry *properties)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -945,8 +986,7 @@ static inline enum dev_dma_attr acpi_get_dma_attr(struct acpi_device *adev)
|
|||
return DEV_DMA_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
static inline int acpi_dma_get_range(struct device *dev, u64 *dma_addr,
|
||||
u64 *offset, u64 *size)
|
||||
static inline int acpi_dma_get_range(struct device *dev, const struct bus_dma_region **map)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
|
|
@ -994,6 +1034,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)
|
||||
{
|
||||
|
|
@ -1003,6 +1048,17 @@ static inline int acpi_register_wakeup_handler(int wake_irq,
|
|||
static inline void acpi_unregister_wakeup_handler(
|
||||
bool (*wakeup)(void *context), void *context) { }
|
||||
|
||||
struct acpi_osc_context;
|
||||
static inline u32 acpi_osc_ctx_get_pci_control(struct acpi_osc_context *context)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline u32 acpi_osc_ctx_get_cxl_control(struct acpi_osc_context *context)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* !CONFIG_ACPI */
|
||||
|
||||
#ifdef CONFIG_ACPI_HOTPLUG_IOAPIC
|
||||
|
|
@ -1023,7 +1079,16 @@ void acpi_os_set_prepare_extended_sleep(int (*func)(u8 sleep_state,
|
|||
|
||||
acpi_status acpi_os_prepare_extended_sleep(u8 sleep_state,
|
||||
u32 val_a, u32 val_b);
|
||||
|
||||
#ifdef CONFIG_X86
|
||||
struct acpi_s2idle_dev_ops {
|
||||
struct list_head list_node;
|
||||
void (*prepare)(void);
|
||||
void (*check)(void);
|
||||
void (*restore)(void);
|
||||
};
|
||||
int acpi_register_lps0_dev(struct acpi_s2idle_dev_ops *arg);
|
||||
void acpi_unregister_lps0_dev(struct acpi_s2idle_dev_ops *arg);
|
||||
#endif /* CONFIG_X86 */
|
||||
#ifndef CONFIG_IA64
|
||||
void arch_reserve_mem_area(acpi_physical_address addr, size_t size);
|
||||
#else
|
||||
|
|
@ -1146,7 +1211,8 @@ bool acpi_gpio_get_irq_resource(struct acpi_resource *ares,
|
|||
struct acpi_resource_gpio **agpio);
|
||||
bool acpi_gpio_get_io_resource(struct acpi_resource *ares,
|
||||
struct acpi_resource_gpio **agpio);
|
||||
int acpi_dev_gpio_irq_get_by(struct acpi_device *adev, const char *name, int index);
|
||||
int acpi_dev_gpio_irq_wake_get_by(struct acpi_device *adev, const char *name, int index,
|
||||
bool *wake_capable);
|
||||
#else
|
||||
static inline bool acpi_gpio_get_irq_resource(struct acpi_resource *ares,
|
||||
struct acpi_resource_gpio **agpio)
|
||||
|
|
@ -1158,16 +1224,28 @@ static inline bool acpi_gpio_get_io_resource(struct acpi_resource *ares,
|
|||
{
|
||||
return false;
|
||||
}
|
||||
static inline int acpi_dev_gpio_irq_get_by(struct acpi_device *adev,
|
||||
const char *name, int index)
|
||||
static inline int acpi_dev_gpio_irq_wake_get_by(struct acpi_device *adev, const char *name,
|
||||
int index, bool *wake_capable)
|
||||
{
|
||||
return -ENXIO;
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline int acpi_dev_gpio_irq_wake_get(struct acpi_device *adev, int index,
|
||||
bool *wake_capable)
|
||||
{
|
||||
return acpi_dev_gpio_irq_wake_get_by(adev, NULL, index, wake_capable);
|
||||
}
|
||||
|
||||
static inline int acpi_dev_gpio_irq_get_by(struct acpi_device *adev, const char *name,
|
||||
int index)
|
||||
{
|
||||
return acpi_dev_gpio_irq_wake_get_by(adev, name, index, NULL);
|
||||
}
|
||||
|
||||
static inline int acpi_dev_gpio_irq_get(struct acpi_device *adev, int index)
|
||||
{
|
||||
return acpi_dev_gpio_irq_get_by(adev, NULL, index);
|
||||
return acpi_dev_gpio_irq_wake_get_by(adev, NULL, index, NULL);
|
||||
}
|
||||
|
||||
/* Device properties */
|
||||
|
|
@ -1195,7 +1273,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);
|
||||
|
|
@ -1381,7 +1459,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)
|
||||
{
|
||||
|
|
@ -1403,10 +1480,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
|
||||
|
|
|
|||
13
include/linux/acpi_agdi.h
Normal file
13
include/linux/acpi_agdi.h
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
|
||||
#ifndef __ACPI_AGDI_H__
|
||||
#define __ACPI_AGDI_H__
|
||||
|
||||
#include <linux/acpi.h>
|
||||
|
||||
#ifdef CONFIG_ACPI_AGDI
|
||||
void __init acpi_agdi_init(void);
|
||||
#else
|
||||
static inline void acpi_agdi_init(void) {}
|
||||
#endif
|
||||
#endif /* __ACPI_AGDI_H__ */
|
||||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
|
||||
#include <linux/compiler.h>
|
||||
|
||||
struct clk;
|
||||
struct device;
|
||||
struct ata_port_info;
|
||||
struct ahci_host_priv;
|
||||
|
|
@ -21,8 +22,12 @@ struct scsi_host_template;
|
|||
|
||||
int ahci_platform_enable_phys(struct ahci_host_priv *hpriv);
|
||||
void ahci_platform_disable_phys(struct ahci_host_priv *hpriv);
|
||||
struct clk *ahci_platform_find_clk(struct ahci_host_priv *hpriv,
|
||||
const char *con_id);
|
||||
int ahci_platform_enable_clks(struct ahci_host_priv *hpriv);
|
||||
void ahci_platform_disable_clks(struct ahci_host_priv *hpriv);
|
||||
int ahci_platform_deassert_rsts(struct ahci_host_priv *hpriv);
|
||||
int ahci_platform_assert_rsts(struct ahci_host_priv *hpriv);
|
||||
int ahci_platform_enable_regulators(struct ahci_host_priv *hpriv);
|
||||
void ahci_platform_disable_regulators(struct ahci_host_priv *hpriv);
|
||||
int ahci_platform_enable_resources(struct ahci_host_priv *hpriv);
|
||||
|
|
@ -41,6 +46,7 @@ int ahci_platform_resume_host(struct device *dev);
|
|||
int ahci_platform_suspend(struct device *dev);
|
||||
int ahci_platform_resume(struct device *dev);
|
||||
|
||||
#define AHCI_PLATFORM_GET_RESETS 0x01
|
||||
#define AHCI_PLATFORM_GET_RESETS BIT(0)
|
||||
#define AHCI_PLATFORM_RST_TRIGGER BIT(1)
|
||||
|
||||
#endif /* _AHCI_PLATFORM_H */
|
||||
|
|
|
|||
|
|
@ -67,10 +67,15 @@ 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];
|
||||
char *driver_override;
|
||||
/*
|
||||
* Driver name to force a match. Do not set directly, because core
|
||||
* frees it. Use driver_set_override() to set or clear it.
|
||||
*/
|
||||
const char *driver_override;
|
||||
};
|
||||
|
||||
struct amba_driver {
|
||||
|
|
@ -79,6 +84,14 @@ struct amba_driver {
|
|||
void (*remove)(struct amba_device *);
|
||||
void (*shutdown)(struct amba_device *);
|
||||
const struct amba_id *id_table;
|
||||
/*
|
||||
* For most device drivers, no need to care about this flag as long as
|
||||
* all DMAs are handled through the kernel DMA API. For some special
|
||||
* ones, for example VFIO drivers, they know how to manage the DMA
|
||||
* themselves and set this flag so that the IOMMU layer will allow them
|
||||
* to setup and manage their own I/O address space.
|
||||
*/
|
||||
bool driver_managed_dma;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -117,30 +130,9 @@ void amba_device_put(struct amba_device *);
|
|||
int amba_device_add(struct amba_device *, struct resource *);
|
||||
int amba_device_register(struct amba_device *, struct resource *);
|
||||
void amba_device_unregister(struct amba_device *);
|
||||
struct amba_device *amba_find_device(const char *, struct device *, unsigned int, unsigned int);
|
||||
int amba_request_regions(struct amba_device *, const char *);
|
||||
void amba_release_regions(struct amba_device *);
|
||||
|
||||
static inline int amba_pclk_enable(struct amba_device *dev)
|
||||
{
|
||||
return clk_enable(dev->pclk);
|
||||
}
|
||||
|
||||
static inline void amba_pclk_disable(struct amba_device *dev)
|
||||
{
|
||||
clk_disable(dev->pclk);
|
||||
}
|
||||
|
||||
static inline int amba_pclk_prepare(struct amba_device *dev)
|
||||
{
|
||||
return clk_prepare(dev->pclk);
|
||||
}
|
||||
|
||||
static inline void amba_pclk_unprepare(struct amba_device *dev)
|
||||
{
|
||||
clk_unprepare(dev->pclk);
|
||||
}
|
||||
|
||||
/* Some drivers don't use the struct amba_device */
|
||||
#define AMBA_CONFIG_BITS(a) (((a) >> 24) & 0xff)
|
||||
#define AMBA_REV_BITS(a) (((a) >> 20) & 0x0f)
|
||||
|
|
|
|||
|
|
@ -13,17 +13,11 @@
|
|||
* @ocr_mask: available voltages on the 4 pins from the block, this
|
||||
* is ignored if a regulator is used, see the MMC_VDD_* masks in
|
||||
* mmc/host.h
|
||||
* @ios_handler: a callback function to act on specfic ios changes,
|
||||
* used for example to control a levelshifter
|
||||
* mask into a value to be binary (or set some other custom bits
|
||||
* in MMCIPWR) or:ed and written into the MMCIPWR register of the
|
||||
* block. May also control external power based on the power_mode.
|
||||
* @status: if no GPIO line was given to the block in this function will
|
||||
* be called to determine whether a card is present in the MMC slot or not
|
||||
*/
|
||||
struct mmci_platform_data {
|
||||
unsigned int ocr_mask;
|
||||
int (*ios_handler)(struct device *, struct mmc_ios *);
|
||||
unsigned int (*status)(struct device *);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
77
include/linux/amd-pstate.h
Normal file
77
include/linux/amd-pstate.h
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* linux/include/linux/amd-pstate.h
|
||||
*
|
||||
* Copyright (C) 2022 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* Author: Meng Li <li.meng@amd.com>
|
||||
*/
|
||||
|
||||
#ifndef _LINUX_AMD_PSTATE_H
|
||||
#define _LINUX_AMD_PSTATE_H
|
||||
|
||||
#include <linux/pm_qos.h>
|
||||
|
||||
/*********************************************************************
|
||||
* AMD P-state INTERFACE *
|
||||
*********************************************************************/
|
||||
/**
|
||||
* struct amd_aperf_mperf
|
||||
* @aperf: actual performance frequency clock count
|
||||
* @mperf: maximum performance frequency clock count
|
||||
* @tsc: time stamp counter
|
||||
*/
|
||||
struct amd_aperf_mperf {
|
||||
u64 aperf;
|
||||
u64 mperf;
|
||||
u64 tsc;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct amd_cpudata - private CPU data for AMD P-State
|
||||
* @cpu: CPU number
|
||||
* @req: constraint request to apply
|
||||
* @cppc_req_cached: cached performance request hints
|
||||
* @highest_perf: the maximum performance an individual processor may reach,
|
||||
* assuming ideal conditions
|
||||
* @nominal_perf: the maximum sustained performance level of the processor,
|
||||
* assuming ideal operating conditions
|
||||
* @lowest_nonlinear_perf: the lowest performance level at which nonlinear power
|
||||
* savings are achieved
|
||||
* @lowest_perf: the absolute lowest performance level of the processor
|
||||
* @max_freq: the frequency that mapped to highest_perf
|
||||
* @min_freq: the frequency that mapped to lowest_perf
|
||||
* @nominal_freq: the frequency that mapped to nominal_perf
|
||||
* @lowest_nonlinear_freq: the frequency that mapped to lowest_nonlinear_perf
|
||||
* @cur: Difference of Aperf/Mperf/tsc count between last and current sample
|
||||
* @prev: Last Aperf/Mperf/tsc count value read from register
|
||||
* @freq: current cpu frequency value
|
||||
* @boost_supported: check whether the Processor or SBIOS supports boost mode
|
||||
*
|
||||
* The amd_cpudata is key private data for each CPU thread in AMD P-State, and
|
||||
* represents all the attributes and goals that AMD P-State requests at runtime.
|
||||
*/
|
||||
struct amd_cpudata {
|
||||
int cpu;
|
||||
|
||||
struct freq_qos_request req[2];
|
||||
u64 cppc_req_cached;
|
||||
|
||||
u32 highest_perf;
|
||||
u32 nominal_perf;
|
||||
u32 lowest_nonlinear_perf;
|
||||
u32 lowest_perf;
|
||||
|
||||
u32 max_freq;
|
||||
u32 min_freq;
|
||||
u32 nominal_freq;
|
||||
u32 lowest_nonlinear_freq;
|
||||
|
||||
struct amd_aperf_mperf cur;
|
||||
struct amd_aperf_mperf prev;
|
||||
|
||||
u64 freq;
|
||||
bool boost_supported;
|
||||
};
|
||||
|
||||
#endif /* _LINUX_AMD_PSTATE_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
|
||||
|
|
@ -11,6 +11,10 @@
|
|||
void topology_normalize_cpu_scale(void);
|
||||
int topology_update_cpu_topology(void);
|
||||
|
||||
#ifdef CONFIG_ACPI_CPPC_LIB
|
||||
void topology_init_cpu_capacity_cppc(void);
|
||||
#endif
|
||||
|
||||
struct device_node;
|
||||
bool topology_parse_cpu_capacity(struct device_node *cpu_node, int cpu);
|
||||
|
||||
|
|
@ -64,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;
|
||||
|
|
|
|||
|
|
@ -92,6 +92,11 @@
|
|||
ARM_SMCCC_SMC_32, \
|
||||
0, 0x7fff)
|
||||
|
||||
#define ARM_SMCCC_ARCH_WORKAROUND_3 \
|
||||
ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
|
||||
ARM_SMCCC_SMC_32, \
|
||||
0, 0x3fff)
|
||||
|
||||
#define ARM_SMCCC_VENDOR_HYP_CALL_UID_FUNC_ID \
|
||||
ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
|
||||
ARM_SMCCC_SMC_32, \
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ struct ffa_device {
|
|||
bool mode_32bit;
|
||||
uuid_t uuid;
|
||||
struct device dev;
|
||||
const struct ffa_ops *ops;
|
||||
};
|
||||
|
||||
#define to_ffa_dev(d) container_of(d, struct ffa_device, dev)
|
||||
|
|
@ -38,21 +39,27 @@ struct ffa_driver {
|
|||
|
||||
static inline void ffa_dev_set_drvdata(struct ffa_device *fdev, void *data)
|
||||
{
|
||||
fdev->dev.driver_data = data;
|
||||
dev_set_drvdata(&fdev->dev, data);
|
||||
}
|
||||
|
||||
static inline void *ffa_dev_get_drvdata(struct ffa_device *fdev)
|
||||
{
|
||||
return dev_get_drvdata(&fdev->dev);
|
||||
}
|
||||
|
||||
#if IS_REACHABLE(CONFIG_ARM_FFA_TRANSPORT)
|
||||
struct ffa_device *ffa_device_register(const uuid_t *uuid, int vm_id);
|
||||
struct ffa_device *ffa_device_register(const uuid_t *uuid, int vm_id,
|
||||
const struct ffa_ops *ops);
|
||||
void ffa_device_unregister(struct ffa_device *ffa_dev);
|
||||
int ffa_driver_register(struct ffa_driver *driver, struct module *owner,
|
||||
const char *mod_name);
|
||||
void ffa_driver_unregister(struct ffa_driver *driver);
|
||||
bool ffa_device_is_valid(struct ffa_device *ffa_dev);
|
||||
const struct ffa_dev_ops *ffa_dev_ops_get(struct ffa_device *dev);
|
||||
|
||||
#else
|
||||
static inline
|
||||
struct ffa_device *ffa_device_register(const uuid_t *uuid, int vm_id)
|
||||
struct ffa_device *ffa_device_register(const uuid_t *uuid, int vm_id,
|
||||
const struct ffa_ops *ops)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -71,11 +78,6 @@ static inline void ffa_driver_unregister(struct ffa_driver *driver) {}
|
|||
static inline
|
||||
bool ffa_device_is_valid(struct ffa_device *ffa_dev) { return false; }
|
||||
|
||||
static inline
|
||||
const struct ffa_dev_ops *ffa_dev_ops_get(struct ffa_device *dev)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
#endif /* CONFIG_ARM_FFA_TRANSPORT */
|
||||
|
||||
#define ffa_register(driver) \
|
||||
|
|
@ -104,7 +106,10 @@ struct ffa_partition_info {
|
|||
#define FFA_PARTITION_DIRECT_SEND BIT(1)
|
||||
/* partition can send and receive indirect messages. */
|
||||
#define FFA_PARTITION_INDIRECT_MSG BIT(2)
|
||||
/* partition runs in the AArch64 execution state. */
|
||||
#define FFA_PARTITION_AARCH64_EXEC BIT(8)
|
||||
u32 properties;
|
||||
u32 uuid[4];
|
||||
};
|
||||
|
||||
/* For use with FFA_MSG_SEND_DIRECT_{REQ,RESP} which pass data via registers */
|
||||
|
|
@ -252,18 +257,28 @@ struct ffa_mem_ops_args {
|
|||
struct ffa_mem_region_attributes *attrs;
|
||||
};
|
||||
|
||||
struct ffa_dev_ops {
|
||||
struct ffa_info_ops {
|
||||
u32 (*api_version_get)(void);
|
||||
int (*partition_info_get)(const char *uuid_str,
|
||||
struct ffa_partition_info *buffer);
|
||||
};
|
||||
|
||||
struct ffa_msg_ops {
|
||||
void (*mode_32bit_set)(struct ffa_device *dev);
|
||||
int (*sync_send_receive)(struct ffa_device *dev,
|
||||
struct ffa_send_direct_data *data);
|
||||
};
|
||||
|
||||
struct ffa_mem_ops {
|
||||
int (*memory_reclaim)(u64 g_handle, u32 flags);
|
||||
int (*memory_share)(struct ffa_device *dev,
|
||||
struct ffa_mem_ops_args *args);
|
||||
int (*memory_lend)(struct ffa_device *dev,
|
||||
struct ffa_mem_ops_args *args);
|
||||
int (*memory_share)(struct ffa_mem_ops_args *args);
|
||||
int (*memory_lend)(struct ffa_mem_ops_args *args);
|
||||
};
|
||||
|
||||
struct ffa_ops {
|
||||
const struct ffa_info_ops *info_ops;
|
||||
const struct ffa_msg_ops *msg_ops;
|
||||
const struct ffa_mem_ops *mem_ops;
|
||||
};
|
||||
|
||||
#endif /* _LINUX_ARM_FFA_H */
|
||||
|
|
|
|||
|
|
@ -46,9 +46,11 @@ int sdei_unregister_ghes(struct ghes *ghes);
|
|||
/* For use by arch code when CPU hotplug notifiers are not appropriate. */
|
||||
int sdei_mask_local_cpu(void);
|
||||
int sdei_unmask_local_cpu(void);
|
||||
void __init sdei_init(void);
|
||||
#else
|
||||
static inline int sdei_mask_local_cpu(void) { return 0; }
|
||||
static inline int sdei_unmask_local_cpu(void) { return 0; }
|
||||
static inline void sdei_init(void) { }
|
||||
#endif /* CONFIG_ARM_SDE_INTERFACE */
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -324,12 +324,12 @@ enum {
|
|||
ATA_LOG_NCQ_NON_DATA = 0x12,
|
||||
ATA_LOG_NCQ_SEND_RECV = 0x13,
|
||||
ATA_LOG_IDENTIFY_DEVICE = 0x30,
|
||||
ATA_LOG_CONCURRENT_POSITIONING_RANGES = 0x47,
|
||||
|
||||
/* Identify device log pages: */
|
||||
ATA_LOG_SECURITY = 0x06,
|
||||
ATA_LOG_SATA_SETTINGS = 0x08,
|
||||
ATA_LOG_ZONED_INFORMATION = 0x09,
|
||||
ATA_LOG_CONCURRENT_POSITIONING_RANGES = 0x47,
|
||||
|
||||
/* Identify device SATA settings log:*/
|
||||
ATA_LOG_DEVSLP_OFFSET = 0x30,
|
||||
|
|
@ -566,6 +566,18 @@ struct ata_bmdma_prd {
|
|||
((((id)[ATA_ID_SATA_CAPABILITY] != 0x0000) && \
|
||||
((id)[ATA_ID_SATA_CAPABILITY] != 0xffff)) && \
|
||||
((id)[ATA_ID_FEATURE_SUPP] & (1 << 2)))
|
||||
#define ata_id_has_devslp(id) \
|
||||
((((id)[ATA_ID_SATA_CAPABILITY] != 0x0000) && \
|
||||
((id)[ATA_ID_SATA_CAPABILITY] != 0xffff)) && \
|
||||
((id)[ATA_ID_FEATURE_SUPP] & (1 << 8)))
|
||||
#define ata_id_has_ncq_autosense(id) \
|
||||
((((id)[ATA_ID_SATA_CAPABILITY] != 0x0000) && \
|
||||
((id)[ATA_ID_SATA_CAPABILITY] != 0xffff)) && \
|
||||
((id)[ATA_ID_FEATURE_SUPP] & (1 << 7)))
|
||||
#define ata_id_has_dipm(id) \
|
||||
((((id)[ATA_ID_SATA_CAPABILITY] != 0x0000) && \
|
||||
((id)[ATA_ID_SATA_CAPABILITY] != 0xffff)) && \
|
||||
((id)[ATA_ID_FEATURE_SUPP] & (1 << 3)))
|
||||
#define ata_id_iordy_disable(id) ((id)[ATA_ID_CAPABILITY] & (1 << 10))
|
||||
#define ata_id_has_iordy(id) ((id)[ATA_ID_CAPABILITY] & (1 << 11))
|
||||
#define ata_id_u32(id,n) \
|
||||
|
|
@ -578,9 +590,6 @@ struct ata_bmdma_prd {
|
|||
|
||||
#define ata_id_cdb_intr(id) (((id)[ATA_ID_CONFIG] & 0x60) == 0x20)
|
||||
#define ata_id_has_da(id) ((id)[ATA_ID_SATA_CAPABILITY_2] & (1 << 4))
|
||||
#define ata_id_has_devslp(id) ((id)[ATA_ID_FEATURE_SUPP] & (1 << 8))
|
||||
#define ata_id_has_ncq_autosense(id) \
|
||||
((id)[ATA_ID_FEATURE_SUPP] & (1 << 7))
|
||||
|
||||
static inline bool ata_id_has_hipm(const u16 *id)
|
||||
{
|
||||
|
|
@ -592,17 +601,6 @@ static inline bool ata_id_has_hipm(const u16 *id)
|
|||
return val & (1 << 9);
|
||||
}
|
||||
|
||||
static inline bool ata_id_has_dipm(const u16 *id)
|
||||
{
|
||||
u16 val = id[ATA_ID_FEATURE_SUPP];
|
||||
|
||||
if (val == 0 || val == 0xffff)
|
||||
return false;
|
||||
|
||||
return val & (1 << 3);
|
||||
}
|
||||
|
||||
|
||||
static inline bool ata_id_has_fua(const u16 *id)
|
||||
{
|
||||
if ((id[ATA_ID_CFSSE] & 0xC000) != 0x4000)
|
||||
|
|
@ -771,16 +769,21 @@ static inline bool ata_id_has_read_log_dma_ext(const u16 *id)
|
|||
|
||||
static inline bool ata_id_has_sense_reporting(const u16 *id)
|
||||
{
|
||||
if (!(id[ATA_ID_CFS_ENABLE_2] & (1 << 15)))
|
||||
if (!(id[ATA_ID_CFS_ENABLE_2] & BIT(15)))
|
||||
return false;
|
||||
return id[ATA_ID_COMMAND_SET_3] & (1 << 6);
|
||||
if ((id[ATA_ID_COMMAND_SET_3] & (BIT(15) | BIT(14))) != BIT(14))
|
||||
return false;
|
||||
return id[ATA_ID_COMMAND_SET_3] & BIT(6);
|
||||
}
|
||||
|
||||
static inline bool ata_id_sense_reporting_enabled(const u16 *id)
|
||||
{
|
||||
if (!(id[ATA_ID_CFS_ENABLE_2] & (1 << 15)))
|
||||
if (!ata_id_has_sense_reporting(id))
|
||||
return false;
|
||||
return id[ATA_ID_COMMAND_SET_4] & (1 << 6);
|
||||
/* ata_id_has_sense_reporting() == true, word 86 must have bit 15 set */
|
||||
if ((id[ATA_ID_COMMAND_SET_4] & (BIT(15) | BIT(14))) != BIT(14))
|
||||
return false;
|
||||
return id[ATA_ID_COMMAND_SET_4] & BIT(6);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -147,11 +147,90 @@
|
|||
|
||||
#endif /* arch_try_cmpxchg_relaxed */
|
||||
|
||||
#ifndef arch_try_cmpxchg64_relaxed
|
||||
#ifdef arch_try_cmpxchg64
|
||||
#define arch_try_cmpxchg64_acquire arch_try_cmpxchg64
|
||||
#define arch_try_cmpxchg64_release arch_try_cmpxchg64
|
||||
#define arch_try_cmpxchg64_relaxed arch_try_cmpxchg64
|
||||
#endif /* arch_try_cmpxchg64 */
|
||||
|
||||
#ifndef arch_try_cmpxchg64
|
||||
#define arch_try_cmpxchg64(_ptr, _oldp, _new) \
|
||||
({ \
|
||||
typeof(*(_ptr)) *___op = (_oldp), ___o = *___op, ___r; \
|
||||
___r = arch_cmpxchg64((_ptr), ___o, (_new)); \
|
||||
if (unlikely(___r != ___o)) \
|
||||
*___op = ___r; \
|
||||
likely(___r == ___o); \
|
||||
})
|
||||
#endif /* arch_try_cmpxchg64 */
|
||||
|
||||
#ifndef arch_try_cmpxchg64_acquire
|
||||
#define arch_try_cmpxchg64_acquire(_ptr, _oldp, _new) \
|
||||
({ \
|
||||
typeof(*(_ptr)) *___op = (_oldp), ___o = *___op, ___r; \
|
||||
___r = arch_cmpxchg64_acquire((_ptr), ___o, (_new)); \
|
||||
if (unlikely(___r != ___o)) \
|
||||
*___op = ___r; \
|
||||
likely(___r == ___o); \
|
||||
})
|
||||
#endif /* arch_try_cmpxchg64_acquire */
|
||||
|
||||
#ifndef arch_try_cmpxchg64_release
|
||||
#define arch_try_cmpxchg64_release(_ptr, _oldp, _new) \
|
||||
({ \
|
||||
typeof(*(_ptr)) *___op = (_oldp), ___o = *___op, ___r; \
|
||||
___r = arch_cmpxchg64_release((_ptr), ___o, (_new)); \
|
||||
if (unlikely(___r != ___o)) \
|
||||
*___op = ___r; \
|
||||
likely(___r == ___o); \
|
||||
})
|
||||
#endif /* arch_try_cmpxchg64_release */
|
||||
|
||||
#ifndef arch_try_cmpxchg64_relaxed
|
||||
#define arch_try_cmpxchg64_relaxed(_ptr, _oldp, _new) \
|
||||
({ \
|
||||
typeof(*(_ptr)) *___op = (_oldp), ___o = *___op, ___r; \
|
||||
___r = arch_cmpxchg64_relaxed((_ptr), ___o, (_new)); \
|
||||
if (unlikely(___r != ___o)) \
|
||||
*___op = ___r; \
|
||||
likely(___r == ___o); \
|
||||
})
|
||||
#endif /* arch_try_cmpxchg64_relaxed */
|
||||
|
||||
#else /* arch_try_cmpxchg64_relaxed */
|
||||
|
||||
#ifndef arch_try_cmpxchg64_acquire
|
||||
#define arch_try_cmpxchg64_acquire(...) \
|
||||
__atomic_op_acquire(arch_try_cmpxchg64, __VA_ARGS__)
|
||||
#endif
|
||||
|
||||
#ifndef arch_try_cmpxchg64_release
|
||||
#define arch_try_cmpxchg64_release(...) \
|
||||
__atomic_op_release(arch_try_cmpxchg64, __VA_ARGS__)
|
||||
#endif
|
||||
|
||||
#ifndef arch_try_cmpxchg64
|
||||
#define arch_try_cmpxchg64(...) \
|
||||
__atomic_op_fence(arch_try_cmpxchg64, __VA_ARGS__)
|
||||
#endif
|
||||
|
||||
#endif /* arch_try_cmpxchg64_relaxed */
|
||||
|
||||
#ifndef arch_atomic_read_acquire
|
||||
static __always_inline int
|
||||
arch_atomic_read_acquire(const atomic_t *v)
|
||||
{
|
||||
return smp_load_acquire(&(v)->counter);
|
||||
int ret;
|
||||
|
||||
if (__native_word(atomic_t)) {
|
||||
ret = smp_load_acquire(&(v)->counter);
|
||||
} else {
|
||||
ret = arch_atomic_read(v);
|
||||
__atomic_acquire_fence();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
#define arch_atomic_read_acquire arch_atomic_read_acquire
|
||||
#endif
|
||||
|
|
@ -160,7 +239,12 @@ arch_atomic_read_acquire(const atomic_t *v)
|
|||
static __always_inline void
|
||||
arch_atomic_set_release(atomic_t *v, int i)
|
||||
{
|
||||
smp_store_release(&(v)->counter, i);
|
||||
if (__native_word(atomic_t)) {
|
||||
smp_store_release(&(v)->counter, i);
|
||||
} else {
|
||||
__atomic_release_fence();
|
||||
arch_atomic_set(v, i);
|
||||
}
|
||||
}
|
||||
#define arch_atomic_set_release arch_atomic_set_release
|
||||
#endif
|
||||
|
|
@ -1258,7 +1342,16 @@ arch_atomic_dec_if_positive(atomic_t *v)
|
|||
static __always_inline s64
|
||||
arch_atomic64_read_acquire(const atomic64_t *v)
|
||||
{
|
||||
return smp_load_acquire(&(v)->counter);
|
||||
s64 ret;
|
||||
|
||||
if (__native_word(atomic64_t)) {
|
||||
ret = smp_load_acquire(&(v)->counter);
|
||||
} else {
|
||||
ret = arch_atomic64_read(v);
|
||||
__atomic_acquire_fence();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
#define arch_atomic64_read_acquire arch_atomic64_read_acquire
|
||||
#endif
|
||||
|
|
@ -1267,7 +1360,12 @@ arch_atomic64_read_acquire(const atomic64_t *v)
|
|||
static __always_inline void
|
||||
arch_atomic64_set_release(atomic64_t *v, s64 i)
|
||||
{
|
||||
smp_store_release(&(v)->counter, i);
|
||||
if (__native_word(atomic64_t)) {
|
||||
smp_store_release(&(v)->counter, i);
|
||||
} else {
|
||||
__atomic_release_fence();
|
||||
arch_atomic64_set(v, i);
|
||||
}
|
||||
}
|
||||
#define arch_atomic64_set_release arch_atomic64_set_release
|
||||
#endif
|
||||
|
|
@ -2358,4 +2456,4 @@ arch_atomic64_dec_if_positive(atomic64_t *v)
|
|||
#endif
|
||||
|
||||
#endif /* _LINUX_ATOMIC_FALLBACK_H */
|
||||
// cca554917d7ea73d5e3e7397dd70c484cad9b2c4
|
||||
// b5e87bdd5ede61470c29f7a7e4de781af3770f09
|
||||
|
|
|
|||
|
|
@ -2006,6 +2006,44 @@ atomic_long_dec_if_positive(atomic_long_t *v)
|
|||
arch_try_cmpxchg_relaxed(__ai_ptr, __ai_oldp, __VA_ARGS__); \
|
||||
})
|
||||
|
||||
#define try_cmpxchg64(ptr, oldp, ...) \
|
||||
({ \
|
||||
typeof(ptr) __ai_ptr = (ptr); \
|
||||
typeof(oldp) __ai_oldp = (oldp); \
|
||||
kcsan_mb(); \
|
||||
instrument_atomic_write(__ai_ptr, sizeof(*__ai_ptr)); \
|
||||
instrument_atomic_write(__ai_oldp, sizeof(*__ai_oldp)); \
|
||||
arch_try_cmpxchg64(__ai_ptr, __ai_oldp, __VA_ARGS__); \
|
||||
})
|
||||
|
||||
#define try_cmpxchg64_acquire(ptr, oldp, ...) \
|
||||
({ \
|
||||
typeof(ptr) __ai_ptr = (ptr); \
|
||||
typeof(oldp) __ai_oldp = (oldp); \
|
||||
instrument_atomic_write(__ai_ptr, sizeof(*__ai_ptr)); \
|
||||
instrument_atomic_write(__ai_oldp, sizeof(*__ai_oldp)); \
|
||||
arch_try_cmpxchg64_acquire(__ai_ptr, __ai_oldp, __VA_ARGS__); \
|
||||
})
|
||||
|
||||
#define try_cmpxchg64_release(ptr, oldp, ...) \
|
||||
({ \
|
||||
typeof(ptr) __ai_ptr = (ptr); \
|
||||
typeof(oldp) __ai_oldp = (oldp); \
|
||||
kcsan_release(); \
|
||||
instrument_atomic_write(__ai_ptr, sizeof(*__ai_ptr)); \
|
||||
instrument_atomic_write(__ai_oldp, sizeof(*__ai_oldp)); \
|
||||
arch_try_cmpxchg64_release(__ai_ptr, __ai_oldp, __VA_ARGS__); \
|
||||
})
|
||||
|
||||
#define try_cmpxchg64_relaxed(ptr, oldp, ...) \
|
||||
({ \
|
||||
typeof(ptr) __ai_ptr = (ptr); \
|
||||
typeof(oldp) __ai_oldp = (oldp); \
|
||||
instrument_atomic_write(__ai_ptr, sizeof(*__ai_ptr)); \
|
||||
instrument_atomic_write(__ai_oldp, sizeof(*__ai_oldp)); \
|
||||
arch_try_cmpxchg64_relaxed(__ai_ptr, __ai_oldp, __VA_ARGS__); \
|
||||
})
|
||||
|
||||
#define cmpxchg_local(ptr, ...) \
|
||||
({ \
|
||||
typeof(ptr) __ai_ptr = (ptr); \
|
||||
|
|
@ -2045,4 +2083,4 @@ atomic_long_dec_if_positive(atomic_long_t *v)
|
|||
})
|
||||
|
||||
#endif /* _LINUX_ATOMIC_INSTRUMENTED_H */
|
||||
// 87c974b93032afd42143613434d1a7788fa598f9
|
||||
// 764f741eb77a7ad565dc8d99ce2837d5542e8aee
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
@ -339,7 +336,7 @@ static inline void audit_uring_entry(u8 op)
|
|||
}
|
||||
static inline void audit_uring_exit(int success, long code)
|
||||
{
|
||||
if (unlikely(!audit_dummy_context()))
|
||||
if (unlikely(audit_context()))
|
||||
__audit_uring_exit(success, code);
|
||||
}
|
||||
static inline void audit_syscall_entry(int major, unsigned long a0,
|
||||
|
|
@ -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 */
|
||||
|
|
@ -207,14 +200,6 @@ struct backing_dev_info {
|
|||
#endif
|
||||
};
|
||||
|
||||
enum {
|
||||
BLK_RW_ASYNC = 0,
|
||||
BLK_RW_SYNC = 1,
|
||||
};
|
||||
|
||||
void clear_bdi_congested(struct backing_dev_info *bdi, int sync);
|
||||
void set_bdi_congested(struct backing_dev_info *bdi, int sync);
|
||||
|
||||
struct wb_lock_cookie {
|
||||
bool locked;
|
||||
unsigned long flags;
|
||||
|
|
|
|||
|
|
@ -17,8 +17,6 @@
|
|||
#include <linux/backing-dev-defs.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
struct blkcg;
|
||||
|
||||
static inline struct backing_dev_info *bdi_get(struct backing_dev_info *bdi)
|
||||
{
|
||||
kref_get(&bdi->refcnt);
|
||||
|
|
@ -121,6 +119,8 @@ int bdi_set_max_ratio(struct backing_dev_info *bdi, unsigned int max_ratio);
|
|||
|
||||
extern struct backing_dev_info noop_backing_dev_info;
|
||||
|
||||
int bdi_init(struct backing_dev_info *bdi);
|
||||
|
||||
/**
|
||||
* writeback_in_progress - determine whether there is writeback in progress
|
||||
* @wb: bdi_writeback of interest
|
||||
|
|
@ -135,24 +135,11 @@ static inline bool writeback_in_progress(struct bdi_writeback *wb)
|
|||
|
||||
struct backing_dev_info *inode_to_bdi(struct inode *inode);
|
||||
|
||||
static inline int wb_congested(struct bdi_writeback *wb, int cong_bits)
|
||||
{
|
||||
return wb->congested & cong_bits;
|
||||
}
|
||||
|
||||
long congestion_wait(int sync, long timeout);
|
||||
|
||||
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,
|
||||
|
|
@ -161,8 +148,7 @@ struct bdi_writeback *wb_get_create(struct backing_dev_info *bdi,
|
|||
struct cgroup_subsys_state *memcg_css,
|
||||
gfp_t gfp);
|
||||
void wb_memcg_offline(struct mem_cgroup *memcg);
|
||||
void wb_blkcg_offline(struct blkcg *blkcg);
|
||||
int inode_congested(struct inode *inode, int cong_bits);
|
||||
void wb_blkcg_offline(struct cgroup_subsys_state *css);
|
||||
|
||||
/**
|
||||
* inode_cgwb_enabled - test whether cgroup writeback is enabled on an inode
|
||||
|
|
@ -243,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
|
||||
|
|
@ -353,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;
|
||||
|
|
@ -386,54 +355,12 @@ static inline void wb_memcg_offline(struct mem_cgroup *memcg)
|
|||
{
|
||||
}
|
||||
|
||||
static inline void wb_blkcg_offline(struct blkcg *blkcg)
|
||||
static inline void wb_blkcg_offline(struct cgroup_subsys_state *css)
|
||||
{
|
||||
}
|
||||
|
||||
static inline int inode_congested(struct inode *inode, int cong_bits)
|
||||
{
|
||||
return wb_congested(&inode_to_bdi(inode)->wb, cong_bits);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_CGROUP_WRITEBACK */
|
||||
|
||||
static inline int inode_read_congested(struct inode *inode)
|
||||
{
|
||||
return inode_congested(inode, 1 << WB_sync_congested);
|
||||
}
|
||||
|
||||
static inline int inode_write_congested(struct inode *inode)
|
||||
{
|
||||
return inode_congested(inode, 1 << WB_async_congested);
|
||||
}
|
||||
|
||||
static inline int inode_rw_congested(struct inode *inode)
|
||||
{
|
||||
return inode_congested(inode, (1 << WB_sync_congested) |
|
||||
(1 << WB_async_congested));
|
||||
}
|
||||
|
||||
static inline int bdi_congested(struct backing_dev_info *bdi, int cong_bits)
|
||||
{
|
||||
return wb_congested(&bdi->wb, cong_bits);
|
||||
}
|
||||
|
||||
static inline int bdi_read_congested(struct backing_dev_info *bdi)
|
||||
{
|
||||
return bdi_congested(bdi, 1 << WB_sync_congested);
|
||||
}
|
||||
|
||||
static inline int bdi_write_congested(struct backing_dev_info *bdi)
|
||||
{
|
||||
return bdi_congested(bdi, 1 << WB_async_congested);
|
||||
}
|
||||
|
||||
static inline int bdi_rw_congested(struct backing_dev_info *bdi)
|
||||
{
|
||||
return bdi_congested(bdi, (1 << WB_sync_congested) |
|
||||
(1 << WB_async_congested));
|
||||
}
|
||||
|
||||
const char *bdi_dev_name(struct backing_dev_info *bdi);
|
||||
|
||||
#endif /* _LINUX_BACKING_DEV_H */
|
||||
|
|
|
|||
|
|
@ -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,17 +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 bool balloon_page_isolate(struct page *page,
|
||||
isolate_mode_t mode);
|
||||
extern void balloon_page_putback(struct page *page);
|
||||
extern int balloon_page_migrate(struct address_space *mapping,
|
||||
struct page *newpage,
|
||||
struct page *page, enum migrate_mode mode);
|
||||
extern const struct movable_operations balloon_mops;
|
||||
|
||||
/*
|
||||
* balloon_page_insert - insert a page into the balloon's page list and make
|
||||
|
|
@ -100,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);
|
||||
}
|
||||
|
|
@ -155,22 +147,6 @@ static inline void balloon_page_delete(struct page *page)
|
|||
list_del(&page->lru);
|
||||
}
|
||||
|
||||
static inline bool balloon_page_isolate(struct page *page)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline void balloon_page_putback(struct page *page)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static inline int balloon_page_migrate(struct page *newpage,
|
||||
struct page *page, enum migrate_mode mode)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline gfp_t balloon_mapping_gfp_mask(void)
|
||||
{
|
||||
return GFP_HIGHUSER;
|
||||
|
|
|
|||
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 */
|
||||
|
|
@ -3,6 +3,7 @@
|
|||
#define LINUX_BCMA_DRIVER_CC_H_
|
||||
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/platform_data/brcmnand.h>
|
||||
#include <linux/gpio.h>
|
||||
|
||||
/** ChipCommon core registers. **/
|
||||
|
|
@ -270,6 +271,7 @@
|
|||
#define BCMA_CC_SROM_CONTROL_OP_WRDIS 0x40000000
|
||||
#define BCMA_CC_SROM_CONTROL_OP_WREN 0x60000000
|
||||
#define BCMA_CC_SROM_CONTROL_OTPSEL 0x00000010
|
||||
#define BCMA_CC_SROM_CONTROL_OTP_PRESENT 0x00000020
|
||||
#define BCMA_CC_SROM_CONTROL_LOCK 0x00000008
|
||||
#define BCMA_CC_SROM_CONTROL_SIZE_MASK 0x00000006
|
||||
#define BCMA_CC_SROM_CONTROL_SIZE_1K 0x00000000
|
||||
|
|
@ -599,6 +601,10 @@ struct bcma_sflash {
|
|||
|
||||
#ifdef CONFIG_BCMA_NFLASH
|
||||
struct bcma_nflash {
|
||||
/* Must be the fist member for the brcmnand driver to
|
||||
* de-reference that structure.
|
||||
*/
|
||||
struct brcmnand_platform_data brcmnand_info;
|
||||
bool present;
|
||||
bool boot; /* This is the flash the SoC boots from */
|
||||
};
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
#include <uapi/linux/binfmts.h>
|
||||
|
||||
struct filename;
|
||||
struct coredump_params;
|
||||
|
||||
#define CORENAME_MAX_SIZE 128
|
||||
|
||||
|
|
@ -42,9 +43,6 @@ struct linux_binprm {
|
|||
* original userspace.
|
||||
*/
|
||||
point_of_no_return:1;
|
||||
#ifdef __alpha__
|
||||
unsigned int taso:1;
|
||||
#endif
|
||||
struct file *executable; /* Executable to pass to the interpreter */
|
||||
struct file *interpreter;
|
||||
struct file *file;
|
||||
|
|
@ -77,18 +75,6 @@ struct linux_binprm {
|
|||
#define BINPRM_FLAGS_PRESERVE_ARGV0_BIT 3
|
||||
#define BINPRM_FLAGS_PRESERVE_ARGV0 (1 << BINPRM_FLAGS_PRESERVE_ARGV0_BIT)
|
||||
|
||||
/* Function parameter for binfmt->coredump */
|
||||
struct coredump_params {
|
||||
const kernel_siginfo_t *siginfo;
|
||||
struct pt_regs *regs;
|
||||
struct file *file;
|
||||
unsigned long limit;
|
||||
unsigned long mm_flags;
|
||||
loff_t written;
|
||||
loff_t pos;
|
||||
loff_t to_skip;
|
||||
};
|
||||
|
||||
/*
|
||||
* This structure defines the functions that are used to load the binary formats that
|
||||
* linux accepts.
|
||||
|
|
@ -98,8 +84,10 @@ struct linux_binfmt {
|
|||
struct module *module;
|
||||
int (*load_binary)(struct linux_binprm *);
|
||||
int (*load_shlib)(struct file *);
|
||||
#ifdef CONFIG_COREDUMP
|
||||
int (*core_dump)(struct coredump_params *cprm);
|
||||
unsigned long min_coredump; /* minimal dump size */
|
||||
#endif
|
||||
} __randomize_layout;
|
||||
|
||||
extern void __register_binfmt(struct linux_binfmt *fmt, int insert);
|
||||
|
|
|
|||
|
|
@ -65,7 +65,6 @@ static inline bool bio_no_advance_iter(const struct bio *bio)
|
|||
{
|
||||
return bio_op(bio) == REQ_OP_DISCARD ||
|
||||
bio_op(bio) == REQ_OP_SECURE_ERASE ||
|
||||
bio_op(bio) == REQ_OP_WRITE_SAME ||
|
||||
bio_op(bio) == REQ_OP_WRITE_ZEROES;
|
||||
}
|
||||
|
||||
|
|
@ -186,8 +185,6 @@ static inline unsigned bio_segments(struct bio *bio)
|
|||
case REQ_OP_SECURE_ERASE:
|
||||
case REQ_OP_WRITE_ZEROES:
|
||||
return 0;
|
||||
case REQ_OP_WRITE_SAME:
|
||||
return 1;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
@ -272,6 +269,7 @@ struct folio_iter {
|
|||
size_t offset;
|
||||
size_t length;
|
||||
/* private: for use by the iterator */
|
||||
struct folio *_next;
|
||||
size_t _seg_count;
|
||||
int _i;
|
||||
};
|
||||
|
|
@ -286,6 +284,7 @@ static inline void bio_first_folio(struct folio_iter *fi, struct bio *bio,
|
|||
PAGE_SIZE * (bvec->bv_page - &fi->folio->page);
|
||||
fi->_seg_count = bvec->bv_len;
|
||||
fi->length = min(folio_size(fi->folio) - fi->offset, fi->_seg_count);
|
||||
fi->_next = folio_next(fi->folio);
|
||||
fi->_i = i;
|
||||
}
|
||||
|
||||
|
|
@ -293,9 +292,10 @@ static inline void bio_next_folio(struct folio_iter *fi, struct bio *bio)
|
|||
{
|
||||
fi->_seg_count -= fi->length;
|
||||
if (fi->_seg_count) {
|
||||
fi->folio = folio_next(fi->folio);
|
||||
fi->folio = fi->_next;
|
||||
fi->offset = 0;
|
||||
fi->length = min(folio_size(fi->folio), fi->_seg_count);
|
||||
fi->_next = folio_next(fi->folio);
|
||||
} else if (fi->_i + 1 < bio->bi_vcnt) {
|
||||
bio_first_folio(fi, bio, fi->_i + 1);
|
||||
} else {
|
||||
|
|
@ -403,23 +403,24 @@ enum {
|
|||
extern int bioset_init(struct bio_set *, unsigned int, unsigned int, int flags);
|
||||
extern void bioset_exit(struct bio_set *);
|
||||
extern int biovec_init_pool(mempool_t *pool, int pool_entries);
|
||||
extern int bioset_init_from_src(struct bio_set *bs, struct bio_set *src);
|
||||
|
||||
struct bio *bio_alloc_bioset(gfp_t gfp, unsigned short nr_iovecs,
|
||||
struct bio_set *bs);
|
||||
struct bio *bio_alloc_kiocb(struct kiocb *kiocb, unsigned short nr_vecs,
|
||||
struct bio_set *bs);
|
||||
struct bio *bio_kmalloc(gfp_t gfp_mask, unsigned short nr_iovecs);
|
||||
struct bio *bio_alloc_bioset(struct block_device *bdev, unsigned short nr_vecs,
|
||||
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 *);
|
||||
|
||||
extern void __bio_clone_fast(struct bio *, struct bio *);
|
||||
extern struct bio *bio_clone_fast(struct bio *, gfp_t, struct bio_set *);
|
||||
struct bio *bio_alloc_clone(struct block_device *bdev, struct bio *bio_src,
|
||||
gfp_t gfp, struct bio_set *bs);
|
||||
int bio_init_clone(struct block_device *bdev, struct bio *bio,
|
||||
struct bio *bio_src, gfp_t gfp);
|
||||
|
||||
extern struct bio_set fs_bio_set;
|
||||
|
||||
static inline struct bio *bio_alloc(gfp_t gfp_mask, unsigned short nr_iovecs)
|
||||
static inline struct bio *bio_alloc(struct block_device *bdev,
|
||||
unsigned short nr_vecs, blk_opf_t opf, gfp_t gfp_mask)
|
||||
{
|
||||
return bio_alloc_bioset(gfp_mask, nr_iovecs, &fs_bio_set);
|
||||
return bio_alloc_bioset(bdev, nr_vecs, opf, gfp_mask, &fs_bio_set);
|
||||
}
|
||||
|
||||
void submit_bio(struct bio *bio);
|
||||
|
|
@ -454,10 +455,10 @@ static inline int bio_iov_vecs_to_alloc(struct iov_iter *iter, int max_segs)
|
|||
struct request_queue;
|
||||
|
||||
extern int submit_bio_wait(struct bio *bio);
|
||||
extern void bio_init(struct bio *bio, struct bio_vec *table,
|
||||
unsigned short max_vecs);
|
||||
void bio_init(struct bio *bio, struct block_device *bdev, struct bio_vec *table,
|
||||
unsigned short max_vecs, blk_opf_t opf);
|
||||
extern void bio_uninit(struct bio *);
|
||||
extern void bio_reset(struct bio *);
|
||||
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);
|
||||
|
|
@ -487,8 +488,6 @@ static inline void bio_release_pages(struct bio *bio, bool mark_dirty)
|
|||
__bio_release_pages(bio, mark_dirty);
|
||||
}
|
||||
|
||||
extern const char *bio_devname(struct bio *bio, char *buffer);
|
||||
|
||||
#define bio_dev(bio) \
|
||||
disk_devt((bio)->bi_bdev->bd_disk)
|
||||
|
||||
|
|
@ -510,18 +509,11 @@ static inline void bio_set_dev(struct bio *bio, struct block_device *bdev)
|
|||
{
|
||||
bio_clear_flag(bio, BIO_REMAPPED);
|
||||
if (bio->bi_bdev != bdev)
|
||||
bio_clear_flag(bio, BIO_THROTTLED);
|
||||
bio_clear_flag(bio, BIO_BPS_THROTTLED);
|
||||
bio->bi_bdev = bdev;
|
||||
bio_associate_blkg(bio);
|
||||
}
|
||||
|
||||
static inline void bio_copy_dev(struct bio *dst, struct bio *src)
|
||||
{
|
||||
bio_clear_flag(dst, BIO_REMAPPED);
|
||||
dst->bi_bdev = src->bi_bdev;
|
||||
bio_clone_blkg_association(dst, src);
|
||||
}
|
||||
|
||||
/*
|
||||
* BIO list management for use by remapping drivers (e.g. DM or MD) and loop.
|
||||
*
|
||||
|
|
@ -790,6 +782,13 @@ static inline void bio_set_polled(struct bio *bio, struct kiocb *kiocb)
|
|||
bio->bi_opf |= REQ_NOWAIT;
|
||||
}
|
||||
|
||||
struct bio *blk_next_bio(struct bio *bio, unsigned int nr_pages, gfp_t gfp);
|
||||
static inline void bio_clear_polled(struct bio *bio)
|
||||
{
|
||||
/* can't support alloc cache if we turn off polling */
|
||||
bio->bi_opf &= ~(REQ_POLLED | REQ_ALLOC_CACHE);
|
||||
}
|
||||
|
||||
struct bio *blk_next_bio(struct bio *bio, struct block_device *bdev,
|
||||
unsigned int nr_pages, blk_opf_t opf, gfp_t gfp);
|
||||
|
||||
#endif /* __LINUX_BIO_H */
|
||||
|
|
|
|||
|
|
@ -19,6 +19,9 @@
|
|||
*
|
||||
* Example:
|
||||
*
|
||||
* #include <linux/bitfield.h>
|
||||
* #include <linux/bits.h>
|
||||
*
|
||||
* #define REG_FIELD_A GENMASK(6, 0)
|
||||
* #define REG_FIELD_B BIT(7)
|
||||
* #define REG_FIELD_C GENMASK(15, 8)
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@ struct device;
|
|||
* bitmap_empty(src, nbits) Are all bits zero in *src?
|
||||
* bitmap_full(src, nbits) Are all bits set in *src?
|
||||
* bitmap_weight(src, nbits) Hamming Weight: number set bits
|
||||
* bitmap_weight_and(src1, src2, nbits) Hamming Weight of and'ed bitmap
|
||||
* bitmap_set(dst, pos, nbits) Set specified bit area
|
||||
* bitmap_clear(dst, pos, nbits) Clear specified bit area
|
||||
* bitmap_find_next_zero_area(buf, len, pos, n, mask) Find bit free area
|
||||
|
|
@ -71,7 +72,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_get_value8(map, start) Get 8bit value from map at start
|
||||
* bitmap_set_value8(map, value, start) Set 8bit value to map at start
|
||||
*
|
||||
|
|
@ -132,8 +135,8 @@ unsigned long *devm_bitmap_zalloc(struct device *dev,
|
|||
* lib/bitmap.c provides these functions:
|
||||
*/
|
||||
|
||||
int __bitmap_equal(const unsigned long *bitmap1,
|
||||
const unsigned long *bitmap2, unsigned int nbits);
|
||||
bool __bitmap_equal(const unsigned long *bitmap1,
|
||||
const unsigned long *bitmap2, unsigned int nbits);
|
||||
bool __pure __bitmap_or_equal(const unsigned long *src1,
|
||||
const unsigned long *src2,
|
||||
const unsigned long *src3,
|
||||
|
|
@ -146,22 +149,24 @@ 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,
|
||||
const unsigned long *mask, unsigned int nbits);
|
||||
int __bitmap_intersects(const unsigned long *bitmap1,
|
||||
const unsigned long *bitmap2, unsigned int nbits);
|
||||
int __bitmap_subset(const unsigned long *bitmap1,
|
||||
const unsigned long *bitmap2, unsigned int nbits);
|
||||
int __bitmap_weight(const unsigned long *bitmap, unsigned int nbits);
|
||||
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);
|
||||
unsigned int __bitmap_weight(const unsigned long *bitmap, unsigned int nbits);
|
||||
unsigned int __bitmap_weight_and(const unsigned long *bitmap1,
|
||||
const unsigned long *bitmap2, 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);
|
||||
|
||||
|
|
@ -220,7 +225,6 @@ void bitmap_copy_le(unsigned long *dst, const unsigned long *src, unsigned int n
|
|||
#else
|
||||
#define bitmap_copy_le bitmap_copy
|
||||
#endif
|
||||
unsigned int bitmap_ord_to_pos(const unsigned long *bitmap, unsigned int ord, unsigned int nbits);
|
||||
int bitmap_print_to_pagebuf(bool list, char *buf,
|
||||
const unsigned long *maskp, int nmaskbits);
|
||||
|
||||
|
|
@ -236,20 +240,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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -264,8 +280,12 @@ static inline void bitmap_copy_clear_tail(unsigned long *dst,
|
|||
}
|
||||
|
||||
/*
|
||||
* On 32-bit systems bitmaps are represented as u32 arrays internally, and
|
||||
* therefore conversion is not needed when copying data from/to arrays of u32.
|
||||
* On 32-bit systems bitmaps are represented as u32 arrays internally. On LE64
|
||||
* machines the order of hi and lo parts of numbers match the bitmap structure.
|
||||
* In both cases conversion is not needed when copying data from/to arrays of
|
||||
* u32. But in LE64 case, typecast in bitmap_copy_clear_tail() may lead
|
||||
* to out-of-bound access. To avoid that, both LE and BE variants of 64-bit
|
||||
* architectures are not using bitmap_copy_clear_tail().
|
||||
*/
|
||||
#if BITS_PER_LONG == 64
|
||||
void bitmap_from_arr32(unsigned long *bitmap, const u32 *buf,
|
||||
|
|
@ -281,7 +301,23 @@ void bitmap_to_arr32(u32 *buf, const unsigned long *bitmap,
|
|||
(const unsigned long *) (bitmap), (nbits))
|
||||
#endif
|
||||
|
||||
static inline int bitmap_and(unsigned long *dst, const unsigned long *src1,
|
||||
/*
|
||||
* On 64-bit systems bitmaps are represented as u64 arrays internally. On LE32
|
||||
* machines the order of hi and lo parts of numbers match the bitmap structure.
|
||||
* In both cases conversion is not needed when copying data from/to arrays of
|
||||
* u64.
|
||||
*/
|
||||
#if (BITS_PER_LONG == 32) && defined(__BIG_ENDIAN)
|
||||
void bitmap_from_arr64(unsigned long *bitmap, const u64 *buf, unsigned int nbits);
|
||||
void bitmap_to_arr64(u64 *buf, const unsigned long *bitmap, unsigned int nbits);
|
||||
#else
|
||||
#define bitmap_from_arr64(bitmap, buf, nbits) \
|
||||
bitmap_copy_clear_tail((unsigned long *)(bitmap), (const unsigned long *)(buf), (nbits))
|
||||
#define bitmap_to_arr64(buf, bitmap, nbits) \
|
||||
bitmap_copy_clear_tail((unsigned long *)(buf), (const unsigned long *)(bitmap), (nbits))
|
||||
#endif
|
||||
|
||||
static inline bool bitmap_and(unsigned long *dst, const unsigned long *src1,
|
||||
const unsigned long *src2, unsigned int nbits)
|
||||
{
|
||||
if (small_const_nbits(nbits))
|
||||
|
|
@ -307,7 +343,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))
|
||||
|
|
@ -331,8 +367,8 @@ static inline void bitmap_complement(unsigned long *dst, const unsigned long *sr
|
|||
#endif
|
||||
#define BITMAP_MEM_MASK (BITMAP_MEM_ALIGNMENT - 1)
|
||||
|
||||
static inline int bitmap_equal(const unsigned long *src1,
|
||||
const unsigned long *src2, unsigned int nbits)
|
||||
static inline bool bitmap_equal(const unsigned long *src1,
|
||||
const unsigned long *src2, unsigned int nbits)
|
||||
{
|
||||
if (small_const_nbits(nbits))
|
||||
return !((*src1 ^ *src2) & BITMAP_LAST_WORD_MASK(nbits));
|
||||
|
|
@ -362,8 +398,9 @@ static inline bool bitmap_or_equal(const unsigned long *src1,
|
|||
return !(((*src1 | *src2) ^ *src3) & BITMAP_LAST_WORD_MASK(nbits));
|
||||
}
|
||||
|
||||
static inline int bitmap_intersects(const unsigned long *src1,
|
||||
const unsigned long *src2, unsigned int nbits)
|
||||
static inline bool bitmap_intersects(const unsigned long *src1,
|
||||
const unsigned long *src2,
|
||||
unsigned int nbits)
|
||||
{
|
||||
if (small_const_nbits(nbits))
|
||||
return ((*src1 & *src2) & BITMAP_LAST_WORD_MASK(nbits)) != 0;
|
||||
|
|
@ -371,8 +408,8 @@ static inline int bitmap_intersects(const unsigned long *src1,
|
|||
return __bitmap_intersects(src1, src2, nbits);
|
||||
}
|
||||
|
||||
static inline int bitmap_subset(const unsigned long *src1,
|
||||
const unsigned long *src2, unsigned int nbits)
|
||||
static inline bool bitmap_subset(const unsigned long *src1,
|
||||
const unsigned long *src2, unsigned int nbits)
|
||||
{
|
||||
if (small_const_nbits(nbits))
|
||||
return ! ((*src1 & ~(*src2)) & BITMAP_LAST_WORD_MASK(nbits));
|
||||
|
|
@ -396,18 +433,30 @@ 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));
|
||||
return __bitmap_weight(src, nbits);
|
||||
}
|
||||
|
||||
static __always_inline
|
||||
unsigned long bitmap_weight_and(const unsigned long *src1,
|
||||
const unsigned long *src2, unsigned int nbits)
|
||||
{
|
||||
if (small_const_nbits(nbits))
|
||||
return hweight_long(*src1 & *src2 & BITMAP_LAST_WORD_MASK(nbits));
|
||||
return __bitmap_weight_and(src1, src2, nbits);
|
||||
}
|
||||
|
||||
static __always_inline void bitmap_set(unsigned long *map, unsigned int start,
|
||||
unsigned int nbits)
|
||||
{
|
||||
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) &&
|
||||
|
|
@ -422,6 +471,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) &&
|
||||
|
|
@ -514,10 +565,7 @@ static inline void bitmap_next_set_region(unsigned long *bitmap,
|
|||
*/
|
||||
static inline void bitmap_from_u64(unsigned long *dst, u64 mask)
|
||||
{
|
||||
dst[0] = mask & ULONG_MAX;
|
||||
|
||||
if (sizeof(mask) > sizeof(unsigned long))
|
||||
dst[1] = mask >> 32;
|
||||
bitmap_from_arr64(dst, &mask, 64);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
@ -196,6 +247,25 @@ static inline unsigned long __ffs64(u64 word)
|
|||
return __ffs((unsigned long)word);
|
||||
}
|
||||
|
||||
/**
|
||||
* fns - find N'th set bit in a word
|
||||
* @word: The word to search
|
||||
* @n: Bit to find
|
||||
*/
|
||||
static inline unsigned long fns(unsigned long word, unsigned int n)
|
||||
{
|
||||
unsigned int bit;
|
||||
|
||||
while (word) {
|
||||
bit = __ffs(word);
|
||||
if (n-- == 0)
|
||||
return bit;
|
||||
__clear_bit(bit, &word);
|
||||
}
|
||||
|
||||
return BITS_PER_LONG;
|
||||
}
|
||||
|
||||
/**
|
||||
* assign_bit - Assign value to a bit in memory
|
||||
* @nr: the bit to set
|
||||
|
|
@ -277,10 +347,10 @@ static __always_inline void __assign_bit(long nr, volatile unsigned long *addr,
|
|||
const typeof(*(ptr)) mask__ = (mask), bits__ = (bits); \
|
||||
typeof(*(ptr)) old__, new__; \
|
||||
\
|
||||
old__ = READ_ONCE(*(ptr)); \
|
||||
do { \
|
||||
old__ = READ_ONCE(*(ptr)); \
|
||||
new__ = (old__ & ~mask__) | bits__; \
|
||||
} while (cmpxchg(ptr, old__, new__) != old__); \
|
||||
} while (!try_cmpxchg(ptr, &old__, new__)); \
|
||||
\
|
||||
old__; \
|
||||
})
|
||||
|
|
@ -292,11 +362,12 @@ static __always_inline void __assign_bit(long nr, volatile unsigned long *addr,
|
|||
const typeof(*(ptr)) clear__ = (clear), test__ = (test);\
|
||||
typeof(*(ptr)) old__, new__; \
|
||||
\
|
||||
old__ = READ_ONCE(*(ptr)); \
|
||||
do { \
|
||||
old__ = READ_ONCE(*(ptr)); \
|
||||
if (old__ & test__) \
|
||||
break; \
|
||||
new__ = old__ & ~clear__; \
|
||||
} while (!(old__ & test__) && \
|
||||
cmpxchg(ptr, old__, new__) != old__); \
|
||||
} while (!try_cmpxchg(ptr, &old__, new__)); \
|
||||
\
|
||||
!(old__ & test__); \
|
||||
})
|
||||
|
|
|
|||
|
|
@ -14,713 +14,38 @@
|
|||
* Nauman Rafique <nauman@google.com>
|
||||
*/
|
||||
|
||||
#include <linux/cgroup.h>
|
||||
#include <linux/percpu.h>
|
||||
#include <linux/percpu_counter.h>
|
||||
#include <linux/u64_stats_sync.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/radix-tree.h>
|
||||
#include <linux/blkdev.h>
|
||||
#include <linux/atomic.h>
|
||||
#include <linux/kthread.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
/* percpu_counter batch for blkg_[rw]stats, per-cpu drift doesn't matter */
|
||||
#define BLKG_STAT_CPU_BATCH (INT_MAX / 2)
|
||||
struct bio;
|
||||
struct cgroup_subsys_state;
|
||||
struct gendisk;
|
||||
|
||||
/* Max limits for throttle policy */
|
||||
#define THROTL_IOPS_MAX UINT_MAX
|
||||
#define FC_APPID_LEN 129
|
||||
|
||||
|
||||
#ifdef CONFIG_BLK_CGROUP
|
||||
|
||||
enum blkg_iostat_type {
|
||||
BLKG_IOSTAT_READ,
|
||||
BLKG_IOSTAT_WRITE,
|
||||
BLKG_IOSTAT_DISCARD,
|
||||
|
||||
BLKG_IOSTAT_NR,
|
||||
};
|
||||
|
||||
struct blkcg_gq;
|
||||
|
||||
struct blkcg {
|
||||
struct cgroup_subsys_state css;
|
||||
spinlock_t lock;
|
||||
refcount_t online_pin;
|
||||
|
||||
struct radix_tree_root blkg_tree;
|
||||
struct blkcg_gq __rcu *blkg_hint;
|
||||
struct hlist_head blkg_list;
|
||||
|
||||
struct blkcg_policy_data *cpd[BLKCG_MAX_POLS];
|
||||
|
||||
struct list_head all_blkcgs_node;
|
||||
#ifdef CONFIG_BLK_CGROUP_FC_APPID
|
||||
char fc_app_id[FC_APPID_LEN];
|
||||
#endif
|
||||
#ifdef CONFIG_CGROUP_WRITEBACK
|
||||
struct list_head cgwb_list;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct blkg_iostat {
|
||||
u64 bytes[BLKG_IOSTAT_NR];
|
||||
u64 ios[BLKG_IOSTAT_NR];
|
||||
};
|
||||
|
||||
struct blkg_iostat_set {
|
||||
struct u64_stats_sync sync;
|
||||
struct blkg_iostat cur;
|
||||
struct blkg_iostat last;
|
||||
};
|
||||
|
||||
/*
|
||||
* A blkcg_gq (blkg) is association between a block cgroup (blkcg) and a
|
||||
* request_queue (q). This is used by blkcg policies which need to track
|
||||
* information per blkcg - q pair.
|
||||
*
|
||||
* There can be multiple active blkcg policies and each blkg:policy pair is
|
||||
* represented by a blkg_policy_data which is allocated and freed by each
|
||||
* policy's pd_alloc/free_fn() methods. A policy can allocate private data
|
||||
* area by allocating larger data structure which embeds blkg_policy_data
|
||||
* at the beginning.
|
||||
*/
|
||||
struct blkg_policy_data {
|
||||
/* the blkg and policy id this per-policy data belongs to */
|
||||
struct blkcg_gq *blkg;
|
||||
int plid;
|
||||
};
|
||||
|
||||
/*
|
||||
* Policies that need to keep per-blkcg data which is independent from any
|
||||
* request_queue associated to it should implement cpd_alloc/free_fn()
|
||||
* methods. A policy can allocate private data area by allocating larger
|
||||
* data structure which embeds blkcg_policy_data at the beginning.
|
||||
* cpd_init() is invoked to let each policy handle per-blkcg data.
|
||||
*/
|
||||
struct blkcg_policy_data {
|
||||
/* the blkcg and policy id this per-policy data belongs to */
|
||||
struct blkcg *blkcg;
|
||||
int plid;
|
||||
};
|
||||
|
||||
/* association between a blk cgroup and a request queue */
|
||||
struct blkcg_gq {
|
||||
/* Pointer to the associated request_queue */
|
||||
struct request_queue *q;
|
||||
struct list_head q_node;
|
||||
struct hlist_node blkcg_node;
|
||||
struct blkcg *blkcg;
|
||||
|
||||
/* all non-root blkcg_gq's are guaranteed to have access to parent */
|
||||
struct blkcg_gq *parent;
|
||||
|
||||
/* reference count */
|
||||
struct percpu_ref refcnt;
|
||||
|
||||
/* is this blkg online? protected by both blkcg and q locks */
|
||||
bool online;
|
||||
|
||||
struct blkg_iostat_set __percpu *iostat_cpu;
|
||||
struct blkg_iostat_set iostat;
|
||||
|
||||
struct blkg_policy_data *pd[BLKCG_MAX_POLS];
|
||||
|
||||
spinlock_t async_bio_lock;
|
||||
struct bio_list async_bios;
|
||||
struct work_struct async_bio_work;
|
||||
|
||||
atomic_t use_delay;
|
||||
atomic64_t delay_nsec;
|
||||
atomic64_t delay_start;
|
||||
u64 last_delay;
|
||||
int last_use;
|
||||
|
||||
struct rcu_head rcu_head;
|
||||
};
|
||||
|
||||
typedef struct blkcg_policy_data *(blkcg_pol_alloc_cpd_fn)(gfp_t gfp);
|
||||
typedef void (blkcg_pol_init_cpd_fn)(struct blkcg_policy_data *cpd);
|
||||
typedef void (blkcg_pol_free_cpd_fn)(struct blkcg_policy_data *cpd);
|
||||
typedef void (blkcg_pol_bind_cpd_fn)(struct blkcg_policy_data *cpd);
|
||||
typedef struct blkg_policy_data *(blkcg_pol_alloc_pd_fn)(gfp_t gfp,
|
||||
struct request_queue *q, struct blkcg *blkcg);
|
||||
typedef void (blkcg_pol_init_pd_fn)(struct blkg_policy_data *pd);
|
||||
typedef void (blkcg_pol_online_pd_fn)(struct blkg_policy_data *pd);
|
||||
typedef void (blkcg_pol_offline_pd_fn)(struct blkg_policy_data *pd);
|
||||
typedef void (blkcg_pol_free_pd_fn)(struct blkg_policy_data *pd);
|
||||
typedef void (blkcg_pol_reset_pd_stats_fn)(struct blkg_policy_data *pd);
|
||||
typedef bool (blkcg_pol_stat_pd_fn)(struct blkg_policy_data *pd,
|
||||
struct seq_file *s);
|
||||
|
||||
struct blkcg_policy {
|
||||
int plid;
|
||||
/* cgroup files for the policy */
|
||||
struct cftype *dfl_cftypes;
|
||||
struct cftype *legacy_cftypes;
|
||||
|
||||
/* operations */
|
||||
blkcg_pol_alloc_cpd_fn *cpd_alloc_fn;
|
||||
blkcg_pol_init_cpd_fn *cpd_init_fn;
|
||||
blkcg_pol_free_cpd_fn *cpd_free_fn;
|
||||
blkcg_pol_bind_cpd_fn *cpd_bind_fn;
|
||||
|
||||
blkcg_pol_alloc_pd_fn *pd_alloc_fn;
|
||||
blkcg_pol_init_pd_fn *pd_init_fn;
|
||||
blkcg_pol_online_pd_fn *pd_online_fn;
|
||||
blkcg_pol_offline_pd_fn *pd_offline_fn;
|
||||
blkcg_pol_free_pd_fn *pd_free_fn;
|
||||
blkcg_pol_reset_pd_stats_fn *pd_reset_stats_fn;
|
||||
blkcg_pol_stat_pd_fn *pd_stat_fn;
|
||||
};
|
||||
|
||||
extern struct blkcg blkcg_root;
|
||||
extern struct cgroup_subsys_state * const blkcg_root_css;
|
||||
extern bool blkcg_debug_stats;
|
||||
|
||||
struct blkcg_gq *blkg_lookup_slowpath(struct blkcg *blkcg,
|
||||
struct request_queue *q, bool update_hint);
|
||||
int blkcg_init_queue(struct request_queue *q);
|
||||
void blkcg_exit_queue(struct request_queue *q);
|
||||
|
||||
/* Blkio controller policy registration */
|
||||
int blkcg_policy_register(struct blkcg_policy *pol);
|
||||
void blkcg_policy_unregister(struct blkcg_policy *pol);
|
||||
int blkcg_activate_policy(struct request_queue *q,
|
||||
const struct blkcg_policy *pol);
|
||||
void blkcg_deactivate_policy(struct request_queue *q,
|
||||
const struct blkcg_policy *pol);
|
||||
|
||||
const char *blkg_dev_name(struct blkcg_gq *blkg);
|
||||
void blkcg_print_blkgs(struct seq_file *sf, struct blkcg *blkcg,
|
||||
u64 (*prfill)(struct seq_file *,
|
||||
struct blkg_policy_data *, int),
|
||||
const struct blkcg_policy *pol, int data,
|
||||
bool show_total);
|
||||
u64 __blkg_prfill_u64(struct seq_file *sf, struct blkg_policy_data *pd, u64 v);
|
||||
|
||||
struct blkg_conf_ctx {
|
||||
struct block_device *bdev;
|
||||
struct blkcg_gq *blkg;
|
||||
char *body;
|
||||
};
|
||||
|
||||
struct block_device *blkcg_conf_open_bdev(char **inputp);
|
||||
int blkg_conf_prep(struct blkcg *blkcg, const struct blkcg_policy *pol,
|
||||
char *input, struct blkg_conf_ctx *ctx);
|
||||
void blkg_conf_finish(struct blkg_conf_ctx *ctx);
|
||||
|
||||
/**
|
||||
* blkcg_css - find the current css
|
||||
*
|
||||
* Find the css associated with either the kthread or the current task.
|
||||
* This may return a dying css, so it is up to the caller to use tryget logic
|
||||
* to confirm it is alive and well.
|
||||
*/
|
||||
static inline struct cgroup_subsys_state *blkcg_css(void)
|
||||
{
|
||||
struct cgroup_subsys_state *css;
|
||||
|
||||
css = kthread_blkcg();
|
||||
if (css)
|
||||
return css;
|
||||
return task_css(current, io_cgrp_id);
|
||||
}
|
||||
|
||||
static inline struct blkcg *css_to_blkcg(struct cgroup_subsys_state *css)
|
||||
{
|
||||
return css ? container_of(css, struct blkcg, css) : NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* __bio_blkcg - internal, inconsistent version to get blkcg
|
||||
*
|
||||
* DO NOT USE.
|
||||
* This function is inconsistent and consequently is dangerous to use. The
|
||||
* first part of the function returns a blkcg where a reference is owned by the
|
||||
* bio. This means it does not need to be rcu protected as it cannot go away
|
||||
* with the bio owning a reference to it. However, the latter potentially gets
|
||||
* it from task_css(). This can race against task migration and the cgroup
|
||||
* dying. It is also semantically different as it must be called rcu protected
|
||||
* and is susceptible to failure when trying to get a reference to it.
|
||||
* Therefore, it is not ok to assume that *_get() will always succeed on the
|
||||
* blkcg returned here.
|
||||
*/
|
||||
static inline struct blkcg *__bio_blkcg(struct bio *bio)
|
||||
{
|
||||
if (bio && bio->bi_blkg)
|
||||
return bio->bi_blkg->blkcg;
|
||||
return css_to_blkcg(blkcg_css());
|
||||
}
|
||||
|
||||
/**
|
||||
* bio_blkcg - grab the blkcg associated with a bio
|
||||
* @bio: target bio
|
||||
*
|
||||
* This returns the blkcg associated with a bio, %NULL if not associated.
|
||||
* Callers are expected to either handle %NULL or know association has been
|
||||
* done prior to calling this.
|
||||
*/
|
||||
static inline struct blkcg *bio_blkcg(struct bio *bio)
|
||||
{
|
||||
if (bio && bio->bi_blkg)
|
||||
return bio->bi_blkg->blkcg;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline bool blk_cgroup_congested(void)
|
||||
{
|
||||
struct cgroup_subsys_state *css;
|
||||
bool ret = false;
|
||||
|
||||
rcu_read_lock();
|
||||
css = kthread_blkcg();
|
||||
if (!css)
|
||||
css = task_css(current, io_cgrp_id);
|
||||
while (css) {
|
||||
if (atomic_read(&css->cgroup->congestion_count)) {
|
||||
ret = true;
|
||||
break;
|
||||
}
|
||||
css = css->parent;
|
||||
}
|
||||
rcu_read_unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* bio_issue_as_root_blkg - see if this bio needs to be issued as root blkg
|
||||
* @return: true if this bio needs to be submitted with the root blkg context.
|
||||
*
|
||||
* In order to avoid priority inversions we sometimes need to issue a bio as if
|
||||
* it were attached to the root blkg, and then backcharge to the actual owning
|
||||
* blkg. The idea is we do bio_blkcg() to look up the actual context for the
|
||||
* bio and attach the appropriate blkg to the bio. Then we call this helper and
|
||||
* if it is true run with the root blkg for that queue and then do any
|
||||
* backcharging to the originating cgroup once the io is complete.
|
||||
*/
|
||||
static inline bool bio_issue_as_root_blkg(struct bio *bio)
|
||||
{
|
||||
return (bio->bi_opf & (REQ_META | REQ_SWAP)) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* blkcg_parent - get the parent of a blkcg
|
||||
* @blkcg: blkcg of interest
|
||||
*
|
||||
* Return the parent blkcg of @blkcg. Can be called anytime.
|
||||
*/
|
||||
static inline struct blkcg *blkcg_parent(struct blkcg *blkcg)
|
||||
{
|
||||
return css_to_blkcg(blkcg->css.parent);
|
||||
}
|
||||
|
||||
/**
|
||||
* __blkg_lookup - internal version of blkg_lookup()
|
||||
* @blkcg: blkcg of interest
|
||||
* @q: request_queue of interest
|
||||
* @update_hint: whether to update lookup hint with the result or not
|
||||
*
|
||||
* This is internal version and shouldn't be used by policy
|
||||
* implementations. Looks up blkgs for the @blkcg - @q pair regardless of
|
||||
* @q's bypass state. If @update_hint is %true, the caller should be
|
||||
* holding @q->queue_lock and lookup hint is updated on success.
|
||||
*/
|
||||
static inline struct blkcg_gq *__blkg_lookup(struct blkcg *blkcg,
|
||||
struct request_queue *q,
|
||||
bool update_hint)
|
||||
{
|
||||
struct blkcg_gq *blkg;
|
||||
|
||||
if (blkcg == &blkcg_root)
|
||||
return q->root_blkg;
|
||||
|
||||
blkg = rcu_dereference(blkcg->blkg_hint);
|
||||
if (blkg && blkg->q == q)
|
||||
return blkg;
|
||||
|
||||
return blkg_lookup_slowpath(blkcg, q, update_hint);
|
||||
}
|
||||
|
||||
/**
|
||||
* blkg_lookup - lookup blkg for the specified blkcg - q pair
|
||||
* @blkcg: blkcg of interest
|
||||
* @q: request_queue of interest
|
||||
*
|
||||
* Lookup blkg for the @blkcg - @q pair. This function should be called
|
||||
* under RCU read lock.
|
||||
*/
|
||||
static inline struct blkcg_gq *blkg_lookup(struct blkcg *blkcg,
|
||||
struct request_queue *q)
|
||||
{
|
||||
WARN_ON_ONCE(!rcu_read_lock_held());
|
||||
return __blkg_lookup(blkcg, q, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* blk_queue_root_blkg - return blkg for the (blkcg_root, @q) pair
|
||||
* @q: request_queue of interest
|
||||
*
|
||||
* Lookup blkg for @q at the root level. See also blkg_lookup().
|
||||
*/
|
||||
static inline struct blkcg_gq *blk_queue_root_blkg(struct request_queue *q)
|
||||
{
|
||||
return q->root_blkg;
|
||||
}
|
||||
|
||||
/**
|
||||
* blkg_to_pdata - get policy private data
|
||||
* @blkg: blkg of interest
|
||||
* @pol: policy of interest
|
||||
*
|
||||
* Return pointer to private data associated with the @blkg-@pol pair.
|
||||
*/
|
||||
static inline struct blkg_policy_data *blkg_to_pd(struct blkcg_gq *blkg,
|
||||
struct blkcg_policy *pol)
|
||||
{
|
||||
return blkg ? blkg->pd[pol->plid] : NULL;
|
||||
}
|
||||
|
||||
static inline struct blkcg_policy_data *blkcg_to_cpd(struct blkcg *blkcg,
|
||||
struct blkcg_policy *pol)
|
||||
{
|
||||
return blkcg ? blkcg->cpd[pol->plid] : NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* pdata_to_blkg - get blkg associated with policy private data
|
||||
* @pd: policy private data of interest
|
||||
*
|
||||
* @pd is policy private data. Determine the blkg it's associated with.
|
||||
*/
|
||||
static inline struct blkcg_gq *pd_to_blkg(struct blkg_policy_data *pd)
|
||||
{
|
||||
return pd ? pd->blkg : NULL;
|
||||
}
|
||||
|
||||
static inline struct blkcg *cpd_to_blkcg(struct blkcg_policy_data *cpd)
|
||||
{
|
||||
return cpd ? cpd->blkcg : NULL;
|
||||
}
|
||||
|
||||
extern void blkcg_destroy_blkgs(struct blkcg *blkcg);
|
||||
|
||||
/**
|
||||
* blkcg_pin_online - pin online state
|
||||
* @blkcg: blkcg of interest
|
||||
*
|
||||
* While pinned, a blkcg is kept online. This is primarily used to
|
||||
* impedance-match blkg and cgwb lifetimes so that blkg doesn't go offline
|
||||
* while an associated cgwb is still active.
|
||||
*/
|
||||
static inline void blkcg_pin_online(struct blkcg *blkcg)
|
||||
{
|
||||
refcount_inc(&blkcg->online_pin);
|
||||
}
|
||||
|
||||
/**
|
||||
* blkcg_unpin_online - unpin online state
|
||||
* @blkcg: blkcg of interest
|
||||
*
|
||||
* This is primarily used to impedance-match blkg and cgwb lifetimes so
|
||||
* that blkg doesn't go offline while an associated cgwb is still active.
|
||||
* When this count goes to zero, all active cgwbs have finished so the
|
||||
* blkcg can continue destruction by calling blkcg_destroy_blkgs().
|
||||
*/
|
||||
static inline void blkcg_unpin_online(struct blkcg *blkcg)
|
||||
{
|
||||
do {
|
||||
if (!refcount_dec_and_test(&blkcg->online_pin))
|
||||
break;
|
||||
blkcg_destroy_blkgs(blkcg);
|
||||
blkcg = blkcg_parent(blkcg);
|
||||
} while (blkcg);
|
||||
}
|
||||
|
||||
/**
|
||||
* blkg_path - format cgroup path of blkg
|
||||
* @blkg: blkg of interest
|
||||
* @buf: target buffer
|
||||
* @buflen: target buffer length
|
||||
*
|
||||
* Format the path of the cgroup of @blkg into @buf.
|
||||
*/
|
||||
static inline int blkg_path(struct blkcg_gq *blkg, char *buf, int buflen)
|
||||
{
|
||||
return cgroup_path(blkg->blkcg->css.cgroup, buf, buflen);
|
||||
}
|
||||
|
||||
/**
|
||||
* blkg_get - get a blkg reference
|
||||
* @blkg: blkg to get
|
||||
*
|
||||
* The caller should be holding an existing reference.
|
||||
*/
|
||||
static inline void blkg_get(struct blkcg_gq *blkg)
|
||||
{
|
||||
percpu_ref_get(&blkg->refcnt);
|
||||
}
|
||||
|
||||
/**
|
||||
* blkg_tryget - try and get a blkg reference
|
||||
* @blkg: blkg to get
|
||||
*
|
||||
* This is for use when doing an RCU lookup of the blkg. We may be in the midst
|
||||
* of freeing this blkg, so we can only use it if the refcnt is not zero.
|
||||
*/
|
||||
static inline bool blkg_tryget(struct blkcg_gq *blkg)
|
||||
{
|
||||
return blkg && percpu_ref_tryget(&blkg->refcnt);
|
||||
}
|
||||
|
||||
/**
|
||||
* blkg_put - put a blkg reference
|
||||
* @blkg: blkg to put
|
||||
*/
|
||||
static inline void blkg_put(struct blkcg_gq *blkg)
|
||||
{
|
||||
percpu_ref_put(&blkg->refcnt);
|
||||
}
|
||||
|
||||
/**
|
||||
* blkg_for_each_descendant_pre - pre-order walk of a blkg's descendants
|
||||
* @d_blkg: loop cursor pointing to the current descendant
|
||||
* @pos_css: used for iteration
|
||||
* @p_blkg: target blkg to walk descendants of
|
||||
*
|
||||
* Walk @c_blkg through the descendants of @p_blkg. Must be used with RCU
|
||||
* read locked. If called under either blkcg or queue lock, the iteration
|
||||
* is guaranteed to include all and only online blkgs. The caller may
|
||||
* update @pos_css by calling css_rightmost_descendant() to skip subtree.
|
||||
* @p_blkg is included in the iteration and the first node to be visited.
|
||||
*/
|
||||
#define blkg_for_each_descendant_pre(d_blkg, pos_css, p_blkg) \
|
||||
css_for_each_descendant_pre((pos_css), &(p_blkg)->blkcg->css) \
|
||||
if (((d_blkg) = __blkg_lookup(css_to_blkcg(pos_css), \
|
||||
(p_blkg)->q, false)))
|
||||
|
||||
/**
|
||||
* blkg_for_each_descendant_post - post-order walk of a blkg's descendants
|
||||
* @d_blkg: loop cursor pointing to the current descendant
|
||||
* @pos_css: used for iteration
|
||||
* @p_blkg: target blkg to walk descendants of
|
||||
*
|
||||
* Similar to blkg_for_each_descendant_pre() but performs post-order
|
||||
* traversal instead. Synchronization rules are the same. @p_blkg is
|
||||
* included in the iteration and the last node to be visited.
|
||||
*/
|
||||
#define blkg_for_each_descendant_post(d_blkg, pos_css, p_blkg) \
|
||||
css_for_each_descendant_post((pos_css), &(p_blkg)->blkcg->css) \
|
||||
if (((d_blkg) = __blkg_lookup(css_to_blkcg(pos_css), \
|
||||
(p_blkg)->q, false)))
|
||||
|
||||
bool __blkcg_punt_bio_submit(struct bio *bio);
|
||||
|
||||
static inline bool blkcg_punt_bio_submit(struct bio *bio)
|
||||
{
|
||||
if (bio->bi_opf & REQ_CGROUP_PUNT)
|
||||
return __blkcg_punt_bio_submit(bio);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline void blkcg_bio_issue_init(struct bio *bio)
|
||||
{
|
||||
bio_issue_init(&bio->bi_issue, bio_sectors(bio));
|
||||
}
|
||||
|
||||
static inline void blkcg_use_delay(struct blkcg_gq *blkg)
|
||||
{
|
||||
if (WARN_ON_ONCE(atomic_read(&blkg->use_delay) < 0))
|
||||
return;
|
||||
if (atomic_add_return(1, &blkg->use_delay) == 1)
|
||||
atomic_inc(&blkg->blkcg->css.cgroup->congestion_count);
|
||||
}
|
||||
|
||||
static inline int blkcg_unuse_delay(struct blkcg_gq *blkg)
|
||||
{
|
||||
int old = atomic_read(&blkg->use_delay);
|
||||
|
||||
if (WARN_ON_ONCE(old < 0))
|
||||
return 0;
|
||||
if (old == 0)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* We do this song and dance because we can race with somebody else
|
||||
* adding or removing delay. If we just did an atomic_dec we'd end up
|
||||
* negative and we'd already be in trouble. We need to subtract 1 and
|
||||
* then check to see if we were the last delay so we can drop the
|
||||
* congestion count on the cgroup.
|
||||
*/
|
||||
while (old) {
|
||||
int cur = atomic_cmpxchg(&blkg->use_delay, old, old - 1);
|
||||
if (cur == old)
|
||||
break;
|
||||
old = cur;
|
||||
}
|
||||
|
||||
if (old == 0)
|
||||
return 0;
|
||||
if (old == 1)
|
||||
atomic_dec(&blkg->blkcg->css.cgroup->congestion_count);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* blkcg_set_delay - Enable allocator delay mechanism with the specified delay amount
|
||||
* @blkg: target blkg
|
||||
* @delay: delay duration in nsecs
|
||||
*
|
||||
* When enabled with this function, the delay is not decayed and must be
|
||||
* explicitly cleared with blkcg_clear_delay(). Must not be mixed with
|
||||
* blkcg_[un]use_delay() and blkcg_add_delay() usages.
|
||||
*/
|
||||
static inline void blkcg_set_delay(struct blkcg_gq *blkg, u64 delay)
|
||||
{
|
||||
int old = atomic_read(&blkg->use_delay);
|
||||
|
||||
/* We only want 1 person setting the congestion count for this blkg. */
|
||||
if (!old && atomic_cmpxchg(&blkg->use_delay, old, -1) == old)
|
||||
atomic_inc(&blkg->blkcg->css.cgroup->congestion_count);
|
||||
|
||||
atomic64_set(&blkg->delay_nsec, delay);
|
||||
}
|
||||
|
||||
/**
|
||||
* blkcg_clear_delay - Disable allocator delay mechanism
|
||||
* @blkg: target blkg
|
||||
*
|
||||
* Disable use_delay mechanism. See blkcg_set_delay().
|
||||
*/
|
||||
static inline void blkcg_clear_delay(struct blkcg_gq *blkg)
|
||||
{
|
||||
int old = atomic_read(&blkg->use_delay);
|
||||
|
||||
/* We only want 1 person clearing the congestion count for this blkg. */
|
||||
if (old && atomic_cmpxchg(&blkg->use_delay, old, 0) == old)
|
||||
atomic_dec(&blkg->blkcg->css.cgroup->congestion_count);
|
||||
}
|
||||
|
||||
void blk_cgroup_bio_start(struct bio *bio);
|
||||
void blkcg_add_delay(struct blkcg_gq *blkg, u64 now, u64 delta);
|
||||
void blkcg_schedule_throttle(struct request_queue *q, bool use_memdelay);
|
||||
void blkcg_schedule_throttle(struct gendisk *disk, bool use_memdelay);
|
||||
void blkcg_maybe_throttle_current(void);
|
||||
bool blk_cgroup_congested(void);
|
||||
void blkcg_pin_online(struct cgroup_subsys_state *blkcg_css);
|
||||
void blkcg_unpin_online(struct cgroup_subsys_state *blkcg_css);
|
||||
struct list_head *blkcg_get_cgwb_list(struct cgroup_subsys_state *css);
|
||||
struct cgroup_subsys_state *bio_blkcg_css(struct bio *bio);
|
||||
|
||||
#else /* CONFIG_BLK_CGROUP */
|
||||
|
||||
struct blkcg {
|
||||
};
|
||||
|
||||
struct blkg_policy_data {
|
||||
};
|
||||
|
||||
struct blkcg_policy_data {
|
||||
};
|
||||
|
||||
struct blkcg_gq {
|
||||
};
|
||||
|
||||
struct blkcg_policy {
|
||||
};
|
||||
|
||||
#define blkcg_root_css ((struct cgroup_subsys_state *)ERR_PTR(-EINVAL))
|
||||
|
||||
static inline void blkcg_maybe_throttle_current(void) { }
|
||||
static inline bool blk_cgroup_congested(void) { return false; }
|
||||
|
||||
#ifdef CONFIG_BLOCK
|
||||
|
||||
static inline void blkcg_schedule_throttle(struct request_queue *q, bool use_memdelay) { }
|
||||
|
||||
static inline struct blkcg_gq *blkg_lookup(struct blkcg *blkcg, void *key) { return NULL; }
|
||||
static inline struct blkcg_gq *blk_queue_root_blkg(struct request_queue *q)
|
||||
{ return NULL; }
|
||||
static inline int blkcg_init_queue(struct request_queue *q) { return 0; }
|
||||
static inline void blkcg_exit_queue(struct request_queue *q) { }
|
||||
static inline int blkcg_policy_register(struct blkcg_policy *pol) { return 0; }
|
||||
static inline void blkcg_policy_unregister(struct blkcg_policy *pol) { }
|
||||
static inline int blkcg_activate_policy(struct request_queue *q,
|
||||
const struct blkcg_policy *pol) { return 0; }
|
||||
static inline void blkcg_deactivate_policy(struct request_queue *q,
|
||||
const struct blkcg_policy *pol) { }
|
||||
|
||||
static inline struct blkcg *__bio_blkcg(struct bio *bio) { return NULL; }
|
||||
static inline struct blkcg *bio_blkcg(struct bio *bio) { return NULL; }
|
||||
|
||||
static inline struct blkg_policy_data *blkg_to_pd(struct blkcg_gq *blkg,
|
||||
struct blkcg_policy *pol) { return NULL; }
|
||||
static inline struct blkcg_gq *pd_to_blkg(struct blkg_policy_data *pd) { return NULL; }
|
||||
static inline char *blkg_path(struct blkcg_gq *blkg) { return NULL; }
|
||||
static inline void blkg_get(struct blkcg_gq *blkg) { }
|
||||
static inline void blkg_put(struct blkcg_gq *blkg) { }
|
||||
|
||||
static inline bool blkcg_punt_bio_submit(struct bio *bio) { return false; }
|
||||
static inline void blkcg_bio_issue_init(struct bio *bio) { }
|
||||
static inline void blk_cgroup_bio_start(struct bio *bio) { }
|
||||
|
||||
#define blk_queue_for_each_rl(rl, q) \
|
||||
for ((rl) = &(q)->root_rl; (rl); (rl) = NULL)
|
||||
|
||||
#endif /* CONFIG_BLOCK */
|
||||
#endif /* CONFIG_BLK_CGROUP */
|
||||
|
||||
#ifdef CONFIG_BLK_CGROUP_FC_APPID
|
||||
/*
|
||||
* Sets the fc_app_id field associted to blkcg
|
||||
* @app_id: application identifier
|
||||
* @cgrp_id: cgroup id
|
||||
* @app_id_len: size of application identifier
|
||||
*/
|
||||
static inline int blkcg_set_fc_appid(char *app_id, u64 cgrp_id, size_t app_id_len)
|
||||
static inline struct cgroup_subsys_state *bio_blkcg_css(struct bio *bio)
|
||||
{
|
||||
struct cgroup *cgrp;
|
||||
struct cgroup_subsys_state *css;
|
||||
struct blkcg *blkcg;
|
||||
int ret = 0;
|
||||
|
||||
if (app_id_len > FC_APPID_LEN)
|
||||
return -EINVAL;
|
||||
|
||||
cgrp = cgroup_get_from_id(cgrp_id);
|
||||
if (!cgrp)
|
||||
return -ENOENT;
|
||||
css = cgroup_get_e_css(cgrp, &io_cgrp_subsys);
|
||||
if (!css) {
|
||||
ret = -ENOENT;
|
||||
goto out_cgrp_put;
|
||||
}
|
||||
blkcg = css_to_blkcg(css);
|
||||
/*
|
||||
* There is a slight race condition on setting the appid.
|
||||
* Worst case an I/O may not find the right id.
|
||||
* This is no different from the I/O we let pass while obtaining
|
||||
* the vmid from the fabric.
|
||||
* Adding the overhead of a lock is not necessary.
|
||||
*/
|
||||
strlcpy(blkcg->fc_app_id, app_id, app_id_len);
|
||||
css_put(css);
|
||||
out_cgrp_put:
|
||||
cgroup_put(cgrp);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* blkcg_get_fc_appid - get the fc app identifier associated with a bio
|
||||
* @bio: target bio
|
||||
*
|
||||
* On success return the fc_app_id, on failure return NULL
|
||||
*/
|
||||
static inline char *blkcg_get_fc_appid(struct bio *bio)
|
||||
{
|
||||
if (bio && bio->bi_blkg &&
|
||||
(bio->bi_blkg->blkcg->fc_app_id[0] != '\0'))
|
||||
return bio->bi_blkg->blkcg->fc_app_id;
|
||||
return NULL;
|
||||
}
|
||||
#else
|
||||
static inline int blkcg_set_fc_appid(char *buf, u64 id, size_t len) { return -EINVAL; }
|
||||
static inline char *blkcg_get_fc_appid(struct bio *bio) { return NULL; }
|
||||
#endif /*CONFIG_BLK_CGROUP_FC_APPID*/
|
||||
#endif /* CONFIG_BLK_CGROUP */
|
||||
|
||||
int blkcg_set_fc_appid(char *app_id, u64 cgrp_id, size_t app_id_len);
|
||||
char *blkcg_get_fc_appid(struct bio *bio);
|
||||
|
||||
#endif /* _BLK_CGROUP_H */
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ struct blk_integrity_iter {
|
|||
sector_t seed;
|
||||
unsigned int data_size;
|
||||
unsigned short interval;
|
||||
unsigned char tuple_size;
|
||||
const char *disk_name;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
struct blk_mq_queue_map;
|
||||
struct pci_dev;
|
||||
|
||||
int blk_mq_pci_map_queues(struct blk_mq_queue_map *qmap, struct pci_dev *pdev,
|
||||
int offset);
|
||||
void blk_mq_pci_map_queues(struct blk_mq_queue_map *qmap, struct pci_dev *pdev,
|
||||
int offset);
|
||||
|
||||
#endif /* _LINUX_BLK_MQ_PCI_H */
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
struct blk_mq_tag_set;
|
||||
struct ib_device;
|
||||
|
||||
int blk_mq_rdma_map_queues(struct blk_mq_queue_map *map,
|
||||
void blk_mq_rdma_map_queues(struct blk_mq_queue_map *map,
|
||||
struct ib_device *dev, int first_vec);
|
||||
|
||||
#endif /* _LINUX_BLK_MQ_RDMA_H */
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
struct blk_mq_queue_map;
|
||||
struct virtio_device;
|
||||
|
||||
int blk_mq_virtio_map_queues(struct blk_mq_queue_map *qmap,
|
||||
void blk_mq_virtio_map_queues(struct blk_mq_queue_map *qmap,
|
||||
struct virtio_device *vdev, int first_vec);
|
||||
|
||||
#endif /* _LINUX_BLK_MQ_VIRTIO_H */
|
||||
|
|
|
|||
|
|
@ -14,7 +14,12 @@ struct blk_flush_queue;
|
|||
#define BLKDEV_MIN_RQ 4
|
||||
#define BLKDEV_DEFAULT_RQ 128
|
||||
|
||||
typedef void (rq_end_io_fn)(struct request *, blk_status_t);
|
||||
enum rq_end_io_ret {
|
||||
RQ_END_IO_NONE,
|
||||
RQ_END_IO_FREE,
|
||||
};
|
||||
|
||||
typedef enum rq_end_io_ret (rq_end_io_fn)(struct request *, blk_status_t);
|
||||
|
||||
/*
|
||||
* request flags */
|
||||
|
|
@ -57,6 +62,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 +85,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;
|
||||
|
|
@ -163,7 +169,6 @@ struct request {
|
|||
struct rb_node rb_node; /* sort/lookup */
|
||||
struct bio_vec special_vec;
|
||||
void *completion_data;
|
||||
int error_count; /* for legacy drivers, don't use */
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -198,8 +203,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)
|
||||
{
|
||||
|
|
@ -266,9 +273,16 @@ static inline void rq_list_move(struct request **src, struct request **dst,
|
|||
rq_list_add(dst, rq);
|
||||
}
|
||||
|
||||
/**
|
||||
* enum blk_eh_timer_return - How the timeout handler should proceed
|
||||
* @BLK_EH_DONE: The block driver completed the command or will complete it at
|
||||
* a later time.
|
||||
* @BLK_EH_RESET_TIMER: Reset the request timer and continue waiting for the
|
||||
* request to complete.
|
||||
*/
|
||||
enum blk_eh_timer_return {
|
||||
BLK_EH_DONE, /* drivers has completed the command */
|
||||
BLK_EH_RESET_TIMER, /* reset timer and try again */
|
||||
BLK_EH_DONE,
|
||||
BLK_EH_RESET_TIMER,
|
||||
};
|
||||
|
||||
#define BLK_TAG_ALLOC_FIFO 0 /* allocate starting from 0 */
|
||||
|
|
@ -520,7 +534,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
|
||||
|
|
@ -575,7 +589,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.
|
||||
|
|
@ -628,7 +642,7 @@ struct blk_mq_ops {
|
|||
* @map_queues: This allows drivers specify their own queue mapping by
|
||||
* overriding the setup-time function that builds the mq_map.
|
||||
*/
|
||||
int (*map_queues)(struct blk_mq_tag_set *set);
|
||||
void (*map_queues)(struct blk_mq_tag_set *set);
|
||||
|
||||
#ifdef CONFIG_BLK_DEBUG_FS
|
||||
/**
|
||||
|
|
@ -687,10 +701,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,
|
||||
|
|
@ -711,10 +727,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);
|
||||
|
||||
/*
|
||||
|
|
@ -824,6 +840,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.
|
||||
|
|
@ -832,8 +853,10 @@ static inline bool blk_mq_add_to_batch(struct request *req,
|
|||
struct io_comp_batch *iob, int ioerror,
|
||||
void (*complete)(struct io_comp_batch *))
|
||||
{
|
||||
if (!iob || (req->rq_flags & RQF_ELV) || req->end_io || ioerror)
|
||||
if (!iob || (req->rq_flags & RQF_ELV) || ioerror ||
|
||||
(req->end_io && !blk_rq_is_passthrough(req)))
|
||||
return false;
|
||||
|
||||
if (!iob->complete)
|
||||
iob->complete = complete;
|
||||
else if (iob->complete != complete)
|
||||
|
|
@ -848,7 +871,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);
|
||||
|
|
@ -872,7 +894,7 @@ void blk_mq_freeze_queue_wait(struct request_queue *q);
|
|||
int blk_mq_freeze_queue_wait_timeout(struct request_queue *q,
|
||||
unsigned long timeout);
|
||||
|
||||
int blk_mq_map_queues(struct blk_mq_queue_map *qmap);
|
||||
void blk_mq_map_queues(struct blk_mq_queue_map *qmap);
|
||||
void blk_mq_update_nr_hw_queues(struct blk_mq_tag_set *set, int nr_hw_queues);
|
||||
|
||||
void blk_mq_quiesce_queue_nowait(struct request_queue *q);
|
||||
|
|
@ -917,8 +939,7 @@ static inline void *blk_mq_rq_to_pdu(struct request *rq)
|
|||
}
|
||||
|
||||
#define queue_for_each_hw_ctx(q, hctx, i) \
|
||||
for ((i) = 0; (i) < (q)->nr_hw_queues && \
|
||||
({ hctx = (q)->queue_hw_ctx[i]; 1; }); (i)++)
|
||||
xa_for_each(&(q)->hctx_table, (i), (hctx))
|
||||
|
||||
#define hctx_for_each_ctx(hctx, ctx, i) \
|
||||
for ((i) = 0; (i) < (hctx)->nr_ctx && \
|
||||
|
|
@ -952,29 +973,30 @@ int blk_rq_prep_clone(struct request *rq, struct request *rq_src,
|
|||
struct bio_set *bs, gfp_t gfp_mask,
|
||||
int (*bio_ctr)(struct bio *, struct bio *, void *), void *data);
|
||||
void blk_rq_unprep_clone(struct request *rq);
|
||||
blk_status_t blk_insert_cloned_request(struct request_queue *q,
|
||||
struct request *rq);
|
||||
blk_status_t blk_insert_cloned_request(struct request *rq);
|
||||
|
||||
struct rq_map_data {
|
||||
struct page **pages;
|
||||
int page_order;
|
||||
int nr_entries;
|
||||
unsigned long offset;
|
||||
int null_mapped;
|
||||
int from_user;
|
||||
unsigned short page_order;
|
||||
unsigned short nr_entries;
|
||||
bool null_mapped;
|
||||
bool from_user;
|
||||
};
|
||||
|
||||
int blk_rq_map_user(struct request_queue *, struct request *,
|
||||
struct rq_map_data *, void __user *, unsigned long, gfp_t);
|
||||
int blk_rq_map_user_io(struct request *, struct rq_map_data *,
|
||||
void __user *, unsigned long, gfp_t, bool, int, bool, int);
|
||||
int blk_rq_map_user_iov(struct request_queue *, struct request *,
|
||||
struct rq_map_data *, const struct iov_iter *, gfp_t);
|
||||
int blk_rq_unmap_user(struct bio *);
|
||||
int blk_rq_map_kern(struct request_queue *, struct request *, void *,
|
||||
unsigned int, gfp_t);
|
||||
int blk_rq_append_bio(struct request *rq, struct bio *bio);
|
||||
void blk_execute_rq_nowait(struct request *rq, bool at_head,
|
||||
rq_end_io_fn *end_io);
|
||||
void blk_execute_rq_nowait(struct request *rq, bool at_head);
|
||||
blk_status_t blk_execute_rq(struct request *rq, bool at_head);
|
||||
bool blk_rq_is_poll(struct request *rq);
|
||||
|
||||
struct req_iterator {
|
||||
struct bvec_iter iter;
|
||||
|
|
@ -1125,12 +1147,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);
|
||||
|
|
@ -1152,8 +1174,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)
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ struct block_device {
|
|||
unsigned long bd_stamp;
|
||||
bool bd_read_only; /* read-only policy */
|
||||
dev_t bd_dev;
|
||||
int bd_openers;
|
||||
atomic_t bd_openers;
|
||||
struct inode * bd_inode; /* will die */
|
||||
struct super_block * bd_super;
|
||||
void * bd_claiming;
|
||||
|
|
@ -85,8 +85,10 @@ struct block_device {
|
|||
*/
|
||||
#if defined(CONFIG_ALPHA) && !defined(__alpha_bwx__)
|
||||
typedef u32 __bitwise blk_status_t;
|
||||
typedef u32 blk_short_t;
|
||||
#else
|
||||
typedef u8 __bitwise blk_status_t;
|
||||
typedef u16 blk_short_t;
|
||||
#endif
|
||||
#define BLK_STS_OK 0
|
||||
#define BLK_STS_NOTSUPP ((__force blk_status_t)1)
|
||||
|
|
@ -103,6 +105,10 @@ typedef u8 __bitwise blk_status_t;
|
|||
/* hack for device mapper, don't use elsewhere: */
|
||||
#define BLK_STS_DM_REQUEUE ((__force blk_status_t)11)
|
||||
|
||||
/*
|
||||
* BLK_STS_AGAIN should only be returned if RQF_NOWAIT is set
|
||||
* and the bio would block (cf bio_wouldblock_error())
|
||||
*/
|
||||
#define BLK_STS_AGAIN ((__force blk_status_t)12)
|
||||
|
||||
/*
|
||||
|
|
@ -153,6 +159,13 @@ typedef u8 __bitwise blk_status_t;
|
|||
*/
|
||||
#define BLK_STS_ZONE_ACTIVE_RESOURCE ((__force blk_status_t)16)
|
||||
|
||||
/*
|
||||
* BLK_STS_OFFLINE is returned from the driver when the target device is offline
|
||||
* or is being taken offline. This could help differentiate the case where a
|
||||
* device is intentionally being shut down from a real I/O error.
|
||||
*/
|
||||
#define BLK_STS_OFFLINE ((__force blk_status_t)17)
|
||||
|
||||
/**
|
||||
* blk_path_error - returns true if error may be path related
|
||||
* @error: status the request was completed with
|
||||
|
|
@ -227,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
|
||||
|
||||
|
|
@ -237,13 +252,11 @@ 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 flags,
|
||||
* top bits REQ_OP. Use
|
||||
* accessors.
|
||||
blk_opf_t bi_opf; /* bottom bits REQ_OP, top bits
|
||||
* req_flags.
|
||||
*/
|
||||
unsigned short bi_flags; /* BIO_* below */
|
||||
unsigned short bi_ioprio;
|
||||
unsigned short bi_write_hint;
|
||||
blk_status_t bi_status;
|
||||
atomic_t __bi_remaining;
|
||||
|
||||
|
|
@ -308,26 +321,29 @@ enum {
|
|||
BIO_NO_PAGE_REF, /* don't put release vec pages */
|
||||
BIO_CLONED, /* doesn't own data */
|
||||
BIO_BOUNCED, /* bio is a bounce bio */
|
||||
BIO_WORKINGSET, /* contains userspace workingset pages */
|
||||
BIO_QUIET, /* Make BIO Quiet */
|
||||
BIO_CHAIN, /* chained bio, ->bi_remaining in effect */
|
||||
BIO_REFFED, /* bio has elevated ->bi_cnt */
|
||||
BIO_THROTTLED, /* This bio has already been subjected to
|
||||
BIO_BPS_THROTTLED, /* This bio has already been subjected to
|
||||
* throttling rules. Don't do it again. */
|
||||
BIO_TRACE_COMPLETION, /* bio_endio() should trace the final completion
|
||||
* of this bio. */
|
||||
BIO_CGROUP_ACCT, /* has been accounted to a cgroup */
|
||||
BIO_TRACKED, /* set if bio goes through the rq_qos path */
|
||||
BIO_QOS_THROTTLED, /* bio went through rq_qos throttle path */
|
||||
BIO_QOS_MERGED, /* but went through rq_qos merge path */
|
||||
BIO_REMAPPED,
|
||||
BIO_ZONE_WRITE_LOCKED, /* Owns a zoned device zone write lock */
|
||||
BIO_PERCPU_CACHE, /* can participate in per-cpu alloc cache */
|
||||
BIO_FLAG_LAST
|
||||
};
|
||||
|
||||
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
|
||||
|
|
@ -339,43 +355,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,
|
||||
/* write the same sector many times */
|
||||
REQ_OP_WRITE_SAME = 7,
|
||||
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 {
|
||||
|
|
@ -402,39 +412,45 @@ enum req_flag_bits {
|
|||
* work item to avoid such priority inversions.
|
||||
*/
|
||||
__REQ_CGROUP_PUNT,
|
||||
__REQ_POLLED, /* caller polls for completion using bio_poll */
|
||||
__REQ_ALLOC_CACHE, /* allocate IO from cache if available */
|
||||
__REQ_SWAP, /* swap I/O */
|
||||
__REQ_DRV, /* for driver use */
|
||||
|
||||
/* command specific flags for REQ_OP_WRITE_ZEROES: */
|
||||
/*
|
||||
* Command specific flags, keep last:
|
||||
*/
|
||||
/* for REQ_OP_WRITE_ZEROES: */
|
||||
__REQ_NOUNMAP, /* do not free blocks when zeroing */
|
||||
|
||||
__REQ_POLLED, /* caller polls for completion using bio_poll */
|
||||
|
||||
/* for driver use */
|
||||
__REQ_DRV,
|
||||
__REQ_SWAP, /* swapping request. */
|
||||
__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_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)
|
||||
|
|
@ -451,26 +467,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);
|
||||
}
|
||||
|
|
@ -480,13 +498,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;
|
||||
}
|
||||
|
|
@ -497,7 +515,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:
|
||||
|
|
@ -510,7 +528,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;
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -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)
|
||||
|
||||
|
|
@ -27,12 +28,10 @@ struct blk_trace {
|
|||
atomic_t dropped;
|
||||
};
|
||||
|
||||
struct blkcg;
|
||||
|
||||
extern int blk_trace_ioctl(struct block_device *, unsigned, char __user *);
|
||||
extern void blk_trace_shutdown(struct request_queue *);
|
||||
extern __printf(3, 4)
|
||||
void __trace_note_message(struct blk_trace *, struct blkcg *blkcg, const char *fmt, ...);
|
||||
__printf(3, 4) void __blk_trace_note_message(struct blk_trace *bt,
|
||||
struct cgroup_subsys_state *css, const char *fmt, ...);
|
||||
|
||||
/**
|
||||
* blk_add_trace_msg - Add a (simple) message to the blktrace stream
|
||||
|
|
@ -47,14 +46,14 @@ void __trace_note_message(struct blk_trace *, struct blkcg *blkcg, const char *f
|
|||
* NOTE: Can not use 'static inline' due to presence of var args...
|
||||
*
|
||||
**/
|
||||
#define blk_add_cgroup_trace_msg(q, cg, fmt, ...) \
|
||||
#define blk_add_cgroup_trace_msg(q, css, fmt, ...) \
|
||||
do { \
|
||||
struct blk_trace *bt; \
|
||||
\
|
||||
rcu_read_lock(); \
|
||||
bt = rcu_dereference((q)->blk_trace); \
|
||||
if (unlikely(bt)) \
|
||||
__trace_note_message(bt, cg, fmt, ##__VA_ARGS__);\
|
||||
__blk_trace_note_message(bt, css, fmt, ##__VA_ARGS__);\
|
||||
rcu_read_unlock(); \
|
||||
} while (0)
|
||||
#define blk_add_trace_msg(q, fmt, ...) \
|
||||
|
|
@ -79,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)
|
||||
|
|
@ -93,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
|
||||
|
|
@ -117,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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -33,8 +33,8 @@ struct bma150_cfg {
|
|||
unsigned char lg_hyst; /* Low-G hysterisis */
|
||||
unsigned char lg_dur; /* Low-G duration */
|
||||
unsigned char lg_thres; /* Low-G threshold */
|
||||
unsigned char range; /* one of BMA0150_RANGE_xxx */
|
||||
unsigned char bandwidth; /* one of BMA0150_BW_xxx */
|
||||
unsigned char range; /* one of BMA150_RANGE_xxx */
|
||||
unsigned char bandwidth; /* one of BMA150_BW_xxx */
|
||||
};
|
||||
|
||||
struct bma150_platform_data {
|
||||
|
|
|
|||
|
|
@ -289,4 +289,14 @@ int __init xbc_get_info(int *node_size, size_t *data_size);
|
|||
/* XBC cleanup data structures */
|
||||
void __init xbc_exit(void);
|
||||
|
||||
/* XBC embedded bootconfig data in kernel */
|
||||
#ifdef CONFIG_BOOT_CONFIG_EMBED
|
||||
const char * __init xbc_get_embedded_bootconfig(size_t *size);
|
||||
#else
|
||||
static inline const char *xbc_get_embedded_bootconfig(size_t *size)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
#include <linux/jump_label.h>
|
||||
#include <linux/percpu.h>
|
||||
#include <linux/rbtree.h>
|
||||
#include <net/sock.h>
|
||||
#include <uapi/linux/bpf.h>
|
||||
|
||||
struct sock;
|
||||
|
|
@ -22,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) \
|
||||
|
|
@ -94,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];
|
||||
|
|
@ -165,11 +173,23 @@ int bpf_percpu_cgroup_storage_copy(struct bpf_map *map, void *key, void *value);
|
|||
int bpf_percpu_cgroup_storage_update(struct bpf_map *map, void *key,
|
||||
void *value, u64 flags);
|
||||
|
||||
/* Opportunistic check to see whether we have any BPF program attached*/
|
||||
static inline bool cgroup_bpf_sock_enabled(struct sock *sk,
|
||||
enum cgroup_bpf_attach_type type)
|
||||
{
|
||||
struct cgroup *cgrp = sock_cgroup_ptr(&sk->sk_cgrp_data);
|
||||
struct bpf_prog_array *array;
|
||||
|
||||
array = rcu_access_pointer(cgrp->bpf.effective[type]);
|
||||
return array != &bpf_empty_prog_array.hdr;
|
||||
}
|
||||
|
||||
/* Wrappers for __cgroup_bpf_run_filter_skb() guarded by cgroup_bpf_enabled. */
|
||||
#define BPF_CGROUP_RUN_PROG_INET_INGRESS(sk, skb) \
|
||||
({ \
|
||||
int __ret = 0; \
|
||||
if (cgroup_bpf_enabled(CGROUP_INET_INGRESS)) \
|
||||
if (cgroup_bpf_enabled(CGROUP_INET_INGRESS) && \
|
||||
cgroup_bpf_sock_enabled(sk, CGROUP_INET_INGRESS)) \
|
||||
__ret = __cgroup_bpf_run_filter_skb(sk, skb, \
|
||||
CGROUP_INET_INGRESS); \
|
||||
\
|
||||
|
|
@ -181,7 +201,8 @@ int bpf_percpu_cgroup_storage_update(struct bpf_map *map, void *key,
|
|||
int __ret = 0; \
|
||||
if (cgroup_bpf_enabled(CGROUP_INET_EGRESS) && sk && sk == skb->sk) { \
|
||||
typeof(sk) __sk = sk_to_full_sk(sk); \
|
||||
if (sk_fullsock(__sk)) \
|
||||
if (sk_fullsock(__sk) && \
|
||||
cgroup_bpf_sock_enabled(__sk, CGROUP_INET_EGRESS)) \
|
||||
__ret = __cgroup_bpf_run_filter_skb(__sk, skb, \
|
||||
CGROUP_INET_EGRESS); \
|
||||
} \
|
||||
|
|
@ -211,24 +232,20 @@ int bpf_percpu_cgroup_storage_update(struct bpf_map *map, void *key,
|
|||
|
||||
#define BPF_CGROUP_RUN_SA_PROG(sk, uaddr, atype) \
|
||||
({ \
|
||||
u32 __unused_flags; \
|
||||
int __ret = 0; \
|
||||
if (cgroup_bpf_enabled(atype)) \
|
||||
__ret = __cgroup_bpf_run_filter_sock_addr(sk, uaddr, atype, \
|
||||
NULL, \
|
||||
&__unused_flags); \
|
||||
NULL, NULL); \
|
||||
__ret; \
|
||||
})
|
||||
|
||||
#define BPF_CGROUP_RUN_SA_PROG_LOCK(sk, uaddr, atype, t_ctx) \
|
||||
({ \
|
||||
u32 __unused_flags; \
|
||||
int __ret = 0; \
|
||||
if (cgroup_bpf_enabled(atype)) { \
|
||||
lock_sock(sk); \
|
||||
__ret = __cgroup_bpf_run_filter_sock_addr(sk, uaddr, atype, \
|
||||
t_ctx, \
|
||||
&__unused_flags); \
|
||||
t_ctx, NULL); \
|
||||
release_sock(sk); \
|
||||
} \
|
||||
__ret; \
|
||||
|
|
@ -347,7 +364,8 @@ int bpf_percpu_cgroup_storage_update(struct bpf_map *map, void *key,
|
|||
kernel_optval) \
|
||||
({ \
|
||||
int __ret = 0; \
|
||||
if (cgroup_bpf_enabled(CGROUP_SETSOCKOPT)) \
|
||||
if (cgroup_bpf_enabled(CGROUP_SETSOCKOPT) && \
|
||||
cgroup_bpf_sock_enabled(sock, CGROUP_SETSOCKOPT)) \
|
||||
__ret = __cgroup_bpf_run_filter_setsockopt(sock, level, \
|
||||
optname, optval, \
|
||||
optlen, \
|
||||
|
|
@ -367,7 +385,8 @@ int bpf_percpu_cgroup_storage_update(struct bpf_map *map, void *key,
|
|||
max_optlen, retval) \
|
||||
({ \
|
||||
int __ret = retval; \
|
||||
if (cgroup_bpf_enabled(CGROUP_GETSOCKOPT)) \
|
||||
if (cgroup_bpf_enabled(CGROUP_GETSOCKOPT) && \
|
||||
cgroup_bpf_sock_enabled(sock, CGROUP_GETSOCKOPT)) \
|
||||
if (!(sock)->sk_prot->bpf_bypass_getsockopt || \
|
||||
!INDIRECT_CALL_INET_1((sock)->sk_prot->bpf_bypass_getsockopt, \
|
||||
tcp_bpf_bypass_getsockopt, \
|
||||
|
|
@ -395,6 +414,11 @@ int cgroup_bpf_prog_detach(const union bpf_attr *attr,
|
|||
int cgroup_bpf_link_attach(const union bpf_attr *attr, struct bpf_prog *prog);
|
||||
int cgroup_bpf_prog_query(const union bpf_attr *attr,
|
||||
union bpf_attr __user *uattr);
|
||||
|
||||
const struct bpf_func_proto *
|
||||
cgroup_common_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog);
|
||||
const struct bpf_func_proto *
|
||||
cgroup_current_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog);
|
||||
#else
|
||||
|
||||
static inline int cgroup_bpf_inherit(struct cgroup *cgrp) { return 0; }
|
||||
|
|
@ -425,6 +449,18 @@ static inline int cgroup_bpf_prog_query(const union bpf_attr *attr,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
static inline const struct bpf_func_proto *
|
||||
cgroup_common_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline const struct bpf_func_proto *
|
||||
cgroup_current_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline int bpf_cgroup_storage_assign(struct bpf_prog_aux *aux,
|
||||
struct bpf_map *map) { return 0; }
|
||||
static inline struct bpf_cgroup_storage *bpf_cgroup_storage_alloc(
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -143,9 +143,9 @@ void bpf_selem_link_storage_nolock(struct bpf_local_storage *local_storage,
|
|||
|
||||
bool bpf_selem_unlink_storage_nolock(struct bpf_local_storage *local_storage,
|
||||
struct bpf_local_storage_elem *selem,
|
||||
bool uncharge_omem);
|
||||
bool uncharge_omem, bool use_trace_rcu);
|
||||
|
||||
void bpf_selem_unlink(struct bpf_local_storage_elem *selem);
|
||||
void bpf_selem_unlink(struct bpf_local_storage_elem *selem, bool use_trace_rcu);
|
||||
|
||||
void bpf_selem_link_map(struct bpf_local_storage_map *smap,
|
||||
struct bpf_local_storage_elem *selem);
|
||||
|
|
@ -154,16 +154,17 @@ void bpf_selem_unlink_map(struct bpf_local_storage_elem *selem);
|
|||
|
||||
struct bpf_local_storage_elem *
|
||||
bpf_selem_alloc(struct bpf_local_storage_map *smap, void *owner, void *value,
|
||||
bool charge_mem);
|
||||
bool charge_mem, gfp_t gfp_flags);
|
||||
|
||||
int
|
||||
bpf_local_storage_alloc(void *owner,
|
||||
struct bpf_local_storage_map *smap,
|
||||
struct bpf_local_storage_elem *first_selem);
|
||||
struct bpf_local_storage_elem *first_selem,
|
||||
gfp_t gfp_flags);
|
||||
|
||||
struct bpf_local_storage_data *
|
||||
bpf_local_storage_update(void *owner, struct bpf_local_storage_map *smap,
|
||||
void *value, u64 map_flags);
|
||||
void *value, u64 map_flags, gfp_t gfp_flags);
|
||||
|
||||
void bpf_local_storage_free_rcu(struct rcu_head *rcu);
|
||||
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
28
include/linux/bpf_mem_alloc.h
Normal file
28
include/linux/bpf_mem_alloc.h
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/* Copyright (c) 2022 Meta Platforms, Inc. and affiliates. */
|
||||
#ifndef _BPF_MEM_ALLOC_H
|
||||
#define _BPF_MEM_ALLOC_H
|
||||
#include <linux/compiler_types.h>
|
||||
#include <linux/workqueue.h>
|
||||
|
||||
struct bpf_mem_cache;
|
||||
struct bpf_mem_caches;
|
||||
|
||||
struct bpf_mem_alloc {
|
||||
struct bpf_mem_caches __percpu *caches;
|
||||
struct bpf_mem_cache __percpu *cache;
|
||||
struct work_struct work;
|
||||
};
|
||||
|
||||
int bpf_mem_alloc_init(struct bpf_mem_alloc *ma, int size, bool percpu);
|
||||
void bpf_mem_alloc_destroy(struct bpf_mem_alloc *ma);
|
||||
|
||||
/* kmalloc/kfree equivalent: */
|
||||
void *bpf_mem_alloc(struct bpf_mem_alloc *ma, size_t size);
|
||||
void bpf_mem_free(struct bpf_mem_alloc *ma, void *ptr);
|
||||
|
||||
/* kmem_cache_alloc/free equivalent: */
|
||||
void *bpf_mem_cache_alloc(struct bpf_mem_alloc *ma);
|
||||
void bpf_mem_cache_free(struct bpf_mem_alloc *ma, void *ptr);
|
||||
|
||||
#endif /* _BPF_MEM_ALLOC_H */
|
||||
|
|
@ -126,6 +126,7 @@ BPF_MAP_TYPE(BPF_MAP_TYPE_STRUCT_OPS, bpf_struct_ops_map_ops)
|
|||
#endif
|
||||
BPF_MAP_TYPE(BPF_MAP_TYPE_RINGBUF, ringbuf_map_ops)
|
||||
BPF_MAP_TYPE(BPF_MAP_TYPE_BLOOM_FILTER, bloom_filter_map_ops)
|
||||
BPF_MAP_TYPE(BPF_MAP_TYPE_USER_RINGBUF, user_ringbuf_map_ops)
|
||||
|
||||
BPF_LINK_TYPE(BPF_LINK_TYPE_RAW_TRACEPOINT, raw_tracepoint)
|
||||
BPF_LINK_TYPE(BPF_LINK_TYPE_TRACING, tracing)
|
||||
|
|
@ -140,3 +141,5 @@ BPF_LINK_TYPE(BPF_LINK_TYPE_XDP, xdp)
|
|||
#ifdef CONFIG_PERF_EVENTS
|
||||
BPF_LINK_TYPE(BPF_LINK_TYPE_PERF_EVENT, perf)
|
||||
#endif
|
||||
BPF_LINK_TYPE(BPF_LINK_TYPE_KPROBE_MULTI, kprobe_multi)
|
||||
BPF_LINK_TYPE(BPF_LINK_TYPE_STRUCT_OPS, struct_ops)
|
||||
|
|
|
|||
|
|
@ -72,6 +72,18 @@ struct bpf_reg_state {
|
|||
|
||||
u32 mem_size; /* for PTR_TO_MEM | PTR_TO_MEM_OR_NULL */
|
||||
|
||||
/* For dynptr stack slots */
|
||||
struct {
|
||||
enum bpf_dynptr_type type;
|
||||
/* A dynptr is 16 bytes so it takes up 2 stack slots.
|
||||
* We need to track which slot is the first slot
|
||||
* to protect against cases where the user may try to
|
||||
* pass in an address starting at the second slot of the
|
||||
* dynptr.
|
||||
*/
|
||||
bool first_slot;
|
||||
} dynptr;
|
||||
|
||||
/* Max size from any of the above. */
|
||||
struct {
|
||||
unsigned long raw1;
|
||||
|
|
@ -88,6 +100,8 @@ struct bpf_reg_state {
|
|||
* for the purpose of tracking that it's freed.
|
||||
* For PTR_TO_SOCKET this is used to share which pointers retain the
|
||||
* same reference to the socket, to determine proper reference freeing.
|
||||
* For stack slots that are dynptrs, this is used to track references to
|
||||
* the dynptr to determine proper reference freeing.
|
||||
*/
|
||||
u32 id;
|
||||
/* PTR_TO_SOCKET and PTR_TO_TCP_SOCK could be a ptr returned
|
||||
|
|
@ -174,9 +188,15 @@ enum bpf_stack_slot_type {
|
|||
STACK_SPILL, /* register spilled into stack */
|
||||
STACK_MISC, /* BPF program wrote some data into this slot */
|
||||
STACK_ZERO, /* BPF program wrote constant zero */
|
||||
/* A dynptr is stored in this stack slot. The type of dynptr
|
||||
* is stored in bpf_stack_state->spilled_ptr.dynptr.type
|
||||
*/
|
||||
STACK_DYNPTR,
|
||||
};
|
||||
|
||||
#define BPF_REG_SIZE 8 /* size of eBPF register in bytes */
|
||||
#define BPF_DYNPTR_SIZE sizeof(struct bpf_dynptr_kern)
|
||||
#define BPF_DYNPTR_NR_SLOTS (BPF_DYNPTR_SIZE / BPF_REG_SIZE)
|
||||
|
||||
struct bpf_stack_state {
|
||||
struct bpf_reg_state spilled_ptr;
|
||||
|
|
@ -192,6 +212,17 @@ struct bpf_reference_state {
|
|||
* is used purely to inform the user of a reference leak.
|
||||
*/
|
||||
int insn_idx;
|
||||
/* There can be a case like:
|
||||
* main (frame 0)
|
||||
* cb (frame 1)
|
||||
* func (frame 3)
|
||||
* cb (frame 4)
|
||||
* Hence for frame 4, if callback_ref just stored boolean, it would be
|
||||
* impossible to distinguish nested callback refs. Hence store the
|
||||
* frameno and compare that to callback_ref in check_reference_leak when
|
||||
* exiting a callback function.
|
||||
*/
|
||||
int callback_ref;
|
||||
};
|
||||
|
||||
/* state of the program:
|
||||
|
|
@ -217,6 +248,7 @@ struct bpf_func_state {
|
|||
*/
|
||||
u32 async_entry_cnt;
|
||||
bool in_callback_fn;
|
||||
struct tnum callback_ret_range;
|
||||
bool in_async_callback_fn;
|
||||
|
||||
/* The following fields should be last. See copy_func_state() */
|
||||
|
|
@ -279,7 +311,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().
|
||||
|
|
@ -317,6 +349,27 @@ struct bpf_verifier_state {
|
|||
iter < frame->allocated_stack / BPF_REG_SIZE; \
|
||||
iter++, reg = bpf_get_spilled_reg(iter, frame))
|
||||
|
||||
/* Invoke __expr over regsiters in __vst, setting __state and __reg */
|
||||
#define bpf_for_each_reg_in_vstate(__vst, __state, __reg, __expr) \
|
||||
({ \
|
||||
struct bpf_verifier_state *___vstate = __vst; \
|
||||
int ___i, ___j; \
|
||||
for (___i = 0; ___i <= ___vstate->curframe; ___i++) { \
|
||||
struct bpf_reg_state *___regs; \
|
||||
__state = ___vstate->frame[___i]; \
|
||||
___regs = __state->regs; \
|
||||
for (___j = 0; ___j < MAX_BPF_REG; ___j++) { \
|
||||
__reg = &___regs[___j]; \
|
||||
(void)(__expr); \
|
||||
} \
|
||||
bpf_for_each_spilled_reg(___j, __state, __reg) { \
|
||||
if (!__reg) \
|
||||
continue; \
|
||||
(void)(__expr); \
|
||||
} \
|
||||
} \
|
||||
})
|
||||
|
||||
/* linked list of verifier states used to prune search */
|
||||
struct bpf_verifier_state_list {
|
||||
struct bpf_verifier_state state;
|
||||
|
|
@ -324,6 +377,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)
|
||||
|
|
@ -353,6 +414,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 */
|
||||
|
|
@ -521,8 +586,18 @@ bpf_prog_offload_remove_insns(struct bpf_verifier_env *env, u32 off, u32 cnt);
|
|||
|
||||
int check_ptr_off_reg(struct bpf_verifier_env *env,
|
||||
const struct bpf_reg_state *reg, int regno);
|
||||
int check_func_arg_reg_off(struct bpf_verifier_env *env,
|
||||
const struct bpf_reg_state *reg, int regno,
|
||||
enum bpf_arg_type arg_type);
|
||||
int check_kfunc_mem_size_reg(struct bpf_verifier_env *env, struct bpf_reg_state *reg,
|
||||
u32 regno);
|
||||
int check_mem_reg(struct bpf_verifier_env *env, struct bpf_reg_state *reg,
|
||||
u32 regno, u32 mem_size);
|
||||
bool is_dynptr_reg_valid_init(struct bpf_verifier_env *env,
|
||||
struct bpf_reg_state *reg);
|
||||
bool is_dynptr_type_expected(struct bpf_verifier_env *env,
|
||||
struct bpf_reg_state *reg,
|
||||
enum bpf_arg_type arg_type);
|
||||
|
||||
/* this lives here instead of in bpf.h because it needs to dereference tgt_prog */
|
||||
static inline u64 bpf_trampoline_compute_key(const struct bpf_prog *tgt_prog,
|
||||
|
|
@ -550,6 +625,8 @@ int bpf_check_attach_target(struct bpf_verifier_log *log,
|
|||
struct bpf_attach_target_info *tgt_info);
|
||||
void bpf_free_kfunc_btf_tab(struct bpf_kfunc_btf_tab *tab);
|
||||
|
||||
int mark_chain_precision(struct bpf_verifier_env *env, int regno);
|
||||
|
||||
#define BPF_BASE_TYPE_MASK GENMASK(BPF_BASE_TYPE_BITS - 1, 0)
|
||||
|
||||
/* extract base type from bpf_{arg, return, reg}_type. */
|
||||
|
|
@ -564,4 +641,11 @@ static inline u32 type_flag(u32 type)
|
|||
return type & ~BPF_BASE_TYPE_MASK;
|
||||
}
|
||||
|
||||
/* only use after check_attach_btf_id() */
|
||||
static inline enum bpf_prog_type resolve_prog_type(struct bpf_prog *prog)
|
||||
{
|
||||
return prog->type == BPF_PROG_TYPE_EXT ?
|
||||
prog->aux->dst_prog->type : prog->type;
|
||||
}
|
||||
|
||||
#endif /* _LINUX_BPF_VERIFIER_H */
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -292,6 +293,7 @@
|
|||
#define MII_BRCM_FET_SHDW_MC_FAME 0x4000 /* Force Auto MDIX enable */
|
||||
|
||||
#define MII_BRCM_FET_SHDW_AUXMODE4 0x1a /* Auxiliary mode 4 */
|
||||
#define MII_BRCM_FET_SHDW_AM4_STANDBY 0x0008 /* Standby enable */
|
||||
#define MII_BRCM_FET_SHDW_AM4_LED_MASK 0x0003
|
||||
#define MII_BRCM_FET_SHDW_AM4_LED_MODE1 0x0001
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@
|
|||
#define _BLK_BSG_
|
||||
|
||||
#include <linux/blkdev.h>
|
||||
#include <scsi/scsi_request.h>
|
||||
|
||||
struct bsg_job;
|
||||
struct request;
|
||||
|
|
|
|||
|
|
@ -12,11 +12,73 @@
|
|||
#define BTF_TYPE_EMIT(type) ((void)(type *)0)
|
||||
#define BTF_TYPE_EMIT_ENUM(enum_val) ((void)enum_val)
|
||||
|
||||
/* 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 */
|
||||
#define KF_SLEEPABLE (1 << 5) /* kfunc may sleep */
|
||||
#define KF_DESTRUCTIVE (1 << 6) /* kfunc performs destructive actions */
|
||||
|
||||
/*
|
||||
* Return the name of the passed struct, if exists, or halt the build if for
|
||||
* example the structure gets renamed. In this way, developers have to revisit
|
||||
* the code using that structure name, and update it accordingly.
|
||||
*/
|
||||
#define stringify_struct(x) \
|
||||
({ BUILD_BUG_ON(sizeof(struct x) < 0); \
|
||||
__stringify(x); })
|
||||
|
||||
struct btf;
|
||||
struct btf_member;
|
||||
struct btf_type;
|
||||
union bpf_attr;
|
||||
struct btf_show;
|
||||
struct btf_id_set;
|
||||
|
||||
struct btf_kfunc_id_set {
|
||||
struct module *owner;
|
||||
struct btf_id_set8 *set;
|
||||
};
|
||||
|
||||
struct btf_id_dtor_kfunc {
|
||||
u32 btf_id;
|
||||
u32 kfunc_btf_id;
|
||||
};
|
||||
|
||||
typedef void (*btf_dtor_kfunc_t)(void *);
|
||||
|
||||
extern const struct file_operations btf_fops;
|
||||
|
||||
|
|
@ -101,6 +163,8 @@ bool btf_member_is_reg_int(const struct btf *btf, const struct btf_type *s,
|
|||
u32 expected_offset, u32 expected_size);
|
||||
int btf_find_spin_lock(const struct btf *btf, const struct btf_type *t);
|
||||
int btf_find_timer(const struct btf *btf, const struct btf_type *t);
|
||||
struct bpf_map_value_off *btf_parse_kptrs(const struct btf *btf,
|
||||
const struct btf_type *t);
|
||||
bool btf_type_is_void(const struct btf_type *t);
|
||||
s32 btf_find_by_name_kind(const struct btf *btf, const char *name, u8 kind);
|
||||
const struct btf_type *btf_type_skip_modifiers(const struct btf *btf,
|
||||
|
|
@ -144,6 +208,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];
|
||||
|
|
@ -159,6 +236,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);
|
||||
|
|
@ -216,6 +303,11 @@ static inline bool btf_type_is_var(const struct btf_type *t)
|
|||
return BTF_INFO_KIND(t->info) == BTF_KIND_VAR;
|
||||
}
|
||||
|
||||
static inline bool btf_type_is_type_tag(const struct btf_type *t)
|
||||
{
|
||||
return BTF_INFO_KIND(t->info) == BTF_KIND_TYPE_TAG;
|
||||
}
|
||||
|
||||
/* union is only a special case of struct:
|
||||
* all its offsetof(member) == 0
|
||||
*/
|
||||
|
|
@ -294,12 +386,22 @@ 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)
|
||||
{
|
||||
return (const struct btf_var_secinfo *)(t + 1);
|
||||
}
|
||||
|
||||
static inline struct btf_param *btf_params(const struct btf_type *t)
|
||||
{
|
||||
return (struct btf_param *)(t + 1);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_BPF_SYSCALL
|
||||
struct bpf_prog;
|
||||
|
||||
|
|
@ -307,6 +409,14 @@ 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);
|
||||
u32 *btf_kfunc_id_set_contains(const struct btf *btf,
|
||||
enum bpf_prog_type prog_type,
|
||||
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);
|
||||
int register_btf_id_dtor_kfuncs(const struct btf_id_dtor_kfunc *dtors, u32 add_cnt,
|
||||
struct module *owner);
|
||||
#else
|
||||
static inline const struct btf_type *btf_type_by_id(const struct btf *btf,
|
||||
u32 type_id)
|
||||
|
|
@ -318,50 +428,36 @@ static inline const char *btf_name_by_offset(const struct btf *btf,
|
|||
{
|
||||
return NULL;
|
||||
}
|
||||
static inline u32 *btf_kfunc_id_set_contains(const struct btf *btf,
|
||||
enum bpf_prog_type prog_type,
|
||||
u32 kfunc_btf_id)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
static inline int register_btf_kfunc_id_set(enum bpf_prog_type prog_type,
|
||||
const struct btf_kfunc_id_set *s)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static inline s32 btf_find_dtor_kfunc(struct btf *btf, u32 btf_id)
|
||||
{
|
||||
return -ENOENT;
|
||||
}
|
||||
static inline int register_btf_id_dtor_kfuncs(const struct btf_id_dtor_kfunc *dtors,
|
||||
u32 add_cnt, struct module *owner)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
struct kfunc_btf_id_set {
|
||||
struct list_head list;
|
||||
struct btf_id_set *set;
|
||||
struct module *owner;
|
||||
};
|
||||
|
||||
struct kfunc_btf_id_list {
|
||||
struct list_head list;
|
||||
struct mutex mutex;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_DEBUG_INFO_BTF_MODULES
|
||||
void register_kfunc_btf_id_set(struct kfunc_btf_id_list *l,
|
||||
struct kfunc_btf_id_set *s);
|
||||
void unregister_kfunc_btf_id_set(struct kfunc_btf_id_list *l,
|
||||
struct kfunc_btf_id_set *s);
|
||||
bool bpf_check_mod_kfunc_call(struct kfunc_btf_id_list *klist, u32 kfunc_id,
|
||||
struct module *owner);
|
||||
|
||||
extern struct kfunc_btf_id_list bpf_tcp_ca_kfunc_list;
|
||||
extern struct kfunc_btf_id_list prog_test_kfunc_list;
|
||||
#else
|
||||
static inline void register_kfunc_btf_id_set(struct kfunc_btf_id_list *l,
|
||||
struct kfunc_btf_id_set *s)
|
||||
static inline bool btf_type_is_struct_ptr(struct btf *btf, const struct btf_type *t)
|
||||
{
|
||||
}
|
||||
static inline void unregister_kfunc_btf_id_set(struct kfunc_btf_id_list *l,
|
||||
struct kfunc_btf_id_set *s)
|
||||
{
|
||||
}
|
||||
static inline bool bpf_check_mod_kfunc_call(struct kfunc_btf_id_list *klist,
|
||||
u32 kfunc_id, struct module *owner)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!btf_type_is_ptr(t))
|
||||
return false;
|
||||
|
||||
static struct kfunc_btf_id_list bpf_tcp_ca_kfunc_list __maybe_unused;
|
||||
static struct kfunc_btf_id_list prog_test_kfunc_list __maybe_unused;
|
||||
#endif
|
||||
t = btf_type_skip_modifiers(btf, t->type, NULL);
|
||||
|
||||
#define DEFINE_KFUNC_BTF_ID_SET(set, name) \
|
||||
struct kfunc_btf_id_set name = { LIST_HEAD_INIT(name.list), (set), \
|
||||
THIS_MODULE }
|
||||
return btf_type_is_struct(t);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -8,9 +8,19 @@ 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 */
|
||||
#include <linux/compiler_attributes.h> /* for __maybe_unused */
|
||||
|
||||
/*
|
||||
* Following macros help to define lists of BTF IDs placed
|
||||
|
|
@ -24,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" \
|
||||
|
|
@ -32,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__)
|
||||
|
|
@ -45,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
|
||||
|
|
@ -144,17 +162,60 @@ 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 name[5];
|
||||
#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 name[n];
|
||||
#define BTF_ID_LIST_SINGLE(name, prefix, typename) static u32 name[1];
|
||||
#define BTF_ID_LIST_GLOBAL_SINGLE(name, prefix, typename) u32 name[1];
|
||||
#define BTF_SET_START(name) static struct btf_id_set name = { 0 };
|
||||
#define BTF_SET_START_GLOBAL(name) static struct btf_id_set name = { 0 };
|
||||
#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];
|
||||
#define BTF_ID_LIST_GLOBAL_SINGLE(name, prefix, typename) u32 __maybe_unused name[1];
|
||||
#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 */
|
||||
|
||||
|
|
@ -177,7 +238,9 @@ extern struct btf_id_set name;
|
|||
BTF_SOCK_TYPE(BTF_SOCK_TYPE_TCP6, tcp6_sock) \
|
||||
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_UNIX, unix_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 */
|
||||
|
|
@ -144,8 +179,9 @@ BUFFER_FNS(Defer_Completion, defer_completion)
|
|||
((struct buffer_head *)page_private(page)); \
|
||||
})
|
||||
#define page_has_buffers(page) PagePrivate(page)
|
||||
#define folio_buffers(folio) folio_get_private(folio)
|
||||
|
||||
void buffer_check_dirty_writeback(struct page *page,
|
||||
void buffer_check_dirty_writeback(struct folio *folio,
|
||||
bool *dirty, bool *writeback);
|
||||
|
||||
/*
|
||||
|
|
@ -157,7 +193,7 @@ void mark_buffer_write_io_error(struct buffer_head *bh);
|
|||
void touch_buffer(struct buffer_head *bh);
|
||||
void set_bh_page(struct buffer_head *bh,
|
||||
struct page *page, unsigned long offset);
|
||||
int try_to_free_buffers(struct page *);
|
||||
bool try_to_free_buffers(struct folio *);
|
||||
struct buffer_head *alloc_page_buffers(struct page *page, unsigned long size,
|
||||
bool retry);
|
||||
void create_empty_buffers(struct page *, unsigned long,
|
||||
|
|
@ -189,8 +225,6 @@ struct buffer_head *__getblk_gfp(struct block_device *bdev, sector_t block,
|
|||
void __brelse(struct buffer_head *);
|
||||
void __bforget(struct buffer_head *);
|
||||
void __breadahead(struct block_device *, sector_t block, unsigned int size);
|
||||
void __breadahead_gfp(struct block_device *, sector_t block, unsigned int size,
|
||||
gfp_t gfp);
|
||||
struct buffer_head *__bread_gfp(struct block_device *,
|
||||
sector_t block, unsigned size, gfp_t gfp);
|
||||
void invalidate_bh_lrus(void);
|
||||
|
|
@ -200,15 +234,16 @@ 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[]);
|
||||
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);
|
||||
void 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);
|
||||
int bh_submit_read(struct buffer_head *bh);
|
||||
int __bh_read(struct buffer_head *bh, blk_opf_t op_flags, bool wait);
|
||||
void __bh_read_batch(int nr, struct buffer_head *bhs[],
|
||||
blk_opf_t op_flags, bool force_lock);
|
||||
|
||||
extern int buffer_heads_over_limit;
|
||||
|
||||
|
|
@ -216,18 +251,16 @@ extern int buffer_heads_over_limit;
|
|||
* Generic address_space_operations implementations for buffer_head-backed
|
||||
* address_spaces.
|
||||
*/
|
||||
void block_invalidatepage(struct page *page, unsigned int offset,
|
||||
unsigned int length);
|
||||
void block_invalidate_folio(struct folio *folio, size_t offset, size_t length);
|
||||
int block_write_full_page(struct page *page, get_block_t *get_block,
|
||||
struct writeback_control *wbc);
|
||||
int __block_write_full_page(struct inode *inode, struct page *page,
|
||||
get_block_t *get_block, struct writeback_control *wbc,
|
||||
bh_end_io_t *handler);
|
||||
int block_read_full_page(struct page*, get_block_t*);
|
||||
int block_is_partially_uptodate(struct page *page, unsigned long from,
|
||||
unsigned long count);
|
||||
int block_read_full_folio(struct folio *, get_block_t *);
|
||||
bool block_is_partially_uptodate(struct folio *, size_t from, size_t count);
|
||||
int block_write_begin(struct address_space *mapping, loff_t pos, unsigned len,
|
||||
unsigned flags, struct page **pagep, get_block_t *get_block);
|
||||
struct page **pagep, get_block_t *get_block);
|
||||
int __block_write_begin(struct page *page, loff_t pos, unsigned len,
|
||||
get_block_t *get_block);
|
||||
int block_write_end(struct file *, struct address_space *,
|
||||
|
|
@ -239,7 +272,7 @@ int generic_write_end(struct file *, struct address_space *,
|
|||
void page_zero_new_buffers(struct page *page, unsigned from, unsigned to);
|
||||
void clean_page_buffers(struct page *page);
|
||||
int cont_write_begin(struct file *, struct address_space *, loff_t,
|
||||
unsigned, unsigned, struct page **, void **,
|
||||
unsigned, struct page **, void **,
|
||||
get_block_t *, loff_t *);
|
||||
int generic_cont_expand_simple(struct inode *inode, loff_t size);
|
||||
int block_commit_write(struct page *page, unsigned from, unsigned to);
|
||||
|
|
@ -259,14 +292,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, unsigned,
|
||||
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);
|
||||
|
||||
|
|
@ -315,12 +350,6 @@ sb_breadahead(struct super_block *sb, sector_t block)
|
|||
__breadahead(sb->s_bdev, block, sb->s_blocksize);
|
||||
}
|
||||
|
||||
static inline void
|
||||
sb_breadahead_unmovable(struct super_block *sb, sector_t block)
|
||||
{
|
||||
__breadahead_gfp(sb->s_bdev, block, sb->s_blocksize, 0);
|
||||
}
|
||||
|
||||
static inline struct buffer_head *
|
||||
sb_getblk(struct super_block *sb, sector_t block)
|
||||
{
|
||||
|
|
@ -382,6 +411,41 @@ static inline struct buffer_head *__getblk(struct block_device *bdev,
|
|||
return __getblk_gfp(bdev, block, size, __GFP_MOVABLE);
|
||||
}
|
||||
|
||||
static inline void bh_readahead(struct buffer_head *bh, blk_opf_t op_flags)
|
||||
{
|
||||
if (!buffer_uptodate(bh) && trylock_buffer(bh)) {
|
||||
if (!buffer_uptodate(bh))
|
||||
__bh_read(bh, op_flags, false);
|
||||
else
|
||||
unlock_buffer(bh);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void bh_read_nowait(struct buffer_head *bh, blk_opf_t op_flags)
|
||||
{
|
||||
if (!bh_uptodate_or_lock(bh))
|
||||
__bh_read(bh, op_flags, false);
|
||||
}
|
||||
|
||||
/* Returns 1 if buffer uptodated, 0 on success, and -EIO on error. */
|
||||
static inline int bh_read(struct buffer_head *bh, blk_opf_t op_flags)
|
||||
{
|
||||
if (bh_uptodate_or_lock(bh))
|
||||
return 1;
|
||||
return __bh_read(bh, op_flags, true);
|
||||
}
|
||||
|
||||
static inline void bh_read_batch(int nr, struct buffer_head *bhs[])
|
||||
{
|
||||
__bh_read_batch(nr, bhs, 0, true);
|
||||
}
|
||||
|
||||
static inline void bh_readahead_batch(int nr, struct buffer_head *bhs[],
|
||||
blk_opf_t op_flags)
|
||||
{
|
||||
__bh_read_batch(nr, bhs, op_flags, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* __bread() - reads a specified block and returns the bh
|
||||
* @bdev: the block_device to read from
|
||||
|
|
@ -398,12 +462,12 @@ __bread(struct block_device *bdev, sector_t block, unsigned size)
|
|||
return __bread_gfp(bdev, block, size, __GFP_MOVABLE);
|
||||
}
|
||||
|
||||
extern int __set_page_dirty_buffers(struct page *page);
|
||||
bool block_dirty_folio(struct address_space *mapping, struct folio *folio);
|
||||
|
||||
#else /* CONFIG_BLOCK */
|
||||
|
||||
static inline void buffer_init(void) {}
|
||||
static inline int try_to_free_buffers(struct page *page) { return 1; }
|
||||
static inline bool try_to_free_buffers(struct folio *folio) { return true; }
|
||||
static inline int inode_has_buffers(struct inode *inode) { return 0; }
|
||||
static inline void invalidate_inode_buffers(struct inode *inode) {}
|
||||
static inline int remove_inode_buffers(struct inode *inode) { return 1; }
|
||||
|
|
|
|||
|
|
@ -85,4 +85,17 @@
|
|||
#define cache_line_size() L1_CACHE_BYTES
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Helper to add padding within a struct to ensure data fall into separate
|
||||
* cachelines.
|
||||
*/
|
||||
#if defined(CONFIG_SMP)
|
||||
struct cacheline_padding {
|
||||
char x[0];
|
||||
} ____cacheline_internodealigned_in_smp;
|
||||
#define CACHELINE_PADDING(name) struct cacheline_padding name
|
||||
#else
|
||||
#define CACHELINE_PADDING(name)
|
||||
#endif
|
||||
|
||||
#endif /* __LINUX_CACHE_H */
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@
|
|||
|
||||
#include <asm/cacheflush.h>
|
||||
|
||||
struct folio;
|
||||
|
||||
#if ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE
|
||||
#ifndef ARCH_IMPLEMENTS_FLUSH_DCACHE_FOLIO
|
||||
void flush_dcache_folio(struct folio *folio);
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
@ -113,7 +115,7 @@ struct can_tdc_const {
|
|||
};
|
||||
|
||||
#ifdef CONFIG_CAN_CALC_BITTIMING
|
||||
int can_calc_bittiming(struct net_device *dev, struct can_bittiming *bt,
|
||||
int can_calc_bittiming(const struct net_device *dev, struct can_bittiming *bt,
|
||||
const struct can_bittiming_const *btc);
|
||||
|
||||
void can_calc_tdco(struct can_tdc *tdc, const struct can_tdc_const *tdc_const,
|
||||
|
|
@ -121,7 +123,7 @@ void can_calc_tdco(struct can_tdc *tdc, const struct can_tdc_const *tdc_const,
|
|||
u32 *ctrlmode, u32 ctrlmode_supported);
|
||||
#else /* !CONFIG_CAN_CALC_BITTIMING */
|
||||
static inline int
|
||||
can_calc_bittiming(struct net_device *dev, struct can_bittiming *bt,
|
||||
can_calc_bittiming(const struct net_device *dev, struct can_bittiming *bt,
|
||||
const struct can_bittiming_const *btc)
|
||||
{
|
||||
netdev_err(dev, "bit-timing calculation not available\n");
|
||||
|
|
@ -136,7 +138,7 @@ can_calc_tdco(struct can_tdc *tdc, const struct can_tdc_const *tdc_const,
|
|||
}
|
||||
#endif /* CONFIG_CAN_CALC_BITTIMING */
|
||||
|
||||
int can_get_bittiming(struct net_device *dev, struct can_bittiming *bt,
|
||||
int can_get_bittiming(const struct net_device *dev, struct can_bittiming *bt,
|
||||
const struct can_bittiming_const *btc,
|
||||
const u32 *bitrate_const,
|
||||
const unsigned int bitrate_const_cnt);
|
||||
|
|
|
|||
|
|
@ -17,10 +17,10 @@
|
|||
#include <linux/can.h>
|
||||
#include <linux/can/bittiming.h>
|
||||
#include <linux/can/error.h>
|
||||
#include <linux/can/led.h>
|
||||
#include <linux/can/length.h>
|
||||
#include <linux/can/netlink.h>
|
||||
#include <linux/can/skb.h>
|
||||
#include <linux/ethtool.h>
|
||||
#include <linux/netdevice.h>
|
||||
|
||||
/*
|
||||
|
|
@ -85,15 +85,6 @@ struct can_priv {
|
|||
int (*do_get_berr_counter)(const struct net_device *dev,
|
||||
struct can_berr_counter *bec);
|
||||
int (*do_get_auto_tdcv)(const struct net_device *dev, u32 *tdcv);
|
||||
|
||||
#ifdef CONFIG_CAN_LEDS
|
||||
struct led_trigger *tx_led_trig;
|
||||
char tx_led_trig_name[CAN_LED_NAME_SZ];
|
||||
struct led_trigger *rx_led_trig;
|
||||
char rx_led_trig_name[CAN_LED_NAME_SZ];
|
||||
struct led_trigger *rxtx_led_trig;
|
||||
char rxtx_led_trig_name[CAN_LED_NAME_SZ];
|
||||
#endif
|
||||
};
|
||||
|
||||
static inline bool can_tdc_is_enabled(const struct can_priv *priv)
|
||||
|
|
@ -156,6 +147,27 @@ static inline u32 can_get_static_ctrlmode(struct can_priv *priv)
|
|||
return priv->ctrlmode & ~priv->ctrlmode_supported;
|
||||
}
|
||||
|
||||
static inline bool can_is_canxl_dev_mtu(unsigned int mtu)
|
||||
{
|
||||
return (mtu >= CANXL_MIN_MTU && mtu <= CANXL_MAX_MTU);
|
||||
}
|
||||
|
||||
/* drop skb if it does not contain a valid CAN frame for sending */
|
||||
static inline bool can_dev_dropped_skb(struct net_device *dev, struct sk_buff *skb)
|
||||
{
|
||||
struct can_priv *priv = netdev_priv(dev);
|
||||
|
||||
if (priv->ctrlmode & CAN_CTRLMODE_LISTENONLY) {
|
||||
netdev_info_once(dev,
|
||||
"interface in listen only mode, dropping skb\n");
|
||||
kfree_skb(skb);
|
||||
dev->stats.tx_dropped++;
|
||||
return true;
|
||||
}
|
||||
|
||||
return can_dropped_invalid_skb(dev, skb);
|
||||
}
|
||||
|
||||
void can_setup(struct net_device *dev);
|
||||
|
||||
struct net_device *alloc_candev_mqs(int sizeof_priv, unsigned int echo_skb_max,
|
||||
|
|
@ -172,6 +184,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);
|
||||
|
|
|
|||
|
|
@ -1,51 +0,0 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright 2012, Fabio Baltieri <fabio.baltieri@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef _CAN_LED_H
|
||||
#define _CAN_LED_H
|
||||
|
||||
#include <linux/if.h>
|
||||
#include <linux/leds.h>
|
||||
#include <linux/netdevice.h>
|
||||
|
||||
enum can_led_event {
|
||||
CAN_LED_EVENT_OPEN,
|
||||
CAN_LED_EVENT_STOP,
|
||||
CAN_LED_EVENT_TX,
|
||||
CAN_LED_EVENT_RX,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_CAN_LEDS
|
||||
|
||||
/* keep space for interface name + "-tx"/"-rx"/"-rxtx"
|
||||
* suffix and null terminator
|
||||
*/
|
||||
#define CAN_LED_NAME_SZ (IFNAMSIZ + 6)
|
||||
|
||||
void can_led_event(struct net_device *netdev, enum can_led_event event);
|
||||
void devm_can_led_init(struct net_device *netdev);
|
||||
int __init can_led_notifier_init(void);
|
||||
void __exit can_led_notifier_exit(void);
|
||||
|
||||
#else
|
||||
|
||||
static inline void can_led_event(struct net_device *netdev,
|
||||
enum can_led_event event)
|
||||
{
|
||||
}
|
||||
static inline void devm_can_led_init(struct net_device *netdev)
|
||||
{
|
||||
}
|
||||
static inline int can_led_notifier_init(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static inline void can_led_notifier_exit(void)
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* !_CAN_LED_H */
|
||||
|
|
@ -14,7 +14,7 @@
|
|||
#define OCR_MODE_TEST 0x01
|
||||
#define OCR_MODE_NORMAL 0x02
|
||||
#define OCR_MODE_CLOCK 0x03
|
||||
#define OCR_MODE_MASK 0x07
|
||||
#define OCR_MODE_MASK 0x03
|
||||
#define OCR_TX0_INVERT 0x04
|
||||
#define OCR_TX0_PULLDOWN 0x08
|
||||
#define OCR_TX0_PULLUP 0x10
|
||||
|
|
|
|||
|
|
@ -42,8 +42,8 @@ int can_rx_offload_add_manual(struct net_device *dev,
|
|||
int can_rx_offload_irq_offload_timestamp(struct can_rx_offload *offload,
|
||||
u64 reg);
|
||||
int can_rx_offload_irq_offload_fifo(struct can_rx_offload *offload);
|
||||
int can_rx_offload_queue_sorted(struct can_rx_offload *offload,
|
||||
struct sk_buff *skb, u32 timestamp);
|
||||
int can_rx_offload_queue_timestamp(struct can_rx_offload *offload,
|
||||
struct sk_buff *skb, u32 timestamp);
|
||||
unsigned int can_rx_offload_get_echo_skb(struct can_rx_offload *offload,
|
||||
unsigned int idx, u32 timestamp,
|
||||
unsigned int *frame_len_ptr);
|
||||
|
|
|
|||
|
|
@ -20,7 +20,8 @@ void can_flush_echo_skb(struct net_device *dev);
|
|||
int can_put_echo_skb(struct sk_buff *skb, struct net_device *dev,
|
||||
unsigned int idx, unsigned int frame_len);
|
||||
struct sk_buff *__can_get_echo_skb(struct net_device *dev, unsigned int idx,
|
||||
u8 *len_ptr, unsigned int *frame_len_ptr);
|
||||
unsigned int *len_ptr,
|
||||
unsigned int *frame_len_ptr);
|
||||
unsigned int __must_check can_get_echo_skb(struct net_device *dev,
|
||||
unsigned int idx,
|
||||
unsigned int *frame_len_ptr);
|
||||
|
|
@ -29,8 +30,12 @@ void can_free_echo_skb(struct net_device *dev, unsigned int idx,
|
|||
struct sk_buff *alloc_can_skb(struct net_device *dev, struct can_frame **cf);
|
||||
struct sk_buff *alloc_canfd_skb(struct net_device *dev,
|
||||
struct canfd_frame **cfd);
|
||||
struct sk_buff *alloc_canxl_skb(struct net_device *dev,
|
||||
struct canxl_frame **cxl,
|
||||
unsigned int data_len);
|
||||
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,68 +101,59 @@ 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)
|
||||
static inline bool can_is_can_skb(const 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;
|
||||
struct can_frame *cf = (struct can_frame *)skb->data;
|
||||
|
||||
/* 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;
|
||||
/* the CAN specific type of skb is identified by its data length */
|
||||
return (skb->len == CAN_MTU && cf->len <= CAN_MAX_DLEN);
|
||||
}
|
||||
|
||||
static inline bool can_is_canfd_skb(const struct sk_buff *skb)
|
||||
{
|
||||
struct canfd_frame *cfd = (struct canfd_frame *)skb->data;
|
||||
|
||||
/* the CAN specific type of skb is identified by its data length */
|
||||
return skb->len == CANFD_MTU;
|
||||
return (skb->len == CANFD_MTU && cfd->len <= CANFD_MAX_DLEN);
|
||||
}
|
||||
|
||||
static inline bool can_is_canxl_skb(const struct sk_buff *skb)
|
||||
{
|
||||
const struct canxl_frame *cxl = (struct canxl_frame *)skb->data;
|
||||
|
||||
if (skb->len < CANXL_HDR_SIZE + CANXL_MIN_DLEN || skb->len > CANXL_MTU)
|
||||
return false;
|
||||
|
||||
/* this also checks valid CAN XL data length boundaries */
|
||||
if (skb->len != CANXL_HDR_SIZE + cxl->len)
|
||||
return false;
|
||||
|
||||
return cxl->flags & CANXL_XLF;
|
||||
}
|
||||
|
||||
/* get length element value from can[|fd|xl]_frame structure */
|
||||
static inline unsigned int can_skb_get_len_val(struct sk_buff *skb)
|
||||
{
|
||||
const struct canxl_frame *cxl = (struct canxl_frame *)skb->data;
|
||||
const struct canfd_frame *cfd = (struct canfd_frame *)skb->data;
|
||||
|
||||
if (can_is_canxl_skb(skb))
|
||||
return cxl->len;
|
||||
|
||||
return cfd->len;
|
||||
}
|
||||
|
||||
/* get needed data length inside CAN frame for all frame types (RTR aware) */
|
||||
static inline unsigned int can_skb_get_data_len(struct sk_buff *skb)
|
||||
{
|
||||
unsigned int len = can_skb_get_len_val(skb);
|
||||
const struct can_frame *cf = (struct can_frame *)skb->data;
|
||||
|
||||
/* RTR frames have an actual length of zero */
|
||||
if (can_is_can_skb(skb) && cf->can_id & CAN_RTR_FLAG)
|
||||
return 0;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
#endif /* !_CAN_SKB_H */
|
||||
|
|
|
|||
|
|
@ -72,6 +72,24 @@ enum cc_attr {
|
|||
* Examples include TDX guest & SEV.
|
||||
*/
|
||||
CC_ATTR_GUEST_UNROLL_STRING_IO,
|
||||
|
||||
/**
|
||||
* @CC_ATTR_SEV_SNP: Guest SNP is active.
|
||||
*
|
||||
* The platform/OS is running as a guest/virtual machine and actively
|
||||
* using AMD SEV-SNP features.
|
||||
*/
|
||||
CC_ATTR_GUEST_SEV_SNP,
|
||||
|
||||
/**
|
||||
* @CC_ATTR_HOTPLUG_DISABLED: Hotplug is not supported or disabled.
|
||||
*
|
||||
* The platform/OS is running as a guest/virtual machine does not
|
||||
* support CPU hotplug feature.
|
||||
*
|
||||
* Examples include TDX Guest.
|
||||
*/
|
||||
CC_ATTR_HOTPLUG_DISABLED,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_ARCH_HAS_CC_PLATFORM
|
||||
|
|
|
|||
|
|
@ -77,7 +77,6 @@ struct cdrom_device_ops {
|
|||
int (*tray_move) (struct cdrom_device_info *, int);
|
||||
int (*lock_door) (struct cdrom_device_info *, int);
|
||||
int (*select_speed) (struct cdrom_device_info *, int);
|
||||
int (*select_disc) (struct cdrom_device_info *, int);
|
||||
int (*get_last_session) (struct cdrom_device_info *,
|
||||
struct cdrom_multisession *);
|
||||
int (*get_mcn) (struct cdrom_device_info *,
|
||||
|
|
|
|||
|
|
@ -28,8 +28,8 @@
|
|||
|
||||
|
||||
#define CEPH_INO_ROOT 1
|
||||
#define CEPH_INO_CEPH 2 /* hidden .ceph dir */
|
||||
#define CEPH_INO_DOTDOT 3 /* used by ceph fuse for parent (..) */
|
||||
#define CEPH_INO_CEPH 2 /* hidden .ceph dir */
|
||||
#define CEPH_INO_GLOBAL_SNAPREALM 3 /* global dummy snaprealm */
|
||||
|
||||
/* arbitrary limit on max # of monitors (cluster of 3 is typical) */
|
||||
#define CEPH_MAX_MON 31
|
||||
|
|
@ -328,6 +328,7 @@ enum {
|
|||
CEPH_MDS_OP_LOOKUPPARENT = 0x00103,
|
||||
CEPH_MDS_OP_LOOKUPINO = 0x00104,
|
||||
CEPH_MDS_OP_LOOKUPNAME = 0x00105,
|
||||
CEPH_MDS_OP_GETVXATTR = 0x00106,
|
||||
|
||||
CEPH_MDS_OP_SETXATTR = 0x01105,
|
||||
CEPH_MDS_OP_RMXATTR = 0x01106,
|
||||
|
|
@ -432,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;
|
||||
|
|
@ -767,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;
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@
|
|||
#define CEPH_OPT_TCP_NODELAY (1<<4) /* TCP_NODELAY on TCP sockets */
|
||||
#define CEPH_OPT_NOMSGSIGN (1<<5) /* don't sign msgs (msgr1) */
|
||||
#define CEPH_OPT_ABORT_ON_FULL (1<<6) /* abort w/ ENOSPC when full */
|
||||
#define CEPH_OPT_RXBOUNCE (1<<7) /* double-buffer read data */
|
||||
|
||||
#define CEPH_OPT_DEFAULT (CEPH_OPT_TCP_NODELAY)
|
||||
|
||||
|
|
@ -283,6 +284,7 @@ DEFINE_RB_LOOKUP_FUNC(name, type, keyfld, nodefld)
|
|||
|
||||
extern struct kmem_cache *ceph_inode_cachep;
|
||||
extern struct kmem_cache *ceph_cap_cachep;
|
||||
extern struct kmem_cache *ceph_cap_snap_cachep;
|
||||
extern struct kmem_cache *ceph_cap_flush_cachep;
|
||||
extern struct kmem_cache *ceph_dentry_cachep;
|
||||
extern struct kmem_cache *ceph_file_cachep;
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -207,7 +207,6 @@ struct ceph_msg_data_cursor {
|
|||
|
||||
struct ceph_msg_data *data; /* current data item */
|
||||
size_t resid; /* bytes not yet consumed */
|
||||
bool last_piece; /* current is last piece */
|
||||
bool need_crc; /* crc update needed */
|
||||
union {
|
||||
#ifdef CONFIG_BLOCK
|
||||
|
|
@ -383,6 +382,10 @@ struct ceph_connection_v2_info {
|
|||
struct ceph_gcm_nonce in_gcm_nonce;
|
||||
struct ceph_gcm_nonce out_gcm_nonce;
|
||||
|
||||
struct page **in_enc_pages;
|
||||
int in_enc_page_cnt;
|
||||
int in_enc_resid;
|
||||
int in_enc_i;
|
||||
struct page **out_enc_pages;
|
||||
int out_enc_page_cnt;
|
||||
int out_enc_resid;
|
||||
|
|
@ -457,6 +460,7 @@ struct ceph_connection {
|
|||
struct ceph_msg *out_msg; /* sending message (== tail of
|
||||
out_sent) */
|
||||
|
||||
struct page *bounce_page;
|
||||
u32 in_front_crc, in_middle_crc, in_data_crc; /* calculated crc */
|
||||
|
||||
struct timespec64 last_keepalive_ack; /* keepalive2 ack stamp */
|
||||
|
|
@ -493,8 +497,7 @@ void ceph_con_discard_requeued(struct ceph_connection *con, u64 reconnect_seq);
|
|||
void ceph_msg_data_cursor_init(struct ceph_msg_data_cursor *cursor,
|
||||
struct ceph_msg *msg, size_t length);
|
||||
struct page *ceph_msg_data_next(struct ceph_msg_data_cursor *cursor,
|
||||
size_t *page_offset, size_t *length,
|
||||
bool *last_piece);
|
||||
size_t *page_offset, size_t *length);
|
||||
void ceph_msg_data_advance(struct ceph_msg_data_cursor *cursor, size_t bytes);
|
||||
|
||||
u32 ceph_crc32c_page(u32 crc, struct page *page, unsigned int page_offset,
|
||||
|
|
|
|||
|
|
@ -287,6 +287,9 @@ struct ceph_osd_linger_request {
|
|||
rados_watcherrcb_t errcb;
|
||||
void *data;
|
||||
|
||||
struct ceph_pagelist *request_pl;
|
||||
struct page **notify_id_pages;
|
||||
|
||||
struct page ***preply_pages;
|
||||
size_t *preply_len;
|
||||
};
|
||||
|
|
@ -504,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);
|
||||
|
|
|
|||
|
|
@ -2,40 +2,38 @@
|
|||
/*
|
||||
* Clang Control Flow Integrity (CFI) support.
|
||||
*
|
||||
* Copyright (C) 2021 Google LLC
|
||||
* Copyright (C) 2022 Google LLC
|
||||
*/
|
||||
#ifndef _LINUX_CFI_H
|
||||
#define _LINUX_CFI_H
|
||||
|
||||
#include <linux/bug.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#ifdef CONFIG_CFI_CLANG
|
||||
typedef void (*cfi_check_fn)(uint64_t id, void *ptr, void *diag);
|
||||
enum bug_trap_type report_cfi_failure(struct pt_regs *regs, unsigned long addr,
|
||||
unsigned long *target, u32 type);
|
||||
|
||||
/* Compiler-generated function in each module, and the kernel */
|
||||
extern void __cfi_check(uint64_t id, void *ptr, void *diag);
|
||||
|
||||
/*
|
||||
* Force the compiler to generate a CFI jump table entry for a function
|
||||
* and store the jump table address to __cfi_jt_<function>.
|
||||
*/
|
||||
#define __CFI_ADDRESSABLE(fn, __attr) \
|
||||
const void *__cfi_jt_ ## fn __visible __attr = (void *)&fn
|
||||
|
||||
#ifdef CONFIG_CFI_CLANG_SHADOW
|
||||
|
||||
extern void cfi_module_add(struct module *mod, unsigned long base_addr);
|
||||
extern void cfi_module_remove(struct module *mod, unsigned long base_addr);
|
||||
|
||||
#else
|
||||
|
||||
static inline void cfi_module_add(struct module *mod, unsigned long base_addr) {}
|
||||
static inline void cfi_module_remove(struct module *mod, unsigned long base_addr) {}
|
||||
|
||||
#endif /* CONFIG_CFI_CLANG_SHADOW */
|
||||
|
||||
#else /* !CONFIG_CFI_CLANG */
|
||||
|
||||
#define __CFI_ADDRESSABLE(fn, __attr)
|
||||
static inline enum bug_trap_type report_cfi_failure_noaddr(struct pt_regs *regs,
|
||||
unsigned long addr)
|
||||
{
|
||||
return report_cfi_failure(regs, addr, NULL, 0);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ARCH_USES_CFI_TRAPS
|
||||
bool is_cfi_trap(unsigned long addr);
|
||||
#endif
|
||||
#endif /* CONFIG_CFI_CLANG */
|
||||
|
||||
#ifdef CONFIG_MODULES
|
||||
#ifdef CONFIG_ARCH_USES_CFI_TRAPS
|
||||
void module_cfi_finalize(const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs,
|
||||
struct module *mod);
|
||||
#else
|
||||
static inline void module_cfi_finalize(const Elf_Ehdr *hdr,
|
||||
const Elf_Shdr *sechdrs,
|
||||
struct module *mod) {}
|
||||
#endif /* CONFIG_ARCH_USES_CFI_TRAPS */
|
||||
#endif /* CONFIG_MODULES */
|
||||
|
||||
#endif /* _LINUX_CFI_H */
|
||||
|
|
|
|||
45
include/linux/cfi_types.h
Normal file
45
include/linux/cfi_types.h
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Clang Control Flow Integrity (CFI) type definitions.
|
||||
*/
|
||||
#ifndef _LINUX_CFI_TYPES_H
|
||||
#define _LINUX_CFI_TYPES_H
|
||||
|
||||
#ifdef __ASSEMBLY__
|
||||
#include <linux/linkage.h>
|
||||
|
||||
#ifdef CONFIG_CFI_CLANG
|
||||
/*
|
||||
* Use the __kcfi_typeid_<function> type identifier symbol to
|
||||
* annotate indirectly called assembly functions. The compiler emits
|
||||
* these symbols for all address-taken function declarations in C
|
||||
* code.
|
||||
*/
|
||||
#ifndef __CFI_TYPE
|
||||
#define __CFI_TYPE(name) \
|
||||
.4byte __kcfi_typeid_##name
|
||||
#endif
|
||||
|
||||
#define SYM_TYPED_ENTRY(name, linkage, align...) \
|
||||
linkage(name) ASM_NL \
|
||||
align ASM_NL \
|
||||
__CFI_TYPE(name) ASM_NL \
|
||||
name:
|
||||
|
||||
#define SYM_TYPED_START(name, linkage, align...) \
|
||||
SYM_TYPED_ENTRY(name, linkage, align)
|
||||
|
||||
#else /* CONFIG_CFI_CLANG */
|
||||
|
||||
#define SYM_TYPED_START(name, linkage, align...) \
|
||||
SYM_START(name, linkage, align)
|
||||
|
||||
#endif /* CONFIG_CFI_CLANG */
|
||||
|
||||
#ifndef SYM_TYPED_FUNC_START
|
||||
#define SYM_TYPED_FUNC_START(name) \
|
||||
SYM_TYPED_START(name, SYM_L_GLOBAL, SYM_A_ALIGN)
|
||||
#endif
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
#endif /* _LINUX_CFI_TYPES_H */
|
||||
|
|
@ -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 */
|
||||
|
|
@ -113,11 +126,11 @@ enum {
|
|||
CFTYPE_NO_PREFIX = (1 << 3), /* (DON'T USE FOR NEW FILES) no subsys prefix */
|
||||
CFTYPE_WORLD_WRITABLE = (1 << 4), /* (DON'T USE FOR NEW FILES) S_IWUGO */
|
||||
CFTYPE_DEBUG = (1 << 5), /* create when cgroup_debug */
|
||||
CFTYPE_PRESSURE = (1 << 6), /* only if pressure feature is enabled */
|
||||
|
||||
/* internal flags, do not use outside cgroup core proper */
|
||||
__CFTYPE_ONLY_ON_DFL = (1 << 16), /* only on default hierarchy */
|
||||
__CFTYPE_NOT_ON_DFL = (1 << 17), /* not on default hierarchy */
|
||||
__CFTYPE_ADDED = (1 << 18),
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -264,7 +277,8 @@ struct css_set {
|
|||
* List of csets participating in the on-going migration either as
|
||||
* source or destination. Protected by cgroup_mutex.
|
||||
*/
|
||||
struct list_head mg_preload_node;
|
||||
struct list_head mg_src_preload_node;
|
||||
struct list_head mg_dst_preload_node;
|
||||
struct list_head mg_node;
|
||||
|
||||
/*
|
||||
|
|
@ -287,6 +301,10 @@ struct css_set {
|
|||
|
||||
struct cgroup_base_stat {
|
||||
struct task_cputime cputime;
|
||||
|
||||
#ifdef CONFIG_SCHED_CORE
|
||||
u64 forceidle_sum;
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -366,7 +384,7 @@ struct cgroup {
|
|||
/*
|
||||
* The depth this cgroup is at. The root is at depth zero and each
|
||||
* step down the hierarchy increments the level. This along with
|
||||
* ancestor_ids[] can determine whether a given cgroup is a
|
||||
* ancestors[] can determine whether a given cgroup is a
|
||||
* descendant of another without traversing the hierarchy.
|
||||
*/
|
||||
int level;
|
||||
|
|
@ -410,6 +428,9 @@ struct cgroup {
|
|||
struct cgroup_file procs_file; /* handle for "cgroup.procs" */
|
||||
struct cgroup_file events_file; /* handle for "cgroup.events" */
|
||||
|
||||
/* handles for "{cpu,memory,io,irq}.pressure" */
|
||||
struct cgroup_file psi_files[NR_PSI_RESOURCES];
|
||||
|
||||
/*
|
||||
* The bitmask of subsystems enabled on the child cgroups.
|
||||
* ->subtree_control is the one configured through
|
||||
|
|
@ -475,7 +496,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;
|
||||
|
|
@ -486,8 +507,8 @@ struct cgroup {
|
|||
/* Used to store internal freezer state */
|
||||
struct cgroup_freezer_state freezer;
|
||||
|
||||
/* ids of the ancestors at each level including self */
|
||||
u64 ancestor_ids[];
|
||||
/* All ancestors including self */
|
||||
struct cgroup *ancestors[];
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -504,11 +525,15 @@ struct cgroup_root {
|
|||
/* Unique id for this hierarchy. */
|
||||
int hierarchy_id;
|
||||
|
||||
/* The root cgroup. Root is destroyed on its release. */
|
||||
/*
|
||||
* The root cgroup. The containing cgroup_root will be destroyed on its
|
||||
* release. cgrp->ancestors[0] will be used overflowing into the
|
||||
* following field. cgrp_ancestor_storage must immediately follow.
|
||||
*/
|
||||
struct cgroup cgrp;
|
||||
|
||||
/* for cgrp->ancestor_ids[0] */
|
||||
u64 cgrp_ancestor_id_storage;
|
||||
/* must follow cgrp for cgrp->ancestors[0], see above */
|
||||
struct cgroup *cgrp_ancestor_storage;
|
||||
|
||||
/* Number of cgroups in the hierarchy, used only for /proc/cgroups */
|
||||
atomic_t nr_cgrps;
|
||||
|
|
|
|||
|
|
@ -68,6 +68,7 @@ struct css_task_iter {
|
|||
struct list_head iters_node; /* css_set->task_iters */
|
||||
};
|
||||
|
||||
extern struct file_system_type cgroup_fs_type;
|
||||
extern struct cgroup_root cgrp_dfl_root;
|
||||
extern struct css_set init_css_set;
|
||||
|
||||
|
|
@ -106,6 +107,7 @@ struct cgroup_subsys_state *css_tryget_online_from_dir(struct dentry *dentry,
|
|||
|
||||
struct cgroup *cgroup_get_from_path(const char *path);
|
||||
struct cgroup *cgroup_get_from_fd(int fd);
|
||||
struct cgroup *cgroup_v1v2_get_from_fd(int fd);
|
||||
|
||||
int cgroup_attach_task_all(struct task_struct *from, struct task_struct *);
|
||||
int cgroup_transfer_tasks(struct cgroup *to, struct cgroup *from);
|
||||
|
|
@ -114,6 +116,7 @@ int cgroup_add_dfl_cftypes(struct cgroup_subsys *ss, struct cftype *cfts);
|
|||
int cgroup_add_legacy_cftypes(struct cgroup_subsys *ss, struct cftype *cfts);
|
||||
int cgroup_rm_cftypes(struct cftype *cfts);
|
||||
void cgroup_file_notify(struct cgroup_file *cfile);
|
||||
void cgroup_file_show(struct cgroup_file *cfile, bool show);
|
||||
|
||||
int task_cgroup_path(struct task_struct *task, char *buf, size_t buflen);
|
||||
int cgroupstats_build(struct cgroupstats *stats, struct dentry *dentry);
|
||||
|
|
@ -432,6 +435,18 @@ static inline void cgroup_put(struct cgroup *cgrp)
|
|||
css_put(&cgrp->self);
|
||||
}
|
||||
|
||||
extern struct mutex cgroup_mutex;
|
||||
|
||||
static inline void cgroup_lock(void)
|
||||
{
|
||||
mutex_lock(&cgroup_mutex);
|
||||
}
|
||||
|
||||
static inline void cgroup_unlock(void)
|
||||
{
|
||||
mutex_unlock(&cgroup_mutex);
|
||||
}
|
||||
|
||||
/**
|
||||
* task_css_set_check - obtain a task's css_set with extra access conditions
|
||||
* @task: the task to obtain css_set for
|
||||
|
|
@ -446,10 +461,10 @@ static inline void cgroup_put(struct cgroup *cgrp)
|
|||
* as locks used during the cgroup_subsys::attach() methods.
|
||||
*/
|
||||
#ifdef CONFIG_PROVE_RCU
|
||||
extern struct mutex cgroup_mutex;
|
||||
extern spinlock_t css_set_lock;
|
||||
#define task_css_set_check(task, __c) \
|
||||
rcu_dereference_check((task)->cgroups, \
|
||||
rcu_read_lock_sched_held() || \
|
||||
lockdep_is_held(&cgroup_mutex) || \
|
||||
lockdep_is_held(&css_set_lock) || \
|
||||
((task)->flags & PF_EXITING) || (__c))
|
||||
|
|
@ -573,7 +588,7 @@ static inline bool cgroup_is_descendant(struct cgroup *cgrp,
|
|||
{
|
||||
if (cgrp->root != ancestor->root || cgrp->level < ancestor->level)
|
||||
return false;
|
||||
return cgrp->ancestor_ids[ancestor->level] == cgroup_id(ancestor);
|
||||
return cgrp->ancestors[ancestor->level] == ancestor;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -590,11 +605,9 @@ static inline bool cgroup_is_descendant(struct cgroup *cgrp,
|
|||
static inline struct cgroup *cgroup_ancestor(struct cgroup *cgrp,
|
||||
int ancestor_level)
|
||||
{
|
||||
if (cgrp->level < ancestor_level)
|
||||
if (ancestor_level < 0 || ancestor_level > cgrp->level)
|
||||
return NULL;
|
||||
while (cgrp && cgrp->level > ancestor_level)
|
||||
cgrp = cgroup_parent(cgrp);
|
||||
return cgrp;
|
||||
return cgrp->ancestors[ancestor_level];
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -671,11 +684,6 @@ static inline void pr_cont_cgroup_path(struct cgroup *cgrp)
|
|||
pr_cont_kernfs_path(cgrp->kn);
|
||||
}
|
||||
|
||||
static inline struct psi_group *cgroup_psi(struct cgroup *cgrp)
|
||||
{
|
||||
return &cgrp->psi;
|
||||
}
|
||||
|
||||
bool cgroup_psi_enabled(void);
|
||||
|
||||
static inline void cgroup_init_kthreadd(void)
|
||||
|
|
@ -707,6 +715,8 @@ struct cgroup;
|
|||
static inline u64 cgroup_id(const struct cgroup *cgrp) { return 1; }
|
||||
static inline void css_get(struct cgroup_subsys_state *css) {}
|
||||
static inline void css_put(struct cgroup_subsys_state *css) {}
|
||||
static inline void cgroup_lock(void) {}
|
||||
static inline void cgroup_unlock(void) {}
|
||||
static inline int cgroup_attach_task_all(struct task_struct *from,
|
||||
struct task_struct *t) { return 0; }
|
||||
static inline int cgroupstats_build(struct cgroupstats *stats,
|
||||
|
|
@ -733,11 +743,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;
|
||||
|
|
@ -751,11 +756,6 @@ static inline bool task_under_cgroup_hierarchy(struct task_struct *task,
|
|||
|
||||
static inline void cgroup_path_from_kernfs_id(u64 id, char *buf, size_t buflen)
|
||||
{}
|
||||
|
||||
static inline struct cgroup *cgroup_get_from_id(u64 id)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
#endif /* !CONFIG_CGROUPS */
|
||||
|
||||
#ifdef CONFIG_CGROUPS
|
||||
|
|
@ -791,11 +791,9 @@ static inline void cgroup_account_cputime(struct task_struct *task,
|
|||
|
||||
cpuacct_charge(task, delta_exec);
|
||||
|
||||
rcu_read_lock();
|
||||
cgrp = task_dfl_cgroup(task);
|
||||
if (cgroup_parent(cgrp))
|
||||
__cgroup_account_cputime(cgrp, delta_exec);
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
static inline void cgroup_account_cputime_field(struct task_struct *task,
|
||||
|
|
@ -806,11 +804,9 @@ static inline void cgroup_account_cputime_field(struct task_struct *task,
|
|||
|
||||
cpuacct_account_field(task, index, delta_exec);
|
||||
|
||||
rcu_read_lock();
|
||||
cgrp = task_dfl_cgroup(task);
|
||||
if (cgroup_parent(cgrp))
|
||||
__cgroup_account_cputime_field(cgrp, index, delta_exec);
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
#else /* CONFIG_CGROUPS */
|
||||
|
|
|
|||
1
include/linux/cgroup_api.h
Normal file
1
include/linux/cgroup_api.h
Normal file
|
|
@ -0,0 +1 @@
|
|||
#include <linux/cgroup.h>
|
||||
|
|
@ -42,6 +42,8 @@ struct dentry;
|
|||
* struct clk_rate_request - Structure encoding the clk constraints that
|
||||
* a clock user might require.
|
||||
*
|
||||
* Should be initialized by calling clk_hw_init_rate_request().
|
||||
*
|
||||
* @rate: Requested clock rate. This field will be adjusted by
|
||||
* clock drivers according to hardware capabilities.
|
||||
* @min_rate: Minimum rate imposed by clk users.
|
||||
|
|
@ -60,6 +62,15 @@ struct clk_rate_request {
|
|||
struct clk_hw *best_parent_hw;
|
||||
};
|
||||
|
||||
void clk_hw_init_rate_request(const struct clk_hw *hw,
|
||||
struct clk_rate_request *req,
|
||||
unsigned long rate);
|
||||
void clk_hw_forward_rate_request(const struct clk_hw *core,
|
||||
const struct clk_rate_request *old_req,
|
||||
const struct clk_hw *parent,
|
||||
struct clk_rate_request *req,
|
||||
unsigned long parent_rate);
|
||||
|
||||
/**
|
||||
* struct clk_duty - Struture encoding the duty cycle ratio of a clock
|
||||
*
|
||||
|
|
@ -118,8 +129,9 @@ struct clk_duty {
|
|||
*
|
||||
* @recalc_rate Recalculate the rate of this clock, by querying hardware. The
|
||||
* parent rate is an input parameter. It is up to the caller to
|
||||
* ensure that the prepare_mutex is held across this call.
|
||||
* Returns the calculated rate. Optional, but recommended - if
|
||||
* ensure that the prepare_mutex is held across this call. If the
|
||||
* driver cannot figure out a rate for this clock, it must return
|
||||
* 0. Returns the calculated rate. Optional, but recommended - if
|
||||
* this op is not set then clock rate will be initialized to 0.
|
||||
*
|
||||
* @round_rate: Given a target rate as input, returns the closest rate actually
|
||||
|
|
@ -350,7 +362,7 @@ struct clk_hw *__clk_hw_register_fixed_rate(struct device *dev,
|
|||
const char *parent_name, const struct clk_hw *parent_hw,
|
||||
const struct clk_parent_data *parent_data, unsigned long flags,
|
||||
unsigned long fixed_rate, unsigned long fixed_accuracy,
|
||||
unsigned long clk_fixed_flags);
|
||||
unsigned long clk_fixed_flags, bool devm);
|
||||
struct clk *clk_register_fixed_rate(struct device *dev, const char *name,
|
||||
const char *parent_name, unsigned long flags,
|
||||
unsigned long fixed_rate);
|
||||
|
|
@ -365,7 +377,20 @@ struct clk *clk_register_fixed_rate(struct device *dev, const char *name,
|
|||
*/
|
||||
#define clk_hw_register_fixed_rate(dev, name, parent_name, flags, fixed_rate) \
|
||||
__clk_hw_register_fixed_rate((dev), NULL, (name), (parent_name), NULL, \
|
||||
NULL, (flags), (fixed_rate), 0, 0)
|
||||
NULL, (flags), (fixed_rate), 0, 0, false)
|
||||
|
||||
/**
|
||||
* devm_clk_hw_register_fixed_rate - register fixed-rate clock with the clock
|
||||
* framework
|
||||
* @dev: device that is registering this clock
|
||||
* @name: name of this clock
|
||||
* @parent_name: name of clock's parent
|
||||
* @flags: framework-specific flags
|
||||
* @fixed_rate: non-adjustable clock rate
|
||||
*/
|
||||
#define devm_clk_hw_register_fixed_rate(dev, name, parent_name, flags, fixed_rate) \
|
||||
__clk_hw_register_fixed_rate((dev), NULL, (name), (parent_name), NULL, \
|
||||
NULL, (flags), (fixed_rate), 0, 0, true)
|
||||
/**
|
||||
* clk_hw_register_fixed_rate_parent_hw - register fixed-rate clock with
|
||||
* the clock framework
|
||||
|
|
@ -378,7 +403,7 @@ struct clk *clk_register_fixed_rate(struct device *dev, const char *name,
|
|||
#define clk_hw_register_fixed_rate_parent_hw(dev, name, parent_hw, flags, \
|
||||
fixed_rate) \
|
||||
__clk_hw_register_fixed_rate((dev), NULL, (name), NULL, (parent_hw), \
|
||||
NULL, (flags), (fixed_rate), 0, 0)
|
||||
NULL, (flags), (fixed_rate), 0, 0, false)
|
||||
/**
|
||||
* clk_hw_register_fixed_rate_parent_data - register fixed-rate clock with
|
||||
* the clock framework
|
||||
|
|
@ -392,7 +417,7 @@ struct clk *clk_register_fixed_rate(struct device *dev, const char *name,
|
|||
fixed_rate) \
|
||||
__clk_hw_register_fixed_rate((dev), NULL, (name), NULL, NULL, \
|
||||
(parent_data), (flags), (fixed_rate), 0, \
|
||||
0)
|
||||
0, false)
|
||||
/**
|
||||
* clk_hw_register_fixed_rate_with_accuracy - register fixed-rate clock with
|
||||
* the clock framework
|
||||
|
|
@ -408,7 +433,7 @@ struct clk *clk_register_fixed_rate(struct device *dev, const char *name,
|
|||
fixed_accuracy) \
|
||||
__clk_hw_register_fixed_rate((dev), NULL, (name), (parent_name), \
|
||||
NULL, NULL, (flags), (fixed_rate), \
|
||||
(fixed_accuracy), 0)
|
||||
(fixed_accuracy), 0, false)
|
||||
/**
|
||||
* clk_hw_register_fixed_rate_with_accuracy_parent_hw - register fixed-rate
|
||||
* clock with the clock framework
|
||||
|
|
@ -423,7 +448,7 @@ struct clk *clk_register_fixed_rate(struct device *dev, const char *name,
|
|||
parent_hw, flags, fixed_rate, fixed_accuracy) \
|
||||
__clk_hw_register_fixed_rate((dev), NULL, (name), NULL, (parent_hw) \
|
||||
NULL, NULL, (flags), (fixed_rate), \
|
||||
(fixed_accuracy), 0)
|
||||
(fixed_accuracy), 0, false)
|
||||
/**
|
||||
* clk_hw_register_fixed_rate_with_accuracy_parent_data - register fixed-rate
|
||||
* clock with the clock framework
|
||||
|
|
@ -438,7 +463,21 @@ struct clk *clk_register_fixed_rate(struct device *dev, const char *name,
|
|||
parent_data, flags, fixed_rate, fixed_accuracy) \
|
||||
__clk_hw_register_fixed_rate((dev), NULL, (name), NULL, NULL, \
|
||||
(parent_data), NULL, (flags), \
|
||||
(fixed_rate), (fixed_accuracy), 0)
|
||||
(fixed_rate), (fixed_accuracy), 0, false)
|
||||
/**
|
||||
* clk_hw_register_fixed_rate_parent_accuracy - register fixed-rate clock with
|
||||
* the clock framework
|
||||
* @dev: device that is registering this clock
|
||||
* @name: name of this clock
|
||||
* @parent_name: name of clock's parent
|
||||
* @flags: framework-specific flags
|
||||
* @fixed_rate: non-adjustable clock rate
|
||||
*/
|
||||
#define clk_hw_register_fixed_rate_parent_accuracy(dev, name, parent_data, \
|
||||
flags, fixed_rate) \
|
||||
__clk_hw_register_fixed_rate((dev), NULL, (name), NULL, NULL, \
|
||||
(parent_data), (flags), (fixed_rate), 0, \
|
||||
CLK_FIXED_RATE_PARENT_ACCURACY, false)
|
||||
|
||||
void clk_unregister_fixed_rate(struct clk *clk);
|
||||
void clk_hw_unregister_fixed_rate(struct clk_hw *hw);
|
||||
|
|
@ -831,6 +870,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)
|
||||
|
|
@ -888,7 +946,7 @@ void clk_hw_unregister_divider(struct clk_hw *hw);
|
|||
struct clk_mux {
|
||||
struct clk_hw hw;
|
||||
void __iomem *reg;
|
||||
u32 *table;
|
||||
const u32 *table;
|
||||
u32 mask;
|
||||
u8 shift;
|
||||
u8 flags;
|
||||
|
|
@ -913,18 +971,18 @@ struct clk_hw *__clk_hw_register_mux(struct device *dev, struct device_node *np,
|
|||
const struct clk_hw **parent_hws,
|
||||
const struct clk_parent_data *parent_data,
|
||||
unsigned long flags, void __iomem *reg, u8 shift, u32 mask,
|
||||
u8 clk_mux_flags, u32 *table, spinlock_t *lock);
|
||||
u8 clk_mux_flags, const u32 *table, spinlock_t *lock);
|
||||
struct clk_hw *__devm_clk_hw_register_mux(struct device *dev, struct device_node *np,
|
||||
const char *name, u8 num_parents,
|
||||
const char * const *parent_names,
|
||||
const struct clk_hw **parent_hws,
|
||||
const struct clk_parent_data *parent_data,
|
||||
unsigned long flags, void __iomem *reg, u8 shift, u32 mask,
|
||||
u8 clk_mux_flags, u32 *table, spinlock_t *lock);
|
||||
u8 clk_mux_flags, const u32 *table, spinlock_t *lock);
|
||||
struct clk *clk_register_mux_table(struct device *dev, const char *name,
|
||||
const char * const *parent_names, u8 num_parents,
|
||||
unsigned long flags, void __iomem *reg, u8 shift, u32 mask,
|
||||
u8 clk_mux_flags, u32 *table, spinlock_t *lock);
|
||||
u8 clk_mux_flags, const u32 *table, spinlock_t *lock);
|
||||
|
||||
#define clk_register_mux(dev, name, parent_names, num_parents, flags, reg, \
|
||||
shift, width, clk_mux_flags, lock) \
|
||||
|
|
@ -938,6 +996,13 @@ struct clk *clk_register_mux_table(struct device *dev, const char *name,
|
|||
(parent_names), NULL, NULL, (flags), (reg), \
|
||||
(shift), (mask), (clk_mux_flags), (table), \
|
||||
(lock))
|
||||
#define clk_hw_register_mux_table_parent_data(dev, name, parent_data, \
|
||||
num_parents, flags, reg, shift, mask, \
|
||||
clk_mux_flags, table, lock) \
|
||||
__clk_hw_register_mux((dev), NULL, (name), (num_parents), \
|
||||
NULL, NULL, (parent_data), (flags), (reg), \
|
||||
(shift), (mask), (clk_mux_flags), (table), \
|
||||
(lock))
|
||||
#define clk_hw_register_mux(dev, name, parent_names, num_parents, flags, reg, \
|
||||
shift, width, clk_mux_flags, lock) \
|
||||
__clk_hw_register_mux((dev), NULL, (name), (num_parents), \
|
||||
|
|
@ -955,16 +1020,37 @@ struct clk *clk_register_mux_table(struct device *dev, const char *name,
|
|||
__clk_hw_register_mux((dev), NULL, (name), (num_parents), NULL, NULL, \
|
||||
(parent_data), (flags), (reg), (shift), \
|
||||
BIT((width)) - 1, (clk_mux_flags), NULL, (lock))
|
||||
#define clk_hw_register_mux_parent_data_table(dev, name, parent_data, \
|
||||
num_parents, flags, reg, shift, \
|
||||
width, clk_mux_flags, table, \
|
||||
lock) \
|
||||
__clk_hw_register_mux((dev), NULL, (name), (num_parents), NULL, NULL, \
|
||||
(parent_data), (flags), (reg), (shift), \
|
||||
BIT((width)) - 1, (clk_mux_flags), table, (lock))
|
||||
#define devm_clk_hw_register_mux(dev, name, parent_names, num_parents, flags, reg, \
|
||||
shift, width, clk_mux_flags, lock) \
|
||||
__devm_clk_hw_register_mux((dev), NULL, (name), (num_parents), \
|
||||
(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))
|
||||
#define devm_clk_hw_register_mux_parent_data_table(dev, name, parent_data, \
|
||||
num_parents, flags, reg, shift, \
|
||||
width, clk_mux_flags, table, \
|
||||
lock) \
|
||||
__devm_clk_hw_register_mux((dev), NULL, (name), (num_parents), NULL, \
|
||||
NULL, (parent_data), (flags), (reg), (shift), \
|
||||
BIT((width)) - 1, (clk_mux_flags), table, (lock))
|
||||
|
||||
int clk_mux_val_to_index(struct clk_hw *hw, u32 *table, unsigned int flags,
|
||||
int clk_mux_val_to_index(struct clk_hw *hw, const u32 *table, unsigned int flags,
|
||||
unsigned int val);
|
||||
unsigned int clk_mux_index_to_val(u32 *table, unsigned int flags, u8 index);
|
||||
unsigned int clk_mux_index_to_val(const u32 *table, unsigned int flags, u8 index);
|
||||
|
||||
void clk_unregister_mux(struct clk *clk);
|
||||
void clk_hw_unregister_mux(struct clk_hw *hw);
|
||||
|
|
@ -1003,6 +1089,17 @@ void clk_hw_unregister_fixed_factor(struct clk_hw *hw);
|
|||
struct clk_hw *devm_clk_hw_register_fixed_factor(struct device *dev,
|
||||
const char *name, const char *parent_name, unsigned long flags,
|
||||
unsigned int mult, unsigned int div);
|
||||
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
|
||||
*
|
||||
|
|
@ -1173,10 +1270,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);
|
||||
|
|
@ -1220,6 +1315,8 @@ int clk_mux_determine_rate_flags(struct clk_hw *hw,
|
|||
struct clk_rate_request *req,
|
||||
unsigned long flags);
|
||||
void clk_hw_reparent(struct clk_hw *hw, struct clk_hw *new_parent);
|
||||
void clk_hw_get_rate_range(struct clk_hw *hw, unsigned long *min_rate,
|
||||
unsigned long *max_rate);
|
||||
void clk_hw_set_rate_range(struct clk_hw *hw, unsigned long min_rate,
|
||||
unsigned long max_rate);
|
||||
|
||||
|
|
@ -1419,7 +1516,7 @@ int devm_of_clk_add_hw_provider(struct device *dev,
|
|||
void *data),
|
||||
void *data);
|
||||
void of_clk_del_provider(struct device_node *np);
|
||||
void devm_of_clk_del_provider(struct device *dev);
|
||||
|
||||
struct clk *of_clk_src_simple_get(struct of_phandle_args *clkspec,
|
||||
void *data);
|
||||
struct clk_hw *of_clk_hw_simple_get(struct of_phandle_args *clkspec,
|
||||
|
|
@ -1456,7 +1553,7 @@ static inline int devm_of_clk_add_hw_provider(struct device *dev,
|
|||
return 0;
|
||||
}
|
||||
static inline void of_clk_del_provider(struct device_node *np) {}
|
||||
static inline void devm_of_clk_del_provider(struct device *dev) {}
|
||||
|
||||
static inline struct clk *of_clk_src_simple_get(
|
||||
struct of_phandle_args *clkspec, void *data)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
@ -701,7 +799,7 @@ int clk_set_rate_exclusive(struct clk *clk, unsigned long rate);
|
|||
*
|
||||
* Returns true if @parent is a possible parent for @clk, false otherwise.
|
||||
*/
|
||||
bool clk_has_parent(struct clk *clk, struct clk *parent);
|
||||
bool clk_has_parent(const struct clk *clk, const struct clk *parent);
|
||||
|
||||
/**
|
||||
* clk_set_rate_range - set a rate range for a clock source
|
||||
|
|
@ -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)
|
||||
{
|
||||
|
|
@ -986,6 +1108,17 @@ static inline void clk_bulk_disable_unprepare(int num_clks,
|
|||
clk_bulk_unprepare(num_clks, clks);
|
||||
}
|
||||
|
||||
/**
|
||||
* clk_drop_range - Reset any range set on that clock
|
||||
* @clk: clock source
|
||||
*
|
||||
* Returns success (0) or negative errno.
|
||||
*/
|
||||
static inline int clk_drop_range(struct clk *clk)
|
||||
{
|
||||
return clk_set_rate_range(clk, 0, ULONG_MAX);
|
||||
}
|
||||
|
||||
/**
|
||||
* clk_get_optional - lookup and obtain a reference to an optional clock
|
||||
* producer.
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@
|
|||
#ifndef AT91_PMC_H
|
||||
#define AT91_PMC_H
|
||||
|
||||
#include <linux/bits.h>
|
||||
|
||||
#define AT91_PMC_V1 (1) /* PMC version 1 */
|
||||
#define AT91_PMC_V2 (2) /* PMC version 2 [SAM9X60] */
|
||||
|
||||
|
|
@ -45,8 +47,8 @@
|
|||
#define AT91_PMC_PCSR 0x18 /* Peripheral Clock Status Register */
|
||||
|
||||
#define AT91_PMC_PLL_ACR 0x18 /* PLL Analog Control Register [for SAM9X60] */
|
||||
#define AT91_PMC_PLL_ACR_DEFAULT_UPLL 0x12020010UL /* Default PLL ACR value for UPLL */
|
||||
#define AT91_PMC_PLL_ACR_DEFAULT_PLLA 0x00020010UL /* Default PLL ACR value for PLLA */
|
||||
#define AT91_PMC_PLL_ACR_DEFAULT_UPLL UL(0x12020010) /* Default PLL ACR value for UPLL */
|
||||
#define AT91_PMC_PLL_ACR_DEFAULT_PLLA UL(0x00020010) /* Default PLL ACR value for PLLA */
|
||||
#define AT91_PMC_PLL_ACR_UTMIVR (1 << 12) /* UPLL Voltage regulator Control */
|
||||
#define AT91_PMC_PLL_ACR_UTMIBG (1 << 13) /* UPLL Bandgap Control */
|
||||
|
||||
|
|
@ -78,6 +80,10 @@
|
|||
#define AT91_PMC_MAINRDY (1 << 16) /* Main Clock Ready */
|
||||
|
||||
#define AT91_CKGR_PLLAR 0x28 /* PLL A Register */
|
||||
|
||||
#define AT91_PMC_RATIO 0x2c /* Processor clock ratio register [SAMA7G5 only] */
|
||||
#define AT91_PMC_RATIO_RATIO (0xf) /* CPU clock ratio. */
|
||||
|
||||
#define AT91_CKGR_PLLBR 0x2c /* PLL B Register */
|
||||
#define AT91_PMC_DIV (0xff << 0) /* Divider */
|
||||
#define AT91_PMC_PLLCOUNT (0x3f << 8) /* PLL Counter */
|
||||
|
|
|
|||
|
|
@ -28,13 +28,5 @@ int dm365_pll1_init(struct device *dev, void __iomem *base, struct regmap *cfgch
|
|||
int dm365_pll2_init(struct device *dev, void __iomem *base, struct regmap *cfgchip);
|
||||
int dm365_psc_init(struct device *dev, void __iomem *base);
|
||||
#endif
|
||||
#ifdef CONFIG_ARCH_DAVINCI_DM644x
|
||||
int dm644x_pll1_init(struct device *dev, void __iomem *base, struct regmap *cfgchip);
|
||||
int dm644x_psc_init(struct device *dev, void __iomem *base);
|
||||
#endif
|
||||
#ifdef CONFIG_ARCH_DAVINCI_DM646x
|
||||
int dm646x_pll1_init(struct device *dev, void __iomem *base, struct regmap *cfgchip);
|
||||
int dm646x_psc_init(struct device *dev, void __iomem *base);
|
||||
#endif
|
||||
|
||||
#endif /* __LINUX_CLK_DAVINCI_PLL_H___ */
|
||||
|
|
|
|||
16
include/linux/clk/pxa.h
Normal file
16
include/linux/clk/pxa.h
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
|
||||
#include <linux/compiler.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
extern int pxa25x_clocks_init(void __iomem *regs);
|
||||
extern int pxa27x_clocks_init(void __iomem *regs);
|
||||
extern int pxa3xx_clocks_init(void __iomem *regs, void __iomem *oscc_reg);
|
||||
|
||||
#ifdef CONFIG_PXA3xx
|
||||
extern unsigned pxa3xx_get_clk_frequency_khz(int);
|
||||
extern void pxa3xx_clk_update_accr(u32 disable, u32 enable, u32 xclkcfg, u32 mask);
|
||||
#else
|
||||
#define pxa3xx_get_clk_frequency_khz(x) (0)
|
||||
#define pxa3xx_clk_update_accr(disable, enable, xclkcfg, mask) do { } while (0)
|
||||
#endif
|
||||
|
|
@ -8,6 +8,20 @@
|
|||
#ifndef __LINUX_CLK_SPEAR_H
|
||||
#define __LINUX_CLK_SPEAR_H
|
||||
|
||||
#ifdef CONFIG_ARCH_SPEAR3XX
|
||||
void __init spear3xx_clk_init(void __iomem *misc_base,
|
||||
void __iomem *soc_config_base);
|
||||
#else
|
||||
static inline void __init spear3xx_clk_init(void __iomem *misc_base,
|
||||
void __iomem *soc_config_base) {}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ARCH_SPEAR6XX
|
||||
void __init spear6xx_clk_init(void __iomem *misc_base);
|
||||
#else
|
||||
static inline void __init spear6xx_clk_init(void __iomem *misc_base) {}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_MACH_SPEAR1310
|
||||
void __init spear1310_clk_init(void __iomem *misc_base, void __iomem *ras_base);
|
||||
#else
|
||||
|
|
|
|||
|
|
@ -9,4 +9,6 @@
|
|||
int sunxi_ccu_set_mmc_timing_mode(struct clk *clk, bool new_mode);
|
||||
int sunxi_ccu_get_mmc_timing_mode(struct clk *clk);
|
||||
|
||||
int sun6i_rtc_ccu_probe(struct device *dev, void __iomem *reg);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -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__
|
||||
|
|
|
|||
|
|
@ -46,6 +46,4 @@ int clk_hw_register_clkdev(struct clk_hw *, const char *, const char *);
|
|||
|
||||
int devm_clk_hw_register_clkdev(struct device *dev, struct clk_hw *hw,
|
||||
const char *con_id, const char *dev_id);
|
||||
void devm_clk_release_clkdev(struct device *dev, const char *con_id,
|
||||
const char *dev_id);
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -12,14 +12,18 @@
|
|||
*/
|
||||
#ifdef CONFIG_CMA_AREAS
|
||||
#define MAX_CMA_AREAS (1 + CONFIG_CMA_AREAS)
|
||||
|
||||
#else
|
||||
#define MAX_CMA_AREAS (0)
|
||||
|
||||
#endif
|
||||
|
||||
#define CMA_MAX_NAME 64
|
||||
|
||||
/*
|
||||
* the buddy -- especially pageblock merging and alloc_contig_range()
|
||||
* -- can deal with only some pageblocks of a higher-order page being
|
||||
* MIGRATE_CMA, we can use pageblock_nr_pages.
|
||||
*/
|
||||
#define CMA_MIN_ALIGNMENT_PAGES pageblock_nr_pages
|
||||
#define CMA_MIN_ALIGNMENT_BYTES (PAGE_SIZE * CMA_MIN_ALIGNMENT_PAGES)
|
||||
|
||||
struct cma;
|
||||
|
||||
extern unsigned long totalcma_pages;
|
||||
|
|
@ -50,4 +54,6 @@ extern bool cma_pages_valid(struct cma *cma, const struct page *pages, unsigned
|
|||
extern bool cma_release(struct cma *cma, const struct page *pages, unsigned long count);
|
||||
|
||||
extern int cma_for_each_area(int (*it)(struct cma *cma, void *data), void *data);
|
||||
|
||||
extern void cma_reserve_pages_on_error(struct cma *cma);
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -177,7 +177,7 @@ static inline bool compaction_withdrawn(enum compact_result result)
|
|||
bool compaction_zonelist_suitable(struct alloc_context *ac, int order,
|
||||
int alloc_flags);
|
||||
|
||||
extern int kcompactd_run(int nid);
|
||||
extern void kcompactd_run(int nid);
|
||||
extern void kcompactd_stop(int nid);
|
||||
extern void wakeup_kcompactd(pg_data_t *pgdat, int order, int highest_zoneidx);
|
||||
|
||||
|
|
@ -212,9 +212,8 @@ static inline bool compaction_withdrawn(enum compact_result result)
|
|||
return true;
|
||||
}
|
||||
|
||||
static inline int kcompactd_run(int nid)
|
||||
static inline void kcompactd_run(int nid)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static inline void kcompactd_stop(int nid)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -235,6 +235,7 @@ typedef struct compat_siginfo {
|
|||
struct {
|
||||
compat_ulong_t _data;
|
||||
u32 _type;
|
||||
u32 _flags;
|
||||
} _perf;
|
||||
};
|
||||
} _sigfault;
|
||||
|
|
@ -258,6 +259,37 @@ struct compat_rlimit {
|
|||
compat_ulong_t rlim_max;
|
||||
};
|
||||
|
||||
#ifdef __ARCH_NEED_COMPAT_FLOCK64_PACKED
|
||||
#define __ARCH_COMPAT_FLOCK64_PACK __attribute__((packed))
|
||||
#else
|
||||
#define __ARCH_COMPAT_FLOCK64_PACK
|
||||
#endif
|
||||
|
||||
struct compat_flock {
|
||||
short l_type;
|
||||
short l_whence;
|
||||
compat_off_t l_start;
|
||||
compat_off_t l_len;
|
||||
#ifdef __ARCH_COMPAT_FLOCK_EXTRA_SYSID
|
||||
__ARCH_COMPAT_FLOCK_EXTRA_SYSID
|
||||
#endif
|
||||
compat_pid_t l_pid;
|
||||
#ifdef __ARCH_COMPAT_FLOCK_PAD
|
||||
__ARCH_COMPAT_FLOCK_PAD
|
||||
#endif
|
||||
};
|
||||
|
||||
struct compat_flock64 {
|
||||
short l_type;
|
||||
short l_whence;
|
||||
compat_loff_t l_start;
|
||||
compat_loff_t l_len;
|
||||
compat_pid_t l_pid;
|
||||
#ifdef __ARCH_COMPAT_FLOCK64_PAD
|
||||
__ARCH_COMPAT_FLOCK64_PAD
|
||||
#endif
|
||||
} __ARCH_COMPAT_FLOCK64_PACK;
|
||||
|
||||
struct compat_rusage {
|
||||
struct old_timeval32 ru_utime;
|
||||
struct old_timeval32 ru_stime;
|
||||
|
|
@ -895,6 +927,43 @@ asmlinkage long compat_sys_sigaction(int sig,
|
|||
/* obsolete: net/socket.c */
|
||||
asmlinkage long compat_sys_socketcall(int call, u32 __user *args);
|
||||
|
||||
#ifdef __ARCH_WANT_COMPAT_TRUNCATE64
|
||||
asmlinkage long compat_sys_truncate64(const char __user *pathname, compat_arg_u64(len));
|
||||
#endif
|
||||
|
||||
#ifdef __ARCH_WANT_COMPAT_FTRUNCATE64
|
||||
asmlinkage long compat_sys_ftruncate64(unsigned int fd, compat_arg_u64(len));
|
||||
#endif
|
||||
|
||||
#ifdef __ARCH_WANT_COMPAT_FALLOCATE
|
||||
asmlinkage long compat_sys_fallocate(int fd, int mode, compat_arg_u64(offset),
|
||||
compat_arg_u64(len));
|
||||
#endif
|
||||
|
||||
#ifdef __ARCH_WANT_COMPAT_PREAD64
|
||||
asmlinkage long compat_sys_pread64(unsigned int fd, char __user *buf, size_t count,
|
||||
compat_arg_u64(pos));
|
||||
#endif
|
||||
|
||||
#ifdef __ARCH_WANT_COMPAT_PWRITE64
|
||||
asmlinkage long compat_sys_pwrite64(unsigned int fd, const char __user *buf, size_t count,
|
||||
compat_arg_u64(pos));
|
||||
#endif
|
||||
|
||||
#ifdef __ARCH_WANT_COMPAT_SYNC_FILE_RANGE
|
||||
asmlinkage long compat_sys_sync_file_range(int fd, compat_arg_u64(pos),
|
||||
compat_arg_u64(nbytes), unsigned int flags);
|
||||
#endif
|
||||
|
||||
#ifdef __ARCH_WANT_COMPAT_FADVISE64_64
|
||||
asmlinkage long compat_sys_fadvise64_64(int fd, compat_arg_u64(pos),
|
||||
compat_arg_u64(len), int advice);
|
||||
#endif
|
||||
|
||||
#ifdef __ARCH_WANT_COMPAT_READAHEAD
|
||||
asmlinkage long compat_sys_readahead(int fd, compat_arg_u64(offset), size_t count);
|
||||
#endif
|
||||
|
||||
#endif /* CONFIG_ARCH_HAS_SYSCALL_WRAPPER */
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -51,6 +51,29 @@
|
|||
#define __no_sanitize_undefined
|
||||
#endif
|
||||
|
||||
#if __has_feature(memory_sanitizer)
|
||||
#define __SANITIZE_MEMORY__
|
||||
/*
|
||||
* Unlike other sanitizers, KMSAN still inserts code into functions marked with
|
||||
* no_sanitize("kernel-memory"). Using disable_sanitizer_instrumentation
|
||||
* provides the behavior consistent with other __no_sanitize_ attributes,
|
||||
* guaranteeing that __no_sanitize_memory functions remain uninstrumented.
|
||||
*/
|
||||
#define __no_sanitize_memory __disable_sanitizer_instrumentation
|
||||
|
||||
/*
|
||||
* The __no_kmsan_checks attribute ensures that a function does not produce
|
||||
* false positive reports by:
|
||||
* - initializing all local variables and memory stores in this function;
|
||||
* - skipping all shadow checks;
|
||||
* - passing initialized arguments to this function's callees.
|
||||
*/
|
||||
#define __no_kmsan_checks __attribute__((no_sanitize("kernel-memory")))
|
||||
#else
|
||||
#define __no_sanitize_memory
|
||||
#define __no_kmsan_checks
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Support for __has_feature(coverage_sanitizer) was added in Clang 13 together
|
||||
* with no_sanitize("coverage"). Prior versions of Clang support coverage
|
||||
|
|
@ -66,5 +89,32 @@
|
|||
# define __noscs __attribute__((__no_sanitize__("shadow-call-stack")))
|
||||
#endif
|
||||
|
||||
#define __nocfi __attribute__((__no_sanitize__("cfi")))
|
||||
#define __cficanonical __attribute__((__cfi_canonical_jump_table__))
|
||||
#if __has_feature(kcfi)
|
||||
/* Disable CFI checking inside a function. */
|
||||
#define __nocfi __attribute__((__no_sanitize__("kcfi")))
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Turn individual warnings and errors on and off locally, depending
|
||||
* on version.
|
||||
*/
|
||||
#define __diag_clang(version, severity, s) \
|
||||
__diag_clang_ ## version(__diag_clang_ ## severity s)
|
||||
|
||||
/* Severity used in pragma directives */
|
||||
#define __diag_clang_ignore ignored
|
||||
#define __diag_clang_warn warning
|
||||
#define __diag_clang_error error
|
||||
|
||||
#define __diag_str1(s) #s
|
||||
#define __diag_str(s) __diag_str1(s)
|
||||
#define __diag(s) _Pragma(__diag_str(clang diagnostic s))
|
||||
|
||||
#if CONFIG_CLANG_VERSION >= 110000
|
||||
#define __diag_clang_11(s) __diag(s)
|
||||
#else
|
||||
#define __diag_clang_11(s)
|
||||
#endif
|
||||
|
||||
#define __diag_ignore_all(option, comment) \
|
||||
__diag_clang(11, ignore, option)
|
||||
|
|
|
|||
|
|
@ -66,25 +66,6 @@
|
|||
__builtin_unreachable(); \
|
||||
} while (0)
|
||||
|
||||
#if defined(RANDSTRUCT_PLUGIN) && !defined(__CHECKER__)
|
||||
#define __randomize_layout __attribute__((randomize_layout))
|
||||
#define __no_randomize_layout __attribute__((no_randomize_layout))
|
||||
/* This anon struct can add padding, so only enable it under randstruct. */
|
||||
#define randomized_struct_fields_start struct {
|
||||
#define randomized_struct_fields_end } __randomize_layout;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* 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__
|
||||
|
|
@ -97,6 +78,10 @@
|
|||
#define KASAN_ABI_VERSION 4
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SHADOW_CALL_STACK
|
||||
#define __noscs __attribute__((__no_sanitize__("shadow-call-stack")))
|
||||
#endif
|
||||
|
||||
#if __has_attribute(__no_sanitize_address__)
|
||||
#define __no_sanitize_address __attribute__((no_sanitize_address))
|
||||
#else
|
||||
|
|
@ -129,6 +114,12 @@
|
|||
#define __SANITIZE_ADDRESS__
|
||||
#endif
|
||||
|
||||
/*
|
||||
* GCC does not support KMSAN.
|
||||
*/
|
||||
#define __no_sanitize_memory
|
||||
#define __no_kmsan_checks
|
||||
|
||||
/*
|
||||
* Turn individual warnings and errors on and off locally, depending
|
||||
* on version.
|
||||
|
|
@ -151,6 +142,9 @@
|
|||
#define __diag_GCC_8(s)
|
||||
#endif
|
||||
|
||||
#define __diag_ignore_all(option, comment) \
|
||||
__diag_GCC(8, ignore, option)
|
||||
|
||||
/*
|
||||
* Prior to 9.1, -Wno-alloc-size-larger-than (and therefore the "alloc_size"
|
||||
* attribute) do not work, and must be disabled.
|
||||
|
|
|
|||
|
|
@ -109,7 +109,7 @@ void ftrace_likely_update(struct ftrace_likely_data *f, int val,
|
|||
#endif
|
||||
|
||||
/* Unreachable code */
|
||||
#ifdef CONFIG_STACK_VALIDATION
|
||||
#ifdef CONFIG_OBJTOOL
|
||||
/*
|
||||
* These macros help objtool understand GCC code flow for unreachable code.
|
||||
* The __COUNTER__ based labels are a hack to make each instance of the macros
|
||||
|
|
@ -117,14 +117,6 @@ void ftrace_likely_update(struct ftrace_likely_data *f, int val,
|
|||
*/
|
||||
#define __stringify_label(n) #n
|
||||
|
||||
#define __annotate_reachable(c) ({ \
|
||||
asm volatile(__stringify_label(c) ":\n\t" \
|
||||
".pushsection .discard.reachable\n\t" \
|
||||
".long " __stringify_label(c) "b - .\n\t" \
|
||||
".popsection\n\t" : : "i" (c)); \
|
||||
})
|
||||
#define annotate_reachable() __annotate_reachable(__COUNTER__)
|
||||
|
||||
#define __annotate_unreachable(c) ({ \
|
||||
asm volatile(__stringify_label(c) ":\n\t" \
|
||||
".pushsection .discard.unreachable\n\t" \
|
||||
|
|
@ -133,24 +125,14 @@ void ftrace_likely_update(struct ftrace_likely_data *f, int val,
|
|||
})
|
||||
#define annotate_unreachable() __annotate_unreachable(__COUNTER__)
|
||||
|
||||
#define ASM_UNREACHABLE \
|
||||
"999:\n\t" \
|
||||
".pushsection .discard.unreachable\n\t" \
|
||||
".long 999b - .\n\t" \
|
||||
".popsection\n\t"
|
||||
|
||||
/* Annotate a C jump table to allow objtool to follow the code flow */
|
||||
#define __annotate_jump_table __section(".rodata..c_jump_table")
|
||||
|
||||
#else
|
||||
#define annotate_reachable()
|
||||
#else /* !CONFIG_OBJTOOL */
|
||||
#define annotate_unreachable()
|
||||
#define __annotate_jump_table
|
||||
#endif
|
||||
#endif /* CONFIG_OBJTOOL */
|
||||
|
||||
#ifndef ASM_UNREACHABLE
|
||||
# define ASM_UNREACHABLE
|
||||
#endif
|
||||
#ifndef unreachable
|
||||
# define unreachable() do { \
|
||||
annotate_unreachable(); \
|
||||
|
|
@ -221,16 +203,6 @@ void ftrace_likely_update(struct ftrace_likely_data *f, int val,
|
|||
__v; \
|
||||
})
|
||||
|
||||
/*
|
||||
* With CONFIG_CFI_CLANG, the compiler replaces function addresses in
|
||||
* instrumented C code with jump table addresses. Architectures that
|
||||
* support CFI can define this macro to return the actual function address
|
||||
* when needed.
|
||||
*/
|
||||
#ifndef function_nocfi
|
||||
#define function_nocfi(x) (x)
|
||||
#endif
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
/*
|
||||
|
|
@ -239,9 +211,11 @@ void ftrace_likely_update(struct ftrace_likely_data *f, int val,
|
|||
* otherwise, or eliminated entirely due to lack of references that are
|
||||
* visible to the compiler.
|
||||
*/
|
||||
#define __ADDRESSABLE(sym) \
|
||||
static void * __section(".discard.addressable") __used \
|
||||
#define ___ADDRESSABLE(sym, __attrs) \
|
||||
static void * __used __attrs \
|
||||
__UNIQUE_ID(__PASTE(__addressable_,sym)) = (void *)&sym;
|
||||
#define __ADDRESSABLE(sym) \
|
||||
___ADDRESSABLE(sym, __section(".discard.addressable"))
|
||||
|
||||
/**
|
||||
* offset_to_ptr - convert a relative memory offset to an absolute pointer
|
||||
|
|
@ -257,6 +231,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.
|
||||
|
|
|
|||
|
|
@ -35,7 +35,8 @@
|
|||
|
||||
/*
|
||||
* Note: do not use this directly. Instead, use __alloc_size() since it is conditionally
|
||||
* available and includes other attributes.
|
||||
* available and includes other attributes. For GCC < 9.1, __alloc_size__ gets undefined
|
||||
* in compiler-gcc.h, due to misbehaviors.
|
||||
*
|
||||
* gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-alloc_005fsize-function-attribute
|
||||
* clang: https://clang.llvm.org/docs/AttributeReference.html#alloc-size
|
||||
|
|
@ -100,6 +101,19 @@
|
|||
# define __copy(symbol)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Optional: not supported by gcc
|
||||
* Optional: only supported since clang >= 14.0
|
||||
* Optional: not supported by icc
|
||||
*
|
||||
* clang: https://clang.llvm.org/docs/AttributeReference.html#diagnose_as_builtin
|
||||
*/
|
||||
#if __has_attribute(__diagnose_as_builtin__)
|
||||
# define __diagnose_as(builtin...) __attribute__((__diagnose_as_builtin__(builtin)))
|
||||
#else
|
||||
# define __diagnose_as(builtin...)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Don't. Just don't. See commit 771c035372a0 ("deprecate the '__deprecated'
|
||||
* attribute warnings entirely and for good") for more information.
|
||||
|
|
@ -257,12 +271,38 @@
|
|||
*/
|
||||
#define __noreturn __attribute__((__noreturn__))
|
||||
|
||||
/*
|
||||
* Optional: not supported by gcc.
|
||||
* Optional: not supported by icc.
|
||||
*
|
||||
* clang: https://clang.llvm.org/docs/AttributeReference.html#overloadable
|
||||
*/
|
||||
#if __has_attribute(__overloadable__)
|
||||
# define __overloadable __attribute__((__overloadable__))
|
||||
#else
|
||||
# define __overloadable
|
||||
#endif
|
||||
|
||||
/*
|
||||
* gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Type-Attributes.html#index-packed-type-attribute
|
||||
* clang: https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html#index-packed-variable-attribute
|
||||
*/
|
||||
#define __packed __attribute__((__packed__))
|
||||
|
||||
/*
|
||||
* Note: the "type" argument should match any __builtin_object_size(p, type) usage.
|
||||
*
|
||||
* Optional: not supported by gcc.
|
||||
* Optional: not supported by icc.
|
||||
*
|
||||
* clang: https://clang.llvm.org/docs/AttributeReference.html#pass-object-size-pass-dynamic-object-size
|
||||
*/
|
||||
#if __has_attribute(__pass_object_size__)
|
||||
# define __pass_object_size(type) __attribute__((__pass_object_size__(type)))
|
||||
#else
|
||||
# define __pass_object_size(type)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-pure-function-attribute
|
||||
*/
|
||||
|
|
@ -332,4 +372,11 @@
|
|||
*/
|
||||
#define __weak __attribute__((__weak__))
|
||||
|
||||
/*
|
||||
* Used by functions that use '__builtin_return_address'. These function
|
||||
* don't want to be splited or made inline, which can make
|
||||
* the '__builtin_return_address' get unexpected address.
|
||||
*/
|
||||
#define __fix_address noinline __noclone
|
||||
|
||||
#endif /* __LINUX_COMPILER_ATTRIBUTES_H */
|
||||
|
|
|
|||
|
|
@ -4,6 +4,18 @@
|
|||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
/*
|
||||
* Skipped when running bindgen due to a libclang issue;
|
||||
* see https://github.com/rust-lang/rust-bindgen/issues/2244.
|
||||
*/
|
||||
#if defined(CONFIG_DEBUG_INFO_BTF) && defined(CONFIG_PAHOLE_HAS_BTF_TAG) && \
|
||||
__has_attribute(btf_type_tag) && !defined(__BINDGEN__)
|
||||
# define BTF_TYPE_TAG(value) __attribute__((btf_type_tag(#value)))
|
||||
#else
|
||||
# define BTF_TYPE_TAG(value) /* nothing */
|
||||
#endif
|
||||
|
||||
/* sparse defines __CHECKER__; see Documentation/dev-tools/sparse.rst */
|
||||
#ifdef __CHECKER__
|
||||
/* address spaces */
|
||||
# define __kernel __attribute__((address_space(0)))
|
||||
|
|
@ -16,6 +28,7 @@ static inline void __chk_io_ptr(const volatile void __iomem *ptr) { }
|
|||
/* context/locking */
|
||||
# define __must_hold(x) __attribute__((context(x,1,1)))
|
||||
# define __acquires(x) __attribute__((context(x,0,1)))
|
||||
# define __cond_acquires(x) __attribute__((context(x,0,-1)))
|
||||
# define __releases(x) __attribute__((context(x,1,0)))
|
||||
# define __acquire(x) __context__(x,1)
|
||||
# define __release(x) __context__(x,-1)
|
||||
|
|
@ -32,16 +45,17 @@ static inline void __chk_io_ptr(const volatile void __iomem *ptr) { }
|
|||
# ifdef STRUCTLEAK_PLUGIN
|
||||
# define __user __attribute__((user))
|
||||
# else
|
||||
# define __user
|
||||
# define __user BTF_TYPE_TAG(user)
|
||||
# endif
|
||||
# define __iomem
|
||||
# define __percpu
|
||||
# define __percpu BTF_TYPE_TAG(percpu)
|
||||
# define __rcu
|
||||
# define __chk_user_ptr(x) (void)0
|
||||
# define __chk_io_ptr(x) (void)0
|
||||
/* context/locking */
|
||||
# define __must_hold(x)
|
||||
# define __acquires(x)
|
||||
# define __cond_acquires(x)
|
||||
# define __releases(x)
|
||||
# define __acquire(x) (void)0
|
||||
# define __release(x) (void)0
|
||||
|
|
@ -137,8 +151,6 @@ struct ftrace_likely_data {
|
|||
*/
|
||||
#define __naked __attribute__((__naked__)) notrace
|
||||
|
||||
#define __compiler_offsetof(a, b) __builtin_offsetof(a, b)
|
||||
|
||||
/*
|
||||
* Prefer gnu_inline, so that extern inline functions do not emit an
|
||||
* externally visible function. This makes extern inline behave as per gnu89
|
||||
|
|
@ -221,7 +233,8 @@ struct ftrace_likely_data {
|
|||
/* Section for code which can't be instrumented at all */
|
||||
#define noinstr \
|
||||
noinline notrace __attribute((__section__(".noinstr.text"))) \
|
||||
__no_kcsan __no_sanitize_address __no_profile __no_sanitize_coverage
|
||||
__no_kcsan __no_sanitize_address __no_profile __no_sanitize_coverage \
|
||||
__no_sanitize_memory
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
|
|
@ -236,15 +249,15 @@ struct ftrace_likely_data {
|
|||
# define __latent_entropy
|
||||
#endif
|
||||
|
||||
#ifndef __randomize_layout
|
||||
#if defined(RANDSTRUCT) && !defined(__CHECKER__)
|
||||
# define __randomize_layout __designated_init __attribute__((randomize_layout))
|
||||
# define __no_randomize_layout __attribute__((no_randomize_layout))
|
||||
/* This anon struct can add padding, so only enable it under randstruct. */
|
||||
# define randomized_struct_fields_start struct {
|
||||
# define randomized_struct_fields_end } __randomize_layout;
|
||||
#else
|
||||
# define __randomize_layout __designated_init
|
||||
#endif
|
||||
|
||||
#ifndef __no_randomize_layout
|
||||
# define __no_randomize_layout
|
||||
#endif
|
||||
|
||||
#ifndef randomized_struct_fields_start
|
||||
# define randomized_struct_fields_start
|
||||
# define randomized_struct_fields_end
|
||||
#endif
|
||||
|
|
@ -257,20 +270,18 @@ struct ftrace_likely_data {
|
|||
# define __nocfi
|
||||
#endif
|
||||
|
||||
#ifndef __cficanonical
|
||||
# define __cficanonical
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Any place that could be marked with the "alloc_size" attribute is also
|
||||
* a place to be marked with the "malloc" attribute. Do this as part of the
|
||||
* __alloc_size macro to avoid redundant attributes and to avoid missing a
|
||||
* __malloc marking.
|
||||
* a place to be marked with the "malloc" attribute, except those that may
|
||||
* be performing a _reallocation_, as that may alias the existing pointer.
|
||||
* For these, use __realloc_size().
|
||||
*/
|
||||
#ifdef __alloc_size__
|
||||
# define __alloc_size(x, ...) __alloc_size__(x, ## __VA_ARGS__) __malloc
|
||||
# define __realloc_size(x, ...) __alloc_size__(x, ## __VA_ARGS__)
|
||||
#else
|
||||
# define __alloc_size(x, ...) __malloc
|
||||
# define __realloc_size(x, ...)
|
||||
#endif
|
||||
|
||||
#ifndef asm_volatile_goto
|
||||
|
|
@ -368,4 +379,8 @@ struct ftrace_likely_data {
|
|||
#define __diag_error(compiler, version, option, comment) \
|
||||
__diag_ ## compiler(version, error, option)
|
||||
|
||||
#ifndef __diag_ignore_all
|
||||
#define __diag_ignore_all(option, comment)
|
||||
#endif
|
||||
|
||||
#endif /* __LINUX_COMPILER_TYPES_H */
|
||||
|
|
|
|||
|
|
@ -103,6 +103,7 @@ extern void wait_for_completion(struct completion *);
|
|||
extern void wait_for_completion_io(struct completion *);
|
||||
extern int wait_for_completion_interruptible(struct completion *x);
|
||||
extern int wait_for_completion_killable(struct completion *x);
|
||||
extern int wait_for_completion_state(struct completion *x, unsigned int state);
|
||||
extern unsigned long wait_for_completion_timeout(struct completion *x,
|
||||
unsigned long timeout);
|
||||
extern unsigned long wait_for_completion_io_timeout(struct completion *x,
|
||||
|
|
|
|||
|
|
@ -38,10 +38,10 @@ int component_add_typed(struct device *dev, const struct component_ops *ops,
|
|||
int subcomponent);
|
||||
void component_del(struct device *, const struct component_ops *);
|
||||
|
||||
int component_bind_all(struct device *master, void *master_data);
|
||||
void component_unbind_all(struct device *master, void *master_data);
|
||||
int component_bind_all(struct device *parent, void *data);
|
||||
void component_unbind_all(struct device *parent, void *data);
|
||||
|
||||
struct master;
|
||||
struct aggregate_device;
|
||||
|
||||
/**
|
||||
* struct component_master_ops - callback for the aggregate driver
|
||||
|
|
@ -82,6 +82,12 @@ struct component_master_ops {
|
|||
void (*unbind)(struct device *master);
|
||||
};
|
||||
|
||||
/* A set helper functions for component compare/release */
|
||||
int component_compare_of(struct device *dev, void *data);
|
||||
void component_release_of(struct device *dev, void *data);
|
||||
int component_compare_dev(struct device *dev, void *data);
|
||||
int component_compare_dev_name(struct device *dev, void *data);
|
||||
|
||||
void component_master_del(struct device *,
|
||||
const struct component_master_ops *);
|
||||
|
||||
|
|
@ -89,22 +95,22 @@ struct component_match;
|
|||
|
||||
int component_master_add_with_match(struct device *,
|
||||
const struct component_master_ops *, struct component_match *);
|
||||
void component_match_add_release(struct device *master,
|
||||
void component_match_add_release(struct device *parent,
|
||||
struct component_match **matchptr,
|
||||
void (*release)(struct device *, void *),
|
||||
int (*compare)(struct device *, void *), void *compare_data);
|
||||
void component_match_add_typed(struct device *master,
|
||||
void component_match_add_typed(struct device *parent,
|
||||
struct component_match **matchptr,
|
||||
int (*compare_typed)(struct device *, int, void *), void *compare_data);
|
||||
|
||||
/**
|
||||
* component_match_add - add a component match entry
|
||||
* @master: device with the aggregate driver
|
||||
* @parent: device with the aggregate driver
|
||||
* @matchptr: pointer to the list of component matches
|
||||
* @compare: compare function to match against all components
|
||||
* @compare_data: opaque pointer passed to the @compare function
|
||||
*
|
||||
* Adds a new component match to the list stored in @matchptr, which the @master
|
||||
* Adds a new component match to the list stored in @matchptr, which the @parent
|
||||
* aggregate driver needs to function. The list of component matches pointed to
|
||||
* by @matchptr must be initialized to NULL before adding the first match. This
|
||||
* only matches against components added with component_add().
|
||||
|
|
@ -114,11 +120,11 @@ void component_match_add_typed(struct device *master,
|
|||
*
|
||||
* See also component_match_add_release() and component_match_add_typed().
|
||||
*/
|
||||
static inline void component_match_add(struct device *master,
|
||||
static inline void component_match_add(struct device *parent,
|
||||
struct component_match **matchptr,
|
||||
int (*compare)(struct device *, void *), void *compare_data)
|
||||
{
|
||||
component_match_add_release(master, matchptr, NULL, compare,
|
||||
component_match_add_release(parent, matchptr, NULL, compare,
|
||||
compare_data);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -151,6 +151,8 @@ struct console {
|
|||
int cflag;
|
||||
uint ispeed;
|
||||
uint ospeed;
|
||||
u64 seq;
|
||||
unsigned long dropped;
|
||||
void *data;
|
||||
struct console *next;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
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