diff options
Diffstat (limited to 'target/linux/layerscape/patches-5.4/701-net-0308-staging-fsl_ppfe-add-support-for-a-char-dev-for-link.patch')
-rw-r--r-- | target/linux/layerscape/patches-5.4/701-net-0308-staging-fsl_ppfe-add-support-for-a-char-dev-for-link.patch | 364 |
1 files changed, 364 insertions, 0 deletions
diff --git a/target/linux/layerscape/patches-5.4/701-net-0308-staging-fsl_ppfe-add-support-for-a-char-dev-for-link.patch b/target/linux/layerscape/patches-5.4/701-net-0308-staging-fsl_ppfe-add-support-for-a-char-dev-for-link.patch new file mode 100644 index 0000000000..c445952222 --- /dev/null +++ b/target/linux/layerscape/patches-5.4/701-net-0308-staging-fsl_ppfe-add-support-for-a-char-dev-for-link.patch @@ -0,0 +1,364 @@ +From a41d4af2ed4b02edca9d7f69955893d407274dc2 Mon Sep 17 00:00:00 2001 +From: Shreyansh Jain <shreyansh.jain@nxp.com> +Date: Wed, 6 Jun 2018 14:19:34 +0530 +Subject: [PATCH] staging: fsl_ppfe: add support for a char dev for link status + +Read and IOCTL support is added. Application would need to open, +read/ioctl the /dev/pfe_us_cdev device. +select is pending as it requires a wait_queue. + +Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com> +Signed-off-by: Calvin Johnson <calvin.johnson@nxp.com> +--- + drivers/staging/fsl_ppfe/Makefile | 3 +- + drivers/staging/fsl_ppfe/pfe_cdev.c | 207 ++++++++++++++++++++++++++++++++++++ + drivers/staging/fsl_ppfe/pfe_cdev.h | 52 +++++++++ + drivers/staging/fsl_ppfe/pfe_eth.c | 14 +++ + drivers/staging/fsl_ppfe/pfe_mod.c | 14 +++ + 5 files changed, 289 insertions(+), 1 deletion(-) + create mode 100644 drivers/staging/fsl_ppfe/pfe_cdev.c + create mode 100644 drivers/staging/fsl_ppfe/pfe_cdev.h + +--- a/drivers/staging/fsl_ppfe/Makefile ++++ b/drivers/staging/fsl_ppfe/Makefile +@@ -16,4 +16,5 @@ pfe-y += pfe_mod.o \ + pfe_sysfs.o \ + pfe_debugfs.o \ + pfe_ls1012a_platform.o \ +- pfe_hal.o ++ pfe_hal.o \ ++ pfe_cdev.o +--- /dev/null ++++ b/drivers/staging/fsl_ppfe/pfe_cdev.c +@@ -0,0 +1,207 @@ ++/* ++ * Copyright 2018 NXP ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see <http://www.gnu.org/licenses/>. ++ */ ++ ++/* @pfe_cdev.c. ++ * Dummy device representing the PFE US in userspace. ++ * - used for interacting with the kernel layer for link status ++ */ ++ ++#include "pfe_cdev.h" ++ ++static int pfe_majno; ++static struct class *pfe_char_class; ++static struct device *pfe_char_dev; ++ ++struct pfe_shared_info link_states[PFE_CDEV_ETH_COUNT]; ++ ++static int pfe_cdev_open(struct inode *inp, struct file *fp) ++{ ++ pr_debug("PFE CDEV device opened.\n"); ++ return 0; ++} ++ ++static ssize_t pfe_cdev_read(struct file *fp, char *buf, ++ size_t len, loff_t *off) ++{ ++ int ret = 0; ++ ++ pr_info("PFE CDEV attempt copying (%lu) size of user.\n", ++ sizeof(link_states)); ++ ++ pr_debug("Dump link_state on screen before copy_to_user\n"); ++ for (; ret < PFE_CDEV_ETH_COUNT; ret++) { ++ pr_debug("%u %u", link_states[ret].phy_id, ++ link_states[ret].state); ++ pr_debug("\n"); ++ } ++ ++ /* Copy to user the value in buffer sized len */ ++ ret = copy_to_user(buf, &link_states, sizeof(link_states)); ++ if (ret != 0) { ++ pr_err("Failed to send (%d)bytes of (%lu) requested.\n", ++ ret, len); ++ return -EFAULT; ++ } ++ ++ /* offset set back to 0 as there is contextual reading offset */ ++ *off = 0; ++ pr_debug("Read of (%lu) bytes performed.\n", sizeof(link_states)); ++ ++ return sizeof(link_states); ++} ++ ++/** ++ * This function is for getting some commands from user through non-IOCTL ++ * channel. It can used to configure the device. ++ * TODO: To be filled in future, if require duplex communication with user ++ * space. ++ */ ++static ssize_t pfe_cdev_write(struct file *fp, const char *buf, ++ size_t len, loff_t *off) ++{ ++ pr_info("PFE CDEV Write operation not supported!\n"); ++ ++ return -EFAULT; ++} ++ ++static int pfe_cdev_release(struct inode *inp, struct file *fp) ++{ ++ pr_info("PFE_CDEV: Device successfully closed\n"); ++ return 0; ++} ++ ++static long pfe_cdev_ioctl(struct file *fp, unsigned int cmd, ++ unsigned long arg) ++{ ++ int ret = -EFAULT; ++ int __user *argp = (int __user *)arg; ++ ++ pr_debug("PFE CDEV IOCTL Called with cmd=(%u)\n", cmd); ++ ++ switch (cmd) { ++ case PFE_CDEV_ETH0_STATE_GET: ++ /* Return an unsigned int (link state) for ETH0 */ ++ *argp = link_states[0].state; ++ pr_debug("Returning state=%d for ETH0\n", *argp); ++ ret = 0; ++ break; ++ case PFE_CDEV_ETH1_STATE_GET: ++ /* Return an unsigned int (link state) for ETH0 */ ++ *argp = link_states[1].state; ++ pr_debug("Returning state=%d for ETH1\n", *argp); ++ ret = 0; ++ break; ++ default: ++ pr_info("Unsupport cmd (%d) for PFE CDEV.\n", cmd); ++ break; ++ }; ++ ++ return ret; ++} ++ ++static unsigned int pfe_cdev_poll(struct file *fp, ++ struct poll_table_struct *wait) ++{ ++ pr_info("PFE CDEV poll method not supported\n"); ++ return 0; ++} ++ ++static const struct file_operations pfe_cdev_fops = { ++ .open = pfe_cdev_open, ++ .read = pfe_cdev_read, ++ .write = pfe_cdev_write, ++ .release = pfe_cdev_release, ++ .unlocked_ioctl = pfe_cdev_ioctl, ++ .poll = pfe_cdev_poll, ++}; ++ ++int pfe_cdev_init(void) ++{ ++ int ret; ++ ++ pr_debug("PFE CDEV initialization begin\n"); ++ ++ /* Register the major number for the device */ ++ pfe_majno = register_chrdev(0, PFE_CDEV_NAME, &pfe_cdev_fops); ++ if (pfe_majno < 0) { ++ pr_err("Unable to register PFE CDEV. PFE CDEV not available\n"); ++ ret = pfe_majno; ++ goto cleanup; ++ } ++ ++ pr_debug("PFE CDEV assigned major number: %d\n", pfe_majno); ++ ++ /* Register the class for the device */ ++ pfe_char_class = class_create(THIS_MODULE, PFE_CLASS_NAME); ++ if (IS_ERR(pfe_char_class)) { ++ pr_err( ++ "Failed to init class for PFE CDEV. PFE CDEV not available.\n"); ++ goto cleanup; ++ } ++ ++ pr_debug("PFE CDEV Class created successfully.\n"); ++ ++ /* Create the device without any parent and without any callback data */ ++ pfe_char_dev = device_create(pfe_char_class, NULL, ++ MKDEV(pfe_majno, 0), NULL, ++ PFE_CDEV_NAME); ++ if (IS_ERR(pfe_char_dev)) { ++ pr_err("Unable to PFE CDEV device. PFE CDEV not available.\n"); ++ ret = PTR_ERR(pfe_char_dev); ++ goto cleanup; ++ } ++ ++ /* Information structure being shared with the userspace */ ++ memset(link_states, 0, sizeof(struct pfe_shared_info) * ++ PFE_CDEV_ETH_COUNT); ++ ++ pr_info("PFE CDEV created: %s\n", PFE_CDEV_NAME); ++ ++ ret = 0; ++ return ret; ++ ++cleanup: ++ if (!IS_ERR(pfe_char_class)) ++ class_destroy(pfe_char_class); ++ ++ if (pfe_majno > 0) ++ unregister_chrdev(pfe_majno, PFE_CDEV_NAME); ++ ++ ret = -EFAULT; ++ return ret; ++} ++ ++void pfe_cdev_exit(void) ++{ ++ if (!IS_ERR(pfe_char_dev)) ++ device_destroy(pfe_char_class, MKDEV(pfe_majno, 0)); ++ ++ if (!IS_ERR(pfe_char_class)) { ++ class_unregister(pfe_char_class); ++ class_destroy(pfe_char_class); ++ } ++ ++ if (pfe_majno > 0) ++ unregister_chrdev(pfe_majno, PFE_CDEV_NAME); ++ ++ /* reset the variables */ ++ pfe_majno = 0; ++ pfe_char_class = NULL; ++ pfe_char_dev = NULL; ++ ++ pr_info("PFE CDEV Removed.\n"); ++} +--- /dev/null ++++ b/drivers/staging/fsl_ppfe/pfe_cdev.h +@@ -0,0 +1,52 @@ ++/* ++ * Copyright 2018 NXP ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see <http://www.gnu.org/licenses/>. ++ */ ++ ++#ifndef _PFE_CDEV_H_ ++#define _PFE_CDEV_H_ ++ ++#include <linux/init.h> ++#include <linux/device.h> ++#include <linux/err.h> ++#include <linux/kernel.h> ++#include <linux/fs.h> ++#include <linux/uaccess.h> ++#include <linux/poll.h> ++ ++#define PFE_CDEV_NAME "pfe_us_cdev" ++#define PFE_CLASS_NAME "ppfe_us" ++ ++/* Extracted from ls1012a_pfe_platform_data, there are 3 interfaces which are ++ * supported by PFE driver. Should be updated if number of eth devices are ++ * changed. ++ */ ++#define PFE_CDEV_ETH_COUNT 3 ++ ++struct pfe_shared_info { ++ uint32_t phy_id; /* Link phy ID */ ++ uint8_t state; /* Has either 0 or 1 */ ++}; ++ ++extern struct pfe_shared_info link_states[PFE_CDEV_ETH_COUNT]; ++ ++/* IOCTL Commands */ ++#define PFE_CDEV_ETH0_STATE_GET 0 ++#define PFE_CDEV_ETH1_STATE_GET 1 ++ ++int pfe_cdev_init(void); ++void pfe_cdev_exit(void); ++ ++#endif /* _PFE_CDEV_H_ */ +--- a/drivers/staging/fsl_ppfe/pfe_eth.c ++++ b/drivers/staging/fsl_ppfe/pfe_eth.c +@@ -55,6 +55,7 @@ + + #include "pfe_mod.h" + #include "pfe_eth.h" ++#include "pfe_cdev.h" + + #define LS1012A_REV_1_0 0x87040010 + +@@ -1160,6 +1161,19 @@ static void pfe_eth_adjust_link(struct n + phy_print_status(phydev); + + spin_unlock_irqrestore(&priv->lock, flags); ++ ++ /* Now, dump the details to the cdev. ++ * XXX: Locking would be required? (uniprocess arch) ++ * Or, maybe move it in spinlock above ++ */ ++ if (us && priv->einfo->gem_id < PFE_CDEV_ETH_COUNT) { ++ pr_debug("Changing link state from (%u) to (%u) for ID=(%u)\n", ++ link_states[priv->einfo->gem_id].state, ++ phydev->link, ++ priv->einfo->gem_id); ++ link_states[priv->einfo->gem_id].phy_id = priv->einfo->gem_id; ++ link_states[priv->einfo->gem_id].state = phydev->link; ++ } + } + + /* pfe_phy_exit +--- a/drivers/staging/fsl_ppfe/pfe_mod.c ++++ b/drivers/staging/fsl_ppfe/pfe_mod.c +@@ -18,6 +18,7 @@ + + #include <linux/dma-mapping.h> + #include "pfe_mod.h" ++#include "pfe_cdev.h" + + unsigned int us; + module_param(us, uint, 0444); +@@ -92,8 +93,18 @@ firmware_init: + if (rc < 0) + goto err_debugfs; + ++ if (us) { ++ /* Creating a character device */ ++ rc = pfe_cdev_init(); ++ if (rc < 0) ++ goto err_cdev; ++ } ++ + return 0; + ++err_cdev: ++ pfe_debugfs_exit(pfe); ++ + err_debugfs: + pfe_sysfs_exit(pfe); + +@@ -129,6 +140,9 @@ int pfe_remove(struct pfe *pfe) + { + pr_info("%s\n", __func__); + ++ if (us) ++ pfe_cdev_exit(); ++ + pfe_debugfs_exit(pfe); + + pfe_sysfs_exit(pfe); |