Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4ce2cf70 authored by Ravinder Konka's avatar Ravinder Konka Committed by Subash Abhinov Kasiviswanathan
Browse files

msm_rmnet_bam: Add support for IOCTL RMNET_IOCTL_DEREGISTER_DEV



msm_rmnet_bam registers platform drivers for multiple BAM_DMUX
channels on startup. The probe and remove events register and
unregister net devices respectively.

In scenarios where MAP protocol is used, these devices are treated
as physical devices and multiple virtual net devices are associated
with them. Multiple BAM_DMUX channels may not be used in such a case.
The unused channels add unnecessary delay during sub system restart.

Implement RMNET_IOCTL_DEREGISTER_DEV which will allow user space
modules to deregister a platform driver for a particular BAM_DMUX
channel.

Change-Id: Id27bff8c59c36b00f4887492575dfb4e7c93198e
Acked-by: default avatarNagarjuna Chaganti <nchagant@qti.qualcomm.com>
Signed-off-by: default avatarRavinder Konka <rkonka@codeaurora.org>
[subashab@codeaurora.org: add blank line after declaration]
Signed-off-by: default avatarSubash Abhinov Kasiviswanathan <subashab@codeaurora.org>
parent 9e219435
Loading
Loading
Loading
Loading
+37 −2
Original line number Diff line number Diff line
@@ -29,6 +29,8 @@
#include <linux/if_arp.h>
#include <linux/msm_rmnet.h>
#include <linux/platform_device.h>
#include <linux/workqueue.h>

#include <net/pkt_sched.h>

#include <soc/qcom/bam_dmux.h>
@@ -88,6 +90,11 @@ struct rmnet_private {
	uint8_t in_reset;
};

struct rmnet_free_bam_work {
	struct work_struct work;
	uint32_t ch_id;
};

#ifdef CONFIG_MSM_RMNET_DEBUG
static unsigned long timeout_us;

@@ -153,6 +160,8 @@ DEVICE_ATTR(timeout, 0664, timeout_show, timeout_store);
static int rmnet_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);
static struct platform_driver bam_rmnet_drivers[BAM_DMUX_NUM_CHANNELS];

static struct net_device *netdevs[BAM_DMUX_NUM_CHANNELS];

static __be16 rmnet_ip_type_trans(struct sk_buff *skb, struct net_device *dev)
{
	__be16 protocol = 0;
@@ -522,12 +531,30 @@ static const struct net_device_ops rmnet_ops_ip = {
	.ndo_validate_addr = 0,
};

static void _rmnet_free_bam_later(struct work_struct *work)
{
	struct rmnet_free_bam_work *fwork;

	fwork = container_of(work, struct rmnet_free_bam_work, work);

	DBG0("%s: unregister_netdev, done", __func__);

	if (bam_rmnet_drivers[fwork->ch_id].remove) {
		platform_driver_unregister(&bam_rmnet_drivers[fwork->ch_id]);
		bam_rmnet_drivers[fwork->ch_id].remove = NULL;
	}

	DBG0("%s: free_netdev, done", __func__);

	kfree(work);
}

static int rmnet_ioctl_extended(struct net_device *dev, struct ifreq *ifr)
{
	struct rmnet_ioctl_extended_s ext_cmd;
	int rc = 0;
	struct rmnet_private *p = netdev_priv(dev);

	struct rmnet_free_bam_work *work;

	rc = copy_from_user(&ext_cmd, ifr->ifr_ifru.ifru_data,
			    sizeof(ext_cmd));
@@ -551,6 +578,15 @@ static int rmnet_ioctl_extended(struct net_device *dev, struct ifreq *ifr)
		strlcpy(ext_cmd.u.if_name, RMNET_BAM_DRIVER_NAME,
			sizeof(ext_cmd.u.if_name));
		break;
	case RMNET_IOCTL_DEREGISTER_DEV:
		work = kmalloc(sizeof(*work), GFP_KERNEL);
		if (!work)
			break;
		INIT_WORK(&work->work, _rmnet_free_bam_later);

		work->ch_id = p->ch_id;
		schedule_work(&work->work);
		break;
	default:
		rc = -EINVAL;
		break;
@@ -721,7 +757,6 @@ static void rmnet_setup(struct net_device *dev)
	dev->watchdog_timeo = 1000; /* 10 seconds? */
}

static struct net_device *netdevs[BAM_DMUX_NUM_CHANNELS];

#ifdef CONFIG_MSM_RMNET_DEBUG
static int rmnet_debug_init(struct net_device *dev)