Merge remote-tracking branch 'aosp/android-5.4' into android-5.4-stable

Final merge of android-5.4 before KMI freeze

Change-Id: Icedf0ccbd2fd7c7d087da026565743771f360b46
Signed-off-by: Todd Kjos <tkjos@google.com>
This commit is contained in:
Todd Kjos 2020-04-12 12:33:57 -07:00
commit 9489b78a0f
113 changed files with 39743 additions and 37931 deletions

View file

@ -189,7 +189,8 @@ Description:
Access: Read
Valid values: "Unknown", "Good", "Overheat", "Dead",
"Over voltage", "Unspecified failure", "Cold",
"Watchdog timer expire", "Safety timer expire"
"Watchdog timer expire", "Safety timer expire",
"Over current", "Warm", "Cool", "Hot"
What: /sys/class/power_supply/<supply_name>/precharge_current
Date: June 2017

View file

@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0
VERSION = 5
PATCHLEVEL = 4
SUBLEVEL = 30
SUBLEVEL = 31
EXTRAVERSION =
NAME = Kleptomaniac Octopus
@ -880,7 +880,7 @@ LD_FLAGS_LTO_CLANG := -mllvm -import-instr-limit=5
KBUILD_LDFLAGS += $(LD_FLAGS_LTO_CLANG)
KBUILD_LDFLAGS_MODULE += $(LD_FLAGS_LTO_CLANG)
KBUILD_LDS_MODULE += $(srctree)/scripts/module-lto.lds
KBUILD_LDS_MODULE += scripts/module-lto.lds
endif
ifdef CONFIG_LTO

File diff suppressed because it is too large Load diff

View file

@ -98,6 +98,7 @@
devm_free_irq
devm_gpiochip_add_data
devm_gpiod_get
devm_gpio_free
devm_gpio_request
devm_hwspin_lock_request_specific
__devm_iio_device_register
@ -189,6 +190,7 @@
gpiod_direction_output_raw
gpiod_get_raw_value
gpiod_set_raw_value
gpiod_set_raw_value_cansleep
gpiod_to_chip
gpiod_to_irq
gpio_free
@ -199,6 +201,7 @@
handle_level_irq
i2c_del_driver
i2c_register_driver
i2c_transfer_buffer_flags
i2c_smbus_read_byte_data
i2c_smbus_write_byte_data
ida_alloc_range
@ -220,6 +223,33 @@
input_register_device
__ioremap
iounmap
iommu_alloc_resv_region
iommu_attach_device
iommu_detach_device
iommu_device_register
iommu_device_unregister
iommu_dma_get_resv_regions
iommu_domain_alloc
iommu_domain_free
iommu_domain_get_attr
iommu_domain_set_attr
iommu_fwspec_add_ids
iommu_fwspec_free
iommu_get_dma_cookie
iommu_get_domain_for_dev
iommu_group_get
iommu_group_get_for_dev
iommu_group_get_iommudata
iommu_group_put
iommu_group_ref_get
iommu_group_remove_device
iommu_group_set_iommudata
iommu_map
iommu_map_sg
iommu_present
iommu_put_dma_cookie
iommu_set_fault_handler
iommu_unmap
ip_route_output_flow
irq_find_mapping
irq_get_irq_data
@ -263,6 +293,8 @@
ktime_get_real_seconds
ktime_get_real_ts64
kzfree
__list_add_valid
__list_del_entry_valid
memcpy
memset
misc_deregister
@ -435,6 +467,7 @@
seq_putc
seq_puts
seq_read
set_normalized_timespec64
set_user_nice
sg_init_table
sg_miter_next
@ -460,6 +493,7 @@
snd_pcm_hw_constraint_minmax
snd_pcm_lib_ioctl
snd_pcm_period_elapsed
snd_soc_add_component_controls
snd_soc_dapm_disable_pin
snd_soc_dapm_enable_pin
snd_soc_dapm_ignore_suspend
@ -826,6 +860,9 @@
# required by microarray_fp.ko
cdev_alloc
# required by mmc_hsq.ko
mmc_cqe_request_done
# required by musb_hdrc.ko
device_wakeup_enable
dev_printk
@ -947,6 +984,8 @@
memcmp
mutex_is_locked
of_devfreq_cooling_register_power
of_hwspin_lock_get_id_byname
of_modalias_node
on_each_cpu
prepare_to_wait
put_unused_fd
@ -1134,6 +1173,7 @@
mmc_of_parse
mmc_regulator_set_vqmmc
mmc_remove_host
mmc_request_done
__sdhci_add_host
sdhci_cleanup_host
sdhci_enable_clk
@ -1225,6 +1265,14 @@
# required by sipc_core.ko
gen_pool_destroy
mbox_chan_received_data
mbox_chan_txdone
mbox_client_txdone
mbox_controller_register
mbox_controller_unregister
mbox_free_channel
mbox_request_channel
mbox_send_message
register_syscore_ops
# required by sipx.ko
@ -1233,6 +1281,15 @@
hrtimer_start_range_ns
hrtimer_try_to_cancel
# required by snd-soc-aw881xx.ko
i2c_smbus_write_byte
# required by snd-soc-akm4377.ko
regcache_mark_dirty
regcache_sync
snd_soc_get_volsw
snd_soc_put_volsw
# required by snd-soc-sprd-audio-dma.ko
dmam_alloc_attrs
dmam_free_coherent
@ -1302,6 +1359,16 @@
snd_ctl_boolean_mono_info
snd_pcm_hw_constraint_list
# required by snd-soc-tfa98xx.ko
crc32_le
device_create_bin_file
device_remove_bin_file
msleep_interruptible
snd_pcm_format_width
snd_pcm_hw_constraint_mask64
snd_soc_dapm_add_routes
snd_soc_dapm_new_controls
# required by sprd-cpufreq-common.ko
dev_pm_opp_remove
@ -1328,6 +1395,7 @@
dma_get_sgtable_attrs
dma_mmap_attrs
dma_set_coherent_mask
drm_add_edid_modes
drm_atomic_helper_async_commit
drm_atomic_helper_check
drm_atomic_helper_cleanup_planes
@ -1350,17 +1418,33 @@
__drm_atomic_helper_plane_destroy_state
__drm_atomic_helper_plane_duplicate_state
drm_atomic_helper_prepare_planes
drm_atomic_helper_resume
drm_atomic_helper_set_config
drm_atomic_helper_shutdown
drm_atomic_helper_suspend
drm_atomic_helper_swap_state
drm_atomic_helper_update_legacy_modeset_state
drm_atomic_helper_update_plane
drm_atomic_helper_wait_for_dependencies
drm_atomic_helper_wait_for_fences
drm_atomic_helper_wait_for_vblanks
drm_atomic_private_obj_fini
drm_atomic_private_obj_init
drm_atomic_set_crtc_for_connector
drm_atomic_set_fence_for_plane
drm_atomic_set_mode_for_crtc
drm_atomic_state_alloc
drm_atomic_state_clear
drm_atomic_state_default_clear
drm_atomic_state_default_release
__drm_atomic_state_free
drm_bridge_attach
drm_connector_attach_content_protection_property
drm_connector_attach_encoder
drm_connector_cleanup
drm_connector_init
drm_connector_unregister
drm_connector_update_edid_property
drm_crtc_cleanup
__drm_crtc_commit_free
drm_crtc_handle_vblank
@ -1370,9 +1454,21 @@
drm_crtc_vblank_on
drm_display_mode_from_videomode
drm_display_mode_to_videomode
drm_dp_aux_register
drm_dp_aux_unregister
drm_dp_calc_pbn_mode
drm_dp_channel_eq_ok
drm_dp_clock_recovery_ok
drm_dp_dpcd_read
drm_dp_dpcd_read_link_status
drm_dp_dpcd_write
drm_encoder_cleanup
drm_encoder_init
drm_format_info
drm_gem_cma_prime_get_sg_table
drm_gem_cma_prime_mmap
drm_gem_cma_prime_vmap
drm_gem_cma_prime_vunmap
drm_gem_cma_vm_ops
drm_gem_create_mmap_offset
drm_gem_fb_create
@ -1383,12 +1479,19 @@
drm_gem_object_init
drm_gem_object_put_unlocked
drm_gem_object_release
drm_gem_prime_export
drm_gem_prime_fd_to_handle
drm_gem_prime_handle_to_fd
drm_gem_prime_import
drm_gem_vm_close
drm_get_edid
drm_hdcp_check_ksvs_revoked
drm_hdcp_update_content_protection
drm_helper_hpd_irq_event
drm_helper_probe_single_connector_modes
drm_kms_helper_poll_fini
drm_kms_helper_poll_init
drm_match_cea_mode
drm_mode_config_reset
drm_mode_create
drm_mode_crtc_set_gamma_size
@ -1628,7 +1731,22 @@
free_percpu_irq
irq_create_of_mapping
panic_notifier_list
register_virtio_device
register_virtio_driver
__request_percpu_irq
unregister_virtio_device
unregister_virtio_driver
virtqueue_add_inbuf
virtqueue_add_outbuf
virtqueue_detach_unused_buf
virtqueue_get_buf
virtqueue_get_vring_size
virtqueue_kick
virtqueue_kick_prepare
virtqueue_notify
vring_del_virtqueue
vring_interrupt
vring_new_virtqueue
wait_woken
woken_wake_function
@ -1757,3 +1875,4 @@
of_usb_host_tpl_support
pci_bus_type
__usb_create_hcd
usb_hcd_platform_shutdown

View file

@ -11,9 +11,11 @@ CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_IKHEADERS=y
CONFIG_UCLAMP_TASK=y
CONFIG_CGROUPS=y
CONFIG_MEMCG=y
CONFIG_MEMCG_SWAP=y
CONFIG_BLK_CGROUP=y
CONFIG_CGROUP_SCHED=y
CONFIG_UCLAMP_TASK_GROUP=y
CONFIG_CGROUP_FREEZER=y
CONFIG_CPUSETS=y
@ -22,7 +24,6 @@ CONFIG_CGROUP_BPF=y
CONFIG_NAMESPACES=y
# CONFIG_UTS_NS is not set
# CONFIG_PID_NS is not set
CONFIG_SCHED_AUTOGROUP=y
CONFIG_BLK_DEV_INITRD=y
# CONFIG_RD_BZIP2 is not set
# CONFIG_RD_LZMA is not set
@ -61,6 +62,7 @@ CONFIG_PM_WAKELOCKS_LIMIT=0
CONFIG_ENERGY_MODEL=y
CONFIG_CPU_IDLE=y
CONFIG_ARM_CPUIDLE=y
CONFIG_ARM_PSCI_CPUIDLE=y
CONFIG_CPU_FREQ=y
CONFIG_CPU_FREQ_TIMES=y
CONFIG_CPU_FREQ_DEFAULT_GOV_SCHEDUTIL=y
@ -206,8 +208,6 @@ CONFIG_CFG80211=y
CONFIG_MAC80211=y
CONFIG_RFKILL=y
CONFIG_PCI=y
CONFIG_PCIEPORTBUS=y
# CONFIG_PCIEAER is not set
CONFIG_PCI_HOST_GENERIC=y
CONFIG_PCIE_QCOM=y
CONFIG_PCIE_KIRIN=y
@ -501,9 +501,10 @@ CONFIG_DEBUG_STACK_USAGE=y
CONFIG_DEBUG_MEMORY_INIT=y
CONFIG_SOFTLOCKUP_DETECTOR=y
# CONFIG_DETECT_HUNG_TASK is not set
CONFIG_PANIC_TIMEOUT=5
CONFIG_PANIC_ON_OOPS=y
CONFIG_PANIC_TIMEOUT=-1
CONFIG_SCHEDSTATS=y
# CONFIG_DEBUG_PREEMPT is not set
CONFIG_DEBUG_LIST=y
CONFIG_BUG_ON_DATA_CORRUPTION=y
CONFIG_CORESIGHT=y
CONFIG_CORESIGHT_STM=y

View file

@ -12,8 +12,10 @@ CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_IKHEADERS=y
CONFIG_UCLAMP_TASK=y
CONFIG_CGROUPS=y
CONFIG_MEMCG=y
CONFIG_MEMCG_SWAP=y
CONFIG_CGROUP_SCHED=y
CONFIG_UCLAMP_TASK_GROUP=y
CONFIG_CGROUP_FREEZER=y
CONFIG_CPUSETS=y
@ -22,7 +24,6 @@ CONFIG_CGROUP_BPF=y
CONFIG_NAMESPACES=y
# CONFIG_UTS_NS is not set
# CONFIG_PID_NS is not set
CONFIG_SCHED_AUTOGROUP=y
CONFIG_BLK_DEV_INITRD=y
# CONFIG_RD_BZIP2 is not set
# CONFIG_RD_LZMA is not set
@ -437,6 +438,7 @@ CONFIG_DEBUG_STACK_USAGE=y
CONFIG_DEBUG_MEMORY_INIT=y
CONFIG_SOFTLOCKUP_DETECTOR=y
# CONFIG_DETECT_HUNG_TASK is not set
CONFIG_PANIC_ON_OOPS=y
CONFIG_PANIC_TIMEOUT=5
CONFIG_SCHEDSTATS=y
CONFIG_DEBUG_LIST=y
CONFIG_BUG_ON_DATA_CORRUPTION=y

View file

@ -488,21 +488,13 @@ out:
return false;
}
/**
* blk_crypto_start_using_mode() - Start using a crypto algorithm on a device
* @mode_num: the blk_crypto_mode we want to allocate ciphers for.
* @data_unit_size: the data unit size that will be used
* @q: the request queue for the device
*
* Upper layers must call this function to ensure that a the crypto API fallback
* has transforms for this algorithm, if they become necessary.
*
* Return: 0 on success and -err on error.
/*
* Prepare blk-crypto-fallback for the specified crypto mode.
* Returns -ENOPKG if the needed crypto API support is missing.
*/
int blk_crypto_start_using_mode(enum blk_crypto_mode_num mode_num,
unsigned int data_unit_size,
struct request_queue *q)
int blk_crypto_fallback_start_using_mode(enum blk_crypto_mode_num mode_num)
{
const char *cipher_str = blk_crypto_modes[mode_num].cipher_str;
struct blk_crypto_keyslot *slotp;
unsigned int i;
int err = 0;
@ -515,25 +507,20 @@ int blk_crypto_start_using_mode(enum blk_crypto_mode_num mode_num,
if (likely(smp_load_acquire(&tfms_inited[mode_num])))
return 0;
/*
* If the keyslot manager of the request queue supports this
* crypto mode, then we don't need to allocate this mode.
*/
if (keyslot_manager_crypto_mode_supported(q->ksm, mode_num,
data_unit_size))
return 0;
mutex_lock(&tfms_init_lock);
if (likely(tfms_inited[mode_num]))
goto out;
for (i = 0; i < blk_crypto_num_keyslots; i++) {
slotp = &blk_crypto_keyslots[i];
slotp->tfms[mode_num] = crypto_alloc_skcipher(
blk_crypto_modes[mode_num].cipher_str,
0, 0);
slotp->tfms[mode_num] = crypto_alloc_skcipher(cipher_str, 0, 0);
if (IS_ERR(slotp->tfms[mode_num])) {
err = PTR_ERR(slotp->tfms[mode_num]);
if (err == -ENOENT) {
pr_warn_once("Missing crypto API support for \"%s\"\n",
cipher_str);
err = -ENOPKG;
}
slotp->tfms[mode_num] = NULL;
goto out_free_tfms;
}
@ -559,7 +546,6 @@ out:
mutex_unlock(&tfms_init_lock);
return err;
}
EXPORT_SYMBOL_GPL(blk_crypto_start_using_mode);
int blk_crypto_fallback_evict_key(const struct blk_crypto_key *key)
{
@ -615,9 +601,11 @@ int __init blk_crypto_fallback_init(void)
crypto_mode_supported[i] = 0xFFFFFFFF;
crypto_mode_supported[BLK_ENCRYPTION_MODE_INVALID] = 0;
blk_crypto_ksm = keyslot_manager_create(NULL, blk_crypto_num_keyslots,
&blk_crypto_ksm_ll_ops,
crypto_mode_supported, NULL);
blk_crypto_ksm = keyslot_manager_create(
NULL, blk_crypto_num_keyslots,
&blk_crypto_ksm_ll_ops,
BLK_CRYPTO_FEATURE_STANDARD_KEYS,
crypto_mode_supported, NULL);
if (!blk_crypto_ksm)
return -ENOMEM;

View file

@ -19,6 +19,8 @@ extern const struct blk_crypto_mode blk_crypto_modes[];
#ifdef CONFIG_BLK_INLINE_ENCRYPTION_FALLBACK
int blk_crypto_fallback_start_using_mode(enum blk_crypto_mode_num mode_num);
int blk_crypto_fallback_submit_bio(struct bio **bio_ptr);
bool blk_crypto_queue_decrypt_bio(struct bio *bio);
@ -29,6 +31,13 @@ bool bio_crypt_fallback_crypted(const struct bio_crypt_ctx *bc);
#else /* CONFIG_BLK_INLINE_ENCRYPTION_FALLBACK */
static inline int
blk_crypto_fallback_start_using_mode(enum blk_crypto_mode_num mode_num)
{
pr_warn_once("crypto API fallback is disabled\n");
return -ENOPKG;
}
static inline bool bio_crypt_fallback_crypted(const struct bio_crypt_ctx *bc)
{
return false;

View file

@ -109,7 +109,8 @@ int blk_crypto_submit_bio(struct bio **bio_ptr)
/* Get device keyslot if supported */
if (keyslot_manager_crypto_mode_supported(q->ksm,
bc->bc_key->crypto_mode,
bc->bc_key->data_unit_size)) {
bc->bc_key->data_unit_size,
bc->bc_key->is_hw_wrapped)) {
err = bio_crypt_ctx_acquire_keyslot(bc, q->ksm);
if (!err)
return 0;
@ -232,6 +233,38 @@ int blk_crypto_init_key(struct blk_crypto_key *blk_key,
}
EXPORT_SYMBOL_GPL(blk_crypto_init_key);
/**
* blk_crypto_start_using_mode() - Start using blk-crypto on a device
* @crypto_mode: the crypto mode that will be used
* @data_unit_size: the data unit size that will be used
* @is_hw_wrapped_key: whether the key will be hardware-wrapped
* @q: the request queue for the device
*
* Upper layers must call this function to ensure that either the hardware
* supports the needed crypto settings, or the crypto API fallback has
* transforms for the needed mode allocated and ready to go.
*
* Return: 0 on success; -ENOPKG if the hardware doesn't support the crypto
* settings and blk-crypto-fallback is either disabled or the needed
* algorithm is disabled in the crypto API; or another -errno code.
*/
int blk_crypto_start_using_mode(enum blk_crypto_mode_num crypto_mode,
unsigned int data_unit_size,
bool is_hw_wrapped_key,
struct request_queue *q)
{
if (keyslot_manager_crypto_mode_supported(q->ksm, crypto_mode,
data_unit_size,
is_hw_wrapped_key))
return 0;
if (is_hw_wrapped_key) {
pr_warn_once("hardware doesn't support wrapped keys\n");
return -EOPNOTSUPP;
}
return blk_crypto_fallback_start_using_mode(crypto_mode);
}
EXPORT_SYMBOL_GPL(blk_crypto_start_using_mode);
/**
* blk_crypto_evict_key() - Evict a key from any inline encryption hardware
* it may have been programmed into
@ -252,7 +285,8 @@ int blk_crypto_evict_key(struct request_queue *q,
{
if (q->ksm &&
keyslot_manager_crypto_mode_supported(q->ksm, key->crypto_mode,
key->data_unit_size))
key->data_unit_size,
key->is_hw_wrapped))
return keyslot_manager_evict_key(q->ksm, key);
return blk_crypto_fallback_evict_key(key);

View file

@ -43,6 +43,7 @@ struct keyslot {
struct keyslot_manager {
unsigned int num_slots;
struct keyslot_mgmt_ll_ops ksm_ll_ops;
unsigned int features;
unsigned int crypto_mode_supported[BLK_ENCRYPTION_MODE_MAX];
void *ll_priv_data;
@ -135,6 +136,8 @@ static inline void keyslot_manager_hw_exit(struct keyslot_manager *ksm)
* @ksm_ll_ops: The struct keyslot_mgmt_ll_ops for the device that this keyslot
* manager will use to perform operations like programming and
* evicting keys.
* @features: The supported features as a bitmask of BLK_CRYPTO_FEATURE_* flags.
* Most drivers should set BLK_CRYPTO_FEATURE_STANDARD_KEYS here.
* @crypto_mode_supported: Array of size BLK_ENCRYPTION_MODE_MAX of
* bitmasks that represents whether a crypto mode
* and data unit size are supported. The i'th bit
@ -154,6 +157,7 @@ struct keyslot_manager *keyslot_manager_create(
struct device *dev,
unsigned int num_slots,
const struct keyslot_mgmt_ll_ops *ksm_ll_ops,
unsigned int features,
const unsigned int crypto_mode_supported[BLK_ENCRYPTION_MODE_MAX],
void *ll_priv_data)
{
@ -175,6 +179,7 @@ struct keyslot_manager *keyslot_manager_create(
ksm->num_slots = num_slots;
ksm->ksm_ll_ops = *ksm_ll_ops;
ksm->features = features;
memcpy(ksm->crypto_mode_supported, crypto_mode_supported,
sizeof(ksm->crypto_mode_supported));
ksm->ll_priv_data = ll_priv_data;
@ -381,23 +386,24 @@ void keyslot_manager_put_slot(struct keyslot_manager *ksm, unsigned int slot)
}
/**
* keyslot_manager_crypto_mode_supported() - Find out if a crypto_mode/data
* unit size combination is supported
* by a ksm.
* keyslot_manager_crypto_mode_supported() - Find out if a crypto_mode /
* data unit size / is_hw_wrapped_key
* combination is supported by a ksm.
* @ksm: The keyslot manager to check
* @crypto_mode: The crypto mode to check for.
* @data_unit_size: The data_unit_size for the mode.
* @is_hw_wrapped_key: Whether a hardware-wrapped key will be used.
*
* Calls and returns the result of the crypto_mode_supported function specified
* by the ksm.
*
* Context: Process context.
* Return: Whether or not this ksm supports the specified crypto_mode/
* data_unit_size combo.
* Return: Whether or not this ksm supports the specified crypto settings.
*/
bool keyslot_manager_crypto_mode_supported(struct keyslot_manager *ksm,
enum blk_crypto_mode_num crypto_mode,
unsigned int data_unit_size)
unsigned int data_unit_size,
bool is_hw_wrapped_key)
{
if (!ksm)
return false;
@ -405,6 +411,13 @@ bool keyslot_manager_crypto_mode_supported(struct keyslot_manager *ksm,
return false;
if (WARN_ON(!is_power_of_2(data_unit_size)))
return false;
if (is_hw_wrapped_key) {
if (!(ksm->features & BLK_CRYPTO_FEATURE_WRAPPED_KEYS))
return false;
} else {
if (!(ksm->features & BLK_CRYPTO_FEATURE_STANDARD_KEYS))
return false;
}
return ksm->crypto_mode_supported[crypto_mode] & data_unit_size;
}
@ -520,6 +533,7 @@ EXPORT_SYMBOL_GPL(keyslot_manager_destroy);
* keyslot_manager_create_passthrough() - Create a passthrough keyslot manager
* @dev: Device for runtime power management (NULL if none)
* @ksm_ll_ops: The struct keyslot_mgmt_ll_ops
* @features: Bitmask of BLK_CRYPTO_FEATURE_* flags
* @crypto_mode_supported: Bitmasks for supported encryption modes
* @ll_priv_data: Private data passed as is to the functions in ksm_ll_ops.
*
@ -537,6 +551,7 @@ EXPORT_SYMBOL_GPL(keyslot_manager_destroy);
struct keyslot_manager *keyslot_manager_create_passthrough(
struct device *dev,
const struct keyslot_mgmt_ll_ops *ksm_ll_ops,
unsigned int features,
const unsigned int crypto_mode_supported[BLK_ENCRYPTION_MODE_MAX],
void *ll_priv_data)
{
@ -547,6 +562,7 @@ struct keyslot_manager *keyslot_manager_create_passthrough(
return NULL;
ksm->ksm_ll_ops = *ksm_ll_ops;
ksm->features = features;
memcpy(ksm->crypto_mode_supported, crypto_mode_supported,
sizeof(ksm->crypto_mode_supported));
ksm->ll_priv_data = ll_priv_data;
@ -575,11 +591,13 @@ void keyslot_manager_intersect_modes(struct keyslot_manager *parent,
if (child) {
unsigned int i;
parent->features &= child->features;
for (i = 0; i < ARRAY_SIZE(child->crypto_mode_supported); i++) {
parent->crypto_mode_supported[i] &=
child->crypto_mode_supported[i];
}
} else {
parent->features = 0;
memset(parent->crypto_mode_supported, 0,
sizeof(parent->crypto_mode_supported));
}

View file

@ -1342,6 +1342,8 @@ Run:
error = dpm_run_callback(callback, dev, state, info);
if (error) {
async_error = error;
log_suspend_abort_reason("Callback failed on %s in %pS returned %d",
dev_name(dev), callback, error);
goto Complete;
}
@ -1549,6 +1551,8 @@ Run:
error = dpm_run_callback(callback, dev, state, info);
if (error) {
async_error = error;
log_suspend_abort_reason("Callback failed on %s in %pS returned %d",
dev_name(dev), callback, error);
goto Complete;
}
dpm_propagate_wakeup_to_parent(dev);
@ -1716,7 +1720,6 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async)
pm_callback_t callback = NULL;
const char *info = NULL;
int error = 0;
char suspend_abort[MAX_SUSPEND_ABORT_LEN];
DECLARE_DPM_WATCHDOG_ON_STACK(wd);
TRACE_DEVICE(dev);
@ -1740,9 +1743,6 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async)
if (pm_wakeup_pending()) {
dev->power.direct_complete = false;
pm_get_active_wakeup_sources(suspend_abort,
MAX_SUSPEND_ABORT_LEN);
log_suspend_abort_reason(suspend_abort);
async_error = -EBUSY;
goto Complete;
}
@ -1819,6 +1819,9 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async)
dpm_propagate_wakeup_to_parent(dev);
dpm_clear_superiors_direct_complete(dev);
} else {
log_suspend_abort_reason("Callback failed on %s in %pS returned %d",
dev_name(dev), callback, error);
}
device_unlock(dev);
@ -2028,6 +2031,8 @@ int dpm_prepare(pm_message_t state)
}
pr_info("Device %s not prepared for power transition: code %d\n",
dev_name(dev), error);
log_suspend_abort_reason("Device %s not prepared for power transition: code %d",
dev_name(dev), error);
dpm_save_failed_dev(dev_name(dev));
put_device(dev);
break;

View file

@ -15,7 +15,9 @@
#include <linux/seq_file.h>
#include <linux/debugfs.h>
#include <linux/pm_wakeirq.h>
#include <linux/types.h>
#include <linux/irq.h>
#include <linux/irqdesc.h>
#include <linux/wakeup_reason.h>
#include <trace/events/power.h>
#include "power.h"
@ -883,6 +885,7 @@ bool pm_wakeup_pending(void)
{
unsigned long flags;
bool ret = false;
char suspend_abort[MAX_SUSPEND_ABORT_LEN];
raw_spin_lock_irqsave(&events_lock, flags);
if (events_check_enabled) {
@ -897,6 +900,10 @@ bool pm_wakeup_pending(void)
if (ret) {
pm_pr_dbg("Wakeup pending, aborting suspend\n");
pm_print_active_wakeup_sources();
pm_get_active_wakeup_sources(suspend_abort,
MAX_SUSPEND_ABORT_LEN);
log_suspend_abort_reason(suspend_abort);
pr_info("PM: %s\n", suspend_abort);
}
return ret || atomic_read(&pm_abort_suspend) > 0;
@ -924,6 +931,18 @@ void pm_wakeup_clear(bool reset)
void pm_system_irq_wakeup(unsigned int irq_number)
{
if (pm_wakeup_irq == 0) {
struct irq_desc *desc;
const char *name = "null";
desc = irq_to_desc(irq_number);
if (desc == NULL)
name = "stray irq";
else if (desc->action && desc->action->name)
name = desc->action->name;
log_irq_wakeup_reason(irq_number);
pr_warn("%s: %d triggered %s\n", __func__, irq_number, name);
pm_wakeup_irq = irq_number;
pm_system_wakeup();
}

View file

@ -214,7 +214,8 @@ static void __loop_update_dio(struct loop_device *lo, bool dio)
* LO_FLAGS_READ_ONLY, both are set from kernel, and losetup
* will get updated by ioctl(LOOP_GET_STATUS)
*/
blk_mq_freeze_queue(lo->lo_queue);
if (lo->lo_state == Lo_bound)
blk_mq_freeze_queue(lo->lo_queue);
lo->use_dio = use_dio;
if (use_dio) {
blk_queue_flag_clear(QUEUE_FLAG_NOMERGES, lo->lo_queue);
@ -223,7 +224,8 @@ static void __loop_update_dio(struct loop_device *lo, bool dio)
blk_queue_flag_set(QUEUE_FLAG_NOMERGES, lo->lo_queue);
lo->lo_flags &= ~LO_FLAGS_DIRECT_IO;
}
blk_mq_unfreeze_queue(lo->lo_queue);
if (lo->lo_state == Lo_bound)
blk_mq_unfreeze_queue(lo->lo_queue);
}
static int
@ -1536,16 +1538,16 @@ static int loop_set_block_size(struct loop_device *lo, unsigned long arg)
if (arg < 512 || arg > PAGE_SIZE || !is_power_of_2(arg))
return -EINVAL;
if (lo->lo_queue->limits.logical_block_size != arg) {
sync_blockdev(lo->lo_device);
kill_bdev(lo->lo_device);
}
if (lo->lo_queue->limits.logical_block_size == arg)
return 0;
sync_blockdev(lo->lo_device);
kill_bdev(lo->lo_device);
blk_mq_freeze_queue(lo->lo_queue);
/* kill_bdev should have truncated all the pages */
if (lo->lo_queue->limits.logical_block_size != arg &&
lo->lo_device->bd_inode->i_mapping->nrpages) {
if (lo->lo_device->bd_inode->i_mapping->nrpages) {
err = -EAGAIN;
pr_warn("%s: loop%d (%s) has still dirty pages (nrpages=%lu)\n",
__func__, lo->lo_number, lo->lo_file_name,

View file

@ -106,6 +106,8 @@ bool have_governor_per_policy(void)
}
EXPORT_SYMBOL_GPL(have_governor_per_policy);
static struct kobject *cpufreq_global_kobject;
struct kobject *get_governor_parent_kobj(struct cpufreq_policy *policy)
{
if (have_governor_per_policy())
@ -2764,9 +2766,6 @@ int cpufreq_unregister_driver(struct cpufreq_driver *driver)
}
EXPORT_SYMBOL_GPL(cpufreq_unregister_driver);
struct kobject *cpufreq_global_kobject;
EXPORT_SYMBOL(cpufreq_global_kobject);
static int __init cpufreq_core_init(void)
{
if (cpufreq_disabled())

View file

@ -486,6 +486,28 @@ static int sprd_dma_set_2stage_config(struct sprd_dma_chn *schan)
return 0;
}
static void sprd_dma_set_pending(struct sprd_dma_chn *schan, bool enable)
{
struct sprd_dma_dev *sdev = to_sprd_dma_dev(&schan->vc.chan);
u32 reg, val, req_id;
if (schan->dev_id == SPRD_DMA_SOFTWARE_UID)
return;
/* The DMA request id always starts from 0. */
req_id = schan->dev_id - 1;
if (req_id < 32) {
reg = SPRD_DMA_GLB_REQ_PEND0_EN;
val = BIT(req_id);
} else {
reg = SPRD_DMA_GLB_REQ_PEND1_EN;
val = BIT(req_id - 32);
}
sprd_dma_glb_update(sdev, reg, val, enable ? val : 0);
}
static void sprd_dma_set_chn_config(struct sprd_dma_chn *schan,
struct sprd_dma_desc *sdesc)
{
@ -532,6 +554,7 @@ static void sprd_dma_start(struct sprd_dma_chn *schan)
*/
sprd_dma_set_chn_config(schan, schan->cur_desc);
sprd_dma_set_uid(schan);
sprd_dma_set_pending(schan, true);
sprd_dma_enable_chn(schan);
if (schan->dev_id == SPRD_DMA_SOFTWARE_UID &&
@ -543,6 +566,7 @@ static void sprd_dma_start(struct sprd_dma_chn *schan)
static void sprd_dma_stop(struct sprd_dma_chn *schan)
{
sprd_dma_stop_and_disable(schan);
sprd_dma_set_pending(schan, false);
sprd_dma_unset_uid(schan);
sprd_dma_clear_int(schan);
schan->cur_desc = NULL;

View file

@ -423,9 +423,40 @@ static int axp288_extcon_probe(struct platform_device *pdev)
/* Start charger cable type detection */
axp288_extcon_enable(info);
device_init_wakeup(dev, true);
platform_set_drvdata(pdev, info);
return 0;
}
static int __maybe_unused axp288_extcon_suspend(struct device *dev)
{
struct axp288_extcon_info *info = dev_get_drvdata(dev);
if (device_may_wakeup(dev))
enable_irq_wake(info->irq[VBUS_RISING_IRQ]);
return 0;
}
static int __maybe_unused axp288_extcon_resume(struct device *dev)
{
struct axp288_extcon_info *info = dev_get_drvdata(dev);
/*
* Wakeup when a charger is connected to do charger-type
* connection and generate an extcon event which makes the
* axp288 charger driver set the input current limit.
*/
if (device_may_wakeup(dev))
disable_irq_wake(info->irq[VBUS_RISING_IRQ]);
return 0;
}
static SIMPLE_DEV_PM_OPS(axp288_extcon_pm_ops, axp288_extcon_suspend,
axp288_extcon_resume);
static const struct platform_device_id axp288_extcon_table[] = {
{ .name = "axp288_extcon" },
{},
@ -437,6 +468,7 @@ static struct platform_driver axp288_extcon_driver = {
.id_table = axp288_extcon_table,
.driver = {
.name = "axp288_extcon",
.pm = &axp288_extcon_pm_ops,
},
};

View file

@ -569,6 +569,7 @@ static int sprd_eic_probe(struct platform_device *pdev)
const struct sprd_eic_variant_data *pdata;
struct gpio_irq_chip *irq;
struct sprd_eic *sprd_eic;
struct resource *res;
int ret, i;
pdata = of_device_get_match_data(&pdev->dev);
@ -595,9 +596,13 @@ static int sprd_eic_probe(struct platform_device *pdev)
* have one bank EIC, thus base[1] and base[2] can be
* optional.
*/
sprd_eic->base[i] = devm_platform_ioremap_resource(pdev, i);
if (IS_ERR(sprd_eic->base[i]))
res = platform_get_resource(pdev, IORESOURCE_MEM, i);
if (!res)
continue;
sprd_eic->base[i] = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(sprd_eic->base[i]))
return PTR_ERR(sprd_eic->base[i]);
}
sprd_eic->chip.label = sprd_eic_label_name[sprd_eic->type];

View file

@ -1375,7 +1375,7 @@ static int vcn_v1_0_set_clockgating_state(void *handle,
if (enable) {
/* wait for STATUS to clear */
if (vcn_v1_0_is_idle(handle))
if (!vcn_v1_0_is_idle(handle))
return -EBUSY;
vcn_v1_0_enable_clock_gating(adev);
} else {

View file

@ -2879,6 +2879,17 @@ static bool retrieve_link_cap(struct dc_link *link)
sink_id.ieee_device_id,
sizeof(sink_id.ieee_device_id));
/* Quirk Apple MBP 2017 15" Retina panel: Wrong DP_MAX_LINK_RATE */
{
uint8_t str_mbp_2017[] = { 101, 68, 21, 101, 98, 97 };
if ((link->dpcd_caps.sink_dev_id == 0x0010fa) &&
!memcmp(link->dpcd_caps.sink_dev_id_str, str_mbp_2017,
sizeof(str_mbp_2017))) {
link->reported_link_cap.link_rate = 0x0c;
}
}
core_link_read_dpcd(
link,
DP_SINK_HW_REVISION_START,

View file

@ -156,10 +156,8 @@ int bochs_hw_init(struct drm_device *dev)
size = min(size, mem);
}
if (pci_request_region(pdev, 0, "bochs-drm") != 0) {
DRM_ERROR("Cannot request framebuffer\n");
return -EBUSY;
}
if (pci_request_region(pdev, 0, "bochs-drm") != 0)
DRM_WARN("Cannot request framebuffer, boot fb still active?\n");
bochs->fb_map = ioremap(addr, size);
if (bochs->fb_map == NULL) {

View file

@ -129,11 +129,6 @@
#define TCOBASE 0x050
#define TCOCTL 0x054
#define ACPIBASE 0x040
#define ACPIBASE_SMI_OFF 0x030
#define ACPICTRL 0x044
#define ACPICTRL_EN 0x080
#define SBREG_BAR 0x10
#define SBREG_SMBCTRL 0xc6000c
#define SBREG_SMBCTRL_DNV 0xcf000c
@ -1544,7 +1539,7 @@ i801_add_tco_spt(struct i801_priv *priv, struct pci_dev *pci_dev,
pci_bus_write_config_byte(pci_dev->bus, devfn, 0xe1, hidden);
spin_unlock(&p2sb_spinlock);
res = &tco_res[ICH_RES_MEM_OFF];
res = &tco_res[1];
if (pci_dev->device == PCI_DEVICE_ID_INTEL_DNV_SMBUS)
res->start = (resource_size_t)base64_addr + SBREG_SMBCTRL_DNV;
else
@ -1554,7 +1549,7 @@ i801_add_tco_spt(struct i801_priv *priv, struct pci_dev *pci_dev,
res->flags = IORESOURCE_MEM;
return platform_device_register_resndata(&pci_dev->dev, "iTCO_wdt", -1,
tco_res, 3, &spt_tco_platform_data,
tco_res, 2, &spt_tco_platform_data,
sizeof(spt_tco_platform_data));
}
@ -1567,17 +1562,16 @@ static struct platform_device *
i801_add_tco_cnl(struct i801_priv *priv, struct pci_dev *pci_dev,
struct resource *tco_res)
{
return platform_device_register_resndata(&pci_dev->dev, "iTCO_wdt", -1,
tco_res, 2, &cnl_tco_platform_data,
sizeof(cnl_tco_platform_data));
return platform_device_register_resndata(&pci_dev->dev,
"iTCO_wdt", -1, tco_res, 1, &cnl_tco_platform_data,
sizeof(cnl_tco_platform_data));
}
static void i801_add_tco(struct i801_priv *priv)
{
u32 base_addr, tco_base, tco_ctl, ctrl_val;
struct pci_dev *pci_dev = priv->pci_dev;
struct resource tco_res[3], *res;
unsigned int devfn;
struct resource tco_res[2], *res;
u32 tco_base, tco_ctl;
/* If we have ACPI based watchdog use that instead */
if (acpi_has_watchdog())
@ -1592,30 +1586,15 @@ static void i801_add_tco(struct i801_priv *priv)
return;
memset(tco_res, 0, sizeof(tco_res));
res = &tco_res[ICH_RES_IO_TCO];
/*
* Always populate the main iTCO IO resource here. The second entry
* for NO_REBOOT MMIO is filled by the SPT specific function.
*/
res = &tco_res[0];
res->start = tco_base & ~1;
res->end = res->start + 32 - 1;
res->flags = IORESOURCE_IO;
/*
* Power Management registers.
*/
devfn = PCI_DEVFN(PCI_SLOT(pci_dev->devfn), 2);
pci_bus_read_config_dword(pci_dev->bus, devfn, ACPIBASE, &base_addr);
res = &tco_res[ICH_RES_IO_SMI];
res->start = (base_addr & ~1) + ACPIBASE_SMI_OFF;
res->end = res->start + 3;
res->flags = IORESOURCE_IO;
/*
* Enable the ACPI I/O space.
*/
pci_bus_read_config_dword(pci_dev->bus, devfn, ACPICTRL, &ctrl_val);
ctrl_val |= ACPICTRL_EN;
pci_bus_write_config_dword(pci_dev->bus, devfn, ACPICTRL, ctrl_val);
if (priv->features & FEATURE_TCO_CNL)
priv->tco_pdev = i801_add_tco_cnl(priv, pci_dev, tco_res);
else

View file

@ -141,6 +141,7 @@ static int defer_packet_queue(
*/
xchg(&pq->state, SDMA_PKT_Q_DEFERRED);
if (list_empty(&pq->busy.list)) {
pq->busy.lock = &sde->waitlock;
iowait_get_priority(&pq->busy);
iowait_queue(pkts_sent, &pq->busy, &sde->dmawait);
}
@ -155,6 +156,7 @@ static void activate_packet_queue(struct iowait *wait, int reason)
{
struct hfi1_user_sdma_pkt_q *pq =
container_of(wait, struct hfi1_user_sdma_pkt_q, busy);
pq->busy.lock = NULL;
xchg(&pq->state, SDMA_PKT_Q_ACTIVE);
wake_up(&wait->wait_dma);
};
@ -256,6 +258,21 @@ pq_reqs_nomem:
return ret;
}
static void flush_pq_iowait(struct hfi1_user_sdma_pkt_q *pq)
{
unsigned long flags;
seqlock_t *lock = pq->busy.lock;
if (!lock)
return;
write_seqlock_irqsave(lock, flags);
if (!list_empty(&pq->busy.list)) {
list_del_init(&pq->busy.list);
pq->busy.lock = NULL;
}
write_sequnlock_irqrestore(lock, flags);
}
int hfi1_user_sdma_free_queues(struct hfi1_filedata *fd,
struct hfi1_ctxtdata *uctxt)
{
@ -281,6 +298,7 @@ int hfi1_user_sdma_free_queues(struct hfi1_filedata *fd,
kfree(pq->reqs);
kfree(pq->req_in_use);
kmem_cache_destroy(pq->txreq_cache);
flush_pq_iowait(pq);
kfree(pq);
} else {
spin_unlock(&fd->pq_rcu_lock);
@ -587,11 +605,12 @@ int hfi1_user_sdma_process_request(struct hfi1_filedata *fd,
if (ret < 0) {
if (ret != -EBUSY)
goto free_req;
wait_event_interruptible_timeout(
if (wait_event_interruptible_timeout(
pq->busy.wait_dma,
(pq->state == SDMA_PKT_Q_ACTIVE),
pq->state == SDMA_PKT_Q_ACTIVE,
msecs_to_jiffies(
SDMA_IOWAIT_TIMEOUT));
SDMA_IOWAIT_TIMEOUT)) <= 0)
flush_pq_iowait(pq);
}
}
*count += idx;

View file

@ -18,6 +18,8 @@
#include <linux/percpu.h>
#include <linux/refcount.h>
#include <linux/slab.h>
#include <linux/wakeup_reason.h>
#include <linux/irqchip.h>
#include <linux/irqchip/arm-gic-common.h>
@ -648,6 +650,9 @@ static asmlinkage void __exception_irq_entry gic_handle_irq(struct pt_regs *regs
err = handle_domain_irq(gic_data.domain, irqnr, regs);
if (err) {
WARN_ONCE(true, "Unexpected interrupt received!\n");
log_abnormal_wakeup_reason(
"unexpected HW IRQ %u", irqnr);
gic_deactivate_unhandled(irqnr);
}
return;

View file

@ -239,6 +239,7 @@ static int default_key_ctr(struct dm_target *ti, unsigned int argc, char **argv)
}
err = blk_crypto_start_using_mode(cipher->mode_num, dkc->sector_size,
dkc->is_hw_wrapped,
dkc->dev->bdev->bd_queue);
if (err) {
ti->error = "Error starting to use blk-crypto";

View file

@ -1741,8 +1741,9 @@ static blk_qc_t dm_process_bio(struct mapped_device *md,
* won't be imposed.
*/
if (current->bio_list) {
blk_queue_split(md->queue, &bio);
if (!is_abnormal_io(bio))
if (is_abnormal_io(bio))
blk_queue_split(md->queue, &bio);
else
dm_queue_split(md, ti, &bio);
}
@ -2370,16 +2371,21 @@ static struct keyslot_mgmt_ll_ops dm_ksm_ll_ops = {
static int dm_init_inline_encryption(struct mapped_device *md)
{
unsigned int features;
unsigned int mode_masks[BLK_ENCRYPTION_MODE_MAX];
/*
* Start out with all crypto mode support bits set. Any unsupported
* bits will be cleared later when calculating the device restrictions.
* Initially declare support for all crypto settings. Anything
* unsupported by a child device will be removed later when calculating
* the device restrictions.
*/
features = BLK_CRYPTO_FEATURE_STANDARD_KEYS |
BLK_CRYPTO_FEATURE_WRAPPED_KEYS;
memset(mode_masks, 0xFF, sizeof(mode_masks));
md->queue->ksm = keyslot_manager_create_passthrough(NULL,
&dm_ksm_ll_ops,
features,
mode_masks, md);
if (!md->queue->ksm)
return -ENOMEM;

View file

@ -10,6 +10,7 @@
#include <linux/of_device.h>
#include <linux/regmap.h>
#include <linux/spi/spi.h>
#include <uapi/linux/usb/charger.h>
#define SPRD_PMIC_INT_MASK_STATUS 0x0
#define SPRD_PMIC_INT_RAW_STATUS 0x4
@ -17,6 +18,16 @@
#define SPRD_SC2731_IRQ_BASE 0x140
#define SPRD_SC2731_IRQ_NUMS 16
#define SPRD_SC2731_CHG_DET 0xedc
/* PMIC charger detection definition */
#define SPRD_PMIC_CHG_DET_DELAY_US 200000
#define SPRD_PMIC_CHG_DET_TIMEOUT 2000000
#define SPRD_PMIC_CHG_DET_DONE BIT(11)
#define SPRD_PMIC_SDP_TYPE BIT(7)
#define SPRD_PMIC_DCP_TYPE BIT(6)
#define SPRD_PMIC_CDP_TYPE BIT(5)
#define SPRD_PMIC_CHG_TYPE_MASK GENMASK(7, 5)
struct sprd_pmic {
struct regmap *regmap;
@ -24,12 +35,14 @@ struct sprd_pmic {
struct regmap_irq *irqs;
struct regmap_irq_chip irq_chip;
struct regmap_irq_chip_data *irq_data;
const struct sprd_pmic_data *pdata;
int irq;
};
struct sprd_pmic_data {
u32 irq_base;
u32 num_irqs;
u32 charger_det;
};
/*
@ -40,8 +53,46 @@ struct sprd_pmic_data {
static const struct sprd_pmic_data sc2731_data = {
.irq_base = SPRD_SC2731_IRQ_BASE,
.num_irqs = SPRD_SC2731_IRQ_NUMS,
.charger_det = SPRD_SC2731_CHG_DET,
};
enum usb_charger_type sprd_pmic_detect_charger_type(struct device *dev)
{
struct spi_device *spi = to_spi_device(dev);
struct sprd_pmic *ddata = spi_get_drvdata(spi);
const struct sprd_pmic_data *pdata = ddata->pdata;
enum usb_charger_type type;
u32 val;
int ret;
ret = regmap_read_poll_timeout(ddata->regmap, pdata->charger_det, val,
(val & SPRD_PMIC_CHG_DET_DONE),
SPRD_PMIC_CHG_DET_DELAY_US,
SPRD_PMIC_CHG_DET_TIMEOUT);
if (ret) {
dev_err(&spi->dev, "failed to detect charger type\n");
return UNKNOWN_TYPE;
}
switch (val & SPRD_PMIC_CHG_TYPE_MASK) {
case SPRD_PMIC_CDP_TYPE:
type = CDP_TYPE;
break;
case SPRD_PMIC_DCP_TYPE:
type = DCP_TYPE;
break;
case SPRD_PMIC_SDP_TYPE:
type = SDP_TYPE;
break;
default:
type = UNKNOWN_TYPE;
break;
}
return type;
}
EXPORT_SYMBOL_GPL(sprd_pmic_detect_charger_type);
static const struct mfd_cell sprd_pmic_devs[] = {
{
.name = "sc27xx-wdt",
@ -181,6 +232,7 @@ static int sprd_pmic_probe(struct spi_device *spi)
spi_set_drvdata(spi, ddata);
ddata->dev = &spi->dev;
ddata->irq = spi->irq;
ddata->pdata = pdata;
ddata->irq_chip.name = dev_name(&spi->dev);
ddata->irq_chip.status_base =

View file

@ -394,6 +394,7 @@ static const struct pcr_ops rts522a_pcr_ops = {
void rts522a_init_params(struct rtsx_pcr *pcr)
{
rts5227_init_params(pcr);
pcr->ops = &rts522a_pcr_ops;
pcr->tx_initial_phase = SET_CLOCK_PHASE(20, 20, 11);
pcr->reg_pm_ctrl3 = RTS522A_PM_CTRL3;

View file

@ -87,6 +87,8 @@
#define MEI_DEV_ID_CMP_H 0x06e0 /* Comet Lake H */
#define MEI_DEV_ID_CMP_H_3 0x06e4 /* Comet Lake H 3 (iTouch) */
#define MEI_DEV_ID_CDF 0x18D3 /* Cedar Fork */
#define MEI_DEV_ID_ICP_LP 0x34E0 /* Ice Lake Point LP */
#define MEI_DEV_ID_TGP_LP 0xA0E0 /* Tiger Lake Point LP */

View file

@ -109,6 +109,8 @@ static const struct pci_device_id mei_me_pci_tbl[] = {
{MEI_PCI_DEVICE(MEI_DEV_ID_MCC, MEI_ME_PCH12_CFG)},
{MEI_PCI_DEVICE(MEI_DEV_ID_MCC_4, MEI_ME_PCH8_CFG)},
{MEI_PCI_DEVICE(MEI_DEV_ID_CDF, MEI_ME_PCH8_CFG)},
/* required last entry */
{0, }
};

View file

@ -98,6 +98,7 @@ struct pci_endpoint_test {
struct completion irq_raised;
int last_irq;
int num_irqs;
int irq_type;
/* mutex to protect the ioctls */
struct mutex mutex;
struct miscdevice miscdev;
@ -157,6 +158,7 @@ static void pci_endpoint_test_free_irq_vectors(struct pci_endpoint_test *test)
struct pci_dev *pdev = test->pdev;
pci_free_irq_vectors(pdev);
test->irq_type = IRQ_TYPE_UNDEFINED;
}
static bool pci_endpoint_test_alloc_irq_vectors(struct pci_endpoint_test *test,
@ -191,6 +193,8 @@ static bool pci_endpoint_test_alloc_irq_vectors(struct pci_endpoint_test *test,
irq = 0;
res = false;
}
test->irq_type = type;
test->num_irqs = irq;
return res;
@ -330,6 +334,7 @@ static bool pci_endpoint_test_copy(struct pci_endpoint_test *test, size_t size)
dma_addr_t orig_dst_phys_addr;
size_t offset;
size_t alignment = test->alignment;
int irq_type = test->irq_type;
u32 src_crc32;
u32 dst_crc32;
@ -426,6 +431,7 @@ static bool pci_endpoint_test_write(struct pci_endpoint_test *test, size_t size)
dma_addr_t orig_phys_addr;
size_t offset;
size_t alignment = test->alignment;
int irq_type = test->irq_type;
u32 crc32;
if (size > SIZE_MAX - alignment)
@ -494,6 +500,7 @@ static bool pci_endpoint_test_read(struct pci_endpoint_test *test, size_t size)
dma_addr_t orig_phys_addr;
size_t offset;
size_t alignment = test->alignment;
int irq_type = test->irq_type;
u32 crc32;
if (size > SIZE_MAX - alignment)
@ -555,7 +562,7 @@ static bool pci_endpoint_test_set_irq(struct pci_endpoint_test *test,
return false;
}
if (irq_type == req_irq_type)
if (test->irq_type == req_irq_type)
return true;
pci_endpoint_test_release_irq(test);
@ -567,12 +574,10 @@ static bool pci_endpoint_test_set_irq(struct pci_endpoint_test *test,
if (!pci_endpoint_test_request_irq(test))
goto err;
irq_type = req_irq_type;
return true;
err:
pci_endpoint_test_free_irq_vectors(test);
irq_type = IRQ_TYPE_UNDEFINED;
return false;
}
@ -633,7 +638,7 @@ static int pci_endpoint_test_probe(struct pci_dev *pdev,
{
int err;
int id;
char name[20];
char name[24];
enum pci_barno bar;
void __iomem *base;
struct device *dev = &pdev->dev;
@ -652,6 +657,7 @@ static int pci_endpoint_test_probe(struct pci_dev *pdev,
test->test_reg_bar = 0;
test->alignment = 0;
test->pdev = pdev;
test->irq_type = IRQ_TYPE_UNDEFINED;
if (no_msi)
irq_type = IRQ_TYPE_LEGACY;

View file

@ -168,6 +168,11 @@ MODULE_PARM_DESC(perdev_minors, "Minors numbers to allocate per device");
static inline int mmc_blk_part_switch(struct mmc_card *card,
unsigned int part_type);
static void mmc_blk_rw_rq_prep(struct mmc_queue_req *mqrq,
struct mmc_card *card,
int disable_multi,
struct mmc_queue *mq);
static void mmc_blk_hsq_req_done(struct mmc_request *mrq);
static struct mmc_blk_data *mmc_blk_get(struct gendisk *disk)
{
@ -1532,9 +1537,30 @@ static int mmc_blk_cqe_issue_flush(struct mmc_queue *mq, struct request *req)
return mmc_blk_cqe_start_req(mq->card->host, mrq);
}
static int mmc_blk_hsq_issue_rw_rq(struct mmc_queue *mq, struct request *req)
{
struct mmc_queue_req *mqrq = req_to_mmc_queue_req(req);
struct mmc_host *host = mq->card->host;
int err;
mmc_blk_rw_rq_prep(mqrq, mq->card, 0, mq);
mqrq->brq.mrq.done = mmc_blk_hsq_req_done;
mmc_pre_req(host, &mqrq->brq.mrq);
err = mmc_cqe_start_req(host, &mqrq->brq.mrq);
if (err)
mmc_post_req(host, &mqrq->brq.mrq, err);
return err;
}
static int mmc_blk_cqe_issue_rw_rq(struct mmc_queue *mq, struct request *req)
{
struct mmc_queue_req *mqrq = req_to_mmc_queue_req(req);
struct mmc_host *host = mq->card->host;
if (host->hsq_enabled)
return mmc_blk_hsq_issue_rw_rq(mq, req);
mmc_blk_data_prep(mq, mqrq, 0, NULL, NULL);
@ -1920,6 +1946,41 @@ static void mmc_blk_urgent_bkops(struct mmc_queue *mq,
mmc_run_bkops(mq->card);
}
static void mmc_blk_hsq_req_done(struct mmc_request *mrq)
{
struct mmc_queue_req *mqrq =
container_of(mrq, struct mmc_queue_req, brq.mrq);
struct request *req = mmc_queue_req_to_req(mqrq);
struct request_queue *q = req->q;
struct mmc_queue *mq = q->queuedata;
struct mmc_host *host = mq->card->host;
unsigned long flags;
if (mmc_blk_rq_error(&mqrq->brq) ||
mmc_blk_urgent_bkops_needed(mq, mqrq)) {
spin_lock_irqsave(&mq->lock, flags);
mq->recovery_needed = true;
mq->recovery_req = req;
spin_unlock_irqrestore(&mq->lock, flags);
host->cqe_ops->cqe_recovery_start(host);
schedule_work(&mq->recovery_work);
return;
}
mmc_blk_rw_reset_success(mq, req);
/*
* Block layer timeouts race with completions which means the normal
* completion path cannot be used during recovery.
*/
if (mq->in_recovery)
mmc_blk_cqe_complete_rq(mq, req);
else
blk_mq_complete_request(req);
}
void mmc_blk_mq_complete(struct request *req)
{
struct mmc_queue *mq = req->q->queuedata;

View file

@ -1852,15 +1852,19 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
*/
card->reenable_cmdq = card->ext_csd.cmdq_en;
if (card->ext_csd.cmdq_en && !host->cqe_enabled) {
if (host->cqe_ops && !host->cqe_enabled) {
err = host->cqe_ops->cqe_enable(host, card);
if (err) {
pr_err("%s: Failed to enable CQE, error %d\n",
mmc_hostname(host), err);
} else {
if (!err) {
host->cqe_enabled = true;
pr_info("%s: Command Queue Engine enabled\n",
mmc_hostname(host));
if (card->ext_csd.cmdq_en) {
pr_info("%s: Command Queue Engine enabled\n",
mmc_hostname(host));
} else {
host->hsq_enabled = true;
pr_info("%s: Host Software Queue enabled\n",
mmc_hostname(host));
}
}
}

View file

@ -62,7 +62,7 @@ enum mmc_issue_type mmc_issue_type(struct mmc_queue *mq, struct request *req)
{
struct mmc_host *host = mq->card->host;
if (mq->use_cqe)
if (mq->use_cqe && !host->hsq_enabled)
return mmc_cqe_issue_type(host, req);
if (req_op(req) == REQ_OP_READ || req_op(req) == REQ_OP_WRITE)
@ -124,12 +124,14 @@ static enum blk_eh_timer_return mmc_mq_timed_out(struct request *req,
{
struct request_queue *q = req->q;
struct mmc_queue *mq = q->queuedata;
struct mmc_card *card = mq->card;
struct mmc_host *host = card->host;
unsigned long flags;
int ret;
spin_lock_irqsave(&mq->lock, flags);
if (mq->recovery_needed || !mq->use_cqe)
if (mq->recovery_needed || !mq->use_cqe || host->hsq_enabled)
ret = BLK_EH_RESET_TIMER;
else
ret = mmc_cqe_timed_out(req);
@ -144,12 +146,13 @@ static void mmc_mq_recovery_handler(struct work_struct *work)
struct mmc_queue *mq = container_of(work, struct mmc_queue,
recovery_work);
struct request_queue *q = mq->queue;
struct mmc_host *host = mq->card->host;
mmc_get_card(mq->card, &mq->ctx);
mq->in_recovery = true;
if (mq->use_cqe)
if (mq->use_cqe && !host->hsq_enabled)
mmc_blk_cqe_recovery(mq);
else
mmc_blk_mq_recovery(mq);
@ -160,6 +163,9 @@ static void mmc_mq_recovery_handler(struct work_struct *work)
mq->recovery_needed = false;
spin_unlock_irq(&mq->lock);
if (host->hsq_enabled)
host->cqe_ops->cqe_recovery_finish(host);
mmc_put_card(mq->card, &mq->ctx);
blk_mq_run_hw_queues(q, true);
@ -279,6 +285,14 @@ static blk_status_t mmc_mq_queue_rq(struct blk_mq_hw_ctx *hctx,
}
break;
case MMC_ISSUE_ASYNC:
/*
* For MMC host software queue, we only allow 2 requests in
* flight to avoid a long latency.
*/
if (host->hsq_enabled && mq->in_flight[issue_type] > 2) {
spin_unlock_irq(&mq->lock);
return BLK_STS_RESOURCE;
}
break;
default:
/*
@ -430,7 +444,7 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card)
* The queue depth for CQE must match the hardware because the request
* tag is used to index the hardware queue.
*/
if (mq->use_cqe)
if (mq->use_cqe && !host->hsq_enabled)
mq->tag_set.queue_depth =
min_t(int, card->ext_csd.cmdq_depth, host->cqe_qdepth);
else

View file

@ -1082,6 +1082,16 @@ retry:
}
}
if (host->cqe_ops && !host->cqe_enabled) {
err = host->cqe_ops->cqe_enable(host, card);
if (!err) {
host->cqe_enabled = true;
host->hsq_enabled = true;
pr_info("%s: Host Software Queue enabled\n",
mmc_hostname(host));
}
}
if (host->caps2 & MMC_CAP2_AVOID_3_3V &&
host->ios.signal_voltage == MMC_SIGNAL_VOLTAGE_330) {
pr_err("%s: Host failed to negotiate down from 3.3V\n",

View file

@ -632,6 +632,7 @@ config MMC_SDHCI_SPRD
depends on ARCH_SPRD
depends on MMC_SDHCI_PLTFM
select MMC_SDHCI_IO_ACCESSORS
select MMC_HSQ
help
This selects the SDIO Host Controller in Spreadtrum
SoCs, this driver supports R11(IP version: R11P0).
@ -936,6 +937,17 @@ config MMC_CQHCI
If unsure, say N.
config MMC_HSQ
tristate "MMC Host Software Queue support"
help
This selects the MMC Host Software Queue support. This may increase
performance, if the host controller and its driver supports it.
If you have a controller/driver supporting this interface, say Y or M
here.
If unsure, say N.
config MMC_TOSHIBA_PCI
tristate "Toshiba Type A SD/MMC Card Interface Driver"
depends on PCI

View file

@ -98,6 +98,7 @@ obj-$(CONFIG_MMC_SDHCI_BRCMSTB) += sdhci-brcmstb.o
obj-$(CONFIG_MMC_SDHCI_OMAP) += sdhci-omap.o
obj-$(CONFIG_MMC_SDHCI_SPRD) += sdhci-sprd.o
obj-$(CONFIG_MMC_CQHCI) += cqhci.o
obj-$(CONFIG_MMC_HSQ) += mmc_hsq.o
ifeq ($(CONFIG_CB710_DEBUG),y)
CFLAGS-cb710-mmc += -DDEBUG

View file

@ -321,14 +321,20 @@ static int cqhci_enable(struct mmc_host *mmc, struct mmc_card *card)
struct cqhci_host *cq_host = mmc->cqe_private;
int err;
if (!card->ext_csd.cmdq_en)
return -EINVAL;
if (cq_host->enabled)
return 0;
cq_host->rca = card->rca;
err = cqhci_host_alloc_tdl(cq_host);
if (err)
if (err) {
pr_err("%s: Failed to enable CQE, error %d\n",
mmc_hostname(mmc), err);
return err;
}
__cqhci_enable(cq_host);

348
drivers/mmc/host/mmc_hsq.c Normal file
View file

@ -0,0 +1,348 @@
// SPDX-License-Identifier: GPL-2.0
/*
*
* MMC software queue support based on command queue interfaces
*
* Copyright (C) 2019 Linaro, Inc.
* Author: Baolin Wang <baolin.wang@linaro.org>
*/
#include <linux/mmc/card.h>
#include <linux/mmc/host.h>
#include <linux/module.h>
#include "mmc_hsq.h"
#define HSQ_NUM_SLOTS 64
#define HSQ_INVALID_TAG HSQ_NUM_SLOTS
static void mmc_hsq_pump_requests(struct mmc_hsq *hsq)
{
struct mmc_host *mmc = hsq->mmc;
struct hsq_slot *slot;
unsigned long flags;
spin_lock_irqsave(&hsq->lock, flags);
/* Make sure we are not already running a request now */
if (hsq->mrq) {
spin_unlock_irqrestore(&hsq->lock, flags);
return;
}
/* Make sure there are remain requests need to pump */
if (!hsq->qcnt || !hsq->enabled) {
spin_unlock_irqrestore(&hsq->lock, flags);
return;
}
slot = &hsq->slot[hsq->next_tag];
hsq->mrq = slot->mrq;
hsq->qcnt--;
spin_unlock_irqrestore(&hsq->lock, flags);
mmc->ops->request(mmc, hsq->mrq);
}
static void mmc_hsq_update_next_tag(struct mmc_hsq *hsq, int remains)
{
struct hsq_slot *slot;
int tag;
/*
* If there are no remain requests in software queue, then set a invalid
* tag.
*/
if (!remains) {
hsq->next_tag = HSQ_INVALID_TAG;
return;
}
/*
* Increasing the next tag and check if the corresponding request is
* available, if yes, then we found a candidate request.
*/
if (++hsq->next_tag != HSQ_INVALID_TAG) {
slot = &hsq->slot[hsq->next_tag];
if (slot->mrq)
return;
}
/* Othersie we should iterate all slots to find a available tag. */
for (tag = 0; tag < HSQ_NUM_SLOTS; tag++) {
slot = &hsq->slot[tag];
if (slot->mrq)
break;
}
if (tag == HSQ_NUM_SLOTS)
tag = HSQ_INVALID_TAG;
hsq->next_tag = tag;
}
static void mmc_hsq_post_request(struct mmc_hsq *hsq)
{
unsigned long flags;
int remains;
spin_lock_irqsave(&hsq->lock, flags);
remains = hsq->qcnt;
hsq->mrq = NULL;
/* Update the next available tag to be queued. */
mmc_hsq_update_next_tag(hsq, remains);
if (hsq->waiting_for_idle && !remains) {
hsq->waiting_for_idle = false;
wake_up(&hsq->wait_queue);
}
/* Do not pump new request in recovery mode. */
if (hsq->recovery_halt) {
spin_unlock_irqrestore(&hsq->lock, flags);
return;
}
spin_unlock_irqrestore(&hsq->lock, flags);
/*
* Try to pump new request to host controller as fast as possible,
* after completing previous request.
*/
if (remains > 0)
mmc_hsq_pump_requests(hsq);
}
/**
* mmc_hsq_finalize_request - finalize one request if the request is done
* @mmc: the host controller
* @mrq: the request need to be finalized
*
* Return true if we finalized the corresponding request in software queue,
* otherwise return false.
*/
bool mmc_hsq_finalize_request(struct mmc_host *mmc, struct mmc_request *mrq)
{
struct mmc_hsq *hsq = mmc->cqe_private;
unsigned long flags;
spin_lock_irqsave(&hsq->lock, flags);
if (!hsq->enabled || !hsq->mrq || hsq->mrq != mrq) {
spin_unlock_irqrestore(&hsq->lock, flags);
return false;
}
/*
* Clear current completed slot request to make a room for new request.
*/
hsq->slot[hsq->next_tag].mrq = NULL;
spin_unlock_irqrestore(&hsq->lock, flags);
mmc_cqe_request_done(mmc, hsq->mrq);
mmc_hsq_post_request(hsq);
return true;
}
EXPORT_SYMBOL_GPL(mmc_hsq_finalize_request);
static void mmc_hsq_recovery_start(struct mmc_host *mmc)
{
struct mmc_hsq *hsq = mmc->cqe_private;
unsigned long flags;
spin_lock_irqsave(&hsq->lock, flags);
hsq->recovery_halt = true;
spin_unlock_irqrestore(&hsq->lock, flags);
}
static void mmc_hsq_recovery_finish(struct mmc_host *mmc)
{
struct mmc_hsq *hsq = mmc->cqe_private;
int remains;
spin_lock_irq(&hsq->lock);
hsq->recovery_halt = false;
remains = hsq->qcnt;
spin_unlock_irq(&hsq->lock);
/*
* Try to pump new request if there are request pending in software
* queue after finishing recovery.
*/
if (remains > 0)
mmc_hsq_pump_requests(hsq);
}
static int mmc_hsq_request(struct mmc_host *mmc, struct mmc_request *mrq)
{
struct mmc_hsq *hsq = mmc->cqe_private;
int tag = mrq->tag;
spin_lock_irq(&hsq->lock);
if (!hsq->enabled) {
spin_unlock_irq(&hsq->lock);
return -ESHUTDOWN;
}
/* Do not queue any new requests in recovery mode. */
if (hsq->recovery_halt) {
spin_unlock_irq(&hsq->lock);
return -EBUSY;
}
hsq->slot[tag].mrq = mrq;
/*
* Set the next tag as current request tag if no available
* next tag.
*/
if (hsq->next_tag == HSQ_INVALID_TAG)
hsq->next_tag = tag;
hsq->qcnt++;
spin_unlock_irq(&hsq->lock);
mmc_hsq_pump_requests(hsq);
return 0;
}
static void mmc_hsq_post_req(struct mmc_host *mmc, struct mmc_request *mrq)
{
if (mmc->ops->post_req)
mmc->ops->post_req(mmc, mrq, 0);
}
static bool mmc_hsq_queue_is_idle(struct mmc_hsq *hsq, int *ret)
{
bool is_idle;
spin_lock_irq(&hsq->lock);
is_idle = (!hsq->mrq && !hsq->qcnt) ||
hsq->recovery_halt;
*ret = hsq->recovery_halt ? -EBUSY : 0;
hsq->waiting_for_idle = !is_idle;
spin_unlock_irq(&hsq->lock);
return is_idle;
}
static int mmc_hsq_wait_for_idle(struct mmc_host *mmc)
{
struct mmc_hsq *hsq = mmc->cqe_private;
int ret;
wait_event(hsq->wait_queue,
mmc_hsq_queue_is_idle(hsq, &ret));
return ret;
}
static void mmc_hsq_disable(struct mmc_host *mmc)
{
struct mmc_hsq *hsq = mmc->cqe_private;
u32 timeout = 500;
int ret;
spin_lock_irq(&hsq->lock);
if (!hsq->enabled) {
spin_unlock_irq(&hsq->lock);
return;
}
spin_unlock_irq(&hsq->lock);
ret = wait_event_timeout(hsq->wait_queue,
mmc_hsq_queue_is_idle(hsq, &ret),
msecs_to_jiffies(timeout));
if (ret == 0) {
pr_warn("could not stop mmc software queue\n");
return;
}
spin_lock_irq(&hsq->lock);
hsq->enabled = false;
spin_unlock_irq(&hsq->lock);
}
static int mmc_hsq_enable(struct mmc_host *mmc, struct mmc_card *card)
{
struct mmc_hsq *hsq = mmc->cqe_private;
spin_lock_irq(&hsq->lock);
if (hsq->enabled) {
spin_unlock_irq(&hsq->lock);
return -EBUSY;
}
hsq->enabled = true;
spin_unlock_irq(&hsq->lock);
return 0;
}
static const struct mmc_cqe_ops mmc_hsq_ops = {
.cqe_enable = mmc_hsq_enable,
.cqe_disable = mmc_hsq_disable,
.cqe_request = mmc_hsq_request,
.cqe_post_req = mmc_hsq_post_req,
.cqe_wait_for_idle = mmc_hsq_wait_for_idle,
.cqe_recovery_start = mmc_hsq_recovery_start,
.cqe_recovery_finish = mmc_hsq_recovery_finish,
};
int mmc_hsq_init(struct mmc_hsq *hsq, struct mmc_host *mmc)
{
hsq->num_slots = HSQ_NUM_SLOTS;
hsq->next_tag = HSQ_INVALID_TAG;
hsq->slot = devm_kcalloc(mmc_dev(mmc), hsq->num_slots,
sizeof(struct hsq_slot), GFP_KERNEL);
if (!hsq->slot)
return -ENOMEM;
hsq->mmc = mmc;
hsq->mmc->cqe_private = hsq;
mmc->cqe_ops = &mmc_hsq_ops;
spin_lock_init(&hsq->lock);
init_waitqueue_head(&hsq->wait_queue);
return 0;
}
EXPORT_SYMBOL_GPL(mmc_hsq_init);
void mmc_hsq_suspend(struct mmc_host *mmc)
{
mmc_hsq_disable(mmc);
}
EXPORT_SYMBOL_GPL(mmc_hsq_suspend);
int mmc_hsq_resume(struct mmc_host *mmc)
{
return mmc_hsq_enable(mmc, NULL);
}
EXPORT_SYMBOL_GPL(mmc_hsq_resume);
MODULE_DESCRIPTION("MMC Host Software Queue support");
MODULE_LICENSE("GPL v2");

View file

@ -0,0 +1,30 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef LINUX_MMC_HSQ_H
#define LINUX_MMC_HSQ_H
struct hsq_slot {
struct mmc_request *mrq;
};
struct mmc_hsq {
struct mmc_host *mmc;
struct mmc_request *mrq;
wait_queue_head_t wait_queue;
struct hsq_slot *slot;
spinlock_t lock;
int next_tag;
int num_slots;
int qcnt;
bool enabled;
bool waiting_for_idle;
bool recovery_halt;
};
int mmc_hsq_init(struct mmc_hsq *hsq, struct mmc_host *mmc);
void mmc_hsq_suspend(struct mmc_host *mmc);
int mmc_hsq_resume(struct mmc_host *mmc);
bool mmc_hsq_finalize_request(struct mmc_host *mmc, struct mmc_request *mrq);
#endif

View file

@ -19,6 +19,7 @@
#include <linux/slab.h>
#include "sdhci-pltfm.h"
#include "mmc_hsq.h"
/* SDHCI_ARGUMENT2 register high 16bit */
#define SDHCI_SPRD_ARG2_STUFF GENMASK(31, 16)
@ -379,6 +380,16 @@ static unsigned int sdhci_sprd_get_ro(struct sdhci_host *host)
return 0;
}
static void sdhci_sprd_request_done(struct sdhci_host *host,
struct mmc_request *mrq)
{
/* Validate if the request was from software queue firstly. */
if (mmc_hsq_finalize_request(host->mmc, mrq))
return;
mmc_request_done(host->mmc, mrq);
}
static struct sdhci_ops sdhci_sprd_ops = {
.read_l = sdhci_sprd_readl,
.write_l = sdhci_sprd_writel,
@ -392,6 +403,7 @@ static struct sdhci_ops sdhci_sprd_ops = {
.hw_reset = sdhci_sprd_hw_reset,
.get_max_timeout_count = sdhci_sprd_get_max_timeout_count,
.get_ro = sdhci_sprd_get_ro,
.request_done = sdhci_sprd_request_done,
};
static void sdhci_sprd_request(struct mmc_host *mmc, struct mmc_request *mrq)
@ -521,6 +533,7 @@ static int sdhci_sprd_probe(struct platform_device *pdev)
{
struct sdhci_host *host;
struct sdhci_sprd_host *sprd_host;
struct mmc_hsq *hsq;
struct clk *clk;
int ret = 0;
@ -543,7 +556,7 @@ static int sdhci_sprd_probe(struct platform_device *pdev)
sdhci_sprd_voltage_switch;
host->mmc->caps = MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED |
MMC_CAP_ERASE | MMC_CAP_CMD23;
MMC_CAP_ERASE | MMC_CAP_CMD23 | MMC_CAP_WAIT_WHILE_BUSY;
ret = mmc_of_parse(host->mmc);
if (ret)
goto pltfm_free;
@ -631,6 +644,18 @@ static int sdhci_sprd_probe(struct platform_device *pdev)
sprd_host->flags = host->flags;
hsq = devm_kzalloc(&pdev->dev, sizeof(*hsq), GFP_KERNEL);
if (!hsq) {
ret = -ENOMEM;
goto err_cleanup_host;
}
ret = mmc_hsq_init(hsq, host->mmc);
if (ret)
goto err_cleanup_host;
host->always_defer_done = true;
ret = __sdhci_add_host(host);
if (ret)
goto err_cleanup_host;
@ -689,6 +714,7 @@ static int sdhci_sprd_runtime_suspend(struct device *dev)
struct sdhci_host *host = dev_get_drvdata(dev);
struct sdhci_sprd_host *sprd_host = TO_SPRD_HOST(host);
mmc_hsq_suspend(host->mmc);
sdhci_runtime_suspend_host(host);
clk_disable_unprepare(sprd_host->clk_sdio);
@ -717,6 +743,8 @@ static int sdhci_sprd_runtime_resume(struct device *dev)
goto clk_disable;
sdhci_runtime_resume_host(host, 1);
mmc_hsq_resume(host->mmc);
return 0;
clk_disable:

View file

@ -2727,7 +2727,10 @@ static bool sdhci_request_done(struct sdhci_host *host)
spin_unlock_irqrestore(&host->lock, flags);
mmc_request_done(host->mmc, mrq);
if (host->ops->request_done)
host->ops->request_done(host, mrq);
else
mmc_request_done(host->mmc, mrq);
return false;
}
@ -3030,7 +3033,7 @@ static inline bool sdhci_defer_done(struct sdhci_host *host,
{
struct mmc_data *data = mrq->data;
return host->pending_reset ||
return host->pending_reset || host->always_defer_done ||
((host->flags & SDHCI_REQ_USE_DMA) && data &&
data->host_cookie == COOKIE_MAPPED);
}
@ -3155,7 +3158,12 @@ out:
/* Process mrqs ready for immediate completion */
for (i = 0; i < SDHCI_MAX_MRQS; i++) {
if (mrqs_done[i])
if (!mrqs_done[i])
continue;
if (host->ops->request_done)
host->ops->request_done(host, mrqs_done[i]);
else
mmc_request_done(host->mmc, mrqs_done[i]);
}

View file

@ -535,6 +535,7 @@ struct sdhci_host {
bool pending_reset; /* Cmd/data reset is pending */
bool irq_wake_enabled; /* IRQ wakeup is enabled */
bool v4_mode; /* Host Version 4 Enable */
bool always_defer_done; /* Always defer to complete requests */
struct mmc_request *mrqs_done[SDHCI_MAX_MRQS]; /* Requests done */
struct mmc_command *cmd; /* Current command */
@ -646,6 +647,8 @@ struct sdhci_ops {
void (*voltage_switch)(struct sdhci_host *host);
void (*adma_write_desc)(struct sdhci_host *host, void **desc,
dma_addr_t addr, int len, unsigned int cmd);
void (*request_done)(struct sdhci_host *host,
struct mmc_request *mrq);
};
#ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS

View file

@ -38,8 +38,8 @@ enum {
enum {
MLX5E_TLS_PROGRESS_PARAMS_RECORD_TRACKER_STATE_START = 0,
MLX5E_TLS_PROGRESS_PARAMS_RECORD_TRACKER_STATE_SEARCHING = 1,
MLX5E_TLS_PROGRESS_PARAMS_RECORD_TRACKER_STATE_TRACKING = 2,
MLX5E_TLS_PROGRESS_PARAMS_RECORD_TRACKER_STATE_TRACKING = 1,
MLX5E_TLS_PROGRESS_PARAMS_RECORD_TRACKER_STATE_SEARCHING = 2,
};
struct mlx5e_ktls_offload_context_tx {

View file

@ -218,7 +218,7 @@ tx_sync_info_get(struct mlx5e_ktls_offload_context_tx *priv_tx,
* this packet was already acknowledged and its record info
* was released.
*/
ends_before = before(tcp_seq + datalen, tls_record_start_seq(record));
ends_before = before(tcp_seq + datalen - 1, tls_record_start_seq(record));
if (unlikely(tls_record_is_start_marker(record))) {
ret = ends_before ? MLX5E_KTLS_SYNC_SKIP_NO_DATA : MLX5E_KTLS_SYNC_FAIL;

View file

@ -1934,6 +1934,8 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes)
if (brcmf_sdio_hdparse(bus, bus->rxhdr, &rd_new,
BRCMF_SDIO_FT_NORMAL)) {
rd->len = 0;
brcmf_sdio_rxfail(bus, true, true);
sdio_release_host(bus->sdiodev->func1);
brcmu_pkt_buf_free_skb(pkt);
continue;
}

View file

@ -8,7 +8,7 @@
* Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2015 - 2017 Intel Deutschland GmbH
* Copyright(c) 2018 - 2019 Intel Corporation
* Copyright(c) 2018 - 2020 Intel Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@ -31,7 +31,7 @@
* Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2015 - 2017 Intel Deutschland GmbH
* Copyright(c) 2018 - 2019 Intel Corporation
* Copyright(c) 2018 - 2020 Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -1373,11 +1373,7 @@ static int iwl_dump_ini_rxf_iter(struct iwl_fw_runtime *fwrt,
goto out;
}
/*
* region register have absolute value so apply rxf offset after
* reading the registers
*/
offs += rxf_data.offset;
offs = rxf_data.offset;
/* Lock fence */
iwl_write_prph_no_grab(fwrt->trans, RXF_SET_FENCE_MODE + offs, 0x1);
@ -2315,10 +2311,7 @@ static void iwl_fw_dbg_collect_sync(struct iwl_fw_runtime *fwrt, u8 wk_idx)
goto out;
}
if (iwl_fw_dbg_stop_restart_recording(fwrt, &params, true)) {
IWL_ERR(fwrt, "Failed to stop DBGC recording, aborting dump\n");
goto out;
}
iwl_fw_dbg_stop_restart_recording(fwrt, &params, true);
IWL_DEBUG_FW_INFO(fwrt, "WRT: Data collection start\n");
if (iwl_trans_dbg_ini_valid(fwrt->trans))
@ -2484,14 +2477,14 @@ static int iwl_fw_dbg_restart_recording(struct iwl_trans *trans,
return 0;
}
int iwl_fw_dbg_stop_restart_recording(struct iwl_fw_runtime *fwrt,
struct iwl_fw_dbg_params *params,
bool stop)
void iwl_fw_dbg_stop_restart_recording(struct iwl_fw_runtime *fwrt,
struct iwl_fw_dbg_params *params,
bool stop)
{
int ret = 0;
if (test_bit(STATUS_FW_ERROR, &fwrt->trans->status))
return 0;
return;
if (fw_has_capa(&fwrt->fw->ucode_capa,
IWL_UCODE_TLV_CAPA_DBG_SUSPEND_RESUME_CMD_SUPP))
@ -2508,7 +2501,5 @@ int iwl_fw_dbg_stop_restart_recording(struct iwl_fw_runtime *fwrt,
iwl_fw_set_dbg_rec_on(fwrt);
}
#endif
return ret;
}
IWL_EXPORT_SYMBOL(iwl_fw_dbg_stop_restart_recording);

View file

@ -263,9 +263,9 @@ _iwl_fw_dbg_trigger_simple_stop(struct iwl_fw_runtime *fwrt,
_iwl_fw_dbg_trigger_simple_stop((fwrt), (wdev), \
iwl_fw_dbg_get_trigger((fwrt)->fw,\
(trig)))
int iwl_fw_dbg_stop_restart_recording(struct iwl_fw_runtime *fwrt,
struct iwl_fw_dbg_params *params,
bool stop);
void iwl_fw_dbg_stop_restart_recording(struct iwl_fw_runtime *fwrt,
struct iwl_fw_dbg_params *params,
bool stop);
#ifdef CONFIG_IWLWIFI_DEBUGFS
static inline void iwl_fw_set_dbg_rec_on(struct iwl_fw_runtime *fwrt)

View file

@ -147,7 +147,11 @@ static u16 rs_fw_get_config_flags(struct iwl_mvm *mvm,
(vht_ena && (vht_cap->cap & IEEE80211_VHT_CAP_RXLDPC))))
flags |= IWL_TLC_MNG_CFG_FLAGS_LDPC_MSK;
/* consider our LDPC support in case of HE */
/* consider LDPC support in case of HE */
if (he_cap->has_he && (he_cap->he_cap_elem.phy_cap_info[1] &
IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD))
flags |= IWL_TLC_MNG_CFG_FLAGS_LDPC_MSK;
if (sband->iftype_data && sband->iftype_data->he_cap.has_he &&
!(sband->iftype_data->he_cap.he_cap_elem.phy_cap_info[1] &
IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD))

View file

@ -850,9 +850,11 @@ out_free_tagset:
if (new)
blk_mq_free_tag_set(ctrl->ctrl.admin_tagset);
out_free_async_qe:
nvme_rdma_free_qe(ctrl->device->dev, &ctrl->async_event_sqe,
sizeof(struct nvme_command), DMA_TO_DEVICE);
ctrl->async_event_sqe.data = NULL;
if (ctrl->async_event_sqe.data) {
nvme_rdma_free_qe(ctrl->device->dev, &ctrl->async_event_sqe,
sizeof(struct nvme_command), DMA_TO_DEVICE);
ctrl->async_event_sqe.data = NULL;
}
out_free_queue:
nvme_rdma_free_queue(&ctrl->queues[0]);
return error;

View file

@ -56,6 +56,9 @@ static ssize_t bin_attr_nvmem_read(struct file *filp, struct kobject *kobj,
count = round_down(count, nvmem->word_size);
if (!nvmem->reg_read)
return -EPERM;
rc = nvmem->reg_read(nvmem->priv, pos, buf, count);
if (rc)
@ -90,6 +93,9 @@ static ssize_t bin_attr_nvmem_write(struct file *filp, struct kobject *kobj,
count = round_down(count, nvmem->word_size);
if (!nvmem->reg_write)
return -EPERM;
rc = nvmem->reg_write(nvmem->priv, pos, buf, count);
if (rc)

View file

@ -217,12 +217,14 @@ static int sprd_efuse_raw_prog(struct sprd_efuse *efuse, u32 blk, bool doub,
* Enable the auto-check function to validate if the programming is
* successful.
*/
sprd_efuse_set_auto_check(efuse, true);
if (lock)
sprd_efuse_set_auto_check(efuse, true);
writel(*data, efuse->base + SPRD_EFUSE_MEM(blk));
/* Disable auto-check and data double after programming */
sprd_efuse_set_auto_check(efuse, false);
if (lock)
sprd_efuse_set_auto_check(efuse, false);
sprd_efuse_set_data_double(efuse, false);
/*
@ -237,9 +239,9 @@ static int sprd_efuse_raw_prog(struct sprd_efuse *efuse, u32 blk, bool doub,
writel(SPRD_EFUSE_ERR_CLR_MASK,
efuse->base + SPRD_EFUSE_ERR_CLR);
ret = -EBUSY;
} else {
} else if (lock) {
sprd_efuse_set_prog_lock(efuse, lock);
writel(*data, efuse->base + SPRD_EFUSE_MEM(blk));
writel(0, efuse->base + SPRD_EFUSE_MEM(blk));
sprd_efuse_set_prog_lock(efuse, false);
}
@ -322,6 +324,8 @@ unlock:
static int sprd_efuse_write(void *context, u32 offset, void *val, size_t bytes)
{
struct sprd_efuse *efuse = context;
bool blk_double = efuse->data->blk_double;
bool lock;
int ret;
ret = sprd_efuse_lock(efuse);
@ -332,7 +336,20 @@ static int sprd_efuse_write(void *context, u32 offset, void *val, size_t bytes)
if (ret)
goto unlock;
ret = sprd_efuse_raw_prog(efuse, offset, false, false, val);
/*
* If the writing bytes are equal with the block width, which means the
* whole block will be programmed. For this case, we should not allow
* this block to be programmed again by locking this block.
*
* If the block was programmed partially, we should allow this block to
* be programmed again.
*/
if (bytes < SPRD_EFUSE_BLOCK_WIDTH)
lock = false;
else
lock = true;
ret = sprd_efuse_raw_prog(efuse, offset, blk_double, lock, val);
clk_disable_unprepare(efuse->clk);

View file

@ -464,7 +464,8 @@ static ssize_t dev_rescan_store(struct device *dev,
}
return count;
}
static DEVICE_ATTR_WO(dev_rescan);
static struct device_attribute dev_attr_dev_rescan = __ATTR(rescan, 0200, NULL,
dev_rescan_store);
static ssize_t remove_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
@ -501,7 +502,8 @@ static ssize_t bus_rescan_store(struct device *dev,
}
return count;
}
static DEVICE_ATTR_WO(bus_rescan);
static struct device_attribute dev_attr_bus_rescan = __ATTR(rescan, 0200, NULL,
bus_rescan_store);
#if defined(CONFIG_PM) && defined(CONFIG_ACPI)
static ssize_t d3cold_allowed_store(struct device *dev,

View file

@ -464,9 +464,15 @@ static int sprd_pinconf_get(struct pinctrl_dev *pctldev, unsigned int pin_id,
case PIN_CONFIG_INPUT_ENABLE:
arg = (reg >> SLEEP_INPUT_SHIFT) & SLEEP_INPUT_MASK;
break;
case PIN_CONFIG_OUTPUT:
case PIN_CONFIG_OUTPUT_ENABLE:
arg = reg & SLEEP_OUTPUT_MASK;
break;
case PIN_CONFIG_BIAS_HIGH_IMPEDANCE:
if ((reg & SLEEP_OUTPUT) || (reg & SLEEP_INPUT))
return -EINVAL;
arg = 1;
break;
case PIN_CONFIG_DRIVE_STRENGTH:
arg = (reg >> DRIVE_STRENGTH_SHIFT) &
DRIVE_STRENGTH_MASK;
@ -635,13 +641,23 @@ static int sprd_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin_id,
shift = SLEEP_INPUT_SHIFT;
}
break;
case PIN_CONFIG_OUTPUT:
case PIN_CONFIG_OUTPUT_ENABLE:
if (is_sleep_config == true) {
val |= SLEEP_OUTPUT;
if (arg > 0)
val |= SLEEP_OUTPUT;
else
val &= ~SLEEP_OUTPUT;
mask = SLEEP_OUTPUT_MASK;
shift = SLEEP_OUTPUT_SHIFT;
}
break;
case PIN_CONFIG_BIAS_HIGH_IMPEDANCE:
if (is_sleep_config == true) {
val = shift = 0;
mask = SLEEP_OUTPUT | SLEEP_INPUT;
}
break;
case PIN_CONFIG_DRIVE_STRENGTH:
if (arg < 2 || arg > 60)
return -EINVAL;

View file

@ -21,6 +21,7 @@
#include <linux/property.h>
#include <linux/mfd/axp20x.h>
#include <linux/extcon.h>
#include <linux/dmi.h>
#define PS_STAT_VBUS_TRIGGER BIT(0)
#define PS_STAT_BAT_CHRG_DIR BIT(2)
@ -545,6 +546,49 @@ out:
return IRQ_HANDLED;
}
/*
* The HP Pavilion x2 10 series comes in a number of variants:
* Bay Trail SoC + AXP288 PMIC, DMI_BOARD_NAME: "815D"
* Cherry Trail SoC + AXP288 PMIC, DMI_BOARD_NAME: "813E"
* Cherry Trail SoC + TI PMIC, DMI_BOARD_NAME: "827C" or "82F4"
*
* The variants with the AXP288 PMIC are all kinds of special:
*
* 1. All variants use a Type-C connector which the AXP288 does not support, so
* when using a Type-C charger it is not recognized. Unlike most AXP288 devices,
* this model actually has mostly working ACPI AC / Battery code, the ACPI code
* "solves" this by simply setting the input_current_limit to 3A.
* There are still some issues with the ACPI code, so we use this native driver,
* and to solve the charging not working (500mA is not enough) issue we hardcode
* the 3A input_current_limit like the ACPI code does.
*
* 2. If no charger is connected the machine boots with the vbus-path disabled.
* Normally this is done when a 5V boost converter is active to avoid the PMIC
* trying to charge from the 5V boost converter's output. This is done when
* an OTG host cable is inserted and the ID pin on the micro-B receptacle is
* pulled low and the ID pin has an ACPI event handler associated with it
* which re-enables the vbus-path when the ID pin is pulled high when the
* OTG host cable is removed. The Type-C connector has no ID pin, there is
* no ID pin handler and there appears to be no 5V boost converter, so we
* end up not charging because the vbus-path is disabled, until we unplug
* the charger which automatically clears the vbus-path disable bit and then
* on the second plug-in of the adapter we start charging. To solve the not
* charging on first charger plugin we unconditionally enable the vbus-path at
* probe on this model, which is safe since there is no 5V boost converter.
*/
static const struct dmi_system_id axp288_hp_x2_dmi_ids[] = {
{
/*
* Bay Trail model has "Hewlett-Packard" as sys_vendor, Cherry
* Trail model has "HP", so we only match on product_name.
*/
.matches = {
DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion x2 Detachable"),
},
},
{} /* Terminating entry */
};
static void axp288_charger_extcon_evt_worker(struct work_struct *work)
{
struct axp288_chrg_info *info =
@ -568,7 +612,11 @@ static void axp288_charger_extcon_evt_worker(struct work_struct *work)
}
/* Determine cable/charger type */
if (extcon_get_state(edev, EXTCON_CHG_USB_SDP) > 0) {
if (dmi_check_system(axp288_hp_x2_dmi_ids)) {
/* See comment above axp288_hp_x2_dmi_ids declaration */
dev_dbg(&info->pdev->dev, "HP X2 with Type-C, setting inlmt to 3A\n");
current_limit = 3000000;
} else if (extcon_get_state(edev, EXTCON_CHG_USB_SDP) > 0) {
dev_dbg(&info->pdev->dev, "USB SDP charger is connected\n");
current_limit = 500000;
} else if (extcon_get_state(edev, EXTCON_CHG_USB_CDP) > 0) {
@ -685,6 +733,13 @@ static int charger_init_hw_regs(struct axp288_chrg_info *info)
return ret;
}
if (dmi_check_system(axp288_hp_x2_dmi_ids)) {
/* See comment above axp288_hp_x2_dmi_ids declaration */
ret = axp288_charger_vbus_path_select(info, true);
if (ret < 0)
return ret;
}
/* Read current charge voltage and current limit */
ret = regmap_read(info->regmap, AXP20X_CHRG_CTRL1, &val);
if (ret < 0) {

View file

@ -61,7 +61,7 @@ static const char * const power_supply_charge_type_text[] = {
static const char * const power_supply_health_text[] = {
"Unknown", "Good", "Overheat", "Dead", "Over voltage",
"Unspecified failure", "Cold", "Watchdog timer expire",
"Safety timer expire", "Over current"
"Safety timer expire", "Over current", "Warm", "Cool", "Hot"
};
static const char * const power_supply_technology_text[] = {

View file

@ -336,7 +336,9 @@ int ufshcd_hba_init_crypto_spec(struct ufs_hba *hba,
ufshcd_clear_all_keyslots(hba);
hba->ksm = keyslot_manager_create(hba->dev, ufshcd_num_keyslots(hba),
ksm_ops, crypto_modes_supported, hba);
ksm_ops,
BLK_CRYPTO_FEATURE_STANDARD_KEYS,
crypto_modes_supported, hba);
if (!hba->ksm) {
err = -ENOMEM;

View file

@ -38,6 +38,7 @@ struct cmdq_client *cmdq_mbox_create(struct device *dev, int index, u32 timeout)
client->pkt_cnt = 0;
client->client.dev = dev;
client->client.tx_block = false;
client->client.knows_txdone = true;
client->chan = mbox_request_channel(&client->client, index);
if (IS_ERR(client->chan)) {

View file

@ -45,12 +45,6 @@ static void free_duped_table(struct sg_table *table)
kfree(table);
}
struct ion_dma_buf_attachment {
struct device *dev;
struct sg_table *table;
struct list_head list;
};
static int ion_dma_buf_attach(struct dma_buf *dmabuf,
struct dma_buf_attachment *attachment)
{
@ -293,11 +287,16 @@ static void *ion_dma_buf_vmap(struct dma_buf *dmabuf)
{
struct ion_buffer *buffer = dmabuf->priv;
struct ion_heap *heap = buffer->heap;
void *vaddr;
if (!heap->buf_ops.vmap)
return ERR_PTR(-EOPNOTSUPP);
if (heap->buf_ops.vmap)
return heap->buf_ops.vmap(dmabuf);
return heap->buf_ops.vmap(dmabuf);
mutex_lock(&buffer->lock);
vaddr = ion_buffer_kmap_get(buffer);
mutex_unlock(&buffer->lock);
return vaddr;
}
static void ion_dma_buf_vunmap(struct dma_buf *dmabuf, void *vaddr)
@ -305,10 +304,14 @@ static void ion_dma_buf_vunmap(struct dma_buf *dmabuf, void *vaddr)
struct ion_buffer *buffer = dmabuf->priv;
struct ion_heap *heap = buffer->heap;
if (!heap->buf_ops.vunmap)
if (heap->buf_ops.vunmap) {
heap->buf_ops.vunmap(dmabuf, vaddr);
return;
}
return heap->buf_ops.vunmap(dmabuf, vaddr);
mutex_lock(&buffer->lock);
ion_buffer_kmap_put(buffer);
mutex_unlock(&buffer->lock);
}
static int ion_dma_buf_get_flags(struct dma_buf *dmabuf, unsigned long *flags)

View file

@ -1,10 +1,12 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* iTCO Vendor Specific Support hooks */
#ifdef CONFIG_ITCO_VENDOR_SUPPORT
extern int iTCO_vendorsupport;
extern void iTCO_vendor_pre_start(struct resource *, unsigned int);
extern void iTCO_vendor_pre_stop(struct resource *);
extern int iTCO_vendor_check_noreboot_on(void);
#else
#define iTCO_vendorsupport 0
#define iTCO_vendor_pre_start(acpibase, heartbeat) {}
#define iTCO_vendor_pre_stop(acpibase) {}
#define iTCO_vendor_check_noreboot_on() 1

View file

@ -39,8 +39,10 @@
/* Broken BIOS */
#define BROKEN_BIOS 911
static int vendorsupport;
module_param(vendorsupport, int, 0);
int iTCO_vendorsupport;
EXPORT_SYMBOL(iTCO_vendorsupport);
module_param_named(vendorsupport, iTCO_vendorsupport, int, 0);
MODULE_PARM_DESC(vendorsupport, "iTCO vendor specific support mode, default="
"0 (none), 1=SuperMicro Pent3, 911=Broken SMI BIOS");
@ -152,7 +154,7 @@ static void broken_bios_stop(struct resource *smires)
void iTCO_vendor_pre_start(struct resource *smires,
unsigned int heartbeat)
{
switch (vendorsupport) {
switch (iTCO_vendorsupport) {
case SUPERMICRO_OLD_BOARD:
supermicro_old_pre_start(smires);
break;
@ -165,7 +167,7 @@ EXPORT_SYMBOL(iTCO_vendor_pre_start);
void iTCO_vendor_pre_stop(struct resource *smires)
{
switch (vendorsupport) {
switch (iTCO_vendorsupport) {
case SUPERMICRO_OLD_BOARD:
supermicro_old_pre_stop(smires);
break;
@ -178,7 +180,7 @@ EXPORT_SYMBOL(iTCO_vendor_pre_stop);
int iTCO_vendor_check_noreboot_on(void)
{
switch (vendorsupport) {
switch (iTCO_vendorsupport) {
case SUPERMICRO_OLD_BOARD:
return 0;
default:
@ -189,13 +191,13 @@ EXPORT_SYMBOL(iTCO_vendor_check_noreboot_on);
static int __init iTCO_vendor_init_module(void)
{
if (vendorsupport == SUPERMICRO_NEW_BOARD) {
if (iTCO_vendorsupport == SUPERMICRO_NEW_BOARD) {
pr_warn("Option vendorsupport=%d is no longer supported, "
"please use the w83627hf_wdt driver instead\n",
SUPERMICRO_NEW_BOARD);
return -EINVAL;
}
pr_info("vendor-support=%d\n", vendorsupport);
pr_info("vendor-support=%d\n", iTCO_vendorsupport);
return 0;
}

View file

@ -459,13 +459,25 @@ static int iTCO_wdt_probe(struct platform_device *pdev)
if (!p->tco_res)
return -ENODEV;
p->smi_res = platform_get_resource(pdev, IORESOURCE_IO, ICH_RES_IO_SMI);
if (!p->smi_res)
return -ENODEV;
p->iTCO_version = pdata->version;
p->pci_dev = to_pci_dev(dev->parent);
p->smi_res = platform_get_resource(pdev, IORESOURCE_IO, ICH_RES_IO_SMI);
if (p->smi_res) {
/* The TCO logic uses the TCO_EN bit in the SMI_EN register */
if (!devm_request_region(dev, p->smi_res->start,
resource_size(p->smi_res),
pdev->name)) {
pr_err("I/O address 0x%04llx already in use, device disabled\n",
(u64)SMI_EN(p));
return -EBUSY;
}
} else if (iTCO_vendorsupport ||
turn_SMI_watchdog_clear_off >= p->iTCO_version) {
pr_err("SMI I/O resource is missing\n");
return -ENODEV;
}
iTCO_wdt_no_reboot_bit_setup(p, pdata);
/*
@ -492,14 +504,6 @@ static int iTCO_wdt_probe(struct platform_device *pdev)
/* Set the NO_REBOOT bit to prevent later reboots, just for sure */
p->update_no_reboot_bit(p->no_reboot_priv, true);
/* The TCO logic uses the TCO_EN bit in the SMI_EN register */
if (!devm_request_region(dev, p->smi_res->start,
resource_size(p->smi_res),
pdev->name)) {
pr_err("I/O address 0x%04llx already in use, device disabled\n",
(u64)SMI_EN(p));
return -EBUSY;
}
if (turn_SMI_watchdog_clear_off >= p->iTCO_version) {
/*
* Bit 13: TCO_EN -> 0

View file

@ -326,7 +326,8 @@ extern void fscrypt_destroy_hkdf(struct fscrypt_hkdf *hkdf);
/* inline_crypt.c */
#ifdef CONFIG_FS_ENCRYPTION_INLINE_CRYPT
extern void fscrypt_select_encryption_impl(struct fscrypt_info *ci);
extern int fscrypt_select_encryption_impl(struct fscrypt_info *ci,
bool is_hw_wrapped_key);
static inline bool
fscrypt_using_inline_encryption(const struct fscrypt_info *ci)
@ -370,8 +371,10 @@ fscrypt_is_key_prepared(struct fscrypt_prepared_key *prep_key,
#else /* CONFIG_FS_ENCRYPTION_INLINE_CRYPT */
static inline void fscrypt_select_encryption_impl(struct fscrypt_info *ci)
static inline int fscrypt_select_encryption_impl(struct fscrypt_info *ci,
bool is_hw_wrapped_key)
{
return 0;
}
static inline bool fscrypt_using_inline_encryption(

View file

@ -25,26 +25,76 @@ struct fscrypt_blk_crypto_key {
struct request_queue *devs[];
};
static int fscrypt_get_num_devices(struct super_block *sb)
{
if (sb->s_cop->get_num_devices)
return sb->s_cop->get_num_devices(sb);
return 1;
}
static void fscrypt_get_devices(struct super_block *sb, int num_devs,
struct request_queue **devs)
{
if (num_devs == 1)
devs[0] = bdev_get_queue(sb->s_bdev);
else
sb->s_cop->get_devices(sb, devs);
}
/* Enable inline encryption for this file if supported. */
void fscrypt_select_encryption_impl(struct fscrypt_info *ci)
int fscrypt_select_encryption_impl(struct fscrypt_info *ci,
bool is_hw_wrapped_key)
{
const struct inode *inode = ci->ci_inode;
struct super_block *sb = inode->i_sb;
enum blk_crypto_mode_num crypto_mode = ci->ci_mode->blk_crypto_mode;
struct request_queue **devs;
int num_devs;
int i;
/* The file must need contents encryption, not filenames encryption */
if (!S_ISREG(inode->i_mode))
return;
return 0;
/* blk-crypto must implement the needed encryption algorithm */
if (ci->ci_mode->blk_crypto_mode == BLK_ENCRYPTION_MODE_INVALID)
return;
if (crypto_mode == BLK_ENCRYPTION_MODE_INVALID)
return 0;
/* The filesystem must be mounted with -o inlinecrypt */
if (!sb->s_cop->inline_crypt_enabled ||
!sb->s_cop->inline_crypt_enabled(sb))
return;
return 0;
/*
* The needed encryption settings must be supported either by
* blk-crypto-fallback, or by hardware on all the filesystem's devices.
*/
if (IS_ENABLED(CONFIG_BLK_INLINE_ENCRYPTION_FALLBACK) &&
!is_hw_wrapped_key) {
ci->ci_inlinecrypt = true;
return 0;
}
num_devs = fscrypt_get_num_devices(sb);
devs = kmalloc_array(num_devs, sizeof(*devs), GFP_NOFS);
if (!devs)
return -ENOMEM;
fscrypt_get_devices(sb, num_devs, devs);
for (i = 0; i < num_devs; i++) {
if (!keyslot_manager_crypto_mode_supported(devs[i]->ksm,
crypto_mode,
sb->s_blocksize,
is_hw_wrapped_key))
goto out_free_devs;
}
ci->ci_inlinecrypt = true;
out_free_devs:
kfree(devs);
return 0;
}
int fscrypt_prepare_inline_crypt_key(struct fscrypt_prepared_key *prep_key,
@ -56,14 +106,13 @@ int fscrypt_prepare_inline_crypt_key(struct fscrypt_prepared_key *prep_key,
const struct inode *inode = ci->ci_inode;
struct super_block *sb = inode->i_sb;
enum blk_crypto_mode_num crypto_mode = ci->ci_mode->blk_crypto_mode;
int num_devs = 1;
int num_devs;
int queue_refs = 0;
struct fscrypt_blk_crypto_key *blk_key;
int err;
int i;
if (sb->s_cop->get_num_devices)
num_devs = sb->s_cop->get_num_devices(sb);
num_devs = fscrypt_get_num_devices(sb);
if (WARN_ON(num_devs < 1))
return -EINVAL;
@ -72,10 +121,7 @@ int fscrypt_prepare_inline_crypt_key(struct fscrypt_prepared_key *prep_key,
return -ENOMEM;
blk_key->num_devs = num_devs;
if (num_devs == 1)
blk_key->devs[0] = bdev_get_queue(sb->s_bdev);
else
sb->s_cop->get_devices(sb, blk_key->devs);
fscrypt_get_devices(sb, num_devs, blk_key->devs);
BUILD_BUG_ON(FSCRYPT_MAX_HW_WRAPPED_KEY_SIZE >
BLK_CRYPTO_MAX_WRAPPED_KEY_SIZE);
@ -103,6 +149,7 @@ int fscrypt_prepare_inline_crypt_key(struct fscrypt_prepared_key *prep_key,
queue_refs++;
err = blk_crypto_start_using_mode(crypto_mode, sb->s_blocksize,
is_hw_wrapped,
blk_key->devs[i]);
if (err) {
fscrypt_err(inode,

View file

@ -328,8 +328,6 @@ static int setup_file_encryption_key(struct fscrypt_info *ci,
struct fscrypt_key_specifier mk_spec;
int err;
fscrypt_select_encryption_impl(ci);
switch (ci->ci_policy.version) {
case FSCRYPT_POLICY_V1:
mk_spec.type = FSCRYPT_KEY_SPEC_TYPE_DESCRIPTOR;
@ -354,6 +352,10 @@ static int setup_file_encryption_key(struct fscrypt_info *ci,
ci->ci_policy.version != FSCRYPT_POLICY_V1)
return PTR_ERR(key);
err = fscrypt_select_encryption_impl(ci, false);
if (err)
return err;
/*
* As a legacy fallback for v1 policies, search for the key in
* the current task's subscribed keyrings too. Don't move this
@ -388,6 +390,10 @@ static int setup_file_encryption_key(struct fscrypt_info *ci,
goto out_release_key;
}
err = fscrypt_select_encryption_impl(ci, mk->mk_secret.is_hw_wrapped);
if (err)
goto out_release_key;
switch (ci->ci_policy.version) {
case FSCRYPT_POLICY_V1:
err = fscrypt_setup_v1_file_key(ci, mk->mk_secret.raw);

View file

@ -27,28 +27,19 @@ struct mount_info *incfs_alloc_mount_info(struct super_block *sb,
return ERR_PTR(-ENOMEM);
mi->mi_sb = sb;
mi->mi_options = *options;
mi->mi_backing_dir_path = *backing_dir_path;
mi->mi_owner = get_current_cred();
path_get(&mi->mi_backing_dir_path);
mutex_init(&mi->mi_dir_struct_mutex);
mutex_init(&mi->mi_pending_reads_mutex);
init_waitqueue_head(&mi->mi_pending_reads_notif_wq);
init_waitqueue_head(&mi->mi_log.ml_notif_wq);
spin_lock_init(&mi->mi_log.rl_writer_lock);
INIT_LIST_HEAD(&mi->mi_reads_list_head);
if (options->read_log_pages != 0) {
size_t buf_size = PAGE_SIZE * options->read_log_pages;
spin_lock_init(&mi->mi_log.rl_writer_lock);
init_waitqueue_head(&mi->mi_log.ml_notif_wq);
mi->mi_log.rl_size = buf_size / sizeof(*mi->mi_log.rl_ring_buf);
mi->mi_log.rl_ring_buf = kzalloc(buf_size, GFP_NOFS);
if (!mi->mi_log.rl_ring_buf) {
error = -ENOMEM;
goto err;
}
}
error = incfs_realloc_mount_info(mi, options);
if (error)
goto err;
return mi;
@ -57,6 +48,26 @@ err:
return ERR_PTR(error);
}
int incfs_realloc_mount_info(struct mount_info *mi,
struct mount_options *options)
{
kfree(mi->mi_log.rl_ring_buf);
mi->mi_log.rl_ring_buf = NULL;
mi->mi_log.rl_size = 0;
mi->mi_options = *options;
if (options->read_log_pages != 0) {
size_t buf_size = PAGE_SIZE * options->read_log_pages;
mi->mi_log.rl_size = buf_size / sizeof(*mi->mi_log.rl_ring_buf);
mi->mi_log.rl_ring_buf = kzalloc(buf_size, GFP_NOFS);
if (!mi->mi_log.rl_ring_buf)
return -ENOMEM;
}
return 0;
}
void incfs_free_mount_info(struct mount_info *mi)
{
if (!mi)
@ -371,11 +382,19 @@ static int get_data_file_block(struct data_file *df, int index,
return 0;
}
static int check_room_for_one_range(u32 size, u32 size_out)
{
if (size_out + sizeof(struct incfs_filled_range) > size)
return -ERANGE;
return 0;
}
static int copy_one_range(struct incfs_filled_range *range, void __user *buffer,
u32 size, u32 *size_out)
{
if (*size_out + sizeof(*range) > size)
return -ERANGE;
int error = check_room_for_one_range(size, *size_out);
if (error)
return error;
if (copy_to_user(((char *)buffer) + *size_out, range, sizeof(*range)))
return -EFAULT;
@ -384,6 +403,34 @@ static int copy_one_range(struct incfs_filled_range *range, void __user *buffer,
return 0;
}
static int update_file_header_flags(struct data_file *df, u32 bits_to_reset,
u32 bits_to_set)
{
int result;
u32 new_flags;
struct backing_file_context *bfc;
if (!df)
return -EFAULT;
bfc = df->df_backing_file_context;
if (!bfc)
return -EFAULT;
result = mutex_lock_interruptible(&bfc->bc_mutex);
if (result)
return result;
new_flags = (df->df_header_flags & ~bits_to_reset) | bits_to_set;
if (new_flags != df->df_header_flags) {
df->df_header_flags = new_flags;
result = incfs_write_file_header_flags(bfc, new_flags);
}
mutex_unlock(&bfc->bc_mutex);
return result;
}
int incfs_get_filled_blocks(struct data_file *df,
struct incfs_get_filled_blocks_args *arg)
{
@ -400,6 +447,7 @@ int incfs_get_filled_blocks(struct data_file *df,
if (end_index > df->df_total_block_count)
end_index = df->df_total_block_count;
arg->total_blocks_out = df->df_total_block_count;
arg->data_blocks_out = df->df_data_block_count;
if (df->df_header_flags & INCFS_FILE_COMPLETE) {
pr_debug("File marked full, fast get_filled_blocks");
@ -407,14 +455,22 @@ int incfs_get_filled_blocks(struct data_file *df,
arg->index_out = arg->start_index;
return 0;
}
arg->index_out = arg->start_index;
error = check_room_for_one_range(size, *size_out);
if (error)
return error;
range = (struct incfs_filled_range){
.begin = arg->start_index,
.end = end_index,
};
error = copy_one_range(&range, buffer, size, size_out);
if (error)
return error;
arg->index_out = end_index;
return copy_one_range(&range, buffer, size, size_out);
return 0;
}
for (arg->index_out = arg->start_index; arg->index_out < end_index;
@ -429,13 +485,20 @@ int incfs_get_filled_blocks(struct data_file *df,
continue;
if (!in_range) {
error = check_room_for_one_range(size, *size_out);
if (error)
break;
in_range = true;
range.begin = arg->index_out;
} else {
range.end = arg->index_out;
error = copy_one_range(&range, buffer, size, size_out);
if (error)
if (error) {
/* there will be another try out of the loop,
* it will reset the index_out if it fails too
*/
break;
}
in_range = false;
}
}
@ -443,17 +506,15 @@ int incfs_get_filled_blocks(struct data_file *df,
if (in_range) {
range.end = arg->index_out;
error = copy_one_range(&range, buffer, size, size_out);
if (error)
arg->index_out = range.begin;
}
if (!error && in_range && arg->start_index == 0 &&
end_index == df->df_total_block_count &&
*size_out == sizeof(struct incfs_filled_range)) {
int result;
df->df_header_flags |= INCFS_FILE_COMPLETE;
result = incfs_update_file_header_flags(
df->df_backing_file_context, df->df_header_flags);
int result =
update_file_header_flags(df, 0, INCFS_FILE_COMPLETE);
/* Log failure only, since it's just a failed optimization */
pr_debug("Marked file full with result %d", result);
}

View file

@ -223,6 +223,9 @@ struct mount_info *incfs_alloc_mount_info(struct super_block *sb,
struct mount_options *options,
struct path *backing_dir_path);
int incfs_realloc_mount_info(struct mount_info *mi,
struct mount_options *options);
void incfs_free_mount_info(struct mount_info *mi);
struct data_file *incfs_open_data_file(struct mount_info *mi, struct file *bf);

View file

@ -215,7 +215,7 @@ static int append_md_to_backing_file(struct backing_file_context *bfc,
return result;
}
int incfs_update_file_header_flags(struct backing_file_context *bfc, u32 flags)
int incfs_write_file_header_flags(struct backing_file_context *bfc, u32 flags)
{
if (!bfc)
return -EFAULT;

View file

@ -311,7 +311,7 @@ int incfs_write_file_attr_to_backing_file(struct backing_file_context *bfc,
int incfs_write_signature_to_backing_file(struct backing_file_context *bfc,
struct mem_range sig, u32 tree_size);
int incfs_update_file_header_flags(struct backing_file_context *bfc, u32 flags);
int incfs_write_file_header_flags(struct backing_file_context *bfc, u32 flags);
int incfs_make_empty_backing_file(struct backing_file_context *bfc,
incfs_uuid_t *uuid, u64 file_size);

View file

@ -347,8 +347,8 @@ static int inode_test(struct inode *inode, void *opaque)
return (node->n_backing_inode == backing_inode) &&
inode->i_ino == search->ino;
}
return 1;
} else
return inode->i_ino == search->ino;
}
static int inode_set(struct inode *inode, void *opaque)
@ -894,6 +894,7 @@ static int init_new_file(struct mount_info *mi, struct dentry *dentry,
}
bfc = incfs_alloc_bfc(new_file);
fput(new_file);
if (IS_ERR(bfc)) {
error = PTR_ERR(bfc);
bfc = NULL;
@ -1444,6 +1445,9 @@ static long ioctl_get_filled_blocks(struct file *f, void __user *arg)
if (!df)
return -EINVAL;
if ((uintptr_t)f->private_data != CAN_FILL)
return -EPERM;
if (copy_from_user(&args, args_usr_ptr, sizeof(args)) > 0)
return -EINVAL;
@ -1676,6 +1680,7 @@ static int final_file_delete(struct mount_info *mi,
if (d_really_is_positive(index_file_dentry))
error = incfs_unlink(index_file_dentry);
out:
dput(index_file_dentry);
if (error)
pr_debug("incfs: delete_file_from_index err:%d\n", error);
return error;
@ -1978,6 +1983,7 @@ static void dentry_release(struct dentry *d)
if (di)
path_put(&di->backing_path);
kfree(d->d_fsdata);
d->d_fsdata = NULL;
}
@ -2189,7 +2195,7 @@ struct dentry *incfs_mount_fs(struct file_system_type *type, int flags,
path_put(&backing_dir_path);
sb->s_flags |= SB_ACTIVE;
pr_debug("infs: mount\n");
pr_debug("incfs: mount\n");
return dget(sb->s_root);
err:
sb->s_fs_info = NULL;
@ -2210,12 +2216,11 @@ static int incfs_remount_fs(struct super_block *sb, int *flags, char *data)
if (err)
return err;
if (mi->mi_options.read_timeout_ms != options.read_timeout_ms) {
mi->mi_options.read_timeout_ms = options.read_timeout_ms;
pr_debug("incfs: new timeout_ms=%d", options.read_timeout_ms);
}
err = incfs_realloc_mount_info(mi, &options);
if (err)
return err;
pr_debug("infs: remount\n");
pr_debug("incfs: remount\n");
return 0;
}
@ -2223,7 +2228,7 @@ void incfs_kill_sb(struct super_block *sb)
{
struct mount_info *mi = sb->s_fs_info;
pr_debug("infs: unmount\n");
pr_debug("incfs: unmount\n");
incfs_free_mount_info(mi);
generic_shutdown_super(sb);
}

View file

@ -20,6 +20,11 @@ int blk_crypto_init_key(struct blk_crypto_key *blk_key,
enum blk_crypto_mode_num crypto_mode,
unsigned int data_unit_size);
int blk_crypto_start_using_mode(enum blk_crypto_mode_num crypto_mode,
unsigned int data_unit_size,
bool is_hw_wrapped_key,
struct request_queue *q);
int blk_crypto_evict_key(struct request_queue *q,
const struct blk_crypto_key *key);
@ -39,22 +44,10 @@ static inline bool blk_crypto_endio(struct bio *bio)
#ifdef CONFIG_BLK_INLINE_ENCRYPTION_FALLBACK
int blk_crypto_start_using_mode(enum blk_crypto_mode_num mode_num,
unsigned int data_unit_size,
struct request_queue *q);
int blk_crypto_fallback_init(void);
#else /* CONFIG_BLK_INLINE_ENCRYPTION_FALLBACK */
static inline int
blk_crypto_start_using_mode(enum blk_crypto_mode_num mode_num,
unsigned int data_unit_size,
struct request_queue *q)
{
return 0;
}
static inline int blk_crypto_fallback_init(void)
{
return 0;

View file

@ -104,7 +104,7 @@ struct ftrace_likely_data {
unsigned long constant;
};
#ifdef CONFIG_ENABLE_MUST_CHECK
#if defined(CONFIG_ENABLE_MUST_CHECK) && !defined(__GENKSYMS__)
#define __must_check __attribute__((__warn_unused_result__))
#else
#define __must_check

View file

@ -201,9 +201,6 @@ static inline bool policy_is_shared(struct cpufreq_policy *policy)
return cpumask_weight(policy->cpus) > 1;
}
/* /sys/devices/system/cpu/cpufreq: entry point for global variables */
extern struct kobject *cpufreq_global_kobject;
#ifdef CONFIG_CPU_FREQ
unsigned int cpufreq_get(unsigned int cpu);
unsigned int cpufreq_quick_get(unsigned int cpu);

View file

@ -44,6 +44,7 @@ struct vm_area_struct;
#else
#define ___GFP_NOLOCKDEP 0
#endif
#define ___GFP_CMA 0x1000000u
/* If the above are modified, __GFP_BITS_SHIFT may need updating */
/*
@ -57,6 +58,7 @@ struct vm_area_struct;
#define __GFP_HIGHMEM ((__force gfp_t)___GFP_HIGHMEM)
#define __GFP_DMA32 ((__force gfp_t)___GFP_DMA32)
#define __GFP_MOVABLE ((__force gfp_t)___GFP_MOVABLE) /* ZONE_MOVABLE allowed */
#define __GFP_CMA ((__force gfp_t)___GFP_CMA)
#define GFP_ZONEMASK (__GFP_DMA|__GFP_HIGHMEM|__GFP_DMA32|__GFP_MOVABLE)
/**
@ -217,8 +219,13 @@ struct vm_area_struct;
#define __GFP_NOLOCKDEP ((__force gfp_t)___GFP_NOLOCKDEP)
/* Room for N __GFP_FOO bits */
#define __GFP_BITS_SHIFT (23 + IS_ENABLED(CONFIG_LOCKDEP))
#define __GFP_BITS_SHIFT (25)
#ifdef CONFIG_LOCKDEP
#define __GFP_BITS_MASK ((__force gfp_t)((1 << __GFP_BITS_SHIFT) - 1))
#else
#define __GFP_BITS_MASK (((__force gfp_t)((1 << __GFP_BITS_SHIFT) - 1)) & \
~0x800000u)
#endif
/**
* DOC: Useful GFP flag combinations

View file

@ -205,7 +205,12 @@ static inline struct page *
alloc_zeroed_user_highpage_movable(struct vm_area_struct *vma,
unsigned long vaddr)
{
#ifndef CONFIG_CMA
return __alloc_zeroed_user_highpage(__GFP_MOVABLE, vma, vaddr);
#else
return __alloc_zeroed_user_highpage(__GFP_MOVABLE|__GFP_CMA, vma,
vaddr);
#endif
}
static inline void clear_highpage(struct page *page)

View file

@ -144,6 +144,18 @@ struct ion_heap {
#define ion_device_add_heap(heap) __ion_device_add_heap(heap, THIS_MODULE)
/**
* struct ion_dma_buf_attachment - hold device-table attachment data for buffer
* @dev: device attached to the buffer.
* @table: cached mapping.
* @list: list of ion_dma_buf_attachment.
*/
struct ion_dma_buf_attachment {
struct device *dev;
struct sg_table *table;
struct list_head list;
};
#ifdef CONFIG_ION
/**

View file

@ -8,6 +8,15 @@
#include <linux/bio.h>
/* Inline crypto feature bits. Must set at least one. */
enum {
/* Support for standard software-specified keys */
BLK_CRYPTO_FEATURE_STANDARD_KEYS = BIT(0),
/* Support for hardware-wrapped keys */
BLK_CRYPTO_FEATURE_WRAPPED_KEYS = BIT(1),
};
#ifdef CONFIG_BLK_INLINE_ENCRYPTION
struct keyslot_manager;
@ -45,6 +54,7 @@ struct keyslot_manager *keyslot_manager_create(
struct device *dev,
unsigned int num_slots,
const struct keyslot_mgmt_ll_ops *ksm_ops,
unsigned int features,
const unsigned int crypto_mode_supported[BLK_ENCRYPTION_MODE_MAX],
void *ll_priv_data);
@ -57,7 +67,8 @@ void keyslot_manager_put_slot(struct keyslot_manager *ksm, unsigned int slot);
bool keyslot_manager_crypto_mode_supported(struct keyslot_manager *ksm,
enum blk_crypto_mode_num crypto_mode,
unsigned int data_unit_size);
unsigned int data_unit_size,
bool is_hw_wrapped_key);
int keyslot_manager_evict_key(struct keyslot_manager *ksm,
const struct blk_crypto_key *key);
@ -71,6 +82,7 @@ void keyslot_manager_destroy(struct keyslot_manager *ksm);
struct keyslot_manager *keyslot_manager_create_passthrough(
struct device *dev,
const struct keyslot_mgmt_ll_ops *ksm_ops,
unsigned int features,
const unsigned int crypto_mode_supported[BLK_ENCRYPTION_MODE_MAX],
void *ll_priv_data);

View file

@ -0,0 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __LINUX_MFD_SC27XX_PMIC_H
#define __LINUX_MFD_SC27XX_PMIC_H
extern enum usb_charger_type sprd_pmic_detect_charger_type(struct device *dev);
#endif /* __LINUX_MFD_SC27XX_PMIC_H */

View file

@ -463,6 +463,9 @@ struct mmc_host {
bool cqe_enabled;
bool cqe_on;
/* Host Software Queue support */
bool hsq_enabled;
unsigned long private[0] ____cacheline_aligned;
};

View file

@ -43,8 +43,6 @@ enum migratetype {
MIGRATE_UNMOVABLE,
MIGRATE_MOVABLE,
MIGRATE_RECLAIMABLE,
MIGRATE_PCPTYPES, /* the number of types on the pcp lists */
MIGRATE_HIGHATOMIC = MIGRATE_PCPTYPES,
#ifdef CONFIG_CMA
/*
* MIGRATE_CMA migration type is designed to mimic the way
@ -61,6 +59,8 @@ enum migratetype {
*/
MIGRATE_CMA,
#endif
MIGRATE_PCPTYPES, /* the number of types on the pcp lists */
MIGRATE_HIGHATOMIC = MIGRATE_PCPTYPES,
#ifdef CONFIG_MEMORY_ISOLATION
MIGRATE_ISOLATE, /* can't allocate from here */
#endif
@ -73,9 +73,11 @@ extern const char * const migratetype_names[MIGRATE_TYPES];
#ifdef CONFIG_CMA
# define is_migrate_cma(migratetype) unlikely((migratetype) == MIGRATE_CMA)
# define is_migrate_cma_page(_page) (get_pageblock_migratetype(_page) == MIGRATE_CMA)
# define get_cma_migrate_type() MIGRATE_CMA
#else
# define is_migrate_cma(migratetype) false
# define is_migrate_cma_page(_page) false
# define get_cma_migrate_type() MIGRATE_MOVABLE
#endif
static inline bool is_migrate_movable(int mt)
@ -444,6 +446,10 @@ struct zone {
struct pglist_data *zone_pgdat;
struct per_cpu_pageset __percpu *pageset;
#ifdef CONFIG_CMA
bool cma_alloc;
#endif
#ifndef CONFIG_SPARSEMEM
/*
* Flags for a pageblock_nr_pages block. See pageblock-flags.h.

View file

@ -61,6 +61,9 @@ enum {
POWER_SUPPLY_HEALTH_WATCHDOG_TIMER_EXPIRE,
POWER_SUPPLY_HEALTH_SAFETY_TIMER_EXPIRE,
POWER_SUPPLY_HEALTH_OVERCURRENT,
POWER_SUPPLY_HEALTH_WARM,
POWER_SUPPLY_HEALTH_COOL,
POWER_SUPPLY_HEALTH_HOT,
};
enum {

View file

@ -20,11 +20,18 @@
#define MAX_SUSPEND_ABORT_LEN 256
void log_wakeup_reason(int irq);
#ifdef CONFIG_SUSPEND
void log_irq_wakeup_reason(int irq);
void log_threaded_irq_wakeup_reason(int irq, int parent_irq);
void log_suspend_abort_reason(const char *fmt, ...);
void log_abnormal_wakeup_reason(const char *fmt, ...);
void clear_wakeup_reasons(void);
#else
static inline void log_irq_wakeup_reason(int irq) { }
static inline void log_threaded_irq_wakeup_reason(int irq, int parent_irq) { }
static inline void log_suspend_abort_reason(const char *fmt, ...) { }
static inline void log_abnormal_wakeup_reason(const char *fmt, ...) { }
static inline void clear_wakeup_reasons(void) { }
#endif
#endif /* _LINUX_WAKEUP_REASON_H */

View file

@ -2,8 +2,10 @@
#ifndef __UAPI_CORESIGHT_STM_H_
#define __UAPI_CORESIGHT_STM_H_
#define STM_FLAG_TIMESTAMPED BIT(3)
#define STM_FLAG_GUARANTEED BIT(7)
#include <linux/const.h>
#define STM_FLAG_TIMESTAMPED _BITUL(3)
#define STM_FLAG_GUARANTEED _BITUL(7)
/*
* The CoreSight STM supports guaranteed and invariant timing

View file

@ -321,6 +321,9 @@ struct incfs_get_filled_blocks_args {
/* Actual number of blocks in file */
__u32 total_blocks_out;
/* The number of data blocks in file */
__u32 data_blocks_out;
/* Number of bytes written to range buffer */
__u32 range_buffer_size_out;

View file

@ -44,6 +44,7 @@ config GKI_HIDDEN_SND_SOC_CONFIGS
select SND_SOC_GENERIC_DMAENGINE_PCM if (SND_SOC && SND)
select SND_PCM_IEC958
select SND_SOC_COMPRESS if (SND_SOC && SND)
select SND_SOC_TOPOLOGY if (SND_SOC && SND)
help
Dummy config option used to enable hidden SND_SOC configs.
These are normally selected implicitly when a module

View file

@ -35,4 +35,4 @@ include/generated/compile.h: FORCE
@$($(quiet)chk_compile.h)
$(Q)$(CONFIG_SHELL) $(srctree)/scripts/mkcompile_h $@ \
"$(UTS_MACHINE)" "$(CONFIG_SMP)" "$(CONFIG_PREEMPT)" \
"$(CONFIG_PREEMPT_RT)" "$(CC) $(KBUILD_CFLAGS)"
"$(CONFIG_PREEMPT_RT)" "$(CC) $(KBUILD_CFLAGS)" "$(LD)"

View file

@ -14,6 +14,7 @@
#include <linux/interrupt.h>
#include <linux/kernel_stat.h>
#include <linux/irqdomain.h>
#include <linux/wakeup_reason.h>
#include <trace/events/irq.h>
@ -507,8 +508,22 @@ static bool irq_may_run(struct irq_desc *desc)
* If the interrupt is not in progress and is not an armed
* wakeup interrupt, proceed.
*/
if (!irqd_has_set(&desc->irq_data, mask))
if (!irqd_has_set(&desc->irq_data, mask)) {
#ifdef CONFIG_PM_SLEEP
if (unlikely(desc->no_suspend_depth &&
irqd_is_wakeup_set(&desc->irq_data))) {
unsigned int irq = irq_desc_get_irq(desc);
const char *name = "(unnamed)";
if (desc->action && desc->action->name)
name = desc->action->name;
log_abnormal_wakeup_reason("misconfigured IRQ %u %s",
irq, name);
}
#endif
return true;
}
/*
* If the interrupt is an armed wakeup source, mark it pending

View file

@ -120,7 +120,7 @@ out:
* invoke it.
*
* If module auto-loading support is disabled then this function
* becomes a no-operation.
* simply returns -ENOENT.
*/
int __request_module(bool wait, const char *fmt, ...)
{
@ -137,7 +137,7 @@ int __request_module(bool wait, const char *fmt, ...)
WARN_ON_ONCE(wait && current_is_async());
if (!modprobe_path[0])
return 0;
return -ENOENT;
va_start(args, fmt);
ret = vsnprintf(module_name, MODULE_NAME_LEN, fmt, args);

View file

@ -516,7 +516,7 @@ static int padata_replace(struct padata_instance *pinst)
{
int notification_mask = 0;
struct padata_shell *ps;
int err;
int err = 0;
pinst->flags |= PADATA_RESET;
@ -643,8 +643,8 @@ int padata_set_cpumask(struct padata_instance *pinst, int cpumask_type,
struct cpumask *serial_mask, *parallel_mask;
int err = -EINVAL;
mutex_lock(&pinst->lock);
get_online_cpus();
mutex_lock(&pinst->lock);
switch (cpumask_type) {
case PADATA_CPU_PARALLEL:
@ -662,8 +662,8 @@ int padata_set_cpumask(struct padata_instance *pinst, int cpumask_type,
err = __padata_set_cpumasks(pinst, parallel_mask, serial_mask);
out:
put_online_cpus();
mutex_unlock(&pinst->lock);
put_online_cpus();
return err;
}

View file

@ -22,7 +22,6 @@
#include <linux/kmod.h>
#include <trace/events/power.h>
#include <linux/cpuset.h>
#include <linux/wakeup_reason.h>
/*
* Timeout for stopping processes
@ -39,9 +38,6 @@ static int try_to_freeze_tasks(bool user_only)
unsigned int elapsed_msecs;
bool wakeup = false;
int sleep_usecs = USEC_PER_MSEC;
#ifdef CONFIG_PM_SLEEP
char suspend_abort[MAX_SUSPEND_ABORT_LEN];
#endif
start = ktime_get_boottime();
@ -71,11 +67,6 @@ static int try_to_freeze_tasks(bool user_only)
break;
if (pm_wakeup_pending()) {
#ifdef CONFIG_PM_SLEEP
pm_get_active_wakeup_sources(suspend_abort,
MAX_SUSPEND_ABORT_LEN);
log_suspend_abort_reason(suspend_abort);
#endif
wakeup = true;
break;
}

View file

@ -140,6 +140,7 @@ static void s2idle_loop(void)
}
pm_wakeup_clear(false);
clear_wakeup_reasons();
s2idle_enter();
}
@ -362,6 +363,7 @@ static int suspend_prepare(suspend_state_t state)
if (!error)
return 0;
log_suspend_abort_reason("One or more tasks refusing to freeze");
suspend_stats.failed_freeze++;
dpm_save_failed_step(SUSPEND_FREEZE);
Finish:
@ -391,7 +393,6 @@ void __weak arch_suspend_enable_irqs(void)
*/
static int suspend_enter(suspend_state_t state, bool *wakeup)
{
char suspend_abort[MAX_SUSPEND_ABORT_LEN];
int error, last_dev;
error = platform_suspend_prepare(state);
@ -403,8 +404,8 @@ static int suspend_enter(suspend_state_t state, bool *wakeup)
last_dev = suspend_stats.last_failed_dev + REC_FAILED_NUM - 1;
last_dev %= REC_FAILED_NUM;
pr_err("late suspend of devices failed\n");
log_suspend_abort_reason("%s device failed to power down",
suspend_stats.failed_devs[last_dev]);
log_suspend_abort_reason("late suspend of %s device failed",
suspend_stats.failed_devs[last_dev]);
goto Platform_finish;
}
error = platform_suspend_prepare_late(state);
@ -417,7 +418,7 @@ static int suspend_enter(suspend_state_t state, bool *wakeup)
last_dev %= REC_FAILED_NUM;
pr_err("noirq suspend of devices failed\n");
log_suspend_abort_reason("noirq suspend of %s device failed",
suspend_stats.failed_devs[last_dev]);
suspend_stats.failed_devs[last_dev]);
goto Platform_early_resume;
}
error = platform_suspend_prepare_noirq(state);
@ -453,9 +454,6 @@ static int suspend_enter(suspend_state_t state, bool *wakeup)
trace_suspend_resume(TPS("machine_suspend"),
state, false);
} else if (*wakeup) {
pm_get_active_wakeup_sources(suspend_abort,
MAX_SUSPEND_ABORT_LEN);
log_suspend_abort_reason(suspend_abort);
error = -EBUSY;
}
syscore_resume();
@ -490,7 +488,7 @@ static int suspend_enter(suspend_state_t state, bool *wakeup)
*/
int suspend_devices_and_enter(suspend_state_t state)
{
int error, last_dev;
int error;
bool wakeup = false;
if (!sleep_state_supported(state))
@ -509,11 +507,9 @@ int suspend_devices_and_enter(suspend_state_t state)
suspend_test_start();
error = dpm_suspend_start(PMSG_SUSPEND);
if (error) {
last_dev = suspend_stats.last_failed_dev + REC_FAILED_NUM - 1;
last_dev %= REC_FAILED_NUM;
pr_err("Some devices failed to suspend, or early wake event detected\n");
log_suspend_abort_reason("%s device failed to suspend, or early wake event detected",
suspend_stats.failed_devs[last_dev]);
log_suspend_abort_reason(
"Some devices failed to suspend, or early wake event detected");
goto Recover_platform;
}
suspend_test_finish("suspend devices");

View file

@ -4,7 +4,7 @@
* Logs the reasons which caused the kernel to resume from
* the suspend mode.
*
* Copyright (C) 2014 Google, Inc.
* Copyright (C) 2020 Google, Inc.
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
@ -26,42 +26,282 @@
#include <linux/spinlock.h>
#include <linux/notifier.h>
#include <linux/suspend.h>
#include <linux/slab.h>
/*
* struct wakeup_irq_node - stores data and relationships for IRQs logged as
* either base or nested wakeup reasons during suspend/resume flow.
* @siblings - for membership on leaf or parent IRQ lists
* @irq - the IRQ number
* @irq_name - the name associated with the IRQ, or a default if none
*/
struct wakeup_irq_node {
struct list_head siblings;
int irq;
const char *irq_name;
};
#define MAX_WAKEUP_REASON_IRQS 32
static int irq_list[MAX_WAKEUP_REASON_IRQS];
static int irqcount;
static DEFINE_SPINLOCK(wakeup_reason_lock);
static LIST_HEAD(leaf_irqs); /* kept in ascending IRQ sorted order */
static LIST_HEAD(parent_irqs); /* unordered */
static struct kmem_cache *wakeup_irq_nodes_cache;
static const char *default_irq_name = "(unnamed)";
static struct kobject *kobj;
static bool capture_reasons;
static bool suspend_abort;
static char abort_reason[MAX_SUSPEND_ABORT_LEN];
static struct kobject *wakeup_reason;
static spinlock_t resume_reason_lock;
static bool abnormal_wake;
static char non_irq_wake_reason[MAX_SUSPEND_ABORT_LEN];
static ktime_t last_monotime; /* monotonic time before last suspend */
static ktime_t curr_monotime; /* monotonic time after last suspend */
static ktime_t last_stime; /* monotonic boottime offset before last suspend */
static ktime_t curr_stime; /* monotonic boottime offset after last suspend */
static ssize_t last_resume_reason_show(struct kobject *kobj, struct kobj_attribute *attr,
char *buf)
static void init_node(struct wakeup_irq_node *p, int irq)
{
int irq_no, buf_offset = 0;
struct irq_desc *desc;
unsigned long flags;
spin_lock_irqsave(&resume_reason_lock, flags);
if (suspend_abort) {
buf_offset = sprintf(buf, "Abort: %s", abort_reason);
} else {
for (irq_no = 0; irq_no < irqcount; irq_no++) {
desc = irq_to_desc(irq_list[irq_no]);
if (desc && desc->action && desc->action->name)
buf_offset += sprintf(buf + buf_offset, "%d %s\n",
irq_list[irq_no], desc->action->name);
INIT_LIST_HEAD(&p->siblings);
p->irq = irq;
desc = irq_to_desc(irq);
if (desc && desc->action && desc->action->name)
p->irq_name = desc->action->name;
else
p->irq_name = default_irq_name;
}
static struct wakeup_irq_node *create_node(int irq)
{
struct wakeup_irq_node *result;
result = kmem_cache_alloc(wakeup_irq_nodes_cache, GFP_ATOMIC);
if (unlikely(!result))
pr_warn("Failed to log wakeup IRQ %d\n", irq);
else
init_node(result, irq);
return result;
}
static void delete_list(struct list_head *head)
{
struct wakeup_irq_node *n;
while (!list_empty(head)) {
n = list_first_entry(head, struct wakeup_irq_node, siblings);
list_del(&n->siblings);
kmem_cache_free(wakeup_irq_nodes_cache, n);
}
}
static bool add_sibling_node_sorted(struct list_head *head, int irq)
{
struct wakeup_irq_node *n;
struct list_head *predecessor = head;
if (unlikely(WARN_ON(!head)))
return NULL;
if (!list_empty(head))
list_for_each_entry(n, head, siblings) {
if (n->irq < irq)
predecessor = &n->siblings;
else if (n->irq == irq)
return true;
else
buf_offset += sprintf(buf + buf_offset, "%d\n",
irq_list[irq_no]);
break;
}
n = create_node(irq);
if (n) {
list_add(&n->siblings, predecessor);
return true;
}
return false;
}
static struct wakeup_irq_node *find_node_in_list(struct list_head *head,
int irq)
{
struct wakeup_irq_node *n;
if (unlikely(WARN_ON(!head)))
return NULL;
list_for_each_entry(n, head, siblings)
if (n->irq == irq)
return n;
return NULL;
}
void log_irq_wakeup_reason(int irq)
{
unsigned long flags;
spin_lock_irqsave(&wakeup_reason_lock, flags);
if (!capture_reasons) {
spin_unlock_irqrestore(&wakeup_reason_lock, flags);
return;
}
if (find_node_in_list(&parent_irqs, irq) == NULL)
add_sibling_node_sorted(&leaf_irqs, irq);
spin_unlock_irqrestore(&wakeup_reason_lock, flags);
}
void log_threaded_irq_wakeup_reason(int irq, int parent_irq)
{
struct wakeup_irq_node *parent;
unsigned long flags;
/*
* Intentionally unsynchronized. Calls that come in after we have
* resumed should have a fast exit path since there's no work to be
* done, any any coherence issue that could cause a wrong value here is
* both highly improbable - given the set/clear timing - and very low
* impact (parent IRQ gets logged instead of the specific child).
*/
if (!capture_reasons)
return;
spin_lock_irqsave(&wakeup_reason_lock, flags);
if (!capture_reasons || (find_node_in_list(&leaf_irqs, irq) != NULL)) {
spin_unlock_irqrestore(&wakeup_reason_lock, flags);
return;
}
parent = find_node_in_list(&parent_irqs, parent_irq);
if (parent != NULL)
add_sibling_node_sorted(&leaf_irqs, irq);
else {
parent = find_node_in_list(&leaf_irqs, parent_irq);
if (parent != NULL) {
list_del_init(&parent->siblings);
list_add_tail(&parent->siblings, &parent_irqs);
add_sibling_node_sorted(&leaf_irqs, irq);
}
}
spin_unlock_irqrestore(&resume_reason_lock, flags);
spin_unlock_irqrestore(&wakeup_reason_lock, flags);
}
void __log_abort_or_abnormal_wake(bool abort, const char *fmt, va_list args)
{
unsigned long flags;
spin_lock_irqsave(&wakeup_reason_lock, flags);
/* Suspend abort or abnormal wake reason has already been logged. */
if (suspend_abort || abnormal_wake) {
spin_unlock_irqrestore(&wakeup_reason_lock, flags);
return;
}
suspend_abort = abort;
abnormal_wake = !abort;
vsnprintf(non_irq_wake_reason, MAX_SUSPEND_ABORT_LEN, fmt, args);
spin_unlock_irqrestore(&wakeup_reason_lock, flags);
}
void log_suspend_abort_reason(const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
__log_abort_or_abnormal_wake(true, fmt, args);
va_end(args);
}
void log_abnormal_wakeup_reason(const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
__log_abort_or_abnormal_wake(false, fmt, args);
va_end(args);
}
void clear_wakeup_reasons(void)
{
unsigned long flags;
spin_lock_irqsave(&wakeup_reason_lock, flags);
delete_list(&leaf_irqs);
delete_list(&parent_irqs);
suspend_abort = false;
abnormal_wake = false;
capture_reasons = true;
spin_unlock_irqrestore(&wakeup_reason_lock, flags);
}
static void print_wakeup_sources(void)
{
struct wakeup_irq_node *n;
unsigned long flags;
spin_lock_irqsave(&wakeup_reason_lock, flags);
capture_reasons = false;
if (suspend_abort) {
pr_info("Abort: %s\n", non_irq_wake_reason);
spin_unlock_irqrestore(&wakeup_reason_lock, flags);
return;
}
if (!list_empty(&leaf_irqs))
list_for_each_entry(n, &leaf_irqs, siblings)
pr_info("Resume caused by IRQ %d, %s\n", n->irq,
n->irq_name);
else if (abnormal_wake)
pr_info("Resume caused by %s\n", non_irq_wake_reason);
else
pr_info("Resume cause unknown\n");
spin_unlock_irqrestore(&wakeup_reason_lock, flags);
}
static ssize_t last_resume_reason_show(struct kobject *kobj,
struct kobj_attribute *attr, char *buf)
{
ssize_t buf_offset = 0;
struct wakeup_irq_node *n;
unsigned long flags;
spin_lock_irqsave(&wakeup_reason_lock, flags);
if (suspend_abort) {
buf_offset = scnprintf(buf, PAGE_SIZE, "Abort: %s",
non_irq_wake_reason);
spin_unlock_irqrestore(&wakeup_reason_lock, flags);
return buf_offset;
}
if (!list_empty(&leaf_irqs))
list_for_each_entry(n, &leaf_irqs, siblings)
buf_offset += scnprintf(buf + buf_offset,
PAGE_SIZE - buf_offset,
"%d %s\n", n->irq, n->irq_name);
else if (abnormal_wake)
buf_offset = scnprintf(buf, PAGE_SIZE, "-1 %s",
non_irq_wake_reason);
spin_unlock_irqrestore(&wakeup_reason_lock, flags);
return buf_offset;
}
@ -90,8 +330,8 @@ static ssize_t last_suspend_time_show(struct kobject *kobj,
/* Export suspend_resume_time and sleep_time in pair here. */
return sprintf(buf, "%llu.%09lu %llu.%09lu\n",
suspend_resume_time.tv_sec, suspend_resume_time.tv_nsec,
sleep_time.tv_sec, sleep_time.tv_nsec);
suspend_resume_time.tv_sec, suspend_resume_time.tv_nsec,
sleep_time.tv_sec, sleep_time.tv_nsec);
}
static struct kobj_attribute resume_reason = __ATTR_RO(last_resume_reason);
@ -106,74 +346,24 @@ static struct attribute_group attr_group = {
.attrs = attrs,
};
/*
* logs all the wake up reasons to the kernel
* stores the irqs to expose them to the userspace via sysfs
*/
void log_wakeup_reason(int irq)
{
struct irq_desc *desc;
unsigned long flags;
desc = irq_to_desc(irq);
if (desc && desc->action && desc->action->name)
printk(KERN_INFO "Resume caused by IRQ %d, %s\n", irq,
desc->action->name);
else
printk(KERN_INFO "Resume caused by IRQ %d\n", irq);
spin_lock_irqsave(&resume_reason_lock, flags);
if (irqcount == MAX_WAKEUP_REASON_IRQS) {
spin_unlock_irqrestore(&resume_reason_lock, flags);
printk(KERN_WARNING "Resume caused by more than %d IRQs\n",
MAX_WAKEUP_REASON_IRQS);
return;
}
irq_list[irqcount++] = irq;
spin_unlock_irqrestore(&resume_reason_lock, flags);
}
void log_suspend_abort_reason(const char *fmt, ...)
{
unsigned long flags;
va_list args;
spin_lock_irqsave(&resume_reason_lock, flags);
//Suspend abort reason has already been logged.
if (suspend_abort) {
spin_unlock_irqrestore(&resume_reason_lock, flags);
return;
}
suspend_abort = true;
va_start(args, fmt);
vsnprintf(abort_reason, MAX_SUSPEND_ABORT_LEN, fmt, args);
va_end(args);
spin_unlock_irqrestore(&resume_reason_lock, flags);
}
/* Detects a suspend and clears all the previous wake up reasons*/
static int wakeup_reason_pm_event(struct notifier_block *notifier,
unsigned long pm_event, void *unused)
{
unsigned long flags;
switch (pm_event) {
case PM_SUSPEND_PREPARE:
spin_lock_irqsave(&resume_reason_lock, flags);
irqcount = 0;
suspend_abort = false;
spin_unlock_irqrestore(&resume_reason_lock, flags);
/* monotonic time since boot */
last_monotime = ktime_get();
/* monotonic time since boot including the time spent in suspend */
last_stime = ktime_get_boottime();
clear_wakeup_reasons();
break;
case PM_POST_SUSPEND:
/* monotonic time since boot */
curr_monotime = ktime_get();
/* monotonic time since boot including the time spent in suspend */
curr_stime = ktime_get_boottime();
print_wakeup_sources();
break;
default:
break;
@ -185,31 +375,40 @@ static struct notifier_block wakeup_reason_pm_notifier_block = {
.notifier_call = wakeup_reason_pm_event,
};
/* Initializes the sysfs parameter
* registers the pm_event notifier
*/
int __init wakeup_reason_init(void)
{
int retval;
spin_lock_init(&resume_reason_lock);
retval = register_pm_notifier(&wakeup_reason_pm_notifier_block);
if (retval)
printk(KERN_WARNING "[%s] failed to register PM notifier %d\n",
__func__, retval);
if (register_pm_notifier(&wakeup_reason_pm_notifier_block)) {
pr_warn("[%s] failed to register PM notifier\n", __func__);
goto fail;
}
wakeup_reason = kobject_create_and_add("wakeup_reasons", kernel_kobj);
if (!wakeup_reason) {
printk(KERN_WARNING "[%s] failed to create a sysfs kobject\n",
__func__);
return 1;
kobj = kobject_create_and_add("wakeup_reasons", kernel_kobj);
if (!kobj) {
pr_warn("[%s] failed to create a sysfs kobject\n", __func__);
goto fail_unregister_pm_notifier;
}
retval = sysfs_create_group(wakeup_reason, &attr_group);
if (retval) {
kobject_put(wakeup_reason);
printk(KERN_WARNING "[%s] failed to create a sysfs group %d\n",
__func__, retval);
if (sysfs_create_group(kobj, &attr_group)) {
pr_warn("[%s] failed to create a sysfs group\n", __func__);
goto fail_kobject_put;
}
wakeup_irq_nodes_cache =
kmem_cache_create("wakeup_irq_node_cache",
sizeof(struct wakeup_irq_node), 0, 0, NULL);
if (!wakeup_irq_nodes_cache)
goto fail_remove_group;
return 0;
fail_remove_group:
sysfs_remove_group(kobj, &attr_group);
fail_kobject_put:
kobject_put(kobj);
fail_unregister_pm_notifier:
unregister_pm_notifier(&wakeup_reason_pm_notifier_block);
fail:
return 1;
}
late_initcall(wakeup_reason_init);

View file

@ -41,8 +41,67 @@ static int convert_prio(int prio)
return cpupri;
}
static inline int __cpupri_find(struct cpupri *cp, struct task_struct *p,
struct cpumask *lowest_mask, int idx)
{
struct cpupri_vec *vec = &cp->pri_to_cpu[idx];
int skip = 0;
if (!atomic_read(&(vec)->count))
skip = 1;
/*
* When looking at the vector, we need to read the counter,
* do a memory barrier, then read the mask.
*
* Note: This is still all racey, but we can deal with it.
* Ideally, we only want to look at masks that are set.
*
* If a mask is not set, then the only thing wrong is that we
* did a little more work than necessary.
*
* If we read a zero count but the mask is set, because of the
* memory barriers, that can only happen when the highest prio
* task for a run queue has left the run queue, in which case,
* it will be followed by a pull. If the task we are processing
* fails to find a proper place to go, that pull request will
* pull this task if the run queue is running at a lower
* priority.
*/
smp_rmb();
/* Need to do the rmb for every iteration */
if (skip)
return 0;
if (cpumask_any_and(p->cpus_ptr, vec->mask) >= nr_cpu_ids)
return 0;
if (lowest_mask) {
cpumask_and(lowest_mask, p->cpus_ptr, vec->mask);
/*
* We have to ensure that we have at least one bit
* still set in the array, since the map could have
* been concurrently emptied between the first and
* second reads of vec->mask. If we hit this
* condition, simply act as though we never hit this
* priority level and continue on.
*/
if (cpumask_empty(lowest_mask))
return 0;
}
return 1;
}
int cpupri_find(struct cpupri *cp, struct task_struct *p,
struct cpumask *lowest_mask)
{
return cpupri_find_fitness(cp, p, lowest_mask, NULL);
}
/**
* cpupri_find - find the best (lowest-pri) CPU in the system
* cpupri_find_fitness - find the best (lowest-pri) CPU in the system
* @cp: The cpupri context
* @p: The task
* @lowest_mask: A mask to fill in with selected CPUs (or NULL)
@ -58,84 +117,59 @@ static int convert_prio(int prio)
*
* Return: (int)bool - CPUs were found
*/
int cpupri_find(struct cpupri *cp, struct task_struct *p,
int cpupri_find_fitness(struct cpupri *cp, struct task_struct *p,
struct cpumask *lowest_mask,
bool (*fitness_fn)(struct task_struct *p, int cpu))
{
int idx = 0;
int task_pri = convert_prio(p->prio);
int idx, cpu;
BUG_ON(task_pri >= CPUPRI_NR_PRIORITIES);
for (idx = 0; idx < task_pri; idx++) {
struct cpupri_vec *vec = &cp->pri_to_cpu[idx];
int skip = 0;
if (!atomic_read(&(vec)->count))
skip = 1;
/*
* When looking at the vector, we need to read the counter,
* do a memory barrier, then read the mask.
*
* Note: This is still all racey, but we can deal with it.
* Ideally, we only want to look at masks that are set.
*
* If a mask is not set, then the only thing wrong is that we
* did a little more work than necessary.
*
* If we read a zero count but the mask is set, because of the
* memory barriers, that can only happen when the highest prio
* task for a run queue has left the run queue, in which case,
* it will be followed by a pull. If the task we are processing
* fails to find a proper place to go, that pull request will
* pull this task if the run queue is running at a lower
* priority.
*/
smp_rmb();
/* Need to do the rmb for every iteration */
if (skip)
if (!__cpupri_find(cp, p, lowest_mask, idx))
continue;
if (cpumask_any_and(p->cpus_ptr, vec->mask) >= nr_cpu_ids)
continue;
if (!lowest_mask || !fitness_fn)
return 1;
if (lowest_mask) {
int cpu;
cpumask_and(lowest_mask, p->cpus_ptr, vec->mask);
/*
* We have to ensure that we have at least one bit
* still set in the array, since the map could have
* been concurrently emptied between the first and
* second reads of vec->mask. If we hit this
* condition, simply act as though we never hit this
* priority level and continue on.
*/
if (cpumask_empty(lowest_mask))
continue;
if (!fitness_fn)
return 1;
/* Ensure the capacity of the CPUs fit the task */
for_each_cpu(cpu, lowest_mask) {
if (!fitness_fn(p, cpu))
cpumask_clear_cpu(cpu, lowest_mask);
}
/*
* If no CPU at the current priority can fit the task
* continue looking
*/
if (cpumask_empty(lowest_mask))
continue;
/* Ensure the capacity of the CPUs fit the task */
for_each_cpu(cpu, lowest_mask) {
if (!fitness_fn(p, cpu))
cpumask_clear_cpu(cpu, lowest_mask);
}
/*
* If no CPU at the current priority can fit the task
* continue looking
*/
if (cpumask_empty(lowest_mask))
continue;
return 1;
}
/*
* If we failed to find a fitting lowest_mask, kick off a new search
* but without taking into account any fitness criteria this time.
*
* This rule favours honouring priority over fitting the task in the
* correct CPU (Capacity Awareness being the only user now).
* The idea is that if a higher priority task can run, then it should
* run even if this ends up being on unfitting CPU.
*
* The cost of this trade-off is not entirely clear and will probably
* be good for some workloads and bad for others.
*
* The main idea here is that if some CPUs were overcommitted, we try
* to spread which is what the scheduler traditionally did. Sys admins
* must do proper RT planning to avoid overloading the system if they
* really care.
*/
if (fitness_fn)
return cpupri_find(cp, p, lowest_mask);
return 0;
}

View file

@ -19,8 +19,10 @@ struct cpupri {
#ifdef CONFIG_SMP
int cpupri_find(struct cpupri *cp, struct task_struct *p,
struct cpumask *lowest_mask,
bool (*fitness_fn)(struct task_struct *p, int cpu));
struct cpumask *lowest_mask);
int cpupri_find_fitness(struct cpupri *cp, struct task_struct *p,
struct cpumask *lowest_mask,
bool (*fitness_fn)(struct task_struct *p, int cpu));
void cpupri_set(struct cpupri *cp, int cpu, int pri);
int cpupri_init(struct cpupri *cp);
void cpupri_cleanup(struct cpupri *cp);

View file

@ -1474,6 +1474,13 @@ select_task_rq_rt(struct task_struct *p, int cpu, int sd_flag, int flags)
if (test || !rt_task_fits_capacity(p, cpu)) {
int target = find_lowest_rq(p);
/*
* Bail out if we were forcing a migration to find a better
* fitting CPU but our search failed.
*/
if (!test && target != -1 && !rt_task_fits_capacity(p, target))
goto out_unlock;
/*
* Don't bother moving it if the destination CPU is
* not running a lower priority task.
@ -1482,6 +1489,8 @@ select_task_rq_rt(struct task_struct *p, int cpu, int sd_flag, int flags)
p->prio < cpu_rq(target)->rt.highest_prio.curr)
cpu = target;
}
out_unlock:
rcu_read_unlock();
out:
@ -1495,7 +1504,7 @@ static void check_preempt_equal_prio(struct rq *rq, struct task_struct *p)
* let's hope p can move out.
*/
if (rq->curr->nr_cpus_allowed == 1 ||
!cpupri_find(&rq->rd->cpupri, rq->curr, NULL, NULL))
!cpupri_find(&rq->rd->cpupri, rq->curr, NULL))
return;
/*
@ -1503,7 +1512,7 @@ static void check_preempt_equal_prio(struct rq *rq, struct task_struct *p)
* see if it is pushed or pulled somewhere else.
*/
if (p->nr_cpus_allowed != 1 &&
cpupri_find(&rq->rd->cpupri, p, NULL, NULL))
cpupri_find(&rq->rd->cpupri, p, NULL))
return;
/*
@ -1650,8 +1659,7 @@ static void put_prev_task_rt(struct rq *rq, struct task_struct *p)
static int pick_rt_task(struct rq *rq, struct task_struct *p, int cpu)
{
if (!task_running(rq, p) &&
cpumask_test_cpu(cpu, p->cpus_ptr) &&
rt_task_fits_capacity(p, cpu))
cpumask_test_cpu(cpu, p->cpus_ptr))
return 1;
return 0;
@ -1685,6 +1693,7 @@ static int find_lowest_rq(struct task_struct *task)
struct cpumask *lowest_mask = this_cpu_cpumask_var_ptr(local_cpu_mask);
int this_cpu = smp_processor_id();
int cpu = task_cpu(task);
int ret;
/* Make sure the mask is initialized first */
if (unlikely(!lowest_mask))
@ -1693,8 +1702,22 @@ static int find_lowest_rq(struct task_struct *task)
if (task->nr_cpus_allowed == 1)
return -1; /* No other targets possible */
if (!cpupri_find(&task_rq(task)->rd->cpupri, task, lowest_mask,
rt_task_fits_capacity))
/*
* If we're on asym system ensure we consider the different capacities
* of the CPUs when searching for the lowest_mask.
*/
if (static_branch_unlikely(&sched_asym_cpucapacity)) {
ret = cpupri_find_fitness(&task_rq(task)->rd->cpupri,
task, lowest_mask,
rt_task_fits_capacity);
} else {
ret = cpupri_find(&task_rq(task)->rd->cpupri,
task, lowest_mask);
}
if (!ret)
return -1; /* No targets found */
/*
@ -2205,7 +2228,7 @@ static void task_woken_rt(struct rq *rq, struct task_struct *p)
(rq->curr->nr_cpus_allowed < 2 ||
rq->curr->prio <= p->prio);
if (need_to_push || !rt_task_fits_capacity(p, cpu_of(rq)))
if (need_to_push)
push_rt_tasks(rq);
}
@ -2277,10 +2300,7 @@ static void switched_to_rt(struct rq *rq, struct task_struct *p)
*/
if (task_on_rq_queued(p) && rq->curr != p) {
#ifdef CONFIG_SMP
bool need_to_push = rq->rt.overloaded ||
!rt_task_fits_capacity(p, cpu_of(rq));
if (p->nr_cpus_allowed > 1 && need_to_push)
if (p->nr_cpus_allowed > 1 && rq->rt.overloaded)
rt_queue_push_tasks(rq);
#endif /* CONFIG_SMP */
if (p->prio < rq->curr->prio && cpu_online(cpu_of(rq)))

View file

@ -1627,7 +1627,7 @@ static void __queue_delayed_work(int cpu, struct workqueue_struct *wq,
struct work_struct *work = &dwork->work;
WARN_ON_ONCE(!wq);
#ifndef CONFIG_CFI
#ifndef CONFIG_CFI_CLANG
WARN_ON_ONCE(timer->function != delayed_work_timer_fn);
#endif
WARN_ON_ONCE(timer_pending(timer));

View file

@ -12,6 +12,9 @@
static unsigned int tests_run;
static unsigned int tests_passed;
static const unsigned int order_limit =
IS_ENABLED(CONFIG_XARRAY_MULTI) ? BITS_PER_LONG : 1;
#ifndef XA_DEBUG
# ifdef __KERNEL__
void xa_dump(const struct xarray *xa) { }
@ -959,6 +962,20 @@ static noinline void check_multi_find_2(struct xarray *xa)
}
}
static noinline void check_multi_find_3(struct xarray *xa)
{
unsigned int order;
for (order = 5; order < order_limit; order++) {
unsigned long index = 1UL << (order - 5);
XA_BUG_ON(xa, !xa_empty(xa));
xa_store_order(xa, 0, order - 4, xa_mk_index(0), GFP_KERNEL);
XA_BUG_ON(xa, xa_find_after(xa, &index, ULONG_MAX, XA_PRESENT));
xa_erase_index(xa, 0);
}
}
static noinline void check_find_1(struct xarray *xa)
{
unsigned long i, j, k;
@ -1081,6 +1098,7 @@ static noinline void check_find(struct xarray *xa)
for (i = 2; i < 10; i++)
check_multi_find_1(xa, i);
check_multi_find_2(xa);
check_multi_find_3(xa);
}
/* See find_swap_entry() in mm/shmem.c */

View file

@ -1839,7 +1839,8 @@ static bool xas_sibling(struct xa_state *xas)
if (!node)
return false;
mask = (XA_CHUNK_SIZE << node->shift) - 1;
return (xas->xa_index & mask) > (xas->xa_offset << node->shift);
return (xas->xa_index & mask) >
((unsigned long)xas->xa_offset << node->shift);
}
/**

View file

@ -2823,7 +2823,9 @@ int mpol_parse_str(char *str, struct mempolicy **mpol)
switch (mode) {
case MPOL_PREFERRED:
/*
* Insist on a nodelist of one node only
* Insist on a nodelist of one node only, although later
* we use first_node(nodes) to grab a single node, so here
* nodelist (or nodes) cannot be empty.
*/
if (nodelist) {
char *rest = nodelist;
@ -2831,6 +2833,8 @@ int mpol_parse_str(char *str, struct mempolicy **mpol)
rest++;
if (*rest)
goto out;
if (nodes_empty(nodes))
goto out;
}
break;
case MPOL_INTERLEAVE:

View file

@ -293,10 +293,10 @@ const char * const migratetype_names[MIGRATE_TYPES] = {
"Unmovable",
"Movable",
"Reclaimable",
"HighAtomic",
#ifdef CONFIG_CMA
"CMA",
#endif
"HighAtomic",
#ifdef CONFIG_MEMORY_ISOLATION
"Isolate",
#endif
@ -2725,19 +2725,37 @@ __rmqueue(struct zone *zone, unsigned int order, int migratetype,
retry:
page = __rmqueue_smallest(zone, order, migratetype);
if (unlikely(!page)) {
if (migratetype == MIGRATE_MOVABLE)
page = __rmqueue_cma_fallback(zone, order);
if (!page && __rmqueue_fallback(zone, order, migratetype,
alloc_flags))
goto retry;
}
if (unlikely(!page) && __rmqueue_fallback(zone, order, migratetype,
alloc_flags))
goto retry;
trace_mm_page_alloc_zone_locked(page, order, migratetype);
return page;
}
#ifdef CONFIG_CMA
static struct page *__rmqueue_cma(struct zone *zone, unsigned int order,
int migratetype,
unsigned int alloc_flags)
{
struct page *page = 0;
if (IS_ENABLED(CONFIG_CMA))
if (!zone->cma_alloc)
page = __rmqueue_cma_fallback(zone, order);
trace_mm_page_alloc_zone_locked(page, order, MIGRATE_CMA);
return page;
}
#else
static inline struct page *__rmqueue_cma(struct zone *zone, unsigned int order,
int migratetype,
unsigned int alloc_flags)
{
return NULL;
}
#endif
/*
* Obtain a specified number of elements from the buddy allocator, all under
* a single hold of the lock, for efficiency. Add them to the supplied list.
@ -2751,8 +2769,19 @@ static int rmqueue_bulk(struct zone *zone, unsigned int order,
spin_lock(&zone->lock);
for (i = 0; i < count; ++i) {
struct page *page = __rmqueue(zone, order, migratetype,
alloc_flags);
struct page *page;
/*
* If migrate type CMA is being requested only try to
* satisfy the request with CMA pages to try and increase
* CMA utlization.
*/
if (is_migrate_cma(migratetype))
page = __rmqueue_cma(zone, order, migratetype,
alloc_flags);
else
page = __rmqueue(zone, order, migratetype, alloc_flags);
if (unlikely(page == NULL))
break;
@ -2787,6 +2816,28 @@ static int rmqueue_bulk(struct zone *zone, unsigned int order,
return alloced;
}
/*
* Return the pcp list that corresponds to the migrate type if that list isn't
* empty.
* If the list is empty return NULL.
*/
static struct list_head *get_populated_pcp_list(struct zone *zone,
unsigned int order, struct per_cpu_pages *pcp,
int migratetype, unsigned int alloc_flags)
{
struct list_head *list = &pcp->lists[migratetype];
if (list_empty(list)) {
pcp->count += rmqueue_bulk(zone, order,
pcp->batch, list,
migratetype, alloc_flags);
if (list_empty(list))
list = NULL;
}
return list;
}
#ifdef CONFIG_NUMA
/*
* Called from the vmstat counter updater to drain pagesets of this
@ -3216,16 +3267,28 @@ static inline void zone_statistics(struct zone *preferred_zone, struct zone *z)
static struct page *__rmqueue_pcplist(struct zone *zone, int migratetype,
unsigned int alloc_flags,
struct per_cpu_pages *pcp,
struct list_head *list)
gfp_t gfp_flags)
{
struct page *page;
struct page *page = NULL;
struct list_head *list = NULL;
do {
if (list_empty(list)) {
pcp->count += rmqueue_bulk(zone, 0,
pcp->batch, list,
/* First try to get CMA pages */
if (migratetype == MIGRATE_MOVABLE &&
gfp_flags & __GFP_CMA) {
list = get_populated_pcp_list(zone, 0, pcp,
get_cma_migrate_type(), alloc_flags);
}
if (list == NULL) {
/*
* Either CMA is not suitable or there are no
* free CMA pages.
*/
list = get_populated_pcp_list(zone, 0, pcp,
migratetype, alloc_flags);
if (unlikely(list_empty(list)))
if (unlikely(list == NULL) ||
unlikely(list_empty(list)))
return NULL;
}
@ -3243,14 +3306,13 @@ static struct page *rmqueue_pcplist(struct zone *preferred_zone,
int migratetype, unsigned int alloc_flags)
{
struct per_cpu_pages *pcp;
struct list_head *list;
struct page *page;
unsigned long flags;
local_irq_save(flags);
pcp = &this_cpu_ptr(zone->pageset)->pcp;
list = &pcp->lists[migratetype];
page = __rmqueue_pcplist(zone, migratetype, alloc_flags, pcp, list);
page = __rmqueue_pcplist(zone, migratetype, alloc_flags, pcp,
gfp_flags);
if (page) {
__count_zid_vm_events(PGALLOC, page_zonenum(page), 1);
zone_statistics(preferred_zone, zone);
@ -3286,14 +3348,22 @@ struct page *rmqueue(struct zone *preferred_zone,
do {
page = NULL;
if (alloc_flags & ALLOC_HARDER) {
page = __rmqueue_smallest(zone, order, MIGRATE_HIGHATOMIC);
if (page)
trace_mm_page_alloc_zone_locked(page, order, migratetype);
}
if (!page && migratetype == MIGRATE_MOVABLE &&
gfp_flags & __GFP_CMA)
page = __rmqueue_cma(zone, order, migratetype,
alloc_flags);
if (!page)
page = __rmqueue(zone, order, migratetype, alloc_flags);
} while (page && check_new_pages(page, order));
spin_unlock(&zone->lock);
if (!page)
goto failed;
@ -8442,6 +8512,9 @@ int alloc_contig_range(unsigned long start, unsigned long end,
if (ret < 0)
return ret;
#ifdef CONFIG_CMA
cc.zone->cma_alloc = 1;
#endif
/*
* In case of -EBUSY, we'd like to know which page causes problem.
* So, just fall through. test_pages_isolated() has a tracepoint
@ -8523,6 +8596,9 @@ int alloc_contig_range(unsigned long start, unsigned long end,
done:
undo_isolate_page_range(pfn_max_align_down(start),
pfn_max_align_up(end), migratetype);
#ifdef CONFIG_CMA
cc.zone->cma_alloc = 0;
#endif
return ret;
}
#endif /* CONFIG_CONTIG_ALLOC */

View file

@ -2795,6 +2795,8 @@ static u16 skb_tx_hash(const struct net_device *dev,
if (skb_rx_queue_recorded(skb)) {
hash = skb_get_rx_queue(skb);
if (hash >= qoffset)
hash -= qoffset;
while (unlikely(hash >= qcount))
hash -= qcount;
return hash + qoffset;

Some files were not shown because too many files have changed in this diff Show more