211 lines
4.4 KiB
C
Executable file
211 lines
4.4 KiB
C
Executable file
// SPDX-License-Identifier: GPL-2.0
|
|
/*
|
|
* Copyright (c) 2021 Samsung Electronics Co., Ltd.
|
|
* http://www.samsung.com/
|
|
*
|
|
* MODEM TOE device support
|
|
*
|
|
*/
|
|
|
|
#include "modem_toe_device.h"
|
|
#include "dit.h"
|
|
#include "link_device.h"
|
|
|
|
#define TOE_DEV_NAME "umts_toe0"
|
|
|
|
static struct toe_ctrl_t *tc;
|
|
|
|
void toe_set_iod_clat_netdev(struct io_device *iod, void *args)
|
|
{
|
|
struct clat_info *clat = (struct clat_info *) args;
|
|
struct net_device *ndev = NULL;
|
|
#if IS_ENABLED(CONFIG_CPIF_TP_MONITOR)
|
|
struct link_device *ld = get_current_link(iod);
|
|
#endif
|
|
unsigned long flags;
|
|
|
|
if (strncmp(iod->name, clat->ipv6_iface, IFNAMSIZ) != 0)
|
|
return;
|
|
|
|
if (clat->ipv4_iface[0])
|
|
ndev = dev_get_by_name(&init_net, clat->ipv4_iface);
|
|
|
|
if (!clat->ipv4_iface[0] || ndev) {
|
|
spin_lock_irqsave(&iod->clat_lock, flags);
|
|
if (iod->clat_ndev)
|
|
dev_put(iod->clat_ndev);
|
|
|
|
if (ndev)
|
|
ndev->features |= NETIF_F_GRO_FRAGLIST;
|
|
iod->clat_ndev = ndev;
|
|
spin_unlock_irqrestore(&iod->clat_lock, flags);
|
|
|
|
#if IS_ENABLED(CONFIG_CPIF_TP_MONITOR)
|
|
if (iod->clat_ndev) {
|
|
struct mem_link_device *mld = to_mem_link_device(ld);
|
|
|
|
mif_info("set RPS again\n");
|
|
mld->tpmon->reset_data("RPS");
|
|
}
|
|
#endif
|
|
|
|
mif_info("%s clat netdev[%d] ch: %d, iface v6/v4: %s/%s\n",
|
|
(ndev ? "set" : "clear"), clat->clat_index, iod->ch,
|
|
clat->ipv6_iface, clat->ipv4_iface);
|
|
}
|
|
}
|
|
|
|
static int toe_dev_open(struct inode *inode, struct file *filp)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static int toe_dev_release(struct inode *inode, struct file *file)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static unsigned int toe_dev_poll(struct file *filp, struct poll_table_struct *wait)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static ssize_t toe_dev_read(struct file *filp, char *buf, size_t count, loff_t *fpos)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static long toe_dev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
|
|
{
|
|
struct clat_info clat;
|
|
u32 ready, num;
|
|
struct mem_link_device *mld = tc->mld;
|
|
|
|
switch (cmd) {
|
|
case IOCTL_TOE_SET_CLAT_READY:
|
|
if (copy_from_user(&ready, (const void __user *)arg, sizeof(ready)))
|
|
return -EFAULT;
|
|
|
|
tc->clat_hal_ready = (ready ? true : false);
|
|
break;
|
|
case IOCTL_TOE_SET_CLAT_IFACES_NUM:
|
|
if (copy_from_user(&num, (const void __user *)arg, sizeof(num)))
|
|
return -EFAULT;
|
|
|
|
tc->clat_ifaces_num = num;
|
|
break;
|
|
case IOCTL_TOE_SET_CLAT_INFO:
|
|
if (copy_from_user(&clat, (const void __user *)arg, sizeof(struct clat_info)))
|
|
return -EFAULT;
|
|
|
|
if (!tc->set_clat_info || !tc->set_clat_info(mld, &clat))
|
|
return -EINVAL;
|
|
break;
|
|
default:
|
|
mif_err("unknown command: 0x%X\n", cmd);
|
|
return -EINVAL;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static ssize_t status_show(struct device *dev, struct device_attribute *attr, char *buf)
|
|
{
|
|
ssize_t count = 0;
|
|
|
|
count += scnprintf(&buf[count], PAGE_SIZE - count,
|
|
"hal_ready:%d ifaces_num:%d dev_support:%d\n",
|
|
tc->clat_hal_ready, tc->clat_ifaces_num, tc->clat_dev_support);
|
|
|
|
return count;
|
|
}
|
|
|
|
static DEVICE_ATTR_RO(status);
|
|
|
|
static struct attribute *toe_attrs[] = {
|
|
&dev_attr_status.attr,
|
|
NULL,
|
|
};
|
|
|
|
static const struct attribute_group toe_group = {
|
|
.attrs = toe_attrs,
|
|
.name = "toe",
|
|
};
|
|
|
|
static const struct file_operations toe_dev_fops = {
|
|
.owner = THIS_MODULE,
|
|
.open = toe_dev_open,
|
|
.poll = toe_dev_poll,
|
|
.read = toe_dev_read,
|
|
.release = toe_dev_release,
|
|
.compat_ioctl = toe_dev_ioctl,
|
|
.unlocked_ioctl = toe_dev_ioctl,
|
|
};
|
|
|
|
static struct miscdevice toe_dev_misc = {
|
|
.minor = MISC_DYNAMIC_MINOR,
|
|
.name = TOE_DEV_NAME,
|
|
.fops = &toe_dev_fops,
|
|
};
|
|
|
|
int toe_dev_init(struct mem_link_device *mld)
|
|
{
|
|
if (unlikely(!tc)) {
|
|
mif_err("toe not created\n");
|
|
return -EPERM;
|
|
}
|
|
|
|
tc->mld = mld;
|
|
tc->clat_dev_support = false;
|
|
tc->set_clat_info = NULL;
|
|
tc->set_iod_clat_netdev = toe_set_iod_clat_netdev;
|
|
|
|
/* Can add the other devs or change the ordering */
|
|
if (dit_support_clat()) {
|
|
tc->clat_dev_support = true;
|
|
tc->set_clat_info = dit_hal_set_clat_info;
|
|
}
|
|
#if IS_ENABLED(CONFIG_CP_PKTPROC_CLAT)
|
|
else {
|
|
tc->clat_dev_support = true;
|
|
tc->set_clat_info = shmem_ap2cp_write_clatinfo;
|
|
}
|
|
#endif
|
|
mld->tc = tc;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int toe_dev_create(struct platform_device *pdev)
|
|
{
|
|
struct device *dev = &pdev->dev;
|
|
int ret = 0;
|
|
|
|
tc = devm_kzalloc(dev, sizeof(struct toe_ctrl_t), GFP_KERNEL);
|
|
if (!tc) {
|
|
mif_err("toe ctrl alloc failed\n");
|
|
return -ENOMEM;
|
|
}
|
|
|
|
ret = sysfs_create_group(&dev->kobj, &toe_group);
|
|
if (ret != 0) {
|
|
mif_err("sysfs_create_group() error %d\n", ret);
|
|
goto error;
|
|
}
|
|
|
|
ret = misc_register(&toe_dev_misc);
|
|
if (ret) {
|
|
mif_err("misc register error\n");
|
|
goto error;
|
|
}
|
|
|
|
return 0;
|
|
|
|
error:
|
|
if (tc) {
|
|
devm_kfree(dev, tc);
|
|
tc = NULL;
|
|
}
|
|
|
|
return ret;
|
|
}
|