+++ /dev/null
-From 19fa4f2a85d777a8052e869c1b892a2f7556569d Mon Sep 17 00:00:00 2001
-From: Heiner Kallweit <hkallweit1@gmail.com>
-Date: Mon, 8 Apr 2024 20:47:40 +0200
-Subject: r8169: fix LED-related deadlock on module removal
-
-From: Heiner Kallweit <hkallweit1@gmail.com>
-
-commit 19fa4f2a85d777a8052e869c1b892a2f7556569d upstream.
-
-Binding devm_led_classdev_register() to the netdev is problematic
-because on module removal we get a RTNL-related deadlock. Fix this
-by avoiding the device-managed LED functions.
-
-Note: We can safely call led_classdev_unregister() for a LED even
-if registering it failed, because led_classdev_unregister() detects
-this and is a no-op in this case.
-
-Fixes: 18764b883e15 ("r8169: add support for LED's on RTL8168/RTL8101")
-Cc: stable@vger.kernel.org
-Reported-by: Lukas Wunner <lukas@wunner.de>
-Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
-Reviewed-by: Andrew Lunn <andrew@lunn.ch>
-Signed-off-by: David S. Miller <davem@davemloft.net>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- drivers/net/ethernet/realtek/r8169.h | 6 ++--
- drivers/net/ethernet/realtek/r8169_leds.c | 35 +++++++++++++++--------
- drivers/net/ethernet/realtek/r8169_main.c | 8 ++++--
- 3 files changed, 33 insertions(+), 16 deletions(-)
-
-diff --git a/drivers/net/ethernet/realtek/r8169.h b/drivers/net/ethernet/realtek/r8169.h
-index 4c043052198d..00882ffc7a02 100644
---- a/drivers/net/ethernet/realtek/r8169.h
-+++ b/drivers/net/ethernet/realtek/r8169.h
-@@ -73,6 +73,7 @@ enum mac_version {
- };
-
- struct rtl8169_private;
-+struct r8169_led_classdev;
-
- void r8169_apply_firmware(struct rtl8169_private *tp);
- u16 rtl8168h_2_get_adc_bias_ioffset(struct rtl8169_private *tp);
-@@ -84,7 +85,8 @@ void r8169_get_led_name(struct rtl8169_private *tp, int idx,
- char *buf, int buf_len);
- int rtl8168_get_led_mode(struct rtl8169_private *tp);
- int rtl8168_led_mod_ctrl(struct rtl8169_private *tp, u16 mask, u16 val);
--void rtl8168_init_leds(struct net_device *ndev);
-+struct r8169_led_classdev *rtl8168_init_leds(struct net_device *ndev);
- int rtl8125_get_led_mode(struct rtl8169_private *tp, int index);
- int rtl8125_set_led_mode(struct rtl8169_private *tp, int index, u16 mode);
--void rtl8125_init_leds(struct net_device *ndev);
-+struct r8169_led_classdev *rtl8125_init_leds(struct net_device *ndev);
-+void r8169_remove_leds(struct r8169_led_classdev *leds);
-diff --git a/drivers/net/ethernet/realtek/r8169_leds.c b/drivers/net/ethernet/realtek/r8169_leds.c
-index 7c5dc9d0df85..e10bee706bc6 100644
---- a/drivers/net/ethernet/realtek/r8169_leds.c
-+++ b/drivers/net/ethernet/realtek/r8169_leds.c
-@@ -146,22 +146,22 @@ static void rtl8168_setup_ldev(struct r8169_led_classdev *ldev,
- led_cdev->hw_control_get_device = r8169_led_hw_control_get_device;
-
- /* ignore errors */
-- devm_led_classdev_register(&ndev->dev, led_cdev);
-+ led_classdev_register(&ndev->dev, led_cdev);
- }
-
--void rtl8168_init_leds(struct net_device *ndev)
-+struct r8169_led_classdev *rtl8168_init_leds(struct net_device *ndev)
- {
-- /* bind resource mgmt to netdev */
-- struct device *dev = &ndev->dev;
- struct r8169_led_classdev *leds;
- int i;
-
-- leds = devm_kcalloc(dev, RTL8168_NUM_LEDS, sizeof(*leds), GFP_KERNEL);
-+ leds = kcalloc(RTL8168_NUM_LEDS + 1, sizeof(*leds), GFP_KERNEL);
- if (!leds)
-- return;
-+ return NULL;
-
- for (i = 0; i < RTL8168_NUM_LEDS; i++)
- rtl8168_setup_ldev(leds + i, ndev, i);
-+
-+ return leds;
- }
-
- static int rtl8125_led_hw_control_is_supported(struct led_classdev *led_cdev,
-@@ -245,20 +245,31 @@ static void rtl8125_setup_led_ldev(struct r8169_led_classdev *ldev,
- led_cdev->hw_control_get_device = r8169_led_hw_control_get_device;
-
- /* ignore errors */
-- devm_led_classdev_register(&ndev->dev, led_cdev);
-+ led_classdev_register(&ndev->dev, led_cdev);
- }
-
--void rtl8125_init_leds(struct net_device *ndev)
-+struct r8169_led_classdev *rtl8125_init_leds(struct net_device *ndev)
- {
-- /* bind resource mgmt to netdev */
-- struct device *dev = &ndev->dev;
- struct r8169_led_classdev *leds;
- int i;
-
-- leds = devm_kcalloc(dev, RTL8125_NUM_LEDS, sizeof(*leds), GFP_KERNEL);
-+ leds = kcalloc(RTL8125_NUM_LEDS + 1, sizeof(*leds), GFP_KERNEL);
- if (!leds)
-- return;
-+ return NULL;
-
- for (i = 0; i < RTL8125_NUM_LEDS; i++)
- rtl8125_setup_led_ldev(leds + i, ndev, i);
-+
-+ return leds;
-+}
-+
-+void r8169_remove_leds(struct r8169_led_classdev *leds)
-+{
-+ if (!leds)
-+ return;
-+
-+ for (struct r8169_led_classdev *l = leds; l->ndev; l++)
-+ led_classdev_unregister(&l->led);
-+
-+ kfree(leds);
- }
-diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c
-index 6f1e6f386b7b..8a27328eae34 100644
---- a/drivers/net/ethernet/realtek/r8169_main.c
-+++ b/drivers/net/ethernet/realtek/r8169_main.c
-@@ -647,6 +647,8 @@ struct rtl8169_private {
- const char *fw_name;
- struct rtl_fw *rtl_fw;
-
-+ struct r8169_led_classdev *leds;
-+
- u32 ocp_base;
- };
-
-@@ -5044,6 +5046,8 @@ static void rtl_remove_one(struct pci_dev *pdev)
-
- cancel_work_sync(&tp->wk.work);
-
-+ r8169_remove_leds(tp->leds);
-+
- unregister_netdev(tp->dev);
-
- if (tp->dash_type != RTL_DASH_NONE)
-@@ -5501,9 +5505,9 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
-
- if (IS_ENABLED(CONFIG_R8169_LEDS)) {
- if (rtl_is_8125(tp))
-- rtl8125_init_leds(dev);
-+ tp->leds = rtl8125_init_leds(dev);
- else if (tp->mac_version > RTL_GIGA_MAC_VER_06)
-- rtl8168_init_leds(dev);
-+ tp->leds = rtl8168_init_leds(dev);
- }
-
- netdev_info(dev, "%s, %pM, XID %03x, IRQ %d\n",
---
-2.44.0
-
+++ /dev/null
-From c6ff459037b2e35450af2351037eac4c8aca1d6b Mon Sep 17 00:00:00 2001
-From: Paulo Alcantara <pc@manguebit.com>
-Date: Tue, 9 Apr 2024 11:28:59 -0300
-Subject: smb: client: instantiate when creating SFU files
-
-From: Paulo Alcantara <pc@manguebit.com>
-
-commit c6ff459037b2e35450af2351037eac4c8aca1d6b upstream.
-
-In cifs_sfu_make_node(), on success, instantiate rather than leave it
-with dentry unhashed negative to support callers that expect mknod(2)
-to always instantiate.
-
-This fixes the following test case:
-
- mount.cifs //srv/share /mnt -o ...,sfu
- mkfifo /mnt/fifo
- ./xfstests/ltp/growfiles -b -W test -e 1 -u -i 0 -L 30 /mnt/fifo
- ...
- BUG: unable to handle page fault for address: 000000034cec4e58
- #PF: supervisor read access in kernel mode
- #PF: error_code(0x0000) - not-present page
- PGD 0 P4D 0
- Oops: 0000 1 PREEMPT SMP PTI
- CPU: 0 PID: 138098 Comm: growfiles Kdump: loaded Not tainted
- 5.14.0-436.3987_1240945149.el9.x86_64 #1
- Hardware name: Red Hat KVM, BIOS 0.5.1 01/01/2011
- RIP: 0010:_raw_callee_save__kvm_vcpu_is_preempted+0x0/0x20
- Code: e8 15 d9 61 00 e9 63 ff ff ff 41 bd ea ff ff ff e9 58 ff ff ff e8
- d0 71 c0 00 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 <48> 8b 04
- fd 60 2b c1 99 80 b8 90 50 03 00 00 0f 95 c0 c3 cc cc cc
- RSP: 0018:ffffb6a143cf7cf8 EFLAGS: 00010206
- RAX: ffff8a9bc30fb038 RBX: ffff8a9bc666a200 RCX: ffff8a9cc0260000
- RDX: 00000000736f622e RSI: ffff8a9bc30fb038 RDI: 000000007665645f
- RBP: ffffb6a143cf7d70 R08: 0000000000001000 R09: 0000000000000001
- R10: 0000000000000001 R11: 0000000000000000 R12: ffff8a9bc666a200
- R13: 0000559a302a12b0 R14: 0000000000001000 R15: 0000000000000000
- FS: 00007fbed1dbb740(0000) GS:ffff8a9cf0000000(0000)
- knlGS:0000000000000000
- CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
- CR2: 000000034cec4e58 CR3: 0000000128ec6006 CR4: 0000000000770ef0
- DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
- DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
- PKRU: 55555554
- Call Trace:
- <TASK>
- ? show_trace_log_lvl+0x1c4/0x2df
- ? show_trace_log_lvl+0x1c4/0x2df
- ? __mutex_lock.constprop.0+0x5f7/0x6a0
- ? __die_body.cold+0x8/0xd
- ? page_fault_oops+0x134/0x170
- ? exc_page_fault+0x62/0x150
- ? asm_exc_page_fault+0x22/0x30
- ? _pfx_raw_callee_save__kvm_vcpu_is_preempted+0x10/0x10
- __mutex_lock.constprop.0+0x5f7/0x6a0
- ? __mod_memcg_lruvec_state+0x84/0xd0
- pipe_write+0x47/0x650
- ? do_anonymous_page+0x258/0x410
- ? inode_security+0x22/0x60
- ? selinux_file_permission+0x108/0x150
- vfs_write+0x2cb/0x410
- ksys_write+0x5f/0xe0
- do_syscall_64+0x5c/0xf0
- ? syscall_exit_to_user_mode+0x22/0x40
- ? do_syscall_64+0x6b/0xf0
- ? sched_clock_cpu+0x9/0xc0
- ? exc_page_fault+0x62/0x150
- entry_SYSCALL_64_after_hwframe+0x6e/0x76
-
-Cc: stable@vger.kernel.org
-Fixes: 72bc63f5e23a ("smb3: fix creating FIFOs when mounting with "sfu" mount option")
-Suggested-by: Al Viro <viro@zeniv.linux.org.uk>
-Signed-off-by: Paulo Alcantara (Red Hat) <pc@manguebit.com>
-Signed-off-by: Steve French <stfrench@microsoft.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- fs/smb/client/smb2ops.c | 94 ++++++++++++++++++++++++++++--------------------
- 1 file changed, 55 insertions(+), 39 deletions(-)
-
---- a/fs/smb/client/smb2ops.c
-+++ b/fs/smb/client/smb2ops.c
-@@ -5066,68 +5066,84 @@ static int smb2_next_header(struct TCP_S
- return 0;
- }
-
--int cifs_sfu_make_node(unsigned int xid, struct inode *inode,
-- struct dentry *dentry, struct cifs_tcon *tcon,
-- const char *full_path, umode_t mode, dev_t dev)
-+static int __cifs_sfu_make_node(unsigned int xid, struct inode *inode,
-+ struct dentry *dentry, struct cifs_tcon *tcon,
-+ const char *full_path, umode_t mode, dev_t dev)
- {
-- struct cifs_open_info_data buf = {};
- struct TCP_Server_Info *server = tcon->ses->server;
- struct cifs_open_parms oparms;
- struct cifs_io_parms io_parms = {};
- struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
- struct cifs_fid fid;
- unsigned int bytes_written;
-- struct win_dev *pdev;
-+ struct win_dev pdev = {};
- struct kvec iov[2];
- __u32 oplock = server->oplocks ? REQ_OPLOCK : 0;
- int rc;
-
-- if (!S_ISCHR(mode) && !S_ISBLK(mode) && !S_ISFIFO(mode))
-+ switch (mode & S_IFMT) {
-+ case S_IFCHR:
-+ strscpy(pdev.type, "IntxCHR");
-+ pdev.major = cpu_to_le64(MAJOR(dev));
-+ pdev.minor = cpu_to_le64(MINOR(dev));
-+ break;
-+ case S_IFBLK:
-+ strscpy(pdev.type, "IntxBLK");
-+ pdev.major = cpu_to_le64(MAJOR(dev));
-+ pdev.minor = cpu_to_le64(MINOR(dev));
-+ break;
-+ case S_IFIFO:
-+ strscpy(pdev.type, "LnxFIFO");
-+ break;
-+ default:
- return -EPERM;
-+ }
-
-- oparms = (struct cifs_open_parms) {
-- .tcon = tcon,
-- .cifs_sb = cifs_sb,
-- .desired_access = GENERIC_WRITE,
-- .create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR |
-- CREATE_OPTION_SPECIAL),
-- .disposition = FILE_CREATE,
-- .path = full_path,
-- .fid = &fid,
-- };
-+ oparms = CIFS_OPARMS(cifs_sb, tcon, full_path, GENERIC_WRITE,
-+ FILE_CREATE, CREATE_NOT_DIR |
-+ CREATE_OPTION_SPECIAL, ACL_NO_MODE);
-+ oparms.fid = &fid;
-
-- rc = server->ops->open(xid, &oparms, &oplock, &buf);
-+ rc = server->ops->open(xid, &oparms, &oplock, NULL);
- if (rc)
- return rc;
-
-- /*
-- * BB Do not bother to decode buf since no local inode yet to put
-- * timestamps in, but we can reuse it safely.
-- */
-- pdev = (struct win_dev *)&buf.fi;
- io_parms.pid = current->tgid;
- io_parms.tcon = tcon;
-- io_parms.length = sizeof(*pdev);
-- iov[1].iov_base = pdev;
-- iov[1].iov_len = sizeof(*pdev);
-- if (S_ISCHR(mode)) {
-- memcpy(pdev->type, "IntxCHR", 8);
-- pdev->major = cpu_to_le64(MAJOR(dev));
-- pdev->minor = cpu_to_le64(MINOR(dev));
-- } else if (S_ISBLK(mode)) {
-- memcpy(pdev->type, "IntxBLK", 8);
-- pdev->major = cpu_to_le64(MAJOR(dev));
-- pdev->minor = cpu_to_le64(MINOR(dev));
-- } else if (S_ISFIFO(mode)) {
-- memcpy(pdev->type, "LnxFIFO", 8);
-- }
-+ io_parms.length = sizeof(pdev);
-+ iov[1].iov_base = &pdev;
-+ iov[1].iov_len = sizeof(pdev);
-
- rc = server->ops->sync_write(xid, &fid, &io_parms,
- &bytes_written, iov, 1);
- server->ops->close(xid, tcon, &fid);
-- d_drop(dentry);
-- /* FIXME: add code here to set EAs */
-- cifs_free_open_info(&buf);
-+ return rc;
-+}
-+
-+int cifs_sfu_make_node(unsigned int xid, struct inode *inode,
-+ struct dentry *dentry, struct cifs_tcon *tcon,
-+ const char *full_path, umode_t mode, dev_t dev)
-+{
-+ struct inode *new = NULL;
-+ int rc;
-+
-+ rc = __cifs_sfu_make_node(xid, inode, dentry, tcon,
-+ full_path, mode, dev);
-+ if (rc)
-+ return rc;
-+
-+ if (tcon->posix_extensions) {
-+ rc = smb311_posix_get_inode_info(&new, full_path, NULL,
-+ inode->i_sb, xid);
-+ } else if (tcon->unix_ext) {
-+ rc = cifs_get_inode_info_unix(&new, full_path,
-+ inode->i_sb, xid);
-+ } else {
-+ rc = cifs_get_inode_info(&new, full_path, NULL,
-+ inode->i_sb, xid, NULL);
-+ }
-+ if (!rc)
-+ d_instantiate(dentry, new);
- return rc;
- }
-