Import of kernel-5.14.0-687.36.1.el9_8
This commit is contained in:
parent
8fb3f67c3a
commit
d8f1f57754
@ -12,7 +12,7 @@ RHEL_MINOR = 8
|
||||
#
|
||||
# Use this spot to avoid future merge conflicts.
|
||||
# Do not trim this comment.
|
||||
RHEL_RELEASE = 687.34.1
|
||||
RHEL_RELEASE = 687.36.1
|
||||
|
||||
#
|
||||
# ZSTREAM
|
||||
|
||||
@ -65,6 +65,21 @@ bool arch_dma_unmap_sg_direct(struct device *dev, struct scatterlist *sg,
|
||||
|
||||
return true;
|
||||
}
|
||||
bool arch_dma_alloc_direct(struct device *dev)
|
||||
{
|
||||
if (dev->dma_ops_bypass && dev->bus_dma_limit)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool arch_dma_free_direct(struct device *dev, dma_addr_t dma_handle)
|
||||
{
|
||||
if (!dev->dma_ops_bypass || !dev->bus_dma_limit)
|
||||
return false;
|
||||
|
||||
return is_direct_handle(dev, dma_handle);
|
||||
}
|
||||
#endif /* CONFIG_ARCH_HAS_DMA_MAP_DIRECT */
|
||||
|
||||
/*
|
||||
@ -148,17 +163,12 @@ int dma_iommu_dma_supported(struct device *dev, u64 mask)
|
||||
|
||||
if (dev_is_pci(dev) && dma_iommu_bypass_supported(dev, mask)) {
|
||||
/*
|
||||
* dma_iommu_bypass_supported() sets dma_max when there is
|
||||
* 1:1 mapping but it is somehow limited.
|
||||
* ibm,pmemory is one example.
|
||||
* fixed ops will be used for RAM. This is limited by
|
||||
* bus_dma_limit which is set when RAM is pre-mapped.
|
||||
*/
|
||||
dev->dma_ops_bypass = dev->bus_dma_limit == 0;
|
||||
if (!dev->dma_ops_bypass)
|
||||
dev_warn(dev,
|
||||
"iommu: 64-bit OK but direct DMA is limited by %llx\n",
|
||||
dev->bus_dma_limit);
|
||||
else
|
||||
dev_dbg(dev, "iommu: 64-bit OK, using fixed ops\n");
|
||||
dev->dma_ops_bypass = true;
|
||||
dev_info(dev, "iommu: 64-bit OK but direct DMA is limited by %llx\n",
|
||||
dev->bus_dma_limit);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@ -1772,10 +1772,8 @@ out_failed:
|
||||
out_unlock:
|
||||
mutex_unlock(&dma_win_init_mutex);
|
||||
|
||||
/* If we have persistent memory and the window size is not big enough
|
||||
* to directly map both RAM and vPMEM, then we need to set DMA limit.
|
||||
*/
|
||||
if (pmem_present && direct_mapping && len != MAX_PHYSMEM_BITS)
|
||||
/* For pre-mapped memory, set bus_dma_limit to the max RAM */
|
||||
if (direct_mapping)
|
||||
dev->dev.bus_dma_limit = dev->dev.archdata.dma_offset +
|
||||
(1ULL << max_ram_len);
|
||||
|
||||
|
||||
@ -196,7 +196,7 @@ static void octep_vf_setup_iq_regs_cn93(struct octep_vf_device *oct, int iq_no)
|
||||
}
|
||||
|
||||
/* Setup registers for a hardware Rx Queue */
|
||||
static void octep_vf_setup_oq_regs_cn93(struct octep_vf_device *oct, int oq_no)
|
||||
static int octep_vf_setup_oq_regs_cn93(struct octep_vf_device *oct, int oq_no)
|
||||
{
|
||||
struct octep_vf_oq *oq = oct->oq[oq_no];
|
||||
u32 time_threshold = 0;
|
||||
@ -239,6 +239,7 @@ static void octep_vf_setup_oq_regs_cn93(struct octep_vf_device *oct, int oq_no)
|
||||
time_threshold = CFG_GET_OQ_INTR_TIME(oct->conf);
|
||||
reg_val = ((u64)time_threshold << 32) | CFG_GET_OQ_INTR_PKT(oct->conf);
|
||||
octep_vf_write_csr64(oct, CN93_VF_SDP_R_OUT_INT_LEVELS(oq_no), reg_val);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Setup registers for a VF mailbox */
|
||||
|
||||
@ -199,11 +199,13 @@ static void octep_vf_setup_iq_regs_cnxk(struct octep_vf_device *oct, int iq_no)
|
||||
}
|
||||
|
||||
/* Setup registers for a hardware Rx Queue */
|
||||
static void octep_vf_setup_oq_regs_cnxk(struct octep_vf_device *oct, int oq_no)
|
||||
static int octep_vf_setup_oq_regs_cnxk(struct octep_vf_device *oct, int oq_no)
|
||||
{
|
||||
struct octep_vf_oq *oq = oct->oq[oq_no];
|
||||
unsigned long t_out_jiffies;
|
||||
u32 time_threshold = 0;
|
||||
u64 oq_ctl = ULL(0);
|
||||
u64 reg_ba_val;
|
||||
u64 reg_val;
|
||||
|
||||
reg_val = octep_vf_read_csr64(oct, CNXK_VF_SDP_R_OUT_CONTROL(oq_no));
|
||||
@ -214,6 +216,38 @@ static void octep_vf_setup_oq_regs_cnxk(struct octep_vf_device *oct, int oq_no)
|
||||
reg_val = octep_vf_read_csr64(oct, CNXK_VF_SDP_R_OUT_CONTROL(oq_no));
|
||||
} while (!(reg_val & CNXK_VF_R_OUT_CTL_IDLE));
|
||||
}
|
||||
octep_vf_write_csr64(oct, CNXK_VF_SDP_R_OUT_WMARK(oq_no),
|
||||
oq->max_count);
|
||||
/* Wait for WMARK to get applied */
|
||||
usleep_range(10, 15);
|
||||
|
||||
octep_vf_write_csr64(oct, CNXK_VF_SDP_R_OUT_SLIST_BADDR(oq_no),
|
||||
oq->desc_ring_dma);
|
||||
octep_vf_write_csr64(oct, CNXK_VF_SDP_R_OUT_SLIST_RSIZE(oq_no),
|
||||
oq->max_count);
|
||||
reg_ba_val = octep_vf_read_csr64(oct,
|
||||
CNXK_VF_SDP_R_OUT_SLIST_BADDR(oq_no));
|
||||
if (reg_ba_val != oq->desc_ring_dma) {
|
||||
t_out_jiffies = jiffies + 10 * HZ;
|
||||
do {
|
||||
if (reg_ba_val == ULLONG_MAX)
|
||||
return -EFAULT;
|
||||
octep_vf_write_csr64(oct,
|
||||
CNXK_VF_SDP_R_OUT_SLIST_BADDR
|
||||
(oq_no), oq->desc_ring_dma);
|
||||
octep_vf_write_csr64(oct,
|
||||
CNXK_VF_SDP_R_OUT_SLIST_RSIZE
|
||||
(oq_no), oq->max_count);
|
||||
reg_ba_val =
|
||||
octep_vf_read_csr64(oct,
|
||||
CNXK_VF_SDP_R_OUT_SLIST_BADDR
|
||||
(oq_no));
|
||||
} while ((reg_ba_val != oq->desc_ring_dma) &&
|
||||
time_before(jiffies, t_out_jiffies));
|
||||
|
||||
if (reg_ba_val != oq->desc_ring_dma)
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
reg_val &= ~(CNXK_VF_R_OUT_CTL_IMODE);
|
||||
reg_val &= ~(CNXK_VF_R_OUT_CTL_ROR_P);
|
||||
@ -227,8 +261,6 @@ static void octep_vf_setup_oq_regs_cnxk(struct octep_vf_device *oct, int oq_no)
|
||||
reg_val |= (CNXK_VF_R_OUT_CTL_ES_P);
|
||||
|
||||
octep_vf_write_csr64(oct, CNXK_VF_SDP_R_OUT_CONTROL(oq_no), reg_val);
|
||||
octep_vf_write_csr64(oct, CNXK_VF_SDP_R_OUT_SLIST_BADDR(oq_no), oq->desc_ring_dma);
|
||||
octep_vf_write_csr64(oct, CNXK_VF_SDP_R_OUT_SLIST_RSIZE(oq_no), oq->max_count);
|
||||
|
||||
oq_ctl = octep_vf_read_csr64(oct, CNXK_VF_SDP_R_OUT_CONTROL(oq_no));
|
||||
/* Clear the ISIZE and BSIZE (22-0) */
|
||||
@ -250,6 +282,7 @@ static void octep_vf_setup_oq_regs_cnxk(struct octep_vf_device *oct, int oq_no)
|
||||
reg_val &= ~GENMASK_ULL(31, 0);
|
||||
reg_val |= CFG_GET_OQ_WMARK(oct->conf);
|
||||
octep_vf_write_csr64(oct, CNXK_VF_SDP_R_OUT_WMARK(oq_no), reg_val);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Setup registers for a VF mailbox */
|
||||
|
||||
@ -220,7 +220,7 @@ static int octep_vf_request_irqs(struct octep_vf_device *oct)
|
||||
ioq_irq_err:
|
||||
while (i) {
|
||||
--i;
|
||||
free_irq(oct->msix_entries[i].vector, oct);
|
||||
free_irq(oct->msix_entries[i].vector, oct->ioq_vector[i]);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
@ -287,29 +287,46 @@ static void octep_vf_clean_irqs(struct octep_vf_device *oct)
|
||||
octep_vf_free_ioq_vectors(oct);
|
||||
}
|
||||
|
||||
/**
|
||||
* octep_vf_update_pkt() - Update IQ/OQ IN/OUT_CNT registers.
|
||||
*
|
||||
* @iq: Octeon Tx queue data structure.
|
||||
* @oq: Octeon Rx queue data structure.
|
||||
*/
|
||||
|
||||
static void octep_vf_update_pkt(struct octep_vf_iq *iq, struct octep_vf_oq *oq)
|
||||
{
|
||||
u32 pkts_pend = READ_ONCE(oq->pkts_pending);
|
||||
u32 last_pkt_count = READ_ONCE(oq->last_pkt_count);
|
||||
u32 pkts_processed = READ_ONCE(iq->pkts_processed);
|
||||
u32 pkt_in_done = READ_ONCE(iq->pkt_in_done);
|
||||
|
||||
netdev_dbg(iq->netdev, "enabling intr for Q-%u\n", iq->q_no);
|
||||
if (pkts_processed) {
|
||||
writel(pkts_processed, iq->inst_cnt_reg);
|
||||
readl(iq->inst_cnt_reg);
|
||||
WRITE_ONCE(iq->pkt_in_done, (pkt_in_done - pkts_processed));
|
||||
WRITE_ONCE(iq->pkts_processed, 0);
|
||||
}
|
||||
if (last_pkt_count - pkts_pend) {
|
||||
writel(last_pkt_count - pkts_pend, oq->pkts_sent_reg);
|
||||
readl(oq->pkts_sent_reg);
|
||||
WRITE_ONCE(oq->last_pkt_count, pkts_pend);
|
||||
}
|
||||
|
||||
/* Flush the previous wrties before writing to RESEND bit */
|
||||
smp_wmb();
|
||||
}
|
||||
|
||||
/**
|
||||
* octep_vf_enable_ioq_irq() - Enable MSI-x interrupt of a Tx/Rx queue.
|
||||
*
|
||||
* @iq: Octeon Tx queue data structure.
|
||||
* @oq: Octeon Rx queue data structure.
|
||||
*/
|
||||
static void octep_vf_enable_ioq_irq(struct octep_vf_iq *iq, struct octep_vf_oq *oq)
|
||||
static void octep_vf_enable_ioq_irq(struct octep_vf_iq *iq,
|
||||
struct octep_vf_oq *oq)
|
||||
{
|
||||
u32 pkts_pend = oq->pkts_pending;
|
||||
|
||||
netdev_dbg(iq->netdev, "enabling intr for Q-%u\n", iq->q_no);
|
||||
if (iq->pkts_processed) {
|
||||
writel(iq->pkts_processed, iq->inst_cnt_reg);
|
||||
iq->pkt_in_done -= iq->pkts_processed;
|
||||
iq->pkts_processed = 0;
|
||||
}
|
||||
if (oq->last_pkt_count - pkts_pend) {
|
||||
writel(oq->last_pkt_count - pkts_pend, oq->pkts_sent_reg);
|
||||
oq->last_pkt_count = pkts_pend;
|
||||
}
|
||||
|
||||
/* Flush the previous wrties before writing to RESEND bit */
|
||||
smp_wmb();
|
||||
writeq(1UL << OCTEP_VF_OQ_INTR_RESEND_BIT, oq->pkts_sent_reg);
|
||||
writeq(1UL << OCTEP_VF_IQ_INTR_RESEND_BIT, iq->inst_cnt_reg);
|
||||
}
|
||||
@ -335,6 +352,7 @@ static int octep_vf_napi_poll(struct napi_struct *napi, int budget)
|
||||
if (tx_pending || rx_done >= budget)
|
||||
return budget;
|
||||
|
||||
octep_vf_update_pkt(ioq_vector->iq, ioq_vector->oq);
|
||||
if (likely(napi_complete_done(napi, rx_done)))
|
||||
octep_vf_enable_ioq_irq(ioq_vector->iq, ioq_vector->oq);
|
||||
|
||||
|
||||
@ -55,7 +55,7 @@ struct octep_vf_mmio {
|
||||
|
||||
struct octep_vf_hw_ops {
|
||||
void (*setup_iq_regs)(struct octep_vf_device *oct, int q);
|
||||
void (*setup_oq_regs)(struct octep_vf_device *oct, int q);
|
||||
int (*setup_oq_regs)(struct octep_vf_device *oct, int q);
|
||||
void (*setup_mbox_regs)(struct octep_vf_device *oct, int mbox);
|
||||
|
||||
irqreturn_t (*non_ioq_intr_handler)(void *ioq_vector);
|
||||
|
||||
@ -12,6 +12,8 @@
|
||||
#include "octep_vf_config.h"
|
||||
#include "octep_vf_main.h"
|
||||
|
||||
static void octep_vf_oq_free_ring_buffers(struct octep_vf_oq *oq);
|
||||
|
||||
static void octep_vf_oq_reset_indices(struct octep_vf_oq *oq)
|
||||
{
|
||||
oq->host_read_idx = 0;
|
||||
@ -171,11 +173,15 @@ static int octep_vf_setup_oq(struct octep_vf_device *oct, int q_no)
|
||||
goto oq_fill_buff_err;
|
||||
|
||||
octep_vf_oq_reset_indices(oq);
|
||||
oct->hw_ops.setup_oq_regs(oct, q_no);
|
||||
if (oct->hw_ops.setup_oq_regs(oct, q_no))
|
||||
goto oq_setup_err;
|
||||
|
||||
oct->num_oqs++;
|
||||
|
||||
return 0;
|
||||
|
||||
oq_setup_err:
|
||||
octep_vf_oq_free_ring_buffers(oq);
|
||||
oq_fill_buff_err:
|
||||
vfree(oq->buff_info);
|
||||
oq->buff_info = NULL;
|
||||
@ -319,9 +325,16 @@ static int octep_vf_oq_check_hw_for_pkts(struct octep_vf_device *oct,
|
||||
struct octep_vf_oq *oq)
|
||||
{
|
||||
u32 pkt_count, new_pkts;
|
||||
u32 last_pkt_count, pkts_pending;
|
||||
|
||||
pkt_count = readl(oq->pkts_sent_reg);
|
||||
new_pkts = pkt_count - oq->last_pkt_count;
|
||||
last_pkt_count = READ_ONCE(oq->last_pkt_count);
|
||||
new_pkts = pkt_count - last_pkt_count;
|
||||
|
||||
if (pkt_count < last_pkt_count) {
|
||||
dev_err(oq->dev, "OQ-%u pkt_count(%u) < oq->last_pkt_count(%u)\n",
|
||||
oq->q_no, pkt_count, last_pkt_count);
|
||||
}
|
||||
|
||||
/* Clear the hardware packets counter register if the rx queue is
|
||||
* being processed continuously with-in a single interrupt and
|
||||
@ -333,11 +346,17 @@ static int octep_vf_oq_check_hw_for_pkts(struct octep_vf_device *oct,
|
||||
pkt_count = readl(oq->pkts_sent_reg);
|
||||
new_pkts += pkt_count;
|
||||
}
|
||||
oq->last_pkt_count = pkt_count;
|
||||
oq->pkts_pending += new_pkts;
|
||||
WRITE_ONCE(oq->last_pkt_count, pkt_count);
|
||||
pkts_pending = READ_ONCE(oq->pkts_pending);
|
||||
WRITE_ONCE(oq->pkts_pending, (pkts_pending + new_pkts));
|
||||
return new_pkts;
|
||||
}
|
||||
|
||||
static inline u32 octep_vf_oq_next_idx(struct octep_vf_oq *oq, u32 idx)
|
||||
{
|
||||
return (idx + 1 == oq->max_count) ? 0 : idx + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* __octep_vf_oq_process_rx() - Process hardware Rx queue and push to stack.
|
||||
*
|
||||
@ -363,7 +382,7 @@ static int __octep_vf_oq_process_rx(struct octep_vf_device *oct,
|
||||
struct sk_buff *skb;
|
||||
u32 read_idx;
|
||||
|
||||
read_idx = oq->host_read_idx;
|
||||
read_idx = READ_ONCE(oq->host_read_idx);
|
||||
rx_bytes = 0;
|
||||
desc_used = 0;
|
||||
for (pkt = 0; pkt < pkts_to_process; pkt++) {
|
||||
@ -395,30 +414,52 @@ static int __octep_vf_oq_process_rx(struct octep_vf_device *oct,
|
||||
data_offset = OCTEP_VF_OQ_RESP_HW_SIZE;
|
||||
rx_ol_flags = 0;
|
||||
}
|
||||
rx_bytes += buff_info->len;
|
||||
|
||||
if (buff_info->len <= oq->max_single_buffer_size) {
|
||||
skb = napi_build_skb((void *)resp_hw, PAGE_SIZE);
|
||||
if (!skb) {
|
||||
oq->stats->alloc_failures++;
|
||||
desc_used++;
|
||||
read_idx = octep_vf_oq_next_idx(oq, read_idx);
|
||||
continue;
|
||||
}
|
||||
rx_bytes += buff_info->len;
|
||||
skb_reserve(skb, data_offset);
|
||||
skb_put(skb, buff_info->len);
|
||||
read_idx++;
|
||||
desc_used++;
|
||||
if (read_idx == oq->max_count)
|
||||
read_idx = 0;
|
||||
read_idx = octep_vf_oq_next_idx(oq, read_idx);
|
||||
} else {
|
||||
struct skb_shared_info *shinfo;
|
||||
u16 data_len;
|
||||
|
||||
skb = napi_build_skb((void *)resp_hw, PAGE_SIZE);
|
||||
if (!skb) {
|
||||
oq->stats->alloc_failures++;
|
||||
desc_used++;
|
||||
read_idx = octep_vf_oq_next_idx(oq, read_idx);
|
||||
data_len = buff_info->len - oq->max_single_buffer_size;
|
||||
while (data_len) {
|
||||
dma_unmap_page(oq->dev, oq->desc_ring[read_idx].buffer_ptr,
|
||||
PAGE_SIZE, DMA_FROM_DEVICE);
|
||||
buff_info = (struct octep_vf_rx_buffer *)
|
||||
&oq->buff_info[read_idx];
|
||||
buff_info->page = NULL;
|
||||
if (data_len < oq->buffer_size)
|
||||
data_len = 0;
|
||||
else
|
||||
data_len -= oq->buffer_size;
|
||||
desc_used++;
|
||||
read_idx = octep_vf_oq_next_idx(oq, read_idx);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
rx_bytes += buff_info->len;
|
||||
skb_reserve(skb, data_offset);
|
||||
/* Head fragment includes response header(s);
|
||||
* subsequent fragments contains only data.
|
||||
*/
|
||||
skb_put(skb, oq->max_single_buffer_size);
|
||||
read_idx++;
|
||||
desc_used++;
|
||||
if (read_idx == oq->max_count)
|
||||
read_idx = 0;
|
||||
read_idx = octep_vf_oq_next_idx(oq, read_idx);
|
||||
|
||||
shinfo = skb_shinfo(skb);
|
||||
data_len = buff_info->len - oq->max_single_buffer_size;
|
||||
@ -440,10 +481,8 @@ static int __octep_vf_oq_process_rx(struct octep_vf_device *oct,
|
||||
buff_info->len,
|
||||
buff_info->len);
|
||||
buff_info->page = NULL;
|
||||
read_idx++;
|
||||
desc_used++;
|
||||
if (read_idx == oq->max_count)
|
||||
read_idx = 0;
|
||||
read_idx = octep_vf_oq_next_idx(oq, read_idx);
|
||||
}
|
||||
}
|
||||
|
||||
@ -457,7 +496,7 @@ static int __octep_vf_oq_process_rx(struct octep_vf_device *oct,
|
||||
napi_gro_receive(oq->napi, skb);
|
||||
}
|
||||
|
||||
oq->host_read_idx = read_idx;
|
||||
WRITE_ONCE(oq->host_read_idx, read_idx);
|
||||
oq->refill_count += desc_used;
|
||||
oq->stats->packets += pkt;
|
||||
oq->stats->bytes += rx_bytes;
|
||||
@ -480,22 +519,26 @@ int octep_vf_oq_process_rx(struct octep_vf_oq *oq, int budget)
|
||||
{
|
||||
u32 pkts_available, pkts_processed, total_pkts_processed;
|
||||
struct octep_vf_device *oct = oq->octep_vf_dev;
|
||||
u32 pkts_pending;
|
||||
|
||||
pkts_available = 0;
|
||||
pkts_processed = 0;
|
||||
total_pkts_processed = 0;
|
||||
while (total_pkts_processed < budget) {
|
||||
/* update pending count only when current one exhausted */
|
||||
if (oq->pkts_pending == 0)
|
||||
pkts_pending = READ_ONCE(oq->pkts_pending);
|
||||
if (pkts_pending == 0)
|
||||
octep_vf_oq_check_hw_for_pkts(oct, oq);
|
||||
pkts_pending = READ_ONCE(oq->pkts_pending);
|
||||
pkts_available = min(budget - total_pkts_processed,
|
||||
oq->pkts_pending);
|
||||
pkts_pending);
|
||||
if (!pkts_available)
|
||||
break;
|
||||
|
||||
pkts_processed = __octep_vf_oq_process_rx(oct, oq,
|
||||
pkts_available);
|
||||
oq->pkts_pending -= pkts_processed;
|
||||
pkts_pending = READ_ONCE(oq->pkts_pending);
|
||||
WRITE_ONCE(oq->pkts_pending, (pkts_pending - pkts_processed));
|
||||
total_pkts_processed += pkts_processed;
|
||||
}
|
||||
|
||||
|
||||
@ -26,7 +26,7 @@ static const struct file_operations proc_sys_dir_file_operations;
|
||||
static const struct inode_operations proc_sys_dir_operations;
|
||||
|
||||
/* shared constants to be used in various sysctls */
|
||||
const int sysctl_vals[] = { -1, 0, 1, 2, 4, 100, 200, 1000, 3000, INT_MAX, 65535 };
|
||||
const int sysctl_vals[] = { -1, 0, 1, 2, 4, 100, 200, 1000, 3000, INT_MAX, 65535, MAX_RECLAIM_RETRIES, DEF_PRIORITY - 1 };
|
||||
EXPORT_SYMBOL(sysctl_vals);
|
||||
|
||||
const unsigned long sysctl_long_vals[] = { 0, 1, LONG_MAX };
|
||||
|
||||
@ -398,11 +398,15 @@ bool arch_dma_map_sg_direct(struct device *dev, struct scatterlist *sg,
|
||||
int nents);
|
||||
bool arch_dma_unmap_sg_direct(struct device *dev, struct scatterlist *sg,
|
||||
int nents);
|
||||
bool arch_dma_alloc_direct(struct device *dev);
|
||||
bool arch_dma_free_direct(struct device *dev, dma_addr_t dma_handle);
|
||||
#else
|
||||
#define arch_dma_map_page_direct(d, a) (false)
|
||||
#define arch_dma_unmap_page_direct(d, a) (false)
|
||||
#define arch_dma_map_sg_direct(d, s, n) (false)
|
||||
#define arch_dma_unmap_sg_direct(d, s, n) (false)
|
||||
#define arch_dma_alloc_direct(d) (false)
|
||||
#define arch_dma_free_direct(d, a) (false)
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ARCH_HAS_SETUP_DMA_OPS
|
||||
|
||||
@ -54,9 +54,16 @@ struct mempolicy {
|
||||
nodemask_t cpuset_mems_allowed; /* relative to these nodes */
|
||||
nodemask_t user_nodemask; /* nodemask passed by user */
|
||||
} w;
|
||||
RH_KABI_RESERVE(1)
|
||||
RH_KABI_RESERVE(2)
|
||||
RH_KABI_USE(1, 2, struct rcu_head rcu)
|
||||
RH_KABI_RESERVE(3)
|
||||
|
||||
/*
|
||||
* RH Note:
|
||||
* Struct mempolicy is always dynamically allocated with the policy_cache
|
||||
* in mpol_new(), __mpol_dup() and shared_policy_replace() of mm/memplicy.c.
|
||||
* It is also not embedded in any other data structures. So it can be
|
||||
* safely extended with RH_KABI_EXTEND() here.
|
||||
*/
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
@ -79,6 +79,11 @@ extern int page_cluster;
|
||||
extern const int page_cluster_max;
|
||||
|
||||
#ifdef CONFIG_SYSCTL
|
||||
|
||||
#ifdef CONFIG_MEMCG
|
||||
extern int sysctl_mem_cgroup_reclaim_retries;
|
||||
#endif
|
||||
|
||||
extern int sysctl_legacy_va_layout;
|
||||
#else
|
||||
#define sysctl_legacy_va_layout 0
|
||||
@ -3937,6 +3942,7 @@ static inline int in_gate_area(struct mm_struct *mm, unsigned long addr)
|
||||
extern bool process_shares_mm(struct task_struct *p, struct mm_struct *mm);
|
||||
|
||||
#ifdef CONFIG_SYSCTL
|
||||
extern int sysctl_dr_prio_drop;
|
||||
extern int sysctl_drop_caches;
|
||||
int drop_caches_sysctl_handler(struct ctl_table *, int, void *, size_t *,
|
||||
loff_t *);
|
||||
|
||||
@ -1201,6 +1201,12 @@ static inline bool zone_intersects(struct zone *zone,
|
||||
*/
|
||||
#define DEF_PRIORITY 12
|
||||
|
||||
/*
|
||||
* Maximum number of reclaim retries without progress before the OOM
|
||||
* killer is consider the only way forward.
|
||||
*/
|
||||
#define MAX_RECLAIM_RETRIES 16
|
||||
|
||||
/* Maximum number of zones on a zonelist */
|
||||
#define MAX_ZONES_PER_ZONELIST (MAX_NUMNODES * MAX_NR_ZONES)
|
||||
|
||||
|
||||
@ -51,6 +51,8 @@ struct ctl_dir;
|
||||
|
||||
/* this is needed for the proc_dointvec_minmax for [fs_]overflow UID and GID */
|
||||
#define SYSCTL_MAXOLDUID ((void *)&sysctl_vals[10])
|
||||
#define SYSCTL_MAX_RECLAIM_TRIES ((void *)&sysctl_vals[11])
|
||||
#define SYSCTL_MAX_PRIO_DROP ((void *)&sysctl_vals[12])
|
||||
|
||||
extern const int sysctl_vals[];
|
||||
|
||||
|
||||
@ -1,3 +1,3 @@
|
||||
sbat,1,SBAT Version,sbat,1,https://github.com/rhboot/shim/blob/main/SBAT.md
|
||||
kernel.rhel,1,Red Hat,kernel-core,5.14.0-687.34.1.el9.x86_64,mailto:secalert@redhat.com
|
||||
kernel.almalinux,1,AlmaLinux,kernel-core,5.14.0-687.34.1.el9.x86_64,mailto:security@almalinux.org
|
||||
kernel.rhel,1,Red Hat,kernel-core,5.14.0-687.36.1.el9.x86_64,mailto:secalert@redhat.com
|
||||
kernel.almalinux,1,AlmaLinux,kernel-core,5.14.0-687.36.1.el9.x86_64,mailto:security@almalinux.org
|
||||
|
||||
@ -632,7 +632,7 @@ void *dma_alloc_attrs(struct device *dev, size_t size, dma_addr_t *dma_handle,
|
||||
/* let the implementation decide on the zone to allocate from: */
|
||||
flag &= ~(__GFP_DMA | __GFP_DMA32 | __GFP_HIGHMEM);
|
||||
|
||||
if (dma_alloc_direct(dev, ops)) {
|
||||
if (dma_alloc_direct(dev, ops) || arch_dma_alloc_direct(dev)) {
|
||||
cpu_addr = dma_direct_alloc(dev, size, dma_handle, flag, attrs);
|
||||
} else if (use_dma_iommu(dev)) {
|
||||
cpu_addr = iommu_dma_alloc(dev, size, dma_handle, flag, attrs);
|
||||
@ -673,7 +673,7 @@ void dma_free_attrs(struct device *dev, size_t size, void *cpu_addr,
|
||||
return;
|
||||
|
||||
debug_dma_free_coherent(dev, size, cpu_addr, dma_handle);
|
||||
if (dma_alloc_direct(dev, ops))
|
||||
if (dma_alloc_direct(dev, ops) || arch_dma_free_direct(dev, dma_handle))
|
||||
dma_direct_free(dev, size, cpu_addr, dma_handle, attrs);
|
||||
else if (use_dma_iommu(dev))
|
||||
iommu_dma_free(dev, size, cpu_addr, dma_handle, attrs);
|
||||
|
||||
@ -341,7 +341,7 @@ static int __futex_key_to_node(struct mm_struct *mm, unsigned long addr)
|
||||
if (!vma)
|
||||
return FUTEX_NO_NODE;
|
||||
|
||||
mpol = vma_policy(vma);
|
||||
mpol = READ_ONCE(vma->vm_policy);
|
||||
if (!mpol)
|
||||
return FUTEX_NO_NODE;
|
||||
|
||||
|
||||
@ -918,7 +918,7 @@ int fixup_pi_owner(u32 __user *uaddr, struct futex_q *q, int locked)
|
||||
int futex_lock_pi(u32 __user *uaddr, unsigned int flags, ktime_t *time, int trylock)
|
||||
{
|
||||
struct hrtimer_sleeper timeout, *to;
|
||||
struct task_struct *exiting = NULL;
|
||||
struct task_struct *exiting;
|
||||
struct rt_mutex_waiter rt_waiter;
|
||||
struct futex_q q = futex_q_init;
|
||||
DEFINE_WAKE_Q(wake_q);
|
||||
@ -933,6 +933,7 @@ int futex_lock_pi(u32 __user *uaddr, unsigned int flags, ktime_t *time, int tryl
|
||||
to = futex_setup_timer(time, &timeout, flags, 0);
|
||||
|
||||
retry:
|
||||
exiting = NULL;
|
||||
ret = get_futex_key(uaddr, flags, &q.key, FUTEX_WRITE);
|
||||
if (unlikely(ret != 0))
|
||||
goto out;
|
||||
|
||||
@ -318,8 +318,11 @@ futex_proxy_trylock_atomic(u32 __user *pifutex, struct futex_hash_bucket *hb1,
|
||||
return -EINVAL;
|
||||
|
||||
/* Ensure that this does not race against an early wakeup */
|
||||
if (!futex_requeue_pi_prepare(top_waiter, NULL))
|
||||
if (!futex_requeue_pi_prepare(top_waiter, NULL)) {
|
||||
plist_del(&top_waiter->list, &hb1->chain);
|
||||
futex_hb_waiters_dec(hb1);
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
/*
|
||||
* Try to take the lock for top_waiter and set the FUTEX_WAITERS bit
|
||||
@ -721,10 +724,12 @@ int handle_early_requeue_pi_wakeup(struct futex_hash_bucket *hb,
|
||||
|
||||
/*
|
||||
* We were woken prior to requeue by a timeout or a signal.
|
||||
* Unqueue the futex_q and determine which it was.
|
||||
* Conditionally unqueue the futex_q and determine which it was.
|
||||
*/
|
||||
plist_del(&q->list, &hb->chain);
|
||||
futex_hb_waiters_dec(hb);
|
||||
if (!plist_node_empty(&q->list)) {
|
||||
plist_del(&q->list, &hb->chain);
|
||||
futex_hb_waiters_dec(hb);
|
||||
}
|
||||
|
||||
/* Handle spurious wakeups gracefully */
|
||||
ret = -EWOULDBLOCK;
|
||||
|
||||
@ -459,6 +459,14 @@ SYSCALL_DEFINE4(futex_requeue,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* For now mandate both flags are identical, like the sys_futex()
|
||||
* interface has. If/when we merge the variable sized futex support,
|
||||
* that patch can modify this test to allow a difference in size.
|
||||
*/
|
||||
if (futexes[0].w.flags != futexes[1].w.flags)
|
||||
return -EINVAL;
|
||||
|
||||
cmpval = futexes[0].w.val;
|
||||
|
||||
return futex_requeue(u64_to_user_ptr(futexes[0].w.uaddr), futexes[0].w.flags,
|
||||
|
||||
@ -71,6 +71,7 @@
|
||||
|
||||
#include <linux/uaccess.h>
|
||||
#include <asm/processor.h>
|
||||
#include <linux/mmzone.h>
|
||||
|
||||
#ifdef CONFIG_X86
|
||||
#include <asm/nmi.h>
|
||||
@ -2193,6 +2194,17 @@ static struct ctl_table vm_table[] = {
|
||||
.extra1 = SYSCTL_ZERO,
|
||||
.extra2 = SYSCTL_TWO_HUNDRED,
|
||||
},
|
||||
#ifdef CONFIG_MEMCG
|
||||
{
|
||||
.procname = "mem_cgroup_reclaim_retries",
|
||||
.data = &sysctl_mem_cgroup_reclaim_retries,
|
||||
.maxlen = sizeof(int),
|
||||
.mode = 0644,
|
||||
.proc_handler = proc_dointvec_minmax,
|
||||
.extra1 = SYSCTL_ONE,
|
||||
.extra2 = SYSCTL_MAX_RECLAIM_TRIES,
|
||||
},
|
||||
#endif
|
||||
#ifdef CONFIG_NUMA
|
||||
{
|
||||
.procname = "numa_stat",
|
||||
@ -2357,6 +2369,16 @@ static struct ctl_table vm_table[] = {
|
||||
.extra2 = SYSCTL_ONE,
|
||||
},
|
||||
#endif
|
||||
{
|
||||
.procname = "dr_prio_drop",
|
||||
.data = &sysctl_dr_prio_drop,
|
||||
.maxlen = sizeof(int),
|
||||
.mode = 0644,
|
||||
.proc_handler = proc_dointvec_minmax,
|
||||
.extra1 = SYSCTL_ZERO,
|
||||
.extra2 = SYSCTL_MAX_PRIO_DROP,
|
||||
},
|
||||
|
||||
{ }
|
||||
};
|
||||
|
||||
|
||||
@ -234,12 +234,6 @@ static inline bool folio_needs_release(struct folio *folio)
|
||||
|
||||
extern unsigned long highest_memmap_pfn;
|
||||
|
||||
/*
|
||||
* Maximum number of reclaim retries without progress before the OOM
|
||||
* killer is consider the only way forward.
|
||||
*/
|
||||
#define MAX_RECLAIM_RETRIES 16
|
||||
|
||||
/*
|
||||
* in mm/vmscan.c:
|
||||
*/
|
||||
|
||||
163
mm/memcontrol.c
163
mm/memcontrol.c
@ -217,6 +217,8 @@ enum percpu_stats_state {
|
||||
iter != NULL; \
|
||||
iter = mem_cgroup_iter(NULL, iter, NULL))
|
||||
|
||||
int sysctl_mem_cgroup_reclaim_retries = MAX_RECLAIM_RETRIES;
|
||||
|
||||
static inline bool task_is_dying(void)
|
||||
{
|
||||
return tsk_is_oom_victim(current) || fatal_signal_pending(current) ||
|
||||
@ -2434,7 +2436,7 @@ void mem_cgroup_handle_over_high(gfp_t gfp_mask)
|
||||
unsigned long pflags;
|
||||
unsigned long nr_reclaimed;
|
||||
unsigned int nr_pages = current->memcg_nr_pages_over_high;
|
||||
int nr_retries = MAX_RECLAIM_RETRIES;
|
||||
int nr_retries = sysctl_mem_cgroup_reclaim_retries;
|
||||
struct mem_cgroup *memcg;
|
||||
bool in_retry = false;
|
||||
|
||||
@ -2525,110 +2527,103 @@ static int try_charge_memcg(struct mem_cgroup *memcg, gfp_t gfp_mask,
|
||||
unsigned int nr_pages)
|
||||
{
|
||||
unsigned int batch = max(MEMCG_CHARGE_BATCH, nr_pages);
|
||||
int nr_retries = MAX_RECLAIM_RETRIES;
|
||||
int nr_retries = sysctl_mem_cgroup_reclaim_retries;
|
||||
struct mem_cgroup *mem_over_limit;
|
||||
struct page_counter *counter;
|
||||
unsigned long nr_reclaimed;
|
||||
bool passed_oom = false;
|
||||
unsigned int reclaim_options = MEMCG_RECLAIM_MAY_SWAP;
|
||||
bool drained = false;
|
||||
bool raised_max_event = false;
|
||||
unsigned long pflags;
|
||||
|
||||
retry:
|
||||
if (consume_stock(memcg, nr_pages))
|
||||
return 0;
|
||||
for (; nr_retries >= 0; nr_retries--) {
|
||||
|
||||
if (!do_memsw_account() ||
|
||||
page_counter_try_charge(&memcg->memsw, batch, &counter)) {
|
||||
if (page_counter_try_charge(&memcg->memory, batch, &counter))
|
||||
goto done_restock;
|
||||
if (do_memsw_account())
|
||||
page_counter_uncharge(&memcg->memsw, batch);
|
||||
mem_over_limit = mem_cgroup_from_counter(counter, memory);
|
||||
} else {
|
||||
mem_over_limit = mem_cgroup_from_counter(counter, memsw);
|
||||
reclaim_options &= ~MEMCG_RECLAIM_MAY_SWAP;
|
||||
}
|
||||
if (consume_stock(memcg, nr_pages))
|
||||
return 0;
|
||||
if (!do_memsw_account() ||
|
||||
page_counter_try_charge(&memcg->memsw, batch, &counter)) {
|
||||
if (page_counter_try_charge(&memcg->memory, batch, &counter))
|
||||
goto done_restock;
|
||||
if (do_memsw_account())
|
||||
page_counter_uncharge(&memcg->memsw, batch);
|
||||
mem_over_limit = mem_cgroup_from_counter(counter, memory);
|
||||
} else {
|
||||
mem_over_limit = mem_cgroup_from_counter(counter, memsw);
|
||||
reclaim_options &= ~MEMCG_RECLAIM_MAY_SWAP;
|
||||
}
|
||||
|
||||
if (batch > nr_pages) {
|
||||
batch = nr_pages;
|
||||
goto retry;
|
||||
}
|
||||
if (batch > nr_pages) {
|
||||
batch = nr_pages;
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Prevent unbounded recursion when reclaim operations need to
|
||||
* allocate memory. This might exceed the limits temporarily,
|
||||
* but we prefer facilitating memory reclaim and getting back
|
||||
* under the limit over triggering OOM kills in these cases.
|
||||
*/
|
||||
if (unlikely(current->flags & PF_MEMALLOC))
|
||||
goto force;
|
||||
/*
|
||||
* Prevent unbounded recursion when reclaim operations need to
|
||||
* allocate memory. This might exceed the limits temporarily,
|
||||
* but we prefer facilitating memory reclaim and getting back
|
||||
* under the limit over triggering OOM kills in these cases.
|
||||
*/
|
||||
if (unlikely(current->flags & PF_MEMALLOC))
|
||||
goto force;
|
||||
|
||||
if (unlikely(task_in_memcg_oom(current)))
|
||||
goto nomem;
|
||||
if (unlikely(task_in_memcg_oom(current)))
|
||||
goto nomem;
|
||||
|
||||
if (!gfpflags_allow_blocking(gfp_mask))
|
||||
goto nomem;
|
||||
if (!gfpflags_allow_blocking(gfp_mask))
|
||||
goto nomem;
|
||||
|
||||
memcg_memory_event(mem_over_limit, MEMCG_MAX);
|
||||
raised_max_event = true;
|
||||
memcg_memory_event(mem_over_limit, MEMCG_MAX);
|
||||
raised_max_event = true;
|
||||
|
||||
psi_memstall_enter(&pflags);
|
||||
nr_reclaimed = try_to_free_mem_cgroup_pages(mem_over_limit, nr_pages,
|
||||
psi_memstall_enter(&pflags);
|
||||
nr_reclaimed = try_to_free_mem_cgroup_pages(mem_over_limit, nr_pages,
|
||||
gfp_mask, reclaim_options);
|
||||
psi_memstall_leave(&pflags);
|
||||
psi_memstall_leave(&pflags);
|
||||
|
||||
if (mem_cgroup_margin(mem_over_limit) >= nr_pages)
|
||||
goto retry;
|
||||
if (mem_cgroup_margin(mem_over_limit) >= nr_pages) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!drained) {
|
||||
drain_all_stock(mem_over_limit);
|
||||
drained = true;
|
||||
goto retry;
|
||||
if (!drained) {
|
||||
drain_all_stock(mem_over_limit);
|
||||
drained = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (gfp_mask & __GFP_NORETRY)
|
||||
goto nomem;
|
||||
/*
|
||||
* Even though the limit is exceeded at this point, reclaim
|
||||
* may have been able to free some pages. Retry the charge
|
||||
* before killing the task.
|
||||
*
|
||||
* Only for regular pages, though: huge pages are rather
|
||||
* unlikely to succeed so close to the limit, and we fall back
|
||||
* to regular pages anyway in case of failure.
|
||||
*/
|
||||
if (nr_reclaimed && nr_pages <= (1 << PAGE_ALLOC_COSTLY_ORDER)) {
|
||||
continue;
|
||||
}
|
||||
/*
|
||||
* At task move, charge accounts can be doubly counted. So, it's
|
||||
* better to wait until the end of task_move if something is going on.
|
||||
*/
|
||||
if (mem_cgroup_wait_acct_move(mem_over_limit)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((gfp_mask & __GFP_RETRY_MAYFAIL) || task_is_dying())
|
||||
goto nomem;
|
||||
}
|
||||
|
||||
if (gfp_mask & __GFP_NORETRY)
|
||||
goto nomem;
|
||||
/*
|
||||
* Even though the limit is exceeded at this point, reclaim
|
||||
* may have been able to free some pages. Retry the charge
|
||||
* before killing the task.
|
||||
*
|
||||
* Only for regular pages, though: huge pages are rather
|
||||
* unlikely to succeed so close to the limit, and we fall back
|
||||
* to regular pages anyway in case of failure.
|
||||
*/
|
||||
if (nr_reclaimed && nr_pages <= (1 << PAGE_ALLOC_COSTLY_ORDER))
|
||||
goto retry;
|
||||
/*
|
||||
* At task move, charge accounts can be doubly counted. So, it's
|
||||
* better to wait until the end of task_move if something is going on.
|
||||
*/
|
||||
if (mem_cgroup_wait_acct_move(mem_over_limit))
|
||||
goto retry;
|
||||
|
||||
if (nr_retries--)
|
||||
goto retry;
|
||||
|
||||
if (gfp_mask & __GFP_RETRY_MAYFAIL)
|
||||
goto nomem;
|
||||
|
||||
/* Avoid endless loop for tasks bypassed by the oom killer */
|
||||
if (passed_oom && task_is_dying())
|
||||
goto nomem;
|
||||
|
||||
/*
|
||||
* keep retrying as long as the memcg oom killer is able to make
|
||||
* a forward progress or bypass the charge if the oom killer
|
||||
* couldn't make any progress.
|
||||
*/
|
||||
if (mem_cgroup_oom(mem_over_limit, gfp_mask,
|
||||
get_order(nr_pages * PAGE_SIZE))) {
|
||||
passed_oom = true;
|
||||
nr_retries = MAX_RECLAIM_RETRIES;
|
||||
goto retry;
|
||||
}
|
||||
mem_cgroup_oom(mem_over_limit, gfp_mask,
|
||||
get_order(nr_pages * PAGE_SIZE));
|
||||
|
||||
nomem:
|
||||
/*
|
||||
* Memcg doesn't have a dedicated reserve for atomic
|
||||
@ -3518,7 +3513,7 @@ static int mem_cgroup_resize_max(struct mem_cgroup *memcg,
|
||||
*/
|
||||
static int mem_cgroup_force_empty(struct mem_cgroup *memcg)
|
||||
{
|
||||
int nr_retries = MAX_RECLAIM_RETRIES;
|
||||
int nr_retries = sysctl_mem_cgroup_reclaim_retries;
|
||||
|
||||
/* we call try-to-free pages for make this cgroup empty */
|
||||
lru_add_drain_all();
|
||||
@ -6535,7 +6530,7 @@ static ssize_t memory_high_write(struct kernfs_open_file *of,
|
||||
char *buf, size_t nbytes, loff_t off)
|
||||
{
|
||||
struct mem_cgroup *memcg = mem_cgroup_from_css(of_css(of));
|
||||
unsigned int nr_retries = MAX_RECLAIM_RETRIES;
|
||||
unsigned int nr_retries = sysctl_mem_cgroup_reclaim_retries;
|
||||
bool drained = false;
|
||||
unsigned long high;
|
||||
int err;
|
||||
@ -6584,7 +6579,7 @@ static ssize_t memory_max_write(struct kernfs_open_file *of,
|
||||
char *buf, size_t nbytes, loff_t off)
|
||||
{
|
||||
struct mem_cgroup *memcg = mem_cgroup_from_css(of_css(of));
|
||||
unsigned int nr_reclaims = MAX_RECLAIM_RETRIES;
|
||||
unsigned int nr_reclaims = sysctl_mem_cgroup_reclaim_retries;
|
||||
bool drained = false;
|
||||
unsigned long max;
|
||||
int err;
|
||||
@ -6744,7 +6739,7 @@ static ssize_t memory_reclaim(struct kernfs_open_file *of, char *buf,
|
||||
size_t nbytes, loff_t off)
|
||||
{
|
||||
struct mem_cgroup *memcg = mem_cgroup_from_css(of_css(of));
|
||||
unsigned int nr_retries = MAX_RECLAIM_RETRIES;
|
||||
unsigned int nr_retries = sysctl_mem_cgroup_reclaim_retries;
|
||||
unsigned long nr_to_reclaim, nr_reclaimed = 0;
|
||||
unsigned int reclaim_options;
|
||||
int err;
|
||||
|
||||
@ -312,7 +312,13 @@ void __mpol_put(struct mempolicy *pol)
|
||||
{
|
||||
if (!atomic_dec_and_test(&pol->refcnt))
|
||||
return;
|
||||
kmem_cache_free(policy_cache, pol);
|
||||
/*
|
||||
* Required to allow mmap_lock_speculative*() access, see for example
|
||||
* futex_key_to_node_opt(). All accesses are serialized by mmap_lock,
|
||||
* however the speculative lock section unbound by the normal lock
|
||||
* boundaries, requiring RCU freeing.
|
||||
*/
|
||||
kfree_rcu(pol, rcu);
|
||||
}
|
||||
|
||||
static void mpol_rebind_default(struct mempolicy *pol, const nodemask_t *nodes)
|
||||
@ -761,7 +767,7 @@ static int vma_replace_policy(struct vm_area_struct *vma,
|
||||
}
|
||||
|
||||
old = vma->vm_policy;
|
||||
vma->vm_policy = new; /* protected by mmap_lock */
|
||||
WRITE_ONCE(vma->vm_policy, new); /* protected by mmap_lock */
|
||||
mpol_put(old);
|
||||
|
||||
return 0;
|
||||
|
||||
17
mm/vmscan.c
17
mm/vmscan.c
@ -168,6 +168,8 @@ struct scan_control {
|
||||
|
||||
/* for recording the reclaimed slab by now */
|
||||
struct reclaim_state reclaim_state;
|
||||
|
||||
bool give_up_direct_reclaim;
|
||||
};
|
||||
|
||||
#ifdef ARCH_HAS_PREFETCHW
|
||||
@ -5619,6 +5621,8 @@ static void lru_gen_shrink_node(struct pglist_data *pgdat, struct scan_control *
|
||||
|
||||
#endif /* CONFIG_LRU_GEN */
|
||||
|
||||
int sysctl_dr_prio_drop = 0;
|
||||
|
||||
static void shrink_lruvec(struct lruvec *lruvec, struct scan_control *sc)
|
||||
{
|
||||
unsigned long nr[NR_LRU_LISTS];
|
||||
@ -5630,6 +5634,16 @@ static void shrink_lruvec(struct lruvec *lruvec, struct scan_control *sc)
|
||||
bool proportional_reclaim;
|
||||
struct blk_plug plug;
|
||||
|
||||
/*
|
||||
* Prevent lruvec overscanning by direct reclaimers
|
||||
* to reduce contention over the lruvec spinlock.
|
||||
*/
|
||||
if (unlikely(sysctl_dr_prio_drop && !current_is_kswapd() &&
|
||||
sc->priority <= (DEF_PRIORITY - sysctl_dr_prio_drop))) {
|
||||
sc->give_up_direct_reclaim = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (lru_gen_enabled() && !root_reclaim(sc)) {
|
||||
lru_gen_shrink_lruvec(lruvec, sc);
|
||||
return;
|
||||
@ -6199,6 +6213,9 @@ retry:
|
||||
if (sc->compaction_ready)
|
||||
break;
|
||||
|
||||
if (sc->give_up_direct_reclaim)
|
||||
break;
|
||||
|
||||
/*
|
||||
* If we're getting trouble reclaiming, start doing
|
||||
* writepage even in laptop mode.
|
||||
|
||||
@ -603,10 +603,10 @@ restart:
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (cb->args[1]) {
|
||||
cb->args[1] = 0;
|
||||
goto restart;
|
||||
if (cb->args[1]) {
|
||||
cb->args[1] = 0;
|
||||
goto restart;
|
||||
}
|
||||
}
|
||||
out:
|
||||
rcu_read_unlock();
|
||||
|
||||
@ -1,3 +1,25 @@
|
||||
* Wed Aug 05 2026 CKI KWF Bot <cki-ci-bot+kwf-gitlab-com@redhat.com> [5.14.0-687.36.1.el9_8]
|
||||
- powerpc/powernv/iommu: iommu incorrectly bypass DMA APIs (Mamatha Inamdar) [RHEL-215575]
|
||||
- powerpc/iommu: bypass DMA APIs for coherent allocations for pre-mapped memory (Mamatha Inamdar) [RHEL-215575]
|
||||
- mm/vmscan: add sysctl to limit direct reclaim scanning depth (Audra Mitchell) [RHEL-211058]
|
||||
- mm/memcg: refactor try_charge_memcg retry logic to use for loop (Audra Mitchell) [RHEL-211058]
|
||||
- mm/memcg: introduce tunable sysctl for memory cgroup reclaim retries (Audra Mitchell) [RHEL-211058]
|
||||
- futex: Prevent lockup in requeue-PI during signal/ timeout wakeup (Waiman Long) [RHEL-193526] {CVE-2026-52977}
|
||||
- futex: Require sys_futex_requeue() to have identical flags (Waiman Long) [RHEL-193526] {CVE-2026-31554}
|
||||
- futex: Clear stale exiting pointer in futex_lock_pi() retry path (Waiman Long) [RHEL-193526] {CVE-2026-31555}
|
||||
- futex: Fix UaF between futex_key_to_node_opt() and vma_replace_policy() (Waiman Long) [RHEL-193526] {CVE-2026-23415}
|
||||
Resolves: RHEL-193526, RHEL-211058, RHEL-215575
|
||||
|
||||
* Tue Aug 04 2026 CKI KWF Bot <cki-ci-bot+kwf-gitlab-com@redhat.com> [5.14.0-687.35.1.el9_8]
|
||||
- octeon_ep_vf: add NULL check for napi_build_skb() (CKI Backport Bot) [RHEL-186331]
|
||||
- octeon_ep_vf: introduce octep_vf_oq_next_idx() helper (CKI Backport Bot) [RHEL-186331]
|
||||
- octeon_ep_vf: avoid compiler and IQ/OQ reordering (CKI Backport Bot) [RHEL-186331]
|
||||
- octeon_ep_vf: Relocate counter updates before NAPI (CKI Backport Bot) [RHEL-186331]
|
||||
- octeon_ep_vf: ensure dbell BADDR updation (CKI Backport Bot) [RHEL-186331]
|
||||
- net: octeon_ep_vf: fix free_irq dev_id mismatch in IRQ rollback (CKI Backport Bot) [RHEL-186331]
|
||||
- netfilter: nfnetlink_cthelper: fix OOB read in nfnl_cthelper_dump_table() (CKI Backport Bot) [RHEL-179745] {CVE-2026-43450}
|
||||
Resolves: RHEL-179745, RHEL-186331
|
||||
|
||||
* Mon Aug 03 2026 CKI KWF Bot <cki-ci-bot+kwf-gitlab-com@redhat.com> [5.14.0-687.34.1.el9_8]
|
||||
- s390/mm: Ensure physical addr derived from page is passed in to uv_convert_from_secure() (Lucas Oakley) [RHEL-192430]
|
||||
- s390/mm: Fix phys_to_folio() usage in do_secure_storage_access() (Charles Haithcock) [RHEL-216471]
|
||||
|
||||
Loading…
Reference in New Issue
Block a user