Merge remote-tracking branch 'common/android-4.9' into hikey-4.9
Change-Id: I67c2880d8bce75f1c213b1b14da023c0806a096b
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
VERSION = 4
|
||||
PATCHLEVEL = 9
|
||||
SUBLEVEL = 59
|
||||
SUBLEVEL = 60
|
||||
EXTRAVERSION =
|
||||
NAME = Roaring Lionus
|
||||
|
||||
|
||||
@@ -112,8 +112,12 @@ int dump_task_regs(struct task_struct *t, elf_gregset_t *elfregs);
|
||||
#define CORE_DUMP_USE_REGSET
|
||||
#define ELF_EXEC_PAGESIZE 4096
|
||||
|
||||
/* This is the base location for PIE (ET_DYN with INTERP) loads. */
|
||||
#define ELF_ET_DYN_BASE 0x400000UL
|
||||
/* This is the location that an ET_DYN program is loaded if exec'ed. Typical
|
||||
use of this is to invoke "./ld.so someprog" to test out a new version of
|
||||
the loader. We need to make sure that it is out of the way of the program
|
||||
that it will "exec", and that there is sufficient room for the brk. */
|
||||
|
||||
#define ELF_ET_DYN_BASE (TASK_SIZE / 3 * 2)
|
||||
|
||||
/* When the program starts, a1 contains a pointer to a function to be
|
||||
registered with atexit, as per the SVR4 ABI. A value of 0 means we
|
||||
|
||||
@@ -169,7 +169,7 @@ extern int arch_setup_additional_pages(struct linux_binprm *bprm,
|
||||
#ifdef CONFIG_COMPAT
|
||||
|
||||
/* PIE load location for compat arm. Must match ARM ELF_ET_DYN_BASE. */
|
||||
#define COMPAT_ELF_ET_DYN_BASE 0x000400000UL
|
||||
#define COMPAT_ELF_ET_DYN_BASE (2 * TASK_SIZE_32 / 3)
|
||||
|
||||
/* AArch32 registers. */
|
||||
#define COMPAT_ELF_NGREG 18
|
||||
|
||||
@@ -601,8 +601,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
|
||||
break;
|
||||
#endif
|
||||
case KVM_CAP_PPC_HTM:
|
||||
r = cpu_has_feature(CPU_FTR_TM_COMP) &&
|
||||
is_kvmppc_hv_enabled(kvm);
|
||||
r = cpu_has_feature(CPU_FTR_TM_COMP) && hv_enabled;
|
||||
break;
|
||||
default:
|
||||
r = 0;
|
||||
|
||||
@@ -825,7 +825,7 @@ uint32_t smu7_get_xclk(struct pp_hwmgr *hwmgr)
|
||||
{
|
||||
uint32_t reference_clock, tmp;
|
||||
struct cgs_display_info info = {0};
|
||||
struct cgs_mode_info mode_info;
|
||||
struct cgs_mode_info mode_info = {0};
|
||||
|
||||
info.mode_info = &mode_info;
|
||||
|
||||
@@ -3718,10 +3718,9 @@ int smu7_program_display_gap(struct pp_hwmgr *hwmgr)
|
||||
uint32_t ref_clock;
|
||||
uint32_t refresh_rate = 0;
|
||||
struct cgs_display_info info = {0};
|
||||
struct cgs_mode_info mode_info;
|
||||
struct cgs_mode_info mode_info = {0};
|
||||
|
||||
info.mode_info = &mode_info;
|
||||
|
||||
cgs_get_active_displays_info(hwmgr->device, &info);
|
||||
num_active_displays = info.display_count;
|
||||
|
||||
@@ -3737,6 +3736,7 @@ int smu7_program_display_gap(struct pp_hwmgr *hwmgr)
|
||||
frame_time_in_us = 1000000 / refresh_rate;
|
||||
|
||||
pre_vbi_time_in_us = frame_time_in_us - 200 - mode_info.vblank_time_us;
|
||||
|
||||
data->frame_time_x2 = frame_time_in_us * 2 / 100;
|
||||
|
||||
display_gap2 = pre_vbi_time_in_us * (ref_clock / 100);
|
||||
|
||||
@@ -1240,6 +1240,7 @@ static const struct acpi_device_id elan_acpi_id[] = {
|
||||
{ "ELAN0605", 0 },
|
||||
{ "ELAN0609", 0 },
|
||||
{ "ELAN060B", 0 },
|
||||
{ "ELAN0611", 0 },
|
||||
{ "ELAN1000", 0 },
|
||||
{ }
|
||||
};
|
||||
|
||||
@@ -230,13 +230,17 @@ static void parse_hid_report_descriptor(struct gtco *device, char * report,
|
||||
|
||||
/* Walk this report and pull out the info we need */
|
||||
while (i < length) {
|
||||
prefix = report[i];
|
||||
|
||||
/* Skip over prefix */
|
||||
i++;
|
||||
prefix = report[i++];
|
||||
|
||||
/* Determine data size and save the data in the proper variable */
|
||||
size = PREF_SIZE(prefix);
|
||||
size = (1U << PREF_SIZE(prefix)) >> 1;
|
||||
if (i + size > length) {
|
||||
dev_err(ddev,
|
||||
"Not enough data (need %d, have %d)\n",
|
||||
i + size, length);
|
||||
break;
|
||||
}
|
||||
|
||||
switch (size) {
|
||||
case 1:
|
||||
data = report[i];
|
||||
@@ -244,8 +248,7 @@ static void parse_hid_report_descriptor(struct gtco *device, char * report,
|
||||
case 2:
|
||||
data16 = get_unaligned_le16(&report[i]);
|
||||
break;
|
||||
case 3:
|
||||
size = 4;
|
||||
case 4:
|
||||
data32 = get_unaligned_le32(&report[i]);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -342,7 +342,7 @@ static int sun4i_can_start(struct net_device *dev)
|
||||
|
||||
/* enter the selected mode */
|
||||
mod_reg_val = readl(priv->base + SUN4I_REG_MSEL_ADDR);
|
||||
if (priv->can.ctrlmode & CAN_CTRLMODE_PRESUME_ACK)
|
||||
if (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK)
|
||||
mod_reg_val |= SUN4I_MSEL_LOOPBACK_MODE;
|
||||
else if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY)
|
||||
mod_reg_val |= SUN4I_MSEL_LISTEN_ONLY_MODE;
|
||||
@@ -811,7 +811,6 @@ static int sun4ican_probe(struct platform_device *pdev)
|
||||
priv->can.ctrlmode_supported = CAN_CTRLMODE_BERR_REPORTING |
|
||||
CAN_CTRLMODE_LISTENONLY |
|
||||
CAN_CTRLMODE_LOOPBACK |
|
||||
CAN_CTRLMODE_PRESUME_ACK |
|
||||
CAN_CTRLMODE_3_SAMPLES;
|
||||
priv->base = addr;
|
||||
priv->clk = clk;
|
||||
|
||||
@@ -137,6 +137,7 @@ static inline bool kvaser_is_usbcan(const struct usb_device_id *id)
|
||||
#define CMD_RESET_ERROR_COUNTER 49
|
||||
#define CMD_TX_ACKNOWLEDGE 50
|
||||
#define CMD_CAN_ERROR_EVENT 51
|
||||
#define CMD_FLUSH_QUEUE_REPLY 68
|
||||
|
||||
#define CMD_LEAF_USB_THROTTLE 77
|
||||
#define CMD_LEAF_LOG_MESSAGE 106
|
||||
@@ -1301,6 +1302,11 @@ static void kvaser_usb_handle_message(const struct kvaser_usb *dev,
|
||||
goto warn;
|
||||
break;
|
||||
|
||||
case CMD_FLUSH_QUEUE_REPLY:
|
||||
if (dev->family != KVASER_LEAF)
|
||||
goto warn;
|
||||
break;
|
||||
|
||||
default:
|
||||
warn: dev_warn(dev->udev->dev.parent,
|
||||
"Unhandled message (%d)\n", msg->id);
|
||||
@@ -1609,7 +1615,8 @@ static int kvaser_usb_close(struct net_device *netdev)
|
||||
if (err)
|
||||
netdev_warn(netdev, "Cannot flush queue, error %d\n", err);
|
||||
|
||||
if (kvaser_usb_send_simple_msg(dev, CMD_RESET_CHIP, priv->channel))
|
||||
err = kvaser_usb_send_simple_msg(dev, CMD_RESET_CHIP, priv->channel);
|
||||
if (err)
|
||||
netdev_warn(netdev, "Cannot reset card, error %d\n", err);
|
||||
|
||||
err = kvaser_usb_stop_chip(priv);
|
||||
|
||||
@@ -476,7 +476,10 @@ static const struct i2c_device_id fan53555_id[] = {
|
||||
.name = "fan53555",
|
||||
.driver_data = FAN53555_VENDOR_FAIRCHILD
|
||||
}, {
|
||||
.name = "syr82x",
|
||||
.name = "syr827",
|
||||
.driver_data = FAN53555_VENDOR_SILERGY
|
||||
}, {
|
||||
.name = "syr828",
|
||||
.driver_data = FAN53555_VENDOR_SILERGY
|
||||
},
|
||||
{ },
|
||||
|
||||
@@ -358,6 +358,8 @@ struct zfcp_adapter *zfcp_adapter_enqueue(struct ccw_device *ccw_device)
|
||||
|
||||
adapter->next_port_scan = jiffies;
|
||||
|
||||
adapter->erp_action.adapter = adapter;
|
||||
|
||||
if (zfcp_qdio_setup(adapter))
|
||||
goto failed;
|
||||
|
||||
@@ -514,6 +516,9 @@ struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *adapter, u64 wwpn,
|
||||
port->dev.groups = zfcp_port_attr_groups;
|
||||
port->dev.release = zfcp_port_release;
|
||||
|
||||
port->erp_action.adapter = adapter;
|
||||
port->erp_action.port = port;
|
||||
|
||||
if (dev_set_name(&port->dev, "0x%016llx", (unsigned long long)wwpn)) {
|
||||
kfree(port);
|
||||
goto err_out;
|
||||
|
||||
@@ -193,9 +193,8 @@ static struct zfcp_erp_action *zfcp_erp_setup_act(int need, u32 act_status,
|
||||
atomic_or(ZFCP_STATUS_COMMON_ERP_INUSE,
|
||||
&zfcp_sdev->status);
|
||||
erp_action = &zfcp_sdev->erp_action;
|
||||
memset(erp_action, 0, sizeof(struct zfcp_erp_action));
|
||||
erp_action->port = port;
|
||||
erp_action->sdev = sdev;
|
||||
WARN_ON_ONCE(erp_action->port != port);
|
||||
WARN_ON_ONCE(erp_action->sdev != sdev);
|
||||
if (!(atomic_read(&zfcp_sdev->status) &
|
||||
ZFCP_STATUS_COMMON_RUNNING))
|
||||
act_status |= ZFCP_STATUS_ERP_CLOSE_ONLY;
|
||||
@@ -208,8 +207,8 @@ static struct zfcp_erp_action *zfcp_erp_setup_act(int need, u32 act_status,
|
||||
zfcp_erp_action_dismiss_port(port);
|
||||
atomic_or(ZFCP_STATUS_COMMON_ERP_INUSE, &port->status);
|
||||
erp_action = &port->erp_action;
|
||||
memset(erp_action, 0, sizeof(struct zfcp_erp_action));
|
||||
erp_action->port = port;
|
||||
WARN_ON_ONCE(erp_action->port != port);
|
||||
WARN_ON_ONCE(erp_action->sdev != NULL);
|
||||
if (!(atomic_read(&port->status) & ZFCP_STATUS_COMMON_RUNNING))
|
||||
act_status |= ZFCP_STATUS_ERP_CLOSE_ONLY;
|
||||
break;
|
||||
@@ -219,7 +218,8 @@ static struct zfcp_erp_action *zfcp_erp_setup_act(int need, u32 act_status,
|
||||
zfcp_erp_action_dismiss_adapter(adapter);
|
||||
atomic_or(ZFCP_STATUS_COMMON_ERP_INUSE, &adapter->status);
|
||||
erp_action = &adapter->erp_action;
|
||||
memset(erp_action, 0, sizeof(struct zfcp_erp_action));
|
||||
WARN_ON_ONCE(erp_action->port != NULL);
|
||||
WARN_ON_ONCE(erp_action->sdev != NULL);
|
||||
if (!(atomic_read(&adapter->status) &
|
||||
ZFCP_STATUS_COMMON_RUNNING))
|
||||
act_status |= ZFCP_STATUS_ERP_CLOSE_ONLY;
|
||||
@@ -229,7 +229,11 @@ static struct zfcp_erp_action *zfcp_erp_setup_act(int need, u32 act_status,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
erp_action->adapter = adapter;
|
||||
WARN_ON_ONCE(erp_action->adapter != adapter);
|
||||
memset(&erp_action->list, 0, sizeof(erp_action->list));
|
||||
memset(&erp_action->timer, 0, sizeof(erp_action->timer));
|
||||
erp_action->step = ZFCP_ERP_STEP_UNINITIALIZED;
|
||||
erp_action->fsf_req_id = 0;
|
||||
erp_action->action = need;
|
||||
erp_action->status = act_status;
|
||||
|
||||
|
||||
@@ -115,10 +115,15 @@ static int zfcp_scsi_slave_alloc(struct scsi_device *sdev)
|
||||
struct zfcp_unit *unit;
|
||||
int npiv = adapter->connection_features & FSF_FEATURE_NPIV_MODE;
|
||||
|
||||
zfcp_sdev->erp_action.adapter = adapter;
|
||||
zfcp_sdev->erp_action.sdev = sdev;
|
||||
|
||||
port = zfcp_get_port_by_wwpn(adapter, rport->port_name);
|
||||
if (!port)
|
||||
return -ENXIO;
|
||||
|
||||
zfcp_sdev->erp_action.port = port;
|
||||
|
||||
unit = zfcp_unit_find(port, zfcp_scsi_dev_lun(sdev));
|
||||
if (unit)
|
||||
put_device(&unit->dev);
|
||||
|
||||
+1
-1
@@ -837,7 +837,7 @@ sg_fill_request_table(Sg_fd *sfp, sg_req_info_t *rinfo)
|
||||
|
||||
val = 0;
|
||||
list_for_each_entry(srp, &sfp->rq_list, entry) {
|
||||
if (val > SG_MAX_QUEUE)
|
||||
if (val >= SG_MAX_QUEUE)
|
||||
break;
|
||||
rinfo[val].req_state = srp->done + 1;
|
||||
rinfo[val].problem =
|
||||
|
||||
@@ -1215,7 +1215,7 @@ int bcm_qspi_probe(struct platform_device *pdev,
|
||||
goto qspi_probe_err;
|
||||
}
|
||||
} else {
|
||||
goto qspi_probe_err;
|
||||
goto qspi_resource_err;
|
||||
}
|
||||
|
||||
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "bspi");
|
||||
@@ -1237,7 +1237,7 @@ int bcm_qspi_probe(struct platform_device *pdev,
|
||||
qspi->base[CHIP_SELECT] = devm_ioremap_resource(dev, res);
|
||||
if (IS_ERR(qspi->base[CHIP_SELECT])) {
|
||||
ret = PTR_ERR(qspi->base[CHIP_SELECT]);
|
||||
goto qspi_probe_err;
|
||||
goto qspi_resource_err;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1245,7 +1245,7 @@ int bcm_qspi_probe(struct platform_device *pdev,
|
||||
GFP_KERNEL);
|
||||
if (!qspi->dev_ids) {
|
||||
ret = -ENOMEM;
|
||||
goto qspi_probe_err;
|
||||
goto qspi_resource_err;
|
||||
}
|
||||
|
||||
for (val = 0; val < num_irqs; val++) {
|
||||
@@ -1334,8 +1334,9 @@ qspi_reg_err:
|
||||
bcm_qspi_hw_uninit(qspi);
|
||||
clk_disable_unprepare(qspi->clk);
|
||||
qspi_probe_err:
|
||||
spi_master_put(master);
|
||||
kfree(qspi->dev_ids);
|
||||
qspi_resource_err:
|
||||
spi_master_put(master);
|
||||
return ret;
|
||||
}
|
||||
/* probe function to be called by SoC specific platform driver probe */
|
||||
|
||||
@@ -412,15 +412,25 @@ static int xhci_stop_device(struct xhci_hcd *xhci, int slot_id, int suspend)
|
||||
GFP_NOWAIT);
|
||||
if (!command) {
|
||||
spin_unlock_irqrestore(&xhci->lock, flags);
|
||||
xhci_free_command(xhci, cmd);
|
||||
return -ENOMEM;
|
||||
|
||||
ret = -ENOMEM;
|
||||
goto cmd_cleanup;
|
||||
}
|
||||
|
||||
ret = xhci_queue_stop_endpoint(xhci, command, slot_id,
|
||||
i, suspend);
|
||||
if (ret) {
|
||||
spin_unlock_irqrestore(&xhci->lock, flags);
|
||||
xhci_free_command(xhci, command);
|
||||
goto cmd_cleanup;
|
||||
}
|
||||
xhci_queue_stop_endpoint(xhci, command, slot_id, i,
|
||||
suspend);
|
||||
}
|
||||
}
|
||||
xhci_queue_stop_endpoint(xhci, cmd, slot_id, 0, suspend);
|
||||
ret = xhci_queue_stop_endpoint(xhci, cmd, slot_id, 0, suspend);
|
||||
if (ret) {
|
||||
spin_unlock_irqrestore(&xhci->lock, flags);
|
||||
goto cmd_cleanup;
|
||||
}
|
||||
|
||||
xhci_ring_cmd_db(xhci);
|
||||
spin_unlock_irqrestore(&xhci->lock, flags);
|
||||
|
||||
@@ -431,6 +441,8 @@ static int xhci_stop_device(struct xhci_hcd *xhci, int slot_id, int suspend)
|
||||
xhci_warn(xhci, "Timeout while waiting for stop endpoint command\n");
|
||||
ret = -ETIME;
|
||||
}
|
||||
|
||||
cmd_cleanup:
|
||||
xhci_free_command(xhci, cmd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1030,6 +1030,7 @@ static int gntdev_mmap(struct file *flip, struct vm_area_struct *vma)
|
||||
mutex_unlock(&priv->lock);
|
||||
|
||||
if (use_ptemod) {
|
||||
map->pages_vm_start = vma->vm_start;
|
||||
err = apply_to_page_range(vma->vm_mm, vma->vm_start,
|
||||
vma->vm_end - vma->vm_start,
|
||||
find_grant_ptes, map);
|
||||
@@ -1067,7 +1068,6 @@ static int gntdev_mmap(struct file *flip, struct vm_area_struct *vma)
|
||||
set_grant_ptes_as_special, NULL);
|
||||
}
|
||||
#endif
|
||||
map->pages_vm_start = vma->vm_start;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
+4
-1
@@ -1900,6 +1900,7 @@ static int try_flush_caps(struct inode *inode, u64 *ptid)
|
||||
retry:
|
||||
spin_lock(&ci->i_ceph_lock);
|
||||
if (ci->i_ceph_flags & CEPH_I_NOFLUSH) {
|
||||
spin_unlock(&ci->i_ceph_lock);
|
||||
dout("try_flush_caps skipping %p I_NOFLUSH set\n", inode);
|
||||
goto out;
|
||||
}
|
||||
@@ -1917,8 +1918,10 @@ retry:
|
||||
mutex_lock(&session->s_mutex);
|
||||
goto retry;
|
||||
}
|
||||
if (cap->session->s_state < CEPH_MDS_SESSION_OPEN)
|
||||
if (cap->session->s_state < CEPH_MDS_SESSION_OPEN) {
|
||||
spin_unlock(&ci->i_ceph_lock);
|
||||
goto out;
|
||||
}
|
||||
|
||||
flushing = __mark_caps_flushing(inode, session, true,
|
||||
&flush_tid, &oldest_flush_tid);
|
||||
|
||||
@@ -84,11 +84,16 @@ struct ecryptfs_page_crypt_context {
|
||||
static inline struct ecryptfs_auth_tok *
|
||||
ecryptfs_get_encrypted_key_payload_data(struct key *key)
|
||||
{
|
||||
if (key->type == &key_type_encrypted)
|
||||
return (struct ecryptfs_auth_tok *)
|
||||
(&((struct encrypted_key_payload *)key->payload.data[0])->payload_data);
|
||||
else
|
||||
struct encrypted_key_payload *payload;
|
||||
|
||||
if (key->type != &key_type_encrypted)
|
||||
return NULL;
|
||||
|
||||
payload = key->payload.data[0];
|
||||
if (!payload)
|
||||
return ERR_PTR(-EKEYREVOKED);
|
||||
|
||||
return (struct ecryptfs_auth_tok *)payload->payload_data;
|
||||
}
|
||||
|
||||
static inline struct key *ecryptfs_get_encrypted_key(char *sig)
|
||||
@@ -114,12 +119,17 @@ static inline struct ecryptfs_auth_tok *
|
||||
ecryptfs_get_key_payload_data(struct key *key)
|
||||
{
|
||||
struct ecryptfs_auth_tok *auth_tok;
|
||||
const struct user_key_payload *ukp;
|
||||
|
||||
auth_tok = ecryptfs_get_encrypted_key_payload_data(key);
|
||||
if (!auth_tok)
|
||||
return (struct ecryptfs_auth_tok *)user_key_payload_locked(key)->data;
|
||||
else
|
||||
if (auth_tok)
|
||||
return auth_tok;
|
||||
|
||||
ukp = user_key_payload_locked(key);
|
||||
if (!ukp)
|
||||
return ERR_PTR(-EKEYREVOKED);
|
||||
|
||||
return (struct ecryptfs_auth_tok *)ukp->data;
|
||||
}
|
||||
|
||||
#define ECRYPTFS_MAX_KEYSET_SIZE 1024
|
||||
|
||||
@@ -459,7 +459,8 @@ out:
|
||||
* @auth_tok_key: key containing the authentication token
|
||||
* @auth_tok: authentication token
|
||||
*
|
||||
* Returns zero on valid auth tok; -EINVAL otherwise
|
||||
* Returns zero on valid auth tok; -EINVAL if the payload is invalid; or
|
||||
* -EKEYREVOKED if the key was revoked before we acquired its semaphore.
|
||||
*/
|
||||
static int
|
||||
ecryptfs_verify_auth_tok_from_key(struct key *auth_tok_key,
|
||||
@@ -468,6 +469,12 @@ ecryptfs_verify_auth_tok_from_key(struct key *auth_tok_key,
|
||||
int rc = 0;
|
||||
|
||||
(*auth_tok) = ecryptfs_get_key_payload_data(auth_tok_key);
|
||||
if (IS_ERR(*auth_tok)) {
|
||||
rc = PTR_ERR(*auth_tok);
|
||||
*auth_tok = NULL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (ecryptfs_verify_version((*auth_tok)->version)) {
|
||||
printk(KERN_ERR "Data structure version mismatch. Userspace "
|
||||
"tools must match eCryptfs kernel module with major "
|
||||
|
||||
+2
-1
@@ -1358,7 +1358,8 @@ static int parse_dirplusfile(char *buf, size_t nbytes, struct file *file,
|
||||
*/
|
||||
over = !dir_emit(ctx, dirent->name, dirent->namelen,
|
||||
dirent->ino, dirent->type);
|
||||
ctx->pos = dirent->off;
|
||||
if (!over)
|
||||
ctx->pos = dirent->off;
|
||||
}
|
||||
|
||||
buf += reclen;
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#define SPIDEV_H
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/ioctl.h>
|
||||
|
||||
/* User space versions of kernel symbols for SPI clocking modes,
|
||||
* matching <linux/spi/spi.h>
|
||||
|
||||
@@ -2618,6 +2618,7 @@ void wake_up_new_task(struct task_struct *p)
|
||||
__set_task_cpu(p, select_task_rq(p, task_cpu(p), SD_BALANCE_FORK, 0));
|
||||
#endif
|
||||
rq = __task_rq_lock(p, &rf);
|
||||
update_rq_clock(rq);
|
||||
post_init_entity_util_avg(&p->se);
|
||||
|
||||
walt_mark_task_starting(p);
|
||||
@@ -3175,7 +3176,9 @@ static void sched_freq_tick_pelt(int cpu)
|
||||
* utilization and to harm its performance the least, request
|
||||
* a jump to a higher OPP as soon as the margin of free capacity
|
||||
* is impacted (specified by capacity_margin).
|
||||
* Remember CPU utilization in sched_capacity_reqs should be normalised.
|
||||
*/
|
||||
cpu_utilization = cpu_utilization * SCHED_CAPACITY_SCALE / capacity_orig_of(cpu);
|
||||
set_cfs_cpu_capacity(cpu, true, cpu_utilization);
|
||||
}
|
||||
|
||||
@@ -3202,7 +3205,9 @@ static void sched_freq_tick_walt(int cpu)
|
||||
* It is likely that the load is growing so we
|
||||
* keep the added margin in our request as an
|
||||
* extra boost.
|
||||
* Remember CPU utilization in sched_capacity_reqs should be normalised.
|
||||
*/
|
||||
cpu_utilization = cpu_utilization * SCHED_CAPACITY_SCALE / capacity_orig_of(cpu);
|
||||
set_cfs_cpu_capacity(cpu, true, cpu_utilization);
|
||||
|
||||
}
|
||||
@@ -3819,6 +3824,7 @@ void rt_mutex_setprio(struct task_struct *p, int prio)
|
||||
BUG_ON(prio > MAX_PRIO);
|
||||
|
||||
rq = __task_rq_lock(p, &rf);
|
||||
update_rq_clock(rq);
|
||||
|
||||
/*
|
||||
* Idle task boosting is a nono in general. There is one
|
||||
@@ -3915,6 +3921,8 @@ void set_user_nice(struct task_struct *p, long nice)
|
||||
* the task might be in the middle of scheduling on another CPU.
|
||||
*/
|
||||
rq = task_rq_lock(p, &rf);
|
||||
update_rq_clock(rq);
|
||||
|
||||
/*
|
||||
* The RT priorities are set via sched_setscheduler(), but we still
|
||||
* allow the 'normal' nice value to be set - but as expected
|
||||
@@ -4347,6 +4355,7 @@ recheck:
|
||||
* runqueue lock must be held.
|
||||
*/
|
||||
rq = task_rq_lock(p, &rf);
|
||||
update_rq_clock(rq);
|
||||
|
||||
/*
|
||||
* Changing the policy of the stop threads its a very bad idea
|
||||
@@ -8697,6 +8706,7 @@ static void cpu_cgroup_fork(struct task_struct *task)
|
||||
|
||||
rq = task_rq_lock(task, &rf);
|
||||
|
||||
update_rq_clock(rq);
|
||||
sched_change_group(task, TASK_SET_GROUP);
|
||||
|
||||
task_rq_unlock(rq, task, &rf);
|
||||
|
||||
@@ -202,7 +202,7 @@ static void update_fdomain_capacity_request(int cpu)
|
||||
}
|
||||
|
||||
/* Convert the new maximum capacity request into a cpu frequency */
|
||||
freq_new = capacity * policy->max >> SCHED_CAPACITY_SHIFT;
|
||||
freq_new = capacity * policy->cpuinfo.max_freq >> SCHED_CAPACITY_SHIFT;
|
||||
index_new = cpufreq_frequency_table_target(policy, freq_new, CPUFREQ_RELATION_L);
|
||||
freq_new = policy->freq_table[index_new].frequency;
|
||||
|
||||
|
||||
+217
-117
@@ -4803,7 +4803,7 @@ static void update_capacity_of(int cpu)
|
||||
if (!sched_freq())
|
||||
return;
|
||||
|
||||
/* Convert scale-invariant capacity to cpu. */
|
||||
/* Normalize scale-invariant capacity to cpu. */
|
||||
req_cap = boosted_cpu_util(cpu);
|
||||
req_cap = req_cap * SCHED_CAPACITY_SCALE / capacity_orig_of(cpu);
|
||||
set_cfs_cpu_capacity(cpu, true, req_cap);
|
||||
@@ -4996,7 +4996,7 @@ static void dequeue_task_fair(struct rq *rq, struct task_struct *p, int flags)
|
||||
if (rq->cfs.nr_running)
|
||||
update_capacity_of(cpu_of(rq));
|
||||
else if (sched_freq())
|
||||
set_cfs_cpu_capacity(cpu_of(rq), false, 0);
|
||||
set_cfs_cpu_capacity(cpu_of(rq), false, 0); /* no normalization required for 0 */
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5481,6 +5481,7 @@ struct energy_env {
|
||||
int util_delta;
|
||||
int src_cpu;
|
||||
int dst_cpu;
|
||||
int trg_cpu;
|
||||
int energy;
|
||||
int payoff;
|
||||
struct task_struct *task;
|
||||
@@ -5497,11 +5498,14 @@ struct energy_env {
|
||||
} cap;
|
||||
};
|
||||
|
||||
static int cpu_util_wake(int cpu, struct task_struct *p);
|
||||
|
||||
/*
|
||||
* __cpu_norm_util() returns the cpu util relative to a specific capacity,
|
||||
* i.e. it's busy ratio, in the range [0..SCHED_LOAD_SCALE] which is useful for
|
||||
* energy calculations. Using the scale-invariant util returned by
|
||||
* cpu_util() and approximating scale-invariant util by:
|
||||
* i.e. it's busy ratio, in the range [0..SCHED_LOAD_SCALE], which is useful for
|
||||
* energy calculations.
|
||||
*
|
||||
* Since util is a scale-invariant utilization defined as:
|
||||
*
|
||||
* util ~ (curr_freq/max_freq)*1024 * capacity_orig/1024 * running_time/time
|
||||
*
|
||||
@@ -5511,34 +5515,32 @@ struct energy_env {
|
||||
*
|
||||
* norm_util = running_time/time ~ util/capacity
|
||||
*/
|
||||
static unsigned long __cpu_norm_util(int cpu, unsigned long capacity, int delta)
|
||||
static unsigned long __cpu_norm_util(unsigned long util, unsigned long capacity)
|
||||
{
|
||||
int util = __cpu_util(cpu, delta);
|
||||
|
||||
if (util >= capacity)
|
||||
return SCHED_CAPACITY_SCALE;
|
||||
|
||||
return (util << SCHED_CAPACITY_SHIFT)/capacity;
|
||||
}
|
||||
|
||||
static int calc_util_delta(struct energy_env *eenv, int cpu)
|
||||
static unsigned long group_max_util(struct energy_env *eenv)
|
||||
{
|
||||
if (cpu == eenv->src_cpu)
|
||||
return -eenv->util_delta;
|
||||
if (cpu == eenv->dst_cpu)
|
||||
return eenv->util_delta;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
unsigned long group_max_util(struct energy_env *eenv)
|
||||
{
|
||||
int i, delta;
|
||||
unsigned long max_util = 0;
|
||||
unsigned long util;
|
||||
int cpu;
|
||||
|
||||
for_each_cpu(i, sched_group_cpus(eenv->sg_cap)) {
|
||||
delta = calc_util_delta(eenv, i);
|
||||
max_util = max(max_util, __cpu_util(i, delta));
|
||||
for_each_cpu(cpu, sched_group_cpus(eenv->sg_cap)) {
|
||||
util = cpu_util_wake(cpu, eenv->task);
|
||||
|
||||
/*
|
||||
* If we are looking at the target CPU specified by the eenv,
|
||||
* then we should add the (estimated) utilization of the task
|
||||
* assuming we will wake it up on that CPU.
|
||||
*/
|
||||
if (unlikely(cpu == eenv->trg_cpu))
|
||||
util += eenv->util_delta;
|
||||
|
||||
max_util = max(max_util, util);
|
||||
}
|
||||
|
||||
return max_util;
|
||||
@@ -5546,44 +5548,56 @@ unsigned long group_max_util(struct energy_env *eenv)
|
||||
|
||||
/*
|
||||
* group_norm_util() returns the approximated group util relative to it's
|
||||
* current capacity (busy ratio) in the range [0..SCHED_LOAD_SCALE] for use in
|
||||
* energy calculations. Since task executions may or may not overlap in time in
|
||||
* the group the true normalized util is between max(cpu_norm_util(i)) and
|
||||
* sum(cpu_norm_util(i)) when iterating over all cpus in the group, i. The
|
||||
* latter is used as the estimate as it leads to a more pessimistic energy
|
||||
* current capacity (busy ratio), in the range [0..SCHED_LOAD_SCALE], for use
|
||||
* in energy calculations.
|
||||
*
|
||||
* Since task executions may or may not overlap in time in the group the true
|
||||
* normalized util is between MAX(cpu_norm_util(i)) and SUM(cpu_norm_util(i))
|
||||
* when iterating over all CPUs in the group.
|
||||
* The latter estimate is used as it leads to a more pessimistic energy
|
||||
* estimate (more busy).
|
||||
*/
|
||||
static unsigned
|
||||
long group_norm_util(struct energy_env *eenv, struct sched_group *sg)
|
||||
{
|
||||
int i, delta;
|
||||
unsigned long util_sum = 0;
|
||||
unsigned long capacity = sg->sge->cap_states[eenv->cap_idx].cap;
|
||||
unsigned long util, util_sum = 0;
|
||||
int cpu;
|
||||
|
||||
for_each_cpu(i, sched_group_cpus(sg)) {
|
||||
delta = calc_util_delta(eenv, i);
|
||||
util_sum += __cpu_norm_util(i, capacity, delta);
|
||||
for_each_cpu(cpu, sched_group_cpus(sg)) {
|
||||
util = cpu_util_wake(cpu, eenv->task);
|
||||
|
||||
/*
|
||||
* If we are looking at the target CPU specified by the eenv,
|
||||
* then we should add the (estimated) utilization of the task
|
||||
* assuming we will wake it up on that CPU.
|
||||
*/
|
||||
if (unlikely(cpu == eenv->trg_cpu))
|
||||
util += eenv->util_delta;
|
||||
|
||||
util_sum += __cpu_norm_util(util, capacity);
|
||||
}
|
||||
|
||||
if (util_sum > SCHED_CAPACITY_SCALE)
|
||||
return SCHED_CAPACITY_SCALE;
|
||||
return util_sum;
|
||||
return min_t(unsigned long, util_sum, SCHED_CAPACITY_SCALE);
|
||||
}
|
||||
|
||||
static int find_new_capacity(struct energy_env *eenv,
|
||||
const struct sched_group_energy * const sge)
|
||||
{
|
||||
int idx;
|
||||
int idx, max_idx = sge->nr_cap_states - 1;
|
||||
unsigned long util = group_max_util(eenv);
|
||||
|
||||
/* default is max_cap if we don't find a match */
|
||||
eenv->cap_idx = max_idx;
|
||||
|
||||
for (idx = 0; idx < sge->nr_cap_states; idx++) {
|
||||
if (sge->cap_states[idx].cap >= util)
|
||||
if (sge->cap_states[idx].cap >= util) {
|
||||
eenv->cap_idx = idx;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
eenv->cap_idx = idx;
|
||||
|
||||
return idx;
|
||||
return eenv->cap_idx;
|
||||
}
|
||||
|
||||
static int group_idle_state(struct energy_env *eenv, struct sched_group *sg)
|
||||
@@ -5706,13 +5720,13 @@ static int sched_group_energy(struct energy_env *eenv)
|
||||
|
||||
if (sg->group_weight == 1) {
|
||||
/* Remove capacity of src CPU (before task move) */
|
||||
if (eenv->util_delta == 0 &&
|
||||
if (eenv->trg_cpu == eenv->src_cpu &&
|
||||
cpumask_test_cpu(eenv->src_cpu, sched_group_cpus(sg))) {
|
||||
eenv->cap.before = sg->sge->cap_states[cap_idx].cap;
|
||||
eenv->cap.delta -= eenv->cap.before;
|
||||
}
|
||||
/* Add capacity of dst CPU (after task move) */
|
||||
if (eenv->util_delta != 0 &&
|
||||
if (eenv->trg_cpu == eenv->dst_cpu &&
|
||||
cpumask_test_cpu(eenv->dst_cpu, sched_group_cpus(sg))) {
|
||||
eenv->cap.after = sg->sge->cap_states[cap_idx].cap;
|
||||
eenv->cap.delta += eenv->cap.after;
|
||||
@@ -5760,6 +5774,8 @@ static inline bool cpu_in_sg(struct sched_group *sg, int cpu)
|
||||
return cpu != -1 && cpumask_test_cpu(cpu, sched_group_cpus(sg));
|
||||
}
|
||||
|
||||
static inline unsigned long task_util(struct task_struct *p);
|
||||
|
||||
/*
|
||||
* energy_diff(): Estimate the energy impact of changing the utilization
|
||||
* distribution. eenv specifies the change: utilisation amount, source, and
|
||||
@@ -5775,11 +5791,13 @@ static inline int __energy_diff(struct energy_env *eenv)
|
||||
int diff, margin;
|
||||
|
||||
struct energy_env eenv_before = {
|
||||
.util_delta = 0,
|
||||
.util_delta = task_util(eenv->task),
|
||||
.src_cpu = eenv->src_cpu,
|
||||
.dst_cpu = eenv->dst_cpu,
|
||||
.trg_cpu = eenv->src_cpu,
|
||||
.nrg = { 0, 0, 0, 0},
|
||||
.cap = { 0, 0, 0 },
|
||||
.task = eenv->task,
|
||||
};
|
||||
|
||||
if (eenv->src_cpu == eenv->dst_cpu)
|
||||
@@ -5887,8 +5905,14 @@ energy_diff(struct energy_env *eenv)
|
||||
__energy_diff(eenv);
|
||||
|
||||
/* Return energy diff when boost margin is 0 */
|
||||
if (boost == 0)
|
||||
if (boost == 0) {
|
||||
trace_sched_energy_diff(eenv->task,
|
||||
eenv->src_cpu, eenv->dst_cpu, eenv->util_delta,
|
||||
eenv->nrg.before, eenv->nrg.after, eenv->nrg.diff,
|
||||
eenv->cap.before, eenv->cap.after, eenv->cap.delta,
|
||||
0, -eenv->nrg.diff);
|
||||
return eenv->nrg.diff;
|
||||
}
|
||||
|
||||
/* Compute normalized energy diff */
|
||||
nrg_delta = normalize_energy(eenv->nrg.diff);
|
||||
@@ -6151,8 +6175,6 @@ boosted_task_util(struct task_struct *task)
|
||||
return util + margin;
|
||||
}
|
||||
|
||||
static int cpu_util_wake(int cpu, struct task_struct *p);
|
||||
|
||||
static unsigned long capacity_spare_wake(int cpu, struct task_struct *p)
|
||||
{
|
||||
return capacity_orig_of(cpu) - cpu_util_wake(cpu, p);
|
||||
@@ -6161,6 +6183,8 @@ static unsigned long capacity_spare_wake(int cpu, struct task_struct *p)
|
||||
/*
|
||||
* find_idlest_group finds and returns the least busy CPU group within the
|
||||
* domain.
|
||||
*
|
||||
* Assumes p is allowed on at least one CPU in sd.
|
||||
*/
|
||||
static struct sched_group *
|
||||
find_idlest_group(struct sched_domain *sd, struct task_struct *p,
|
||||
@@ -6168,16 +6192,21 @@ find_idlest_group(struct sched_domain *sd, struct task_struct *p,
|
||||
{
|
||||
struct sched_group *idlest = NULL, *group = sd->groups;
|
||||
struct sched_group *most_spare_sg = NULL;
|
||||
unsigned long min_load = ULONG_MAX, this_load = 0;
|
||||
unsigned long min_runnable_load = ULONG_MAX;
|
||||
unsigned long this_runnable_load = ULONG_MAX;
|
||||
unsigned long min_avg_load = ULONG_MAX, this_avg_load = ULONG_MAX;
|
||||
unsigned long most_spare = 0, this_spare = 0;
|
||||
int load_idx = sd->forkexec_idx;
|
||||
int imbalance = 100 + (sd->imbalance_pct-100)/2;
|
||||
int imbalance_scale = 100 + (sd->imbalance_pct-100)/2;
|
||||
unsigned long imbalance = scale_load_down(NICE_0_LOAD) *
|
||||
(sd->imbalance_pct-100) / 100;
|
||||
|
||||
if (sd_flag & SD_BALANCE_WAKE)
|
||||
load_idx = sd->wake_idx;
|
||||
|
||||
do {
|
||||
unsigned long load, avg_load, spare_cap, max_spare_cap;
|
||||
unsigned long load, avg_load, runnable_load;
|
||||
unsigned long spare_cap, max_spare_cap;
|
||||
int local_group;
|
||||
int i;
|
||||
|
||||
@@ -6194,6 +6223,7 @@ find_idlest_group(struct sched_domain *sd, struct task_struct *p,
|
||||
* the group containing the CPU with most spare capacity.
|
||||
*/
|
||||
avg_load = 0;
|
||||
runnable_load = 0;
|
||||
max_spare_cap = 0;
|
||||
|
||||
for_each_cpu(i, sched_group_cpus(group)) {
|
||||
@@ -6203,7 +6233,9 @@ find_idlest_group(struct sched_domain *sd, struct task_struct *p,
|
||||
else
|
||||
load = target_load(i, load_idx);
|
||||
|
||||
avg_load += load;
|
||||
runnable_load += load;
|
||||
|
||||
avg_load += cfs_rq_load_avg(&cpu_rq(i)->cfs);
|
||||
|
||||
spare_cap = capacity_spare_wake(i, p);
|
||||
|
||||
@@ -6212,14 +6244,32 @@ find_idlest_group(struct sched_domain *sd, struct task_struct *p,
|
||||
}
|
||||
|
||||
/* Adjust by relative CPU capacity of the group */
|
||||
avg_load = (avg_load * SCHED_CAPACITY_SCALE) / group->sgc->capacity;
|
||||
avg_load = (avg_load * SCHED_CAPACITY_SCALE) /
|
||||
group->sgc->capacity;
|
||||
runnable_load = (runnable_load * SCHED_CAPACITY_SCALE) /
|
||||
group->sgc->capacity;
|
||||
|
||||
if (local_group) {
|
||||
this_load = avg_load;
|
||||
this_runnable_load = runnable_load;
|
||||
this_avg_load = avg_load;
|
||||
this_spare = max_spare_cap;
|
||||
} else {
|
||||
if (avg_load < min_load) {
|
||||
min_load = avg_load;
|
||||
if (min_runnable_load > (runnable_load + imbalance)) {
|
||||
/*
|
||||
* The runnable load is significantly smaller
|
||||
* so we can pick this new cpu
|
||||
*/
|
||||
min_runnable_load = runnable_load;
|
||||
min_avg_load = avg_load;
|
||||
idlest = group;
|
||||
} else if ((runnable_load < (min_runnable_load + imbalance)) &&
|
||||
(100*min_avg_load > imbalance_scale*avg_load)) {
|
||||
/*
|
||||
* The runnable loads are close so we take
|
||||
* into account blocked load through avg_load
|
||||
* which is blocked + runnable load
|
||||
*/
|
||||
min_avg_load = avg_load;
|
||||
idlest = group;
|
||||
}
|
||||
|
||||
@@ -6236,23 +6286,32 @@ find_idlest_group(struct sched_domain *sd, struct task_struct *p,
|
||||
* utilized systems if we require spare_capacity > task_util(p),
|
||||
* so we allow for some task stuffing by using
|
||||
* spare_capacity > task_util(p)/2.
|
||||
* spare capacity can't be used for fork because the utilization has
|
||||
* not been set yet as it need to get a rq to init the utilization
|
||||
*/
|
||||
if (sd_flag & SD_BALANCE_FORK)
|
||||
goto skip_spare;
|
||||
|
||||
if (this_spare > task_util(p) / 2 &&
|
||||
imbalance*this_spare > 100*most_spare)
|
||||
imbalance_scale*this_spare > 100*most_spare)
|
||||
return NULL;
|
||||
else if (most_spare > task_util(p) / 2)
|
||||
return most_spare_sg;
|
||||
|
||||
if (!idlest || 100*this_load < imbalance*min_load)
|
||||
skip_spare:
|
||||
if (!idlest ||
|
||||
(min_runnable_load > (this_runnable_load + imbalance)) ||
|
||||
((this_runnable_load < (min_runnable_load + imbalance)) &&
|
||||
(100*this_avg_load < imbalance_scale*min_avg_load)))
|
||||
return NULL;
|
||||
return idlest;
|
||||
}
|
||||
|
||||
/*
|
||||
* find_idlest_cpu - find the idlest cpu among the cpus in group.
|
||||
* find_idlest_group_cpu - find the idlest cpu among the cpus in group.
|
||||
*/
|
||||
static int
|
||||
find_idlest_cpu(struct sched_group *group, struct task_struct *p, int this_cpu)
|
||||
find_idlest_group_cpu(struct sched_group *group, struct task_struct *p, int this_cpu)
|
||||
{
|
||||
unsigned long load, min_load = ULONG_MAX;
|
||||
unsigned int min_exit_latency = UINT_MAX;
|
||||
@@ -6301,6 +6360,68 @@ find_idlest_cpu(struct sched_group *group, struct task_struct *p, int this_cpu)
|
||||
return shallowest_idle_cpu != -1 ? shallowest_idle_cpu : least_loaded_cpu;
|
||||
}
|
||||
|
||||
static inline int find_idlest_cpu(struct sched_domain *sd, struct task_struct *p,
|
||||
int cpu, int prev_cpu, int sd_flag)
|
||||
{
|
||||
int wu = sd_flag & SD_BALANCE_WAKE;
|
||||
int cas_cpu = -1;
|
||||
int new_cpu = cpu;
|
||||
|
||||
if (wu) {
|
||||
schedstat_inc(p->se.statistics.nr_wakeups_cas_attempts);
|
||||
schedstat_inc(this_rq()->eas_stats.cas_attempts);
|
||||
}
|
||||
|
||||
if (!cpumask_intersects(sched_domain_span(sd), &p->cpus_allowed))
|
||||
return prev_cpu;
|
||||
|
||||
while (sd) {
|
||||
struct sched_group *group;
|
||||
struct sched_domain *tmp;
|
||||
int weight;
|
||||
|
||||
if (wu)
|
||||
schedstat_inc(sd->eas_stats.cas_attempts);
|
||||
|
||||
if (!(sd->flags & sd_flag)) {
|
||||
sd = sd->child;
|
||||
continue;
|
||||
}
|
||||
|
||||
group = find_idlest_group(sd, p, cpu, sd_flag);
|
||||
if (!group) {
|
||||
sd = sd->child;
|
||||
continue;
|
||||
}
|
||||
|
||||
new_cpu = find_idlest_group_cpu(group, p, cpu);
|
||||
if (new_cpu == cpu) {
|
||||
/* Now try balancing at a lower domain level of cpu */
|
||||
sd = sd->child;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Now try balancing at a lower domain level of new_cpu */
|
||||
cpu = cas_cpu = new_cpu;
|
||||
weight = sd->span_weight;
|
||||
sd = NULL;
|
||||
for_each_domain(cpu, tmp) {
|
||||
if (weight <= tmp->span_weight)
|
||||
break;
|
||||
if (tmp->flags & sd_flag)
|
||||
sd = tmp;
|
||||
}
|
||||
/* while loop will break here if sd == NULL */
|
||||
}
|
||||
|
||||
if (wu && (cas_cpu >= 0)) {
|
||||
schedstat_inc(p->se.statistics.nr_wakeups_cas_count);
|
||||
schedstat_inc(this_rq()->eas_stats.cas_count);
|
||||
}
|
||||
|
||||
return new_cpu;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SCHED_SMT
|
||||
|
||||
static inline void set_idle_cores(int cpu, int val)
|
||||
@@ -6605,9 +6726,6 @@ static int start_cpu(bool boosted)
|
||||
{
|
||||
struct root_domain *rd = cpu_rq(smp_processor_id())->rd;
|
||||
|
||||
RCU_LOCKDEP_WARN(rcu_read_lock_sched_held(),
|
||||
"sched RCU must be held");
|
||||
|
||||
return boosted ? rd->max_cap_orig_cpu : rd->min_cap_orig_cpu;
|
||||
}
|
||||
|
||||
@@ -6757,6 +6875,19 @@ static inline int find_best_target(struct task_struct *p, int *backup_cpu,
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Enforce EAS mode
|
||||
*
|
||||
* For non latency sensitive tasks, skip CPUs that
|
||||
* will be overutilized by moving the task there.
|
||||
*
|
||||
* The goal here is to remain in EAS mode as long as
|
||||
* possible at least for !prefer_idle tasks.
|
||||
*/
|
||||
if ((new_util * capacity_margin) >
|
||||
(capacity_orig * SCHED_CAPACITY_SCALE))
|
||||
continue;
|
||||
|
||||
/*
|
||||
* Case B) Non latency sensitive tasks on IDLE CPUs.
|
||||
*
|
||||
@@ -6953,6 +7084,7 @@ static int select_energy_cpu_brute(struct task_struct *p, int prev_cpu, int sync
|
||||
.src_cpu = prev_cpu,
|
||||
.dst_cpu = target_cpu,
|
||||
.task = p,
|
||||
.trg_cpu = target_cpu,
|
||||
};
|
||||
|
||||
/* Not enough spare capacity on previous cpu */
|
||||
@@ -6966,7 +7098,10 @@ static int select_energy_cpu_brute(struct task_struct *p, int prev_cpu, int sync
|
||||
/* No energy saving for target_cpu, try backup */
|
||||
target_cpu = tmp_backup;
|
||||
eenv.dst_cpu = target_cpu;
|
||||
if (tmp_backup < 0 || energy_diff(&eenv) >= 0) {
|
||||
eenv.trg_cpu = target_cpu;
|
||||
if (tmp_backup < 0 ||
|
||||
tmp_backup == prev_cpu ||
|
||||
energy_diff(&eenv) >= 0) {
|
||||
schedstat_inc(p->se.statistics.nr_wakeups_secb_no_nrg_sav);
|
||||
schedstat_inc(this_rq()->eas_stats.secb_no_nrg_sav);
|
||||
target_cpu = prev_cpu;
|
||||
@@ -7044,62 +7179,21 @@ select_task_rq_fair(struct task_struct *p, int prev_cpu, int sd_flag, int wake_f
|
||||
new_cpu = cpu;
|
||||
}
|
||||
|
||||
if (sd && !(sd_flag & SD_BALANCE_FORK)) {
|
||||
/*
|
||||
* We're going to need the task's util for capacity_spare_wake
|
||||
* in find_idlest_group. Sync it up to prev_cpu's
|
||||
* last_update_time.
|
||||
*/
|
||||
sync_entity_load_avg(&p->se);
|
||||
}
|
||||
|
||||
if (!sd) {
|
||||
if (sd_flag & SD_BALANCE_WAKE) /* XXX always ? */
|
||||
new_cpu = select_idle_sibling(p, prev_cpu, new_cpu);
|
||||
|
||||
} else {
|
||||
int wu = sd_flag & SD_BALANCE_WAKE;
|
||||
int cas_cpu = -1;
|
||||
|
||||
if (wu) {
|
||||
schedstat_inc(p->se.statistics.nr_wakeups_cas_attempts);
|
||||
schedstat_inc(this_rq()->eas_stats.cas_attempts);
|
||||
}
|
||||
|
||||
|
||||
while (sd) {
|
||||
struct sched_group *group;
|
||||
int weight;
|
||||
|
||||
if (wu)
|
||||
schedstat_inc(sd->eas_stats.cas_attempts);
|
||||
|
||||
if (!(sd->flags & sd_flag)) {
|
||||
sd = sd->child;
|
||||
continue;
|
||||
}
|
||||
|
||||
group = find_idlest_group(sd, p, cpu, sd_flag);
|
||||
if (!group) {
|
||||
sd = sd->child;
|
||||
continue;
|
||||
}
|
||||
|
||||
new_cpu = find_idlest_cpu(group, p, cpu);
|
||||
if (new_cpu == -1 || new_cpu == cpu) {
|
||||
/* Now try balancing at a lower domain level of cpu */
|
||||
sd = sd->child;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Now try balancing at a lower domain level of new_cpu */
|
||||
cpu = cas_cpu = new_cpu;
|
||||
weight = sd->span_weight;
|
||||
sd = NULL;
|
||||
for_each_domain(cpu, tmp) {
|
||||
if (weight <= tmp->span_weight)
|
||||
break;
|
||||
if (tmp->flags & sd_flag)
|
||||
sd = tmp;
|
||||
}
|
||||
/* while loop will break here if sd == NULL */
|
||||
}
|
||||
|
||||
if (wu && (cas_cpu >= 0)) {
|
||||
schedstat_inc(p->se.statistics.nr_wakeups_cas_count);
|
||||
schedstat_inc(this_rq()->eas_stats.cas_count);
|
||||
}
|
||||
new_cpu = find_idlest_cpu(sd, p, cpu, prev_cpu, sd_flag);
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
@@ -9077,8 +9171,11 @@ static struct sched_group *find_busiest_group(struct lb_env *env)
|
||||
if (busiest->group_type == group_imbalanced)
|
||||
goto force_balance;
|
||||
|
||||
/* SD_BALANCE_NEWIDLE trumps SMP nice when underutilized */
|
||||
if (env->idle == CPU_NEWLY_IDLE && group_has_capacity(env, local) &&
|
||||
/*
|
||||
* When dst_cpu is idle, prevent SMP nice and/or asymmetric group
|
||||
* capacities from resulting in underutilization due to avg_load.
|
||||
*/
|
||||
if (env->idle != CPU_NOT_IDLE && group_has_capacity(env, local) &&
|
||||
busiest->group_no_capacity)
|
||||
goto force_balance;
|
||||
|
||||
@@ -9364,6 +9461,7 @@ redo:
|
||||
|
||||
more_balance:
|
||||
raw_spin_lock_irqsave(&busiest->lock, flags);
|
||||
update_rq_clock(busiest);
|
||||
|
||||
/*
|
||||
* cur_ld_moved - load moved in current iteration
|
||||
@@ -9756,6 +9854,7 @@ static int active_load_balance_cpu_stop(void *data)
|
||||
};
|
||||
|
||||
schedstat_inc(sd->alb_count);
|
||||
update_rq_clock(busiest_rq);
|
||||
|
||||
p = detach_one_task(&env);
|
||||
if (p) {
|
||||
@@ -10584,7 +10683,8 @@ void online_fair_sched_group(struct task_group *tg)
|
||||
se = tg->se[i];
|
||||
|
||||
raw_spin_lock_irq(&rq->lock);
|
||||
post_init_entity_util_avg(se);
|
||||
update_rq_clock(rq);
|
||||
attach_entity_cfs_rq(se);
|
||||
sync_throttle(tg, i);
|
||||
raw_spin_unlock_irq(&rq->lock);
|
||||
}
|
||||
|
||||
@@ -1667,6 +1667,10 @@ static inline bool sched_freq(void)
|
||||
return static_key_false(&__sched_freq);
|
||||
}
|
||||
|
||||
/*
|
||||
* sched_capacity_reqs expects capacity requests to be normalised.
|
||||
* All capacities should sum to the range of 0-1024.
|
||||
*/
|
||||
DECLARE_PER_CPU(struct sched_capacity_reqs, cpu_sched_capacity_reqs);
|
||||
void update_cpu_capacity_request(int cpu, bool request);
|
||||
|
||||
|
||||
+15
-22
@@ -68,6 +68,7 @@ enum {
|
||||
* attach_mutex to avoid changing binding state while
|
||||
* worker_attach_to_pool() is in progress.
|
||||
*/
|
||||
POOL_MANAGER_ACTIVE = 1 << 0, /* being managed */
|
||||
POOL_DISASSOCIATED = 1 << 2, /* cpu can't serve workers */
|
||||
|
||||
/* worker flags */
|
||||
@@ -165,7 +166,6 @@ struct worker_pool {
|
||||
/* L: hash of busy workers */
|
||||
|
||||
/* see manage_workers() for details on the two manager mutexes */
|
||||
struct mutex manager_arb; /* manager arbitration */
|
||||
struct worker *manager; /* L: purely informational */
|
||||
struct mutex attach_mutex; /* attach/detach exclusion */
|
||||
struct list_head workers; /* A: attached workers */
|
||||
@@ -297,6 +297,7 @@ static struct workqueue_attrs *wq_update_unbound_numa_attrs_buf;
|
||||
|
||||
static DEFINE_MUTEX(wq_pool_mutex); /* protects pools and workqueues list */
|
||||
static DEFINE_SPINLOCK(wq_mayday_lock); /* protects wq->maydays list */
|
||||
static DECLARE_WAIT_QUEUE_HEAD(wq_manager_wait); /* wait for manager to go away */
|
||||
|
||||
static LIST_HEAD(workqueues); /* PR: list of all workqueues */
|
||||
static bool workqueue_freezing; /* PL: have wqs started freezing? */
|
||||
@@ -799,7 +800,7 @@ static bool need_to_create_worker(struct worker_pool *pool)
|
||||
/* Do we have too many workers and should some go away? */
|
||||
static bool too_many_workers(struct worker_pool *pool)
|
||||
{
|
||||
bool managing = mutex_is_locked(&pool->manager_arb);
|
||||
bool managing = pool->flags & POOL_MANAGER_ACTIVE;
|
||||
int nr_idle = pool->nr_idle + managing; /* manager is considered idle */
|
||||
int nr_busy = pool->nr_workers - nr_idle;
|
||||
|
||||
@@ -1979,24 +1980,17 @@ static bool manage_workers(struct worker *worker)
|
||||
{
|
||||
struct worker_pool *pool = worker->pool;
|
||||
|
||||
/*
|
||||
* Anyone who successfully grabs manager_arb wins the arbitration
|
||||
* and becomes the manager. mutex_trylock() on pool->manager_arb
|
||||
* failure while holding pool->lock reliably indicates that someone
|
||||
* else is managing the pool and the worker which failed trylock
|
||||
* can proceed to executing work items. This means that anyone
|
||||
* grabbing manager_arb is responsible for actually performing
|
||||
* manager duties. If manager_arb is grabbed and released without
|
||||
* actual management, the pool may stall indefinitely.
|
||||
*/
|
||||
if (!mutex_trylock(&pool->manager_arb))
|
||||
if (pool->flags & POOL_MANAGER_ACTIVE)
|
||||
return false;
|
||||
|
||||
pool->flags |= POOL_MANAGER_ACTIVE;
|
||||
pool->manager = worker;
|
||||
|
||||
maybe_create_worker(pool);
|
||||
|
||||
pool->manager = NULL;
|
||||
mutex_unlock(&pool->manager_arb);
|
||||
pool->flags &= ~POOL_MANAGER_ACTIVE;
|
||||
wake_up(&wq_manager_wait);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -3203,7 +3197,6 @@ static int init_worker_pool(struct worker_pool *pool)
|
||||
setup_timer(&pool->mayday_timer, pool_mayday_timeout,
|
||||
(unsigned long)pool);
|
||||
|
||||
mutex_init(&pool->manager_arb);
|
||||
mutex_init(&pool->attach_mutex);
|
||||
INIT_LIST_HEAD(&pool->workers);
|
||||
|
||||
@@ -3273,13 +3266,15 @@ static void put_unbound_pool(struct worker_pool *pool)
|
||||
hash_del(&pool->hash_node);
|
||||
|
||||
/*
|
||||
* Become the manager and destroy all workers. Grabbing
|
||||
* manager_arb prevents @pool's workers from blocking on
|
||||
* attach_mutex.
|
||||
* Become the manager and destroy all workers. This prevents
|
||||
* @pool's workers from blocking on attach_mutex. We're the last
|
||||
* manager and @pool gets freed with the flag set.
|
||||
*/
|
||||
mutex_lock(&pool->manager_arb);
|
||||
|
||||
spin_lock_irq(&pool->lock);
|
||||
wait_event_lock_irq(wq_manager_wait,
|
||||
!(pool->flags & POOL_MANAGER_ACTIVE), pool->lock);
|
||||
pool->flags |= POOL_MANAGER_ACTIVE;
|
||||
|
||||
while ((worker = first_idle_worker(pool)))
|
||||
destroy_worker(worker);
|
||||
WARN_ON(pool->nr_workers || pool->nr_idle);
|
||||
@@ -3293,8 +3288,6 @@ static void put_unbound_pool(struct worker_pool *pool)
|
||||
if (pool->detach_completion)
|
||||
wait_for_completion(pool->detach_completion);
|
||||
|
||||
mutex_unlock(&pool->manager_arb);
|
||||
|
||||
/* shut down the timers */
|
||||
del_timer_sync(&pool->idle_timer);
|
||||
del_timer_sync(&pool->mayday_timer);
|
||||
|
||||
+17
-34
@@ -598,21 +598,31 @@ static bool assoc_array_insert_into_terminal_node(struct assoc_array_edit *edit,
|
||||
if ((edit->segment_cache[ASSOC_ARRAY_FAN_OUT] ^ base_seg) == 0)
|
||||
goto all_leaves_cluster_together;
|
||||
|
||||
/* Otherwise we can just insert a new node ahead of the old
|
||||
* one.
|
||||
/* Otherwise all the old leaves cluster in the same slot, but
|
||||
* the new leaf wants to go into a different slot - so we
|
||||
* create a new node (n0) to hold the new leaf and a pointer to
|
||||
* a new node (n1) holding all the old leaves.
|
||||
*
|
||||
* This can be done by falling through to the node splitting
|
||||
* path.
|
||||
*/
|
||||
goto present_leaves_cluster_but_not_new_leaf;
|
||||
pr_devel("present leaves cluster but not new leaf\n");
|
||||
}
|
||||
|
||||
split_node:
|
||||
pr_devel("split node\n");
|
||||
|
||||
/* We need to split the current node; we know that the node doesn't
|
||||
* simply contain a full set of leaves that cluster together (it
|
||||
* contains meta pointers and/or non-clustering leaves).
|
||||
/* We need to split the current node. The node must contain anything
|
||||
* from a single leaf (in the one leaf case, this leaf will cluster
|
||||
* with the new leaf) and the rest meta-pointers, to all leaves, some
|
||||
* of which may cluster.
|
||||
*
|
||||
* It won't contain the case in which all the current leaves plus the
|
||||
* new leaves want to cluster in the same slot.
|
||||
*
|
||||
* We need to expel at least two leaves out of a set consisting of the
|
||||
* leaves in the node and the new leaf.
|
||||
* leaves in the node and the new leaf. The current meta pointers can
|
||||
* just be copied as they shouldn't cluster with any of the leaves.
|
||||
*
|
||||
* We need a new node (n0) to replace the current one and a new node to
|
||||
* take the expelled nodes (n1).
|
||||
@@ -717,33 +727,6 @@ found_slot_for_multiple_occupancy:
|
||||
pr_devel("<--%s() = ok [split node]\n", __func__);
|
||||
return true;
|
||||
|
||||
present_leaves_cluster_but_not_new_leaf:
|
||||
/* All the old leaves cluster in the same slot, but the new leaf wants
|
||||
* to go into a different slot, so we create a new node to hold the new
|
||||
* leaf and a pointer to a new node holding all the old leaves.
|
||||
*/
|
||||
pr_devel("present leaves cluster but not new leaf\n");
|
||||
|
||||
new_n0->back_pointer = node->back_pointer;
|
||||
new_n0->parent_slot = node->parent_slot;
|
||||
new_n0->nr_leaves_on_branch = node->nr_leaves_on_branch;
|
||||
new_n1->back_pointer = assoc_array_node_to_ptr(new_n0);
|
||||
new_n1->parent_slot = edit->segment_cache[0];
|
||||
new_n1->nr_leaves_on_branch = node->nr_leaves_on_branch;
|
||||
edit->adjust_count_on = new_n0;
|
||||
|
||||
for (i = 0; i < ASSOC_ARRAY_FAN_OUT; i++)
|
||||
new_n1->slots[i] = node->slots[i];
|
||||
|
||||
new_n0->slots[edit->segment_cache[0]] = assoc_array_node_to_ptr(new_n0);
|
||||
edit->leaf_p = &new_n0->slots[edit->segment_cache[ASSOC_ARRAY_FAN_OUT]];
|
||||
|
||||
edit->set[0].ptr = &assoc_array_ptr_to_node(node->back_pointer)->slots[node->parent_slot];
|
||||
edit->set[0].to = assoc_array_node_to_ptr(new_n0);
|
||||
edit->excised_meta[0] = assoc_array_node_to_ptr(node);
|
||||
pr_devel("<--%s() = ok [insert node before]\n", __func__);
|
||||
return true;
|
||||
|
||||
all_leaves_cluster_together:
|
||||
/* All the leaves, new and old, want to cluster together in this node
|
||||
* in the same slot, so we have to replace this node with a shortcut to
|
||||
|
||||
+41
-9
@@ -505,11 +505,6 @@ static int cfg80211_sme_connect(struct wireless_dev *wdev,
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (wdev->current_bss) {
|
||||
if (!prev_bssid)
|
||||
return -EALREADY;
|
||||
if (prev_bssid &&
|
||||
!ether_addr_equal(prev_bssid, wdev->current_bss->pub.bssid))
|
||||
return -ENOTCONN;
|
||||
cfg80211_unhold_bss(wdev->current_bss);
|
||||
cfg80211_put_bss(wdev->wiphy, &wdev->current_bss->pub);
|
||||
wdev->current_bss = NULL;
|
||||
@@ -1025,11 +1020,35 @@ int cfg80211_connect(struct cfg80211_registered_device *rdev,
|
||||
|
||||
ASSERT_WDEV_LOCK(wdev);
|
||||
|
||||
if (WARN_ON(wdev->connect_keys)) {
|
||||
kzfree(wdev->connect_keys);
|
||||
wdev->connect_keys = NULL;
|
||||
/*
|
||||
* If we have an ssid_len, we're trying to connect or are
|
||||
* already connected, so reject a new SSID unless it's the
|
||||
* same (which is the case for re-association.)
|
||||
*/
|
||||
if (wdev->ssid_len &&
|
||||
(wdev->ssid_len != connect->ssid_len ||
|
||||
memcmp(wdev->ssid, connect->ssid, wdev->ssid_len)))
|
||||
return -EALREADY;
|
||||
|
||||
/*
|
||||
* If connected, reject (re-)association unless prev_bssid
|
||||
* matches the current BSSID.
|
||||
*/
|
||||
if (wdev->current_bss) {
|
||||
if (!prev_bssid)
|
||||
return -EALREADY;
|
||||
if (!ether_addr_equal(prev_bssid, wdev->current_bss->pub.bssid))
|
||||
return -ENOTCONN;
|
||||
}
|
||||
|
||||
/*
|
||||
* Reject if we're in the process of connecting with WEP,
|
||||
* this case isn't very interesting and trying to handle
|
||||
* it would make the code much more complex.
|
||||
*/
|
||||
if (wdev->connect_keys)
|
||||
return -EINPROGRESS;
|
||||
|
||||
cfg80211_oper_and_ht_capa(&connect->ht_capa_mask,
|
||||
rdev->wiphy.ht_capa_mod_mask);
|
||||
|
||||
@@ -1080,7 +1099,12 @@ int cfg80211_connect(struct cfg80211_registered_device *rdev,
|
||||
|
||||
if (err) {
|
||||
wdev->connect_keys = NULL;
|
||||
wdev->ssid_len = 0;
|
||||
/*
|
||||
* This could be reassoc getting refused, don't clear
|
||||
* ssid_len in that case.
|
||||
*/
|
||||
if (!wdev->current_bss)
|
||||
wdev->ssid_len = 0;
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -1105,5 +1129,13 @@ int cfg80211_disconnect(struct cfg80211_registered_device *rdev,
|
||||
else if (wdev->current_bss)
|
||||
err = rdev_disconnect(rdev, dev, reason);
|
||||
|
||||
/*
|
||||
* Clear ssid_len unless we actually were fully connected,
|
||||
* in which case cfg80211_disconnected() will take care of
|
||||
* this later.
|
||||
*/
|
||||
if (!wdev->current_bss)
|
||||
wdev->ssid_len = 0;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
+15
-10
@@ -1664,32 +1664,34 @@ static int dump_one_policy(struct xfrm_policy *xp, int dir, int count, void *ptr
|
||||
|
||||
static int xfrm_dump_policy_done(struct netlink_callback *cb)
|
||||
{
|
||||
struct xfrm_policy_walk *walk = (struct xfrm_policy_walk *) &cb->args[1];
|
||||
struct xfrm_policy_walk *walk = (struct xfrm_policy_walk *)cb->args;
|
||||
struct net *net = sock_net(cb->skb->sk);
|
||||
|
||||
xfrm_policy_walk_done(walk, net);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int xfrm_dump_policy_start(struct netlink_callback *cb)
|
||||
{
|
||||
struct xfrm_policy_walk *walk = (struct xfrm_policy_walk *)cb->args;
|
||||
|
||||
BUILD_BUG_ON(sizeof(*walk) > sizeof(cb->args));
|
||||
|
||||
xfrm_policy_walk_init(walk, XFRM_POLICY_TYPE_ANY);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int xfrm_dump_policy(struct sk_buff *skb, struct netlink_callback *cb)
|
||||
{
|
||||
struct net *net = sock_net(skb->sk);
|
||||
struct xfrm_policy_walk *walk = (struct xfrm_policy_walk *) &cb->args[1];
|
||||
struct xfrm_policy_walk *walk = (struct xfrm_policy_walk *)cb->args;
|
||||
struct xfrm_dump_info info;
|
||||
|
||||
BUILD_BUG_ON(sizeof(struct xfrm_policy_walk) >
|
||||
sizeof(cb->args) - sizeof(cb->args[0]));
|
||||
|
||||
info.in_skb = cb->skb;
|
||||
info.out_skb = skb;
|
||||
info.nlmsg_seq = cb->nlh->nlmsg_seq;
|
||||
info.nlmsg_flags = NLM_F_MULTI;
|
||||
|
||||
if (!cb->args[0]) {
|
||||
cb->args[0] = 1;
|
||||
xfrm_policy_walk_init(walk, XFRM_POLICY_TYPE_ANY);
|
||||
}
|
||||
|
||||
(void) xfrm_policy_walk(net, walk, dump_one_policy, &info);
|
||||
|
||||
return skb->len;
|
||||
@@ -2437,6 +2439,7 @@ static const struct nla_policy xfrma_spd_policy[XFRMA_SPD_MAX+1] = {
|
||||
|
||||
static const struct xfrm_link {
|
||||
int (*doit)(struct sk_buff *, struct nlmsghdr *, struct nlattr **);
|
||||
int (*start)(struct netlink_callback *);
|
||||
int (*dump)(struct sk_buff *, struct netlink_callback *);
|
||||
int (*done)(struct netlink_callback *);
|
||||
const struct nla_policy *nla_pol;
|
||||
@@ -2450,6 +2453,7 @@ static const struct xfrm_link {
|
||||
[XFRM_MSG_NEWPOLICY - XFRM_MSG_BASE] = { .doit = xfrm_add_policy },
|
||||
[XFRM_MSG_DELPOLICY - XFRM_MSG_BASE] = { .doit = xfrm_get_policy },
|
||||
[XFRM_MSG_GETPOLICY - XFRM_MSG_BASE] = { .doit = xfrm_get_policy,
|
||||
.start = xfrm_dump_policy_start,
|
||||
.dump = xfrm_dump_policy,
|
||||
.done = xfrm_dump_policy_done },
|
||||
[XFRM_MSG_ALLOCSPI - XFRM_MSG_BASE] = { .doit = xfrm_alloc_userspi },
|
||||
@@ -2501,6 +2505,7 @@ static int xfrm_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
|
||||
|
||||
{
|
||||
struct netlink_dump_control c = {
|
||||
.start = link->start,
|
||||
.dump = link->dump,
|
||||
.done = link->done,
|
||||
};
|
||||
|
||||
@@ -329,6 +329,7 @@ static void alc_fill_eapd_coef(struct hda_codec *codec)
|
||||
break;
|
||||
case 0x10ec0225:
|
||||
case 0x10ec0233:
|
||||
case 0x10ec0236:
|
||||
case 0x10ec0255:
|
||||
case 0x10ec0256:
|
||||
case 0x10ec0282:
|
||||
@@ -909,6 +910,7 @@ static struct alc_codec_rename_pci_table rename_pci_tbl[] = {
|
||||
{ 0x10ec0275, 0x1028, 0, "ALC3260" },
|
||||
{ 0x10ec0899, 0x1028, 0, "ALC3861" },
|
||||
{ 0x10ec0298, 0x1028, 0, "ALC3266" },
|
||||
{ 0x10ec0236, 0x1028, 0, "ALC3204" },
|
||||
{ 0x10ec0256, 0x1028, 0, "ALC3246" },
|
||||
{ 0x10ec0225, 0x1028, 0, "ALC3253" },
|
||||
{ 0x10ec0295, 0x1028, 0, "ALC3254" },
|
||||
@@ -3694,6 +3696,7 @@ static void alc_headset_mode_unplugged(struct hda_codec *codec)
|
||||
alc_process_coef_fw(codec, coef0255_1);
|
||||
alc_process_coef_fw(codec, coef0255);
|
||||
break;
|
||||
case 0x10ec0236:
|
||||
case 0x10ec0256:
|
||||
alc_process_coef_fw(codec, coef0256);
|
||||
alc_process_coef_fw(codec, coef0255);
|
||||
@@ -3777,6 +3780,7 @@ static void alc_headset_mode_mic_in(struct hda_codec *codec, hda_nid_t hp_pin,
|
||||
|
||||
|
||||
switch (codec->core.vendor_id) {
|
||||
case 0x10ec0236:
|
||||
case 0x10ec0255:
|
||||
case 0x10ec0256:
|
||||
alc_write_coef_idx(codec, 0x45, 0xc489);
|
||||
@@ -3885,6 +3889,7 @@ static void alc_headset_mode_default(struct hda_codec *codec)
|
||||
case 0x10ec0295:
|
||||
alc_process_coef_fw(codec, coef0225);
|
||||
break;
|
||||
case 0x10ec0236:
|
||||
case 0x10ec0255:
|
||||
case 0x10ec0256:
|
||||
alc_process_coef_fw(codec, coef0255);
|
||||
@@ -3971,6 +3976,7 @@ static void alc_headset_mode_ctia(struct hda_codec *codec)
|
||||
case 0x10ec0255:
|
||||
alc_process_coef_fw(codec, coef0255);
|
||||
break;
|
||||
case 0x10ec0236:
|
||||
case 0x10ec0256:
|
||||
alc_process_coef_fw(codec, coef0256);
|
||||
break;
|
||||
@@ -4064,6 +4070,7 @@ static void alc_headset_mode_omtp(struct hda_codec *codec)
|
||||
case 0x10ec0255:
|
||||
alc_process_coef_fw(codec, coef0255);
|
||||
break;
|
||||
case 0x10ec0236:
|
||||
case 0x10ec0256:
|
||||
alc_process_coef_fw(codec, coef0256);
|
||||
break;
|
||||
@@ -4131,6 +4138,7 @@ static void alc_determine_headset_type(struct hda_codec *codec)
|
||||
};
|
||||
|
||||
switch (codec->core.vendor_id) {
|
||||
case 0x10ec0236:
|
||||
case 0x10ec0255:
|
||||
case 0x10ec0256:
|
||||
alc_process_coef_fw(codec, coef0255);
|
||||
@@ -4335,6 +4343,7 @@ static void alc255_set_default_jack_type(struct hda_codec *codec)
|
||||
case 0x10ec0255:
|
||||
alc_process_coef_fw(codec, alc255fw);
|
||||
break;
|
||||
case 0x10ec0236:
|
||||
case 0x10ec0256:
|
||||
alc_process_coef_fw(codec, alc256fw);
|
||||
break;
|
||||
@@ -5852,6 +5861,14 @@ static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = {
|
||||
ALC225_STANDARD_PINS,
|
||||
{0x12, 0xb7a60130},
|
||||
{0x1b, 0x90170110}),
|
||||
SND_HDA_PIN_QUIRK(0x10ec0236, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
|
||||
{0x12, 0x90a60140},
|
||||
{0x14, 0x90170110},
|
||||
{0x21, 0x02211020}),
|
||||
SND_HDA_PIN_QUIRK(0x10ec0236, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
|
||||
{0x12, 0x90a60140},
|
||||
{0x14, 0x90170150},
|
||||
{0x21, 0x02211020}),
|
||||
SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL2_MIC_NO_PRESENCE,
|
||||
{0x14, 0x90170110},
|
||||
{0x21, 0x02211020}),
|
||||
@@ -6226,6 +6243,7 @@ static int patch_alc269(struct hda_codec *codec)
|
||||
case 0x10ec0255:
|
||||
spec->codec_variant = ALC269_TYPE_ALC255;
|
||||
break;
|
||||
case 0x10ec0236:
|
||||
case 0x10ec0256:
|
||||
spec->codec_variant = ALC269_TYPE_ALC256;
|
||||
spec->gen.mixer_nid = 0; /* ALC256 does not have any loopback mixer path */
|
||||
@@ -7205,6 +7223,7 @@ static const struct hda_device_id snd_hda_id_realtek[] = {
|
||||
HDA_CODEC_ENTRY(0x10ec0233, "ALC233", patch_alc269),
|
||||
HDA_CODEC_ENTRY(0x10ec0234, "ALC234", patch_alc269),
|
||||
HDA_CODEC_ENTRY(0x10ec0235, "ALC233", patch_alc269),
|
||||
HDA_CODEC_ENTRY(0x10ec0236, "ALC236", patch_alc269),
|
||||
HDA_CODEC_ENTRY(0x10ec0255, "ALC255", patch_alc269),
|
||||
HDA_CODEC_ENTRY(0x10ec0256, "ALC256", patch_alc269),
|
||||
HDA_CODEC_ENTRY(0x10ec0260, "ALC260", patch_alc260),
|
||||
|
||||
Reference in New Issue
Block a user