From: Wang Wensheng wangwensheng4@huawei.com
ascend inclusion category: feature bugzilla: NA CVE: NA
-------------------------------------------------
The cdm nodes are easiler to raise an ECC error and it may cause the kernel crash if the essential structures went wrong. So move the management structures for hbm nodes to the ddr nodes of the same partion to reduce the probability of kernel crashes.
Signed-off-by: Wang Wensheng wangwensheng4@huawei.com Reviewed-by: Kefeng Wang wangkefeng.wang@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- arch/arm64/Kconfig | 10 ++++++++ arch/arm64/mm/numa.c | 54 +++++++++++++++++++++++++++++++++++++++- include/linux/nodemask.h | 7 ++++++ mm/sparse.c | 8 +++--- 4 files changed, 75 insertions(+), 4 deletions(-)
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index b7caf370a14b7..3848c062ea2c5 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -1583,6 +1583,16 @@ config ASCEND_BOOT_CRASH_KERNEL Usage: 1. add a node name:kexecmailbox to dts config. 2. after kexec run, set sysctl -w kernel.kexec_bios_start=1. + +config ASCEND_CLEAN_CDM + bool "move the management structure for HBM to DDR" + def_bool n + depends on COHERENT_DEVICE + help + The cdm nodes sometimes are easiler to raise an ECC error and it may + cause the kernel crash if the essential structures went wrong. So move + the management structures for hbm nodes to the ddr nodes of the same + partion to reduce the probability of kernel crashes. endif
endmenu diff --git a/arch/arm64/mm/numa.c b/arch/arm64/mm/numa.c index a9d3ad5ee0cc3..a194bad6fdfcf 100644 --- a/arch/arm64/mm/numa.c +++ b/arch/arm64/mm/numa.c @@ -45,6 +45,57 @@ inline int arch_check_node_cdm(int nid) return node_isset(nid, cdmmask); }
+#ifdef CONFIG_ASCEND_CLEAN_CDM +/** + * cdm_node_to_ddr_node - Convert the cdm node to the ddr node of the + * same partion. + * @nid: input node ID + * + * Here is a typical memory topology in usage. + * There are some DDR and HBM in each partion and DDRs present at first, then + * come all the HBMs of the first partion, then HBMs of the second partion, etc. + * + * ------------------------- + * | P0 | P1 | + * ----------- | ----------- + * |node0 DDR| | |node1 DDR| + * |---------- | ----------| + * |node2 HBM| | |node4 HBM| + * |---------- | ----------| + * |node3 HBM| | |node5 HBM| + * ----------- | ----------- + * + * Return: + * This function returns a ddr node which is of the same partion with the input + * node if the input node is a HBM node. + * The input nid is returned if it is a DDR node or if the memory topology of + * the system doesn't apply to the above model. + */ +int __init cdm_node_to_ddr_node(int nid) +{ + nodemask_t ddr_mask; + int nr_ddr, cdm_per_part, fake_nid; + int nr_cdm = nodes_weight(cdmmask); + + if (!nr_cdm || nodes_empty(numa_nodes_parsed)) + return nid; + + if (!node_isset(nid, cdmmask)) + return nid; + + nodes_xor(ddr_mask, cdmmask, numa_nodes_parsed); + nr_ddr = nodes_weight(ddr_mask); + cdm_per_part = nr_cdm / nr_ddr ? : 1; + + fake_nid = (nid - nr_ddr) / cdm_per_part; + fake_nid = !node_isset(fake_nid, cdmmask) ? fake_nid : nid; + + pr_info("nid: %d, fake_nid: %d\n", nid, fake_nid); + + return fake_nid; +} +#endif + static int __init cdm_nodes_setup(char *s) { int nid; @@ -264,11 +315,12 @@ static void __init setup_node_data(int nid, u64 start_pfn, u64 end_pfn) u64 nd_pa; void *nd; int tnid; + int fake_nid = cdm_node_to_ddr_node(nid);
if (start_pfn >= end_pfn) pr_info("Initmem setup node %d [<memory-less node>]\n", nid);
- nd_pa = memblock_alloc_try_nid(nd_size, SMP_CACHE_BYTES, nid); + nd_pa = memblock_alloc_try_nid(nd_size, SMP_CACHE_BYTES, fake_nid); nd = __va(nd_pa);
/* report and initialize */ diff --git a/include/linux/nodemask.h b/include/linux/nodemask.h index 41fb047bdba80..7c0571b95ce4d 100644 --- a/include/linux/nodemask.h +++ b/include/linux/nodemask.h @@ -508,6 +508,12 @@ static inline int node_random(const nodemask_t *mask) #ifdef CONFIG_COHERENT_DEVICE extern int arch_check_node_cdm(int nid);
+#ifdef CONFIG_ASCEND_CLEAN_CDM +extern int cdm_node_to_ddr_node(int nid); +#else +static inline int cdm_node_to_ddr_node(int nid) { return nid; } +#endif + static inline nodemask_t system_mem_nodemask(void) { nodemask_t system_mem; @@ -551,6 +557,7 @@ static inline void node_clear_state_cdm(int node) #else
static inline int arch_check_node_cdm(int nid) { return 0; } +static inline int cdm_node_to_ddr_node(int nid) { return nid; }
static inline nodemask_t system_mem_nodemask(void) { diff --git a/mm/sparse.c b/mm/sparse.c index 9854aff6b4193..581982a376bdd 100644 --- a/mm/sparse.c +++ b/mm/sparse.c @@ -458,21 +458,23 @@ static void __init sparse_init_nid(int nid, unsigned long pnum_begin, { unsigned long pnum, usemap_longs, *usemap; struct page *map; + int fake_nid = cdm_node_to_ddr_node(nid);
usemap_longs = BITS_TO_LONGS(SECTION_BLOCKFLAGS_BITS); - usemap = sparse_early_usemaps_alloc_pgdat_section(NODE_DATA(nid), + usemap = sparse_early_usemaps_alloc_pgdat_section(NODE_DATA(fake_nid), usemap_size() * map_count); if (!usemap) { pr_err("%s: node[%d] usemap allocation failed", __func__, nid); goto failed; } - sparse_buffer_init(map_count * section_map_size(), nid); + + sparse_buffer_init(map_count * section_map_size(), fake_nid); for_each_present_section_nr(pnum_begin, pnum) { if (pnum >= pnum_end) break;
- map = sparse_mem_map_populate(pnum, nid, NULL); + map = sparse_mem_map_populate(pnum, fake_nid, NULL); if (!map) { pr_err("%s: node[%d] memory map backing failed. Some memory will not be available.", __func__, nid);
From: Wang Wensheng wangwensheng4@huawei.com
ascend inclusion category: feature bugzilla: NA CVE: NA
-------------------
Signed-off-by: Wang Wensheng wangwensheng4@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- arch/arm64/configs/hulk_defconfig | 1 + 1 file changed, 1 insertion(+)
diff --git a/arch/arm64/configs/hulk_defconfig b/arch/arm64/configs/hulk_defconfig index f4e97cd9db1e0..9d5299c791214 100644 --- a/arch/arm64/configs/hulk_defconfig +++ b/arch/arm64/configs/hulk_defconfig @@ -484,6 +484,7 @@ CONFIG_ASCEND_WATCHDOG_SYSFS_CONFIGURE=y CONFIG_ASCEND_AUTO_TUNING_HUGEPAGE=y CONFIG_ASCEND_SHARE_POOL=y CONFIG_ASCEND_BOOT_CRASH_KERNEL=y +CONFIG_ASCEND_CLEAN_CDM=y CONFIG_ARM64_CNP=y
#
From: Jason Yan yanaijie@huawei.com
hulk inclusion category: bugfix bugzilla: NA CVE: NA
-----------------------------------------------
When the scsi device status is offline, mode sense command will return a result with only DID_NO_CONNECT set. Then in sd_read_write_protect_flag(), only status byte of the result is checked, we still consider the command returned good, and read sdkp->write_prot from the buffer. And because of bug [1], garbage data is copied to the buffer, the disk sometimes be set readonly. When the scsi device is set running again, users cannot write data to the disk.
Fix this by check the whole result returned by the driver.
[1] https://patchwork.kernel.org/project/linux-block/patch/20210318122621.330010...
Signed-off-by: Jason Yan yanaijie@huawei.com Reviewed-by: Yufen Yu yuyufen@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- drivers/scsi/sd.c | 6 +++--- include/scsi/scsi.h | 13 +++++++++++++ 2 files changed, 16 insertions(+), 3 deletions(-)
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 478c2f8334d85..d466d5a4b3129 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -2651,18 +2651,18 @@ sd_read_write_protect_flag(struct scsi_disk *sdkp, unsigned char *buffer) * 5: Illegal Request, Sense Code 24: Invalid field in * CDB. */ - if (!scsi_status_is_good(res)) + if (!scsi_result_is_good(res)) res = sd_do_mode_sense(sdp, 0, 0, buffer, 4, &data, NULL);
/* * Third attempt: ask 255 bytes, as we did earlier. */ - if (!scsi_status_is_good(res)) + if (!scsi_result_is_good(res)) res = sd_do_mode_sense(sdp, 0, 0x3F, buffer, 255, &data, NULL); }
- if (!scsi_status_is_good(res)) { + if (!scsi_result_is_good(res)) { sd_first_printk(KERN_WARNING, sdkp, "Test WP failed, assume Write Enabled\n"); } else { diff --git a/include/scsi/scsi.h b/include/scsi/scsi.h index eb7853c1a23b8..f6c2dedd7f8c9 100644 --- a/include/scsi/scsi.h +++ b/include/scsi/scsi.h @@ -55,6 +55,19 @@ static inline int scsi_status_is_good(int status) (status == SAM_STAT_COMMAND_TERMINATED)); }
+/** scsi_result_is_good - check the result return. + * + * @result: the result passed up from the driver (including host and + * driver components) + * + * Drivers may only set other bytes but not status byte. + * This checks both the status byte and other bytes. + */ +static inline int scsi_result_is_good(int result) +{ + return scsi_status_is_good(result) && (result & ~0xff) == 0; +} +
/* * standard mode-select header prepended to all mode-select commands
From: Ding Tianhong dingtianhong@huawei.com
ascend inclusion category: feature bugzilla: NA CVE: NA
-------------------------------------------------
In AI training scene, the sp area range is specified by host user, it will result in an address offset calculation error, so fix it to avoid the offset overflow.
If the user needs to specify the sp area range, the user should reserve the virtual memory space by themselvs, otherwise the sp area would be used for none share pool process.
Signed-off-by: Ding Tianhong dingtianhong@huawei.com Reviewed-by: Kefeng Wang wangkefeng.wang@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- mm/share_pool.c | 40 +++++++++++++++++++++++++++++++--------- 1 file changed, 31 insertions(+), 9 deletions(-)
diff --git a/mm/share_pool.c b/mm/share_pool.c index 28fc074791833..c6eacb89dc23b 100644 --- a/mm/share_pool.c +++ b/mm/share_pool.c @@ -214,7 +214,7 @@ struct sp_area { }; static DEFINE_SPINLOCK(sp_area_lock); static struct rb_root sp_area_root = RB_ROOT; -static bool host_svm_sp_enable = false; +static bool sp_area_customized;
static unsigned long spa_size(struct sp_area *spa) { @@ -409,6 +409,18 @@ int sp_group_id_by_pid(int pid) } EXPORT_SYMBOL_GPL(sp_group_id_by_pid);
+static loff_t addr_to_offset(unsigned long addr, struct sp_area *spa) +{ + if (sp_area_customized == false) + return (loff_t)(addr - MMAP_SHARE_POOL_START); + + if (spa && spa->spg) + return (loff_t)(addr - spa->spg->dvpp_va_start); + + pr_err("share pool: the addr is not belong to share pool range\n"); + return addr; +} + /* the caller must hold sp_group_sem */ static struct sp_group *find_or_alloc_sp_group(int spg_id) { @@ -812,7 +824,7 @@ static struct sp_area *sp_alloc_area(unsigned long size, unsigned long flags, unsigned long size_align = PMD_ALIGN(size); /* va aligned to 2M */
if ((flags & SP_DVPP)) { - if (host_svm_sp_enable == false) { + if (sp_area_customized == false) { vstart = MMAP_SHARE_POOL_16G_START; vend = MMAP_SHARE_POOL_16G_START + MMAP_SHARE_POOL_16G_SIZE; } else { @@ -1204,7 +1216,7 @@ int sp_free(unsigned long addr)
/* Free the memory of the backing shmem or hugetlbfs */ mode = FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE; - offset = addr - MMAP_SHARE_POOL_START; + offset = addr_to_offset(addr, spa); ret = vfs_fallocate(spa_file(spa), mode, offset, spa_size(spa)); if (ret) pr_err("share pool: sp free fallocate failed: %d\n", ret); @@ -1241,7 +1253,7 @@ static unsigned long sp_mmap(struct mm_struct *mm, struct file *file, unsigned long flags = MAP_FIXED | MAP_SHARED | MAP_POPULATE | MAP_SHARE_POOL; unsigned long vm_flags = VM_NORESERVE | VM_SHARE_POOL | VM_DONTCOPY; - unsigned long pgoff = (addr - MMAP_SHARE_POOL_START) >> PAGE_SHIFT; + unsigned long pgoff = addr_to_offset(addr, spa) >> PAGE_SHIFT;
/* Mark the mapped region to be locked. After the MAP_LOCKED is enable, * multiple tasks will preempt resources, causing performance loss. @@ -1439,7 +1451,7 @@ void *sp_alloc(unsigned long size, unsigned long sp_flags, int spg_id) p = ERR_PTR(ret);
mode = FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE; - offset = sp_addr - MMAP_SHARE_POOL_START; + offset = addr_to_offset(sp_addr, spa);
ret = vfs_fallocate(spa_file(spa), mode, offset, spa_size(spa)); if (ret) @@ -2457,7 +2469,7 @@ bool sp_config_dvpp_range(size_t start, size_t size, int device_id, int pid) spg->dvpp_multi_spaces = true; up_write(&spg->rw_lock);
- host_svm_sp_enable = true; + sp_area_customized = true;
sp_group_drop(spg); return true; @@ -2467,10 +2479,20 @@ EXPORT_SYMBOL_GPL(sp_config_dvpp_range); /* Check whether the address belongs to the share pool. */ bool is_sharepool_addr(unsigned long addr) { - if (host_svm_sp_enable == false) - return addr >= MMAP_SHARE_POOL_START && addr < (MMAP_SHARE_POOL_16G_START + MMAP_SHARE_POOL_16G_SIZE); + struct sp_area *spa; + bool ret = false; + + if (sp_area_customized == false) + return addr >= MMAP_SHARE_POOL_START && + addr < (MMAP_SHARE_POOL_16G_START + MMAP_SHARE_POOL_16G_SIZE); + + spa = __find_sp_area(addr); + if (spa && spa->spg) + ret = addr >= spa->spg->dvpp_va_start && + addr < (spa->spg->dvpp_va_start + spa->spg->dvpp_size);
- return addr >= MMAP_SHARE_POOL_START && addr < MMAP_SHARE_POOL_END; + __sp_area_drop(spa); + return ret; } EXPORT_SYMBOL_GPL(is_sharepool_addr);
From: Wenwen Wang wenwen@cs.uga.edu
mainline inclusion from mainline-5.4-rc1 commit cfddf9f4c9f038c91c6c61d5cf3a161731b5c418 category: bugfix bugzilla: 21612 CVE: NA
---------------------------
In __break_lease(), the file lock 'new_fl' is allocated in lease_alloc(). However, it is not deallocated in the following execution if smp_load_acquire() fails, leading to a memory leak bug. To fix this issue, free 'new_fl' before returning the error.
Signed-off-by: Wenwen Wang wenwen@cs.uga.edu Signed-off-by: Jeff Layton jlayton@kernel.org Signed-off-by: Yu Kuai yukuai3@huawei.com Reviewed-by: zhangyi (F) yi.zhang@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- fs/locks.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/fs/locks.c b/fs/locks.c index 28270e74be342..545e79d6eb70b 100644 --- a/fs/locks.c +++ b/fs/locks.c @@ -1459,7 +1459,7 @@ int __break_lease(struct inode *inode, unsigned int mode, unsigned int type) ctx = smp_load_acquire(&inode->i_flctx); if (!ctx) { WARN_ON_ONCE(1); - return error; + goto free_lock; }
percpu_down_read_preempt_disable(&file_rwsem); @@ -1539,6 +1539,7 @@ int __break_lease(struct inode *inode, unsigned int mode, unsigned int type) spin_unlock(&ctx->flc_lock); percpu_up_read_preempt_enable(&file_rwsem); locks_dispose_list(&dispose); +free_lock: locks_free_lock(new_fl); return error; }
From: Chiqijun chiqijun@huawei.com
driver inclusion category: feature bugzilla: 4472
-----------------------------------------------------------------------
Add the 'ethtool -K ethx rx-vlan-filter on/off' command to turn on/off the vlan filter.
Signed-off-by: Chiqijun chiqijun@huawei.com Reviewed-by: Wangxiaoyun cloud.wangxiaoyun@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- .../net/ethernet/huawei/hinic/hinic_main.c | 43 ++++++++++++++++--- 1 file changed, 38 insertions(+), 5 deletions(-)
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_main.c b/drivers/net/ethernet/huawei/hinic/hinic_main.c index d0c4bdf7383ca..6797d50d1bd49 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_main.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_main.c @@ -1331,6 +1331,9 @@ hinic_vlan_rx_add_vid(struct net_device *netdev, u32 col, line; int err;
+ if (vid == 0) + return 0; + col = VID_COL(nic_dev, vid); line = VID_LINE(nic_dev, vid);
@@ -1362,6 +1365,12 @@ hinic_vlan_rx_kill_vid(struct net_device *netdev, u16 func_id; int err, col, line;
+ /* vlan 0 is used internally by the firmware and must always exist + * after netdev open + */ + if (vid == 0) + return 0; + col = VID_COL(nic_dev, vid); line = VID_LINE(nic_dev, vid);
@@ -1490,6 +1499,31 @@ static int set_feature_lro(struct hinic_nic_dev *nic_dev, return err; }
+static int set_feature_vlan_filter(struct hinic_nic_dev *nic_dev, + netdev_features_t wanted_features, + netdev_features_t features, + netdev_features_t *failed_features) +{ + netdev_features_t changed = wanted_features ^ features; + bool en = !!(wanted_features & NETIF_F_HW_VLAN_CTAG_FILTER); + int err; + + if (!(changed & NETIF_F_HW_VLAN_CTAG_FILTER)) + return 0; + + err = hinic_set_vlan_fliter(nic_dev->hwdev, en); + if (err) { + hinic_err(nic_dev, drv, "%s rx vlan filter failed\n", + FEATURES_OP_STR(en)); + *failed_features |= NETIF_F_HW_VLAN_CTAG_FILTER; + } else { + hinic_info(nic_dev, drv, "%s rx vlan filter success\n", + FEATURES_OP_STR(en)); + } + + return err; +} + static int set_features(struct hinic_nic_dev *nic_dev, netdev_features_t pre_features, netdev_features_t features) @@ -1505,6 +1539,8 @@ static int set_features(struct hinic_nic_dev *nic_dev, &failed_features); err |= (u32)set_feature_lro(nic_dev, features, pre_features, &failed_features); + err |= (u32)set_feature_vlan_filter(nic_dev, features, pre_features, + &failed_features); if (err) { nic_dev->netdev->features = features ^ failed_features; return -EIO; @@ -2100,6 +2136,8 @@ static void netdev_feature_init(struct net_device *netdev) netdev->features |= NETIF_F_HW_VLAN_CTAG_RX; }
+ netdev->features |= NETIF_F_HW_VLAN_CTAG_FILTER; + /* copy netdev features into list of user selectable features */ hw_features = netdev->hw_features; hw_features |= netdev->features; @@ -2116,11 +2154,6 @@ static void netdev_feature_init(struct net_device *netdev)
netdev->hw_features = hw_features;
- /* Set after hw_features because this could not be part of - * hw_features - */ - netdev->features |= NETIF_F_HW_VLAN_CTAG_FILTER; - netdev->priv_flags |= IFF_UNICAST_FLT;
if (FUNC_SUPPORT_ENCAP_TSO_CSUM(nic_dev->hwdev)) {
From: Chiqijun chiqijun@huawei.com
driver inclusion category: feature bugzilla: 4472
-----------------------------------------------------------------------
Add XDP support for pass and drop actions.
Signed-off-by: Chiqijun chiqijun@huawei.com Reviewed-by: Wangxiaoyun cloud.wangxiaoyun@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- .../net/ethernet/huawei/hinic/hinic_ethtool.c | 2 + .../net/ethernet/huawei/hinic/hinic_main.c | 80 +++++++++++++++++ .../net/ethernet/huawei/hinic/hinic_nic_dev.h | 5 ++ drivers/net/ethernet/huawei/hinic/hinic_rx.c | 89 +++++++++++++++++++ drivers/net/ethernet/huawei/hinic/hinic_rx.h | 3 + 5 files changed, 179 insertions(+)
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_ethtool.c b/drivers/net/ethernet/huawei/hinic/hinic_ethtool.c index 9fa5af2dacce3..9796f2fa2f062 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_ethtool.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_ethtool.c @@ -114,6 +114,7 @@ static struct hinic_stats hinic_rx_queue_stats[] = { HINIC_RXQ_STAT(csum_errors), HINIC_RXQ_STAT(other_errors), HINIC_RXQ_STAT(dropped), + HINIC_RXQ_STAT(xdp_dropped), HINIC_RXQ_STAT(rx_buf_empty), };
@@ -121,6 +122,7 @@ static struct hinic_stats hinic_rx_queue_stats_extern[] = { HINIC_RXQ_STAT(alloc_skb_err), HINIC_RXQ_STAT(alloc_rx_buf_err), HINIC_RXQ_STAT(map_rx_buf_err), + HINIC_RXQ_STAT(xdp_large_pkt), };
static struct hinic_stats hinic_tx_queue_stats[] = { diff --git a/drivers/net/ethernet/huawei/hinic/hinic_main.c b/drivers/net/ethernet/huawei/hinic/hinic_main.c index 6797d50d1bd49..47232e1f6ae86 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_main.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_main.c @@ -30,6 +30,8 @@ #include <linux/tcp.h> #include <linux/ip.h> #include <linux/debugfs.h> +#include <linux/netlink.h> +#include <linux/bpf.h>
#include "ossl_knl.h" #include "hinic_hw_mgmt.h" @@ -1262,8 +1264,18 @@ static int hinic_change_mtu(struct net_device *netdev, int new_mtu) { struct hinic_nic_dev *nic_dev = netdev_priv(netdev); u32 mtu = (u32)new_mtu; + u32 xdp_max_mtu; int err = 0;
+ if (hinic_is_xdp_enable(nic_dev)) { + xdp_max_mtu = hinic_xdp_max_mtu(nic_dev); + if (mtu > xdp_max_mtu) { + nicif_err(nic_dev, drv, nic_dev->netdev, + "Max MTU for xdp usage is %d\n", xdp_max_mtu); + return -EINVAL; + } + } + err = hinic_set_port_mtu(nic_dev->hwdev, mtu); if (err) { nicif_err(nic_dev, drv, netdev, "Failed to change port mtu to %d\n", @@ -1484,6 +1496,12 @@ static int set_feature_lro(struct hinic_nic_dev *nic_dev, if (!(changed & NETIF_F_LRO)) return 0;
+ if (en && hinic_is_xdp_enable(nic_dev)) { + hinic_err(nic_dev, drv, "Can not enable LRO when xdp is enable\n"); + *failed_features |= NETIF_F_LRO; + return -EINVAL; + } + lro_timer = nic_dev->adaptive_cfg.lro.timer; lro_buf_size = nic_dev->adaptive_cfg.lro.buffer_size; err = hinic_set_rx_lro_state(nic_dev->hwdev, en, lro_timer, @@ -2057,6 +2075,66 @@ static void hinic_nic_set_rx_mode(struct net_device *netdev) queue_work(nic_dev->workq, &nic_dev->rx_mode_work); }
+bool hinic_is_xdp_enable(struct hinic_nic_dev *nic_dev) +{ + return !!nic_dev->xdp_prog; +} + +int hinic_xdp_max_mtu(struct hinic_nic_dev *nic_dev) +{ + return nic_dev->rx_buff_len - (ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN); +} + +static int hinic_xdp_setup(struct hinic_nic_dev *nic_dev, struct bpf_prog *prog, + struct netlink_ext_ack *extack) +{ + struct bpf_prog *old_prog = NULL; + int max_mtu = hinic_xdp_max_mtu(nic_dev); + int q_id; + + if (prog && nic_dev->netdev->mtu > max_mtu) { + nicif_err(nic_dev, drv, nic_dev->netdev, + "Failed to setup xdp program, the current MTU %d is larger than max allowed MTU %d\n", + nic_dev->netdev->mtu, max_mtu); + NL_SET_ERR_MSG_MOD(extack, + "MTU is too large to load xdp program"); + return -EINVAL; + } + + if (prog && nic_dev->netdev->features & NETIF_F_LRO) { + nicif_err(nic_dev, drv, nic_dev->netdev, + "Failed to setup xdp program while LRO is on\n"); + NL_SET_ERR_MSG_MOD(extack, + "Failed to setup xdp program while LRO is on\n"); + return -EINVAL; + } + + old_prog = xchg(&nic_dev->xdp_prog, prog); + for (q_id = 0; q_id < nic_dev->max_qps; q_id++) + xchg(&nic_dev->rxqs[q_id].xdp_prog, nic_dev->xdp_prog); + + if (old_prog) + bpf_prog_put(old_prog); + + return 0; +} + +static int hinic_xdp(struct net_device *netdev, struct netdev_bpf *xdp) +{ + struct hinic_nic_dev *nic_dev = netdev_priv(netdev); + + switch (xdp->command) { + case XDP_SETUP_PROG: + return hinic_xdp_setup(nic_dev, xdp->prog, xdp->extack); + case XDP_QUERY_PROG: + xdp->prog_id = nic_dev->xdp_prog ? + nic_dev->xdp_prog->aux->id : 0; + return 0; + default: + return -EINVAL; + } +} + static const struct net_device_ops hinic_netdev_ops = { .ndo_open = hinic_open, .ndo_stop = hinic_close, @@ -2087,6 +2165,7 @@ static const struct net_device_ops hinic_netdev_ops = { .ndo_set_vf_link_state = hinic_ndo_set_vf_link_state, .ndo_fix_features = hinic_fix_features, .ndo_set_features = hinic_set_features, + .ndo_bpf = hinic_xdp, };
static const struct net_device_ops hinicvf_netdev_ops = { @@ -2110,6 +2189,7 @@ static const struct net_device_ops hinicvf_netdev_ops = {
.ndo_fix_features = hinic_fix_features, .ndo_set_features = hinic_set_features, + .ndo_bpf = hinic_xdp, };
static void netdev_feature_init(struct net_device *netdev) diff --git a/drivers/net/ethernet/huawei/hinic/hinic_nic_dev.h b/drivers/net/ethernet/huawei/hinic/hinic_nic_dev.h index 1e6479a93ead6..7255a3603b7f4 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_nic_dev.h +++ b/drivers/net/ethernet/huawei/hinic/hinic_nic_dev.h @@ -246,6 +246,8 @@ struct hinic_nic_dev { u32 lro_replenish_thld; u16 rx_buff_len; u32 page_order; + + struct bpf_prog *xdp_prog; };
extern struct hinic_uld_info nic_uld_info; @@ -266,6 +268,9 @@ void hinic_link_status_change(struct hinic_nic_dev *nic_dev, bool status); int hinic_disable_func_rss(struct hinic_nic_dev *nic_dev); int hinic_enable_func_rss(struct hinic_nic_dev *nic_dev);
+bool hinic_is_xdp_enable(struct hinic_nic_dev *nic_dev); +int hinic_xdp_max_mtu(struct hinic_nic_dev *nic_dev); + #define hinic_msg(level, nic_dev, msglvl, format, arg...) \ do { \ if ((nic_dev)->netdev && (nic_dev)->netdev->reg_state \ diff --git a/drivers/net/ethernet/huawei/hinic/hinic_rx.c b/drivers/net/ethernet/huawei/hinic/hinic_rx.c index 212a281200c4f..a9047432f3053 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_rx.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_rx.c @@ -383,6 +383,7 @@ void hinic_rxq_get_stats(struct hinic_rxq *rxq, stats->csum_errors = rxq_stats->csum_errors; stats->other_errors = rxq_stats->other_errors; stats->dropped = rxq_stats->dropped; + stats->xdp_dropped = rxq_stats->xdp_dropped; stats->rx_buf_empty = rxq_stats->rx_buf_empty; } while (u64_stats_fetch_retry(&rxq_stats->syncp, start)); u64_stats_update_end(&stats->syncp); @@ -397,11 +398,13 @@ void hinic_rxq_clean_stats(struct hinic_rxq_stats *rxq_stats) rxq_stats->csum_errors = 0; rxq_stats->other_errors = 0; rxq_stats->dropped = 0; + rxq_stats->xdp_dropped = 0;
rxq_stats->alloc_skb_err = 0; rxq_stats->alloc_rx_buf_err = 0; rxq_stats->map_rx_buf_err = 0; rxq_stats->rx_buf_empty = 0; + rxq_stats->xdp_large_pkt = 0; u64_stats_update_end(&rxq_stats->syncp); }
@@ -510,6 +513,87 @@ static void hinic_copy_lp_data(struct hinic_nic_dev *nic_dev, nic_dev->lb_test_rx_idx++; }
+enum hinic_xdp_pkt { + HINIC_XDP_PKT_PASS, + HINIC_XDP_PKT_DROP, +}; + +static inline void update_drop_rx_info(struct hinic_rxq *rxq, u16 weqbb_num) +{ + struct hinic_rx_info *rx_info = NULL; + + while (weqbb_num) { + rx_info = &rxq->rx_info[rxq->cons_idx & rxq->q_mask]; + if (likely(page_to_nid(rx_info->page) == numa_node_id())) + hinic_reuse_rx_page(rxq, rx_info); + + rx_info->buf_dma_addr = 0; + rx_info->page = NULL; + rxq->cons_idx++; + rxq->delta++; + + weqbb_num--; + } +} + +int hinic_run_xdp(struct hinic_rxq *rxq, u32 pkt_len) +{ + struct bpf_prog *xdp_prog = NULL; + struct hinic_rx_info *rx_info = NULL; + struct xdp_buff xdp; + int result = HINIC_XDP_PKT_PASS; + u16 weqbb_num = 1; /* xdp can only use one rx_buff */ + u8 *va = NULL; + u32 act; + + rcu_read_lock(); + xdp_prog = READ_ONCE(rxq->xdp_prog); + if (!xdp_prog) + goto unlock_rcu; + + if (unlikely(pkt_len > rxq->buf_len)) { + RXQ_STATS_INC(rxq, xdp_large_pkt); + weqbb_num = (u16)(pkt_len >> rxq->rx_buff_shift) + + ((pkt_len & (rxq->buf_len - 1)) ? 1 : 0); + result = HINIC_XDP_PKT_DROP; + goto xdp_out; + } + + rx_info = &rxq->rx_info[rxq->cons_idx & rxq->q_mask]; + va = (u8 *)page_address(rx_info->page) + rx_info->page_offset; + prefetch(va); + dma_sync_single_range_for_cpu(rxq->dev, rx_info->buf_dma_addr, + rx_info->page_offset, rxq->buf_len, + DMA_FROM_DEVICE); + xdp.data = va; + xdp.data_hard_start = xdp.data; + xdp.data_end = xdp.data + pkt_len; + xdp_set_data_meta_invalid(&xdp); + prefetchw(xdp.data_hard_start); + act = bpf_prog_run_xdp(xdp_prog, &xdp); + switch (act) { + case XDP_PASS: + break; + default: + bpf_warn_invalid_xdp_action(act); + /* fallthrough */ + case XDP_DROP: + result = HINIC_XDP_PKT_DROP; + break; + } + +xdp_out: + if (result == HINIC_XDP_PKT_DROP) { + RXQ_STATS_INC(rxq, xdp_dropped); + update_drop_rx_info(rxq, weqbb_num); + } + +unlock_rcu: + rcu_read_unlock(); + + return result; +} + int recv_one_pkt(struct hinic_rxq *rxq, struct hinic_rq_cqe *rx_cqe, u32 pkt_len, u32 vlan_len, u32 status) { @@ -517,6 +601,11 @@ int recv_one_pkt(struct hinic_rxq *rxq, struct hinic_rq_cqe *rx_cqe, struct net_device *netdev = rxq->netdev; struct hinic_nic_dev *nic_dev = netdev_priv(netdev); u32 offload_type; + u32 xdp_status; + + xdp_status = hinic_run_xdp(rxq, pkt_len); + if (xdp_status == HINIC_XDP_PKT_DROP) + return 0;
skb = hinic_fetch_rx_buffer(rxq, pkt_len); if (unlikely(!skb)) { diff --git a/drivers/net/ethernet/huawei/hinic/hinic_rx.h b/drivers/net/ethernet/huawei/hinic/hinic_rx.h index b6e8935c01d48..827904f7839bc 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_rx.h +++ b/drivers/net/ethernet/huawei/hinic/hinic_rx.h @@ -37,11 +37,13 @@ struct hinic_rxq_stats { u64 csum_errors; u64 other_errors; u64 dropped; + u64 xdp_dropped; u64 rx_buf_empty;
u64 alloc_skb_err; u64 alloc_rx_buf_err; u64 map_rx_buf_err; + u64 xdp_large_pkt;
struct u64_stats_sync syncp; }; @@ -75,6 +77,7 @@ struct hinic_rxq { u16 msix_entry_idx;
struct hinic_rx_info *rx_info; + struct bpf_prog *xdp_prog;
struct hinic_irq *irq_cfg; u16 next_to_alloc;
From: Chiqijun chiqijun@huawei.com
driver inclusion category: feature bugzilla: 4472
-----------------------------------------------------------------------
Add support for hinic PMD on VF
Signed-off-by: Chiqijun chiqijun@huawei.com Reviewed-by: Wangxiaoyun cloud.wangxiaoyun@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- drivers/net/ethernet/huawei/hinic/hinic_nic_cfg.c | 7 +++++++ drivers/net/ethernet/huawei/hinic/hinic_port_cmd.h | 7 +++++++ 2 files changed, 14 insertions(+)
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_nic_cfg.c b/drivers/net/ethernet/huawei/hinic/hinic_nic_cfg.c index 921c8baef2048..463b119c42e42 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_nic_cfg.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_nic_cfg.c @@ -166,6 +166,13 @@ struct vf_cmd_check_handle nic_cmd_support_vf[] = {
{HINIC_PORT_CMD_SET_VLAN_FILTER, hinic_mbox_check_func_id_8B}, {HINIC_PORT_CMD_FORCE_PKT_DROP, check_force_pkt_drop}, + {HINIC_PORT_CMD_Q_FILTER, hinic_mbox_check_func_id_8B}, + {HINIC_PORT_CMD_TCAM_FILTER, NULL}, + {HINIC_PORT_CMD_UP_TC_ADD_FLOW, NULL}, + {HINIC_PORT_CMD_UP_TC_DEL_FLOW, NULL}, + {HINIC_PORT_CMD_UP_TC_FLUSH_TCAM, hinic_mbox_check_func_id_8B}, + {HINIC_PORT_CMD_UP_TC_CTRL_TCAM_BLOCK, hinic_mbox_check_func_id_8B}, + {HINIC_PORT_CMD_UP_TC_ENABLE, hinic_mbox_check_func_id_8B}, };
int hinic_init_function_table(void *hwdev, u16 rx_buf_sz) diff --git a/drivers/net/ethernet/huawei/hinic/hinic_port_cmd.h b/drivers/net/ethernet/huawei/hinic/hinic_port_cmd.h index 518c815e0e779..d720974926a7d 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_port_cmd.h +++ b/drivers/net/ethernet/huawei/hinic/hinic_port_cmd.h @@ -160,6 +160,13 @@ enum hinic_port_cmd { /* not defined in base line */
HINIC_PORT_CMD_GET_SFP_INFO = 0xad, + HINIC_PORT_CMD_UP_TC_ADD_FLOW = 0xAF, + HINIC_PORT_CMD_UP_TC_DEL_FLOW = 0xB0, + HINIC_PORT_CMD_UP_TC_GET_FLOW = 0xB1, + HINIC_PORT_CMD_UP_TC_FLUSH_TCAM = 0xB2, + HINIC_PORT_CMD_UP_TC_CTRL_TCAM_BLOCK = 0xB3, + HINIC_PORT_CMD_UP_TC_ENABLE = 0xB4, + HINIC_PORT_CMD_UP_TC_GET_TCAM_BLOCK = 0xB5,
HINIC_PORT_CMD_SET_NETQ = 0xc1, HINIC_PORT_CMD_ADD_RQ_FILTER = 0xc2,
From: Chiqijun chiqijun@huawei.com
driver inclusion category: bugfix bugzilla: 4472
-----------------------------------------------------------------------
update hinic version to 2.3.2.18
Signed-off-by: Chiqijun chiqijun@huawei.com Reviewed-by: Wangxiaoyun cloud.wangxiaoyun@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- drivers/net/ethernet/huawei/hinic/hinic_nic_dev.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_nic_dev.h b/drivers/net/ethernet/huawei/hinic/hinic_nic_dev.h index 7255a3603b7f4..3f3f5558086c3 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_nic_dev.h +++ b/drivers/net/ethernet/huawei/hinic/hinic_nic_dev.h @@ -30,7 +30,7 @@ #define HINIC_DRV_NAME "hinic" #define HINIC_CHIP_NAME "hinic"
-#define HINIC_DRV_VERSION "2.3.2.17" +#define HINIC_DRV_VERSION "2.3.2.18" struct vf_data_storage;
#define HINIC_FUNC_IS_VF(hwdev) (hinic_func_type(hwdev) == TYPE_VF)
From: Thomas Gleixner tglx@linutronix.de
mainline inclusion from mainline-5.2-rc3 commit 2874c5fd284268364ece81a7bd936f3c8168e567 category: bugfix bugzilla: NA CVE: NA
---------------------------
Based on 1 normalized pattern(s):
this program is free software you can redistribute it and or modify it under the terms of the gnu general public license as published by the free software foundation either version 2 of the license or at your option any later version
extracted by the scancode license scanner the SPDX license identifier
GPL-2.0-or-later
has been chosen to replace the boilerplate/reference in 3029 file(s).
Signed-off-by: Thomas Gleixner tglx@linutronix.de Reviewed-by: Allison Randal allison@lohutok.net Cc: linux-spdx@vger.kernel.org Link: https://lkml.kernel.org/r/20190527070032.746973796@linutronix.de Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Yonglong Liu liuyonglong@huawei.com Reviewed-by: li yongxin liyongxin1@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- drivers/net/ethernet/hisilicon/hip04_eth.c | 6 +----- drivers/net/ethernet/hisilicon/hix5hd2_gmac.c | 6 +----- drivers/net/ethernet/hisilicon/hns/hnae.c | 6 +----- drivers/net/ethernet/hisilicon/hns/hnae.h | 6 +----- drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c | 6 +----- drivers/net/ethernet/hisilicon/hns/hns_dsaf_gmac.c | 6 +----- drivers/net/ethernet/hisilicon/hns/hns_dsaf_gmac.h | 6 +----- drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c | 6 +----- drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.h | 6 +----- drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c | 6 +----- drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h | 6 +----- drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c | 6 +----- drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.h | 6 +----- drivers/net/ethernet/hisilicon/hns/hns_dsaf_ppe.c | 6 +----- drivers/net/ethernet/hisilicon/hns/hns_dsaf_ppe.h | 6 +----- drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c | 6 +----- drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.h | 6 +----- drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h | 6 +----- drivers/net/ethernet/hisilicon/hns/hns_dsaf_xgmac.c | 6 +----- drivers/net/ethernet/hisilicon/hns/hns_dsaf_xgmac.h | 6 +----- drivers/net/ethernet/hisilicon/hns/hns_enet.c | 6 +----- drivers/net/ethernet/hisilicon/hns/hns_enet.h | 6 +----- drivers/net/ethernet/hisilicon/hns/hns_ethtool.c | 6 +----- drivers/net/ethernet/hisilicon/hns_mdio.c | 6 +----- 24 files changed, 24 insertions(+), 120 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hip04_eth.c b/drivers/net/ethernet/hisilicon/hip04_eth.c index ba9de46cca941..9630a6cdbd916 100644 --- a/drivers/net/ethernet/hisilicon/hip04_eth.c +++ b/drivers/net/ethernet/hisilicon/hip04_eth.c @@ -1,11 +1,7 @@ +// SPDX-License-Identifier: GPL-2.0-or-later
/* Copyright (c) 2014 Linaro Ltd. * Copyright (c) 2014 Hisilicon Limited. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. */
#include <linux/module.h> diff --git a/drivers/net/ethernet/hisilicon/hix5hd2_gmac.c b/drivers/net/ethernet/hisilicon/hix5hd2_gmac.c index f6749ed0a7d02..ecc4c6e1ef803 100644 --- a/drivers/net/ethernet/hisilicon/hix5hd2_gmac.c +++ b/drivers/net/ethernet/hisilicon/hix5hd2_gmac.c @@ -1,10 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* Copyright (c) 2014 Linaro Ltd. * Copyright (c) 2014 Hisilicon Limited. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. */
#include <linux/module.h> diff --git a/drivers/net/ethernet/hisilicon/hns/hnae.c b/drivers/net/ethernet/hisilicon/hns/hnae.c index c4b219b7e0daf..7d58810c9da7f 100644 --- a/drivers/net/ethernet/hisilicon/hns/hnae.c +++ b/drivers/net/ethernet/hisilicon/hns/hnae.c @@ -1,10 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * Copyright (c) 2014-2015 Hisilicon Limited. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. */
#include <linux/dma-mapping.h> diff --git a/drivers/net/ethernet/hisilicon/hns/hnae.h b/drivers/net/ethernet/hisilicon/hns/hnae.h index fde3113c7806d..5d947e35990e5 100644 --- a/drivers/net/ethernet/hisilicon/hns/hnae.h +++ b/drivers/net/ethernet/hisilicon/hns/hnae.h @@ -1,10 +1,6 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (c) 2014-2015 Hisilicon Limited. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. */
#ifndef __HNAE_H diff --git a/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c b/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c index cadfe42ad5a17..9e5bfc4bee597 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c @@ -1,10 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * Copyright (c) 2014-2015 Hisilicon Limited. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. */
#include <linux/etherdevice.h> diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_gmac.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_gmac.c index 8622650f31a4f..267a95cb3e6b8 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_gmac.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_gmac.c @@ -1,10 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * Copyright (c) 2014-2015 Hisilicon Limited. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. */
#include <linux/delay.h> diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_gmac.h b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_gmac.h index 44fe3010dc6db..ec266e7fff83f 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_gmac.h +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_gmac.h @@ -1,10 +1,6 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (c) 2014-2015 Hisilicon Limited. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. */
#ifndef _HNS_GMAC_H diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c index 11af7baa383bb..c9118a5186010 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c @@ -1,10 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * Copyright (c) 2014-2015 Hisilicon Limited. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. */
#include <linux/acpi.h> diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.h b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.h index 31d589f75947c..9771ba8f5be8f 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.h +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.h @@ -1,10 +1,6 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (c) 2014-2015 Hisilicon Limited. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. */
#ifndef _HNS_DSAF_MAC_H diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c index 9c09beaeaeaf4..0cbe1cf73fe78 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c @@ -1,10 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * Copyright (c) 2014-2015 Hisilicon Limited. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. */
#include <linux/acpi.h> diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h index 76cc8887e1a83..cba04bfa0b3f8 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h @@ -1,10 +1,6 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (c) 2014-2015 Hisilicon Limited. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. */
#ifndef __HNS_DSAF_MAIN_H diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c index e519094658d49..6b9e9ea67b2c9 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c @@ -1,10 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * Copyright (c) 2014-2015 Hisilicon Limited. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. */
#include "hns_dsaf_mac.h" diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.h b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.h index 310e80261366a..f64c6667dd05f 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.h +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.h @@ -1,10 +1,6 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (c) 2014-2015 Hisilicon Limited. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. */
#ifndef _HNS_DSAF_MISC_H diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_ppe.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_ppe.c index 22035a248803f..ad3b8adfa0371 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_ppe.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_ppe.c @@ -1,10 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * Copyright (c) 2014-2015 Hisilicon Limited. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. */
#include <linux/module.h> diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_ppe.h b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_ppe.h index 110c6e8222c70..2721f1f1ab42b 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_ppe.h +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_ppe.h @@ -1,10 +1,6 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (c) 2014-2015 Hisilicon Limited. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. */
#ifndef _HNS_DSAF_PPE_H diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c index 44a2de6021597..a64e755e2510b 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c @@ -1,10 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * Copyright (c) 2014-2015 Hisilicon Limited. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. */
#include <linux/cdev.h> diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.h b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.h index 2319b772a271e..3741befb914e5 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.h +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.h @@ -1,10 +1,6 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (c) 2014-2015 Hisilicon Limited. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. */
#ifndef _HNS_DSAF_RCB_H diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h index b9e7f11f08968..47ccb6e0fcaaf 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h @@ -1,10 +1,6 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (c) 2014-2015 Hisilicon Limited. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. */
#ifndef _DSAF_REG_H_ diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_xgmac.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_xgmac.c index 5c5cbabad1d44..1c4ca8d961864 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_xgmac.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_xgmac.c @@ -1,10 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * Copyright (c) 2014-2015 Hisilicon Limited. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. */
#include <linux/io-64-nonatomic-hi-lo.h> diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_xgmac.h b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_xgmac.h index da6c5343d3e13..e1b3db9807127 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_xgmac.h +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_xgmac.h @@ -1,10 +1,6 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (c) 2014-2015 Hisilicon Limited. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. */
#ifndef _HNS_XGMAC_H diff --git a/drivers/net/ethernet/hisilicon/hns/hns_enet.c b/drivers/net/ethernet/hisilicon/hns/hns_enet.c index 7b9b7503256fc..e96226aa8f8ca 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_enet.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_enet.c @@ -1,10 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * Copyright (c) 2014-2015 Hisilicon Limited. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. */
#include <linux/clk.h> diff --git a/drivers/net/ethernet/hisilicon/hns/hns_enet.h b/drivers/net/ethernet/hisilicon/hns/hns_enet.h index 1b786bc9f82ad..21e4843f38bc7 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_enet.h +++ b/drivers/net/ethernet/hisilicon/hns/hns_enet.h @@ -1,10 +1,6 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (c) 2014-2015 Hisilicon Limited. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. */
#ifndef __HNS_ENET_H diff --git a/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c b/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c index 497e035255769..127c96621add2 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c @@ -1,10 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * Copyright (c) 2014-2015 Hisilicon Limited. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. */
#include <linux/etherdevice.h> diff --git a/drivers/net/ethernet/hisilicon/hns_mdio.c b/drivers/net/ethernet/hisilicon/hns_mdio.c index edca9d8b7f15b..d6e0e3f3d012e 100644 --- a/drivers/net/ethernet/hisilicon/hns_mdio.c +++ b/drivers/net/ethernet/hisilicon/hns_mdio.c @@ -1,10 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * Copyright (c) 2014-2015 Hisilicon Limited. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. */
#include <linux/acpi.h>
From: Yonglong Liu liuyonglong@huawei.com
driver inclusion category: cleanup bugzilla: NA CVE: NA
----------------------------
Signed-off-by: Yonglong Liu liuyonglong@huawei.com Reviewed-by: li yongxin liyongxin1@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- .../net/ethernet/hisilicon/hns/hns_ae_adapt.c | 2 +- .../net/ethernet/hisilicon/hns/hns_dsaf_mac.c | 2 +- .../net/ethernet/hisilicon/hns/hns_dsaf_main.c | 16 ++++++++-------- .../net/ethernet/hisilicon/hns/hns_dsaf_rcb.c | 4 ++-- .../net/ethernet/hisilicon/hns/hns_dsaf_xgmac.c | 2 +- drivers/net/ethernet/hisilicon/hns/hns_enet.c | 4 ++-- drivers/net/ethernet/hisilicon/hns_mdio.c | 4 ++-- 7 files changed, 17 insertions(+), 17 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c b/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c index 9e5bfc4bee597..e94590ba4e7ab 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c @@ -637,7 +637,7 @@ static void hns_ae_update_stats(struct hnae_handle *handle, struct hnae_vf_cb *vf_cb = hns_ae_get_vf_cb(handle); u64 tx_bytes = 0, rx_bytes = 0, tx_packets = 0, rx_packets = 0; u64 rx_errors = 0, tx_errors = 0, tx_dropped = 0; - u64 rx_missed_errors = 0; + u64 rx_missed_errors;
dsaf_dev = hns_ae_get_dsaf_dev(handle->dev); if (!dsaf_dev) diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c index c9118a5186010..961d25c6ea131 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c @@ -1200,7 +1200,7 @@ void hns_mac_get_regs(struct hns_mac_cb *mac_cb, void *data)
void hns_set_led_opt(struct hns_mac_cb *mac_cb) { - int nic_data = 0; + int nic_data; int txpkts, rxpkts;
txpkts = mac_cb->txpkt_for_led - mac_cb->hw_stats.tx_good_pkts; diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c index 0cbe1cf73fe78..4f02dff1a412d 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c @@ -1583,7 +1583,7 @@ int hns_dsaf_set_mac_uc_entry( struct dsaf_device *dsaf_dev, struct dsaf_drv_mac_single_dest_entry *mac_entry) { - u16 entry_index = DSAF_INVALID_ENTRY_IDX; + u16 entry_index; struct dsaf_drv_tbl_tcam_key mac_key; struct dsaf_tbl_tcam_ucast_cfg mac_data; struct dsaf_drv_priv *priv = @@ -1649,7 +1649,7 @@ int hns_dsaf_rm_mac_addr( struct dsaf_device *dsaf_dev, struct dsaf_drv_mac_single_dest_entry *mac_entry) { - u16 entry_index = DSAF_INVALID_ENTRY_IDX; + u16 entry_index; struct dsaf_tbl_tcam_ucast_cfg mac_data; struct dsaf_drv_tbl_tcam_key mac_key;
@@ -1721,7 +1721,7 @@ static void hns_dsaf_mc_mask_bit_clear(char *dst, const char *src) int hns_dsaf_add_mac_mc_port(struct dsaf_device *dsaf_dev, struct dsaf_drv_mac_single_dest_entry *mac_entry) { - u16 entry_index = DSAF_INVALID_ENTRY_IDX; + u16 entry_index; struct dsaf_drv_tbl_tcam_key mac_key; struct dsaf_drv_tbl_tcam_key mask_key; struct dsaf_tbl_tcam_data *pmask_key = NULL; @@ -1831,7 +1831,7 @@ int hns_dsaf_add_mac_mc_port(struct dsaf_device *dsaf_dev, int hns_dsaf_del_mac_entry(struct dsaf_device *dsaf_dev, u16 vlan_id, u8 in_port_num, u8 *addr) { - u16 entry_index = DSAF_INVALID_ENTRY_IDX; + u16 entry_index; struct dsaf_drv_tbl_tcam_key mac_key; struct dsaf_drv_priv *priv = (struct dsaf_drv_priv *)hns_dsaf_dev_priv(dsaf_dev); @@ -1880,7 +1880,7 @@ int hns_dsaf_del_mac_entry(struct dsaf_device *dsaf_dev, u16 vlan_id, int hns_dsaf_del_mac_mc_port(struct dsaf_device *dsaf_dev, struct dsaf_drv_mac_single_dest_entry *mac_entry) { - u16 entry_index = DSAF_INVALID_ENTRY_IDX; + u16 entry_index; struct dsaf_drv_tbl_tcam_key mac_key; struct dsaf_drv_priv *priv = hns_dsaf_dev_priv(dsaf_dev); struct dsaf_drv_soft_mac_tbl *soft_mac_entry = priv->soft_mac_tbl; @@ -2223,7 +2223,7 @@ void hns_dsaf_update_stats(struct dsaf_device *dsaf_dev, u32 node_num) */ void hns_dsaf_get_regs(struct dsaf_device *ddev, u32 port, void *data) { - u32 i = 0; + u32 i; u32 j; u32 *p = data; u32 reg_tmp; @@ -2721,7 +2721,7 @@ static void set_promisc_tcam_enable(struct dsaf_device *dsaf_dev, u32 port) struct dsaf_drv_mac_single_dest_entry mask_entry; struct dsaf_drv_tbl_tcam_key temp_key, mask_key; struct dsaf_drv_soft_mac_tbl *soft_mac_entry; - u16 entry_index = DSAF_INVALID_ENTRY_IDX; + u16 entry_index; struct dsaf_drv_tbl_tcam_key mac_key; struct hns_mac_cb *mac_cb; u8 addr[ETH_ALEN] = {0}; @@ -2823,7 +2823,7 @@ static void set_promisc_tcam_disable(struct dsaf_device *dsaf_dev, u32 port) struct dsaf_tbl_tcam_data tbl_tcam_data_uc = {0, 0}; struct dsaf_tbl_tcam_data tbl_tcam_mask = {0, 0}; struct dsaf_drv_soft_mac_tbl *soft_mac_entry; - u16 entry_index = DSAF_INVALID_ENTRY_IDX; + u16 entry_index; struct dsaf_drv_tbl_tcam_key mac_key; u8 addr[ETH_ALEN] = {0};
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c index a64e755e2510b..c8803cd7271f5 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c @@ -988,7 +988,7 @@ void hns_rcb_get_common_regs(struct rcb_common_cb *rcb_com, void *data) bool is_dbg = HNS_DSAF_IS_DEBUG(rcb_com->dsaf_dev); u32 reg_tmp; u32 reg_num_tmp; - u32 i = 0; + u32 i;
/*rcb common registers */ regs[0] = dsaf_read_dev(rcb_com, RCB_COM_CFG_ENDIAN_REG); @@ -1059,7 +1059,7 @@ void hns_rcb_get_ring_regs(struct hnae_queue *queue, void *data) u32 *regs = data; struct ring_pair_cb *ring_pair = container_of(queue, struct ring_pair_cb, q); - u32 i = 0; + u32 i;
/*rcb ring registers */ regs[0] = dsaf_read_dev(queue, RCB_RING_RX_RING_BASEADDR_L_REG); diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_xgmac.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_xgmac.c index 1c4ca8d961864..bb00a6feb5159 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_xgmac.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_xgmac.c @@ -481,7 +481,7 @@ static void hns_xgmac_get_link_status(void *mac_drv, u32 *link_stat) */ static void hns_xgmac_get_regs(void *mac_drv, void *data) { - u32 i = 0; + u32 i; struct mac_driver *drv = (struct mac_driver *)mac_drv; u32 *regs = data; u64 qtmp; diff --git a/drivers/net/ethernet/hisilicon/hns/hns_enet.c b/drivers/net/ethernet/hisilicon/hns/hns_enet.c index e96226aa8f8ca..c5425e65c33fb 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_enet.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_enet.c @@ -873,7 +873,7 @@ static int hns_nic_rx_poll_one(struct hns_nic_ring_data *ring_data, static bool hns_nic_rx_fini_pro(struct hns_nic_ring_data *ring_data) { struct hnae_ring *ring = ring_data->ring; - int num = 0; + int num; bool rx_stopped;
hns_update_rx_rate(ring); @@ -1914,7 +1914,7 @@ static void hns_nic_set_rx_mode(struct net_device *ndev) static void hns_nic_get_stats64(struct net_device *ndev, struct rtnl_link_stats64 *stats) { - int idx = 0; + int idx; u64 tx_bytes = 0; u64 rx_bytes = 0; u64 tx_pkts = 0; diff --git a/drivers/net/ethernet/hisilicon/hns_mdio.c b/drivers/net/ethernet/hisilicon/hns_mdio.c index d6e0e3f3d012e..d60aefd011f6c 100644 --- a/drivers/net/ethernet/hisilicon/hns_mdio.c +++ b/drivers/net/ethernet/hisilicon/hns_mdio.c @@ -279,7 +279,7 @@ static int hns_mdio_write(struct mii_bus *bus, static int hns_mdio_read(struct mii_bus *bus, int phy_id, int regnum) { int ret; - u16 reg_val = 0; + u16 reg_val; u8 devad = ((regnum >> 16) & 0x1f); u8 is_c45 = !!(regnum & MII_ADDR_C45); u16 reg = (u16)(regnum & 0xffff); @@ -421,7 +421,7 @@ static int hns_mdio_probe(struct platform_device *pdev) struct hns_mdio_device *mdio_dev; struct mii_bus *new_bus; struct resource *res; - int ret = -ENODEV; + int ret;
if (!pdev) { dev_err(NULL, "pdev is NULL!\r\n");
From: Yonglong Liu liuyonglong@huawei.com
driver inclusion category: bugfix bugzilla: NA CVE: NA
----------------------------
When disable promisc mode after enable promisc mode, the non-promiscuous mode does not take effect.
The driver use the last 12 mac table for promisc mode(6 ports, each port have a mc vague mac table and a uc vague mac table). But when disabling promisc mode, the driver did not look for the last 12 vague mac table, cause this problem.
Fixes: 421ccc3859d6 ("net: hns: fix ping failed when use net bridge and send multicast") Signed-off-by: Yonglong Liu liuyonglong@huawei.com Reviewed-by: li yongxin liyongxin1@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c | 10 +++++----- drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c index 4f02dff1a412d..61f2f5896d3b4 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c @@ -1482,7 +1482,7 @@ static u16 hns_dsaf_find_soft_mac_entry( u32 i;
soft_mac_entry = priv->soft_mac_tbl; - for (i = 0; i < dsaf_dev->tcam_max_num; i++) { + for (i = 0; i < DSAF_TCAM_SUM; i++) { /* invall tab entry */ if ((soft_mac_entry->index != DSAF_INVALID_ENTRY_IDX) && (soft_mac_entry->tcam_key.high.val == mac_key->high.val) && @@ -1772,7 +1772,7 @@ int hns_dsaf_add_mac_mc_port(struct dsaf_device *dsaf_dev, if (entry_index == DSAF_INVALID_ENTRY_IDX) { /*if hasnot empty, error*/ dev_err(dsaf_dev->dev, - "set_uc_entry failed, %s Mac key(%#x:%#x)\n", + "set_mc_entry failed, %s Mac key(%#x:%#x)\n", dsaf_dev->ae_dev.name, mac_key.high.val, mac_key.low.val); return -EINVAL; @@ -1801,7 +1801,7 @@ int hns_dsaf_add_mac_mc_port(struct dsaf_device *dsaf_dev, mac_data.tbl_mcast_item_vld = 1;
dev_dbg(dsaf_dev->dev, - "set_uc_entry, %s Mac key(%#x:%#x) entry_index%d\n", + "set_mc_entry, %s Mac key(%#x:%#x) entry_index%d\n", dsaf_dev->ae_dev.name, mac_key.high.val, mac_key.low.val, entry_index);
@@ -1996,7 +1996,7 @@ int hns_dsaf_clr_mac_mc_port(struct dsaf_device *dsaf_dev, u8 mac_id, if (HNS_DSAF_IS_DEBUG(dsaf_dev)) return 0;
- for (i = 0; i < DSAF_TCAM_SUM - DSAFV2_MAC_FUZZY_TCAM_NUM; i++) { + for (i = 0; i < dsaf_dev->tcam_max_num; i++) { u8 addr[ETH_ALEN]; u8 port;
@@ -2775,7 +2775,7 @@ static void set_promisc_tcam_enable(struct dsaf_device *dsaf_dev, u32 port) memset(&temp_key, 0x0, sizeof(temp_key)); mask_entry.addr[0] = 0x01; hns_dsaf_set_mac_key(dsaf_dev, &mask_key, mask_entry.in_vlan_id, - 0xf, mask_entry.addr); + port, mask_entry.addr); tbl_tcam_mcast.tbl_mcast_item_vld = 1; tbl_tcam_mcast.tbl_mcast_old_en = 0;
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h index 47ccb6e0fcaaf..b5a7d26093513 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h @@ -38,7 +38,7 @@ #define DSAF_TOTAL_QUEUE_NUM 129
/* reserved a tcam entry for each port to support promisc by fuzzy match */ -#define DSAFV2_MAC_FUZZY_TCAM_NUM DSAF_MAX_PORT_NUM +#define DSAFV2_MAC_FUZZY_TCAM_NUM (DSAF_MAX_PORT_NUM * 2)
#define DSAF_TCAM_SUM 512 #define DSAF_LINE_SUM (2048 * 14)
From: Tom Rix trix@redhat.com
mainline inclusion from mainline-v5.11-rc5 commit 99d518970c5a1901e83cdd4a0a6ff5a41ba56a56 category: bugfix bugzilla: NA CVE: NA
----------------------------
When DEBUG is defined this error occurs
drivers/net/ethernet/hisilicon/hns/hns_enet.c:1505:36: error: ‘struct net_device’ has no member named ‘ae_handle’; did you mean ‘rx_handler’? assert(skb->queue_mapping < ndev->ae_handle->q_num); ^~~~~~~~~
ae_handle is an element of struct hns_nic_priv, so change ndev to priv.
Signed-off-by: Tom Rix trix@redhat.com Link: https://lore.kernel.org/r/20210117191044.533725-1-trix@redhat.com Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Yonglong Liu liuyonglong@huawei.com Reviewed-by: li yongxin liyongxin1@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- drivers/net/ethernet/hisilicon/hns/hns_enet.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_enet.c b/drivers/net/ethernet/hisilicon/hns/hns_enet.c index c5425e65c33fb..65e91ecdf0235 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_enet.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_enet.c @@ -1539,7 +1539,7 @@ static netdev_tx_t hns_nic_net_xmit(struct sk_buff *skb, { struct hns_nic_priv *priv = netdev_priv(ndev);
- assert(skb->queue_mapping < ndev->ae_handle->q_num); + assert(skb->queue_mapping < priv->ae_handle->q_num);
return hns_nic_net_xmit_hw(ndev, skb, &tx_ring_data(priv, skb->queue_mapping));
From: Yonglong Liu liuyonglong@huawei.com
driver inclusion category: bugfix bugzilla: NA CVE: NA
-----------------------------
When setting "autoneg off speed 100 duplex half", ping will failed. This patch turn off the autoneg mode of mac to fix the problem.
Signed-off-by: Yonglong Liu liuyonglong@huawei.com Reviewed-by: li yongxin liyongxin1@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c | 3 --- 1 file changed, 3 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c index 961d25c6ea131..cdb34322d9af7 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c @@ -470,9 +470,6 @@ void hns_mac_reset(struct hns_mac_cb *mac_cb) if (drv->set_tx_auto_pause_frames) drv->set_tx_auto_pause_frames(drv, mac_cb->tx_pause_frm_time);
- if (drv->set_an_mode) - drv->set_an_mode(drv, 1); - if (drv->mac_pausefrm_cfg) { if (mac_cb->mac_type == HNAE_PORT_DEBUG) drv->mac_pausefrm_cfg(drv, !is_ver1, !is_ver1);
From: Yonglong Liu liuyonglong@huawei.com
driver inclusion category: bugfix bugzilla: NA CVE: NA
-----------------------------
The "Advertised link modes" always shows "1000baseT/Full", because the driver only assigned this value.
Function ethtool_convert_link_mode_to_legacy_u32() should be called after function phy_ethtool_ksettings_get() to get the current value of the phy.
Signed-off-by: Yonglong Liu liuyonglong@huawei.com Reviewed-by: li yongxin liyongxin1@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- drivers/net/ethernet/hisilicon/hns/hns_ethtool.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c b/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c index 127c96621add2..8fcb189ed0ba5 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c @@ -135,11 +135,6 @@ static int hns_nic_get_link_ksettings(struct net_device *net_dev, return -EINVAL; }
- ethtool_convert_link_mode_to_legacy_u32(&supported, - cmd->link_modes.supported); - ethtool_convert_link_mode_to_legacy_u32(&advertising, - cmd->link_modes.advertising); - /* When there is no phy, autoneg is off. */ cmd->base.autoneg = false; cmd->base.speed = speed; @@ -148,6 +143,11 @@ static int hns_nic_get_link_ksettings(struct net_device *net_dev, if (net_dev->phydev) phy_ethtool_ksettings_get(net_dev->phydev, cmd);
+ ethtool_convert_link_mode_to_legacy_u32(&supported, + cmd->link_modes.supported); + ethtool_convert_link_mode_to_legacy_u32(&advertising, + cmd->link_modes.advertising); + link_stat = hns_nic_get_link(net_dev); if (!link_stat) { cmd->base.speed = (u32)SPEED_UNKNOWN; @@ -160,7 +160,6 @@ static int hns_nic_get_link_ksettings(struct net_device *net_dev, supported |= h->if_support; if (h->phy_if == PHY_INTERFACE_MODE_SGMII) { supported |= SUPPORTED_TP; - advertising |= ADVERTISED_1000baseT_Full; } else if (h->phy_if == PHY_INTERFACE_MODE_XGMII) { supported |= SUPPORTED_FIBRE; advertising |= ADVERTISED_10000baseKR_Full;
From: Jason Yan yanaijie@huawei.com
mainline inclusion from mainline-5.8-rc1 commit 6d92797716003a462bd75bbda3740718ce54bcdd category: bugfix bugzilla: NA CVE: NA
---------------------------
Fix the following coccicheck warning:
drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c:700:2-8: WARNING: Assignment of 0/1 to bool variable drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c:702:2-8: WARNING: Assignment of 0/1 to bool variable
Reported-by: Hulk Robot hulkci@huawei.com Signed-off-by: Jason Yan yanaijie@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Yonglong Liu liuyonglong@huawei.com Reviewed-by: li yongxin liyongxin1@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c index cdb34322d9af7..fd68ea287f7e2 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c @@ -693,9 +693,9 @@ hns_mac_register_phydev(struct mii_bus *mdio, struct hns_mac_cb *mac_cb, return rc;
if (!strcmp(phy_type, phy_modes(PHY_INTERFACE_MODE_XGMII))) - is_c45 = 1; + is_c45 = true; else if (!strcmp(phy_type, phy_modes(PHY_INTERFACE_MODE_SGMII))) - is_c45 = 0; + is_c45 = false; else return -ENODATA;
From: Xu Wang vulab@iscas.ac.cn
mainline inclusion from mainline-5.9-rc1 commit 74b5afea3b5e141e9a0b76863858c072e28713f1 category: bugfix bugzilla: NA CVE: NA
---------------------------
This patch is to use eth_broadcast_addr() to assign broadcast address insetad of memset().
Signed-off-by: Xu Wang vulab@iscas.ac.cn Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Yonglong Liu liuyonglong@huawei.com Reviewed-by: li yongxin liyongxin1@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c index 61f2f5896d3b4..385830129ae6d 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c @@ -1698,7 +1698,7 @@ static void hns_dsaf_setup_mc_mask(struct dsaf_device *dsaf_dev, u8 port_num, u8 *mask, u8 *addr) { if (MAC_IS_BROADCAST(addr)) - memset(mask, 0xff, ETH_ALEN); + eth_broadcast_addr(mask); else memcpy(mask, dsaf_dev->mac_cb[port_num]->mc_mask, ETH_ALEN); }
From: Krzysztof Wilczynski kw@linux.com
mainline inclusion from mainline-5.4-rc1 commit 5e5d8bc4a07319aa6961b6ee2d4813626e1fcf13 category: bugfix bugzilla: NA CVE: NA
---------------------------
Move the static keyword to the front of declaration of g_dsaf_mode_match, and resolve the following compiler warning that can be seen when building with warnings enabled (W=1):
drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c:27:1: warning: ‘static’ is not at beginning of declaration [-Wold-style-declaration]
Signed-off-by: Krzysztof Wilczynski kw@linux.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Yonglong Liu liuyonglong@huawei.com Reviewed-by: li yongxin liyongxin1@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c index 385830129ae6d..c1d3ad705e767 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c @@ -24,7 +24,7 @@ #include "hns_dsaf_rcb.h" #include "hns_dsaf_misc.h"
-const static char *g_dsaf_mode_match[DSAF_MODE_MAX] = { +static const char *g_dsaf_mode_match[DSAF_MODE_MAX] = { [DSAF_MODE_DISABLE_2PORT_64VM] = "2port-64vf", [DSAF_MODE_DISABLE_6PORT_0VM] = "6port-16rss", [DSAF_MODE_DISABLE_6PORT_16VM] = "6port-16vf",
From: Colin Ian King colin.king@canonical.com
mainline inclusion from mainline-5.5-rc1 commit 99d895729f5d438518c8223d7ce81615cb9a88e9 category: bugfix bugzilla: NA CVE: NA
---------------------------
Don't populate the arrays port_map and sl_map on the stack but instead make them static. Makes the object code smaller by 64 bytes.
Before: text data bss dec hex filename 49575 6872 64 56511 dcbf hisilicon/hns/hns_dsaf_main.o
After: text data bss dec hex filename 49350 7032 64 56446 dc7e hisilicon/hns/hns_dsaf_main.o
(gcc version 9.2.1, amd64)
Signed-off-by: Colin Ian King colin.king@canonical.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Yonglong Liu liuyonglong@huawei.com Reviewed-by: li yongxin liyongxin1@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c index c1d3ad705e767..be3969dac627e 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c @@ -3001,7 +3001,7 @@ int hns_dsaf_roce_reset(struct fwnode_handle *dsaf_fwnode, bool dereset) u32 sl; u32 credit; int i; - const u32 port_map[DSAF_ROCE_CREDIT_CHN][DSAF_ROCE_CHAN_MODE_NUM] = { + static const u32 port_map[DSAF_ROCE_CREDIT_CHN][DSAF_ROCE_CHAN_MODE_NUM] = { {DSAF_ROCE_PORT_0, DSAF_ROCE_PORT_0, DSAF_ROCE_PORT_0}, {DSAF_ROCE_PORT_1, DSAF_ROCE_PORT_0, DSAF_ROCE_PORT_0}, {DSAF_ROCE_PORT_2, DSAF_ROCE_PORT_1, DSAF_ROCE_PORT_0}, @@ -3011,7 +3011,7 @@ int hns_dsaf_roce_reset(struct fwnode_handle *dsaf_fwnode, bool dereset) {DSAF_ROCE_PORT_5, DSAF_ROCE_PORT_3, DSAF_ROCE_PORT_1}, {DSAF_ROCE_PORT_5, DSAF_ROCE_PORT_3, DSAF_ROCE_PORT_1}, }; - const u32 sl_map[DSAF_ROCE_CREDIT_CHN][DSAF_ROCE_CHAN_MODE_NUM] = { + static const u32 sl_map[DSAF_ROCE_CREDIT_CHN][DSAF_ROCE_CHAN_MODE_NUM] = { {DSAF_ROCE_SL_0, DSAF_ROCE_SL_0, DSAF_ROCE_SL_0}, {DSAF_ROCE_SL_0, DSAF_ROCE_SL_1, DSAF_ROCE_SL_1}, {DSAF_ROCE_SL_0, DSAF_ROCE_SL_0, DSAF_ROCE_SL_2},
From: Zheng Yongjun zhengyongjun3@huawei.com
mainline inclusion from mainline-5.11-rc1 commit 3d4068b24cd947ca4e3fd7f4f2a34fa1bc229202 category: bugfix bugzilla: NA CVE: NA
---------------------------
Replace a comma between expression statements by a semicolon.
Signed-off-by: Zheng Yongjun zhengyongjun3@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Yonglong Liu liuyonglong@huawei.com Reviewed-by: li yongxin liyongxin1@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c index 6b9e9ea67b2c9..8791d4eb1985a 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c @@ -568,9 +568,9 @@ static phy_interface_t hns_mac_get_phy_if_acpi(struct hns_mac_cb *mac_cb) obj_args.integer.type = ACPI_TYPE_INTEGER; obj_args.integer.value = mac_cb->mac_id;
- argv4.type = ACPI_TYPE_PACKAGE, - argv4.package.count = 1, - argv4.package.elements = &obj_args, + argv4.type = ACPI_TYPE_PACKAGE; + argv4.package.count = 1; + argv4.package.elements = &obj_args;
obj = acpi_evaluate_dsm(ACPI_HANDLE(mac_cb->dev), &hns_dsaf_acpi_dsm_guid, 0, @@ -615,9 +615,9 @@ static int hns_mac_get_sfp_prsnt_acpi(struct hns_mac_cb *mac_cb, int *sfp_prsnt) obj_args.integer.type = ACPI_TYPE_INTEGER; obj_args.integer.value = mac_cb->mac_id;
- argv4.type = ACPI_TYPE_PACKAGE, - argv4.package.count = 1, - argv4.package.elements = &obj_args, + argv4.type = ACPI_TYPE_PACKAGE; + argv4.package.count = 1; + argv4.package.elements = &obj_args;
obj = acpi_evaluate_dsm(ACPI_HANDLE(mac_cb->dev), &hns_dsaf_acpi_dsm_guid, 0,
From: "Gustavo A. R. Silva" gustavo@embeddedor.com
mainline inclusion from mainline-5.7-rc1 commit c5d6cf903fe8704b65321b2e0c30afebf239247c category: bugfix bugzilla: NA CVE: NA
---------------------------
The current codebase makes use of the zero-length array language extension to the C90 standard, but the preferred mechanism to declare variable-length types such as these ones is a flexible array member[1][2], introduced in C99:
struct foo { int stuff; struct boo array[]; };
By making use of the mechanism above, we will get a compiler warning in case the flexible array does not occur last in the structure, which will help us prevent some kind of undefined behavior bugs from being inadvertently introduced[3] to the codebase from now on.
Also, notice that, dynamic memory allocations won't be affected by this change:
"Flexible array members have incomplete type, and so the sizeof operator may not be applied. As a quirk of the original implementation of zero-length arrays, sizeof evaluates to zero."[1]
This issue was found with the help of Coccinelle.
[1] https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html [2] https://github.com/KSPP/linux/issues/21 [3] commit 76497732932f ("cxgb3/l2t: Fix undefined behaviour")
Signed-off-by: Gustavo A. R. Silva gustavo@embeddedor.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Yonglong Liu liuyonglong@huawei.com Reviewed-by: li yongxin liyongxin1@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- drivers/net/ethernet/hisilicon/hns/hns_dsaf_ppe.h | 2 +- drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_ppe.h b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_ppe.h index 2721f1f1ab42b..0f0e16f9afc0d 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_ppe.h +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_ppe.h @@ -92,7 +92,7 @@ struct ppe_common_cb { u8 comm_index; /*ppe_common index*/
u32 ppe_num; - struct hns_ppe_cb ppe_cb[0]; + struct hns_ppe_cb ppe_cb[];
};
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.h b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.h index 3741befb914e5..a9f8059256999 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.h +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.h @@ -108,7 +108,7 @@ struct rcb_common_cb { u32 ring_num; u32 desc_num; /* desc num per queue*/
- struct ring_pair_cb ring_pair_cb[0]; + struct ring_pair_cb ring_pair_cb[]; };
int hns_rcb_buf_size2type(u32 buf_size);
From: Barry Song song.bao.hua@hisilicon.com
mainline inclusion from mainline-5.10-rc1 commit 5a6bd84f815485800699f55c78f690b2ed35f0c5 category: bugfix bugzilla: NA CVE: NA
---------------------------
Rather than doing request_irq and then disabling the irq immediately, it should be safer to use IRQ_NOAUTOEN flag for the irq. It removes any gap between request_irq() and disable_irq().
Cc: Salil Mehta salil.mehta@huawei.com Reviewed-by: Yunsheng Lin linyunsheng@huawei.com Signed-off-by: Barry Song song.bao.hua@hisilicon.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Yonglong Liu liuyonglong@huawei.com Reviewed-by: li yongxin liyongxin1@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- drivers/net/ethernet/hisilicon/hns/hns_enet.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_enet.c b/drivers/net/ethernet/hisilicon/hns/hns_enet.c index 65e91ecdf0235..b2a3ace652692 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_enet.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_enet.c @@ -11,6 +11,7 @@ #include <linux/io.h> #include <linux/ip.h> #include <linux/ipv6.h> +#include <linux/irq.h> #include <linux/marvell_phy.h> #include <linux/module.h> #include <linux/phy.h> @@ -1309,6 +1310,7 @@ static int hns_nic_init_irq(struct hns_nic_priv *priv)
rd->ring->ring_name[RCB_RING_NAME_LEN - 1] = '\0';
+ irq_set_status_flags(rd->ring->irq, IRQ_NOAUTOEN); ret = request_irq(rd->ring->irq, hns_irq_handle, 0, rd->ring->ring_name, rd); if (ret) { @@ -1316,7 +1318,6 @@ static int hns_nic_init_irq(struct hns_nic_priv *priv) rd->ring->irq); goto out_free_irq; } - disable_irq(rd->ring->irq);
cpu = hns_nic_init_affinity_mask(h->q_num, i, rd->ring, &rd->mask);
From: YueHaibing yuehaibing@huawei.com
mainline inclusion from mainline-5.10-rc1 commit 26613a9559b46aabccb8bd7469340be705cb54bd category: bugfix bugzilla: NA CVE: NA
---------------------------
There is no caller in tree.
Signed-off-by: YueHaibing yuehaibing@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Yonglong Liu liuyonglong@huawei.com Reviewed-by: li yongxin liyongxin1@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c | 2 -- 1 file changed, 2 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c b/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c index e94590ba4e7ab..2eedb420414d3 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c @@ -13,8 +13,6 @@ #include "hns_dsaf_ppe.h" #include "hns_dsaf_rcb.h"
-#define AE_NAME_PORT_ID_IDX 6 - static struct hns_mac_cb *hns_get_mac_cb(struct hnae_handle *handle) { struct hnae_vf_cb *vf_cb = hns_ae_get_vf_cb(handle);
From: Yonglong Liu liuyonglong@huawei.com
driver inclusion category: bugfix bugzilla: NA CVE: NA
-----------------------------
This patch update hns version to 21.2.1 and make driver version the same as module version.
Signed-off-by: Yonglong Liu liuyonglong@huawei.com Reviewed-by: li yongxin liyongxin1@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- drivers/net/ethernet/hisilicon/hns/hnae.c | 3 +-- drivers/net/ethernet/hisilicon/hns/hnae.h | 2 +- drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c | 2 +- drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h | 1 - drivers/net/ethernet/hisilicon/hns/hns_enet.c | 1 + drivers/net/ethernet/hisilicon/hns_mdio.c | 2 ++ 6 files changed, 6 insertions(+), 5 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns/hnae.c b/drivers/net/ethernet/hisilicon/hns/hnae.c index 7d58810c9da7f..8a2197e3fedbf 100644 --- a/drivers/net/ethernet/hisilicon/hns/hnae.c +++ b/drivers/net/ethernet/hisilicon/hns/hnae.c @@ -464,5 +464,4 @@ module_exit(hnae_exit); MODULE_AUTHOR("Hisilicon, Inc."); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Hisilicon Network Acceleration Engine Framework"); - -/* vi: set tw=78 noet: */ +MODULE_VERSION(HNAE_DRIVER_VERSION); diff --git a/drivers/net/ethernet/hisilicon/hns/hnae.h b/drivers/net/ethernet/hisilicon/hns/hnae.h index 5d947e35990e5..1e891c1d9d850 100644 --- a/drivers/net/ethernet/hisilicon/hns/hnae.h +++ b/drivers/net/ethernet/hisilicon/hns/hnae.h @@ -32,7 +32,7 @@ #include <linux/phy.h> #include <linux/types.h>
-#define HNAE_DRIVER_VERSION "2.0" +#define HNAE_DRIVER_VERSION "21.2.1" #define HNAE_DRIVER_NAME "hns" #define HNAE_COPYRIGHT "Copyright(c) 2015 Huawei Corporation." #define HNAE_DRIVER_STRING "Hisilicon Network Subsystem Driver" diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c index be3969dac627e..4bc2077a42cd3 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c @@ -3099,4 +3099,4 @@ EXPORT_SYMBOL(hns_dsaf_roce_reset); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Huawei Tech. Co., Ltd."); MODULE_DESCRIPTION("HNS DSAF driver"); -MODULE_VERSION(DSAF_MOD_VERSION); +MODULE_VERSION(HNAE_DRIVER_VERSION); diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h index cba04bfa0b3f8..a36bde780f8e6 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h @@ -13,7 +13,6 @@ struct hns_mac_cb;
#define DSAF_DRV_NAME "hns_dsaf" -#define DSAF_MOD_VERSION "v1.0" #define DSAF_DEVICE_NAME "dsaf"
#define HNS_DSAF_DEBUG_NW_REG_OFFSET 0x100000 diff --git a/drivers/net/ethernet/hisilicon/hns/hns_enet.c b/drivers/net/ethernet/hisilicon/hns/hns_enet.c index b2a3ace652692..f6bce7ec88065 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_enet.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_enet.c @@ -2546,3 +2546,4 @@ MODULE_DESCRIPTION("HISILICON HNS Ethernet driver"); MODULE_AUTHOR("Hisilicon, Inc."); MODULE_LICENSE("GPL"); MODULE_ALIAS("platform:hns-nic"); +MODULE_VERSION(HNAE_DRIVER_VERSION); diff --git a/drivers/net/ethernet/hisilicon/hns_mdio.c b/drivers/net/ethernet/hisilicon/hns_mdio.c index d60aefd011f6c..878f496311c88 100644 --- a/drivers/net/ethernet/hisilicon/hns_mdio.c +++ b/drivers/net/ethernet/hisilicon/hns_mdio.c @@ -22,6 +22,7 @@
#define MDIO_DRV_NAME "Hi-HNS_MDIO" #define MDIO_BUS_NAME "Hisilicon MII Bus" +#define MDIO_MOD_VERSION "21.2.1"
#define MDIO_TIMEOUT 1000000
@@ -574,3 +575,4 @@ MODULE_LICENSE("GPL"); MODULE_AUTHOR("Huawei Tech. Co., Ltd."); MODULE_DESCRIPTION("Hisilicon HNS MDIO driver"); MODULE_ALIAS("platform:" MDIO_DRV_NAME); +MODULE_VERSION(MDIO_MOD_VERSION);
From: Guangbin Huang huangguangbin2@huawei.com
driver inclusion category: feature bugzilla: NA CVE: NA
----------------------------
Previously, VF updates its link status every second by send query command to PF in periodic service task. If link stats of PF is changed, VF may need at most one second to update its link status.
To reduce delay of link status between PF and VFs, PF actively push its link status to VFs when its link status is updated. And to let VF know PF supports this new feature, the link status changed mailbox command
Signed-off-by: Guangbin Huang huangguangbin2@huawei.com Reviewed-by: li yongxin liyongxin1@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- .../net/ethernet/hisilicon/hns3/hclge_mbx.h | 3 ++ .../hisilicon/hns3/hns3pf/hclge_main.c | 36 ++++++++++++++++++- .../hisilicon/hns3/hns3pf/hclge_main.h | 1 + .../hisilicon/hns3/hns3pf/hclge_mbx.c | 14 ++++---- 4 files changed, 45 insertions(+), 9 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hclge_mbx.h b/drivers/net/ethernet/hisilicon/hns3/hclge_mbx.h index af3150ba15d56..f273a8c30d56e 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hclge_mbx.h +++ b/drivers/net/ethernet/hisilicon/hns3/hclge_mbx.h @@ -177,4 +177,7 @@ struct hclgevf_mbx_arq_ring { (arq.tail = (arq.tail + 1) % HCLGE_MBX_MAX_ARQ_MSG_NUM) #define hclge_mbx_head_ptr_move_arq(arq) \ (arq.head = (arq.head + 1) % HCLGE_MBX_MAX_ARQ_MSG_NUM) + +/* PF immediately push link status to VFs when link status changed */ +#define HCLGE_MBX_PUSH_LINK_STATUS_EN BIT(0) #endif diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index 7b6d7c157747e..635f72af3e4df 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -2754,6 +2754,28 @@ static int hclge_get_mac_phy_link(struct hclge_dev *hdev, int *link_status) return hclge_get_mac_link_status(hdev, link_status); }
+static void hclge_push_link_status(struct hclge_dev *hdev) +{ + struct hclge_vport *vport; + int ret; + u16 i; + + for (i = 0; i < pci_num_vf(hdev->pdev); i++) { + vport = &hdev->vport[i + HCLGE_VF_VPORT_START_NUM]; + + if (!test_bit(HCLGE_VPORT_STATE_ALIVE, &vport->state) || + vport->vf_info.link_state != IFLA_VF_LINK_STATE_AUTO) + continue; + + ret = hclge_push_vf_link_status(vport); + if (ret) { + dev_err(&hdev->pdev->dev, + "failed to push link status to vf%u, ret=%d\n", + i, ret); + } + } +} + static void hclge_update_link_status(struct hclge_dev *hdev) { struct hnae3_client *rclient = hdev->roce_client; @@ -2787,6 +2809,8 @@ static void hclge_update_link_status(struct hclge_dev *hdev) rclient->ops->link_status_change(rhandle, state); } + + hclge_push_link_status(hdev); }
clear_bit(HCLGE_STATE_LINK_UPDATING, &hdev->state); @@ -2989,14 +3013,24 @@ static int hclge_set_vf_link_state(struct hnae3_handle *handle, int vf, { struct hclge_vport *vport = hclge_get_vport(handle); struct hclge_dev *hdev = vport->back; + int link_state_old; + int ret;
vport = hclge_get_vf_vport(hdev, vf); if (!vport) return -EINVAL;
+ link_state_old = vport->vf_info.link_state; vport->vf_info.link_state = link_state;
- return 0; + ret = hclge_push_vf_link_status(vport); + if (ret) { + vport->vf_info.link_state = link_state_old; + dev_err(&hdev->pdev->dev, + "failed to push vf%d link status, ret = %d\n", vf, ret); + } + + return ret; }
static u32 hclge_check_event_cause(struct hclge_dev *hdev, u32 *clearval) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h index 6b9ca5a5c48b7..b84c2bdbdb3b2 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h @@ -1054,4 +1054,5 @@ void hclge_report_hw_error(struct hclge_dev *hdev, void hclge_inform_vf_promisc_info(struct hclge_vport *vport); void hclge_dbg_dump_rst_info(struct hclge_dev *hdev); bool hclge_vf_vlan_need_enable(struct hclge_vport *vport); +int hclge_push_vf_link_status(struct hclge_vport *vport); #endif diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c index 730838715a928..ae1039f262478 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c @@ -553,16 +553,14 @@ static void hclge_get_vf_media_type(struct hclge_vport *vport, resp_msg->len = HCLGE_VF_MEDIA_TYPE_LENGTH; }
-static int hclge_get_link_info(struct hclge_vport *vport, - struct hclge_mbx_vf_to_pf_cmd *mbx_req) +int hclge_push_vf_link_status(struct hclge_vport *vport) { #define HCLGE_VF_LINK_STATE_UP 1U #define HCLGE_VF_LINK_STATE_DOWN 0U
struct hclge_dev *hdev = vport->back; u16 link_status; - u8 msg_data[8]; - u8 dest_vfid; + u8 msg_data[9]; u16 duplex;
/* mac.link can only be 0 or 1 */ @@ -583,11 +581,11 @@ static int hclge_get_link_info(struct hclge_vport *vport, memcpy(&msg_data[0], &link_status, sizeof(u16)); memcpy(&msg_data[2], &hdev->hw.mac.speed, sizeof(u32)); memcpy(&msg_data[6], &duplex, sizeof(u16)); - dest_vfid = mbx_req->mbx_src_vfid; + msg_data[8] = HCLGE_MBX_PUSH_LINK_STATUS_EN;
/* send this requested info to VF */ return hclge_send_mbx_msg(vport, msg_data, sizeof(msg_data), - HCLGE_MBX_LINK_STAT_CHANGE, dest_vfid); + HCLGE_MBX_LINK_STAT_CHANGE, vport->vport_id); }
static void hclge_get_link_mode(struct hclge_vport *vport, @@ -880,10 +878,10 @@ void hclge_mbx_handler(struct hclge_dev *hdev) hclge_get_vf_tcinfo(vport, &resp_msg); break; case HCLGE_MBX_GET_LINK_STATUS: - ret = hclge_get_link_info(vport, req); + ret = hclge_push_vf_link_status(vport); if (ret) dev_err(&hdev->pdev->dev, - "PF fail(%d) to get link stat for VF\n", + "failed to inform link stat to VF, ret = %d\n", ret); break; case HCLGE_MBX_QUEUE_RESET:
From: Ding Hui dinghui@sangfor.com.cn
driver inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I3BNT6 CVE: NA
-----------------------------------------------
We can get a crash when disconnecting the iSCSI session, the call trace like this:
[ffff00002a00fb70] kfree at ffff00000830e224 [ffff00002a00fba0] ses_intf_remove at ffff000001f200e4 [ffff00002a00fbd0] device_del at ffff0000086b6a98 [ffff00002a00fc50] device_unregister at ffff0000086b6d58 [ffff00002a00fc70] __scsi_remove_device at ffff00000870608c [ffff00002a00fca0] scsi_remove_device at ffff000008706134 [ffff00002a00fcc0] __scsi_remove_target at ffff0000087062e4 [ffff00002a00fd10] scsi_remove_target at ffff0000087064c0 [ffff00002a00fd70] __iscsi_unbind_session at ffff000001c872c4 [ffff00002a00fdb0] process_one_work at ffff00000810f35c [ffff00002a00fe00] worker_thread at ffff00000810f648 [ffff00002a00fe70] kthread at ffff000008116e98
In ses_intf_add, components count could be 0, and kcalloc 0 size scomp, but not saved in edev->component[i].scratch
In this situation, edev->component[0].scratch is an invalid pointer, when kfree it in ses_intf_remove_enclosure, a crash like above would happen The call trace also could be other random cases when kfree cannot catch the invalid pointer
We should not use edev->component[] array when the components count is 0 We also need check index when use edev->component[] array in ses_enclosure_data_process
Another fix option is report error and do not attach in ses_intf_add if we meet a zero component enclosure
Tested-by: Zeng Zhicong timmyzeng@163.com Signed-off-by: Ding Hui dinghui@sangfor.com.cn Reviewed-by: Jason Yan yanaijie@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- drivers/scsi/ses.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-)
diff --git a/drivers/scsi/ses.c b/drivers/scsi/ses.c index 0fc39224ce1e4..63764fe0b34f5 100644 --- a/drivers/scsi/ses.c +++ b/drivers/scsi/ses.c @@ -493,9 +493,6 @@ static int ses_enclosure_find_by_addr(struct enclosure_device *edev, int i; struct ses_component *scomp;
- if (!edev->component[0].scratch) - return 0; - for (i = 0; i < edev->components; i++) { scomp = edev->component[i].scratch; if (scomp->addr != efd->addr) @@ -581,8 +578,10 @@ static void ses_enclosure_data_process(struct enclosure_device *edev, components++, type_ptr[0], name); - else + else if (components < edev->components) ecomp = &edev->component[components++]; + else + ecomp = ERR_PTR(-EINVAL);
if (!IS_ERR(ecomp)) { if (addl_desc_ptr) @@ -747,9 +746,11 @@ static int ses_intf_add(struct device *cdev, buf = NULL; } page2_not_supported: - scomp = kcalloc(components, sizeof(struct ses_component), GFP_KERNEL); - if (!scomp) - goto err_free; + if (components > 0) { + scomp = kcalloc(components, sizeof(struct ses_component), GFP_KERNEL); + if (!scomp) + goto err_free; + }
edev = enclosure_register(cdev->parent, dev_name(&sdev->sdev_gendev), components, &ses_enclosure_callbacks); @@ -829,7 +830,8 @@ static void ses_intf_remove_enclosure(struct scsi_device *sdev) kfree(ses_dev->page2); kfree(ses_dev);
- kfree(edev->component[0].scratch); + if (edev->components > 0) + kfree(edev->component[0].scratch);
put_device(&edev->edev); enclosure_unregister(edev);
From: Guoqing Jiang guoqing.jiang@cloud.ionos.com
mainline inclusion from mainline-5.8-rc1 commit cc1ffe61c026e2318024bfa8722e8f689fd2a7f4 category: bugfix bugzilla: 35792 CVE: NA
---------------------------
Since the purpose of call flush_workqueue in new_dev_store is to ensure md_delayed_delete() has completed, so we should check rdev->del_work is pending or not.
To suppress lockdep warning, we have to check mddev->del_work while md_delayed_delete is attached to rdev->del_work, so it is not aligned to the purpose of flush workquee. So a new workqueue is needed to avoid the awkward situation, and introduce a new func flush_rdev_wq to flush the new workqueue after check if there was pending work.
Also like new_dev_store, ADD_NEW_DISK ioctl has the same purpose to flush workqueue while it holds bdev->bd_mutex, so make the same change applies to the ioctl to avoid similar lock issue.
And md_delayed_delete actually wants to delete rdev, so rename the function to rdev_delayed_delete.
Signed-off-by: Guoqing Jiang guoqing.jiang@cloud.ionos.com Signed-off-by: Song Liu songliubraving@fb.com Signed-off-by: Yu Kuai yukuai3@huawei.com Reviewed-by: Yufen Yu yuyufen@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- drivers/md/md.c | 37 +++++++++++++++++++++++++++++-------- 1 file changed, 29 insertions(+), 8 deletions(-)
diff --git a/drivers/md/md.c b/drivers/md/md.c index fb97c0b1d510c..7fdf309bf0ea4 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -94,6 +94,7 @@ EXPORT_SYMBOL(md_cluster_mod); static DECLARE_WAIT_QUEUE_HEAD(resync_wait); static struct workqueue_struct *md_wq; static struct workqueue_struct *md_misc_wq; +static struct workqueue_struct *md_rdev_misc_wq;
static int remove_and_add_spares(struct mddev *mddev, struct md_rdev *this); @@ -2301,7 +2302,7 @@ static int bind_rdev_to_array(struct md_rdev *rdev, struct mddev *mddev) return err; }
-static void md_delayed_delete(struct work_struct *ws) +static void rdev_delayed_delete(struct work_struct *ws) { struct md_rdev *rdev = container_of(ws, struct md_rdev, del_work); kobject_del(&rdev->kobj); @@ -2325,9 +2326,9 @@ static void unbind_rdev_from_array(struct md_rdev *rdev) * to delay it due to rcu usage. */ synchronize_rcu(); - INIT_WORK(&rdev->del_work, md_delayed_delete); + INIT_WORK(&rdev->del_work, rdev_delayed_delete); kobject_get(&rdev->kobj); - queue_work(md_misc_wq, &rdev->del_work); + queue_work(md_rdev_misc_wq, &rdev->del_work); }
/* @@ -4353,6 +4354,20 @@ null_show(struct mddev *mddev, char *page) return -EINVAL; }
+/* need to ensure rdev_delayed_delete() has completed */ +static void flush_rdev_wq(struct mddev *mddev) +{ + struct md_rdev *rdev; + + rcu_read_lock(); + rdev_for_each_rcu(rdev, mddev) + if (work_pending(&rdev->del_work)) { + flush_workqueue(md_rdev_misc_wq); + break; + } + rcu_read_unlock(); +} + static ssize_t new_dev_store(struct mddev *mddev, const char *buf, size_t len) { @@ -4380,8 +4395,7 @@ new_dev_store(struct mddev *mddev, const char *buf, size_t len) minor != MINOR(dev)) return -EOVERFLOW;
- flush_workqueue(md_misc_wq); - + flush_rdev_wq(mddev); err = mddev_lock(mddev); if (err) return err; @@ -4619,7 +4633,8 @@ action_store(struct mddev *mddev, const char *page, size_t len) clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery); if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery) && mddev_lock(mddev) == 0) { - flush_workqueue(md_misc_wq); + if (work_pending(&mddev->del_work)) + flush_workqueue(md_misc_wq); if (mddev->sync_thread) { set_bit(MD_RECOVERY_INTR, &mddev->recovery); md_reap_sync_thread(mddev); @@ -7237,8 +7252,7 @@ static int md_ioctl(struct block_device *bdev, fmode_t mode, }
if (cmd == ADD_NEW_DISK) - /* need to ensure md_delayed_delete() has completed */ - flush_workqueue(md_misc_wq); + flush_rdev_wq(mddev);
if (cmd == HOT_REMOVE_DISK) /* need to ensure recovery thread has run */ @@ -9193,6 +9207,10 @@ static int __init md_init(void) if (!md_misc_wq) goto err_misc_wq;
+ md_rdev_misc_wq = alloc_workqueue("md_rdev_misc", 0, 0); + if (!md_misc_wq) + goto err_rdev_misc_wq; + if ((ret = register_blkdev(MD_MAJOR, "md")) < 0) goto err_md;
@@ -9214,6 +9232,8 @@ static int __init md_init(void) err_mdp: unregister_blkdev(MD_MAJOR, "md"); err_md: + destroy_workqueue(md_rdev_misc_wq); +err_rdev_misc_wq: destroy_workqueue(md_misc_wq); err_misc_wq: destroy_workqueue(md_wq); @@ -9476,6 +9496,7 @@ static __exit void md_exit(void) * destroy_workqueue() below will wait for that to complete. */ } + destroy_workqueue(md_rdev_misc_wq); destroy_workqueue(md_misc_wq); destroy_workqueue(md_wq); }
From: Guoqing Jiang guoqing.jiang@cloud.ionos.com
mainline inclusion from mainline-5.8-rc1 commit 78b990cf2822d1150a419c13be48e74aefa83f27 category: bugfix bugzilla: 35792 CVE: NA
---------------------------
Since rdev->kobj is removed asynchronously, it is possible that the rdev->kobj still exists when try to add the rdev again after rdev is removed. But this path md_ioctl (HOT_ADD_DISK) -> hot_add_disk -> bind_rdev_to_array missed it.
Signed-off-by: Guoqing Jiang guoqing.jiang@cloud.ionos.com Signed-off-by: Song Liu songliubraving@fb.com Signed-off-by: Yu Kuai yukuai3@huawei.com Reviewed-by: Yufen Yu yuyufen@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- drivers/md/md.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/md/md.c b/drivers/md/md.c index 7fdf309bf0ea4..767a7af084161 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -7251,7 +7251,7 @@ static int md_ioctl(struct block_device *bdev, fmode_t mode,
}
- if (cmd == ADD_NEW_DISK) + if (cmd == ADD_NEW_DISK || cmd == HOT_ADD_DISK) flush_rdev_wq(mddev);
if (cmd == HOT_REMOVE_DISK)
From: Guoqing Jiang guoqing.jiang@cloud.ionos.com
mainline inclusion from mainline-5.10-rc1 commit cf0b9b4821a2955f8a23813ef8f422208ced9bd7 category: bugfix bugzilla: 35792 CVE: NA
---------------------------
It should check md_rdev_misc_wq instead of md_misc_wq.
Fixes: cc1ffe61c026 ("md: add new workqueue for delete rdev") Cc: stable@vger.kernel.org # v5.8+ Signed-off-by: Guoqing Jiang guoqing.jiang@cloud.ionos.com Signed-off-by: Song Liu songliubraving@fb.com Signed-off-by: Yu Kuai yukuai3@huawei.com Reviewed-by: Yufen Yu yuyufen@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- drivers/md/md.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/md/md.c b/drivers/md/md.c index 767a7af084161..90835be93d289 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -9208,7 +9208,7 @@ static int __init md_init(void) goto err_misc_wq;
md_rdev_misc_wq = alloc_workqueue("md_rdev_misc", 0, 0); - if (!md_misc_wq) + if (!md_rdev_misc_wq) goto err_rdev_misc_wq;
if ((ret = register_blkdev(MD_MAJOR, "md")) < 0)
From: Junxiao Bi junxiao.bi@oracle.com
mainline inclusion from mainline-5.9-rc1 commit e1a86dbbbd6a77f73c3d099030495fa31f181e2f category: bugfix bugzilla: 41594 CVE: NA
---------------------------
The following deadlock was captured. The first process is holding 'kernfs_mutex' and hung by io. The io was staging in 'r1conf.pending_bio_list' of raid1 device, this pending bio list would be flushed by second process 'md127_raid1', but it was hung by 'kernfs_mutex'. Using sysfs_notify_dirent_safe() to replace sysfs_notify() can fix it. There were other sysfs_notify() invoked from io path, removed all of them.
PID: 40430 TASK: ffff8ee9c8c65c40 CPU: 29 COMMAND: "probe_file" #0 [ffffb87c4df37260] __schedule at ffffffff9a8678ec #1 [ffffb87c4df372f8] schedule at ffffffff9a867f06 #2 [ffffb87c4df37310] io_schedule at ffffffff9a0c73e6 #3 [ffffb87c4df37328] __dta___xfs_iunpin_wait_3443 at ffffffffc03a4057 [xfs] #4 [ffffb87c4df373a0] xfs_iunpin_wait at ffffffffc03a6c79 [xfs] #5 [ffffb87c4df373b0] __dta_xfs_reclaim_inode_3357 at ffffffffc039a46c [xfs] #6 [ffffb87c4df37400] xfs_reclaim_inodes_ag at ffffffffc039a8b6 [xfs] #7 [ffffb87c4df37590] xfs_reclaim_inodes_nr at ffffffffc039bb33 [xfs] #8 [ffffb87c4df375b0] xfs_fs_free_cached_objects at ffffffffc03af0e9 [xfs] #9 [ffffb87c4df375c0] super_cache_scan at ffffffff9a287ec7 #10 [ffffb87c4df37618] shrink_slab at ffffffff9a1efd93 #11 [ffffb87c4df37700] shrink_node at ffffffff9a1f5968 #12 [ffffb87c4df37788] do_try_to_free_pages at ffffffff9a1f5ea2 #13 [ffffb87c4df377f0] try_to_free_mem_cgroup_pages at ffffffff9a1f6445 #14 [ffffb87c4df37880] try_charge at ffffffff9a26cc5f #15 [ffffb87c4df37920] memcg_kmem_charge_memcg at ffffffff9a270f6a #16 [ffffb87c4df37958] new_slab at ffffffff9a251430 #17 [ffffb87c4df379c0] ___slab_alloc at ffffffff9a251c85 #18 [ffffb87c4df37a80] __slab_alloc at ffffffff9a25635d #19 [ffffb87c4df37ac0] kmem_cache_alloc at ffffffff9a251f89 #20 [ffffb87c4df37b00] alloc_inode at ffffffff9a2a2b10 #21 [ffffb87c4df37b20] iget_locked at ffffffff9a2a4854 #22 [ffffb87c4df37b60] kernfs_get_inode at ffffffff9a311377 #23 [ffffb87c4df37b80] kernfs_iop_lookup at ffffffff9a311e2b #24 [ffffb87c4df37ba8] lookup_slow at ffffffff9a290118 #25 [ffffb87c4df37c10] walk_component at ffffffff9a291e83 #26 [ffffb87c4df37c78] path_lookupat at ffffffff9a293619 #27 [ffffb87c4df37cd8] filename_lookup at ffffffff9a2953af #28 [ffffb87c4df37de8] user_path_at_empty at ffffffff9a295566 #29 [ffffb87c4df37e10] vfs_statx at ffffffff9a289787 #30 [ffffb87c4df37e70] SYSC_newlstat at ffffffff9a289d5d #31 [ffffb87c4df37f18] sys_newlstat at ffffffff9a28a60e #32 [ffffb87c4df37f28] do_syscall_64 at ffffffff9a003949 #33 [ffffb87c4df37f50] entry_SYSCALL_64_after_hwframe at ffffffff9aa001ad RIP: 00007f617a5f2905 RSP: 00007f607334f838 RFLAGS: 00000246 RAX: ffffffffffffffda RBX: 00007f6064044b20 RCX: 00007f617a5f2905 RDX: 00007f6064044b20 RSI: 00007f6064044b20 RDI: 00007f6064005890 RBP: 00007f6064044aa0 R8: 0000000000000030 R9: 000000000000011c R10: 0000000000000013 R11: 0000000000000246 R12: 00007f606417e6d0 R13: 00007f6064044aa0 R14: 00007f6064044b10 R15: 00000000ffffffff ORIG_RAX: 0000000000000006 CS: 0033 SS: 002b
PID: 927 TASK: ffff8f15ac5dbd80 CPU: 42 COMMAND: "md127_raid1" #0 [ffffb87c4df07b28] __schedule at ffffffff9a8678ec #1 [ffffb87c4df07bc0] schedule at ffffffff9a867f06 #2 [ffffb87c4df07bd8] schedule_preempt_disabled at ffffffff9a86825e #3 [ffffb87c4df07be8] __mutex_lock at ffffffff9a869bcc #4 [ffffb87c4df07ca0] __mutex_lock_slowpath at ffffffff9a86a013 #5 [ffffb87c4df07cb0] mutex_lock at ffffffff9a86a04f #6 [ffffb87c4df07cc8] kernfs_find_and_get_ns at ffffffff9a311d83 #7 [ffffb87c4df07cf0] sysfs_notify at ffffffff9a314b3a #8 [ffffb87c4df07d18] md_update_sb at ffffffff9a688696 #9 [ffffb87c4df07d98] md_update_sb at ffffffff9a6886d5 #10 [ffffb87c4df07da8] md_check_recovery at ffffffff9a68ad9c #11 [ffffb87c4df07dd0] raid1d at ffffffffc01f0375 [raid1] #12 [ffffb87c4df07ea0] md_thread at ffffffff9a680348 #13 [ffffb87c4df07f08] kthread at ffffffff9a0b8005 #14 [ffffb87c4df07f50] ret_from_fork at ffffffff9aa00344
Signed-off-by: Junxiao Bi junxiao.bi@oracle.com Signed-off-by: Song Liu songliubraving@fb.com Signed-off-by: Yu Kuai yukuai3@huawei.com Reviewed-by: Yufen Yu yuyufen@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- drivers/md/md-bitmap.c | 2 +- drivers/md/md.c | 44 ++++++++++++++++++++++++++++-------------- drivers/md/md.h | 8 +++++++- drivers/md/raid10.c | 2 +- drivers/md/raid5.c | 6 +++--- 5 files changed, 42 insertions(+), 20 deletions(-)
diff --git a/drivers/md/md-bitmap.c b/drivers/md/md-bitmap.c index 382e231f8e8f6..a5534fa405cd1 100644 --- a/drivers/md/md-bitmap.c +++ b/drivers/md/md-bitmap.c @@ -1635,7 +1635,7 @@ void md_bitmap_cond_end_sync(struct bitmap *bitmap, sector_t sector, bool force) s += blocks; } bitmap->last_end_sync = jiffies; - sysfs_notify(&bitmap->mddev->kobj, NULL, "sync_completed"); + sysfs_notify_dirent_safe(bitmap->mddev->sysfs_completed); } EXPORT_SYMBOL(md_bitmap_cond_end_sync);
diff --git a/drivers/md/md.c b/drivers/md/md.c index 90835be93d289..2062390782f14 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -2287,6 +2287,10 @@ static int bind_rdev_to_array(struct md_rdev *rdev, struct mddev *mddev) if (sysfs_create_link(&rdev->kobj, ko, "block")) /* failure here is OK */; rdev->sysfs_state = sysfs_get_dirent_safe(rdev->kobj.sd, "state"); + rdev->sysfs_unack_badblocks = + sysfs_get_dirent_safe(rdev->kobj.sd, "unacknowledged_bad_blocks"); + rdev->sysfs_badblocks = + sysfs_get_dirent_safe(rdev->kobj.sd, "bad_blocks");
list_add_rcu(&rdev->same_set, &mddev->disks); bd_link_disk_holder(rdev->bdev, mddev->gendisk); @@ -2319,7 +2323,11 @@ static void unbind_rdev_from_array(struct md_rdev *rdev) rdev->mddev = NULL; sysfs_remove_link(&rdev->kobj, "block"); sysfs_put(rdev->sysfs_state); + sysfs_put(rdev->sysfs_unack_badblocks); + sysfs_put(rdev->sysfs_badblocks); rdev->sysfs_state = NULL; + rdev->sysfs_unack_badblocks = NULL; + rdev->sysfs_badblocks = NULL; rdev->badblocks.count = 0; /* We need to delay this, otherwise we can deadlock when * writing to 'remove' to "dev/state". We also need @@ -2664,7 +2672,7 @@ void md_update_sb(struct mddev *mddev, int force_change) goto repeat; wake_up(&mddev->sb_wait); if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery)) - sysfs_notify(&mddev->kobj, NULL, "sync_completed"); + sysfs_notify_dirent_safe(mddev->sysfs_completed);
rdev_for_each(rdev, mddev) { if (test_and_clear_bit(FaultRecorded, &rdev->flags)) @@ -3920,7 +3928,7 @@ level_store(struct mddev *mddev, const char *buf, size_t len) mddev_resume(mddev); if (!mddev->thread) md_update_sb(mddev, 1); - sysfs_notify(&mddev->kobj, NULL, "level"); + sysfs_notify_dirent_safe(mddev->sysfs_level); md_new_event(mddev); rv = len; out_unlock: @@ -4664,7 +4672,7 @@ action_store(struct mddev *mddev, const char *page, size_t len) } if (err) return err; - sysfs_notify(&mddev->kobj, NULL, "degraded"); + sysfs_notify_dirent_safe(mddev->sysfs_degraded); } else { if (cmd_match(page, "check")) set_bit(MD_RECOVERY_CHECK, &mddev->recovery); @@ -5289,6 +5297,13 @@ static void md_free(struct kobject *ko)
if (mddev->sysfs_state) sysfs_put(mddev->sysfs_state); + if (mddev->sysfs_completed) + sysfs_put(mddev->sysfs_completed); + if (mddev->sysfs_degraded) + sysfs_put(mddev->sysfs_degraded); + if (mddev->sysfs_level) + sysfs_put(mddev->sysfs_level); +
if (mddev->gendisk) del_gendisk(mddev->gendisk); @@ -5451,6 +5466,9 @@ static int md_alloc(dev_t dev, char *name) if (!error && mddev->kobj.sd) { kobject_uevent(&mddev->kobj, KOBJ_ADD); mddev->sysfs_state = sysfs_get_dirent_safe(mddev->kobj.sd, "array_state"); + mddev->sysfs_completed = sysfs_get_dirent_safe(mddev->kobj.sd, "sync_completed"); + mddev->sysfs_degraded = sysfs_get_dirent_safe(mddev->kobj.sd, "degraded"); + mddev->sysfs_level = sysfs_get_dirent_safe(mddev->kobj.sd, "level"); } mddev_put(mddev); return error; @@ -5786,7 +5804,7 @@ static int do_md_run(struct mddev *mddev) kobject_uevent(&disk_to_dev(mddev->gendisk)->kobj, KOBJ_CHANGE); sysfs_notify_dirent_safe(mddev->sysfs_state); sysfs_notify_dirent_safe(mddev->sysfs_action); - sysfs_notify(&mddev->kobj, NULL, "degraded"); + sysfs_notify_dirent_safe(mddev->sysfs_degraded); out: clear_bit(MD_NOT_READY, &mddev->flags); return err; @@ -8501,7 +8519,7 @@ void md_do_sync(struct md_thread *thread) } else mddev->curr_resync = 3; /* no longer delayed */ mddev->curr_resync_completed = j; - sysfs_notify(&mddev->kobj, NULL, "sync_completed"); + sysfs_notify_dirent_safe(mddev->sysfs_completed); md_new_event(mddev); update_time = jiffies;
@@ -8529,7 +8547,7 @@ void md_do_sync(struct md_thread *thread) mddev->recovery_cp = j; update_time = jiffies; set_bit(MD_SB_CHANGE_CLEAN, &mddev->sb_flags); - sysfs_notify(&mddev->kobj, NULL, "sync_completed"); + sysfs_notify_dirent_safe(mddev->sysfs_completed); }
while (j >= mddev->resync_max && @@ -8636,7 +8654,7 @@ void md_do_sync(struct md_thread *thread) !test_bit(MD_RECOVERY_INTR, &mddev->recovery) && mddev->curr_resync > 3) { mddev->curr_resync_completed = mddev->curr_resync; - sysfs_notify(&mddev->kobj, NULL, "sync_completed"); + sysfs_notify_dirent_safe(mddev->sysfs_completed); } mddev->pers->sync_request(mddev, max_sectors, &skipped);
@@ -8764,7 +8782,7 @@ static int remove_and_add_spares(struct mddev *mddev, }
if (removed && mddev->kobj.sd) - sysfs_notify(&mddev->kobj, NULL, "degraded"); + sysfs_notify_dirent_safe(mddev->sysfs_degraded);
if (this && removed) goto no_add; @@ -9046,8 +9064,7 @@ void md_reap_sync_thread(struct mddev *mddev) /* success...*/ /* activate any spares */ if (mddev->pers->spare_active(mddev)) { - sysfs_notify(&mddev->kobj, NULL, - "degraded"); + sysfs_notify_dirent_safe(mddev->sysfs_degraded); set_bit(MD_SB_CHANGE_DEVS, &mddev->sb_flags); } } @@ -9126,8 +9143,7 @@ int rdev_set_badblocks(struct md_rdev *rdev, sector_t s, int sectors, if (rv == 0) { /* Make sure they get written out promptly */ if (test_bit(ExternalBbl, &rdev->flags)) - sysfs_notify(&rdev->kobj, NULL, - "unacknowledged_bad_blocks"); + sysfs_notify_dirent_safe(rdev->sysfs_unack_badblocks); sysfs_notify_dirent_safe(rdev->sysfs_state); set_mask_bits(&mddev->sb_flags, 0, BIT(MD_SB_CHANGE_CLEAN) | BIT(MD_SB_CHANGE_PENDING)); @@ -9148,7 +9164,7 @@ int rdev_clear_badblocks(struct md_rdev *rdev, sector_t s, int sectors, s += rdev->data_offset; rv = badblocks_clear(&rdev->badblocks, s, sectors); if ((rv == 0) && test_bit(ExternalBbl, &rdev->flags)) - sysfs_notify(&rdev->kobj, NULL, "bad_blocks"); + sysfs_notify_dirent_safe(rdev->sysfs_badblocks); return rv; } EXPORT_SYMBOL_GPL(rdev_clear_badblocks); @@ -9354,7 +9370,7 @@ static int read_rdev(struct mddev *mddev, struct md_rdev *rdev) if (rdev->recovery_offset == MaxSector && !test_bit(In_sync, &rdev->flags) && mddev->pers->spare_active(mddev)) - sysfs_notify(&mddev->kobj, NULL, "degraded"); + sysfs_notify_dirent_safe(mddev->sysfs_degraded);
put_page(swapout); return 0; diff --git a/drivers/md/md.h b/drivers/md/md.h index f1b1881d804eb..ee3c9768ff9e7 100644 --- a/drivers/md/md.h +++ b/drivers/md/md.h @@ -120,7 +120,10 @@ struct md_rdev {
struct kernfs_node *sysfs_state; /* handle for 'state' * sysfs entry */ - + /* handle for 'unacknowledged_bad_blocks' sysfs dentry */ + struct kernfs_node *sysfs_unack_badblocks; + /* handle for 'bad_blocks' sysfs dentry */ + struct kernfs_node *sysfs_badblocks; struct badblocks badblocks;
struct { @@ -402,6 +405,9 @@ struct mddev { * file in sysfs. */ struct kernfs_node *sysfs_action; /* handle for 'sync_action' */ + struct kernfs_node *sysfs_completed; /*handle for 'sync_completed' */ + struct kernfs_node *sysfs_degraded; /*handle for 'degraded' */ + struct kernfs_node *sysfs_level; /*handle for 'level' */
struct work_struct del_work; /* used for delayed sysfs removal */
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index db47579f3b0d4..37b4b2fc4af9f 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -4458,7 +4458,7 @@ static sector_t reshape_request(struct mddev *mddev, sector_t sector_nr, sector_nr = conf->reshape_progress; if (sector_nr) { mddev->curr_resync_completed = sector_nr; - sysfs_notify(&mddev->kobj, NULL, "sync_completed"); + sysfs_notify_dirent_safe(mddev->sysfs_completed); *skipped = 1; return sector_nr; } diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index c7bda4b0bcedf..2d63668cfadda 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -5791,7 +5791,7 @@ static sector_t reshape_request(struct mddev *mddev, sector_t sector_nr, int *sk sector_div(sector_nr, new_data_disks); if (sector_nr) { mddev->curr_resync_completed = sector_nr; - sysfs_notify(&mddev->kobj, NULL, "sync_completed"); + sysfs_notify_dirent_safe(mddev->sysfs_completed); *skipped = 1; retn = sector_nr; goto finish; @@ -5905,7 +5905,7 @@ static sector_t reshape_request(struct mddev *mddev, sector_t sector_nr, int *sk conf->reshape_safe = mddev->reshape_position; spin_unlock_irq(&conf->device_lock); wake_up(&conf->wait_for_overlap); - sysfs_notify(&mddev->kobj, NULL, "sync_completed"); + sysfs_notify_dirent_safe(mddev->sysfs_completed); }
INIT_LIST_HEAD(&stripes); @@ -6012,7 +6012,7 @@ static sector_t reshape_request(struct mddev *mddev, sector_t sector_nr, int *sk conf->reshape_safe = mddev->reshape_position; spin_unlock_irq(&conf->device_lock); wake_up(&conf->wait_for_overlap); - sysfs_notify(&mddev->kobj, NULL, "sync_completed"); + sysfs_notify_dirent_safe(mddev->sysfs_completed); } ret: return retn;
From: Junxiao Bi junxiao.bi@oracle.com
mainline inclusion from mainline-5.9-rc1 commit e8efa9b88e3c20a20ff34bb33e2e94bf6896016a category: bugfix bugzilla: 41594 CVE: NA
---------------------------
"sync_completed" and "degraded" belongs to redundancy attr group, it was not exist yet when md device was created.
Reported-by: kernel test robot rong.a.chen@intel.com Fixes: e1a86dbbbd6a ("md: fix deadlock causing by sysfs_notify") Signed-off-by: Junxiao Bi junxiao.bi@oracle.com Signed-off-by: Song Liu songliubraving@fb.com Signed-off-by: Yu Kuai yukuai3@huawei.com Reviewed-by: Yufen Yu yuyufen@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- drivers/md/md.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-)
diff --git a/drivers/md/md.c b/drivers/md/md.c index 2062390782f14..268ef4fe70db1 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -688,7 +688,13 @@ void mddev_unlock(struct mddev *mddev) sysfs_remove_group(&mddev->kobj, &md_redundancy_group); if (mddev->sysfs_action) sysfs_put(mddev->sysfs_action); + if (mddev->sysfs_completed) + sysfs_put(mddev->sysfs_completed); + if (mddev->sysfs_degraded) + sysfs_put(mddev->sysfs_degraded); mddev->sysfs_action = NULL; + mddev->sysfs_completed = NULL; + mddev->sysfs_degraded = NULL; } } mddev->sysfs_active = 0; @@ -3881,6 +3887,8 @@ level_store(struct mddev *mddev, const char *buf, size_t len) pr_warn("md: cannot register extra attributes for %s\n", mdname(mddev)); mddev->sysfs_action = sysfs_get_dirent(mddev->kobj.sd, "sync_action"); + mddev->sysfs_completed = sysfs_get_dirent_safe(mddev->kobj.sd, "sync_completed"); + mddev->sysfs_degraded = sysfs_get_dirent_safe(mddev->kobj.sd, "degraded"); } if (oldpers->sync_request != NULL && pers->sync_request == NULL) { @@ -5297,14 +5305,9 @@ static void md_free(struct kobject *ko)
if (mddev->sysfs_state) sysfs_put(mddev->sysfs_state); - if (mddev->sysfs_completed) - sysfs_put(mddev->sysfs_completed); - if (mddev->sysfs_degraded) - sysfs_put(mddev->sysfs_degraded); if (mddev->sysfs_level) sysfs_put(mddev->sysfs_level);
- if (mddev->gendisk) del_gendisk(mddev->gendisk); if (mddev->queue) @@ -5466,8 +5469,6 @@ static int md_alloc(dev_t dev, char *name) if (!error && mddev->kobj.sd) { kobject_uevent(&mddev->kobj, KOBJ_ADD); mddev->sysfs_state = sysfs_get_dirent_safe(mddev->kobj.sd, "array_state"); - mddev->sysfs_completed = sysfs_get_dirent_safe(mddev->kobj.sd, "sync_completed"); - mddev->sysfs_degraded = sysfs_get_dirent_safe(mddev->kobj.sd, "degraded"); mddev->sysfs_level = sysfs_get_dirent_safe(mddev->kobj.sd, "level"); } mddev_put(mddev); @@ -5734,6 +5735,8 @@ int md_run(struct mddev *mddev) pr_warn("md: cannot register extra attributes for %s\n", mdname(mddev)); mddev->sysfs_action = sysfs_get_dirent_safe(mddev->kobj.sd, "sync_action"); + mddev->sysfs_completed = sysfs_get_dirent_safe(mddev->kobj.sd, "sync_completed"); + mddev->sysfs_degraded = sysfs_get_dirent_safe(mddev->kobj.sd, "degraded"); } else if (mddev->ro == 2) /* auto-readonly not meaningful */ mddev->ro = 0;
From: Zhao Heming heming.zhao@suse.com
mainline inclusion from mainline-5.10-rc1 commit 1383b347a8ae4a69c04ae3746e6cb5c8d38e2585 category: bugfix bugzilla: 41594 CVE: NA
---------------------------
Callers of get_bitmap_from_slot() are responsible to free the bitmap.
Suggested-by: Guoqing Jiang guoqing.jiang@cloud.ionos.com Signed-off-by: Zhao Heming heming.zhao@suse.com Signed-off-by: Song Liu songliubraving@fb.com
Conflict: drivers/md/md-cluster.c resize_bitmap() do not exist Signed-off-by: Yu Kuai yukuai3@huawei.com Reviewed-by: Yufen Yu yuyufen@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- drivers/md/md-bitmap.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/md/md-bitmap.c b/drivers/md/md-bitmap.c index a5534fa405cd1..4be79665abd69 100644 --- a/drivers/md/md-bitmap.c +++ b/drivers/md/md-bitmap.c @@ -1947,6 +1947,7 @@ int md_bitmap_load(struct mddev *mddev) } EXPORT_SYMBOL_GPL(md_bitmap_load);
+/* caller need to free returned bitmap with md_bitmap_free() */ struct bitmap *get_bitmap_from_slot(struct mddev *mddev, int slot) { int rv = 0; @@ -2010,6 +2011,7 @@ int md_bitmap_copy_from_slot(struct mddev *mddev, int slot, md_bitmap_unplug(mddev->bitmap); *low = lo; *high = hi; + md_bitmap_free(bitmap);
return rv; } @@ -2599,4 +2601,3 @@ struct attribute_group md_bitmap_group = { .name = "bitmap", .attrs = md_bitmap_attrs, }; -
From: Mauricio Faria de Oliveira mfo@canonical.com
mainline inclusion from mainline-5.12-rc1 commit 4ceddce55eb35d15b0f87f5dcf6f0058fd15d3a4 category: bugfix bugzilla: 50454 CVE: NA ---------------------------
There's an I/O error on fsync() in a detached loop device if it has been previously attached.
The issue is write cache is enabled in the attach path in loop_configure() but it isn't disabled in the detach path; thus it remains enabled in the block device regardless of whether it is attached or not.
Now fsync() can get an I/O request that will just be failed later in loop_queue_rq() as device's state is not 'Lo_bound'.
So, disable write cache in the detach path.
Do so based on the queue flag, not the loop device flag for read-only (used to enable) as the queue flag can be changed via sysfs even on read-only loop devices (e.g., losetup -r.)
Test-case:
# DEV=/dev/loop7
# IMG=/tmp/image # truncate --size 1M $IMG
# losetup $DEV $IMG # losetup -d $DEV
Before:
# strace -e fsync parted -s $DEV print 2>&1 | grep fsync fsync(3) = -1 EIO (Input/output error) Warning: Error fsyncing/closing /dev/loop7: Input/output error [ 982.529929] blk_update_request: I/O error, dev loop7, sector 0 op 0x1:(WRITE) flags 0x800 phys_seg 0 prio class 0
After:
# strace -e fsync parted -s $DEV print 2>&1 | grep fsync fsync(3) = 0
Co-developed-by: Eric Desrochers eric.desrochers@canonical.com Signed-off-by: Eric Desrochers eric.desrochers@canonical.com Signed-off-by: Mauricio Faria de Oliveira mfo@canonical.com Tested-by: Gabriel Krisman Bertazi krisman@collabora.com Reviewed-by: Ming Lei ming.lei@redhat.com Signed-off-by: Jens Axboe axboe@kernel.dk Signed-off-by: Yu Kuai yukuai3@huawei.com Reviewed-by: Yufen Yu yuyufen@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- drivers/block/loop.c | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/drivers/block/loop.c b/drivers/block/loop.c index d0687e90e5d40..94582da07a98c 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -1089,6 +1089,9 @@ static int __loop_clr_fd(struct loop_device *lo, bool release) goto out_unlock; }
+ if (test_bit(QUEUE_FLAG_WC, &lo->lo_queue->queue_flags)) + blk_queue_write_cache(lo->lo_queue, false, false); + /* freeze request queue during the transition */ blk_mq_freeze_queue(lo->lo_queue);
From: Jan Kara jack@suse.cz
mainline inclusion from mainline-v5.12-rc4 commit 2a4ae3bcdf05b8639406eaa09a2939f3c6dd8e75 category: bugfix bugzilla: 46758 CVE: NA
-----------------------------------------------
When filesystem mount fails because of corrupted filesystem we first cancel the s_err_report timer reminding fs errors every day and only then we flush s_error_work. However s_error_work may report another fs error and re-arm timer thus resulting in timer use-after-free. Fix the problem by first flushing the work and only after that canceling the s_err_report timer.
Reported-by: syzbot+628472a2aac693ab0fcd@syzkaller.appspotmail.com Fixes: 2d01ddc86606 ("ext4: save error info to sb through journal if available") CC: stable@vger.kernel.org Signed-off-by: Jan Kara jack@suse.cz Link: https://lore.kernel.org/r/20210315165906.2175-1-jack@suse.cz Signed-off-by: Theodore Ts'o tytso@mit.edu Signed-off-by: Ye Bin yebin10@huawei.com Reviewed-by: zhangyi (F) yi.zhang@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- fs/ext4/super.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/fs/ext4/super.c b/fs/ext4/super.c index f92b5cc115e2e..3b2f7f7ea8cba 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -4746,8 +4746,8 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) failed_mount3a: ext4_es_unregister_shrinker(sbi); failed_mount3: - del_timer_sync(&sbi->s_err_report); flush_work(&sbi->s_error_work); + del_timer_sync(&sbi->s_err_report); if (sbi->s_mmp_tsk) kthread_stop(sbi->s_mmp_tsk); failed_mount2:
From: Wu Bo wubo40@huawei.com
mainline inclusion from mainline-5.7-rc1 commit 1d99702f903277aeaf17e1873151ba40751ed6ed category: bugfix bugzilla: 46895 CVE: NA ---------------------------
Fix an error count for active session if the total_cmds is invalid on the function iscsi_session_setup(). Decrement the number of active sessions before the funcion return.
Link: https://lore.kernel.org/r/EDBAAA0BBBA2AC4E9C8B6B81DEEE1D6916A28542@DGGEML525... Reviewed-by: Lee Duncan lduncan@suuse.com Signed-off-by: Wu Bo wubo40@huawei.com Signed-off-by: Martin K. Petersen martin.petersen@oracle.com Signed-off-by: yangerkun yangerkun@huawei.com Reviewed-by: Jason Yan yanaijie@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- drivers/scsi/libiscsi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index 74b101ef622d6..d40e53e9973dc 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -2836,7 +2836,7 @@ iscsi_session_setup(struct iscsi_transport *iscsit, struct Scsi_Host *shost, "must be a power of 2.\n", total_cmds); total_cmds = rounddown_pow_of_two(total_cmds); if (total_cmds < ISCSI_TOTAL_CMDS_MIN) - return NULL; + goto dec_session_count; printk(KERN_INFO "iscsi: Rounding can_queue to %d.\n", total_cmds); }
From: Mike Christie michael.christie@oracle.com
mainline inclusion from mainline-v5.12-rc1 commit 5923d64b7ab63dcc6f0df946098f50902f9540d1 category: bugfix bugzilla: 46895 CVE: NA ---------------------------
The purpose of the taskqueuelock was to handle the issue where a bad target decides to send a R2T and before its data has been sent decides to send a cmd response to complete the cmd. The following patches fix up the frwd/back locks so they are taken from the queue/xmit (frwd) and completion (back) paths again. To get there this patch removes the taskqueuelock which for iSCSI xmit wq based drivers was taken in the queue, xmit and completion paths.
Instead of the lock, we just make sure we have a ref to the task when we queue a R2T, and then we always remove the task from the requeue list in the xmit path or the forced cleanup paths.
Link: https://lore.kernel.org/r/20210207044608.27585-3-michael.christie@oracle.com Reviewed-by: Lee Duncan lduncan@suse.com Signed-off-by: Mike Christie michael.christie@oracle.com Signed-off-by: Martin K. Petersen martin.petersen@oracle.com
Conflicts: drivers/scsi/libiscsi.c drivers/scsi/libiscsi_tcp.c
Signed-off-by: yangerkun yangerkun@huawei.com Reviewed-by: Jason Yan yanaijie@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- drivers/scsi/libiscsi.c | 177 +++++++++++++++++++++++------------- drivers/scsi/libiscsi_tcp.c | 86 ++++++++++++------ include/scsi/libiscsi.h | 4 +- 3 files changed, 172 insertions(+), 95 deletions(-)
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index d40e53e9973dc..a1eaf0340ca9b 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -567,16 +567,6 @@ static void iscsi_complete_task(struct iscsi_task *task, int state) WARN_ON_ONCE(task->state == ISCSI_TASK_FREE); task->state = state;
- spin_lock_bh(&conn->taskqueuelock); - if (!list_empty(&task->running)) { - pr_debug_once("%s while task on list", __func__); - list_del_init(&task->running); - } - spin_unlock_bh(&conn->taskqueuelock); - - if (conn->task == task) - conn->task = NULL; - if (READ_ONCE(conn->ping_task) == task) WRITE_ONCE(conn->ping_task, NULL);
@@ -608,9 +598,40 @@ void iscsi_complete_scsi_task(struct iscsi_task *task, } EXPORT_SYMBOL_GPL(iscsi_complete_scsi_task);
+/* + * Must be called with back and frwd lock + */ +static bool cleanup_queued_task(struct iscsi_task *task) +{ + struct iscsi_conn *conn = task->conn; + bool early_complete = false; + + /* Bad target might have completed task while it was still running */ + if (task->state == ISCSI_TASK_COMPLETED) + early_complete = true; + + if (!list_empty(&task->running)) { + list_del_init(&task->running); + /* + * If it's on a list but still running, this could be from + * a bad target sending a rsp early, cleanup from a TMF, or + * session recovery. + */ + if (task->state == ISCSI_TASK_RUNNING || + task->state == ISCSI_TASK_COMPLETED) + __iscsi_put_task(task); + } + + if (conn->task == task) { + conn->task = NULL; + __iscsi_put_task(task); + } + + return early_complete; +}
/* - * session back_lock must be held and if not called for a task that is + * session frwd_lock must be held and if not called for a task that is * still pending or from the xmit thread, then xmit thread must * be suspended. */ @@ -629,6 +650,13 @@ static void fail_scsi_task(struct iscsi_task *task, int err) if (!sc) return;
+ /* regular RX path uses back_lock */ + spin_lock_bh(&conn->session->back_lock); + if (cleanup_queued_task(task)) { + spin_unlock_bh(&conn->session->back_lock); + return; + } + if (task->state == ISCSI_TASK_PENDING) { /* * cmd never made it to the xmit thread, so we should not count @@ -650,8 +678,6 @@ static void fail_scsi_task(struct iscsi_task *task, int err) scsi_in(sc)->resid = scsi_in(sc)->length; }
- /* regular RX path uses back_lock */ - spin_lock_bh(&conn->session->back_lock); iscsi_complete_task(task, state); spin_unlock_bh(&conn->session->back_lock); } @@ -797,9 +823,7 @@ __iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, if (session->tt->xmit_task(task)) goto free_task; } else { - spin_lock_bh(&conn->taskqueuelock); list_add_tail(&task->running, &conn->mgmtqueue); - spin_unlock_bh(&conn->taskqueuelock); iscsi_conn_queue_work(conn); }
@@ -1467,31 +1491,61 @@ static int iscsi_check_cmdsn_window_closed(struct iscsi_conn *conn) return 0; }
-static int iscsi_xmit_task(struct iscsi_conn *conn) +static int iscsi_xmit_task(struct iscsi_conn *conn, struct iscsi_task *task, + bool was_requeue) { - struct iscsi_task *task = conn->task; int rc;
- if (test_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx)) - return -ENODATA; - spin_lock_bh(&conn->session->back_lock); - if (conn->task == NULL) { + + if (!conn->task) { + /* Take a ref so we can access it after xmit_task() */ + __iscsi_get_task(task); + } else { + /* Already have a ref from when we failed to send it last call */ + conn->task = NULL; + } + + /* + * If this was a requeue for a R2T we have an extra ref on the task in + * case a bad target sends a cmd rsp before we have handled the task. + */ + if (was_requeue) + __iscsi_put_task(task); + + /* + * Do this after dropping the extra ref because if this was a requeue + * it's removed from that list and cleanup_queued_task would miss it. + */ + if (test_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx)) { + /* + * Save the task and ref in case we weren't cleaning up this + * task and get woken up again. + */ + conn->task = task; spin_unlock_bh(&conn->session->back_lock); return -ENODATA; } - __iscsi_get_task(task); spin_unlock_bh(&conn->session->back_lock); + spin_unlock_bh(&conn->session->frwd_lock); rc = conn->session->tt->xmit_task(task); spin_lock_bh(&conn->session->frwd_lock); if (!rc) { /* done with this task */ task->last_xfer = jiffies; - conn->task = NULL; } /* regular RX path uses back_lock */ spin_lock(&conn->session->back_lock); + if (rc && task->state == ISCSI_TASK_RUNNING) { + /* + * get an extra ref that is released next time we access it + * as conn->task above. + */ + __iscsi_get_task(task); + conn->task = task; + } + __iscsi_put_task(task); spin_unlock(&conn->session->back_lock); return rc; @@ -1501,9 +1555,7 @@ static int iscsi_xmit_task(struct iscsi_conn *conn) * iscsi_requeue_task - requeue task to run from session workqueue * @task: task to requeue * - * LLDs that need to run a task from the session workqueue should call - * this. The session frwd_lock must be held. This should only be called - * by software drivers. + * Callers must have taken a ref to the task that is going to be requeued. */ void iscsi_requeue_task(struct iscsi_task *task) { @@ -1513,11 +1565,18 @@ void iscsi_requeue_task(struct iscsi_task *task) * this may be on the requeue list already if the xmit_task callout * is handling the r2ts while we are adding new ones */ - spin_lock_bh(&conn->taskqueuelock); - if (list_empty(&task->running)) + spin_lock_bh(&conn->session->frwd_lock); + if (list_empty(&task->running)) { list_add_tail(&task->running, &conn->requeue); - spin_unlock_bh(&conn->taskqueuelock); + } else { + /* + * Don't need the extra ref since it's already requeued and + * has a ref. + */ + iscsi_put_task(task); + } iscsi_conn_queue_work(conn); + spin_unlock_bh(&conn->session->frwd_lock); } EXPORT_SYMBOL_GPL(iscsi_requeue_task);
@@ -1543,7 +1602,7 @@ static int iscsi_data_xmit(struct iscsi_conn *conn) }
if (conn->task) { - rc = iscsi_xmit_task(conn); + rc = iscsi_xmit_task(conn, conn->task, false); if (rc) goto done; } @@ -1553,49 +1612,41 @@ static int iscsi_data_xmit(struct iscsi_conn *conn) * only have one nop-out as a ping from us and targets should not * overflow us with nop-ins */ - spin_lock_bh(&conn->taskqueuelock); check_mgmt: while (!list_empty(&conn->mgmtqueue)) { - conn->task = list_entry(conn->mgmtqueue.next, - struct iscsi_task, running); - list_del_init(&conn->task->running); - spin_unlock_bh(&conn->taskqueuelock); - if (iscsi_prep_mgmt_task(conn, conn->task)) { + task = list_entry(conn->mgmtqueue.next, struct iscsi_task, + running); + list_del_init(&task->running); + if (iscsi_prep_mgmt_task(conn, task)) { /* regular RX path uses back_lock */ spin_lock_bh(&conn->session->back_lock); - __iscsi_put_task(conn->task); + __iscsi_put_task(task); spin_unlock_bh(&conn->session->back_lock); - conn->task = NULL; - spin_lock_bh(&conn->taskqueuelock); continue; } - rc = iscsi_xmit_task(conn); + rc = iscsi_xmit_task(conn, task, false); if (rc) goto done; - spin_lock_bh(&conn->taskqueuelock); }
/* process pending command queue */ while (!list_empty(&conn->cmdqueue)) { - conn->task = list_entry(conn->cmdqueue.next, struct iscsi_task, - running); - list_del_init(&conn->task->running); - spin_unlock_bh(&conn->taskqueuelock); + task = list_entry(conn->cmdqueue.next, struct iscsi_task, + running); + list_del_init(&task->running); if (conn->session->state == ISCSI_STATE_LOGGING_OUT) { - fail_scsi_task(conn->task, DID_IMM_RETRY); - spin_lock_bh(&conn->taskqueuelock); + fail_scsi_task(task, DID_IMM_RETRY); continue; } - rc = iscsi_prep_scsi_cmd_pdu(conn->task); + rc = iscsi_prep_scsi_cmd_pdu(task); if (rc) { if (rc == -ENOMEM || rc == -EACCES) - fail_scsi_task(conn->task, DID_IMM_RETRY); + fail_scsi_task(task, DID_IMM_RETRY); else - fail_scsi_task(conn->task, DID_ABORT); - spin_lock_bh(&conn->taskqueuelock); + fail_scsi_task(task, DID_ABORT); continue; } - rc = iscsi_xmit_task(conn); + rc = iscsi_xmit_task(conn, task, false); if (rc) goto done; /* @@ -1603,7 +1654,6 @@ static int iscsi_data_xmit(struct iscsi_conn *conn) * we need to check the mgmt queue for nops that need to * be sent to aviod starvation */ - spin_lock_bh(&conn->taskqueuelock); if (!list_empty(&conn->mgmtqueue)) goto check_mgmt; } @@ -1617,21 +1667,17 @@ static int iscsi_data_xmit(struct iscsi_conn *conn)
task = list_entry(conn->requeue.next, struct iscsi_task, running); + if (iscsi_check_tmf_restrictions(task, ISCSI_OP_SCSI_DATA_OUT)) break;
- conn->task = task; - list_del_init(&conn->task->running); - conn->task->state = ISCSI_TASK_RUNNING; - spin_unlock_bh(&conn->taskqueuelock); - rc = iscsi_xmit_task(conn); + list_del_init(&task->running); + rc = iscsi_xmit_task(conn, task, true); if (rc) goto done; - spin_lock_bh(&conn->taskqueuelock); if (!list_empty(&conn->mgmtqueue)) goto check_mgmt; } - spin_unlock_bh(&conn->taskqueuelock); spin_unlock_bh(&conn->session->frwd_lock); return -ENODATA;
@@ -1797,9 +1843,7 @@ int iscsi_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *sc) goto prepd_reject; } } else { - spin_lock_bh(&conn->taskqueuelock); list_add_tail(&task->running, &conn->cmdqueue); - spin_unlock_bh(&conn->taskqueuelock); iscsi_conn_queue_work(conn); }
@@ -2976,7 +3020,6 @@ iscsi_conn_setup(struct iscsi_cls_session *cls_session, int dd_size, INIT_LIST_HEAD(&conn->mgmtqueue); INIT_LIST_HEAD(&conn->cmdqueue); INIT_LIST_HEAD(&conn->requeue); - spin_lock_init(&conn->taskqueuelock); INIT_WORK(&conn->xmitwork, iscsi_xmitworker);
/* allocate login_task used for the login/text sequences */ @@ -3142,10 +3185,16 @@ fail_mgmt_tasks(struct iscsi_session *session, struct iscsi_conn *conn) ISCSI_DBG_SESSION(conn->session, "failing mgmt itt 0x%x state %d\n", task->itt, task->state); + + spin_lock_bh(&session->back_lock); + if (cleanup_queued_task(task)) { + spin_unlock_bh(&session->back_lock); + continue; + } + state = ISCSI_TASK_ABRT_SESS_RECOV; if (task->state == ISCSI_TASK_PENDING) state = ISCSI_TASK_COMPLETED; - spin_lock_bh(&session->back_lock); iscsi_complete_task(task, state); spin_unlock_bh(&session->back_lock); } diff --git a/drivers/scsi/libiscsi_tcp.c b/drivers/scsi/libiscsi_tcp.c index b88ea3ebd096e..f9437fe983a17 100644 --- a/drivers/scsi/libiscsi_tcp.c +++ b/drivers/scsi/libiscsi_tcp.c @@ -531,48 +531,79 @@ static int iscsi_tcp_data_in(struct iscsi_conn *conn, struct iscsi_task *task) /** * iscsi_tcp_r2t_rsp - iSCSI R2T Response processing * @conn: iscsi connection - * @task: scsi command task + * @hdr: PDU header */ -static int iscsi_tcp_r2t_rsp(struct iscsi_conn *conn, struct iscsi_task *task) +static int iscsi_tcp_r2t_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr) { struct iscsi_session *session = conn->session; - struct iscsi_tcp_task *tcp_task = task->dd_data; - struct iscsi_tcp_conn *tcp_conn = conn->dd_data; - struct iscsi_r2t_rsp *rhdr = (struct iscsi_r2t_rsp *)tcp_conn->in.hdr; + struct iscsi_tcp_task *tcp_task; + struct iscsi_tcp_conn *tcp_conn; + struct iscsi_r2t_rsp *rhdr; struct iscsi_r2t_info *r2t; - int r2tsn = be32_to_cpu(rhdr->r2tsn); + struct iscsi_task *task; u32 data_length; u32 data_offset; + int r2tsn; int rc;
+ spin_lock(&session->back_lock); + task = iscsi_itt_to_ctask(conn, hdr->itt); + if (!task) { + spin_unlock(&session->back_lock); + return ISCSI_ERR_BAD_ITT; + } else if (task->sc->sc_data_direction != DMA_TO_DEVICE) { + spin_unlock(&session->back_lock); + return ISCSI_ERR_PROTO; + } + /* + * A bad target might complete the cmd before we have handled R2Ts + * so get a ref to the task that will be dropped in the xmit path. + */ + if (task->state != ISCSI_TASK_RUNNING) { + spin_unlock(&session->back_lock); + /* Let the path that got the early rsp complete it */ + return 0; + } + task->last_xfer = jiffies; + __iscsi_get_task(task); + + tcp_conn = conn->dd_data; + rhdr = (struct iscsi_r2t_rsp *)tcp_conn->in.hdr; + /* fill-in new R2T associated with the task */ + iscsi_update_cmdsn(session, (struct iscsi_nopin *)rhdr); + spin_unlock(&session->back_lock); + if (tcp_conn->in.datalen) { iscsi_conn_printk(KERN_ERR, conn, "invalid R2t with datalen %d\n", tcp_conn->in.datalen); - return ISCSI_ERR_DATALEN; + rc = ISCSI_ERR_DATALEN; + goto put_task; }
+ tcp_task = task->dd_data; + r2tsn = be32_to_cpu(rhdr->r2tsn); if (tcp_task->exp_datasn != r2tsn){ ISCSI_DBG_TCP(conn, "task->exp_datasn(%d) != rhdr->r2tsn(%d)\n", tcp_task->exp_datasn, r2tsn); - return ISCSI_ERR_R2TSN; + rc = ISCSI_ERR_R2TSN; + goto put_task; }
- /* fill-in new R2T associated with the task */ - iscsi_update_cmdsn(session, (struct iscsi_nopin*)rhdr); - - if (!task->sc || session->state != ISCSI_STATE_LOGGED_IN) { + if (session->state != ISCSI_STATE_LOGGED_IN) { iscsi_conn_printk(KERN_INFO, conn, "dropping R2T itt %d in recovery.\n", task->itt); - return 0; + rc = 0; + goto put_task; }
data_length = be32_to_cpu(rhdr->data_length); if (data_length == 0) { iscsi_conn_printk(KERN_ERR, conn, "invalid R2T with zero data len\n"); - return ISCSI_ERR_DATALEN; + rc = ISCSI_ERR_DATALEN; + goto put_task; }
if (data_length > session->max_burst) @@ -586,7 +617,8 @@ static int iscsi_tcp_r2t_rsp(struct iscsi_conn *conn, struct iscsi_task *task) "invalid R2T with data len %u at offset %u " "and total length %d\n", data_length, data_offset, scsi_out(task->sc)->length); - return ISCSI_ERR_DATALEN; + rc = ISCSI_ERR_DATALEN; + goto put_task; }
spin_lock(&tcp_task->pool2queue); @@ -596,7 +628,8 @@ static int iscsi_tcp_r2t_rsp(struct iscsi_conn *conn, struct iscsi_task *task) "Target has sent more R2Ts than it " "negotiated for or driver has leaked.\n"); spin_unlock(&tcp_task->pool2queue); - return ISCSI_ERR_PROTO; + rc = ISCSI_ERR_PROTO; + goto put_task; }
r2t->exp_statsn = rhdr->statsn; @@ -614,6 +647,10 @@ static int iscsi_tcp_r2t_rsp(struct iscsi_conn *conn, struct iscsi_task *task)
iscsi_requeue_task(task); return 0; + +put_task: + iscsi_put_task(task); + return rc; }
/* @@ -737,20 +774,11 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *hdr) rc = iscsi_complete_pdu(conn, hdr, NULL, 0); break; case ISCSI_OP_R2T: - spin_lock(&conn->session->back_lock); - task = iscsi_itt_to_ctask(conn, hdr->itt); - spin_unlock(&conn->session->back_lock); - if (!task) - rc = ISCSI_ERR_BAD_ITT; - else if (ahslen) + if (ahslen) { rc = ISCSI_ERR_AHSLEN; - else if (task->sc->sc_data_direction == DMA_TO_DEVICE) { - task->last_xfer = jiffies; - spin_lock(&conn->session->frwd_lock); - rc = iscsi_tcp_r2t_rsp(conn, task); - spin_unlock(&conn->session->frwd_lock); - } else - rc = ISCSI_ERR_PROTO; + break; + } + rc = iscsi_tcp_r2t_rsp(conn, hdr); break; case ISCSI_OP_LOGIN_RSP: case ISCSI_OP_TEXT_RSP: diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h index 8e146aa623cfd..c71297f7078c4 100644 --- a/include/scsi/libiscsi.h +++ b/include/scsi/libiscsi.h @@ -200,7 +200,7 @@ struct iscsi_conn { struct iscsi_task *task; /* xmit task in progress */
/* xmit */ - spinlock_t taskqueuelock; /* protects the next three lists */ + /* items must be added/deleted under frwd lock */ struct list_head mgmtqueue; /* mgmt (control) xmit queue */ struct list_head cmdqueue; /* data-path cmd queue */ struct list_head requeue; /* tasks needing another run */ @@ -346,7 +346,7 @@ struct iscsi_session { * cmdsn, queued_cmdsn * * session resources: * * - cmdpool kfifo_out , * - * - mgmtpool, */ + * - mgmtpool, queues */ spinlock_t back_lock; /* protects cmdsn_exp * * cmdsn_max, * * cmdpool kfifo_in */
From: Mike Christie michael.christie@oracle.com
mainline inclusion from mainline-v5.12-rc1 commit 14936b1ed249916c28642d0db47a51b085ce13b4 category: bugfix bugzilla: 46895 CVE: NA ---------------------------
The following bug was reported and debugged by wubo40@huawei.com:
When testing kernel 4.18 version, NULL pointer dereference problem occurs in iscsi_eh_cmd_timed_out() function.
I think this bug in the upstream is still exists.
The analysis reasons are as follows:
1) For some reason, I/O command did not complete within the timeout period. The block layer timer works, call scsi_times_out() to handle I/O timeout logic. At the same time the command just completes.
2) scsi_times_out() call iscsi_eh_cmd_timed_out() to process timeout logic. Although there is an NULL judgment for the task, the task has not been released yet now.
3) iscsi_complete_task() calls __iscsi_put_task(). The task reference count reaches zero, the conditions for free task is met, then iscsi_free_task() frees the task, and sets sc->SCp.ptr = NULL. After iscsi_eh_cmd_timed_out() passes the task judgment check, there can still be NULL dereference scenarios.
CPU0 CPU3
|- scsi_times_out() |- iscsi_complete_task() | | |- iscsi_eh_cmd_timed_out() |- __iscsi_put_task() | | |- task=sc->SCp.ptr, task is not NUL, check passed |- iscsi_free_task(task) | | | |-> sc->SCp.ptr = NULL | | |- task is NULL now, NULL pointer dereference | | | |/ |/
Calltrace: [380751.840862] BUG: unable to handle kernel NULL pointer dereference at 0000000000000138 [380751.843709] PGD 0 P4D 0 [380751.844770] Oops: 0000 [#1] SMP PTI [380751.846283] CPU: 0 PID: 403 Comm: kworker/0:1H Kdump: loaded Tainted: G [380751.851467] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996) [380751.856521] Workqueue: kblockd blk_mq_timeout_work [380751.858527] RIP: 0010:iscsi_eh_cmd_timed_out+0x15e/0x2e0 [libiscsi] [380751.861129] Code: 83 ea 01 48 8d 74 d0 08 48 8b 10 48 8b 4a 50 48 85 c9 74 2c 48 39 d5 74 [380751.868811] RSP: 0018:ffffc1e280a5fd58 EFLAGS: 00010246 [380751.870978] RAX: ffff9fd1e84e15e0 RBX: ffff9fd1e84e6dd0 RCX: 0000000116acc580 [380751.873791] RDX: ffff9fd1f97a9400 RSI: ffff9fd1e84e1800 RDI: ffff9fd1e4d6d420 [380751.876059] RBP: ffff9fd1e4d49000 R08: 0000000116acc580 R09: 0000000116acc580 [380751.878284] R10: 0000000000000000 R11: 0000000000000000 R12: ffff9fd1e6e931e8 [380751.880500] R13: ffff9fd1e84e6ee0 R14: 0000000000000010 R15: 0000000000000003 [380751.882687] FS: 0000000000000000(0000) GS:ffff9fd1fac00000(0000) knlGS:0000000000000000 [380751.885236] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [380751.887059] CR2: 0000000000000138 CR3: 000000011860a001 CR4: 00000000003606f0 [380751.889308] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 [380751.891523] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 [380751.893738] Call Trace: [380751.894639] scsi_times_out+0x60/0x1c0 [380751.895861] blk_mq_check_expired+0x144/0x200 [380751.897302] ? __switch_to_asm+0x35/0x70 [380751.898551] blk_mq_queue_tag_busy_iter+0x195/0x2e0 [380751.900091] ? __blk_mq_requeue_request+0x100/0x100 [380751.901611] ? __switch_to_asm+0x41/0x70 [380751.902853] ? __blk_mq_requeue_request+0x100/0x100 [380751.904398] blk_mq_timeout_work+0x54/0x130 [380751.905740] process_one_work+0x195/0x390 [380751.907228] worker_thread+0x30/0x390 [380751.908713] ? process_one_work+0x390/0x390 [380751.910350] kthread+0x10d/0x130 [380751.911470] ? kthread_flush_work_fn+0x10/0x10 [380751.913007] ret_from_fork+0x35/0x40
crash> dis -l iscsi_eh_cmd_timed_out+0x15e xxxxx/drivers/scsi/libiscsi.c: 2062
1970 enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *sc) { ... 1984 spin_lock_bh(&session->frwd_lock); 1985 task = (struct iscsi_task *)sc->SCp.ptr; 1986 if (!task) { 1987 /* 1988 * Raced with completion. Blk layer has taken ownership 1989 * so let timeout code complete it now. 1990 */ 1991 rc = BLK_EH_DONE; 1992 goto done; 1993 }
...
2052 for (i = 0; i < conn->session->cmds_max; i++) { 2053 running_task = conn->session->cmds[i]; 2054 if (!running_task->sc || running_task == task || 2055 running_task->state != ISCSI_TASK_RUNNING) 2056 continue; 2057 2058 /* 2059 * Only check if cmds started before this one have made 2060 * progress, or this could never fail 2061 */ 2062 if (time_after(running_task->sc->jiffies_at_alloc, 2063 task->sc->jiffies_at_alloc)) <--- 2064 continue; 2065 ... }
carsh> struct scsi_cmnd ffff9fd1e6e931e8 struct scsi_cmnd { ... SCp = { ptr = 0x0, <--- iscsi_task this_residual = 0, ... }, }
To prevent this, we take a ref to the cmd under the back (completion) lock so if the completion side were to call iscsi_complete_task() on the task while the timer/eh paths are not holding the back_lock it will not be freed from under us.
Note that this requires the previous patch, "scsi: libiscsi: Drop taskqueuelock" because bnx2i sleeps in its cleanup_task callout if the cmd is aborted. If the EH/timer and completion path are racing we don't know which path will do the last put. The previous patch moved the operations we needed to do under the forward lock to cleanup_queued_task. Once that has run we can drop the forward lock for the cmd and bnx2i no longer has to worry about if the EH, timer or completion path did the ast put and if the forward lock is held or not since it won't be.
Link: https://lore.kernel.org/r/20210207044608.27585-4-michael.christie@oracle.com Reported-by: Wu Bo wubo40@huawei.com Reviewed-by: Lee Duncan lduncan@suse.com Signed-off-by: Mike Christie michael.christie@oracle.com Signed-off-by: Martin K. Petersen martin.petersen@oracle.com
Conflicts: drivers/scsi/libiscsi.c
Signed-off-by: yangerkun yangerkun@huawei.com Reviewed-by: Jason Yan yanaijie@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- drivers/scsi/bnx2i/bnx2i_iscsi.c | 2 - drivers/scsi/libiscsi.c | 71 ++++++++++++++++++++------------ 2 files changed, 45 insertions(+), 28 deletions(-)
diff --git a/drivers/scsi/bnx2i/bnx2i_iscsi.c b/drivers/scsi/bnx2i/bnx2i_iscsi.c index 718a0335cfbb3..b16a9b73c6f06 100644 --- a/drivers/scsi/bnx2i/bnx2i_iscsi.c +++ b/drivers/scsi/bnx2i/bnx2i_iscsi.c @@ -1173,10 +1173,8 @@ static void bnx2i_cleanup_task(struct iscsi_task *task) bnx2i_send_cmd_cleanup_req(hba, task->dd_data);
spin_unlock_bh(&conn->session->back_lock); - spin_unlock_bh(&conn->session->frwd_lock); wait_for_completion_timeout(&bnx2i_conn->cmd_cleanup_cmpl, msecs_to_jiffies(ISCSI_CMD_CLEANUP_TIMEOUT)); - spin_lock_bh(&conn->session->frwd_lock); spin_lock_bh(&conn->session->back_lock); } bnx2i_iscsi_unmap_sg_list(task->dd_data); diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index a1eaf0340ca9b..0f0cdb4be1255 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -631,9 +631,8 @@ static bool cleanup_queued_task(struct iscsi_task *task) }
/* - * session frwd_lock must be held and if not called for a task that is - * still pending or from the xmit thread, then xmit thread must - * be suspended. + * session frwd lock must be held and if not called for a task that is still + * pending or from the xmit thread, then xmit thread must be suspended */ static void fail_scsi_task(struct iscsi_task *task, int err) { @@ -641,16 +640,6 @@ static void fail_scsi_task(struct iscsi_task *task, int err) struct scsi_cmnd *sc; int state;
- /* - * if a command completes and we get a successful tmf response - * we will hit this because the scsi eh abort code does not take - * a ref to the task. - */ - sc = task->sc; - if (!sc) - return; - - /* regular RX path uses back_lock */ spin_lock_bh(&conn->session->back_lock); if (cleanup_queued_task(task)) { spin_unlock_bh(&conn->session->back_lock); @@ -670,6 +659,7 @@ static void fail_scsi_task(struct iscsi_task *task, int err) else state = ISCSI_TASK_ABRT_TMF;
+ sc = task->sc; sc->result = err << 16; if (!scsi_bidi_cmnd(sc)) scsi_set_resid(sc, scsi_bufflen(sc)); @@ -1955,27 +1945,39 @@ static int iscsi_exec_task_mgmt_fn(struct iscsi_conn *conn, }
/* - * Fail commands. session lock held and recv side suspended and xmit - * thread flushed + * Fail commands. session frwd lock held and xmit thread flushed. */ static void fail_scsi_tasks(struct iscsi_conn *conn, u64 lun, int error) { + struct iscsi_session *session = conn->session; struct iscsi_task *task; int i;
- for (i = 0; i < conn->session->cmds_max; i++) { - task = conn->session->cmds[i]; + spin_lock_bh(&session->back_lock); + for (i = 0; i < session->cmds_max; i++) { + task = session->cmds[i]; if (!task->sc || task->state == ISCSI_TASK_FREE) continue;
if (lun != -1 && lun != task->sc->device->lun) continue;
- ISCSI_DBG_SESSION(conn->session, + __iscsi_get_task(task); + spin_unlock_bh(&session->back_lock); + + ISCSI_DBG_SESSION(session, "failing sc %p itt 0x%x state %d\n", task->sc, task->itt, task->state); fail_scsi_task(task, error); + + spin_unlock_bh(&session->frwd_lock); + iscsi_put_task(task); + spin_lock_bh(&session->frwd_lock); + + spin_lock_bh(&session->back_lock); } + + spin_unlock_bh(&session->back_lock); }
/** @@ -2053,6 +2055,7 @@ enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *sc) ISCSI_DBG_EH(session, "scsi cmd %p timedout\n", sc);
spin_lock_bh(&session->frwd_lock); + spin_lock(&session->back_lock); task = (struct iscsi_task *)sc->SCp.ptr; if (!task) { /* @@ -2060,8 +2063,11 @@ enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *sc) * so let timeout code complete it now. */ rc = BLK_EH_DONE; + spin_unlock(&session->back_lock); goto done; } + __iscsi_get_task(task); + spin_unlock(&session->back_lock);
if (session->state != ISCSI_STATE_LOGGED_IN) { /* @@ -2120,6 +2126,7 @@ enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *sc) goto done; }
+ spin_lock(&session->back_lock); for (i = 0; i < conn->session->cmds_max; i++) { running_task = conn->session->cmds[i]; if (!running_task->sc || running_task == task || @@ -2152,10 +2159,12 @@ enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *sc) "last xfer %lu/%lu. Last check %lu.\n", task->last_xfer, running_task->last_xfer, task->last_timeout); + spin_unlock(&session->back_lock); rc = BLK_EH_RESET_TIMER; goto done; } } + spin_unlock(&session->back_lock);
/* Assumes nop timeout is shorter than scsi cmd timeout */ if (task->have_checked_conn) @@ -2177,9 +2186,12 @@ enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *sc) rc = BLK_EH_RESET_TIMER;
done: - if (task) - task->last_timeout = jiffies; spin_unlock_bh(&session->frwd_lock); + + if (task) { + task->last_timeout = jiffies; + iscsi_put_task(task); + } ISCSI_DBG_EH(session, "return %s\n", rc == BLK_EH_RESET_TIMER ? "timer reset" : "shutdown or nh"); return rc; @@ -2287,15 +2299,20 @@ int iscsi_eh_abort(struct scsi_cmnd *sc) conn->eh_abort_cnt++; age = session->age;
+ spin_lock(&session->back_lock); task = (struct iscsi_task *)sc->SCp.ptr; - ISCSI_DBG_EH(session, "aborting [sc %p itt 0x%x]\n", - sc, task->itt); - - /* task completed before time out */ - if (!task->sc) { + if (!task || !task->sc) { + /* task completed before time out */ ISCSI_DBG_EH(session, "sc completed while abort in progress\n"); - goto success; + + spin_unlock(&session->back_lock); + spin_unlock_bh(&session->frwd_lock); + mutex_unlock(&session->eh_mutex); + return SUCCESS; } + ISCSI_DBG_EH(session, "aborting [sc %p itt 0x%x]\n", sc, task->itt); + __iscsi_get_task(task); + spin_unlock(&session->back_lock);
if (task->state == ISCSI_TASK_PENDING) { fail_scsi_task(task, DID_ABORT); @@ -2357,6 +2374,7 @@ int iscsi_eh_abort(struct scsi_cmnd *sc) success_unlocked: ISCSI_DBG_EH(session, "abort success [sc %p itt 0x%x]\n", sc, task->itt); + iscsi_put_task(task); mutex_unlock(&session->eh_mutex); return SUCCESS;
@@ -2365,6 +2383,7 @@ int iscsi_eh_abort(struct scsi_cmnd *sc) failed_unlocked: ISCSI_DBG_EH(session, "abort failed [sc %p itt 0x%x]\n", sc, task ? task->itt : 0); + iscsi_put_task(task); mutex_unlock(&session->eh_mutex); return FAILED; }
From: Mike Christie michael.christie@oracle.com
mainline inclusion from mainline-v5.12-rc1 commit c435f0a9ecb7435e70f447b7231ca52de589b252 category: bugfix bugzilla: 46895 CVE: NA ---------------------------
We allocate the iSCSI host workq in iscsi_host_alloc() so iscsi_host_free() should do the destruction. Drivers can then do their error/goto handling and call iscsi_host_free() to clean up what has been allocated in iscsi_host_alloc().
Link: https://lore.kernel.org/r/20210207044608.27585-5-michael.christie@oracle.com Reviewed-by: Lee Duncan lduncan@suse.com Signed-off-by: Mike Christie michael.christie@oracle.com Signed-off-by: Martin K. Petersen martin.petersen@oracle.com Signed-off-by: yangerkun yangerkun@huawei.com Reviewed-by: Jason Yan yanaijie@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- drivers/scsi/libiscsi.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index 0f0cdb4be1255..27b66b03392de 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -2800,8 +2800,6 @@ void iscsi_host_remove(struct Scsi_Host *shost) flush_signals(current);
scsi_remove_host(shost); - if (ihost->workq) - destroy_workqueue(ihost->workq); } EXPORT_SYMBOL_GPL(iscsi_host_remove);
@@ -2809,6 +2807,9 @@ void iscsi_host_free(struct Scsi_Host *shost) { struct iscsi_host *ihost = shost_priv(shost);
+ if (ihost->workq) + destroy_workqueue(ihost->workq); + kfree(ihost->netdev); kfree(ihost->hwaddress); kfree(ihost->initiatorname);
From: Mike Christie michael.christie@oracle.com
mainline inclusion from mainline-v5.12-rc1 commit b4046922b3c0740ad50a6e9c59e12f4dc43946d4 category: bugfix bugzilla: 46895 CVE: NA ---------------------------
This patch just breaks out the code that calculates the number of SCSI cmds that will be used for a SCSI session. It also adds a check that we don't go over the host's can_queue value.
Link: https://lore.kernel.org/r/20210207044608.27585-6-michael.christie@oracle.com Reviewed-by: Lee Duncan lduncan@suse.com Signed-off-by: Mike Christie michael.christie@oracle.com Signed-off-by: Martin K. Petersen martin.petersen@oracle.com Signed-off-by: yangerkun yangerkun@huawei.com Reviewed-by: Jason Yan yanaijie@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- drivers/scsi/libiscsi.c | 86 ++++++++++++++++++++++++++--------------- include/scsi/libiscsi.h | 2 + 2 files changed, 56 insertions(+), 32 deletions(-)
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index 27b66b03392de..1ea22d49b73c6 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -2710,6 +2710,56 @@ void iscsi_pool_free(struct iscsi_pool *q) } EXPORT_SYMBOL_GPL(iscsi_pool_free);
+int iscsi_host_get_max_scsi_cmds(struct Scsi_Host *shost, + uint16_t requested_cmds_max) +{ + int scsi_cmds, total_cmds = requested_cmds_max; + +check: + if (!total_cmds) + total_cmds = ISCSI_DEF_XMIT_CMDS_MAX; + /* + * The iscsi layer needs some tasks for nop handling and tmfs, + * so the cmds_max must at least be greater than ISCSI_MGMT_CMDS_MAX + * + 1 command for scsi IO. + */ + if (total_cmds < ISCSI_TOTAL_CMDS_MIN) { + printk(KERN_ERR "iscsi: invalid max cmds of %d. Must be a power of two that is at least %d.\n", + total_cmds, ISCSI_TOTAL_CMDS_MIN); + return -EINVAL; + } + + if (total_cmds > ISCSI_TOTAL_CMDS_MAX) { + printk(KERN_INFO "iscsi: invalid max cmds of %d. Must be a power of 2 less than or equal to %d. Using %d.\n", + requested_cmds_max, ISCSI_TOTAL_CMDS_MAX, + ISCSI_TOTAL_CMDS_MAX); + total_cmds = ISCSI_TOTAL_CMDS_MAX; + } + + if (!is_power_of_2(total_cmds)) { + total_cmds = rounddown_pow_of_two(total_cmds); + if (total_cmds < ISCSI_TOTAL_CMDS_MIN) { + printk(KERN_ERR "iscsi: invalid max cmds of %d. Must be a power of 2 greater than %d.\n", requested_cmds_max, ISCSI_TOTAL_CMDS_MIN); + return -EINVAL; + } + + printk(KERN_INFO "iscsi: invalid max cmds %d. Must be a power of 2. Rounding max cmds down to %d.\n", + requested_cmds_max, total_cmds); + } + + scsi_cmds = total_cmds - ISCSI_MGMT_CMDS_MAX; + if (shost->can_queue && scsi_cmds > shost->can_queue) { + total_cmds = shost->can_queue; + + printk(KERN_INFO "iscsi: requested max cmds %u is higher than driver limit. Using driver limit %u\n", + requested_cmds_max, shost->can_queue); + goto check; + } + + return scsi_cmds; +} +EXPORT_SYMBOL_GPL(iscsi_host_get_max_scsi_cmds); + /** * iscsi_host_add - add host to system * @shost: scsi host @@ -2863,7 +2913,7 @@ iscsi_session_setup(struct iscsi_transport *iscsit, struct Scsi_Host *shost, struct iscsi_host *ihost = shost_priv(shost); struct iscsi_session *session; struct iscsi_cls_session *cls_session; - int cmd_i, scsi_cmds, total_cmds = cmds_max; + int cmd_i, scsi_cmds; unsigned long flags;
spin_lock_irqsave(&ihost->lock, flags); @@ -2874,37 +2924,9 @@ iscsi_session_setup(struct iscsi_transport *iscsit, struct Scsi_Host *shost, ihost->num_sessions++; spin_unlock_irqrestore(&ihost->lock, flags);
- if (!total_cmds) - total_cmds = ISCSI_DEF_XMIT_CMDS_MAX; - /* - * The iscsi layer needs some tasks for nop handling and tmfs, - * so the cmds_max must at least be greater than ISCSI_MGMT_CMDS_MAX - * + 1 command for scsi IO. - */ - if (total_cmds < ISCSI_TOTAL_CMDS_MIN) { - printk(KERN_ERR "iscsi: invalid can_queue of %d. can_queue " - "must be a power of two that is at least %d.\n", - total_cmds, ISCSI_TOTAL_CMDS_MIN); + scsi_cmds = iscsi_host_get_max_scsi_cmds(shost, cmds_max); + if (scsi_cmds < 0) goto dec_session_count; - } - - if (total_cmds > ISCSI_TOTAL_CMDS_MAX) { - printk(KERN_ERR "iscsi: invalid can_queue of %d. can_queue " - "must be a power of 2 less than or equal to %d.\n", - cmds_max, ISCSI_TOTAL_CMDS_MAX); - total_cmds = ISCSI_TOTAL_CMDS_MAX; - } - - if (!is_power_of_2(total_cmds)) { - printk(KERN_ERR "iscsi: invalid can_queue of %d. can_queue " - "must be a power of 2.\n", total_cmds); - total_cmds = rounddown_pow_of_two(total_cmds); - if (total_cmds < ISCSI_TOTAL_CMDS_MIN) - goto dec_session_count; - printk(KERN_INFO "iscsi: Rounding can_queue to %d.\n", - total_cmds); - } - scsi_cmds = total_cmds - ISCSI_MGMT_CMDS_MAX;
cls_session = iscsi_alloc_session(shost, iscsit, sizeof(struct iscsi_session) + @@ -2920,7 +2942,7 @@ iscsi_session_setup(struct iscsi_transport *iscsit, struct Scsi_Host *shost, session->lu_reset_timeout = 15; session->abort_timeout = 10; session->scsi_cmds_max = scsi_cmds; - session->cmds_max = total_cmds; + session->cmds_max = scsi_cmds + ISCSI_MGMT_CMDS_MAX; session->queued_cmdsn = session->cmdsn = initial_cmdsn; session->exp_cmdsn = initial_cmdsn + 1; session->max_cmdsn = initial_cmdsn + 1; diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h index c71297f7078c4..7ae6867316d36 100644 --- a/include/scsi/libiscsi.h +++ b/include/scsi/libiscsi.h @@ -409,6 +409,8 @@ extern struct Scsi_Host *iscsi_host_alloc(struct scsi_host_template *sht, extern void iscsi_host_remove(struct Scsi_Host *shost); extern void iscsi_host_free(struct Scsi_Host *shost); extern int iscsi_target_alloc(struct scsi_target *starget); +extern int iscsi_host_get_max_scsi_cmds(struct Scsi_Host *shost, + uint16_t requested_cmds_max);
/* * session management
From: Mike Christie michael.christie@oracle.com
mainline inclusion from mainline-v5.12-rc1 commit 25c400db2083732a5fbdd72f0d3a0337119b2fa5 category: bugfix bugzilla: 46895 CVE: NA ---------------------------
We are setting the shost's can_queue after we add the host which is too late, because the SCSI midlayer will have allocated the tag set based on the can_queue value at that time. This patch has us use the iscsi_host_get_max_scsi_cmds() helper to figure out the number of SCSI cmds.
It also fixes up the template can_queue so it reflects the max SCSI cmds we can support like how other drivers work.
Link: https://lore.kernel.org/r/20210207044608.27585-7-michael.christie@oracle.com Reviewed-by: Lee Duncan lduncan@suse.com Signed-off-by: Mike Christie michael.christie@oracle.com Signed-off-by: Martin K. Petersen martin.petersen@oracle.com Signed-off-by: yangerkun yangerkun@huawei.com Reviewed-by: Jason Yan yanaijie@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- drivers/scsi/iscsi_tcp.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c index 2543d227200fd..2f3881351c760 100644 --- a/drivers/scsi/iscsi_tcp.c +++ b/drivers/scsi/iscsi_tcp.c @@ -860,6 +860,7 @@ iscsi_sw_tcp_session_create(struct iscsi_endpoint *ep, uint16_t cmds_max, struct iscsi_session *session; struct iscsi_sw_tcp_host *tcp_sw_host; struct Scsi_Host *shost; + int rc;
if (ep) { printk(KERN_ERR "iscsi_tcp: invalid ep %p.\n", ep); @@ -877,6 +878,11 @@ iscsi_sw_tcp_session_create(struct iscsi_endpoint *ep, uint16_t cmds_max, shost->max_channel = 0; shost->max_cmd_len = SCSI_MAX_VARLEN_CDB_SIZE;
+ rc = iscsi_host_get_max_scsi_cmds(shost, cmds_max); + if (rc < 0) + goto free_host; + shost->can_queue = rc; + if (iscsi_host_add(shost, NULL)) goto free_host;
@@ -891,7 +897,6 @@ iscsi_sw_tcp_session_create(struct iscsi_endpoint *ep, uint16_t cmds_max, tcp_sw_host = iscsi_host_priv(shost); tcp_sw_host->session = session;
- shost->can_queue = session->scsi_cmds_max; if (iscsi_tcp_r2tpool_alloc(session)) goto remove_session; return cls_session; @@ -1000,7 +1005,7 @@ static struct scsi_host_template iscsi_sw_tcp_sht = { .name = "iSCSI Initiator over TCP/IP", .queuecommand = iscsi_queuecommand, .change_queue_depth = scsi_change_queue_depth, - .can_queue = ISCSI_DEF_XMIT_CMDS_MAX - 1, + .can_queue = ISCSI_TOTAL_CMDS_MAX, .sg_tablesize = 4096, .max_sectors = 0xFFFF, .cmd_per_lun = ISCSI_DEF_CMD_PER_LUN,
From: Mike Christie michael.christie@oracle.com
mainline inclusion from mainline-v5.12-rc1 commit c8447e4c2eb77dbb96012ae96e7c83179cecf880 category: bugfix bugzilla: 46895 CVE: NA ---------------------------
If we lose the session then relogin, but the new cmdsn window has shrunk (due to something like an admin changing a setting) we will have the old exp/max_cmdsn values and will never be able to update them. For example, max_cmdsn would be 64, but if on the target the user set the window to be smaller then the target could try to return the max_cmdsn as 32. We will see that new max_cmdsn in the rsp but because it's lower than the old max_cmdsn when the window was larger we will not update it.
So this patch has us reset the window values during session cleanup so they can be updated after a new login.
Link: https://lore.kernel.org/r/20210207044608.27585-8-michael.christie@oracle.com Reviewed-by: Lee Duncan lduncan@suse.com Signed-off-by: Mike Christie michael.christie@oracle.com Signed-off-by: Martin K. Petersen martin.petersen@oracle.com Signed-off-by: yangerkun yangerkun@huawei.com Reviewed-by: Jason Yan yanaijie@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- drivers/scsi/libiscsi.c | 7 +++++++ 1 file changed, 7 insertions(+)
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index 1ea22d49b73c6..ffdc54b292294 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -3331,6 +3331,13 @@ int iscsi_conn_bind(struct iscsi_cls_session *cls_session, session->leadconn = conn; spin_unlock_bh(&session->frwd_lock);
+ /* + * The target could have reduced it's window size between logins, so + * we have to reset max/exp cmdsn so we can see the new values. + */ + spin_lock_bh(&session->back_lock); + session->max_cmdsn = session->exp_cmdsn = session->cmdsn + 1; + spin_unlock_bh(&session->back_lock); /* * Unblock xmitworker(), Login Phase will pass through. */
From: Theodore Ts'o tytso@mit.edu
mainline inclusion from mainline-5.11-rc4 commit 5a3b590d4b2db187faa6f06adc9a53d6199fb1f9 category: bugfix bugzilla: 47374 CVE: NA ---------------------------
When the first file is opened, ext4 samples the mountpoint of the filesystem in 64 bytes of the super block. It does so using strlcpy(), this means that the remaining bytes in the super block string buffer are untouched. If the mount point before had a longer path than the current one, it can be reconstructed.
Consider the case where the fs was mounted to "/media/johnjdeveloper" and later to "/". The super block buffer then contains "/\x00edia/johnjdeveloper".
This case was seen in the wild and caused confusion how the name of a developer ands up on the super block of a filesystem used in production...
Fix this by using strncpy() instead of strlcpy(). The superblock field is defined to be a fixed-size char array, and it is already marked using __nonstring in fs/ext4/ext4.h. The consumer of the field in e2fsprogs already assumes that in the case of a 64+ byte mount path, that s_last_mounted will not be NUL terminated.
Link: https://lore.kernel.org/r/X9ujIOJG/HqMr88R@mit.edu Reported-by: Richard Weinberger richard@nod.at Signed-off-by: Theodore Ts'o tytso@mit.edu Cc: stable@kernel.org Signed-off-by: Zhang Yi yi.zhang@huawei.com Reviewed-by: Ye bin yebin10@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- fs/ext4/file.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/fs/ext4/file.c b/fs/ext4/file.c index 4e791056a860b..21b0fc0d6ffed 100644 --- a/fs/ext4/file.c +++ b/fs/ext4/file.c @@ -433,7 +433,7 @@ static int ext4_sample_last_mounted(struct super_block *sb, if (err) goto out_journal; lock_buffer(sbi->s_sbh); - strlcpy(sbi->s_es->s_last_mounted, cp, + strncpy(sbi->s_es->s_last_mounted, cp, sizeof(sbi->s_es->s_last_mounted)); ext4_superblock_csum_set(sb); unlock_buffer(sbi->s_sbh);
From: Tang Yizhou tangyizhou@huawei.com
ascend inclusion category: bugfix bugzilla: 51352 CVE: NA
-------------------------------------------------
A task without adding to an sp group (such as only calls sp_k2u_to_task) should be shown in /proc/sharepool/proc_stat correctly.
Signed-off-by: Tang Yizhou tangyizhou@huawei.com Reviewed-by: Ding Tianhong dingtianhong@huawei.com Reviewed-by: Kefeng Wang wangkefeng.wang@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- mm/share_pool.c | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-)
diff --git a/mm/share_pool.c b/mm/share_pool.c index c6eacb89dc23b..512fe1f20242c 100644 --- a/mm/share_pool.c +++ b/mm/share_pool.c @@ -2766,15 +2766,17 @@ static int idr_proc_stat_cb(int id, void *p, void *data) */ long sp_alloc_nsize, non_sp_res, sp_res, non_sp_shm;
+ anon = get_mm_counter(mm, MM_ANONPAGES); + file = get_mm_counter(mm, MM_FILEPAGES); + shmem = get_mm_counter(mm, MM_SHMEMPAGES); + total_rss = anon + file + shmem; + /* - * a task which is the target of k2u(to task) but without adding to a - * sp group should be handled correctly. - * No longer mmget_not_zero(mm) but a process (k2u to task) may have - * problem + * a task without adding to an sp group should be handled correctly. */ spg = __sp_find_spg(id, SPG_ID_DEFAULT); if (!spg) - goto out; + goto non_spg;
down_read(&spg->rw_lock); if (!spg_valid(spg)) { @@ -2789,10 +2791,6 @@ static int idr_proc_stat_cb(int id, void *p, void *data) up_read(&spg->rw_lock); sp_group_drop(spg);
- anon = get_mm_counter(mm, MM_ANONPAGES); - file = get_mm_counter(mm, MM_FILEPAGES); - shmem = get_mm_counter(mm, MM_SHMEMPAGES); - total_rss = anon + file + shmem; /* * Statistics of RSS has a maximum 64 pages deviation (256KB). * Please check_sync_rss_stat(). @@ -2813,8 +2811,15 @@ static int idr_proc_stat_cb(int id, void *p, void *data) sp_res, non_sp_res, page2kb(mm->total_vm), page2kb(total_rss), page2kb(shmem), non_sp_shm); + return 0;
-out: +non_spg: + seq_printf(seq, "%-8d %-8c %-9d %-9ld %-9d %-10ld %-8ld %-7ld %-7ld %-10ld\n", + id, '-', 0, + byte2kb(atomic64_read(&stat->k2u_size)), + 0, page2kb(total_rss), + page2kb(mm->total_vm), page2kb(total_rss), + page2kb(shmem), page2kb(shmem)); return 0; }
From: Tang Yizhou tangyizhou@huawei.com
ascend inclusion category: bugfix bugzilla: 51352 CVE: NA
-------------------------------------------------
Now a process only calls sp_k2u(to task) but not in any sp group will lead to memleak of struct sp_proc_stat, after the process exits.
We should decouple the release of struct sp_group from the release of struct sp_proc_stat.
Signed-off-by: Tang Yizhou tangyizhou@huawei.com Reviewed-by: Ding Tianhong dingtianhong@huawei.com Reviewed-by: Kefeng Wang wangkefeng.wang@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- include/linux/share_pool.h | 4 +- mm/oom_kill.c | 2 +- mm/share_pool.c | 110 +++++++++++++++++++++---------------- 3 files changed, 66 insertions(+), 50 deletions(-)
diff --git a/include/linux/share_pool.h b/include/linux/share_pool.h index b3041654084d6..98629ad0c0c8a 100644 --- a/include/linux/share_pool.h +++ b/include/linux/share_pool.h @@ -171,7 +171,7 @@ extern int sp_register_notifier(struct notifier_block *nb); extern int sp_unregister_notifier(struct notifier_block *nb); extern bool sp_config_dvpp_range(size_t start, size_t size, int device_id, int pid); extern bool is_sharepool_addr(unsigned long addr); -extern struct sp_proc_stat *sp_get_proc_stat(int tgid); +extern struct sp_proc_stat *sp_get_proc_stat_ref(int tgid); extern void sp_proc_stat_drop(struct sp_proc_stat *stat); extern void spa_overview_show(struct seq_file *seq); extern void spg_overview_show(struct seq_file *seq); @@ -371,7 +371,7 @@ static inline bool is_sharepool_addr(unsigned long addr) return false; }
-static inline struct sp_proc_stat *sp_get_proc_stat(int tgid) +static inline struct sp_proc_stat *sp_get_proc_stat_ref(int tgid) { return NULL; } diff --git a/mm/oom_kill.c b/mm/oom_kill.c index b10a38f58a55c..0dbd6d2a31733 100644 --- a/mm/oom_kill.c +++ b/mm/oom_kill.c @@ -426,7 +426,7 @@ static void dump_tasks(struct mem_cgroup *memcg, const nodemask_t *nodemask) }
if (ascend_sp_oom_show()) { - stat = sp_get_proc_stat(task->tgid); + stat = sp_get_proc_stat_ref(task->tgid);
pr_cont("[%7d] %5d %5d %8lu %8lu ", task->pid, from_kuid(&init_user_ns, task_uid(task)), diff --git a/mm/share_pool.c b/mm/share_pool.c index 512fe1f20242c..d99b3a8b3c005 100644 --- a/mm/share_pool.c +++ b/mm/share_pool.c @@ -96,8 +96,19 @@ static struct sp_proc_stat *sp_get_proc_stat_locked(int tgid) struct sp_proc_stat *stat;
stat = idr_find(&sp_stat_idr, tgid); - if (stat) - atomic_inc(&stat->use_count); + + /* maybe NULL or not, we always return it */ + return stat; +} + +/* The caller must hold sp_stat_sem */ +static struct sp_proc_stat *sp_get_proc_stat_ref_locked(int tgid) +{ + struct sp_proc_stat *stat; + + stat = idr_find(&sp_stat_idr, tgid); + if (!stat || !atomic_inc_not_zero(&stat->use_count)) + stat = NULL;
/* maybe NULL or not, we always return it */ return stat; @@ -106,8 +117,6 @@ static struct sp_proc_stat *sp_get_proc_stat_locked(int tgid) /* * The caller must ensure no concurrency problem * for task_struct and mm_struct. - * - * The user must call sp_proc_stat_drop() after use. */ static struct sp_proc_stat *sp_init_proc_stat(struct task_struct *tsk, struct mm_struct *mm) @@ -138,8 +147,7 @@ static struct sp_proc_stat *sp_init_proc_stat(struct task_struct *tsk, return ERR_PTR(-ENOMEM); }
- /* use_count = 2: match with sp_proc_stat_drop */ - atomic_set(&stat->use_count, 2); + atomic_set(&stat->use_count, 1); atomic64_set(&stat->alloc_size, 0); atomic64_set(&stat->k2u_size, 0); stat->tgid = tgid; @@ -159,6 +167,27 @@ static struct sp_proc_stat *sp_init_proc_stat(struct task_struct *tsk, return stat; }
+static struct sp_proc_stat *sp_get_proc_stat(int tgid) +{ + struct sp_proc_stat *stat; + + down_read(&sp_stat_sem); + stat = sp_get_proc_stat_locked(tgid); + up_read(&sp_stat_sem); + return stat; +} + +/* user must call sp_proc_stat_drop() after use */ +struct sp_proc_stat *sp_get_proc_stat_ref(int tgid) +{ + struct sp_proc_stat *stat; + + down_read(&sp_stat_sem); + stat = sp_get_proc_stat_ref_locked(tgid); + up_read(&sp_stat_sem); + return stat; +} + /* statistics of all sp area, protected by sp_area_lock */ struct sp_spa_stat { unsigned int total_num; @@ -750,9 +779,6 @@ int sp_group_add_task(int pid, int spg_id) spin_unlock(&sp_area_lock); up_read(&spg->rw_lock);
- sp_proc_stat_drop(stat); /* match with sp_init_proc_stat */ - - /* double drop when fail: ensure release stat */ if (unlikely(ret)) sp_proc_stat_drop(stat);
@@ -1228,11 +1254,10 @@ int sp_free(unsigned long addr) atomic64_sub(spa->real_size, &kthread_stat.alloc_size); } else { stat = sp_get_proc_stat(current->mm->sp_stat_id); - if (stat) { + if (stat) atomic64_sub(spa->real_size, &stat->alloc_size); - sp_proc_stat_drop(stat); - } else - BUG(); + else + WARN(1, "share pool: %s: null process stat\n", __func__); }
drop_spa: @@ -1478,10 +1503,10 @@ void *sp_alloc(unsigned long size, unsigned long sp_flags, int spg_id)
if (!IS_ERR(p)) { stat = sp_get_proc_stat(current->mm->sp_stat_id); - if (stat) { + if (stat) atomic64_add(size_aligned, &stat->alloc_size); - sp_proc_stat_drop(stat); - } + else + WARN(1, "share pool: %s: null process stat\n", __func__); }
/* this will free spa if mmap failed */ @@ -1776,14 +1801,14 @@ void *sp_make_share_k2u(unsigned long kva, unsigned long size, if (spg_id != SPG_ID_NONE && spg_id != SPG_ID_DEFAULT) { pr_err_ratelimited("share pool: k2task invalid spg id %d\n", spg_id); uva = ERR_PTR(-EINVAL); - goto out_drop_proc_stat; + goto out_put_mm; } spa = sp_alloc_area(size_aligned, sp_flags, NULL, SPA_TYPE_K2TASK, tsk->tgid); if (IS_ERR(spa)) { pr_err_ratelimited("share pool: k2u(task) failed due to alloc spa failure " "(potential no enough virtual memory when -75): %ld\n", PTR_ERR(spa)); uva = spa; - goto out_drop_proc_stat; + goto out_put_mm; }
if (!vmalloc_area_set_flag(spa, kva_aligned, VM_SHAREPOOL)) { @@ -1853,8 +1878,6 @@ void *sp_make_share_k2u(unsigned long kva, unsigned long size, out_drop_spg: if (spg) sp_group_drop(spg); -out_drop_proc_stat: - sp_proc_stat_drop(stat); out_put_mm: mmput(mm); out_put_task: @@ -2273,10 +2296,9 @@ static int sp_unshare_uva(unsigned long uva, unsigned long size, int pid, int sp atomic64_sub(spa->real_size, &kthread_stat.k2u_size); } else { stat = sp_get_proc_stat(current->mm->sp_stat_id); - if (stat) { + if (stat) atomic64_sub(spa->real_size, &stat->k2u_size); - sp_proc_stat_drop(stat); - } else + else WARN(1, "share pool: %s: null process stat\n", __func__); }
@@ -2512,21 +2534,10 @@ __setup("enable_sp_share_k2u_spg", enable_share_k2u_to_group);
/*** Statistical and maintenance functions ***/
-/* user must call sp_proc_stat_drop() after use */ -struct sp_proc_stat *sp_get_proc_stat(int tgid) -{ - struct sp_proc_stat *stat; - - down_read(&sp_stat_sem); - stat = sp_get_proc_stat_locked(tgid); - up_read(&sp_stat_sem); - return stat; -} - static void free_sp_proc_stat(struct sp_proc_stat *stat) { - stat->mm->sp_stat_id = 0; down_write(&sp_stat_sem); + stat->mm->sp_stat_id = 0; idr_remove(&sp_stat_idr, stat->tgid); up_write(&sp_stat_sem); kfree(stat); @@ -2557,7 +2568,7 @@ int proc_sp_group_state(struct seq_file *m, struct pid_namespace *ns, up_read(&spg->rw_lock);
/* eliminate potential ABBA deadlock */ - stat = sp_get_proc_stat(task->mm->sp_stat_id); + stat = sp_get_proc_stat_ref(task->mm->sp_stat_id); if (unlikely(!stat)) { sp_group_drop(spg); return 0; @@ -2986,10 +2997,16 @@ void sp_group_post_exit(struct mm_struct *mm) struct sp_group *spg = mm->sp_group; long alloc_size, k2u_size;
- if (!spg || !enable_ascend_share_pool) + if (!enable_ascend_share_pool || !mm->sp_stat_id) return;
stat = sp_get_proc_stat(mm->sp_stat_id); + if (stat) { + alloc_size = atomic64_read(&stat->alloc_size); + k2u_size = atomic64_read(&stat->k2u_size); + } else + WARN(1, "share pool: can't find sp proc stat\n"); + /* * There are two basic scenarios when a process in the share pool is * exiting but its share pool memory usage is not 0. @@ -3000,25 +3017,24 @@ void sp_group_post_exit(struct mm_struct *mm) * called sp_free(u). Now A's share pool memory usage is a negative * number. Notice B's memory usage will be a positive number. * - * We decide to print a info when seeing both of the scenarios. + * We decide to print an info when seeing both of the scenarios. + * + * A process not in an sp group doesn't need to print because there + * wont't be any memory which is not freed. */ - if (stat) { - alloc_size = atomic64_read(&stat->alloc_size); - k2u_size = atomic64_read(&stat->k2u_size); + if (spg) { if (alloc_size != 0 || k2u_size != 0) pr_info("share pool: process %s(%d) of sp group %d exits. " "It applied %ld aligned KB, k2u shared %ld aligned KB\n", stat->comm, mm->sp_stat_id, mm->sp_group->id, byte2kb(alloc_size), byte2kb(k2u_size));
- /* match with sp_get_proc_stat in THIS function */ - sp_proc_stat_drop(stat); - /* match with sp_init_proc_stat, we expect stat is released after this call */ - sp_proc_stat_drop(stat); + /* match with sp_group_add_task -> find_or_alloc_sp_group */ + sp_group_drop(spg); }
- /* match with sp_group_add_task -> find_or_alloc_sp_group */ - sp_group_drop(spg); + /* match with sp_init_proc_stat, we expect stat is released after this call */ + sp_proc_stat_drop(stat); }
struct page *sp_alloc_pages(struct vm_struct *area, gfp_t mask,