kernel_samsung_a53x/drivers/soc/samsung/cpif/modem_toe_device.c
2024-06-15 16:02:09 -03:00

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;
}