Clone of https://github.com/NixOS/nixpkgs.git (to stress-test knotserver)
at fix-function-merge 214 lines 6.0 kB view raw
1From 34d611f2dcf7d34db2cb413cc7b4f86f3706fec6 Mon Sep 17 00:00:00 2001 2From: Joan Bruguera <joanbrugueram@gmail.com> 3Date: Tue, 13 Oct 2020 19:35:55 +0200 4Subject: [PATCH 11/16] linuxPackages.broadcom_sta: fix build for kernel 5.9+ 5 6Get rid of get_fs/set_fs calls in Broadcom WL driver. 7 8Tentative patch for broadcom-wl 6.30.223.271 driver for Linux 5.10 (tested -rc1 up to 5.10.1) 9 10Applies on top of all the patches applied to broadcom-wl-dkms 6.30.223.271-23 on Arch Linux. 11 12NB: Some checks in wlc_ioctl_internal are likely superfluous, 13 but I'm not familiar enough with the driver to remove them with confidence. 14 15See also: https://lwn.net/Articles/722267/ 16 https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=47058bb54b57962b3958a936ddbc59355e4c5504 17 https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=5e6e9852d6f76e01b2e6803c74258afa5b432bc5 18 19Signed-off-by: Joan Bruguera <joanbrugueram@gmail.com> 20--- 21 src/wl/sys/wl_cfg80211_hybrid.c | 26 ++------------------- 22 src/wl/sys/wl_iw.c | 25 ++------------------- 23 src/wl/sys/wl_linux.c | 40 ++++++++++++++++++++++++++++----- 24 src/wl/sys/wl_linux.h | 2 ++ 25 src/wl/sys/wlc_pub.h | 1 + 26 5 files changed, 42 insertions(+), 52 deletions(-) 27 28diff --git a/src/wl/sys/wl_cfg80211_hybrid.c b/src/wl/sys/wl_cfg80211_hybrid.c 29index 4b3298f..c45ad48 100644 30--- a/src/wl/sys/wl_cfg80211_hybrid.c 31+++ b/src/wl/sys/wl_cfg80211_hybrid.c 32@@ -41,6 +41,7 @@ 33 #include <wlioctl.h> 34 #include <proto/802.11.h> 35 #include <wl_cfg80211_hybrid.h> 36+#include <wl_linux.h> 37 38 #define EVENT_TYPE(e) dtoh32((e)->event_type) 39 #define EVENT_FLAGS(e) dtoh16((e)->flags) 40@@ -442,30 +443,7 @@ static void key_endian_to_host(struct wl_wsec_key *key) 41 static s32 42 wl_dev_ioctl(struct net_device *dev, u32 cmd, void *arg, u32 len) 43 { 44- struct ifreq ifr; 45- struct wl_ioctl ioc; 46- mm_segment_t fs; 47- s32 err = 0; 48- 49- BUG_ON(len < sizeof(int)); 50- 51- memset(&ioc, 0, sizeof(ioc)); 52- ioc.cmd = cmd; 53- ioc.buf = arg; 54- ioc.len = len; 55- strcpy(ifr.ifr_name, dev->name); 56- ifr.ifr_data = (caddr_t)&ioc; 57- 58- fs = get_fs(); 59- set_fs(KERNEL_DS); 60-#if defined(WL_USE_NETDEV_OPS) 61- err = dev->netdev_ops->ndo_do_ioctl(dev, &ifr, SIOCDEVPRIVATE); 62-#else 63- err = dev->do_ioctl(dev, &ifr, SIOCDEVPRIVATE); 64-#endif 65- set_fs(fs); 66- 67- return err; 68+ return wlc_ioctl_internal(dev, cmd, arg, len); 69 } 70 71 static s32 72diff --git a/src/wl/sys/wl_iw.c b/src/wl/sys/wl_iw.c 73index 9c3c74e..e346b15 100644 74--- a/src/wl/sys/wl_iw.c 75+++ b/src/wl/sys/wl_iw.c 76@@ -37,6 +37,7 @@ typedef const struct si_pub si_t; 77 78 #include <wl_dbg.h> 79 #include <wl_iw.h> 80+#include <wl_linux.h> 81 82 extern bool wl_iw_conn_status_str(uint32 event_type, uint32 status, 83 uint32 reason, char* stringBuf, uint buflen); 84@@ -103,29 +104,7 @@ dev_wlc_ioctl( 85 int len 86 ) 87 { 88- struct ifreq ifr; 89- wl_ioctl_t ioc; 90- mm_segment_t fs; 91- int ret; 92- 93- memset(&ioc, 0, sizeof(ioc)); 94- ioc.cmd = cmd; 95- ioc.buf = arg; 96- ioc.len = len; 97- 98- strcpy(ifr.ifr_name, dev->name); 99- ifr.ifr_data = (caddr_t) &ioc; 100- 101- fs = get_fs(); 102- set_fs(KERNEL_DS); 103-#if defined(WL_USE_NETDEV_OPS) 104- ret = dev->netdev_ops->ndo_do_ioctl(dev, &ifr, SIOCDEVPRIVATE); 105-#else 106- ret = dev->do_ioctl(dev, &ifr, SIOCDEVPRIVATE); 107-#endif 108- set_fs(fs); 109- 110- return ret; 111+ return wlc_ioctl_internal(dev, cmd, arg, len); 112 } 113 114 static int 115diff --git a/src/wl/sys/wl_linux.c b/src/wl/sys/wl_linux.c 116index 646f1d9..26ba9fa 100644 117--- a/src/wl/sys/wl_linux.c 118+++ b/src/wl/sys/wl_linux.c 119@@ -1664,10 +1664,7 @@ wl_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) 120 goto done2; 121 } 122 123- if (segment_eq(get_fs(), KERNEL_DS)) 124- buf = ioc.buf; 125- 126- else if (ioc.buf) { 127+ if (ioc.buf) { 128 if (!(buf = (void *) MALLOC(wl->osh, MAX(ioc.len, WLC_IOCTL_MAXLEN)))) { 129 bcmerror = BCME_NORESOURCE; 130 goto done2; 131@@ -1688,7 +1685,7 @@ wl_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) 132 WL_UNLOCK(wl); 133 134 done1: 135- if (ioc.buf && (ioc.buf != buf)) { 136+ if (ioc.buf) { 137 if (copy_to_user(ioc.buf, buf, ioc.len)) 138 bcmerror = BCME_BADADDR; 139 MFREE(wl->osh, buf, MAX(ioc.len, WLC_IOCTL_MAXLEN)); 140@@ -1701,6 +1698,39 @@ done2: 141 return (OSL_ERROR(bcmerror)); 142 } 143 144+int 145+wlc_ioctl_internal(struct net_device *dev, int cmd, void *buf, int len) 146+{ 147+ wl_info_t *wl; 148+ wl_if_t *wlif; 149+ int bcmerror; 150+ 151+ if (!dev) 152+ return -ENETDOWN; 153+ 154+ wl = WL_INFO(dev); 155+ wlif = WL_DEV_IF(dev); 156+ if (wlif == NULL || wl == NULL || wl->dev == NULL) 157+ return -ENETDOWN; 158+ 159+ bcmerror = 0; 160+ 161+ WL_TRACE(("wl%d: wlc_ioctl_internal: cmd 0x%x\n", wl->pub->unit, cmd)); 162+ 163+ WL_LOCK(wl); 164+ if (!capable(CAP_NET_ADMIN)) { 165+ bcmerror = BCME_EPERM; 166+ } else { 167+ bcmerror = wlc_ioctl(wl->wlc, cmd, buf, len, wlif->wlcif); 168+ } 169+ WL_UNLOCK(wl); 170+ 171+ ASSERT(VALID_BCMERROR(bcmerror)); 172+ if (bcmerror != 0) 173+ wl->pub->bcmerror = bcmerror; 174+ return (OSL_ERROR(bcmerror)); 175+} 176+ 177 static struct net_device_stats* 178 wl_get_stats(struct net_device *dev) 179 { 180diff --git a/src/wl/sys/wl_linux.h b/src/wl/sys/wl_linux.h 181index 5b1048e..c8c1f41 100644 182--- a/src/wl/sys/wl_linux.h 183+++ b/src/wl/sys/wl_linux.h 184@@ -22,6 +22,7 @@ 185 #define _wl_linux_h_ 186 187 #include <wlc_types.h> 188+#include <wlc_pub.h> 189 190 typedef struct wl_timer { 191 struct timer_list timer; 192@@ -187,6 +188,7 @@ extern irqreturn_t wl_isr(int irq, void *dev_id, struct pt_regs *ptregs); 193 extern int __devinit wl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent); 194 extern void wl_free(wl_info_t *wl); 195 extern int wl_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd); 196+extern int wlc_ioctl_internal(struct net_device *dev, int cmd, void *buf, int len); 197 extern struct net_device * wl_netdev_get(wl_info_t *wl); 198 199 #endif 200diff --git a/src/wl/sys/wlc_pub.h b/src/wl/sys/wlc_pub.h 201index 53a98b8..2b5a029 100644 202--- a/src/wl/sys/wlc_pub.h 203+++ b/src/wl/sys/wlc_pub.h 204@@ -24,6 +24,7 @@ 205 206 #include <wlc_types.h> 207 #include <wlc_utils.h> 208+#include <siutils.h> 209 #include "proto/802.11.h" 210 #include "proto/bcmevent.h" 211 212-- 2132.45.1 214