| /************************************************************************ |
| * Copyright (C) 2010, Marvell Technology Group Ltd. |
| * All Rights Reserved. |
| * |
| * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Marvell Technology Group; |
| * the contents of this file may not be disclosed to third parties, copied |
| * or duplicated in any form, in whole or in part, without the prior |
| * written permission of Marvell Technology Group. |
| * |
| ********************************************************************************* |
| * Marvell GPL License Option |
| * |
| * If you received this File from Marvell, you may opt to use, redistribute and/or |
| * modify this File in accordance with the terms and conditions of the General |
| * Public License Version 2, June 1991 (the "GPL License"), a copy of which is |
| * available along with the File in the license.txt file or by writing to the Free |
| * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or |
| * on the worldwide web at http://www.gnu.org/licenses/gpl.txt. |
| * |
| * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED |
| * WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY |
| * DISCLAIMED. The GPL License provides additional details about this warranty |
| * disclaimer. |
| * |
| ********************************************************************************* |
| * mv_cust_dev.c |
| * |
| * DESCRIPTION: |
| * |
| * |
| *******************************************************************************/ |
| |
| #include <linux/kernel.h> |
| #include <linux/module.h> |
| #include <linux/version.h> |
| #include <linux/delay.h> |
| #include <linux/wait.h> |
| #include <linux/mutex.h> |
| #include <linux/spinlock.h> |
| #include <linux/poll.h> |
| #include <linux/clk.h> |
| #include <linux/fs.h> |
| #include <linux/vmalloc.h> |
| #include <linux/cdev.h> |
| #include <linux/device.h> |
| #include <linux/miscdevice.h> |
| |
| #include "mv_cust_dev.h" |
| #include "mv_cust_netdev.h" |
| #include "mv_cust_flow_map.h" |
| #include "mv_cust_mng_if.h" |
| |
| |
| /* Used to prevent multiple access to device */ |
| static int mvcust_device_open = 0; |
| static struct miscdevice mvcust_misc_dev; |
| |
| /******************************************************************************* |
| ** |
| ** mvcust_dev_open |
| ** ___________________________________________________________________________ |
| ** |
| ** DESCRIPTION: The function execute device open actions |
| ** |
| ** PARAMETERS: |
| ** |
| ** |
| ** |
| ** |
| ** OUTPUTS: None |
| ** |
| ** RETURNS: (0) |
| ** |
| *******************************************************************************/ |
| static int mvcust_dev_open(struct inode *inode, struct file *file) |
| { |
| MVCUST_DEBUG_PRINT("Enter"); |
| |
| // if (mvcust_device_open > 0) |
| // return -EBUSY; |
| |
| mvcust_device_open++; |
| |
| return 0; |
| } |
| |
| /******************************************************************************* |
| ** |
| ** mvcust_dev_release |
| ** ___________________________________________________________________________ |
| ** |
| ** DESCRIPTION: The function execute device release actions |
| ** |
| ** PARAMETERS: |
| ** |
| ** |
| ** |
| ** |
| ** OUTPUTS: None |
| ** |
| ** RETURNS: (0) |
| ** |
| *******************************************************************************/ |
| static int mvcust_dev_release(struct inode *inode, struct file *file) |
| { |
| MVCUST_DEBUG_PRINT("Enter"); |
| |
| // if (mvcust_device_open > 0) |
| // mvcust_device_open--; |
| |
| return 0; |
| } |
| |
| /******************************************************************************* |
| ** |
| ** mv_cust_dev_ioctl |
| ** ___________________________________________________________________________ |
| ** |
| ** DESCRIPTION: The function execute IO commands |
| ** |
| ** PARAMETERS: struct inode *inode |
| ** struct file *filp |
| ** unsigned int cmd |
| ** unsigned long arg |
| ** |
| ** OUTPUTS: None |
| ** |
| ** RETURNS: (0) |
| ** |
| *******************************************************************************/ |
| static int mvcust_dev_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) |
| { |
| mv_cust_ioctl_omci_set_t cust_omci_set; |
| mv_cust_ioctl_llid_set_t cust_llid_set; |
| mv_cust_ioctl_flow_map_t cust_flow_map; |
| mv_cust_ioctl_dscp_map_t cust_dscp_map; |
| mv_cust_ioctl_app_etype_t cust_app_etype; |
| int enable; |
| int rc; |
| |
| int ret = -EINVAL; |
| |
| MVCUST_DEBUG_PRINT("Enter"); |
| |
| switch(cmd) |
| { |
| case MV_CUST_IOCTL_OMCI_SET: |
| |
| if(copy_from_user(&cust_omci_set, (mv_cust_ioctl_omci_set_t*)arg, sizeof(mv_cust_ioctl_omci_set_t))) |
| { |
| MVCUST_ERR_PRINT("copy_from_user failed\n"); |
| goto ioctlErr; |
| } |
| |
| rc = mv_cust_omci_set(cust_omci_set.tcont, cust_omci_set.txq, cust_omci_set.gemport, cust_omci_set.keep_rx_mh); |
| if (rc != 0) { |
| MVCUST_ERR_PRINT("mv_cust_omci_set failed\n"); |
| } |
| ret = 0; |
| break; |
| |
| case MV_CUST_IOCTL_OMCI_ENABLE: |
| |
| if(copy_from_user(&enable, (int *)arg, sizeof(int))) |
| { |
| MVCUST_ERR_PRINT("copy_from_user failed\n"); |
| goto ioctlErr; |
| } |
| mv_cust_app_flag_set(MV_CUST_APP_TYPE_OMCI, enable); |
| ret = 0; |
| break; |
| |
| case MV_CUST_IOCTL_EOAM_ENABLE: |
| |
| if(copy_from_user(&enable, (int *)arg, sizeof(int))) |
| { |
| MVCUST_ERR_PRINT("copy_from_user failed\n"); |
| goto ioctlErr; |
| } |
| mv_cust_app_flag_set(MV_CUST_APP_TYPE_OAM, enable); |
| ret = 0; |
| break; |
| |
| case MV_CUST_IOCTL_EOAM_LLID_SET: |
| if(copy_from_user(&cust_llid_set, (int *)arg, sizeof(mv_cust_ioctl_llid_set_t))) |
| { |
| MVCUST_ERR_PRINT("copy_from_user failed\n"); |
| goto ioctlErr; |
| } |
| |
| mv_cust_eoam_llid_set(cust_llid_set.llid, &(cust_llid_set.llid_mac[0]), cust_llid_set.txq); |
| ret = 0; |
| break; |
| |
| case MV_CUST_IOCTL_MAP_RULE_SET: |
| if(copy_from_user(&cust_flow_map, (mv_cust_ioctl_flow_map_t *)arg, sizeof(mv_cust_ioctl_flow_map_t))) |
| { |
| MVCUST_ERR_PRINT("copy_from_user failed\n"); |
| goto ioctlErr; |
| } |
| |
| ret = mv_cust_map_rule_set(&cust_flow_map); |
| break; |
| |
| case MV_CUST_IOCTL_DSCP_MAP_SET: |
| if(copy_from_user(&cust_dscp_map, (mv_cust_ioctl_dscp_map_t *)arg, sizeof(mv_cust_ioctl_dscp_map_t))) |
| { |
| MVCUST_ERR_PRINT("copy_from_user failed\n"); |
| goto ioctlErr; |
| } |
| |
| ret = mv_cust_dscp_map_set(&cust_dscp_map.dscp_map); |
| break; |
| |
| case MV_CUST_IOCTL_MAP_RULE_DEL: |
| if(copy_from_user(&cust_flow_map, (mv_cust_ioctl_flow_map_t *)arg, sizeof(mv_cust_ioctl_flow_map_t))) |
| { |
| MVCUST_ERR_PRINT("copy_from_user failed\n"); |
| goto ioctlErr; |
| } |
| |
| ret = mv_cust_map_rule_del((uint16_t)cust_flow_map.vid, (uint8_t)cust_flow_map.pbits, cust_flow_map.dir); |
| break; |
| |
| case MV_CUST_IOCTL_DSCP_MAP_DEL: |
| |
| ret = mv_cust_dscp_map_del(); |
| break; |
| |
| case MV_CUST_IOCTL_MAP_RULE_CLEAR: |
| |
| ret = mv_cust_map_rule_clear(); |
| break; |
| |
| case MV_CUST_IOCTL_TAG_MAP_RULE_GET: |
| if(copy_from_user(&cust_flow_map, (mv_cust_ioctl_flow_map_t *)arg, sizeof(mv_cust_ioctl_flow_map_t))) |
| { |
| MVCUST_ERR_PRINT("copy_from_user failed\n"); |
| goto ioctlErr; |
| } |
| |
| ret = mv_cust_tag_map_rule_get(&cust_flow_map); |
| |
| if(ret != MV_CUST_OK) |
| goto ioctlErr; |
| |
| if(copy_to_user((mv_cust_ioctl_flow_map_t*)arg, &cust_flow_map, sizeof(mv_cust_ioctl_flow_map_t))) |
| { |
| printk(KERN_ERR "ERROR: (%s:%d) copy_to_user failed\n", __FUNCTION__, __LINE__); |
| goto ioctlErr; |
| } |
| break; |
| |
| case MV_CUST_IOCTL_UNTAG_MAP_RULE_GET: |
| if(copy_from_user(&cust_flow_map, (mv_cust_ioctl_flow_map_t *)arg, sizeof(mv_cust_ioctl_flow_map_t))) |
| { |
| MVCUST_ERR_PRINT("copy_from_user failed\n"); |
| goto ioctlErr; |
| } |
| |
| ret = mv_cust_untag_map_rule_get(&cust_flow_map); |
| |
| if(ret != MV_CUST_OK) |
| goto ioctlErr; |
| |
| if(copy_to_user((mv_cust_ioctl_flow_map_t*)arg, &cust_flow_map, sizeof(mv_cust_ioctl_flow_map_t))) |
| { |
| printk(KERN_ERR "ERROR: (%s:%d) copy_to_user failed\n", __FUNCTION__, __LINE__); |
| goto ioctlErr; |
| } |
| break; |
| |
| case MV_CUST_IOCTL_APP_ETH_TYPE_SET: |
| if(copy_from_user(&cust_app_etype, (mv_cust_ioctl_app_etype_t *)arg, sizeof(mv_cust_ioctl_app_etype_t))) |
| { |
| MVCUST_ERR_PRINT("copy_from_user failed\n"); |
| goto ioctlErr; |
| } |
| |
| mv_cust_app_etype_set(cust_app_etype.app_type, cust_app_etype.eth_type);\ |
| ret = 0; |
| break; |
| |
| default: |
| ret = -EINVAL; |
| } |
| |
| ioctlErr: |
| return(ret); |
| } |
| |
| |
| static const struct file_operations mvcust_dev_fops = |
| { |
| .open = mvcust_dev_open, |
| .release = mvcust_dev_release, |
| .ioctl = mvcust_dev_ioctl, |
| }; |
| |
| /******************************************************************************* |
| ** |
| ** mvcust_dev_init |
| ** ___________________________________________________________________________ |
| ** |
| ** DESCRIPTION: |
| ** |
| ** PARAMETERS: |
| ** |
| ** |
| ** |
| ** |
| ** OUTPUTS: None |
| ** |
| ** RETURNS: (0) |
| ** |
| *******************************************************************************/ |
| int32_t mvcust_dev_init(void) |
| { |
| int rc; |
| |
| MVCUST_DEBUG_PRINT("Enter"); |
| |
| mvcust_misc_dev.minor = MISC_DYNAMIC_MINOR; |
| mvcust_misc_dev.name = MVCUST_DEVICE_NAME; |
| mvcust_misc_dev.fops = &mvcust_dev_fops; |
| |
| rc = misc_register(&mvcust_misc_dev); |
| if (rc != 0) |
| { |
| MVCUST_ERR_PRINT("rc=%d",rc); |
| return rc; |
| } |
| |
| rc = mvcust_netdev_init(); |
| if (rc != 0) |
| { |
| MVCUST_ERR_PRINT("rc=%d",rc); |
| return rc; |
| } |
| |
| rc = mvcust_sysfs_init(); |
| if (rc != 0) |
| { |
| MVCUST_ERR_PRINT("rc=%d",rc); |
| return rc; |
| } |
| |
| printk("MVCUST: misc device %s registered with minor: %d\n", MVCUST_DEVICE_NAME, mvcust_misc_dev.minor); |
| return 0; |
| } |
| |
| |
| /******************************************************************************* |
| ** |
| ** mvcust_dev_shutdown |
| ** ___________________________________________________________________________ |
| ** |
| ** DESCRIPTION: |
| ** |
| ** PARAMETERS: |
| ** |
| ** |
| ** |
| ** |
| ** OUTPUTS: None |
| ** |
| ** RETURNS: (0) |
| ** |
| *******************************************************************************/ |
| void mvcust_dev_shutdown(void) |
| { |
| MVCUST_DEBUG_PRINT("Enter"); |
| |
| mvcust_sysfs_delete(); |
| |
| misc_deregister(&mvcust_misc_dev); |
| } |
| |
| |
| |
| |
| |