Jelajahi Sumber

qcacld-3.0: Create a new ndo callback function for netdev ops

For Kernel 5.15+, the ifr_data variable will no longer be included
in the ifreq struct and would need to be passed as a separate argument.
Thus, create a new ndo callback function ndo_siocdevprivate() that is
used for Kernel 5.15+.

Change-Id: Iccb5b5f5edd650b4a604e15b787d3b927eabc6b5
CRs-Fixed: 3157820
Alan Chen 3 tahun lalu
induk
melakukan
6bb4ffe1c9

+ 2 - 1
core/hdd/inc/wlan_hdd_ftm.h

@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2013-2018 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for
  * any purpose with or without fee is hereby granted, provided that the
@@ -35,7 +36,7 @@ struct hdd_context;
 
 #if  defined(QCA_WIFI_FTM)
 int wlan_hdd_qcmbr_unified_ioctl(struct hdd_adapter *adapter,
-				 struct ifreq *ifr);
+				 void __user *data);
 int hdd_update_cds_config_ftm(struct hdd_context *hdd_ctx);
 #else
 static inline int hdd_update_cds_config_ftm(struct hdd_context *hdd_ctx)

+ 8 - 8
core/hdd/src/wlan_hdd_ftm.c

@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2012-2020 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for
  * any purpose with or without fee is hereby granted, provided that the
@@ -85,11 +86,11 @@ int hdd_update_cds_config_ftm(struct hdd_context *hdd_ctx)
 /**
  * wlan_hdd_qcmbr_ioctl() - Standard QCMBR ioctl handler
  * @adapter: adapter upon which the ioctl was received
- * @ifr: the ioctl request
+ * @data: pointer to the raw command data in the ioctl request
  *
  * Return: 0 on success, non-zero on error
  */
-static int wlan_hdd_qcmbr_ioctl(struct hdd_adapter *adapter, struct ifreq *ifr)
+static int wlan_hdd_qcmbr_ioctl(struct hdd_adapter *adapter, void __user *data)
 {
 	int ret, cmd;
 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
@@ -98,11 +99,11 @@ static int wlan_hdd_qcmbr_ioctl(struct hdd_adapter *adapter, struct ifreq *ifr)
 	if (ret)
 		return ret;
 
-	if (get_user(cmd, (int *)ifr->ifr_data) != 0)
+	if (get_user(cmd, (int *)data) != 0)
 		return QDF_STATUS_E_FAILURE;
 
 	ret = wlan_ioctl_ftm_testmode_cmd(hdd_ctx->pdev, cmd,
-				(uint8_t *)ifr->ifr_data + sizeof(cmd));
+				(uint8_t *)data + sizeof(cmd));
 
 	return ret;
 }
@@ -110,16 +111,15 @@ static int wlan_hdd_qcmbr_ioctl(struct hdd_adapter *adapter, struct ifreq *ifr)
 /**
  * wlan_hdd_qcmbr_unified_ioctl() - Unified QCMBR ioctl handler
  * @adapter: adapter upon which the ioctl was received
- * @ifr: the ioctl request
+ * @data: pointer to the raw command data in the ioctl request
  *
  * Return: 0 on success, non-zero on error
  */
-int wlan_hdd_qcmbr_unified_ioctl(struct hdd_adapter *adapter,
-				 struct ifreq *ifr)
+int wlan_hdd_qcmbr_unified_ioctl(struct hdd_adapter *adapter, void __user *data)
 {
 	int ret;
 
-	ret = wlan_hdd_qcmbr_ioctl(adapter, ifr);
+	ret = wlan_hdd_qcmbr_ioctl(adapter, data);
 
 	return ret;
 }

+ 5 - 0
core/hdd/src/wlan_hdd_hostapd.c

@@ -3871,9 +3871,14 @@ const struct net_device_ops net_ops_struct = {
 	.ndo_tx_timeout = hdd_softap_tx_timeout,
 	.ndo_get_stats = hdd_get_stats,
 	.ndo_set_mac_address = hdd_hostapd_set_mac_address,
+#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 15, 0)
 	.ndo_do_ioctl = hdd_ioctl,
+#endif
 	.ndo_change_mtu = hdd_hostapd_change_mtu,
 	.ndo_select_queue = hdd_select_queue,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0)
+	.ndo_siocdevprivate = hdd_dev_private_ioctl,
+#endif
 };
 
 #ifdef WLAN_FEATURE_TSF_PTP

+ 30 - 23
core/hdd/src/wlan_hdd_ioctl.c

@@ -7069,7 +7069,8 @@ exit:
 }
 
 #ifdef CONFIG_COMPAT
-static int hdd_driver_compat_ioctl(struct hdd_adapter *adapter, struct ifreq *ifr)
+static int hdd_driver_compat_ioctl(struct hdd_adapter *adapter,
+				   void __user *data)
 {
 	struct {
 		compat_uptr_t buf;
@@ -7083,7 +7084,7 @@ static int hdd_driver_compat_ioctl(struct hdd_adapter *adapter, struct ifreq *if
 	 * Note that adapter and ifr have already been verified by caller,
 	 * and HDD context has also been validated
 	 */
-	if (copy_from_user(&compat_priv_data, ifr->ifr_data,
+	if (copy_from_user(&compat_priv_data, data,
 			   sizeof(compat_priv_data))) {
 		ret = -EFAULT;
 		goto exit;
@@ -7096,14 +7097,15 @@ exit:
 	return ret;
 }
 #else /* CONFIG_COMPAT */
-static int hdd_driver_compat_ioctl(struct hdd_adapter *adapter, struct ifreq *ifr)
+static int hdd_driver_compat_ioctl(struct hdd_adapter *adapter,
+				   void __user *data)
 {
 	/* will never be invoked */
 	return 0;
 }
 #endif /* CONFIG_COMPAT */
 
-static int hdd_driver_ioctl(struct hdd_adapter *adapter, struct ifreq *ifr)
+static int hdd_driver_ioctl(struct hdd_adapter *adapter, void __user *data)
 {
 	struct hdd_priv_data priv_data;
 	int ret = 0;
@@ -7112,7 +7114,7 @@ static int hdd_driver_ioctl(struct hdd_adapter *adapter, struct ifreq *ifr)
 	 * Note that adapter and ifr have already been verified by caller,
 	 * and HDD context has also been validated
 	 */
-	if (copy_from_user(&priv_data, ifr->ifr_data, sizeof(priv_data)))
+	if (copy_from_user(&priv_data, data, sizeof(priv_data)))
 		ret = -EFAULT;
 	else
 		ret = hdd_driver_command(adapter, &priv_data);
@@ -7123,7 +7125,7 @@ static int hdd_driver_ioctl(struct hdd_adapter *adapter, struct ifreq *ifr)
 /**
  * __hdd_ioctl() - ioctl handler for wlan network interfaces
  * @dev: device upon which the ioctl was received
- * @ifr: ioctl request information
+ * @data: pointer to the raw command data in the ioctl request
  * @cmd: ioctl command
  *
  * This function does initial processing of wlan device ioctls.
@@ -7138,7 +7140,7 @@ static int hdd_driver_ioctl(struct hdd_adapter *adapter, struct ifreq *ifr)
  *
  * Return: 0 on success, non-zero on error
  */
-static int __hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+static int __hdd_ioctl(struct net_device *dev, void __user *data, int cmd)
 {
 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
 	struct hdd_context *hdd_ctx;
@@ -7152,7 +7154,7 @@ static int __hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 		goto exit;
 	}
 
-	if ((!ifr) || (!ifr->ifr_data)) {
+	if (!data) {
 		hdd_err("invalid data cmd: %d", cmd);
 		ret = -EINVAL;
 		goto exit;
@@ -7160,7 +7162,7 @@ static int __hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 #if  defined(QCA_WIFI_FTM) && defined(LINUX_QCMBR)
 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
 		if (SIOCIOCTLTX99 == cmd) {
-			ret = wlan_hdd_qcmbr_unified_ioctl(adapter, ifr);
+			ret = wlan_hdd_qcmbr_unified_ioctl(adapter, data);
 			goto exit;
 		}
 	}
@@ -7174,9 +7176,9 @@ static int __hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 	switch (cmd) {
 	case (SIOCDEVPRIVATE + 1):
 		if (in_compat_syscall())
-			ret = hdd_driver_compat_ioctl(adapter, ifr);
+			ret = hdd_driver_compat_ioctl(adapter, data);
 		else
-			ret = hdd_driver_ioctl(adapter, ifr);
+			ret = hdd_driver_ioctl(adapter, data);
 		break;
 	default:
 		hdd_warn("unknown ioctl %d", cmd);
@@ -7188,17 +7190,6 @@ exit:
 	return ret;
 }
 
-/**
- * hdd_ioctl() - ioctl handler (wrapper) for wlan network interfaces
- * @net_dev: device upon which the ioctl was received
- * @ifr: ioctl request information
- * @cmd: ioctl command
- *
- * This function acts as an SSR-protecting wrapper to __hdd_ioctl()
- * which is where the ioctls are really handled.
- *
- * Return: 0 on success, non-zero on error
- */
 int hdd_ioctl(struct net_device *net_dev, struct ifreq *ifr, int cmd)
 {
 	struct osif_vdev_sync *vdev_sync;
@@ -7208,10 +7199,26 @@ int hdd_ioctl(struct net_device *net_dev, struct ifreq *ifr, int cmd)
 	if (errno)
 		return errno;
 
-	errno = __hdd_ioctl(net_dev, ifr, cmd);
+	errno = __hdd_ioctl(net_dev, ifr->ifr_data, cmd);
 
 	osif_vdev_sync_op_stop(vdev_sync);
 
 	return errno;
 }
 
+int hdd_dev_private_ioctl(struct net_device *dev, struct ifreq *ifr,
+			  void __user *data, int cmd)
+{
+	struct osif_vdev_sync *vdev_sync;
+	int errno;
+
+	errno = osif_vdev_sync_op_start(dev, &vdev_sync);
+	if (errno)
+		return errno;
+
+	errno = __hdd_ioctl(dev, data, cmd);
+
+	osif_vdev_sync_op_stop(vdev_sync);
+
+	return errno;
+}

+ 27 - 0
core/hdd/src/wlan_hdd_ioctl.h

@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2012-2014, 2017-2019, 2020 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for
  * any purpose with or without fee is hereby granted, provided that the
@@ -25,7 +26,33 @@
 
 extern struct sock *cesium_nl_srv_sock;
 
+/**
+ * hdd_ioctl() - ioctl handler (wrapper) for wlan network interfaces
+ * @net_dev: device upon which the ioctl was received
+ * @ifr: ioctl request information
+ * @cmd: ioctl command
+ *
+ * This function acts as an SSR-protecting wrapper to __hdd_ioctl()
+ * which is where the ioctls are really handled.
+ *
+ * Return: 0 on success, non-zero on error
+ */
 int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);
+
+/**
+ * hdd_dev_private_ioctl() - private ioctl handler for wlan network interfaces
+ * @net_dev: device upon which the ioctl was received
+ * @ifr: ioctl request information
+ * @data: pointer to the raw command data in the ioctl request
+ * @cmd: ioctl command
+ *
+ * For Kernel 5.15+, this function acts as an SSR-protecting wrapper
+ * to __hdd_ioctl(), which is where the ioctls are really handled.
+ *
+ * Return: 0 on success, non-zero on error
+ */
+int hdd_dev_private_ioctl(struct net_device *dev, struct ifreq *ifr,
+			  void __user *data, int cmd);
 int wlan_hdd_set_mc_rate(struct hdd_adapter *adapter, int target_rate);
 
 /**

+ 5 - 0
core/hdd/src/wlan_hdd_main.c

@@ -6045,10 +6045,15 @@ static const struct net_device_ops wlan_drv_ops = {
 	.ndo_set_features = hdd_set_features,
 	.ndo_tx_timeout = hdd_tx_timeout,
 	.ndo_get_stats = hdd_get_stats,
+#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 15, 0)
 	.ndo_do_ioctl = hdd_ioctl,
+#endif
 	.ndo_set_mac_address = hdd_set_mac_address,
 	.ndo_select_queue = hdd_select_queue,
 	.ndo_set_rx_mode = hdd_set_multicast_list,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0)
+	.ndo_siocdevprivate = hdd_dev_private_ioctl,
+#endif
 };
 
 #ifdef FEATURE_MONITOR_MODE_SUPPORT