Merge 4.19.30 into android-4.19
Changes in 4.19.30 connector: fix unsafe usage of ->real_parent gro_cells: make sure device is up in gro_cells_receive() ipv4/route: fail early when inet dev is missing l2tp: fix infoleak in l2tp_ip6_recvmsg() lan743x: Fix RX Kernel Panic lan743x: Fix TX Stall Issue net: hsr: fix memory leak in hsr_dev_finalize() net/hsr: fix possible crash in add_timer() net: sit: fix UBSAN Undefined behaviour in check_6rd net/x25: fix use-after-free in x25_device_event() net/x25: reset state in x25_connect() pptp: dst_release sk_dst_cache in pptp_sock_destruct ravb: Decrease TxFIFO depth of Q3 and Q2 to one route: set the deleted fnhe fnhe_daddr to 0 in ip_del_fnhe to fix a race rxrpc: Fix client call queueing, waiting for channel sctp: remove sched init from sctp_stream_init tcp: do not report TCP_CM_INQ of 0 for closed connections tcp: Don't access TCP_SKB_CB before initializing it tcp: handle inet_csk_reqsk_queue_add() failures vxlan: Fix GRO cells race condition between receive and link delete vxlan: test dev->flags & IFF_UP before calling gro_cells_receive() net/mlx4_core: Fix reset flow when in command polling mode net/mlx4_core: Fix locking in SRIOV mode when switching between events and polling net/mlx4_core: Fix qp mtt size calculation net/x25: fix a race in x25_bind() mdio_bus: Fix use-after-free on device_register fails net: Set rtm_table to RT_TABLE_COMPAT for ipv6 for tables > 255 ipv6: route: purge exception on removal team: use operstate consistently for linkup ipvlan: disallow userns cap_net_admin to change global mode/flags ipv6: route: enforce RCU protection in rt6_update_exception_stamp_rt() ipv6: route: enforce RCU protection in ip6_route_check_nh_onlink() bonding: fix PACKET_ORIGDEV regression net/smc: fix smc_poll in SMC_INIT state missing barriers in some of unix_sock ->addr and ->path accesses net: sched: flower: insert new filter to idr after setting its mask f2fs: wait on atomic writes to count F2FS_CP_WB_DATA perf/x86: Fixup typo in stub functions ALSA: bebob: use more identical mod_alias for Saffire Pro 10 I/O against Liquid Saffire 56 ALSA: firewire-motu: fix construction of PCM frame for capture direction ALSA: hda: Extend i915 component bind timeout ALSA: hda - add more quirks for HP Z2 G4 and HP Z240 ALSA: hda/realtek: Enable audio jacks of ASUS UX362FA with ALC294 ALSA: hda/realtek - Reduce click noise on Dell Precision 5820 headphone ALSA: hda/realtek: Enable headset MIC of Acer TravelMate X514-51T with ALC255 perf/x86/intel: Fix memory corruption perf/x86/intel: Make dev_attr_allow_tsx_force_abort static It's wrong to add len to sector_nr in raid10 reshape twice drm: Block fb changes for async plane updates staging: erofs: fix race when the managed cache is enabled i40e: report correct statistics when XDP is enabled vhost/vsock: fix vhost vsock cid hashing inconsistent Linux 4.19.30 Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
This commit is contained in:
commit
4afd597192
45 files changed
+483
-248
No files matched your search
@@ -1,7 +1,7 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
VERSION = 4
|
||||
PATCHLEVEL = 19
|
||||
SUBLEVEL = 29
|
||||
SUBLEVEL = 30
|
||||
EXTRAVERSION =
|
||||
NAME = "People's Front"
|
||||
|
||||
|
||||
@@ -3282,7 +3282,7 @@ tfa_get_event_constraints(struct cpu_hw_events *cpuc, int idx,
|
||||
/*
|
||||
* Without TFA we must not use PMC3.
|
||||
*/
|
||||
if (!allow_tsx_force_abort && test_bit(3, c->idxmsk)) {
|
||||
if (!allow_tsx_force_abort && test_bit(3, c->idxmsk) && idx >= 0) {
|
||||
c = dyn_constraint(cpuc, c, idx);
|
||||
c->idxmsk64 &= ~(1ULL << 3);
|
||||
c->weight--;
|
||||
@@ -3989,7 +3989,7 @@ static struct attribute *intel_pmu_caps_attrs[] = {
|
||||
NULL
|
||||
};
|
||||
|
||||
DEVICE_BOOL_ATTR(allow_tsx_force_abort, 0644, allow_tsx_force_abort);
|
||||
static DEVICE_BOOL_ATTR(allow_tsx_force_abort, 0644, allow_tsx_force_abort);
|
||||
|
||||
static struct attribute *intel_pmu_attrs[] = {
|
||||
&dev_attr_freeze_on_smi.attr,
|
||||
|
||||
@@ -1030,12 +1030,12 @@ static inline int intel_pmu_init(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int intel_cpuc_prepare(struct cpu_hw_event *cpuc, int cpu)
|
||||
static inline int intel_cpuc_prepare(struct cpu_hw_events *cpuc, int cpu)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void intel_cpuc_finish(struct cpu_hw_event *cpuc)
|
||||
static inline void intel_cpuc_finish(struct cpu_hw_events *cpuc)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -250,6 +250,7 @@ void proc_coredump_connector(struct task_struct *task)
|
||||
{
|
||||
struct cn_msg *msg;
|
||||
struct proc_event *ev;
|
||||
struct task_struct *parent;
|
||||
__u8 buffer[CN_PROC_MSG_SIZE] __aligned(8);
|
||||
|
||||
if (atomic_read(&proc_event_num_listeners) < 1)
|
||||
@@ -262,8 +263,14 @@ void proc_coredump_connector(struct task_struct *task)
|
||||
ev->what = PROC_EVENT_COREDUMP;
|
||||
ev->event_data.coredump.process_pid = task->pid;
|
||||
ev->event_data.coredump.process_tgid = task->tgid;
|
||||
ev->event_data.coredump.parent_pid = task->real_parent->pid;
|
||||
ev->event_data.coredump.parent_tgid = task->real_parent->tgid;
|
||||
|
||||
rcu_read_lock();
|
||||
if (pid_alive(task)) {
|
||||
parent = rcu_dereference(task->real_parent);
|
||||
ev->event_data.coredump.parent_pid = parent->pid;
|
||||
ev->event_data.coredump.parent_tgid = parent->tgid;
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id));
|
||||
msg->ack = 0; /* not used */
|
||||
@@ -276,6 +283,7 @@ void proc_exit_connector(struct task_struct *task)
|
||||
{
|
||||
struct cn_msg *msg;
|
||||
struct proc_event *ev;
|
||||
struct task_struct *parent;
|
||||
__u8 buffer[CN_PROC_MSG_SIZE] __aligned(8);
|
||||
|
||||
if (atomic_read(&proc_event_num_listeners) < 1)
|
||||
@@ -290,8 +298,14 @@ void proc_exit_connector(struct task_struct *task)
|
||||
ev->event_data.exit.process_tgid = task->tgid;
|
||||
ev->event_data.exit.exit_code = task->exit_code;
|
||||
ev->event_data.exit.exit_signal = task->exit_signal;
|
||||
ev->event_data.exit.parent_pid = task->real_parent->pid;
|
||||
ev->event_data.exit.parent_tgid = task->real_parent->tgid;
|
||||
|
||||
rcu_read_lock();
|
||||
if (pid_alive(task)) {
|
||||
parent = rcu_dereference(task->real_parent);
|
||||
ev->event_data.exit.parent_pid = parent->pid;
|
||||
ev->event_data.exit.parent_tgid = parent->tgid;
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id));
|
||||
msg->ack = 0; /* not used */
|
||||
|
||||
@@ -1573,6 +1573,15 @@ int drm_atomic_helper_async_check(struct drm_device *dev,
|
||||
if (old_plane_state->fb != new_plane_state->fb)
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* FIXME: Since prepare_fb and cleanup_fb are always called on
|
||||
* the new_plane_state for async updates we need to block framebuffer
|
||||
* changes. This prevents use of a fb that's been cleaned up and
|
||||
* double cleanups from occuring.
|
||||
*/
|
||||
if (old_plane_state->fb != new_plane_state->fb)
|
||||
return -EINVAL;
|
||||
|
||||
funcs = plane->helper_private;
|
||||
if (!funcs->atomic_async_update)
|
||||
return -EINVAL;
|
||||
|
||||
@@ -4630,7 +4630,6 @@ read_more:
|
||||
atomic_inc(&r10_bio->remaining);
|
||||
read_bio->bi_next = NULL;
|
||||
generic_make_request(read_bio);
|
||||
sector_nr += nr_sectors;
|
||||
sectors_done += nr_sectors;
|
||||
if (sector_nr <= last)
|
||||
goto read_more;
|
||||
|
||||
@@ -1171,29 +1171,22 @@ static rx_handler_result_t bond_handle_frame(struct sk_buff **pskb)
|
||||
}
|
||||
}
|
||||
|
||||
/* Link-local multicast packets should be passed to the
|
||||
* stack on the link they arrive as well as pass them to the
|
||||
* bond-master device. These packets are mostly usable when
|
||||
* stack receives it with the link on which they arrive
|
||||
* (e.g. LLDP) they also must be available on master. Some of
|
||||
* the use cases include (but are not limited to): LLDP agents
|
||||
* that must be able to operate both on enslaved interfaces as
|
||||
* well as on bonds themselves; linux bridges that must be able
|
||||
* to process/pass BPDUs from attached bonds when any kind of
|
||||
* STP version is enabled on the network.
|
||||
/*
|
||||
* For packets determined by bond_should_deliver_exact_match() call to
|
||||
* be suppressed we want to make an exception for link-local packets.
|
||||
* This is necessary for e.g. LLDP daemons to be able to monitor
|
||||
* inactive slave links without being forced to bind to them
|
||||
* explicitly.
|
||||
*
|
||||
* At the same time, packets that are passed to the bonding master
|
||||
* (including link-local ones) can have their originating interface
|
||||
* determined via PACKET_ORIGDEV socket option.
|
||||
*/
|
||||
if (is_link_local_ether_addr(eth_hdr(skb)->h_dest)) {
|
||||
struct sk_buff *nskb = skb_clone(skb, GFP_ATOMIC);
|
||||
|
||||
if (nskb) {
|
||||
nskb->dev = bond->dev;
|
||||
nskb->queue_mapping = 0;
|
||||
netif_rx(nskb);
|
||||
}
|
||||
return RX_HANDLER_PASS;
|
||||
}
|
||||
if (bond_should_deliver_exact_match(skb, slave, bond))
|
||||
if (bond_should_deliver_exact_match(skb, slave, bond)) {
|
||||
if (is_link_local_ether_addr(eth_hdr(skb)->h_dest))
|
||||
return RX_HANDLER_PASS;
|
||||
return RX_HANDLER_EXACT;
|
||||
}
|
||||
|
||||
skb->dev = bond->dev;
|
||||
|
||||
|
||||
@@ -424,9 +424,9 @@ static void i40e_get_netdev_stats_struct(struct net_device *netdev,
|
||||
struct rtnl_link_stats64 *stats)
|
||||
{
|
||||
struct i40e_netdev_priv *np = netdev_priv(netdev);
|
||||
struct i40e_ring *tx_ring, *rx_ring;
|
||||
struct i40e_vsi *vsi = np->vsi;
|
||||
struct rtnl_link_stats64 *vsi_stats = i40e_get_vsi_stats_struct(vsi);
|
||||
struct i40e_ring *ring;
|
||||
int i;
|
||||
|
||||
if (test_bit(__I40E_VSI_DOWN, vsi->state))
|
||||
@@ -440,24 +440,26 @@ static void i40e_get_netdev_stats_struct(struct net_device *netdev,
|
||||
u64 bytes, packets;
|
||||
unsigned int start;
|
||||
|
||||
tx_ring = READ_ONCE(vsi->tx_rings[i]);
|
||||
if (!tx_ring)
|
||||
ring = READ_ONCE(vsi->tx_rings[i]);
|
||||
if (!ring)
|
||||
continue;
|
||||
i40e_get_netdev_stats_struct_tx(tx_ring, stats);
|
||||
i40e_get_netdev_stats_struct_tx(ring, stats);
|
||||
|
||||
rx_ring = &tx_ring[1];
|
||||
if (i40e_enabled_xdp_vsi(vsi)) {
|
||||
ring++;
|
||||
i40e_get_netdev_stats_struct_tx(ring, stats);
|
||||
}
|
||||
|
||||
ring++;
|
||||
do {
|
||||
start = u64_stats_fetch_begin_irq(&rx_ring->syncp);
|
||||
packets = rx_ring->stats.packets;
|
||||
bytes = rx_ring->stats.bytes;
|
||||
} while (u64_stats_fetch_retry_irq(&rx_ring->syncp, start));
|
||||
start = u64_stats_fetch_begin_irq(&ring->syncp);
|
||||
packets = ring->stats.packets;
|
||||
bytes = ring->stats.bytes;
|
||||
} while (u64_stats_fetch_retry_irq(&ring->syncp, start));
|
||||
|
||||
stats->rx_packets += packets;
|
||||
stats->rx_bytes += bytes;
|
||||
|
||||
if (i40e_enabled_xdp_vsi(vsi))
|
||||
i40e_get_netdev_stats_struct_tx(&rx_ring[1], stats);
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
|
||||
@@ -2645,6 +2645,8 @@ int mlx4_cmd_use_events(struct mlx4_dev *dev)
|
||||
if (!priv->cmd.context)
|
||||
return -ENOMEM;
|
||||
|
||||
if (mlx4_is_mfunc(dev))
|
||||
mutex_lock(&priv->cmd.slave_cmd_mutex);
|
||||
down_write(&priv->cmd.switch_sem);
|
||||
for (i = 0; i < priv->cmd.max_cmds; ++i) {
|
||||
priv->cmd.context[i].token = i;
|
||||
@@ -2670,6 +2672,8 @@ int mlx4_cmd_use_events(struct mlx4_dev *dev)
|
||||
down(&priv->cmd.poll_sem);
|
||||
priv->cmd.use_events = 1;
|
||||
up_write(&priv->cmd.switch_sem);
|
||||
if (mlx4_is_mfunc(dev))
|
||||
mutex_unlock(&priv->cmd.slave_cmd_mutex);
|
||||
|
||||
return err;
|
||||
}
|
||||
@@ -2682,6 +2686,8 @@ void mlx4_cmd_use_polling(struct mlx4_dev *dev)
|
||||
struct mlx4_priv *priv = mlx4_priv(dev);
|
||||
int i;
|
||||
|
||||
if (mlx4_is_mfunc(dev))
|
||||
mutex_lock(&priv->cmd.slave_cmd_mutex);
|
||||
down_write(&priv->cmd.switch_sem);
|
||||
priv->cmd.use_events = 0;
|
||||
|
||||
@@ -2689,9 +2695,12 @@ void mlx4_cmd_use_polling(struct mlx4_dev *dev)
|
||||
down(&priv->cmd.event_sem);
|
||||
|
||||
kfree(priv->cmd.context);
|
||||
priv->cmd.context = NULL;
|
||||
|
||||
up(&priv->cmd.poll_sem);
|
||||
up_write(&priv->cmd.switch_sem);
|
||||
if (mlx4_is_mfunc(dev))
|
||||
mutex_unlock(&priv->cmd.slave_cmd_mutex);
|
||||
}
|
||||
|
||||
struct mlx4_cmd_mailbox *mlx4_alloc_cmd_mailbox(struct mlx4_dev *dev)
|
||||
|
||||
@@ -2719,13 +2719,13 @@ static int qp_get_mtt_size(struct mlx4_qp_context *qpc)
|
||||
int total_pages;
|
||||
int total_mem;
|
||||
int page_offset = (be32_to_cpu(qpc->params2) >> 6) & 0x3f;
|
||||
int tot;
|
||||
|
||||
sq_size = 1 << (log_sq_size + log_sq_sride + 4);
|
||||
rq_size = (srq|rss|xrc) ? 0 : (1 << (log_rq_size + log_rq_stride + 4));
|
||||
total_mem = sq_size + rq_size;
|
||||
total_pages =
|
||||
roundup_pow_of_two((total_mem + (page_offset << 6)) >>
|
||||
page_shift);
|
||||
tot = (total_mem + (page_offset << 6)) >> page_shift;
|
||||
total_pages = !tot ? 1 : roundup_pow_of_two(tot);
|
||||
|
||||
return total_pages;
|
||||
}
|
||||
|
||||
@@ -585,8 +585,7 @@ static int lan743x_intr_open(struct lan743x_adapter *adapter)
|
||||
|
||||
if (adapter->csr.flags &
|
||||
LAN743X_CSR_FLAG_SUPPORTS_INTR_AUTO_SET_CLR) {
|
||||
flags = LAN743X_VECTOR_FLAG_VECTOR_ENABLE_AUTO_CLEAR |
|
||||
LAN743X_VECTOR_FLAG_VECTOR_ENABLE_AUTO_SET |
|
||||
flags = LAN743X_VECTOR_FLAG_VECTOR_ENABLE_AUTO_SET |
|
||||
LAN743X_VECTOR_FLAG_SOURCE_ENABLE_AUTO_SET |
|
||||
LAN743X_VECTOR_FLAG_SOURCE_ENABLE_AUTO_CLEAR |
|
||||
LAN743X_VECTOR_FLAG_SOURCE_STATUS_AUTO_CLEAR;
|
||||
@@ -599,12 +598,6 @@ static int lan743x_intr_open(struct lan743x_adapter *adapter)
|
||||
/* map TX interrupt to vector */
|
||||
int_vec_map1 |= INT_VEC_MAP1_TX_VEC_(index, vector);
|
||||
lan743x_csr_write(adapter, INT_VEC_MAP1, int_vec_map1);
|
||||
if (flags &
|
||||
LAN743X_VECTOR_FLAG_VECTOR_ENABLE_AUTO_CLEAR) {
|
||||
int_vec_en_auto_clr |= INT_VEC_EN_(vector);
|
||||
lan743x_csr_write(adapter, INT_VEC_EN_AUTO_CLR,
|
||||
int_vec_en_auto_clr);
|
||||
}
|
||||
|
||||
/* Remove TX interrupt from shared mask */
|
||||
intr->vector_list[0].int_mask &= ~int_bit;
|
||||
@@ -1905,7 +1898,17 @@ static int lan743x_rx_next_index(struct lan743x_rx *rx, int index)
|
||||
return ((++index) % rx->ring_size);
|
||||
}
|
||||
|
||||
static int lan743x_rx_allocate_ring_element(struct lan743x_rx *rx, int index)
|
||||
static struct sk_buff *lan743x_rx_allocate_skb(struct lan743x_rx *rx)
|
||||
{
|
||||
int length = 0;
|
||||
|
||||
length = (LAN743X_MAX_FRAME_SIZE + ETH_HLEN + 4 + RX_HEAD_PADDING);
|
||||
return __netdev_alloc_skb(rx->adapter->netdev,
|
||||
length, GFP_ATOMIC | GFP_DMA);
|
||||
}
|
||||
|
||||
static int lan743x_rx_init_ring_element(struct lan743x_rx *rx, int index,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct lan743x_rx_buffer_info *buffer_info;
|
||||
struct lan743x_rx_descriptor *descriptor;
|
||||
@@ -1914,9 +1917,7 @@ static int lan743x_rx_allocate_ring_element(struct lan743x_rx *rx, int index)
|
||||
length = (LAN743X_MAX_FRAME_SIZE + ETH_HLEN + 4 + RX_HEAD_PADDING);
|
||||
descriptor = &rx->ring_cpu_ptr[index];
|
||||
buffer_info = &rx->buffer_info[index];
|
||||
buffer_info->skb = __netdev_alloc_skb(rx->adapter->netdev,
|
||||
length,
|
||||
GFP_ATOMIC | GFP_DMA);
|
||||
buffer_info->skb = skb;
|
||||
if (!(buffer_info->skb))
|
||||
return -ENOMEM;
|
||||
buffer_info->dma_ptr = dma_map_single(&rx->adapter->pdev->dev,
|
||||
@@ -2063,8 +2064,19 @@ static int lan743x_rx_process_packet(struct lan743x_rx *rx)
|
||||
/* packet is available */
|
||||
if (first_index == last_index) {
|
||||
/* single buffer packet */
|
||||
struct sk_buff *new_skb = NULL;
|
||||
int packet_length;
|
||||
|
||||
new_skb = lan743x_rx_allocate_skb(rx);
|
||||
if (!new_skb) {
|
||||
/* failed to allocate next skb.
|
||||
* Memory is very low.
|
||||
* Drop this packet and reuse buffer.
|
||||
*/
|
||||
lan743x_rx_reuse_ring_element(rx, first_index);
|
||||
goto process_extension;
|
||||
}
|
||||
|
||||
buffer_info = &rx->buffer_info[first_index];
|
||||
skb = buffer_info->skb;
|
||||
descriptor = &rx->ring_cpu_ptr[first_index];
|
||||
@@ -2084,7 +2096,7 @@ static int lan743x_rx_process_packet(struct lan743x_rx *rx)
|
||||
skb_put(skb, packet_length - 4);
|
||||
skb->protocol = eth_type_trans(skb,
|
||||
rx->adapter->netdev);
|
||||
lan743x_rx_allocate_ring_element(rx, first_index);
|
||||
lan743x_rx_init_ring_element(rx, first_index, new_skb);
|
||||
} else {
|
||||
int index = first_index;
|
||||
|
||||
@@ -2097,26 +2109,23 @@ static int lan743x_rx_process_packet(struct lan743x_rx *rx)
|
||||
if (first_index <= last_index) {
|
||||
while ((index >= first_index) &&
|
||||
(index <= last_index)) {
|
||||
lan743x_rx_release_ring_element(rx,
|
||||
index);
|
||||
lan743x_rx_allocate_ring_element(rx,
|
||||
index);
|
||||
lan743x_rx_reuse_ring_element(rx,
|
||||
index);
|
||||
index = lan743x_rx_next_index(rx,
|
||||
index);
|
||||
}
|
||||
} else {
|
||||
while ((index >= first_index) ||
|
||||
(index <= last_index)) {
|
||||
lan743x_rx_release_ring_element(rx,
|
||||
index);
|
||||
lan743x_rx_allocate_ring_element(rx,
|
||||
index);
|
||||
lan743x_rx_reuse_ring_element(rx,
|
||||
index);
|
||||
index = lan743x_rx_next_index(rx,
|
||||
index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
process_extension:
|
||||
if (extension_index >= 0) {
|
||||
descriptor = &rx->ring_cpu_ptr[extension_index];
|
||||
buffer_info = &rx->buffer_info[extension_index];
|
||||
@@ -2293,7 +2302,9 @@ static int lan743x_rx_ring_init(struct lan743x_rx *rx)
|
||||
|
||||
rx->last_head = 0;
|
||||
for (index = 0; index < rx->ring_size; index++) {
|
||||
ret = lan743x_rx_allocate_ring_element(rx, index);
|
||||
struct sk_buff *new_skb = lan743x_rx_allocate_skb(rx);
|
||||
|
||||
ret = lan743x_rx_init_ring_element(rx, index, new_skb);
|
||||
if (ret)
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
@@ -459,7 +459,7 @@ static int ravb_dmac_init(struct net_device *ndev)
|
||||
RCR_EFFS | RCR_ENCF | RCR_ETS0 | RCR_ESF | 0x18000000, RCR);
|
||||
|
||||
/* Set FIFO size */
|
||||
ravb_write(ndev, TGC_TQP_AVBMODE1 | 0x00222200, TGC);
|
||||
ravb_write(ndev, TGC_TQP_AVBMODE1 | 0x00112200, TGC);
|
||||
|
||||
/* Timestamp enable */
|
||||
ravb_write(ndev, TCCR_TFEN, TCCR);
|
||||
|
||||
@@ -494,6 +494,8 @@ static int ipvlan_nl_changelink(struct net_device *dev,
|
||||
|
||||
if (!data)
|
||||
return 0;
|
||||
if (!ns_capable(dev_net(ipvlan->phy_dev)->user_ns, CAP_NET_ADMIN))
|
||||
return -EPERM;
|
||||
|
||||
if (data[IFLA_IPVLAN_MODE]) {
|
||||
u16 nmode = nla_get_u16(data[IFLA_IPVLAN_MODE]);
|
||||
@@ -596,6 +598,8 @@ int ipvlan_link_new(struct net *src_net, struct net_device *dev,
|
||||
struct ipvl_dev *tmp = netdev_priv(phy_dev);
|
||||
|
||||
phy_dev = tmp->phy_dev;
|
||||
if (!ns_capable(dev_net(phy_dev)->user_ns, CAP_NET_ADMIN))
|
||||
return -EPERM;
|
||||
} else if (!netif_is_ipvlan_port(phy_dev)) {
|
||||
/* Exit early if the underlying link is invalid or busy */
|
||||
if (phy_dev->type != ARPHRD_ETHER ||
|
||||
|
||||
@@ -380,7 +380,6 @@ int __mdiobus_register(struct mii_bus *bus, struct module *owner)
|
||||
err = device_register(&bus->dev);
|
||||
if (err) {
|
||||
pr_err("mii_bus %s failed to register\n", bus->id);
|
||||
put_device(&bus->dev);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
||||
@@ -532,6 +532,7 @@ static void pptp_sock_destruct(struct sock *sk)
|
||||
pppox_unbind_sock(sk);
|
||||
}
|
||||
skb_queue_purge(&sk->sk_receive_queue);
|
||||
dst_release(rcu_dereference_protected(sk->sk_dst_cache, 1));
|
||||
}
|
||||
|
||||
static int pptp_create(struct net *net, struct socket *sock, int kern)
|
||||
|
||||
@@ -1259,7 +1259,7 @@ static int team_port_add(struct team *team, struct net_device *port_dev,
|
||||
list_add_tail_rcu(&port->list, &team->port_list);
|
||||
team_port_enable(team, port);
|
||||
__team_compute_features(team);
|
||||
__team_port_change_port_added(port, !!netif_carrier_ok(port_dev));
|
||||
__team_port_change_port_added(port, !!netif_oper_up(port_dev));
|
||||
__team_options_change_check(team);
|
||||
|
||||
netdev_info(dev, "Port device %s added\n", portname);
|
||||
@@ -2918,7 +2918,7 @@ static int team_device_event(struct notifier_block *unused,
|
||||
|
||||
switch (event) {
|
||||
case NETDEV_UP:
|
||||
if (netif_carrier_ok(dev))
|
||||
if (netif_oper_up(dev))
|
||||
team_port_change_check(port, true);
|
||||
break;
|
||||
case NETDEV_DOWN:
|
||||
|
||||
+13
-1
@@ -1469,6 +1469,14 @@ static int vxlan_rcv(struct sock *sk, struct sk_buff *skb)
|
||||
goto drop;
|
||||
}
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
if (unlikely(!(vxlan->dev->flags & IFF_UP))) {
|
||||
rcu_read_unlock();
|
||||
atomic_long_inc(&vxlan->dev->rx_dropped);
|
||||
goto drop;
|
||||
}
|
||||
|
||||
stats = this_cpu_ptr(vxlan->dev->tstats);
|
||||
u64_stats_update_begin(&stats->syncp);
|
||||
stats->rx_packets++;
|
||||
@@ -1476,6 +1484,9 @@ static int vxlan_rcv(struct sock *sk, struct sk_buff *skb)
|
||||
u64_stats_update_end(&stats->syncp);
|
||||
|
||||
gro_cells_receive(&vxlan->gro_cells, skb);
|
||||
|
||||
rcu_read_unlock();
|
||||
|
||||
return 0;
|
||||
|
||||
drop:
|
||||
@@ -2460,6 +2471,8 @@ static void vxlan_uninit(struct net_device *dev)
|
||||
{
|
||||
struct vxlan_dev *vxlan = netdev_priv(dev);
|
||||
|
||||
gro_cells_destroy(&vxlan->gro_cells);
|
||||
|
||||
vxlan_fdb_delete_default(vxlan, vxlan->cfg.vni);
|
||||
|
||||
free_percpu(dev->tstats);
|
||||
@@ -3526,7 +3539,6 @@ static void vxlan_dellink(struct net_device *dev, struct list_head *head)
|
||||
|
||||
vxlan_flush(vxlan, true);
|
||||
|
||||
gro_cells_destroy(&vxlan->gro_cells);
|
||||
list_del(&vxlan->next);
|
||||
unregister_netdevice_queue(dev, head);
|
||||
}
|
||||
|
||||
@@ -260,6 +260,7 @@ repeat:
|
||||
}
|
||||
|
||||
#define __erofs_workgroup_get(grp) atomic_inc(&(grp)->refcount)
|
||||
#define __erofs_workgroup_put(grp) atomic_dec(&(grp)->refcount)
|
||||
|
||||
extern int erofs_workgroup_put(struct erofs_workgroup *grp);
|
||||
|
||||
|
||||
+100
-39
@@ -87,12 +87,21 @@ int erofs_register_workgroup(struct super_block *sb,
|
||||
grp = (void *)((unsigned long)grp |
|
||||
1UL << RADIX_TREE_EXCEPTIONAL_SHIFT);
|
||||
|
||||
err = radix_tree_insert(&sbi->workstn_tree,
|
||||
grp->index, grp);
|
||||
/*
|
||||
* Bump up reference count before making this workgroup
|
||||
* visible to other users in order to avoid potential UAF
|
||||
* without serialized by erofs_workstn_lock.
|
||||
*/
|
||||
__erofs_workgroup_get(grp);
|
||||
|
||||
if (!err) {
|
||||
__erofs_workgroup_get(grp);
|
||||
}
|
||||
err = radix_tree_insert(&sbi->workstn_tree,
|
||||
grp->index, grp);
|
||||
if (unlikely(err))
|
||||
/*
|
||||
* it's safe to decrease since the workgroup isn't visible
|
||||
* and refcount >= 2 (cannot be freezed).
|
||||
*/
|
||||
__erofs_workgroup_put(grp);
|
||||
|
||||
erofs_workstn_unlock(sbi);
|
||||
radix_tree_preload_end();
|
||||
@@ -101,19 +110,99 @@ int erofs_register_workgroup(struct super_block *sb,
|
||||
|
||||
extern void erofs_workgroup_free_rcu(struct erofs_workgroup *grp);
|
||||
|
||||
static void __erofs_workgroup_free(struct erofs_workgroup *grp)
|
||||
{
|
||||
atomic_long_dec(&erofs_global_shrink_cnt);
|
||||
erofs_workgroup_free_rcu(grp);
|
||||
}
|
||||
|
||||
int erofs_workgroup_put(struct erofs_workgroup *grp)
|
||||
{
|
||||
int count = atomic_dec_return(&grp->refcount);
|
||||
|
||||
if (count == 1)
|
||||
atomic_long_inc(&erofs_global_shrink_cnt);
|
||||
else if (!count) {
|
||||
atomic_long_dec(&erofs_global_shrink_cnt);
|
||||
erofs_workgroup_free_rcu(grp);
|
||||
}
|
||||
else if (!count)
|
||||
__erofs_workgroup_free(grp);
|
||||
return count;
|
||||
}
|
||||
|
||||
#ifdef EROFS_FS_HAS_MANAGED_CACHE
|
||||
/* for cache-managed case, customized reclaim paths exist */
|
||||
static void erofs_workgroup_unfreeze_final(struct erofs_workgroup *grp)
|
||||
{
|
||||
erofs_workgroup_unfreeze(grp, 0);
|
||||
__erofs_workgroup_free(grp);
|
||||
}
|
||||
|
||||
bool erofs_try_to_release_workgroup(struct erofs_sb_info *sbi,
|
||||
struct erofs_workgroup *grp,
|
||||
bool cleanup)
|
||||
{
|
||||
void *entry;
|
||||
|
||||
/*
|
||||
* for managed cache enabled, the refcount of workgroups
|
||||
* themselves could be < 0 (freezed). So there is no guarantee
|
||||
* that all refcount > 0 if managed cache is enabled.
|
||||
*/
|
||||
if (!erofs_workgroup_try_to_freeze(grp, 1))
|
||||
return false;
|
||||
|
||||
/*
|
||||
* note that all cached pages should be unlinked
|
||||
* before delete it from the radix tree.
|
||||
* Otherwise some cached pages of an orphan old workgroup
|
||||
* could be still linked after the new one is available.
|
||||
*/
|
||||
if (erofs_try_to_free_all_cached_pages(sbi, grp)) {
|
||||
erofs_workgroup_unfreeze(grp, 1);
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* it is impossible to fail after the workgroup is freezed,
|
||||
* however in order to avoid some race conditions, add a
|
||||
* DBG_BUGON to observe this in advance.
|
||||
*/
|
||||
entry = radix_tree_delete(&sbi->workstn_tree, grp->index);
|
||||
DBG_BUGON((void *)((unsigned long)entry &
|
||||
~RADIX_TREE_EXCEPTIONAL_ENTRY) != grp);
|
||||
|
||||
/*
|
||||
* if managed cache is enable, the last refcount
|
||||
* should indicate the related workstation.
|
||||
*/
|
||||
erofs_workgroup_unfreeze_final(grp);
|
||||
return true;
|
||||
}
|
||||
|
||||
#else
|
||||
/* for nocache case, no customized reclaim path at all */
|
||||
bool erofs_try_to_release_workgroup(struct erofs_sb_info *sbi,
|
||||
struct erofs_workgroup *grp,
|
||||
bool cleanup)
|
||||
{
|
||||
int cnt = atomic_read(&grp->refcount);
|
||||
void *entry;
|
||||
|
||||
DBG_BUGON(cnt <= 0);
|
||||
DBG_BUGON(cleanup && cnt != 1);
|
||||
|
||||
if (cnt > 1)
|
||||
return false;
|
||||
|
||||
entry = radix_tree_delete(&sbi->workstn_tree, grp->index);
|
||||
DBG_BUGON((void *)((unsigned long)entry &
|
||||
~RADIX_TREE_EXCEPTIONAL_ENTRY) != grp);
|
||||
|
||||
/* (rarely) could be grabbed again when freeing */
|
||||
erofs_workgroup_put(grp);
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
unsigned long erofs_shrink_workstation(struct erofs_sb_info *sbi,
|
||||
unsigned long nr_shrink,
|
||||
bool cleanup)
|
||||
@@ -130,44 +219,16 @@ repeat:
|
||||
batch, first_index, PAGEVEC_SIZE);
|
||||
|
||||
for (i = 0; i < found; ++i) {
|
||||
int cnt;
|
||||
struct erofs_workgroup *grp = (void *)
|
||||
((unsigned long)batch[i] &
|
||||
~RADIX_TREE_EXCEPTIONAL_ENTRY);
|
||||
|
||||
first_index = grp->index + 1;
|
||||
|
||||
cnt = atomic_read(&grp->refcount);
|
||||
BUG_ON(cnt <= 0);
|
||||
|
||||
if (cleanup)
|
||||
BUG_ON(cnt != 1);
|
||||
|
||||
#ifndef EROFS_FS_HAS_MANAGED_CACHE
|
||||
else if (cnt > 1)
|
||||
#else
|
||||
if (!erofs_workgroup_try_to_freeze(grp, 1))
|
||||
#endif
|
||||
/* try to shrink each valid workgroup */
|
||||
if (!erofs_try_to_release_workgroup(sbi, grp, cleanup))
|
||||
continue;
|
||||
|
||||
if (radix_tree_delete(&sbi->workstn_tree,
|
||||
grp->index) != grp) {
|
||||
#ifdef EROFS_FS_HAS_MANAGED_CACHE
|
||||
skip:
|
||||
erofs_workgroup_unfreeze(grp, 1);
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
|
||||
#ifdef EROFS_FS_HAS_MANAGED_CACHE
|
||||
if (erofs_try_to_free_all_cached_pages(sbi, grp))
|
||||
goto skip;
|
||||
|
||||
erofs_workgroup_unfreeze(grp, 1);
|
||||
#endif
|
||||
/* (rarely) grabbed again when freeing */
|
||||
erofs_workgroup_put(grp);
|
||||
|
||||
++freed;
|
||||
if (unlikely(!--nr_shrink))
|
||||
break;
|
||||
|
||||
@@ -642,7 +642,7 @@ static int vhost_vsock_set_cid(struct vhost_vsock *vsock, u64 guest_cid)
|
||||
hash_del_rcu(&vsock->hash);
|
||||
|
||||
vsock->guest_cid = guest_cid;
|
||||
hash_add_rcu(vhost_vsock_hash, &vsock->hash, guest_cid);
|
||||
hash_add_rcu(vhost_vsock_hash, &vsock->hash, vsock->guest_cid);
|
||||
spin_unlock_bh(&vhost_vsock_lock);
|
||||
|
||||
return 0;
|
||||
|
||||
+18
-4
@@ -13,22 +13,36 @@ int gro_cells_receive(struct gro_cells *gcells, struct sk_buff *skb)
|
||||
{
|
||||
struct net_device *dev = skb->dev;
|
||||
struct gro_cell *cell;
|
||||
int res;
|
||||
|
||||
if (!gcells->cells || skb_cloned(skb) || netif_elide_gro(dev))
|
||||
return netif_rx(skb);
|
||||
rcu_read_lock();
|
||||
if (unlikely(!(dev->flags & IFF_UP)))
|
||||
goto drop;
|
||||
|
||||
if (!gcells->cells || skb_cloned(skb) || netif_elide_gro(dev)) {
|
||||
res = netif_rx(skb);
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
cell = this_cpu_ptr(gcells->cells);
|
||||
|
||||
if (skb_queue_len(&cell->napi_skbs) > netdev_max_backlog) {
|
||||
drop:
|
||||
atomic_long_inc(&dev->rx_dropped);
|
||||
kfree_skb(skb);
|
||||
return NET_RX_DROP;
|
||||
res = NET_RX_DROP;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
__skb_queue_tail(&cell->napi_skbs, skb);
|
||||
if (skb_queue_len(&cell->napi_skbs) == 1)
|
||||
napi_schedule(&cell->napi);
|
||||
return NET_RX_SUCCESS;
|
||||
|
||||
res = NET_RX_SUCCESS;
|
||||
|
||||
unlock:
|
||||
rcu_read_unlock();
|
||||
return res;
|
||||
}
|
||||
EXPORT_SYMBOL(gro_cells_receive);
|
||||
|
||||
|
||||
@@ -94,9 +94,8 @@ static void hsr_check_announce(struct net_device *hsr_dev,
|
||||
&& (old_operstate != IF_OPER_UP)) {
|
||||
/* Went up */
|
||||
hsr->announce_count = 0;
|
||||
hsr->announce_timer.expires = jiffies +
|
||||
msecs_to_jiffies(HSR_ANNOUNCE_INTERVAL);
|
||||
add_timer(&hsr->announce_timer);
|
||||
mod_timer(&hsr->announce_timer,
|
||||
jiffies + msecs_to_jiffies(HSR_ANNOUNCE_INTERVAL));
|
||||
}
|
||||
|
||||
if ((hsr_dev->operstate != IF_OPER_UP) && (old_operstate == IF_OPER_UP))
|
||||
@@ -332,6 +331,7 @@ static void hsr_announce(struct timer_list *t)
|
||||
{
|
||||
struct hsr_priv *hsr;
|
||||
struct hsr_port *master;
|
||||
unsigned long interval;
|
||||
|
||||
hsr = from_timer(hsr, t, announce_timer);
|
||||
|
||||
@@ -343,18 +343,16 @@ static void hsr_announce(struct timer_list *t)
|
||||
hsr->protVersion);
|
||||
hsr->announce_count++;
|
||||
|
||||
hsr->announce_timer.expires = jiffies +
|
||||
msecs_to_jiffies(HSR_ANNOUNCE_INTERVAL);
|
||||
interval = msecs_to_jiffies(HSR_ANNOUNCE_INTERVAL);
|
||||
} else {
|
||||
send_hsr_supervision_frame(master, HSR_TLV_LIFE_CHECK,
|
||||
hsr->protVersion);
|
||||
|
||||
hsr->announce_timer.expires = jiffies +
|
||||
msecs_to_jiffies(HSR_LIFE_CHECK_INTERVAL);
|
||||
interval = msecs_to_jiffies(HSR_LIFE_CHECK_INTERVAL);
|
||||
}
|
||||
|
||||
if (is_admin_up(master->dev))
|
||||
add_timer(&hsr->announce_timer);
|
||||
mod_timer(&hsr->announce_timer, jiffies + interval);
|
||||
|
||||
rcu_read_unlock();
|
||||
}
|
||||
@@ -486,7 +484,7 @@ int hsr_dev_finalize(struct net_device *hsr_dev, struct net_device *slave[2],
|
||||
|
||||
res = hsr_add_port(hsr, hsr_dev, HSR_PT_MASTER);
|
||||
if (res)
|
||||
return res;
|
||||
goto err_add_port;
|
||||
|
||||
res = register_netdevice(hsr_dev);
|
||||
if (res)
|
||||
@@ -506,6 +504,8 @@ int hsr_dev_finalize(struct net_device *hsr_dev, struct net_device *slave[2],
|
||||
fail:
|
||||
hsr_for_each_port(hsr, port)
|
||||
hsr_del_port(port);
|
||||
err_add_port:
|
||||
hsr_del_node(&hsr->self_node_db);
|
||||
|
||||
return res;
|
||||
}
|
||||
@@ -124,6 +124,18 @@ int hsr_create_self_node(struct list_head *self_node_db,
|
||||
return 0;
|
||||
}
|
||||
|
||||
void hsr_del_node(struct list_head *self_node_db)
|
||||
{
|
||||
struct hsr_node *node;
|
||||
|
||||
rcu_read_lock();
|
||||
node = list_first_or_null_rcu(self_node_db, struct hsr_node, mac_list);
|
||||
rcu_read_unlock();
|
||||
if (node) {
|
||||
list_del_rcu(&node->mac_list);
|
||||
kfree(node);
|
||||
}
|
||||
}
|
||||
|
||||
/* Allocate an hsr_node and add it to node_db. 'addr' is the node's AddressA;
|
||||
* seq_out is used to initialize filtering of outgoing duplicate frames
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
struct hsr_node;
|
||||
|
||||
void hsr_del_node(struct list_head *self_node_db);
|
||||
struct hsr_node *hsr_add_node(struct list_head *node_db, unsigned char addr[],
|
||||
u16 seq_out);
|
||||
struct hsr_node *hsr_get_node(struct hsr_port *port, struct sk_buff *skb,
|
||||
|
||||
+9
-4
@@ -1308,6 +1308,10 @@ static void ip_del_fnhe(struct fib_nh *nh, __be32 daddr)
|
||||
if (fnhe->fnhe_daddr == daddr) {
|
||||
rcu_assign_pointer(*fnhe_p, rcu_dereference_protected(
|
||||
fnhe->fnhe_next, lockdep_is_held(&fnhe_lock)));
|
||||
/* set fnhe_daddr to 0 to ensure it won't bind with
|
||||
* new dsts in rt_bind_exception().
|
||||
*/
|
||||
fnhe->fnhe_daddr = 0;
|
||||
fnhe_flush_routes(fnhe);
|
||||
kfree_rcu(fnhe, rcu);
|
||||
break;
|
||||
@@ -2155,12 +2159,13 @@ int ip_route_input_rcu(struct sk_buff *skb, __be32 daddr, __be32 saddr,
|
||||
int our = 0;
|
||||
int err = -EINVAL;
|
||||
|
||||
if (in_dev)
|
||||
our = ip_check_mc_rcu(in_dev, daddr, saddr,
|
||||
ip_hdr(skb)->protocol);
|
||||
if (!in_dev)
|
||||
return err;
|
||||
our = ip_check_mc_rcu(in_dev, daddr, saddr,
|
||||
ip_hdr(skb)->protocol);
|
||||
|
||||
/* check l3 master if no match yet */
|
||||
if ((!in_dev || !our) && netif_is_l3_slave(dev)) {
|
||||
if (!our && netif_is_l3_slave(dev)) {
|
||||
struct in_device *l3_in_dev;
|
||||
|
||||
l3_in_dev = __in_dev_get_rcu(skb->dev);
|
||||
|
||||
@@ -216,7 +216,12 @@ struct sock *tcp_get_cookie_sock(struct sock *sk, struct sk_buff *skb,
|
||||
refcount_set(&req->rsk_refcnt, 1);
|
||||
tcp_sk(child)->tsoffset = tsoff;
|
||||
sock_rps_save_rxhash(child, skb);
|
||||
inet_csk_reqsk_queue_add(sk, req, child);
|
||||
if (!inet_csk_reqsk_queue_add(sk, req, child)) {
|
||||
bh_unlock_sock(child);
|
||||
sock_put(child);
|
||||
child = NULL;
|
||||
reqsk_put(req);
|
||||
}
|
||||
} else {
|
||||
reqsk_free(req);
|
||||
}
|
||||
|
||||
@@ -1901,6 +1901,11 @@ static int tcp_inq_hint(struct sock *sk)
|
||||
inq = tp->rcv_nxt - tp->copied_seq;
|
||||
release_sock(sk);
|
||||
}
|
||||
/* After receiving a FIN, tell the user-space to continue reading
|
||||
* by returning a non-zero inq.
|
||||
*/
|
||||
if (inq == 0 && sock_flag(sk, SOCK_DONE))
|
||||
inq = 1;
|
||||
return inq;
|
||||
}
|
||||
|
||||
|
||||
@@ -6493,7 +6493,13 @@ int tcp_conn_request(struct request_sock_ops *rsk_ops,
|
||||
af_ops->send_synack(fastopen_sk, dst, &fl, req,
|
||||
&foc, TCP_SYNACK_FASTOPEN);
|
||||
/* Add the child socket directly into the accept queue */
|
||||
inet_csk_reqsk_queue_add(sk, req, fastopen_sk);
|
||||
if (!inet_csk_reqsk_queue_add(sk, req, fastopen_sk)) {
|
||||
reqsk_fastopen_remove(fastopen_sk, req, false);
|
||||
bh_unlock_sock(fastopen_sk);
|
||||
sock_put(fastopen_sk);
|
||||
reqsk_put(req);
|
||||
goto drop;
|
||||
}
|
||||
sk->sk_data_ready(sk);
|
||||
bh_unlock_sock(fastopen_sk);
|
||||
sock_put(fastopen_sk);
|
||||
|
||||
+1
-8
@@ -1646,15 +1646,8 @@ EXPORT_SYMBOL(tcp_add_backlog);
|
||||
int tcp_filter(struct sock *sk, struct sk_buff *skb)
|
||||
{
|
||||
struct tcphdr *th = (struct tcphdr *)skb->data;
|
||||
unsigned int eaten = skb->len;
|
||||
int err;
|
||||
|
||||
err = sk_filter_trim_cap(sk, skb, th->doff * 4);
|
||||
if (!err) {
|
||||
eaten -= skb->len;
|
||||
TCP_SKB_CB(skb)->end_seq -= eaten;
|
||||
}
|
||||
return err;
|
||||
return sk_filter_trim_cap(sk, skb, th->doff * 4);
|
||||
}
|
||||
EXPORT_SYMBOL(tcp_filter);
|
||||
|
||||
|
||||
+24
-8
@@ -1282,18 +1282,29 @@ static DEFINE_SPINLOCK(rt6_exception_lock);
|
||||
static void rt6_remove_exception(struct rt6_exception_bucket *bucket,
|
||||
struct rt6_exception *rt6_ex)
|
||||
{
|
||||
struct fib6_info *from;
|
||||
struct net *net;
|
||||
|
||||
if (!bucket || !rt6_ex)
|
||||
return;
|
||||
|
||||
net = dev_net(rt6_ex->rt6i->dst.dev);
|
||||
net->ipv6.rt6_stats->fib_rt_cache--;
|
||||
|
||||
/* purge completely the exception to allow releasing the held resources:
|
||||
* some [sk] cache may keep the dst around for unlimited time
|
||||
*/
|
||||
from = rcu_dereference_protected(rt6_ex->rt6i->from,
|
||||
lockdep_is_held(&rt6_exception_lock));
|
||||
rcu_assign_pointer(rt6_ex->rt6i->from, NULL);
|
||||
fib6_info_release(from);
|
||||
dst_dev_put(&rt6_ex->rt6i->dst);
|
||||
|
||||
hlist_del_rcu(&rt6_ex->hlist);
|
||||
dst_release(&rt6_ex->rt6i->dst);
|
||||
kfree_rcu(rt6_ex, rcu);
|
||||
WARN_ON_ONCE(!bucket->depth);
|
||||
bucket->depth--;
|
||||
net->ipv6.rt6_stats->fib_rt_cache--;
|
||||
}
|
||||
|
||||
/* Remove oldest rt6_ex in bucket and free the memory
|
||||
@@ -1612,15 +1623,15 @@ static int rt6_remove_exception_rt(struct rt6_info *rt)
|
||||
static void rt6_update_exception_stamp_rt(struct rt6_info *rt)
|
||||
{
|
||||
struct rt6_exception_bucket *bucket;
|
||||
struct fib6_info *from = rt->from;
|
||||
struct in6_addr *src_key = NULL;
|
||||
struct rt6_exception *rt6_ex;
|
||||
|
||||
if (!from ||
|
||||
!(rt->rt6i_flags & RTF_CACHE))
|
||||
return;
|
||||
struct fib6_info *from;
|
||||
|
||||
rcu_read_lock();
|
||||
from = rcu_dereference(rt->from);
|
||||
if (!from || !(rt->rt6i_flags & RTF_CACHE))
|
||||
goto unlock;
|
||||
|
||||
bucket = rcu_dereference(from->rt6i_exception_bucket);
|
||||
|
||||
#ifdef CONFIG_IPV6_SUBTREES
|
||||
@@ -1639,6 +1650,7 @@ static void rt6_update_exception_stamp_rt(struct rt6_info *rt)
|
||||
if (rt6_ex)
|
||||
rt6_ex->stamp = jiffies;
|
||||
|
||||
unlock:
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
@@ -2796,20 +2808,24 @@ static int ip6_route_check_nh_onlink(struct net *net,
|
||||
u32 tbid = l3mdev_fib_table(dev) ? : RT_TABLE_MAIN;
|
||||
const struct in6_addr *gw_addr = &cfg->fc_gateway;
|
||||
u32 flags = RTF_LOCAL | RTF_ANYCAST | RTF_REJECT;
|
||||
struct fib6_info *from;
|
||||
struct rt6_info *grt;
|
||||
int err;
|
||||
|
||||
err = 0;
|
||||
grt = ip6_nh_lookup_table(net, cfg, gw_addr, tbid, 0);
|
||||
if (grt) {
|
||||
rcu_read_lock();
|
||||
from = rcu_dereference(grt->from);
|
||||
if (!grt->dst.error &&
|
||||
/* ignore match if it is the default route */
|
||||
grt->from && !ipv6_addr_any(&grt->from->fib6_dst.addr) &&
|
||||
from && !ipv6_addr_any(&from->fib6_dst.addr) &&
|
||||
(grt->rt6i_flags & flags || dev != grt->dst.dev)) {
|
||||
NL_SET_ERR_MSG(extack,
|
||||
"Nexthop has invalid gateway or device mismatch");
|
||||
err = -EINVAL;
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
ip6_rt_put(grt);
|
||||
}
|
||||
@@ -4687,7 +4703,7 @@ static int rt6_fill_node(struct net *net, struct sk_buff *skb,
|
||||
table = rt->fib6_table->tb6_id;
|
||||
else
|
||||
table = RT6_TABLE_UNSPEC;
|
||||
rtm->rtm_table = table;
|
||||
rtm->rtm_table = table < 256 ? table : RT_TABLE_COMPAT;
|
||||
if (nla_put_u32(skb, RTA_TABLE, table))
|
||||
goto nla_put_failure;
|
||||
|
||||
|
||||
+3
-2
@@ -778,8 +778,9 @@ static bool check_6rd(struct ip_tunnel *tunnel, const struct in6_addr *v6dst,
|
||||
pbw0 = tunnel->ip6rd.prefixlen >> 5;
|
||||
pbi0 = tunnel->ip6rd.prefixlen & 0x1f;
|
||||
|
||||
d = (ntohl(v6dst->s6_addr32[pbw0]) << pbi0) >>
|
||||
tunnel->ip6rd.relay_prefixlen;
|
||||
d = tunnel->ip6rd.relay_prefixlen < 32 ?
|
||||
(ntohl(v6dst->s6_addr32[pbw0]) << pbi0) >>
|
||||
tunnel->ip6rd.relay_prefixlen : 0;
|
||||
|
||||
pbi1 = pbi0 - tunnel->ip6rd.relay_prefixlen;
|
||||
if (pbi1 > 0)
|
||||
|
||||
+1
-3
@@ -674,9 +674,6 @@ static int l2tp_ip6_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,
|
||||
if (flags & MSG_OOB)
|
||||
goto out;
|
||||
|
||||
if (addr_len)
|
||||
*addr_len = sizeof(*lsa);
|
||||
|
||||
if (flags & MSG_ERRQUEUE)
|
||||
return ipv6_recv_error(sk, msg, len, addr_len);
|
||||
|
||||
@@ -706,6 +703,7 @@ static int l2tp_ip6_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,
|
||||
lsa->l2tp_conn_id = 0;
|
||||
if (ipv6_addr_type(&lsa->l2tp_addr) & IPV6_ADDR_LINKLOCAL)
|
||||
lsa->l2tp_scope_id = inet6_iif(skb);
|
||||
*addr_len = sizeof(*lsa);
|
||||
}
|
||||
|
||||
if (np->rxopt.all)
|
||||
|
||||
@@ -353,7 +353,7 @@ static int rxrpc_get_client_conn(struct rxrpc_sock *rx,
|
||||
* normally have to take channel_lock but we do this before anyone else
|
||||
* can see the connection.
|
||||
*/
|
||||
list_add_tail(&call->chan_wait_link, &candidate->waiting_calls);
|
||||
list_add(&call->chan_wait_link, &candidate->waiting_calls);
|
||||
|
||||
if (cp->exclusive) {
|
||||
call->conn = candidate;
|
||||
@@ -432,7 +432,7 @@ found_extant_conn:
|
||||
call->conn = conn;
|
||||
call->security_ix = conn->security_ix;
|
||||
call->service_id = conn->service_id;
|
||||
list_add(&call->chan_wait_link, &conn->waiting_calls);
|
||||
list_add_tail(&call->chan_wait_link, &conn->waiting_calls);
|
||||
spin_unlock(&conn->channel_lock);
|
||||
_leave(" = 0 [extant %d]", conn->debug_id);
|
||||
return 0;
|
||||
|
||||
+25
-24
@@ -1213,6 +1213,24 @@ static int fl_change(struct net *net, struct sk_buff *in_skb,
|
||||
if (err < 0)
|
||||
goto errout;
|
||||
|
||||
if (tb[TCA_FLOWER_FLAGS]) {
|
||||
fnew->flags = nla_get_u32(tb[TCA_FLOWER_FLAGS]);
|
||||
|
||||
if (!tc_flags_valid(fnew->flags)) {
|
||||
err = -EINVAL;
|
||||
goto errout;
|
||||
}
|
||||
}
|
||||
|
||||
err = fl_set_parms(net, tp, fnew, mask, base, tb, tca[TCA_RATE], ovr,
|
||||
tp->chain->tmplt_priv, extack);
|
||||
if (err)
|
||||
goto errout;
|
||||
|
||||
err = fl_check_assign_mask(head, fnew, fold, mask);
|
||||
if (err)
|
||||
goto errout;
|
||||
|
||||
if (!handle) {
|
||||
handle = 1;
|
||||
err = idr_alloc_u32(&head->handle_idr, fnew, &handle,
|
||||
@@ -1223,37 +1241,19 @@ static int fl_change(struct net *net, struct sk_buff *in_skb,
|
||||
handle, GFP_KERNEL);
|
||||
}
|
||||
if (err)
|
||||
goto errout;
|
||||
goto errout_mask;
|
||||
fnew->handle = handle;
|
||||
|
||||
if (tb[TCA_FLOWER_FLAGS]) {
|
||||
fnew->flags = nla_get_u32(tb[TCA_FLOWER_FLAGS]);
|
||||
|
||||
if (!tc_flags_valid(fnew->flags)) {
|
||||
err = -EINVAL;
|
||||
goto errout_idr;
|
||||
}
|
||||
}
|
||||
|
||||
err = fl_set_parms(net, tp, fnew, mask, base, tb, tca[TCA_RATE], ovr,
|
||||
tp->chain->tmplt_priv, extack);
|
||||
if (err)
|
||||
goto errout_idr;
|
||||
|
||||
err = fl_check_assign_mask(head, fnew, fold, mask);
|
||||
if (err)
|
||||
goto errout_idr;
|
||||
|
||||
if (!tc_skip_sw(fnew->flags)) {
|
||||
if (!fold && fl_lookup(fnew->mask, &fnew->mkey)) {
|
||||
err = -EEXIST;
|
||||
goto errout_mask;
|
||||
goto errout_idr;
|
||||
}
|
||||
|
||||
err = rhashtable_insert_fast(&fnew->mask->ht, &fnew->ht_node,
|
||||
fnew->mask->filter_ht_params);
|
||||
if (err)
|
||||
goto errout_mask;
|
||||
goto errout_idr;
|
||||
}
|
||||
|
||||
if (!tc_skip_hw(fnew->flags)) {
|
||||
@@ -1290,12 +1290,13 @@ static int fl_change(struct net *net, struct sk_buff *in_skb,
|
||||
kfree(mask);
|
||||
return 0;
|
||||
|
||||
errout_mask:
|
||||
fl_mask_put(head, fnew->mask, false);
|
||||
|
||||
errout_idr:
|
||||
if (!fold)
|
||||
idr_remove(&head->handle_idr, fnew->handle);
|
||||
|
||||
errout_mask:
|
||||
fl_mask_put(head, fnew->mask, false);
|
||||
|
||||
errout:
|
||||
tcf_exts_destroy(&fnew->exts);
|
||||
kfree(fnew);
|
||||
|
||||
@@ -230,8 +230,6 @@ int sctp_stream_init(struct sctp_stream *stream, __u16 outcnt, __u16 incnt,
|
||||
for (i = 0; i < stream->outcnt; i++)
|
||||
SCTP_SO(stream, i)->state = SCTP_STREAM_OPEN;
|
||||
|
||||
sched->init(stream);
|
||||
|
||||
in:
|
||||
sctp_stream_interleave_init(stream);
|
||||
if (!incnt)
|
||||
|
||||
+3
-3
@@ -113,9 +113,9 @@ struct smc_host_cdc_msg { /* Connection Data Control message */
|
||||
} __aligned(8);
|
||||
|
||||
enum smc_urg_state {
|
||||
SMC_URG_VALID, /* data present */
|
||||
SMC_URG_NOTYET, /* data pending */
|
||||
SMC_URG_READ /* data was already read */
|
||||
SMC_URG_VALID = 1, /* data present */
|
||||
SMC_URG_NOTYET = 2, /* data pending */
|
||||
SMC_URG_READ = 3, /* data was already read */
|
||||
};
|
||||
|
||||
struct smc_connection {
|
||||
|
||||
+33
-24
@@ -888,7 +888,7 @@ retry:
|
||||
addr->hash ^= sk->sk_type;
|
||||
|
||||
__unix_remove_socket(sk);
|
||||
u->addr = addr;
|
||||
smp_store_release(&u->addr, addr);
|
||||
__unix_insert_socket(&unix_socket_table[addr->hash], sk);
|
||||
spin_unlock(&unix_table_lock);
|
||||
err = 0;
|
||||
@@ -1058,7 +1058,7 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
|
||||
|
||||
err = 0;
|
||||
__unix_remove_socket(sk);
|
||||
u->addr = addr;
|
||||
smp_store_release(&u->addr, addr);
|
||||
__unix_insert_socket(list, sk);
|
||||
|
||||
out_unlock:
|
||||
@@ -1329,15 +1329,29 @@ restart:
|
||||
RCU_INIT_POINTER(newsk->sk_wq, &newu->peer_wq);
|
||||
otheru = unix_sk(other);
|
||||
|
||||
/* copy address information from listening to new sock*/
|
||||
if (otheru->addr) {
|
||||
refcount_inc(&otheru->addr->refcnt);
|
||||
newu->addr = otheru->addr;
|
||||
}
|
||||
/* copy address information from listening to new sock
|
||||
*
|
||||
* The contents of *(otheru->addr) and otheru->path
|
||||
* are seen fully set up here, since we have found
|
||||
* otheru in hash under unix_table_lock. Insertion
|
||||
* into the hash chain we'd found it in had been done
|
||||
* in an earlier critical area protected by unix_table_lock,
|
||||
* the same one where we'd set *(otheru->addr) contents,
|
||||
* as well as otheru->path and otheru->addr itself.
|
||||
*
|
||||
* Using smp_store_release() here to set newu->addr
|
||||
* is enough to make those stores, as well as stores
|
||||
* to newu->path visible to anyone who gets newu->addr
|
||||
* by smp_load_acquire(). IOW, the same warranties
|
||||
* as for unix_sock instances bound in unix_bind() or
|
||||
* in unix_autobind().
|
||||
*/
|
||||
if (otheru->path.dentry) {
|
||||
path_get(&otheru->path);
|
||||
newu->path = otheru->path;
|
||||
}
|
||||
refcount_inc(&otheru->addr->refcnt);
|
||||
smp_store_release(&newu->addr, otheru->addr);
|
||||
|
||||
/* Set credentials */
|
||||
copy_peercred(sk, other);
|
||||
@@ -1451,7 +1465,7 @@ out:
|
||||
static int unix_getname(struct socket *sock, struct sockaddr *uaddr, int peer)
|
||||
{
|
||||
struct sock *sk = sock->sk;
|
||||
struct unix_sock *u;
|
||||
struct unix_address *addr;
|
||||
DECLARE_SOCKADDR(struct sockaddr_un *, sunaddr, uaddr);
|
||||
int err = 0;
|
||||
|
||||
@@ -1466,19 +1480,15 @@ static int unix_getname(struct socket *sock, struct sockaddr *uaddr, int peer)
|
||||
sock_hold(sk);
|
||||
}
|
||||
|
||||
u = unix_sk(sk);
|
||||
unix_state_lock(sk);
|
||||
if (!u->addr) {
|
||||
addr = smp_load_acquire(&unix_sk(sk)->addr);
|
||||
if (!addr) {
|
||||
sunaddr->sun_family = AF_UNIX;
|
||||
sunaddr->sun_path[0] = 0;
|
||||
err = sizeof(short);
|
||||
} else {
|
||||
struct unix_address *addr = u->addr;
|
||||
|
||||
err = addr->len;
|
||||
memcpy(sunaddr, addr->name, addr->len);
|
||||
}
|
||||
unix_state_unlock(sk);
|
||||
sock_put(sk);
|
||||
out:
|
||||
return err;
|
||||
@@ -2071,11 +2081,11 @@ static int unix_seqpacket_recvmsg(struct socket *sock, struct msghdr *msg,
|
||||
|
||||
static void unix_copy_addr(struct msghdr *msg, struct sock *sk)
|
||||
{
|
||||
struct unix_sock *u = unix_sk(sk);
|
||||
struct unix_address *addr = smp_load_acquire(&unix_sk(sk)->addr);
|
||||
|
||||
if (u->addr) {
|
||||
msg->msg_namelen = u->addr->len;
|
||||
memcpy(msg->msg_name, u->addr->name, u->addr->len);
|
||||
if (addr) {
|
||||
msg->msg_namelen = addr->len;
|
||||
memcpy(msg->msg_name, addr->name, addr->len);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2579,15 +2589,14 @@ static int unix_open_file(struct sock *sk)
|
||||
if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN))
|
||||
return -EPERM;
|
||||
|
||||
unix_state_lock(sk);
|
||||
if (!smp_load_acquire(&unix_sk(sk)->addr))
|
||||
return -ENOENT;
|
||||
|
||||
path = unix_sk(sk)->path;
|
||||
if (!path.dentry) {
|
||||
unix_state_unlock(sk);
|
||||
if (!path.dentry)
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
path_get(&path);
|
||||
unix_state_unlock(sk);
|
||||
|
||||
fd = get_unused_fd_flags(O_CLOEXEC);
|
||||
if (fd < 0)
|
||||
@@ -2828,7 +2837,7 @@ static int unix_seq_show(struct seq_file *seq, void *v)
|
||||
(s->sk_state == TCP_ESTABLISHED ? SS_CONNECTING : SS_DISCONNECTING),
|
||||
sock_i_ino(s));
|
||||
|
||||
if (u->addr) {
|
||||
if (u->addr) { // under unix_table_lock here
|
||||
int i, len;
|
||||
seq_putc(seq, ' ');
|
||||
|
||||
|
||||
+2
-1
@@ -10,7 +10,8 @@
|
||||
|
||||
static int sk_diag_dump_name(struct sock *sk, struct sk_buff *nlskb)
|
||||
{
|
||||
struct unix_address *addr = unix_sk(sk)->addr;
|
||||
/* might or might not have unix_table_lock */
|
||||
struct unix_address *addr = smp_load_acquire(&unix_sk(sk)->addr);
|
||||
|
||||
if (!addr)
|
||||
return 0;
|
||||
|
||||
+14
-6
@@ -679,8 +679,7 @@ static int x25_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
|
||||
struct sockaddr_x25 *addr = (struct sockaddr_x25 *)uaddr;
|
||||
int len, i, rc = 0;
|
||||
|
||||
if (!sock_flag(sk, SOCK_ZAPPED) ||
|
||||
addr_len != sizeof(struct sockaddr_x25) ||
|
||||
if (addr_len != sizeof(struct sockaddr_x25) ||
|
||||
addr->sx25_family != AF_X25) {
|
||||
rc = -EINVAL;
|
||||
goto out;
|
||||
@@ -695,9 +694,13 @@ static int x25_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
|
||||
}
|
||||
|
||||
lock_sock(sk);
|
||||
x25_sk(sk)->source_addr = addr->sx25_addr;
|
||||
x25_insert_socket(sk);
|
||||
sock_reset_flag(sk, SOCK_ZAPPED);
|
||||
if (sock_flag(sk, SOCK_ZAPPED)) {
|
||||
x25_sk(sk)->source_addr = addr->sx25_addr;
|
||||
x25_insert_socket(sk);
|
||||
sock_reset_flag(sk, SOCK_ZAPPED);
|
||||
} else {
|
||||
rc = -EINVAL;
|
||||
}
|
||||
release_sock(sk);
|
||||
SOCK_DEBUG(sk, "x25_bind: socket is bound\n");
|
||||
out:
|
||||
@@ -813,8 +816,13 @@ static int x25_connect(struct socket *sock, struct sockaddr *uaddr,
|
||||
sock->state = SS_CONNECTED;
|
||||
rc = 0;
|
||||
out_put_neigh:
|
||||
if (rc)
|
||||
if (rc) {
|
||||
read_lock_bh(&x25_list_lock);
|
||||
x25_neigh_put(x25->neighbour);
|
||||
x25->neighbour = NULL;
|
||||
read_unlock_bh(&x25_list_lock);
|
||||
x25->state = X25_STATE_0;
|
||||
}
|
||||
out_put_route:
|
||||
x25_route_put(rt);
|
||||
out:
|
||||
|
||||
@@ -321,6 +321,7 @@ static void dump_common_audit_data(struct audit_buffer *ab,
|
||||
if (a->u.net->sk) {
|
||||
struct sock *sk = a->u.net->sk;
|
||||
struct unix_sock *u;
|
||||
struct unix_address *addr;
|
||||
int len = 0;
|
||||
char *p = NULL;
|
||||
|
||||
@@ -351,14 +352,15 @@ static void dump_common_audit_data(struct audit_buffer *ab,
|
||||
#endif
|
||||
case AF_UNIX:
|
||||
u = unix_sk(sk);
|
||||
addr = smp_load_acquire(&u->addr);
|
||||
if (!addr)
|
||||
break;
|
||||
if (u->path.dentry) {
|
||||
audit_log_d_path(ab, " path=", &u->path);
|
||||
break;
|
||||
}
|
||||
if (!u->addr)
|
||||
break;
|
||||
len = u->addr->len-sizeof(short);
|
||||
p = &u->addr->name->sun_path[0];
|
||||
len = addr->len-sizeof(short);
|
||||
p = &addr->name->sun_path[0];
|
||||
audit_log_format(ab, " path=");
|
||||
if (*p)
|
||||
audit_log_untrustedstring(ab, p);
|
||||
|
||||
@@ -474,7 +474,19 @@ static const struct ieee1394_device_id bebob_id_table[] = {
|
||||
/* Focusrite, SaffirePro 26 I/O */
|
||||
SND_BEBOB_DEV_ENTRY(VEN_FOCUSRITE, 0x00000003, &saffirepro_26_spec),
|
||||
/* Focusrite, SaffirePro 10 I/O */
|
||||
SND_BEBOB_DEV_ENTRY(VEN_FOCUSRITE, 0x00000006, &saffirepro_10_spec),
|
||||
{
|
||||
// The combination of vendor_id and model_id is the same as the
|
||||
// same as the one of Liquid Saffire 56.
|
||||
.match_flags = IEEE1394_MATCH_VENDOR_ID |
|
||||
IEEE1394_MATCH_MODEL_ID |
|
||||
IEEE1394_MATCH_SPECIFIER_ID |
|
||||
IEEE1394_MATCH_VERSION,
|
||||
.vendor_id = VEN_FOCUSRITE,
|
||||
.model_id = 0x000006,
|
||||
.specifier_id = 0x00a02d,
|
||||
.version = 0x010001,
|
||||
.driver_data = (kernel_ulong_t)&saffirepro_10_spec,
|
||||
},
|
||||
/* Focusrite, Saffire(no label and LE) */
|
||||
SND_BEBOB_DEV_ENTRY(VEN_FOCUSRITE, MODEL_FOCUSRITE_SAFFIRE_BOTH,
|
||||
&saffire_spec),
|
||||
|
||||
@@ -136,7 +136,9 @@ static void read_pcm_s32(struct amdtp_stream *s,
|
||||
byte = (u8 *)buffer + p->pcm_byte_offset;
|
||||
|
||||
for (c = 0; c < channels; ++c) {
|
||||
*dst = (byte[0] << 24) | (byte[1] << 16) | byte[2];
|
||||
*dst = (byte[0] << 24) |
|
||||
(byte[1] << 16) |
|
||||
(byte[2] << 8);
|
||||
byte += 3;
|
||||
dst++;
|
||||
}
|
||||
|
||||
@@ -144,9 +144,9 @@ int snd_hdac_i915_init(struct hdac_bus *bus)
|
||||
return -ENODEV;
|
||||
if (!acomp->ops) {
|
||||
request_module("i915");
|
||||
/* 10s timeout */
|
||||
/* 60s timeout */
|
||||
wait_for_completion_timeout(&bind_complete,
|
||||
msecs_to_jiffies(10 * 1000));
|
||||
msecs_to_jiffies(60 * 1000));
|
||||
}
|
||||
if (!acomp->ops) {
|
||||
dev_info(bus->dev, "couldn't bind with audio component\n");
|
||||
|
||||
@@ -936,6 +936,9 @@ static const struct snd_pci_quirk cxt5066_fixups[] = {
|
||||
SND_PCI_QUIRK(0x103c, 0x8299, "HP 800 G3 SFF", CXT_FIXUP_HP_MIC_NO_PRESENCE),
|
||||
SND_PCI_QUIRK(0x103c, 0x829a, "HP 800 G3 DM", CXT_FIXUP_HP_MIC_NO_PRESENCE),
|
||||
SND_PCI_QUIRK(0x103c, 0x8455, "HP Z2 G4", CXT_FIXUP_HP_MIC_NO_PRESENCE),
|
||||
SND_PCI_QUIRK(0x103c, 0x8456, "HP Z2 G4 SFF", CXT_FIXUP_HP_MIC_NO_PRESENCE),
|
||||
SND_PCI_QUIRK(0x103c, 0x8457, "HP Z2 G4 mini", CXT_FIXUP_HP_MIC_NO_PRESENCE),
|
||||
SND_PCI_QUIRK(0x103c, 0x8458, "HP Z2 G4 mini premium", CXT_FIXUP_HP_MIC_NO_PRESENCE),
|
||||
SND_PCI_QUIRK(0x1043, 0x138d, "Asus", CXT_FIXUP_HEADPHONE_MIC_PIN),
|
||||
SND_PCI_QUIRK(0x152d, 0x0833, "OLPC XO-1.5", CXT_FIXUP_OLPC_XO),
|
||||
SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo T400", CXT_PINCFG_LENOVO_TP410),
|
||||
|
||||
@@ -118,6 +118,7 @@ struct alc_spec {
|
||||
unsigned int has_alc5505_dsp:1;
|
||||
unsigned int no_depop_delay:1;
|
||||
unsigned int done_hp_init:1;
|
||||
unsigned int no_shutup_pins:1;
|
||||
|
||||
/* for PLL fix */
|
||||
hda_nid_t pll_nid;
|
||||
@@ -476,6 +477,14 @@ static void alc_auto_setup_eapd(struct hda_codec *codec, bool on)
|
||||
set_eapd(codec, *p, on);
|
||||
}
|
||||
|
||||
static void alc_shutup_pins(struct hda_codec *codec)
|
||||
{
|
||||
struct alc_spec *spec = codec->spec;
|
||||
|
||||
if (!spec->no_shutup_pins)
|
||||
snd_hda_shutup_pins(codec);
|
||||
}
|
||||
|
||||
/* generic shutup callback;
|
||||
* just turning off EAPD and a little pause for avoiding pop-noise
|
||||
*/
|
||||
@@ -486,7 +495,7 @@ static void alc_eapd_shutup(struct hda_codec *codec)
|
||||
alc_auto_setup_eapd(codec, false);
|
||||
if (!spec->no_depop_delay)
|
||||
msleep(200);
|
||||
snd_hda_shutup_pins(codec);
|
||||
alc_shutup_pins(codec);
|
||||
}
|
||||
|
||||
/* generic EAPD initialization */
|
||||
@@ -814,7 +823,7 @@ static inline void alc_shutup(struct hda_codec *codec)
|
||||
if (spec && spec->shutup)
|
||||
spec->shutup(codec);
|
||||
else
|
||||
snd_hda_shutup_pins(codec);
|
||||
alc_shutup_pins(codec);
|
||||
}
|
||||
|
||||
static void alc_reboot_notify(struct hda_codec *codec)
|
||||
@@ -2950,7 +2959,7 @@ static void alc269_shutup(struct hda_codec *codec)
|
||||
(alc_get_coef0(codec) & 0x00ff) == 0x018) {
|
||||
msleep(150);
|
||||
}
|
||||
snd_hda_shutup_pins(codec);
|
||||
alc_shutup_pins(codec);
|
||||
}
|
||||
|
||||
static struct coef_fw alc282_coefs[] = {
|
||||
@@ -3053,14 +3062,15 @@ static void alc282_shutup(struct hda_codec *codec)
|
||||
if (hp_pin_sense)
|
||||
msleep(85);
|
||||
|
||||
snd_hda_codec_write(codec, hp_pin, 0,
|
||||
AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0);
|
||||
if (!spec->no_shutup_pins)
|
||||
snd_hda_codec_write(codec, hp_pin, 0,
|
||||
AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0);
|
||||
|
||||
if (hp_pin_sense)
|
||||
msleep(100);
|
||||
|
||||
alc_auto_setup_eapd(codec, false);
|
||||
snd_hda_shutup_pins(codec);
|
||||
alc_shutup_pins(codec);
|
||||
alc_write_coef_idx(codec, 0x78, coef78);
|
||||
}
|
||||
|
||||
@@ -3166,15 +3176,16 @@ static void alc283_shutup(struct hda_codec *codec)
|
||||
if (hp_pin_sense)
|
||||
msleep(100);
|
||||
|
||||
snd_hda_codec_write(codec, hp_pin, 0,
|
||||
AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0);
|
||||
if (!spec->no_shutup_pins)
|
||||
snd_hda_codec_write(codec, hp_pin, 0,
|
||||
AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0);
|
||||
|
||||
alc_update_coef_idx(codec, 0x46, 0, 3 << 12);
|
||||
|
||||
if (hp_pin_sense)
|
||||
msleep(100);
|
||||
alc_auto_setup_eapd(codec, false);
|
||||
snd_hda_shutup_pins(codec);
|
||||
alc_shutup_pins(codec);
|
||||
alc_write_coef_idx(codec, 0x43, 0x9614);
|
||||
}
|
||||
|
||||
@@ -3240,14 +3251,15 @@ static void alc256_shutup(struct hda_codec *codec)
|
||||
/* NOTE: call this before clearing the pin, otherwise codec stalls */
|
||||
alc_update_coef_idx(codec, 0x46, 0, 3 << 12);
|
||||
|
||||
snd_hda_codec_write(codec, hp_pin, 0,
|
||||
AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0);
|
||||
if (!spec->no_shutup_pins)
|
||||
snd_hda_codec_write(codec, hp_pin, 0,
|
||||
AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0);
|
||||
|
||||
if (hp_pin_sense)
|
||||
msleep(100);
|
||||
|
||||
alc_auto_setup_eapd(codec, false);
|
||||
snd_hda_shutup_pins(codec);
|
||||
alc_shutup_pins(codec);
|
||||
}
|
||||
|
||||
static void alc225_init(struct hda_codec *codec)
|
||||
@@ -3334,7 +3346,7 @@ static void alc225_shutup(struct hda_codec *codec)
|
||||
msleep(100);
|
||||
|
||||
alc_auto_setup_eapd(codec, false);
|
||||
snd_hda_shutup_pins(codec);
|
||||
alc_shutup_pins(codec);
|
||||
}
|
||||
|
||||
static void alc_default_init(struct hda_codec *codec)
|
||||
@@ -3388,14 +3400,15 @@ static void alc_default_shutup(struct hda_codec *codec)
|
||||
if (hp_pin_sense)
|
||||
msleep(85);
|
||||
|
||||
snd_hda_codec_write(codec, hp_pin, 0,
|
||||
AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0);
|
||||
if (!spec->no_shutup_pins)
|
||||
snd_hda_codec_write(codec, hp_pin, 0,
|
||||
AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0);
|
||||
|
||||
if (hp_pin_sense)
|
||||
msleep(100);
|
||||
|
||||
alc_auto_setup_eapd(codec, false);
|
||||
snd_hda_shutup_pins(codec);
|
||||
alc_shutup_pins(codec);
|
||||
}
|
||||
|
||||
static void alc294_hp_init(struct hda_codec *codec)
|
||||
@@ -3412,8 +3425,9 @@ static void alc294_hp_init(struct hda_codec *codec)
|
||||
|
||||
msleep(100);
|
||||
|
||||
snd_hda_codec_write(codec, hp_pin, 0,
|
||||
AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0);
|
||||
if (!spec->no_shutup_pins)
|
||||
snd_hda_codec_write(codec, hp_pin, 0,
|
||||
AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0);
|
||||
|
||||
alc_update_coef_idx(codec, 0x6f, 0x000f, 0);/* Set HP depop to manual mode */
|
||||
alc_update_coefex_idx(codec, 0x58, 0x00, 0x8000, 0x8000); /* HP depop procedure start */
|
||||
@@ -5007,16 +5021,12 @@ static void alc_fixup_auto_mute_via_amp(struct hda_codec *codec,
|
||||
}
|
||||
}
|
||||
|
||||
static void alc_no_shutup(struct hda_codec *codec)
|
||||
{
|
||||
}
|
||||
|
||||
static void alc_fixup_no_shutup(struct hda_codec *codec,
|
||||
const struct hda_fixup *fix, int action)
|
||||
{
|
||||
if (action == HDA_FIXUP_ACT_PRE_PROBE) {
|
||||
struct alc_spec *spec = codec->spec;
|
||||
spec->shutup = alc_no_shutup;
|
||||
spec->no_shutup_pins = 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5602,6 +5612,7 @@ enum {
|
||||
ALC294_FIXUP_ASUS_SPK,
|
||||
ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE,
|
||||
ALC285_FIXUP_LENOVO_PC_BEEP_IN_NOISE,
|
||||
ALC255_FIXUP_ACER_HEADSET_MIC,
|
||||
};
|
||||
|
||||
static const struct hda_fixup alc269_fixups[] = {
|
||||
@@ -6546,6 +6557,16 @@ static const struct hda_fixup alc269_fixups[] = {
|
||||
.chained = true,
|
||||
.chain_id = ALC285_FIXUP_LENOVO_HEADPHONE_NOISE
|
||||
},
|
||||
[ALC255_FIXUP_ACER_HEADSET_MIC] = {
|
||||
.type = HDA_FIXUP_PINS,
|
||||
.v.pins = (const struct hda_pintbl[]) {
|
||||
{ 0x19, 0x03a11130 },
|
||||
{ 0x1a, 0x90a60140 }, /* use as internal mic */
|
||||
{ }
|
||||
},
|
||||
.chained = true,
|
||||
.chain_id = ALC255_FIXUP_HEADSET_MODE_NO_HP_MIC
|
||||
},
|
||||
};
|
||||
|
||||
static const struct snd_pci_quirk alc269_fixup_tbl[] = {
|
||||
@@ -6565,6 +6586,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
|
||||
SND_PCI_QUIRK(0x1025, 0x128f, "Acer Veriton Z6860G", ALC286_FIXUP_ACER_AIO_MIC_NO_PRESENCE),
|
||||
SND_PCI_QUIRK(0x1025, 0x1290, "Acer Veriton Z4860G", ALC286_FIXUP_ACER_AIO_MIC_NO_PRESENCE),
|
||||
SND_PCI_QUIRK(0x1025, 0x1291, "Acer Veriton Z4660G", ALC286_FIXUP_ACER_AIO_MIC_NO_PRESENCE),
|
||||
SND_PCI_QUIRK(0x1025, 0x1330, "Acer TravelMate X514-51T", ALC255_FIXUP_ACER_HEADSET_MIC),
|
||||
SND_PCI_QUIRK(0x1028, 0x0470, "Dell M101z", ALC269_FIXUP_DELL_M101Z),
|
||||
SND_PCI_QUIRK(0x1028, 0x054b, "Dell XPS one 2710", ALC275_FIXUP_DELL_XPS),
|
||||
SND_PCI_QUIRK(0x1028, 0x05bd, "Dell Latitude E6440", ALC292_FIXUP_DELL_E7X),
|
||||
@@ -6596,6 +6618,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
|
||||
SND_PCI_QUIRK(0x1028, 0x0704, "Dell XPS 13 9350", ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE),
|
||||
SND_PCI_QUIRK(0x1028, 0x0706, "Dell Inspiron 7559", ALC256_FIXUP_DELL_INSPIRON_7559_SUBWOOFER),
|
||||
SND_PCI_QUIRK(0x1028, 0x0725, "Dell Inspiron 3162", ALC255_FIXUP_DELL_SPK_NOISE),
|
||||
SND_PCI_QUIRK(0x1028, 0x0738, "Dell Precision 5820", ALC269_FIXUP_NO_SHUTUP),
|
||||
SND_PCI_QUIRK(0x1028, 0x075b, "Dell XPS 13 9360", ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE),
|
||||
SND_PCI_QUIRK(0x1028, 0x075c, "Dell XPS 27 7760", ALC298_FIXUP_SPK_VOLUME),
|
||||
SND_PCI_QUIRK(0x1028, 0x075d, "Dell AIO", ALC298_FIXUP_SPK_VOLUME),
|
||||
@@ -6670,11 +6693,13 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
|
||||
SND_PCI_QUIRK(0x103c, 0x2336, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
|
||||
SND_PCI_QUIRK(0x103c, 0x2337, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
|
||||
SND_PCI_QUIRK(0x103c, 0x221c, "HP EliteBook 755 G2", ALC280_FIXUP_HP_HEADSET_MIC),
|
||||
SND_PCI_QUIRK(0x103c, 0x802e, "HP Z240 SFF", ALC221_FIXUP_HP_MIC_NO_PRESENCE),
|
||||
SND_PCI_QUIRK(0x103c, 0x802f, "HP Z240", ALC221_FIXUP_HP_MIC_NO_PRESENCE),
|
||||
SND_PCI_QUIRK(0x103c, 0x820d, "HP Pavilion 15", ALC269_FIXUP_HP_MUTE_LED_MIC3),
|
||||
SND_PCI_QUIRK(0x103c, 0x8256, "HP", ALC221_FIXUP_HP_FRONT_MIC),
|
||||
SND_PCI_QUIRK(0x103c, 0x827e, "HP x360", ALC295_FIXUP_HP_X360),
|
||||
SND_PCI_QUIRK(0x103c, 0x82bf, "HP", ALC221_FIXUP_HP_MIC_NO_PRESENCE),
|
||||
SND_PCI_QUIRK(0x103c, 0x82c0, "HP", ALC221_FIXUP_HP_MIC_NO_PRESENCE),
|
||||
SND_PCI_QUIRK(0x103c, 0x82bf, "HP G3 mini", ALC221_FIXUP_HP_MIC_NO_PRESENCE),
|
||||
SND_PCI_QUIRK(0x103c, 0x82c0, "HP G3 mini premium", ALC221_FIXUP_HP_MIC_NO_PRESENCE),
|
||||
SND_PCI_QUIRK(0x103c, 0x83b9, "HP Spectre x360", ALC269_FIXUP_HP_MUTE_LED_MIC3),
|
||||
SND_PCI_QUIRK(0x1043, 0x103e, "ASUS X540SA", ALC256_FIXUP_ASUS_MIC),
|
||||
SND_PCI_QUIRK(0x1043, 0x103f, "ASUS TX300", ALC282_FIXUP_ASUS_TX300),
|
||||
@@ -6690,7 +6715,6 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
|
||||
SND_PCI_QUIRK(0x1043, 0x12e0, "ASUS X541SA", ALC256_FIXUP_ASUS_MIC),
|
||||
SND_PCI_QUIRK(0x1043, 0x13b0, "ASUS Z550SA", ALC256_FIXUP_ASUS_MIC),
|
||||
SND_PCI_QUIRK(0x1043, 0x1427, "Asus Zenbook UX31E", ALC269VB_FIXUP_ASUS_ZENBOOK),
|
||||
SND_PCI_QUIRK(0x1043, 0x14a1, "ASUS UX533FD", ALC294_FIXUP_ASUS_SPK),
|
||||
SND_PCI_QUIRK(0x1043, 0x1517, "Asus Zenbook UX31A", ALC269VB_FIXUP_ASUS_ZENBOOK_UX31A),
|
||||
SND_PCI_QUIRK(0x1043, 0x16e3, "ASUS UX50", ALC269_FIXUP_STEREO_DMIC),
|
||||
SND_PCI_QUIRK(0x1043, 0x1a13, "Asus G73Jw", ALC269_FIXUP_ASUS_G73JW),
|
||||
@@ -7303,6 +7327,10 @@ static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = {
|
||||
{0x14, 0x90170110},
|
||||
{0x1b, 0x90a70130},
|
||||
{0x21, 0x04211020}),
|
||||
SND_HDA_PIN_QUIRK(0x10ec0294, 0x1043, "ASUS", ALC294_FIXUP_ASUS_SPK,
|
||||
{0x12, 0x90a60130},
|
||||
{0x17, 0x90170110},
|
||||
{0x21, 0x03211020}),
|
||||
SND_HDA_PIN_QUIRK(0x10ec0294, 0x1043, "ASUS", ALC294_FIXUP_ASUS_SPK,
|
||||
{0x12, 0x90a60130},
|
||||
{0x17, 0x90170110},
|
||||
|
||||
Reference in new issue
Block a user