commit: 4f89508dc4a7aed0d6d9cfbfdb505a2ffd6a550c Author: Mike Pagano <mpagano <AT> gentoo <DOT> org> AuthorDate: Thu Nov 2 10:02:46 2017 +0000 Commit: Mike Pagano <mpagano <AT> gentoo <DOT> org> CommitDate: Thu Nov 2 10:02:46 2017 +0000 URL: https://gitweb.gentoo.org/proj/linux-patches.git/commit/?id=4f89508d
Linux patch 4.4.96 0000_README | 4 + 1095_linux-4.4.96.patch | 809 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 813 insertions(+) diff --git a/0000_README b/0000_README index 3de9efe..5d56409 100644 --- a/0000_README +++ b/0000_README @@ -423,6 +423,10 @@ Patch: 1094_linux-4.4.95.patch From: http://www.kernel.org Desc: Linux 4.4.95 +Patch: 1095_linux-4.4.96.patch +From: http://www.kernel.org +Desc: Linux 4.4.96 + Patch: 1500_XATTR_USER_PREFIX.patch From: https://bugs.gentoo.org/show_bug.cgi?id=470644 Desc: Support for namespace user.pax.* on tmpfs. diff --git a/1095_linux-4.4.96.patch b/1095_linux-4.4.96.patch new file mode 100644 index 0000000..51487e9 --- /dev/null +++ b/1095_linux-4.4.96.patch @@ -0,0 +1,809 @@ +diff --git a/Documentation/devicetree/bindings/display/bridge/ti,ths8135.txt b/Documentation/devicetree/bindings/display/bridge/ti,ths8135.txt +deleted file mode 100644 +index 6ec1a880ac18..000000000000 +--- a/Documentation/devicetree/bindings/display/bridge/ti,ths8135.txt ++++ /dev/null +@@ -1,46 +0,0 @@ +-THS8135 Video DAC +------------------ +- +-This is the binding for Texas Instruments THS8135 Video DAC bridge. +- +-Required properties: +- +-- compatible: Must be "ti,ths8135" +- +-Required nodes: +- +-This device has two video ports. Their connections are modelled using the OF +-graph bindings specified in Documentation/devicetree/bindings/graph.txt. +- +-- Video port 0 for RGB input +-- Video port 1 for VGA output +- +-Example +-------- +- +-vga-bridge { +- compatible = "ti,ths8135"; +- #address-cells = <1>; +- #size-cells = <0>; +- +- ports { +- #address-cells = <1>; +- #size-cells = <0>; +- +- port@0 { +- reg = <0>; +- +- vga_bridge_in: endpoint { +- remote-endpoint = <&lcdc_out_vga>; +- }; +- }; +- +- port@1 { +- reg = <1>; +- +- vga_bridge_out: endpoint { +- remote-endpoint = <&vga_con_in>; +- }; +- }; +- }; +-}; +diff --git a/Makefile b/Makefile +index 57e1ea2a189a..12dfe1dcbaca 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,6 +1,6 @@ + VERSION = 4 + PATCHLEVEL = 4 +-SUBLEVEL = 95 ++SUBLEVEL = 96 + EXTRAVERSION = + NAME = Blurry Fish Butt + +diff --git a/arch/x86/kernel/cpu/microcode/intel.c b/arch/x86/kernel/cpu/microcode/intel.c +index ac8975a65280..abf581ade8d2 100644 +--- a/arch/x86/kernel/cpu/microcode/intel.c ++++ b/arch/x86/kernel/cpu/microcode/intel.c +@@ -990,6 +990,18 @@ static int get_ucode_fw(void *to, const void *from, size_t n) + return 0; + } + ++static bool is_blacklisted(unsigned int cpu) ++{ ++ struct cpuinfo_x86 *c = &cpu_data(cpu); ++ ++ if (c->x86 == 6 && c->x86_model == 79) { ++ pr_err_once("late loading on model 79 is disabled.\n"); ++ return true; ++ } ++ ++ return false; ++} ++ + static enum ucode_state request_microcode_fw(int cpu, struct device *device, + bool refresh_fw) + { +@@ -998,6 +1010,9 @@ static enum ucode_state request_microcode_fw(int cpu, struct device *device, + const struct firmware *firmware; + enum ucode_state ret; + ++ if (is_blacklisted(cpu)) ++ return UCODE_NFOUND; ++ + sprintf(name, "intel-ucode/%02x-%02x-%02x", + c->x86, c->x86_model, c->x86_mask); + +@@ -1022,6 +1037,9 @@ static int get_ucode_user(void *to, const void *from, size_t n) + static enum ucode_state + request_microcode_user(int cpu, const void __user *buf, size_t size) + { ++ if (is_blacklisted(cpu)) ++ return UCODE_NFOUND; ++ + return generic_load_microcode(cpu, (void *)buf, size, &get_ucode_user); + } + +diff --git a/drivers/input/mouse/elan_i2c_core.c b/drivers/input/mouse/elan_i2c_core.c +index 681dce15fbc8..b8c50d883b2c 100644 +--- a/drivers/input/mouse/elan_i2c_core.c ++++ b/drivers/input/mouse/elan_i2c_core.c +@@ -1240,6 +1240,7 @@ static const struct acpi_device_id elan_acpi_id[] = { + { "ELAN0605", 0 }, + { "ELAN0609", 0 }, + { "ELAN060B", 0 }, ++ { "ELAN0611", 0 }, + { "ELAN1000", 0 }, + { } + }; +diff --git a/drivers/input/tablet/gtco.c b/drivers/input/tablet/gtco.c +index 7c18249d6c8e..8b68a210277b 100644 +--- a/drivers/input/tablet/gtco.c ++++ b/drivers/input/tablet/gtco.c +@@ -231,13 +231,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]; +@@ -245,8 +249,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; + } +diff --git a/drivers/net/can/sun4i_can.c b/drivers/net/can/sun4i_can.c +index 68ef0a4cd821..b0c80859f746 100644 +--- a/drivers/net/can/sun4i_can.c ++++ b/drivers/net/can/sun4i_can.c +@@ -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; +diff --git a/drivers/net/can/usb/kvaser_usb.c b/drivers/net/can/usb/kvaser_usb.c +index 022bfa13ebfa..c2e2821a3346 100644 +--- a/drivers/net/can/usb/kvaser_usb.c ++++ b/drivers/net/can/usb/kvaser_usb.c +@@ -134,6 +134,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 +@@ -1297,6 +1298,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); +@@ -1607,7 +1613,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); +diff --git a/drivers/regulator/fan53555.c b/drivers/regulator/fan53555.c +index 4940e8287df6..c3107358b3fb 100644 +--- a/drivers/regulator/fan53555.c ++++ b/drivers/regulator/fan53555.c +@@ -434,7 +434,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 + }, + { }, +diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c +index c00ac4650dce..38c8e308d4c8 100644 +--- a/drivers/s390/scsi/zfcp_aux.c ++++ b/drivers/s390/scsi/zfcp_aux.c +@@ -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; +diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c +index 7ccfce559034..3b23d6754598 100644 +--- a/drivers/s390/scsi/zfcp_erp.c ++++ b/drivers/s390/scsi/zfcp_erp.c +@@ -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; + +diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c +index 9bd9b9a29dfc..a9b8104b982e 100644 +--- a/drivers/s390/scsi/zfcp_scsi.c ++++ b/drivers/s390/scsi/zfcp_scsi.c +@@ -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); +diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c +index 39e8b5dc23fa..38f77e127349 100644 +--- a/drivers/scsi/sg.c ++++ b/drivers/scsi/sg.c +@@ -848,7 +848,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 = +diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c +index a8a2d5005e6e..9df00101bfe1 100644 +--- a/drivers/usb/host/xhci-hub.c ++++ b/drivers/usb/host/xhci-hub.c +@@ -394,15 +394,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); + +@@ -413,6 +423,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; + } +diff --git a/drivers/xen/gntdev.c b/drivers/xen/gntdev.c +index 308600adf6e0..a4d749665c9f 100644 +--- a/drivers/xen/gntdev.c ++++ b/drivers/xen/gntdev.c +@@ -827,6 +827,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); +@@ -864,7 +865,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; +diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c +index c69e1253b47b..0e3de1bb6500 100644 +--- a/fs/ceph/caps.c ++++ b/fs/ceph/caps.c +@@ -1850,6 +1850,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; + } +@@ -1867,8 +1868,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, &flush_tid, + &oldest_flush_tid); +diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h +index 7b39260c7bba..eae9cdb8af46 100644 +--- a/fs/ecryptfs/ecryptfs_kernel.h ++++ b/fs/ecryptfs/ecryptfs_kernel.h +@@ -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(key)->data; +- else ++ if (auth_tok) + return auth_tok; ++ ++ ukp = user_key_payload(key); ++ if (!ukp) ++ return ERR_PTR(-EKEYREVOKED); ++ ++ return (struct ecryptfs_auth_tok *)ukp->data; + } + + #define ECRYPTFS_MAX_KEYSET_SIZE 1024 +diff --git a/fs/ecryptfs/keystore.c b/fs/ecryptfs/keystore.c +index 6bd67e2011f0..20632ee51ae5 100644 +--- a/fs/ecryptfs/keystore.c ++++ b/fs/ecryptfs/keystore.c +@@ -458,7 +458,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, +@@ -467,6 +468,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 " +diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c +index 4b5f2c4e69c8..5068dbf80ff8 100644 +--- a/fs/fuse/dir.c ++++ b/fs/fuse/dir.c +@@ -1295,7 +1295,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; +diff --git a/include/uapi/linux/spi/spidev.h b/include/uapi/linux/spi/spidev.h +index dd5f21e75805..856de39d0b89 100644 +--- a/include/uapi/linux/spi/spidev.h ++++ b/include/uapi/linux/spi/spidev.h +@@ -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> +diff --git a/kernel/workqueue.c b/kernel/workqueue.c +index 23231237f2e2..95cc76785a12 100644 +--- a/kernel/workqueue.c ++++ b/kernel/workqueue.c +@@ -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 */ +@@ -163,7 +164,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 */ +@@ -295,6 +295,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? */ +@@ -808,7 +809,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; + +@@ -1952,24 +1953,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; + } + +@@ -3119,7 +3113,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); + +@@ -3189,13 +3182,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); +@@ -3209,8 +3204,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); +diff --git a/lib/assoc_array.c b/lib/assoc_array.c +index 59fd7c0b119c..5cd093589c5a 100644 +--- a/lib/assoc_array.c ++++ b/lib/assoc_array.c +@@ -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 +diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c +index 5cab24f52825..a83688f8672e 100644 +--- a/sound/pci/hda/patch_realtek.c ++++ b/sound/pci/hda/patch_realtek.c +@@ -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); +@@ -3774,6 +3777,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); +@@ -3879,6 +3883,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); +@@ -3962,6 +3967,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; +@@ -4052,6 +4058,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; +@@ -4119,6 +4126,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); +@@ -4320,6 +4328,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; +@@ -5834,6 +5843,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}), +@@ -6208,6 +6225,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 */ +@@ -7147,6 +7165,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),
