From b50c338b5ee3529e92cc9bd76b48e2a0bdf84b13 Mon Sep 17 00:00:00 2001 From: Marian Chereji Date: Fri, 19 Apr 2013 17:18:07 +0300 Subject: dpa_offload: Add packet classification component wrapper The wrapper component allows the packet classification offloading driver's API to be accessible from user space via ioctl sys calls. Signed-off-by: Marian Chereji Signed-off-by: Radu Bulie Change-Id: I33110048b995205c7f9ef0f40753f9060789dd18 Reviewed-on: http://git.am.freescale.net:8181/2234 Reviewed-by: Fleming Andrew-AFLEMING Tested-by: Fleming Andrew-AFLEMING diff --git a/drivers/staging/fsl_dpa_offload/dpa_classifier_ioctl.h b/drivers/staging/fsl_dpa_offload/dpa_classifier_ioctl.h new file mode 100644 index 0000000..4aab2d7 --- /dev/null +++ b/drivers/staging/fsl_dpa_offload/dpa_classifier_ioctl.h @@ -0,0 +1,848 @@ + +/* Copyright 2008-2012 Freescale Semiconductor, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Freescale Semiconductor nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * + * ALTERNATIVELY, this software may be distributed under the terms of the + * GNU General Public License ("GPL") as published by the Free Software + * Foundation, either version 2 of that License or (at your option) any + * later version. + * + * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * DPA Classifier Wrapper Application Programming Interface + */ + +#ifndef __DPA_CLASSIFIER_IOCTL_H +#define __DPA_CLASSIFIER_IOCTL_H + + +/* Other includes */ +#include "linux/ioctl.h" +#include + + +#define DPA_CLS_IOC_MAGIC 0xbe + + +struct ioc_dpa_cls_tbl_params { + struct dpa_cls_tbl_params table_params; + int td; +}; + +struct ioc_dpa_cls_tbl_miss_action { + int td; + struct dpa_cls_tbl_action miss_action; +}; + +struct ioc_dpa_cls_tbl_entry_params { + int td; + struct dpa_offload_lookup_key key; + struct dpa_cls_tbl_action action; + int priority; + int entry_id; +}; + +struct ioc_dpa_cls_tbl_entry_mod_by_key { + int td; + struct dpa_offload_lookup_key key; + struct dpa_cls_tbl_entry_mod_params mod_params; +}; + +struct ioc_dpa_cls_tbl_entry_mod_by_ref { + int td; + int entry_id; + struct dpa_cls_tbl_entry_mod_params mod_params; +}; + +struct ioc_dpa_cls_tbl_entry_by_key { + int td; + struct dpa_offload_lookup_key key; +}; + +struct ioc_dpa_cls_tbl_entry_by_ref { + int td; + int entry_id; +}; + +struct ioc_dpa_cls_tbl_lookup_by_key { + int td; + struct dpa_offload_lookup_key key; + struct dpa_cls_tbl_action action; +}; + +struct ioc_dpa_cls_tbl_lookup_by_ref { + int td; + int entry_id; + struct dpa_cls_tbl_action action; +}; + +struct ioc_dpa_cls_tbl_entry_stats_by_key { + int td; + struct dpa_offload_lookup_key key; + struct dpa_cls_tbl_entry_stats stats; +}; + +struct ioc_dpa_cls_tbl_entry_stats_by_ref { + int td; + int entry_id; + struct dpa_cls_tbl_entry_stats stats; +}; + +struct ioc_dpa_cls_hm_remove_params { + struct dpa_cls_hm_remove_params rm_params; + int next_hmd; + int hmd; + struct dpa_cls_hm_remove_resources res; + bool chain_head; + int modify_flags; +}; + +struct ioc_dpa_cls_hm_insert_params { + struct dpa_cls_hm_insert_params ins_params; + int next_hmd; + int hmd; + struct dpa_cls_hm_insert_resources res; + bool chain_head; + int modify_flags; +}; + +struct ioc_dpa_cls_hm_vlan_params { + struct dpa_cls_hm_vlan_params vlan_params; + int next_hmd; + int hmd; + struct dpa_cls_hm_vlan_resources res; + bool chain_head; + int modify_flags; +}; + +struct ioc_dpa_cls_hm_nat_params { + struct dpa_cls_hm_nat_params nat_params; + int next_hmd; + int hmd; + struct dpa_cls_hm_nat_resources res; + bool chain_head; + int modify_flags; +}; + +struct ioc_dpa_cls_hm_update_params { + struct dpa_cls_hm_update_params update_params; + int next_hmd; + int hmd; + struct dpa_cls_hm_update_resources res; + bool chain_head; + int modify_flags; +}; + +struct ioc_dpa_cls_hm_fwd_params { + struct dpa_cls_hm_fwd_params fwd_params; + int next_hmd; + int hmd; + struct dpa_cls_hm_fwd_resources res; + bool chain_head; + int modify_flags; +}; + +struct ioc_dpa_cls_hm_mpls_params { + struct dpa_cls_hm_mpls_params mpls_params; + int next_hmd; + int hmd; + struct dpa_cls_hm_mpls_resources res; + bool chain_head; + int modify_flags; +}; + +struct ioc_dpa_cls_mcast_group_params { + struct dpa_cls_mcast_group_params mcast_grp_params; + int grpd; +}; + +struct ioc_dpa_cls_mcast_import_params { + void *group; + int grpd; +}; + +struct ioc_dpa_cls_mcast_member_params { + int grpd; + struct dpa_cls_tbl_enq_action_desc member_params; + int md; +}; + +struct ioc_dpa_cls_mcast_remove_params { + int grpd; + int md; +}; + + +#ifdef CONFIG_COMPAT + +struct dpa_cls_compat_tbl_params { + compat_uptr_t fm_pcd; + compat_uptr_t cc_node; + compat_uptr_t distribution; + compat_uptr_t classification; + enum dpa_cls_tbl_type type; + enum dpa_cls_tbl_entry_mgmt entry_mgmt; + union { + struct dpa_cls_tbl_hash_params hash_params; + struct dpa_cls_tbl_indexed_params indexed_params; + struct dpa_cls_tbl_exact_match_params exact_match_params; + }; + unsigned int prefilled_entries; +}; + +struct compat_ioc_dpa_cls_tbl_params { + struct dpa_cls_compat_tbl_params table_params; + int td; +}; + +struct dpa_cls_compat_tbl_enq_action_desc { + bool override_fqid; + uint32_t new_fqid; + compat_uptr_t policer_params; + int hmd; + uint8_t new_rel_vsp_id; +}; + +struct dpa_cls_compat_tbl_action { + enum dpa_cls_tbl_action_type type; + bool enable_statistics; + union { + struct dpa_cls_compat_tbl_enq_action_desc enq_params; + struct dpa_cls_tbl_next_table_desc next_table_params; + struct dpa_cls_tbl_mcast_group_desc mcast_params; + }; +}; + +struct compat_ioc_dpa_cls_tbl_miss_action { + int td; + struct dpa_cls_compat_tbl_action miss_action; +}; + +struct compat_ioc_dpa_offld_lookup_key { + compat_uptr_t byte; + compat_uptr_t mask; + uint8_t size; +}; + +struct compat_ioc_dpa_cls_tbl_entry_by_key { + int td; + struct compat_ioc_dpa_offld_lookup_key key; +}; + +struct compat_ioc_dpa_cls_tbl_entry_stats_by_key { + int td; + struct compat_ioc_dpa_offld_lookup_key key; + struct dpa_cls_tbl_entry_stats stats; +}; + +struct compat_ioc_dpa_cls_tbl_entry_params { + int td; + struct compat_ioc_dpa_offld_lookup_key key; + struct dpa_cls_compat_tbl_action action; + int priority; + int entry_id; +}; + +struct dpa_cls_compat_tbl_entry_mod_params { + enum dpa_cls_tbl_modify_type type; + compat_uptr_t key; + compat_uptr_t action; +}; + +struct compat_ioc_dpa_cls_tbl_entry_mod_by_key { + int td; + struct compat_ioc_dpa_offld_lookup_key key; + struct dpa_cls_compat_tbl_entry_mod_params mod_params; +}; + +struct compat_ioc_dpa_cls_tbl_entry_mod_by_ref { + int td; + int entry_id; + struct dpa_cls_compat_tbl_entry_mod_params mod_params; +}; + +struct compat_ioc_dpa_cls_tbl_lookup_by_key { + int td; + struct compat_ioc_dpa_offld_lookup_key key; + struct dpa_cls_compat_tbl_action action; +}; + +struct compat_ioc_dpa_cls_tbl_lookup_by_ref { + int td; + int entry_id; + struct dpa_cls_compat_tbl_action action; +}; + +struct dpa_cls_compat_hm_remove_resources { + compat_uptr_t remove_node; +}; + +struct dpa_cls_compat_hm_remove_params { + enum dpa_cls_hm_remove_type type; + struct dpa_cls_hm_custom_rm_params custom; + compat_uptr_t fm_pcd; +}; + +struct compat_ioc_dpa_cls_hm_remove_params { + struct dpa_cls_compat_hm_remove_params rm_params; + int next_hmd; + int hmd; + struct dpa_cls_compat_hm_remove_resources res; + bool chain_head; + int modify_flags; +}; + +struct dpa_cls_compat_hm_insert_resources { + compat_uptr_t insert_node; +}; + +struct dpa_cls_compat_hm_custom_ins_params { + uint8_t offset; + uint8_t size; + compat_uptr_t data; +}; + +struct dpa_cls_compat_hm_insert_params { + enum dpa_cls_hm_insert_type type; + union { + struct dpa_cls_hm_eth_ins_params eth; + struct dpa_cls_hm_pppoe_ins_params pppoe; + uint16_t ppp_pid; + struct dpa_cls_compat_hm_custom_ins_params custom; + }; + compat_uptr_t fm_pcd; +}; + +struct compat_ioc_dpa_cls_hm_insert_params { + struct dpa_cls_compat_hm_insert_params ins_params; + int next_hmd; + int hmd; + struct dpa_cls_compat_hm_insert_resources res; + bool chain_head; + int modify_flags; +}; + +struct dpa_cls_compat_hm_vlan_params { + enum dpa_cls_hm_vlan_type type; + union { + struct dpa_cls_hm_ingress_vlan_params ingress; + struct dpa_cls_hm_egress_vlan_params egress; + }; + compat_uptr_t fm_pcd; +}; + +struct dpa_cls_compat_hm_vlan_resources { + compat_uptr_t vlan_node; +}; + +struct compat_ioc_dpa_cls_hm_vlan_params { + struct dpa_cls_compat_hm_vlan_params vlan_params; + int next_hmd; + int hmd; + struct dpa_cls_compat_hm_vlan_resources res; + bool chain_head; + int modify_flags; +}; + +struct compat_ipv4_header { + struct iphdr header; + compat_uptr_t options; + unsigned int options_size; +}; + +struct dpa_cls_compat_hm_nat_pt_params { + enum dpa_cls_hm_nat_pt_type type; + + union { + struct compat_ipv4_header ipv4; + struct ipv6_header ipv6; + } new_header; +}; + +struct dpa_cls_compat_hm_nat_params { + int flags; + enum dpa_cls_hm_nat_proto proto; + enum dpa_cls_hm_nat_type type; + union { + struct dpa_cls_hm_traditional_nat_params nat; + struct dpa_cls_compat_hm_nat_pt_params nat_pt; + }; + uint16_t sport; + uint16_t dport; + compat_uptr_t fm_pcd; +}; + +struct dpa_cls_compat_hm_nat_resources { + compat_uptr_t l3_update_node; + compat_uptr_t l4_update_node; +}; + +struct compat_ioc_dpa_cls_hm_nat_params { + struct dpa_cls_compat_hm_nat_params nat_params; + int next_hmd; + int hmd; + struct dpa_cls_compat_hm_nat_resources res; + bool chain_head; + int modify_flags; +}; + +struct dpa_cls_compat_hm_update_params { + int op_flags; + union { + struct compat_ipv4_header new_ipv4_hdr; + struct ipv6_header new_ipv6_hdr; + } replace; + union { + struct dpa_cls_hm_l3_update_params l3; + struct dpa_cls_hm_l4_update_params l4; + } update; + struct dpa_cls_hm_ip_frag_params ip_frag_params; + compat_uptr_t fm_pcd; +}; + +struct dpa_cls_compat_hm_update_resources { + compat_uptr_t update_node; + compat_uptr_t ip_frag_node; + +}; + +struct compat_ioc_dpa_cls_hm_update_params { + struct dpa_cls_compat_hm_update_params update_params; + int next_hmd; + int hmd; + struct dpa_cls_compat_hm_update_resources res; + bool chain_head; + int modify_flags; +}; + +struct dpa_cls_compat_hm_fwd_params { + enum dpa_cls_hm_out_if_type out_if_type; + union { + struct dpa_cls_hm_fwd_l2_param eth; + struct dpa_cls_hm_fwd_pppoe_param pppoe; + struct dpa_cls_hm_fwd_ppp_param ppp; + }; + struct dpa_cls_hm_ip_frag_params ip_frag_params; + compat_uptr_t fm_pcd; +}; + +struct dpa_cls_compat_hm_fwd_resources { + compat_uptr_t fwd_node; + compat_uptr_t pppoe_node; + compat_uptr_t ip_frag_node; +}; + +struct compat_ioc_dpa_cls_hm_fwd_params { + struct dpa_cls_compat_hm_fwd_params fwd_params; + int next_hmd; + int hmd; + struct dpa_cls_compat_hm_fwd_resources res; + bool chain_head; + int modify_flags; +}; + +struct dpa_cls_compat_hm_mpls_params { + enum dpa_cls_hm_mpls_type type; + struct mpls_header mpls_hdr[DPA_CLS_HM_MAX_MPLS_LABELS]; + unsigned int num_labels; + compat_uptr_t fm_pcd; +}; + +struct dpa_cls_compat_hm_mpls_resources { + compat_uptr_t ins_rm_node; +}; + +struct compat_ioc_dpa_cls_hm_mpls_params { + struct dpa_cls_compat_hm_mpls_params mpls_params; + int next_hmd; + int hmd; + struct dpa_cls_compat_hm_mpls_resources res; + bool chain_head; + int modify_flags; +}; + +struct dpa_cls_compat_mcast_group_params { + uint8_t max_members; + compat_uptr_t fm_pcd; + struct dpa_cls_compat_tbl_enq_action_desc first_member_params; + unsigned int prefilled_members; + compat_uptr_t group; + compat_uptr_t distribution; + compat_uptr_t classification; +}; + +struct compat_ioc_dpa_cls_mcast_group_params { + struct dpa_cls_compat_mcast_group_params mcast_grp_params; + int grpd; +}; + +struct compat_ioc_dpa_cls_mcast_member_params { + int grpd; + struct dpa_cls_compat_tbl_enq_action_desc member_params; + int md; +}; + +int dpa_cls_tbl_entry_params_compatcpy( + struct ioc_dpa_cls_tbl_entry_params *kparam, + const struct compat_ioc_dpa_cls_tbl_entry_params *uparam); + +int dpa_cls_tbl_params_compatcpy( + struct ioc_dpa_cls_tbl_params *kparam, + const struct compat_ioc_dpa_cls_tbl_params *uparam); + +int dpa_cls_tbl_params_rcompatcpy( + struct compat_ioc_dpa_cls_tbl_params *uparam, + const struct ioc_dpa_cls_tbl_params *kparam); + +int dpa_cls_tbl_miss_action_params_compatcpy( + struct ioc_dpa_cls_tbl_miss_action *kparam, + const struct compat_ioc_dpa_cls_tbl_miss_action *uparam); + +int dpa_cls_tbl_action_params_compatcpy( + struct dpa_cls_tbl_action *kparam, + const struct dpa_cls_compat_tbl_action *uparam); + +int dpa_cls_tbl_action_params_rcompatcpy( + struct dpa_cls_compat_tbl_action *uparam, + const struct dpa_cls_tbl_action *kparam); + +int dpa_cls_tbl_entry_mod_by_key_params_compatcpy( + struct ioc_dpa_cls_tbl_entry_mod_by_key *kparam, + const struct compat_ioc_dpa_cls_tbl_entry_mod_by_key *uparam); + +int dpa_cls_tbl_entry_mod_by_ref_params_compatcpy( + struct ioc_dpa_cls_tbl_entry_mod_by_ref *kparam, + const struct compat_ioc_dpa_cls_tbl_entry_mod_by_ref *uparam); + +int dpa_cls_tbl_entry_mod_params_compatcpy( + struct dpa_cls_tbl_entry_mod_params *kparam, + const struct dpa_cls_compat_tbl_entry_mod_params *uparam); + +int dpa_cls_tbl_entry_by_key_params_compatcpy( + struct ioc_dpa_cls_tbl_entry_by_key *kparam, + const struct compat_ioc_dpa_cls_tbl_entry_by_key *uparam); + +int dpa_cls_tbl_lookup_by_key_params_compatcpy( + struct ioc_dpa_cls_tbl_lookup_by_key *kparam, + const struct compat_ioc_dpa_cls_tbl_lookup_by_key *uparam); + +int dpa_cls_tbl_lookup_by_ref_params_compatcpy( + struct ioc_dpa_cls_tbl_lookup_by_ref *kparam, + const struct compat_ioc_dpa_cls_tbl_lookup_by_ref *uparam); + +int dpa_cls_tbl_entry_stats_by_key_params_compatcpy( + struct ioc_dpa_cls_tbl_entry_stats_by_key *kparam, + const struct compat_ioc_dpa_cls_tbl_entry_stats_by_key *uparam); + +int dpa_lookup_key_params_compatcpy( + struct dpa_offload_lookup_key *kparam, + const struct compat_ioc_dpa_offld_lookup_key *uparam); + +int dpa_cls_hm_remove_params_compatcpy( + struct ioc_dpa_cls_hm_remove_params *kparam, + const struct compat_ioc_dpa_cls_hm_remove_params *uparam); + +int dpa_cls_hm_insert_params_compatcpy( + struct ioc_dpa_cls_hm_insert_params *kparam, + const struct compat_ioc_dpa_cls_hm_insert_params *uparam); + +int dpa_cls_hm_vlan_params_compatcpy( + struct ioc_dpa_cls_hm_vlan_params *kparam, + const struct compat_ioc_dpa_cls_hm_vlan_params *uparam); + +int dpa_cls_hm_nat_params_compatcpy( + struct ioc_dpa_cls_hm_nat_params *kparam, + const struct compat_ioc_dpa_cls_hm_nat_params *uparam); + +int dpa_cls_hm_update_params_compatcpy( + struct ioc_dpa_cls_hm_update_params *kparam, + const struct compat_ioc_dpa_cls_hm_update_params *uparam); + +int dpa_cls_hm_fwd_params_compatcpy( + struct ioc_dpa_cls_hm_fwd_params *kparam, + const struct compat_ioc_dpa_cls_hm_fwd_params *uparam); + +int dpa_cls_hm_mpls_params_compatcpy( + struct ioc_dpa_cls_hm_mpls_params *kparam, + const struct compat_ioc_dpa_cls_hm_mpls_params *uparam); + +int dpa_cls_mcast_group_params_compatcpy( + struct ioc_dpa_cls_mcast_group_params *kparam, + const struct compat_ioc_dpa_cls_mcast_group_params *uparam); + +int dpa_cls_mcast_member_params_compatcpy( + struct ioc_dpa_cls_mcast_member_params *kparam, + const struct compat_ioc_dpa_cls_mcast_member_params *uparam); +#endif /* CONFIG_COMPAT */ + + +#define DPA_CLS_IOC_TBL_CREATE \ + _IOWR(DPA_CLS_IOC_MAGIC, 0, struct ioc_dpa_cls_tbl_params) + +#ifdef CONFIG_COMPAT +#define DPA_CLS_IOC_COMPAT_TBL_CREATE \ + _IOWR(DPA_CLS_IOC_MAGIC, 0, struct compat_ioc_dpa_cls_tbl_params) +#endif /* CONFIG_COMPAT */ + +#define DPA_CLS_IOC_TBL_FREE \ + _IOW(DPA_CLS_IOC_MAGIC, 1, int) + +#define DPA_CLS_IOC_TBL_MODIFY_MISS_ACTION \ + _IOW(DPA_CLS_IOC_MAGIC, 2, struct ioc_dpa_cls_tbl_miss_action) + +#ifdef CONFIG_COMPAT +#define DPA_CLS_IOC_COMPAT_TBL_MODIFY_MISS_ACTION \ + _IOW(DPA_CLS_IOC_MAGIC, 2, struct compat_ioc_dpa_cls_tbl_miss_action) +#endif /* CONFIG_COMPAT */ + +#define DPA_CLS_IOC_TBL_INSERT_ENTRY \ + _IOWR(DPA_CLS_IOC_MAGIC, 3, struct ioc_dpa_cls_tbl_entry_params) + +#ifdef CONFIG_COMPAT +#define DPA_CLS_IOC_COMPAT_TBL_INSERT_ENTRY \ + _IOWR(DPA_CLS_IOC_MAGIC, 3, struct compat_ioc_dpa_cls_tbl_entry_params) +#endif /* CONFIG_COMPAT */ + +#define DPA_CLS_IOC_TBL_MODIFY_ENTRY_BY_KEY \ + _IOW(DPA_CLS_IOC_MAGIC, 4, struct ioc_dpa_cls_tbl_entry_mod_by_key) + +#ifdef CONFIG_COMPAT +#define DPA_CLS_IOC_COMPAT_TBL_MODIFY_ENTRY_BY_KEY \ + _IOW(DPA_CLS_IOC_MAGIC, 4, \ + struct compat_ioc_dpa_cls_tbl_entry_mod_by_key) +#endif /* CONFIG_COMPAT */ + +#define DPA_CLS_IOC_TBL_MODIFY_ENTRY_BY_REF \ + _IOW(DPA_CLS_IOC_MAGIC, 5, struct ioc_dpa_cls_tbl_entry_mod_by_ref) + +#ifdef CONFIG_COMPAT +#define DPA_CLS_IOC_COMPAT_TBL_MODIFY_ENTRY_BY_REF \ + _IOW(DPA_CLS_IOC_MAGIC, 5, \ + struct compat_ioc_dpa_cls_tbl_entry_mod_by_ref) +#endif /* CONFIG_COMPAT */ + +#define DPA_CLS_IOC_TBL_DELETE_ENTRY_BY_KEY \ + _IOW(DPA_CLS_IOC_MAGIC, 6, struct ioc_dpa_cls_tbl_entry_by_key) + +#ifdef CONFIG_COMPAT +#define DPA_CLS_IOC_COMPAT_TBL_DELETE_ENTRY_BY_KEY \ + _IOW(DPA_CLS_IOC_MAGIC, 6, \ + struct compat_ioc_dpa_cls_tbl_entry_by_key) +#endif /* CONFIG_COMPAT */ + +#define DPA_CLS_IOC_TBL_DELETE_ENTRY_BY_REF \ + _IOW(DPA_CLS_IOC_MAGIC, 7, struct ioc_dpa_cls_tbl_entry_by_ref) + +#ifdef CONFIG_COMPAT +#define DPA_CLS_IOC_COMPAT_TBL_DELETE_ENTRY_BY_REF \ + _IOW(DPA_CLS_IOC_MAGIC, 7, \ + struct compat_ioc_dpa_cls_tbl_entry_by_ref) +#endif /* CONFIG_COMPAT */ + +#define DPA_CLS_IOC_TBL_LOOKUP_BY_KEY \ + _IOR(DPA_CLS_IOC_MAGIC, 8, struct ioc_dpa_cls_tbl_lookup_by_key) + +#ifdef CONFIG_COMPAT +#define DPA_CLS_IOC_COMPAT_TBL_LOOKUP_BY_KEY \ + _IOR(DPA_CLS_IOC_MAGIC, 8, struct compat_ioc_dpa_cls_tbl_lookup_by_key) +#endif /* CONFIG_COMPAT */ + +#define DPA_CLS_IOC_TBL_LOOKUP_BY_REF \ + _IOR(DPA_CLS_IOC_MAGIC, 9, struct ioc_dpa_cls_tbl_lookup_by_ref) + +#ifdef CONFIG_COMPAT +#define DPA_CLS_IOC_COMPAT_TBL_LOOKUP_BY_REF \ + _IOR(DPA_CLS_IOC_MAGIC, 9, struct compat_ioc_dpa_cls_tbl_lookup_by_ref) +#endif /* CONFIG_COMPAT */ + +#define DPA_CLS_IOC_TBL_FLUSH \ + _IOW(DPA_CLS_IOC_MAGIC, 10, int) + +#define DPA_CLS_IOC_TBL_GET_STATS_BY_KEY \ + _IOR(DPA_CLS_IOC_MAGIC, 11, struct ioc_dpa_cls_tbl_entry_stats_by_key) + +#ifdef CONFIG_COMPAT +#define DPA_CLS_IOC_COMPAT_TBL_GET_STATS_BY_KEY \ + _IOR(DPA_CLS_IOC_MAGIC, 11, \ + struct compat_ioc_dpa_cls_tbl_entry_stats_by_key) +#endif /* CONFIG_COMPAT */ + +#define DPA_CLS_IOC_TBL_GET_STATS_BY_REF \ + _IOR(DPA_CLS_IOC_MAGIC, 12, struct ioc_dpa_cls_tbl_entry_stats_by_ref) + +#define DPA_CLS_IOC_TBL_GET_PARAMS \ + _IOWR(DPA_CLS_IOC_MAGIC, 15, struct ioc_dpa_cls_tbl_params) + +#ifdef CONFIG_COMPAT +#define DPA_CLS_IOC_COMPAT_TBL_GET_PARAMS \ + _IOWR(DPA_CLS_IOC_MAGIC, 15, struct compat_ioc_dpa_cls_tbl_params) +#endif /* CONFIG_COMPAT */ + +#define DPA_CLS_IOC_SET_REMOVE_HM \ + _IOWR(DPA_CLS_IOC_MAGIC, 16, struct ioc_dpa_cls_hm_remove_params) + +#ifdef CONFIG_COMPAT +#define DPA_CLS_IOC_COMPAT_SET_REMOVE_HM \ + _IOWR(DPA_CLS_IOC_MAGIC, 16, \ + struct compat_ioc_dpa_cls_hm_remove_params) +#endif /* CONFIG_COMPAT */ + +#define DPA_CLS_IOC_MODIFY_REMOVE_HM \ + _IOWR(DPA_CLS_IOC_MAGIC, 17, struct ioc_dpa_cls_hm_remove_params) + +#ifdef CONFIG_COMPAT +#define DPA_CLS_IOC_COMPAT_MODIFY_REMOVE_HM \ + _IOWR(DPA_CLS_IOC_MAGIC, 17, \ + struct compat_ioc_dpa_cls_hm_remove_params) +#endif /* CONFIG_COMPAT */ + +#define DPA_CLS_IOC_SET_INSERT_HM \ + _IOWR(DPA_CLS_IOC_MAGIC, 18, struct ioc_dpa_cls_hm_insert_params) + +#ifdef CONFIG_COMPAT +#define DPA_CLS_IOC_COMPAT_SET_INSERT_HM \ + _IOWR(DPA_CLS_IOC_MAGIC, 18, \ + struct compat_ioc_dpa_cls_hm_insert_params) +#endif /* CONFIG_COMPAT */ + +#define DPA_CLS_IOC_MODIFY_INSERT_HM \ + _IOWR(DPA_CLS_IOC_MAGIC, 19, struct ioc_dpa_cls_hm_insert_params) + +#ifdef CONFIG_COMPAT +#define DPA_CLS_IOC_COMPAT_MODIFY_INSERT_HM \ + _IOWR(DPA_CLS_IOC_MAGIC, 19, \ + struct compat_ioc_dpa_cls_hm_insert_params) +#endif /* CONFIG_COMPAT */ + +#define DPA_CLS_IOC_SET_VLAN_HM \ + _IOWR(DPA_CLS_IOC_MAGIC, 20, struct ioc_dpa_cls_hm_vlan_params) + +#ifdef CONFIG_COMPAT +#define DPA_CLS_IOC_COMPAT_SET_VLAN_HM \ + _IOWR(DPA_CLS_IOC_MAGIC, 20, struct compat_ioc_dpa_cls_hm_vlan_params) +#endif /* CONFIG_COMPAT */ + +#define DPA_CLS_IOC_MODIFY_VLAN_HM \ + _IOWR(DPA_CLS_IOC_MAGIC, 21, struct ioc_dpa_cls_hm_vlan_params) + +#ifdef CONFIG_COMPAT +#define DPA_CLS_IOC_COMPAT_MODIFY_VLAN_HM \ + _IOWR(DPA_CLS_IOC_MAGIC, 21, struct compat_ioc_dpa_cls_hm_vlan_params) +#endif /* CONFIG_COMPAT */ + + +#define DPA_CLS_IOC_SET_NAT_HM \ + _IOWR(DPA_CLS_IOC_MAGIC, 22, struct ioc_dpa_cls_hm_nat_params) + +#ifdef CONFIG_COMPAT +#define DPA_CLS_IOC_COMPAT_SET_NAT_HM \ + _IOWR(DPA_CLS_IOC_MAGIC, 22, struct compat_ioc_dpa_cls_hm_nat_params) +#endif /* CONFIG_COMPAT */ + +#define DPA_CLS_IOC_MODIFY_NAT_HM \ + _IOWR(DPA_CLS_IOC_MAGIC, 23, struct ioc_dpa_cls_hm_nat_params) + +#ifdef CONFIG_COMPAT +#define DPA_CLS_IOC_COMPAT_MODIFY_NAT_HM \ + _IOWR(DPA_CLS_IOC_MAGIC, 23, struct compat_ioc_dpa_cls_hm_nat_params) +#endif /* CONFIG_COMPAT */ + +#define DPA_CLS_IOC_SET_UPDATE_HM \ + _IOWR(DPA_CLS_IOC_MAGIC, 24, struct ioc_dpa_cls_hm_update_params) + +#ifdef CONFIG_COMPAT +#define DPA_CLS_IOC_COMPAT_SET_UPDATE_HM \ + _IOWR(DPA_CLS_IOC_MAGIC, 24, struct compat_ioc_dpa_cls_hm_update_params) +#endif /* CONFIG_COMPAT */ + +#define DPA_CLS_IOC_MODIFY_UPDATE_HM \ + _IOWR(DPA_CLS_IOC_MAGIC, 25, struct ioc_dpa_cls_hm_update_params) + +#ifdef CONFIG_COMPAT +#define DPA_CLS_IOC_COMPAT_MODIFY_UPDATE_HM \ + _IOWR(DPA_CLS_IOC_MAGIC, 25, struct compat_ioc_dpa_cls_hm_update_params) +#endif /* CONFIG_COMPAT */ + +#define DPA_CLS_IOC_SET_FWD_HM \ + _IOWR(DPA_CLS_IOC_MAGIC, 26, struct ioc_dpa_cls_hm_fwd_params) + +#ifdef CONFIG_COMPAT +#define DPA_CLS_IOC_COMPAT_SET_FWD_HM \ + _IOWR(DPA_CLS_IOC_MAGIC, 26, struct compat_ioc_dpa_cls_hm_fwd_params) +#endif /* CONFIG_COMPAT */ + +#define DPA_CLS_IOC_MODIFY_FWD_HM \ + _IOWR(DPA_CLS_IOC_MAGIC, 27, struct ioc_dpa_cls_hm_fwd_params) + +#ifdef CONFIG_COMPAT +#define DPA_CLS_IOC_COMPAT_MODIFY_FWD_HM \ + _IOWR(DPA_CLS_IOC_MAGIC, 27, struct compat_ioc_dpa_cls_hm_fwd_params) +#endif /* CONFIG_COMPAT */ + +#define DPA_CLS_IOC_SET_MPLS_HM \ + _IOWR(DPA_CLS_IOC_MAGIC, 28, struct ioc_dpa_cls_hm_mpls_params) + +#ifdef CONFIG_COMPAT +#define DPA_CLS_IOC_COMPAT_SET_MPLS_HM \ + _IOWR(DPA_CLS_IOC_MAGIC, 28, struct compat_ioc_dpa_cls_hm_mpls_params) +#endif + +#define DPA_CLS_IOC_MODIFY_MPLS_HM \ + _IOWR(DPA_CLS_IOC_MAGIC, 29, struct ioc_dpa_cls_hm_mpls_params) + +#ifdef CONFIG_COMPAT +#define DPA_CLS_IOC_COMPAT_MODIFY_MPLS_HM \ + _IOWR(DPA_CLS_IOC_MAGIC, 29, struct compat_ioc_dpa_cls_hm_mpls_params) +#endif + +#define DPA_CLS_IOC_FREE_HM \ + _IOR(DPA_CLS_IOC_MAGIC, 30, int) + +#define DPA_CLS_IOC_MCAST_CREATE_GROUP \ + _IOWR(DPA_CLS_IOC_MAGIC, 31, struct ioc_dpa_cls_mcast_group_params) + +#ifdef CONFIG_COMPAT +#define DPA_CLS_IOC_COMPAT_MCAST_CREATE_GROUP \ + _IOWR(DPA_CLS_IOC_MAGIC, 31, \ + struct compat_ioc_dpa_cls_mcast_group_params) +#endif + +#define DPA_CLS_IOC_MCAST_ADD_MEMBER \ + _IOWR(DPA_CLS_IOC_MAGIC, 32, struct ioc_dpa_cls_mcast_member_params) + +#ifdef CONFIG_COMPAT +#define DPA_CLS_IOC_COMPAT_MCAST_ADD_MEMBER \ + _IOWR(DPA_CLS_IOC_MAGIC, 32, \ + struct compat_ioc_dpa_cls_mcast_member_params) +#endif + +#define DPA_CLS_IOC_MCAST_REMOVE_MEMBER \ + _IOWR(DPA_CLS_IOC_MAGIC, 33, struct ioc_dpa_cls_mcast_remove_params) + +#define DPA_CLS_IOC_MCAST_FREE_GROUP \ + _IOWR(DPA_CLS_IOC_MAGIC, 34, int) + + +#endif /* __DPA_CLASSIFIER_IOCTL_H */ diff --git a/drivers/staging/fsl_dpa_offload/dpa_offload_module.c b/drivers/staging/fsl_dpa_offload/dpa_offload_module.c new file mode 100644 index 0000000..aaf6693 --- /dev/null +++ b/drivers/staging/fsl_dpa_offload/dpa_offload_module.c @@ -0,0 +1,102 @@ +/* Copyright 2008-2012 Freescale Semiconductor, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Freescale Semiconductor nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * + * ALTERNATIVELY, this software may be distributed under the terms of the + * GNU General Public License ("GPL") as published by the Free Software + * Foundation, either version 2 of that License or (at your option) any + * later version. + * + * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * DPA Offloading driver implementation + */ + +#include + +#include "dpa_offload_module.h" +#include "wrp_dpa_classifier.h" +#include "wrp_dpa_ipsec.h" +#include "wrp_dpa_stats.h" + +static int __init dpa_offload_drv_init(void) +{ + int err; + + /* Initialize DPA Classifier wrapper to listen to [ioctl] calls */ + err = wrp_dpa_classif_init(); + if (err == 0) + printk(KERN_INFO"DPA Classifier Driver initialized.\n"); + else { + printk(KERN_ERR"DPA Classifier Driver failed to initialize.\n"); + return err; + } + + /* Initialize DPA IPSec wrapper to listen to [ioctl] calls */ + err = wrp_dpa_ipsec_init(); + if (err == 0) + printk(KERN_INFO"DPA IPSec Driver initialized.\n"); + else { + printk(KERN_ERR"DPA IPSec Driver failed to initialize.\n"); + return err; + } + + /* Initialize DPA Stats wrapper to listen to [ioctl] calls */ + err = wrp_dpa_stats_init(); + if (err == 0) + printk(KERN_INFO"DPA Stats Driver initialized.\n"); + else { + printk(KERN_ERR"DPA Stats Driver failed to initialize.\n"); + return err; + } + return err; +} +module_init(dpa_offload_drv_init); + +static void __exit dpa_offload_drv_exit(void) +{ + /* Shut down DPA Classifier wrapper */ + if (wrp_dpa_classif_exit() < 0) + printk(KERN_ERR"DPA Classifier Driver failed to unload.\n"); + else + printk(KERN_INFO"DPA Classifier Driver unloaded.\n"); + + /* Shut down DPA IPSec wrapper */ + if (wrp_dpa_ipsec_exit() < 0) + printk(KERN_ERR"DPA IPSec Driver failed to unload.\n"); + else + printk(KERN_INFO"INFO: DPA IPSec Driver unloaded.\n"); + + /* Shut down DPA Stats wrapper */ + if (wrp_dpa_stats_exit() < 0) + printk(KERN_ERR"DPA Stats Driver failed to unload.\n"); + else + printk(KERN_INFO"INFO: DPA Stats Driver unloaded.\n"); +} +module_exit(dpa_offload_drv_exit); + +MODULE_AUTHOR("Freescale, "); +MODULE_DESCRIPTION("DPA Offloading Driver"); +MODULE_LICENSE("GPL"); +MODULE_VERSION(DRV_VERSION); diff --git a/drivers/staging/fsl_dpa_offload/dpa_offload_module.h b/drivers/staging/fsl_dpa_offload/dpa_offload_module.h new file mode 100644 index 0000000..e4f3ad1 --- /dev/null +++ b/drivers/staging/fsl_dpa_offload/dpa_offload_module.h @@ -0,0 +1,46 @@ +/* Copyright 2008-2012 Freescale Semiconductor, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Freescale Semiconductor nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * + * ALTERNATIVELY, this software may be distributed under the terms of the + * GNU General Public License ("GPL") as published by the Free Software + * Foundation, either version 2 of that License or (at your option) any + * later version. + * + * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * DPA Offloading driver internal interface + */ + +#ifndef __DPA_OFFLOAD_DRIVER_H +#define __DPA_OFFLOAD_DRIVER_H + +#define DRV_VERSION "1.0" + +static int __init dpa_offload_drv_init(void); + +static void __exit dpa_offload_drv_exit(void); + + +#endif /* __DPA_OFFLOAD_DRIVER_H */ diff --git a/drivers/staging/fsl_dpa_offload/wrp_dpa_classifier.c b/drivers/staging/fsl_dpa_offload/wrp_dpa_classifier.c new file mode 100644 index 0000000..aa2017a --- /dev/null +++ b/drivers/staging/fsl_dpa_offload/wrp_dpa_classifier.c @@ -0,0 +1,3123 @@ + +/* Copyright 2008-2012 Freescale Semiconductor, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Freescale Semiconductor nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * + * ALTERNATIVELY, this software may be distributed under the terms of the + * GNU General Public License ("GPL") as published by the Free Software + * Foundation, either version 2 of that License or (at your option) any + * later version. + * + * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * DPA Classifier Wrapper implementation. + */ + +/* DPA offloading layer includes */ +#include +#include "wrp_dpa_classifier.h" +#include "dpa_classifier_ioctl.h" + +/* Other includes */ +#include +#include +#include +#include "lnxwrp_fm.h" +#include "fm_pcd_ioctls.h" +#include "fm_port_ioctls.h" +#ifdef CONFIG_COMPAT +#include "lnxwrp_ioctls_fm_compat.h" +#endif /* CONFIG_COMPAT */ + + +#define COPY_KEY_PARAMS \ +do { \ + if ((kparam.key.size <= 0) || \ + (kparam.key.size > DPA_OFFLD_MAXENTRYKEYSIZE)) { \ + pr_err("ERROR: %s, %s (%d): Invalid lookup key size " \ + "(%d bytes).\n", __FILE__, __func__, __LINE__, \ + kparam.key.size); \ + return -EINVAL; \ + } \ + \ + if (copy_from_user(key_buf, kparam.key.byte, \ + kparam.key.size)) { \ + pr_err("ERROR: %s, %s (%d): Read failed: lookup " \ + "key.\n", __FILE__, __func__, __LINE__); \ + return -EBUSY; \ + } \ + kparam.key.byte = key_buf; \ + \ + if (kparam.key.mask) { \ + if (copy_from_user(mask_buf, kparam.key.mask, \ + kparam.key.size)) { \ + pr_err("ERROR: %s, %s (%d): Read failed: " \ + "key mask.\n", __FILE__, __func__, \ + __LINE__); \ + return -EBUSY; \ + } \ + \ + kparam.key.mask = mask_buf; \ + } \ +} while (0) + +#define COPY_NEW_KEY_PARAMS \ +do { \ + if (kparam.mod_params.key) { \ + if (copy_from_user(&new_key, \ + kparam.mod_params.key, \ + sizeof(struct dpa_offload_lookup_key))) { \ + pr_err("ERROR: %s, %s (%d): Read failed: " \ + "new lookup key.\n", __FILE__, \ + __func__, __LINE__); \ + return -EBUSY; \ + } \ + kparam.mod_params.key = &new_key; \ + \ + if ((kparam.mod_params.key->size <= 0) || \ + (kparam.mod_params.key->size > \ + DPA_OFFLD_MAXENTRYKEYSIZE)) { \ + pr_err("ERROR: %s, %s (%d): Invalid new lookup " \ + "key size (%d bytes).\n", __FILE__, \ + __func__, __LINE__, \ + kparam.mod_params.key->size); \ + return -EINVAL; \ + } \ + \ + if (kparam.mod_params.key->byte) { \ + if (copy_from_user(new_key_buf, \ + kparam.mod_params.key->byte, \ + kparam.mod_params.key->size)) { \ + pr_err("ERROR: %s, %s (%d): Read " \ + "failed: new lookup key data.\n", \ + __FILE__, __func__, __LINE__); \ + return -EBUSY; \ + } \ + kparam.mod_params.key->byte = new_key_buf; \ + } \ + if (kparam.mod_params.key->mask) { \ + if (copy_from_user(new_mask_buf, \ + kparam.mod_params.key->mask, \ + kparam.mod_params.key->size)) { \ + pr_err("ERROR: %s, %s (%d): Read " \ + "failed: new key mask.\n", \ + __FILE__, __func__, __LINE__); \ + return -EBUSY; \ + } \ + kparam.mod_params.key->mask = new_mask_buf; \ + } \ + } \ +} while (0) + +#ifdef DPA_CLASSIFIER_WRP_DEBUG +#define dpa_cls_wrp_dbg(message) printk message +#else +#define dpa_cls_wrp_dbg(message) +#endif /* DPA_CLASSIFIER_DEBUG */ + + +static long do_ioctl_table_create(unsigned long args, bool compat_mode); + +static long do_ioctl_table_modify_miss_action(unsigned long args, + bool compat_mode); + +static long do_ioctl_table_insert_entry(unsigned long args, bool compat_mode); + +static long do_ioctl_table_modify_entry_by_key(unsigned long args, + bool compat_mode); + +static long do_ioctl_table_modify_entry_by_ref(unsigned long args, + bool compat_mode); + +static long do_ioctl_table_lookup_by_key(unsigned long args, bool compat_mode); + +static long do_ioctl_table_lookup_by_ref(unsigned long args, bool compat_mode); + +static long do_ioctl_table_delete_entry_by_key(unsigned long args, + bool compat_mode); + +static long do_ioctl_table_get_stats_by_key(unsigned long args, + bool compat_mode); + +static long do_ioctl_set_remove_hm(unsigned long args, + bool compat_mode); + +static long do_ioctl_modify_remove_hm(unsigned long args, + bool compat_mode); + +static long do_ioctl_set_insert_hm(unsigned long args, + bool compat_mode); + +static long do_ioctl_modify_insert_hm(unsigned long args, + bool compat_mode); + +static long do_ioctl_set_vlan_hm(unsigned long args, bool compat_mode); + +static long do_ioctl_modify_vlan_hm(unsigned long args, bool compat_mode); + +static long do_ioctl_set_nat_hm(unsigned long args, bool compat_mode); + +static long do_ioctl_modify_nat_hm(unsigned long args, bool compat_mode); + +static long do_ioctl_set_update_hm(unsigned long args, bool compat_mode); + +static long do_ioctl_modify_update_hm(unsigned long args, bool compat_mode); + +static long do_ioctl_set_fwd_hm(unsigned long args, bool compat_mode); + +static long do_ioctl_modify_fwd_hm(unsigned long args, bool compat_mode); + +static long do_ioctl_set_mpls_hm(unsigned long args, bool compat_mode); + +static long do_ioctl_modify_mpls_hm(unsigned long args, bool compat_mode); + +static long do_ioctl_mcast_create_group(unsigned long args, bool compat_mode); + +static long do_ioctl_mcast_add_member(unsigned long args, bool compat_mode); + +void *translate_fm_pcd_handle(void *fm_pcd); + +static const struct file_operations dpa_classif_fops = { + .owner = THIS_MODULE, + .open = wrp_dpa_classif_open, + .read = wrp_dpa_classif_read, + .write = wrp_dpa_classif_write, + .unlocked_ioctl = wrp_dpa_classif_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = wrp_dpa_classif_compat_ioctl, +#endif /* CONFIG_COMPAT */ + .release = wrp_dpa_classif_release +}; + +static int dpa_cls_cdev_major = -1; + + +int wrp_dpa_classif_init(void) +{ + /* Cannot initialize the wrapper twice */ + if (dpa_cls_cdev_major >= 0) + return 0; + + dpa_cls_cdev_major = register_chrdev( + 0, + WRP_DPA_CLS_CDEVNAME, + &dpa_classif_fops); + if (dpa_cls_cdev_major < 0) { + pr_err("ERROR: %s, %s (%d): Could not register DPA Classifier " + "Control Device.\n", __FILE__, __func__, __LINE__); + return -EBUSY; + } + + return 0; +} + + +int wrp_dpa_classif_exit(void) +{ + if (dpa_cls_cdev_major < 0) + return 0; + + unregister_chrdev(dpa_cls_cdev_major, WRP_DPA_CLS_CDEVNAME); + + dpa_cls_cdev_major = -1; + + return 0; +} + + +int wrp_dpa_classif_open(struct inode *inode, struct file *filp) +{ + return 0; +} + + +int wrp_dpa_classif_release(struct inode *inode, struct file *filp) +{ + return 0; +} + + +ssize_t wrp_dpa_classif_read( + struct file *filp, + char __user *buf, + size_t len, + loff_t *offp) +{ + return 0; +} + + +ssize_t wrp_dpa_classif_write( + struct file *filp, + const char __user *buf, + size_t len, + loff_t *offp) +{ + return 0; +} + + +#ifdef CONFIG_COMPAT +long wrp_dpa_classif_compat_ioctl( + struct file *filp, + unsigned int cmd, + unsigned long args) +{ + return wrp_dpa_classif_do_ioctl(filp, cmd, args, true); +} +#endif /* CONFIG_COMPAT */ + + +long wrp_dpa_classif_ioctl( + struct file *filp, + unsigned int cmd, + unsigned long args) +{ + return wrp_dpa_classif_do_ioctl(filp, cmd, args, false); +} + + +long wrp_dpa_classif_do_ioctl( + struct file *filp, + unsigned int cmd, + unsigned long args, + bool compat_mode) +{ + long ret = 0; + + + dpa_cls_wrp_dbg(("DEBUG: classifier_wrp %s (%d) --> Processing ioctl " + "cmd=0x%x\n", __func__, __LINE__, cmd)); + + switch (cmd) { +#ifdef CONFIG_COMPAT + case DPA_CLS_IOC_COMPAT_TBL_CREATE: +#endif /* CONFIG_COMPAT */ + case DPA_CLS_IOC_TBL_CREATE: + ret = do_ioctl_table_create(args, compat_mode); + break; + + case DPA_CLS_IOC_TBL_FREE: + ret = dpa_classif_table_free((int)args); + break; + +#ifdef CONFIG_COMPAT + case DPA_CLS_IOC_COMPAT_TBL_MODIFY_MISS_ACTION: +#endif /* CONFIG_COMPAT */ + case DPA_CLS_IOC_TBL_MODIFY_MISS_ACTION: + ret = do_ioctl_table_modify_miss_action(args, compat_mode); + break; + +#ifdef CONFIG_COMPAT + case DPA_CLS_IOC_COMPAT_TBL_INSERT_ENTRY: +#endif /* CONFIG_COMPAT */ + case DPA_CLS_IOC_TBL_INSERT_ENTRY: + ret = do_ioctl_table_insert_entry(args, compat_mode); + break; + +#ifdef CONFIG_COMPAT + case DPA_CLS_IOC_COMPAT_TBL_MODIFY_ENTRY_BY_KEY: +#endif /* CONFIG_COMPAT */ + case DPA_CLS_IOC_TBL_MODIFY_ENTRY_BY_KEY: + ret = do_ioctl_table_modify_entry_by_key(args, compat_mode); + break; + +#ifdef CONFIG_COMPAT + case DPA_CLS_IOC_COMPAT_TBL_MODIFY_ENTRY_BY_REF: +#endif /* CONFIG_COMPAT */ + case DPA_CLS_IOC_TBL_MODIFY_ENTRY_BY_REF: + ret = do_ioctl_table_modify_entry_by_ref(args, compat_mode); + break; + +#ifdef CONFIG_COMPAT + case DPA_CLS_IOC_COMPAT_TBL_DELETE_ENTRY_BY_KEY: +#endif /* CONFIG_COMPAT */ + case DPA_CLS_IOC_TBL_DELETE_ENTRY_BY_KEY: + ret = do_ioctl_table_delete_entry_by_key(args, compat_mode); + break; + + case DPA_CLS_IOC_TBL_DELETE_ENTRY_BY_REF: + { + struct ioc_dpa_cls_tbl_entry_by_ref param; + + dpa_cls_wrp_dbg(("DEBUG: classifier_wrp %s (%d): " + "delete_entry_by_ref\n", __func__, __LINE__)); + + /* Prepare arguments */ + if (copy_from_user(¶m, (void *) args, sizeof(param))) { + pr_err("ERROR: %s, %s (%d): Read failed: " + "dpa_classif_table_delete_entry_by_ref user " + "space args.\n", __FILE__, __func__, __LINE__); + return -EBUSY; + } + + /* Call function */ + ret = dpa_classif_table_delete_entry_by_ref(param.td, + param.entry_id); + + break; + } + +#ifdef CONFIG_COMPAT + case DPA_CLS_IOC_COMPAT_TBL_LOOKUP_BY_KEY: +#endif /* CONFIG_COMPAT */ + case DPA_CLS_IOC_TBL_LOOKUP_BY_KEY: + ret = do_ioctl_table_lookup_by_key(args, compat_mode); + break; + +#ifdef CONFIG_COMPAT + case DPA_CLS_IOC_COMPAT_TBL_LOOKUP_BY_REF: +#endif /* CONFIG_COMPAT */ + case DPA_CLS_IOC_TBL_LOOKUP_BY_REF: + ret = do_ioctl_table_lookup_by_ref(args, compat_mode); + break; + + case DPA_CLS_IOC_TBL_FLUSH: + ret = dpa_classif_table_flush((int)args); + break; + +#ifdef CONFIG_COMPAT + case DPA_CLS_IOC_COMPAT_TBL_GET_STATS_BY_KEY: +#endif /* CONFIG_COMPAT */ + case DPA_CLS_IOC_TBL_GET_STATS_BY_KEY: + ret = do_ioctl_table_get_stats_by_key(args, compat_mode); + break; + + case DPA_CLS_IOC_TBL_GET_STATS_BY_REF: + { + struct ioc_dpa_cls_tbl_entry_stats_by_ref param; + + dpa_cls_wrp_dbg(("DEBUG: classifier_wrp %s (%d): " + "get_stats_by_ref\n", __func__, __LINE__)); + + /* Prepare arguments */ + if (copy_from_user(¶m, (void *) args, sizeof(param))) { + pr_err("ERROR: %s, %s (%d): Read failed: " + "dpa_classif_table_get_entry_stats_by_ref user " + "space args.\n", __FILE__, __func__, __LINE__); + return -EBUSY; + } + + /* Call function */ + ret = dpa_classif_table_get_entry_stats_by_ref(param.td, + param.entry_id, + ¶m.stats); + if (ret < 0) + return ret; + + /* Return results to user space */ + if (copy_to_user((void *) args, ¶m, sizeof(param))) { + pr_err("ERROR: %s, %s (%d): Write failed: " + "dpa_classif_table_get_entry_stats_by_ref " + "result.\n", __FILE__, __func__, __LINE__); + return -EBUSY; + } + + break; + } + +#ifdef CONFIG_COMPAT + case DPA_CLS_IOC_COMPAT_TBL_GET_PARAMS: +#endif /* CONFIG_COMPAT */ + case DPA_CLS_IOC_TBL_GET_PARAMS: + { + struct ioc_dpa_cls_tbl_params kparam; +#ifdef CONFIG_COMPAT + struct compat_ioc_dpa_cls_tbl_params uparam; + + /* Prepare arguments */ + if (compat_mode) { + if (copy_from_user(&uparam, (void *) args, + sizeof(uparam))) { + pr_err("ERROR: %s, %s (%d): Read failed: " + "dpa_classif_table_lookup_by_key user " + "space args.\n", __FILE__, __func__, + __LINE__); + return -EBUSY; + } + + /* Transfer the data into the kernel space params: */ + kparam.td = uparam.td; + } else +#endif /* CONFIG_COMPAT */ + /* Prepare arguments */ + if (copy_from_user(&kparam, (void *) args, sizeof(kparam))) { + pr_err("ERROR: %s, %s (%d): Read failed: " + "dpa_classif_table_lookup_by_key user space " + "args.\n", __FILE__, __func__, __LINE__); + return -EBUSY; + } + + dpa_cls_wrp_dbg(("DEBUG: classifier_wrp %s (%d): " + "table_get_params\n", __func__, __LINE__)); + + /* Call function */ + ret = dpa_classif_table_get_params(kparam.td, + &kparam.table_params); + if (ret < 0) + return ret; + +#ifdef CONFIG_COMPAT + if (compat_mode) { + ret = dpa_cls_tbl_params_rcompatcpy(&uparam, &kparam); + if (ret < 0) + return ret; + + if (copy_to_user((void *) args, &uparam, sizeof(uparam))) { + pr_err("ERROR: %s, %s (%d): Write failed: " + "dpa_classif_table_get_params result.\n", + __FILE__, __func__, __LINE__); + return -EBUSY; + } + } else +#endif /* CONFIG_COMPAT */ + /* Return results to user space */ + if (copy_to_user((void *) args, &kparam, sizeof(kparam))) { + pr_err("ERROR: %s, %s (%d): Write failed: " + "dpa_classif_table_get_params result.\n", + __FILE__, __func__, __LINE__); + return -EBUSY; + } + + break; + } +#ifdef CONFIG_COMPAT + case DPA_CLS_IOC_COMPAT_SET_REMOVE_HM: +#endif /* CONFIG_COMPAT */ + case DPA_CLS_IOC_SET_REMOVE_HM: + ret = do_ioctl_set_remove_hm(args, compat_mode); + break; +#ifdef CONFIG_COMPAT + case DPA_CLS_IOC_COMPAT_MODIFY_REMOVE_HM: +#endif /* CONFIG_COMPAT */ + case DPA_CLS_IOC_MODIFY_REMOVE_HM: + ret = do_ioctl_modify_remove_hm(args, compat_mode); + break; +#ifdef CONFIG_COMPAT + case DPA_CLS_IOC_COMPAT_SET_INSERT_HM: +#endif /* CONFIG_COMPAT */ + case DPA_CLS_IOC_SET_INSERT_HM: + ret = do_ioctl_set_insert_hm(args, compat_mode); + break; +#ifdef CONFIG_COMPAT + case DPA_CLS_IOC_COMPAT_MODIFY_INSERT_HM: +#endif /* CONFIG_COMPAT */ + case DPA_CLS_IOC_MODIFY_INSERT_HM: + ret = do_ioctl_modify_insert_hm(args, compat_mode); + break; +#ifdef CONFIG_COMPAT + case DPA_CLS_IOC_COMPAT_SET_VLAN_HM: +#endif /* CONFIG_COMPAT */ + case DPA_CLS_IOC_SET_VLAN_HM: + ret = do_ioctl_set_vlan_hm(args, compat_mode); + break; +#ifdef CONFIG_COMPAT + case DPA_CLS_IOC_COMPAT_MODIFY_VLAN_HM: +#endif /* CONFIG_COMPAT */ + case DPA_CLS_IOC_MODIFY_VLAN_HM: + ret = do_ioctl_modify_vlan_hm(args, compat_mode); + break; +#ifdef CONFIG_COMPAT + case DPA_CLS_IOC_COMPAT_SET_NAT_HM: +#endif /* CONFIG_COMPAT */ + case DPA_CLS_IOC_SET_NAT_HM: + ret = do_ioctl_set_nat_hm(args, compat_mode); + break; +#ifdef CONFIG_COMPAT + case DPA_CLS_IOC_COMPAT_MODIFY_NAT_HM: +#endif /* CONFIG_COMPAT */ + case DPA_CLS_IOC_MODIFY_NAT_HM: + ret = do_ioctl_modify_nat_hm(args, compat_mode); + break; +#ifdef CONFIG_COMPAT + case DPA_CLS_IOC_COMPAT_SET_UPDATE_HM: +#endif /* CONFIG_COMPAT */ + case DPA_CLS_IOC_SET_UPDATE_HM: + ret = do_ioctl_set_update_hm(args, compat_mode); + break; +#ifdef CONFIG_COMPAT + case DPA_CLS_IOC_COMPAT_MODIFY_UPDATE_HM: +#endif /* CONFIG_COMPAT */ + case DPA_CLS_IOC_MODIFY_UPDATE_HM: + ret = do_ioctl_modify_update_hm(args, compat_mode); + break; +#ifdef CONFIG_COMPAT + case DPA_CLS_IOC_COMPAT_SET_FWD_HM: +#endif /* CONFIG_COMPAT */ + case DPA_CLS_IOC_SET_FWD_HM: + ret = do_ioctl_set_fwd_hm(args, compat_mode); + break; +#ifdef CONFIG_COMPAT + case DPA_CLS_IOC_COMPAT_MODIFY_FWD_HM: +#endif /* CONFIG_COMPAT */ + case DPA_CLS_IOC_MODIFY_FWD_HM: + ret = do_ioctl_modify_fwd_hm(args, compat_mode); + break; +#ifdef CONFIG_COMPAT + case DPA_CLS_IOC_COMPAT_SET_MPLS_HM: +#endif /* CONFIG_COMPAT */ + case DPA_CLS_IOC_SET_MPLS_HM: + ret = do_ioctl_set_mpls_hm(args, compat_mode); + break; +#ifdef CONFIG_COMPAT + case DPA_CLS_IOC_COMPAT_MODIFY_MPLS_HM: +#endif /* CONFIG_COMPAT */ + case DPA_CLS_IOC_MODIFY_MPLS_HM: + ret = do_ioctl_modify_mpls_hm(args, compat_mode); + break; + case DPA_CLS_IOC_FREE_HM: + ret = dpa_classif_free_hm((int)args); + break; +#ifdef CONFIG_COMPAT + case DPA_CLS_IOC_COMPAT_MCAST_CREATE_GROUP: +#endif /* CONFIG_COMPAT */ + case DPA_CLS_IOC_MCAST_CREATE_GROUP: + ret = do_ioctl_mcast_create_group(args, compat_mode); + break; +#ifdef CONFIG_COMPAT + case DPA_CLS_IOC_COMPAT_MCAST_ADD_MEMBER: +#endif /* CONFIG_COMPAT */ + case DPA_CLS_IOC_MCAST_ADD_MEMBER: + ret = do_ioctl_mcast_add_member(args, compat_mode); + break; + case DPA_CLS_IOC_MCAST_REMOVE_MEMBER: { + struct ioc_dpa_cls_mcast_remove_params params; + int sz; + sz = sizeof(struct ioc_dpa_cls_mcast_remove_params); + if (copy_from_user(¶ms, + (struct ioc_dpa_cls_mcast_remove_params *)args, + sz)) { + pr_err("ERROR: %s, %s (%d):Could not copy parameters\n", + __FILE__, __func__, __LINE__); + return -EINVAL; + } +#if (DPAA_VERSION >= 11) + ret = dpa_classif_mcast_remove_member(params.grpd, + params.md); +#else + pr_err("ERROR: %s, %s (%d): Multicast not supported on this" + "platform.\n", __FILE__, __func__, __LINE__); + ret = -EINVAL; + return ret; +#endif + break; + } + case DPA_CLS_IOC_MCAST_FREE_GROUP: { + int grpd; + if (copy_from_user(&grpd, (int *)args, sizeof(int))) { + pr_err("ERROR: %s, %s (%d):Could not copy parameters\n", + __FILE__, __func__, __LINE__); + return -EINVAL; + } +#if (DPAA_VERSION >= 11) + ret = dpa_classif_mcast_free_group(grpd); + if (ret < 0) + return ret; +#else + pr_err("ERROR: %s, %s (%d): Multicast not supported on this" + "platform.\n", __FILE__, __func__, __LINE__); + ret = -EINVAL; + return ret; +#endif + break; + } + default: + pr_err("ERROR: %s, %s (%d): DPA Classifier ioctl command " + "(0x%x) not suppoted", __FILE__, __func__, __LINE__, + cmd); + return -EINVAL; + } + + dpa_cls_wrp_dbg(("DEBUG: classifier_wrp %s (%d): Done <--\n", __func__, + __LINE__)); + + return ret; +} + +static long do_ioctl_table_create(unsigned long args, bool compat_mode) +{ + long ret = 0; + struct ioc_dpa_cls_tbl_params kparam; +#ifdef CONFIG_COMPAT + struct compat_ioc_dpa_cls_tbl_params uparam; + + /* Prepare arguments */ + if (compat_mode) { + if (copy_from_user(&uparam, (void *) args, sizeof(uparam))) { + pr_err("ERROR: %s, %s (%d): Read failed: user space " + "args.\n", __FILE__, __func__, __LINE__); + return -EBUSY; + } + + memset(&kparam, 0, sizeof(struct ioc_dpa_cls_tbl_params)); + /* Transfer the data into the kernel space params: */ + ret = dpa_cls_tbl_params_compatcpy(&kparam, &uparam); + if (ret < 0) + return ret; + } else +#endif /* CONFIG_COMPAT */ + if (copy_from_user(&kparam, (void *) args, sizeof(kparam))) { + pr_err("ERROR: %s, %s (%d): Read failed: user space " + "args.\n", __FILE__, __func__, __LINE__); + return -EBUSY; + } + + dpa_cls_wrp_dbg(("DEBUG: classifier_wrp %s (%d) -->\n", __func__, + __LINE__)); + + /* Call function */ + ret = dpa_classif_table_create(&kparam.table_params, + &kparam.td); + if (ret < 0) + return ret; + + /* Return results to user space */ +#ifdef CONFIG_COMPAT + if (compat_mode) { + uparam.td = kparam.td; + if (copy_to_user((void *) args, &uparam, sizeof(uparam))) { + pr_err("ERROR: %s, %s (%d): Write failed: result.\n", + __FILE__, __func__, __LINE__); + return -EBUSY; + } + } else +#endif /* CONFIG_COMPAT */ + if (copy_to_user((void *) args, &kparam, sizeof(kparam))) { + pr_err("ERROR: %s, %s (%d): Write failed: result.\n", + __FILE__, __func__, __LINE__); + return -EBUSY; + } + + dpa_cls_wrp_dbg(("DEBUG: classifier_wrp %s (%d) <--\n", __func__, + __LINE__)); + + return ret; +} + +static long do_ioctl_set_remove_hm(unsigned long args, bool compat_mode) +{ + long ret = 0; + struct ioc_dpa_cls_hm_remove_params kparam; + struct dpa_cls_hm_remove_resources *p_res = NULL; +#ifdef CONFIG_COMPAT + struct compat_ioc_dpa_cls_hm_remove_params uparam; + + if (compat_mode) { + if (copy_from_user(&uparam, (void *) args, sizeof(uparam))) { + pr_err("ERROR: %s, %s (%d): Read failed: user space " + "args.\n", __FILE__, __func__, __LINE__); + return -EBUSY; + } + + /* Transfer the data into the kernel space params: */ + ret = dpa_cls_hm_remove_params_compatcpy(&kparam, &uparam); + if (ret < 0) + return ret; + + } else +#endif /* CONFIG_COMPAT */ + if (copy_from_user(&kparam, (void *) args, sizeof(kparam))) { + pr_err("ERROR: %s, %s (%d): Read failed: user space " + "args.\n", __FILE__, __func__, __LINE__); + return -EBUSY; + } + + dpa_cls_wrp_dbg(("DEBUG: classifier_wrp %s (%d) -->\n", __func__, + __LINE__)); + + if (kparam.res.remove_node) + p_res = &kparam.res; + + /* Translate FM_PCD file descriptor */ + if (!p_res) { + kparam.rm_params.fm_pcd = + translate_fm_pcd_handle(kparam.rm_params.fm_pcd); + if (!kparam.rm_params.fm_pcd) + return -EINVAL; + } + + ret = dpa_classif_set_remove_hm(&kparam.rm_params, kparam.next_hmd, + &kparam.hmd, kparam.chain_head, + p_res); + if (ret < 0) + return ret; + + /* Return results to user space */ +#ifdef CONFIG_COMPAT + if (compat_mode) { + uparam.hmd = kparam.hmd; + if (copy_to_user((void *) args, &uparam, sizeof(uparam))) { + pr_err("ERROR: %s, %s (%d): Write failed: result.\n", + __FILE__, __func__, __LINE__); + return -EBUSY; + } + } else +#endif /* CONFIG_COMPAT */ + if (copy_to_user((void *) args, &kparam, sizeof(kparam))) { + pr_err("ERROR: %s, %s (%d): Write failed: result.\n", + __FILE__, __func__, __LINE__); + return -EBUSY; + } + + dpa_cls_wrp_dbg(("DEBUG: classifier_wrp %s (%d) <--\n", __func__, + __LINE__)); + + return ret; +} + +static long do_ioctl_modify_remove_hm(unsigned long args, bool compat_mode) +{ + struct ioc_dpa_cls_hm_remove_params kparam; +#ifdef CONFIG_COMPAT + long ret = 0; + struct compat_ioc_dpa_cls_hm_remove_params uparam; + + if (compat_mode) { + if (copy_from_user(&uparam, (void *) args, sizeof(uparam))) { + pr_err("ERROR: %s, %s (%d): Read failed: user " + "space args.\n", __FILE__, __func__, __LINE__); + return -EBUSY; + } + + /* Transfer the data into the kernel space params: */ + ret = dpa_cls_hm_remove_params_compatcpy(&kparam, &uparam); + if (ret < 0) + return ret; + + } else +#endif /* CONFIG_COMPAT */ + if (copy_from_user(&kparam, (void *) args, sizeof(kparam))) { + pr_err("ERROR: %s, %s (%d): Read failed: user " + "space args.\n", __FILE__, __func__, __LINE__); + return -EBUSY; + } + + dpa_cls_wrp_dbg(("DEBUG: classifier_wrp %s (%d)\n", __func__, + __LINE__)); + + return dpa_classif_modify_remove_hm(kparam.hmd, &kparam.rm_params, + kparam.modify_flags); +} + +static long do_ioctl_set_insert_hm(unsigned long args, bool compat_mode) +{ + long ret = 0; + struct ioc_dpa_cls_hm_insert_params kparam; + struct dpa_cls_hm_insert_resources *p_res = NULL; + uint8_t *data = NULL; + uint8_t sz; +#ifdef CONFIG_COMPAT + struct compat_ioc_dpa_cls_hm_insert_params uparam; + + if (compat_mode) { + if (copy_from_user(&uparam, (void *) args, sizeof(uparam))) { + pr_err("ERROR: %s, %s (%d): Read failed: user " + "space args.\n", __FILE__, __func__, __LINE__); + return -EBUSY; + } + + /* Transfer the data into the kernel space params: */ + ret = dpa_cls_hm_insert_params_compatcpy(&kparam, &uparam); + if (ret < 0) + return ret; + + } else +#endif /* CONFIG_COMPAT */ + if (copy_from_user(&kparam, (void *) args, sizeof(kparam))) { + pr_err("ERROR: %s, %s (%d): Read failed: space args.\n", + __FILE__, __func__, __LINE__); + return -EBUSY; + } + + dpa_cls_wrp_dbg(("DEBUG: classifier_wrp %s (%d) -->\n", __func__, + __LINE__)); + + if (kparam.res.insert_node) + p_res = &kparam.res; + + /* Translate FM_PCD file descriptor */ + if (!p_res) { + kparam.ins_params.fm_pcd = + translate_fm_pcd_handle(kparam.ins_params.fm_pcd); + if (!kparam.ins_params.fm_pcd) + return -EINVAL; + } + + if (kparam.ins_params.type == DPA_CLS_HM_INSERT_CUSTOM) { + sz = kparam.ins_params.custom.size; + data = kzalloc(sz * sizeof(*data), GFP_KERNEL); + if (!data) { + pr_err("ERROR: %s, %s (%d): Failed to allocate memory " + "for data param for DPA_CLS_HM_INSERT_CUSTOM" + " parameter type.\n", + __FILE__, __func__, __LINE__); + return -ENOMEM; + } + + copy_from_user(data, kparam.ins_params.custom.data, sz); + kparam.ins_params.custom.data = data; + } + + ret = dpa_classif_set_insert_hm(&kparam.ins_params, kparam.next_hmd, + &kparam.hmd, kparam.chain_head, + p_res); + kfree(data); + if (ret < 0) + return ret; + +#ifdef CONFIG_COMPAT + if (compat_mode) { + uparam.hmd = kparam.hmd; + if (copy_to_user((void *) args, &uparam, sizeof(uparam))) { + pr_err("ERROR: %s, %s (%d): Write failed: result.\n", + __FILE__, __func__, __LINE__); + return -EBUSY; + } + } else +#endif /* CONFIG_COMPAT */ + if (copy_to_user((void *) args, &kparam, sizeof(kparam))) { + pr_err("ERROR: %s, %s (%d): Write failed: result.\n", + __FILE__, __func__, __LINE__); + return -EBUSY; + } + + dpa_cls_wrp_dbg(("DEBUG: classifier_wrp %s (%d) <--\n", __func__, + __LINE__)); + + return ret; +} + +static long do_ioctl_modify_insert_hm(unsigned long args, bool compat_mode) +{ + long ret = 0; + struct ioc_dpa_cls_hm_insert_params kparam; + uint8_t *data = NULL; + uint8_t sz; +#ifdef CONFIG_COMPAT + struct compat_ioc_dpa_cls_hm_insert_params uparam; + + if (compat_mode) { + if (copy_from_user(&uparam, (void *) args, sizeof(uparam))) { + pr_err("ERROR: %s, %s (%d): Read failed: user " + "space args.\n", __FILE__, __func__, __LINE__); + return -EBUSY; + } + + /* Transfer the data into the kernel space params: */ + ret = dpa_cls_hm_insert_params_compatcpy(&kparam, &uparam); + if (ret < 0) + return ret; + + } else +#endif /* CONFIG_COMPAT */ + if (copy_from_user(&kparam, (void *) args, sizeof(kparam))) { + pr_err("ERROR: %s, %s (%d): Read failed: user space " + "args.\n", __FILE__, __func__, __LINE__); + return -EBUSY; + } + + dpa_cls_wrp_dbg(("DEBUG: classifier_wrp %s (%d) -->\n", __func__, + __LINE__)); + + if (kparam.ins_params.type == DPA_CLS_HM_INSERT_CUSTOM) { + sz = kparam.ins_params.custom.size; + data = kzalloc(sz * sizeof(*data), GFP_KERNEL); + if (!data) { + pr_err("ERROR: %s, %s (%d): Failed to allocate memory " + "for data param for DPA_CLS_HM_INSERT_CUSTOM " + "parameter type.\n", + __FILE__, __func__, __LINE__); + return -ENOMEM; + } + + copy_from_user(data, kparam.ins_params.custom.data, sz); + kparam.ins_params.custom.data = data; + } + + ret = dpa_classif_modify_insert_hm(kparam.hmd, &kparam.ins_params, + kparam.modify_flags); + kfree(data); + + dpa_cls_wrp_dbg(("DEBUG: classifier_wrp %s (%d) <--\n", __func__, + __LINE__)); + + return ret; +} + +static long do_ioctl_set_vlan_hm(unsigned long args, bool compat_mode) +{ + long ret = 0; + struct ioc_dpa_cls_hm_vlan_params kparam; + struct dpa_cls_hm_vlan_resources *p_res = NULL; +#ifdef CONFIG_COMPAT + struct compat_ioc_dpa_cls_hm_vlan_params uparam; + + if (compat_mode) { + if (copy_from_user(&uparam, (void *) args, sizeof(uparam))) { + pr_err("ERROR: %s, %s (%d): Read failed: user " + "space args.\n", __FILE__, __func__, __LINE__); + return -EBUSY; + } + + /* Transfer the data into the kernel space params: */ + ret = dpa_cls_hm_vlan_params_compatcpy(&kparam, &uparam); + if (ret < 0) + return ret; + + } else +#endif /* CONFIG_COMPAT */ + if (copy_from_user(&kparam, (void *) args, sizeof(kparam))) { + pr_err("ERROR: %s, %s (%d): Read failed: user space " + "args.\n", __FILE__, __func__, __LINE__); + return -EBUSY; + } + + dpa_cls_wrp_dbg(("DEBUG: classifier_wrp %s (%d) -->\n", __func__, + __LINE__)); + + if (kparam.res.vlan_node) + p_res = &kparam.res; + + /* Translate FM_PCD file descriptor */ + if (!p_res) { + kparam.vlan_params.fm_pcd = + translate_fm_pcd_handle(kparam.vlan_params.fm_pcd); + if (!kparam.vlan_params.fm_pcd) + return -EINVAL; + } + + ret = dpa_classif_set_vlan_hm(&kparam.vlan_params, kparam.next_hmd, + &kparam.hmd, kparam.chain_head, + p_res); + if (ret < 0) + return ret; + +#ifdef CONFIG_COMPAT + if (compat_mode) { + uparam.hmd = kparam.hmd; + if (copy_to_user((void *) args, &uparam, sizeof(uparam))) { + pr_err("ERROR: %s, %s (%d): Write failed: result.\n", + __FILE__, __func__, __LINE__); + return -EBUSY; + } + } else +#endif /* CONFIG_COMPAT */ + if (copy_to_user((void *) args, &kparam, sizeof(kparam))) { + pr_err("ERROR: %s, %s (%d): Write failed: result.\n", + __FILE__, __func__, __LINE__); + return -EBUSY; + } + + dpa_cls_wrp_dbg(("DEBUG: classifier_wrp %s (%d) <--\n", __func__, + __LINE__)); + + return ret; + +} + +static long do_ioctl_modify_vlan_hm(unsigned long args, bool compat_mode) +{ + struct ioc_dpa_cls_hm_vlan_params kparam; +#ifdef CONFIG_COMPAT + long ret = 0; + struct compat_ioc_dpa_cls_hm_vlan_params uparam; + + if (compat_mode) { + if (copy_from_user(&uparam, (void *) args, sizeof(uparam))) { + pr_err("ERROR: %s, %s (%d): Read failed: user " + "space args.\n", __FILE__, __func__, __LINE__); + return -EBUSY; + } + + /* Transfer the data into the kernel space params: */ + ret = dpa_cls_hm_vlan_params_compatcpy(&kparam, &uparam); + if (ret < 0) + return ret; + + } else +#endif + if (copy_from_user(&kparam, (void *) args, sizeof(kparam))) { + pr_err("ERROR: %s, %s (%d): Read failed: user space args.\n", + __FILE__, __func__, __LINE__); + return -EBUSY; + } + + dpa_cls_wrp_dbg(("DEBUG: classifier_wrp %s (%d)\n", __func__, + __LINE__)); + + return dpa_classif_modify_vlan_hm(kparam.hmd, &kparam.vlan_params, + kparam.modify_flags); +} + +static long do_ioctl_set_nat_hm(unsigned long args, bool compat_mode) +{ + long ret = 0; + struct ioc_dpa_cls_hm_nat_params kparam; + struct dpa_cls_hm_nat_resources *p_res = NULL; + int type; + unsigned int sz; + uint8_t *options = NULL; +#ifdef CONFIG_COMPAT + struct compat_ioc_dpa_cls_hm_nat_params uparam; + + if (compat_mode) { + if (copy_from_user(&uparam, (void *) args, sizeof(uparam))) { + pr_err("ERROR: %s, %s (%d): Read failed: user " + "space args.\n", __FILE__, __func__, __LINE__); + return -EBUSY; + } + + /* Transfer the data into the kernel space params: */ + ret = dpa_cls_hm_nat_params_compatcpy(&kparam, &uparam); + if (ret < 0) + return ret; + + } else +#endif /* CONFIG_COMPAT */ + if (copy_from_user(&kparam, (void *) args, sizeof(kparam))) { + pr_err("ERROR: %s, %s (%d): Read failed: user space " + "args.\n", __FILE__, __func__, __LINE__); + return -EBUSY; + } + + dpa_cls_wrp_dbg(("DEBUG: classifier_wrp %s (%d) -->\n", __func__, + __LINE__)); + + if (kparam.res.l3_update_node || kparam.res.l4_update_node) + p_res = &kparam.res; + + /* Translate FM_PCD file descriptor */ + if (!p_res) { + kparam.nat_params.fm_pcd = + translate_fm_pcd_handle(kparam.nat_params.fm_pcd); + if (!kparam.nat_params.fm_pcd) + return -EINVAL; + } + + if (kparam.nat_params.type == DPA_CLS_HM_NAT_TYPE_NAT_PT) { + type = kparam.nat_params.nat_pt.type; + if (type == DPA_CLS_HM_NAT_PT_IPv6_TO_IPv4) { + sz = kparam.nat_params.nat_pt.new_header.ipv4. + options_size; + options = kzalloc(sz * sizeof(*options), GFP_KERNEL); + if (!options) { + pr_err("ERROR: %s, %s (%d): Failed to allocate" + " memory for options param for" + " DPA_CLS_HM_NAT_TYPE_NAT_PT parameter" + " type.\n", __FILE__, __func__, + __LINE__); + return -ENOMEM; + } + copy_from_user(options, + kparam.nat_params.nat_pt.new_header. + ipv4.options, sz); + kparam.nat_params.nat_pt.new_header.ipv4.options = + options; + } + } + + ret = dpa_classif_set_nat_hm(&kparam.nat_params, kparam.next_hmd, + &kparam.hmd, kparam.chain_head, + p_res); + kfree(options); + if (ret < 0) + return ret; + +#ifdef CONFIG_COMPAT + if (compat_mode) { + uparam.hmd = kparam.hmd; + if (copy_to_user((void *) args, &uparam, sizeof(uparam))) { + pr_err("ERROR: %s, %s (%d): Write failed: result.\n", + __FILE__, __func__, __LINE__); + return -EBUSY; + } + } else +#endif /* CONFIG_COMPAT */ + if (copy_to_user((void *) args, &kparam, sizeof(kparam))) { + pr_err("ERROR: %s, %s (%d): Write failed: result.\n", + __FILE__, __func__, __LINE__); + return -EBUSY; + } + + dpa_cls_wrp_dbg(("DEBUG: classifier_wrp %s (%d) <--\n", __func__, + __LINE__)); + + return ret; +} + +static long do_ioctl_modify_nat_hm(unsigned long args, bool compat_mode) +{ + struct ioc_dpa_cls_hm_nat_params kparam; + uint8_t *options = NULL; + long ret = 0; + int type; + unsigned int sz; +#ifdef CONFIG_COMPAT + struct compat_ioc_dpa_cls_hm_nat_params uparam; + + if (compat_mode) { + if (copy_from_user(&uparam, (void *) args, sizeof(uparam))) { + pr_err("ERROR: %s, %s (%d): Read failed: user " + "space args.\n", __FILE__, __func__, __LINE__); + return -EBUSY; + } + + /* Transfer the data into the kernel space params: */ + ret = dpa_cls_hm_nat_params_compatcpy(&kparam, &uparam); + if (ret < 0) + return ret; + + } else +#endif /* CONFIG_COMPAT */ + if (copy_from_user(&kparam, (void *) args, sizeof(kparam))) { + pr_err("ERROR: %s, %s (%d): Read failed: user space " + "args.\n", __FILE__, __func__, __LINE__); + return -EBUSY; + } + + if (kparam.nat_params.type == DPA_CLS_HM_NAT_TYPE_NAT_PT) { + type = kparam.nat_params.nat_pt.type; + if (type == DPA_CLS_HM_NAT_PT_IPv6_TO_IPv4) { + sz = kparam.nat_params.nat_pt.new_header.ipv4. + options_size; + options = kzalloc(sz * sizeof(*options), GFP_KERNEL); + if (!options) { + pr_err("ERROR: %s, %s (%d): Failed to allocate" + " memory for options param for" + " DPA_CLS_HM_NAT_TYPE_NAT_PT parameter" + " type.\n", __FILE__, __func__, + __LINE__); + return -ENOMEM; + } + copy_from_user(options, + kparam.nat_params.nat_pt.new_header. + ipv4.options, sz); + kparam.nat_params.nat_pt.new_header.ipv4.options = + options; + } + } + + dpa_cls_wrp_dbg(("DEBUG: classifier_wrp %s (%d)\n", __func__, + __LINE__)); + + ret = dpa_classif_modify_nat_hm(kparam.hmd, &kparam.nat_params, + kparam.modify_flags); + kfree(options); + + return ret; +} + +static long do_ioctl_set_update_hm(unsigned long args, bool compat_mode) +{ + long ret = 0; + struct ioc_dpa_cls_hm_update_params kparam; + struct dpa_cls_hm_update_resources *p_res = NULL; + unsigned int sz; + uint8_t *options = NULL; +#ifdef CONFIG_COMPAT + struct compat_ioc_dpa_cls_hm_update_params uparam; + + if (compat_mode) { + if (copy_from_user(&uparam, (void *) args, sizeof(uparam))) { + pr_err("ERROR: %s, %s (%d): Read failed: user " + "space args.\n", __FILE__, __func__, __LINE__); + return -EBUSY; + } + + /* Transfer the data into the kernel space params: */ + ret = dpa_cls_hm_update_params_compatcpy(&kparam, &uparam); + if (ret < 0) + return ret; + + } else +#endif /* CONFIG_COMPAT */ + if (copy_from_user(&kparam, (void *) args, sizeof(kparam))) { + pr_err("ERROR: %s, %s (%d): Read failed: user space " + "args.\n", __FILE__, __func__, __LINE__); + return -EBUSY; + } + + dpa_cls_wrp_dbg(("DEBUG: classifier_wrp %s (%d) -->\n", __func__, + __LINE__)); + + if (kparam.res.ip_frag_node || kparam.res.update_node) + p_res = &kparam.res; + + /* Translate FM_PCD file descriptor */ + if (!p_res) { + kparam.update_params.fm_pcd = + translate_fm_pcd_handle(kparam.update_params.fm_pcd); + if (!kparam.update_params.fm_pcd) + return -EINVAL; + } + + if (kparam.update_params.op_flags == DPA_CLS_HM_REPLACE_IPv6_BY_IPv4) { + sz = kparam.update_params.replace.new_ipv4_hdr.options_size; + options = kzalloc(sz * sizeof(*options), GFP_KERNEL); + if (!options) { + pr_err("ERROR: %s, %s (%d): Failed to allocate memory " + "for options param for" + " DPA_CLS_HM_REPLACE_IPv6_BY_IPv4" + " parameter type.\n", __FILE__, __func__, + __LINE__); + return -ENOMEM; + } + + copy_from_user(options, + kparam.update_params.replace.new_ipv4_hdr. + options, sz); + kparam.update_params.replace.new_ipv4_hdr.options = options; + } + + ret = dpa_classif_set_update_hm(&kparam.update_params, kparam.next_hmd, + &kparam.hmd, kparam.chain_head, + p_res); + kfree(options); + if (ret < 0) + return ret; + +#ifdef CONFIG_COMPAT + if (compat_mode) { + uparam.hmd = kparam.hmd; + if (copy_to_user((void *) args, &uparam, sizeof(uparam))) { + pr_err("ERROR: %s, %s (%d): Write failed: result.\n", + __FILE__, __func__, __LINE__); + return -EBUSY; + } + } else +#endif /* CONFIG_COMPAT */ + if (copy_to_user((void *) args, &kparam, sizeof(kparam))) { + pr_err("ERROR: %s, %s (%d): Write failed: result.\n", + __FILE__, __func__, __LINE__); + return -EBUSY; + } + + dpa_cls_wrp_dbg(("DEBUG: classifier_wrp %s (%d) <--\n", __func__, + __LINE__)); + + return ret; +} + +static long do_ioctl_modify_update_hm(unsigned long args, bool compat_mode) +{ + struct ioc_dpa_cls_hm_update_params kparam; + uint8_t *options = NULL; + long ret = 0; + unsigned int sz; +#ifdef CONFIG_COMPAT + struct compat_ioc_dpa_cls_hm_update_params uparam; + + if (compat_mode) { + if (copy_from_user(&uparam, (void *) args, sizeof(uparam))) { + pr_err("ERROR: %s, %s (%d): Read failed: user " + "space args.\n", __FILE__, __func__, __LINE__); + return -EBUSY; + } + + /* Transfer the data into the kernel space params: */ + ret = dpa_cls_hm_update_params_compatcpy(&kparam, &uparam); + if (ret < 0) + return ret; + + } else +#endif /* CONFIG_COMPAT */ + if (copy_from_user(&kparam, (void *) args, sizeof(kparam))) { + pr_err("ERROR: %s, %s (%d): Read failed: user " + "space args.\n", __FILE__, __func__, __LINE__); + return -EBUSY; + } + + dpa_cls_wrp_dbg(("DEBUG: classifier_wrp %s (%d)\n", __func__, + __LINE__)); + + if (kparam.update_params.op_flags == DPA_CLS_HM_REPLACE_IPv6_BY_IPv4) { + sz = kparam.update_params.replace.new_ipv4_hdr.options_size; + options = kzalloc(sz * sizeof(*options), GFP_KERNEL); + if (!options) { + pr_err("ERROR: %s, %s (%d): Failed to allocate memory " + "for options param for" + " DPA_CLS_HM_REPLACE_IPv6_BY_IPv4" + " parameter type.\n", __FILE__, __func__, + __LINE__); + return -ENOMEM; + } + + copy_from_user(options, + kparam.update_params.replace.new_ipv4_hdr. + options, sz); + kparam.update_params.replace.new_ipv4_hdr.options = options; + } + + ret = dpa_classif_modify_update_hm(kparam.hmd, &kparam.update_params, + kparam.modify_flags); + + kfree(options); + + return ret; +} + +static long do_ioctl_set_fwd_hm(unsigned long args, bool compat_mode) +{ + long ret = 0; + struct ioc_dpa_cls_hm_fwd_params kparam; + struct dpa_cls_hm_fwd_resources *p_res = NULL; +#ifdef CONFIG_COMPAT + struct compat_ioc_dpa_cls_hm_fwd_params uparam; + + if (compat_mode) { + if (copy_from_user(&uparam, (void *) args, sizeof(uparam))) { + pr_err("ERROR: %s, %s (%d): Read failed: user " + "space args.\n", __FILE__, __func__, __LINE__); + return -EBUSY; + } + + /* Transfer the data into the kernel space params: */ + ret = dpa_cls_hm_fwd_params_compatcpy(&kparam, &uparam); + if (ret < 0) + return ret; + + } else +#endif /* CONFIG_COMPAT */ + if (copy_from_user(&kparam, (void *) args, sizeof(kparam))) { + pr_err("ERROR: %s, %s (%d): Read failed: user space " + "args.\n", __FILE__, __func__, __LINE__); + return -EBUSY; + } + + dpa_cls_wrp_dbg(("DEBUG: classifier_wrp %s (%d) -->\n", __func__, + __LINE__)); + + if (kparam.res.ip_frag_node || kparam.res.fwd_node || + kparam.res.pppoe_node) + p_res = &kparam.res; + + /* Translate FM_PCD file descriptor */ + if (!p_res) { + kparam.fwd_params.fm_pcd = + translate_fm_pcd_handle(kparam.fwd_params.fm_pcd); + if (!kparam.fwd_params.fm_pcd) + return -EINVAL; + } + + ret = dpa_classif_set_fwd_hm(&kparam.fwd_params, kparam.next_hmd, + &kparam.hmd, kparam.chain_head, + p_res); + if (ret < 0) + return ret; + +#ifdef CONFIG_COMPAT + if (compat_mode) { + uparam.hmd = kparam.hmd; + if (copy_to_user((void *) args, &uparam, sizeof(uparam))) { + pr_err("ERROR: %s, %s (%d): Write failed: result.\n", + __FILE__, __func__, __LINE__); + return -EBUSY; + } + } else +#endif /* CONFIG_COMPAT */ + if (copy_to_user((void *) args, &kparam, sizeof(kparam))) { + pr_err("ERROR: %s, %s (%d): Write failed: result.\n", + __FILE__, __func__, __LINE__); + return -EBUSY; + } + + dpa_cls_wrp_dbg(("DEBUG: classifier_wrp %s (%d) <--\n", __func__, + __LINE__)); + + return ret; +} + +static long do_ioctl_modify_fwd_hm(unsigned long args, bool compat_mode) +{ + struct ioc_dpa_cls_hm_fwd_params kparam; +#ifdef CONFIG_COMPAT + long ret = 0; + struct compat_ioc_dpa_cls_hm_fwd_params uparam; + + if (compat_mode) { + if (copy_from_user(&uparam, (void *) args, sizeof(uparam))) { + pr_err("ERROR: %s, %s (%d): Read failed: user " + "space args.\n", __FILE__, __func__, __LINE__); + return -EBUSY; + } + + /* Transfer the data into the kernel space params: */ + ret = dpa_cls_hm_fwd_params_compatcpy(&kparam, &uparam); + if (ret < 0) + return ret; + + } else +#endif /* CONFIG_COMPAT */ + if (copy_from_user(&kparam, (void *) args, sizeof(kparam))) { + pr_err("ERROR: %s, %s (%d): Read failed: user space " + "args.\n", __FILE__, __func__, __LINE__); + return -EBUSY; + } + + dpa_cls_wrp_dbg(("DEBUG: classifier_wrp %s (%d)\n", __func__, + __LINE__)); + + return dpa_classif_modify_fwd_hm(kparam.hmd, &kparam.fwd_params, + kparam.modify_flags); +} + +static long do_ioctl_set_mpls_hm(unsigned long args, bool compat_mode) +{ + long ret = 0; + struct ioc_dpa_cls_hm_mpls_params kparam; + struct dpa_cls_hm_mpls_resources *p_res = NULL; +#ifdef CONFIG_COMPAT + struct compat_ioc_dpa_cls_hm_mpls_params uparam; + if (compat_mode) { + if (copy_from_user(&uparam, (void *) args, sizeof(uparam))) { + pr_err("ERROR: %s, %s (%d): Read failed: user " + "space args.\n", __FILE__, __func__, __LINE__); + return -EBUSY; + } + + /* Transfer the data into the kernel space params: */ + ret = dpa_cls_hm_mpls_params_compatcpy(&kparam, &uparam); + if (ret < 0) + return ret; + + } else +#endif /* CONFIG_COMPAT */ + if (copy_from_user(&kparam, (void *) args, sizeof(kparam))) { + pr_err("ERROR: %s, %s (%d): Read failed: user space " + "args.\n", __FILE__, __func__, __LINE__); + return -EBUSY; + } + + dpa_cls_wrp_dbg(("DEBUG: classifier_wrp %s (%d) -->\n", __func__, + __LINE__)); + + if (kparam.res.ins_rm_node) + p_res = &kparam.res; + + /* Translate FM_PCD file descriptor */ + if (!p_res) { + kparam.mpls_params.fm_pcd = + translate_fm_pcd_handle(kparam.mpls_params.fm_pcd); + if (!kparam.mpls_params.fm_pcd) + return -EINVAL; + } + + ret = dpa_classif_set_mpls_hm(&kparam.mpls_params, kparam.next_hmd, + &kparam.hmd, kparam.chain_head, + p_res); + if (ret < 0) + return ret; + +#ifdef CONFIG_COMPAT + if (compat_mode) { + uparam.hmd = kparam.hmd; + if (copy_to_user((void *) args, &uparam, sizeof(uparam))) { + pr_err("ERROR: %s, %s (%d): Write failed: result.\n", + __FILE__, __func__, __LINE__); + return -EBUSY; + } + } else +#endif /* CONFIG_COMPAT */ + if (copy_to_user((void *) args, &kparam, sizeof(kparam))) { + pr_err("ERROR: %s, %s (%d): Write failed: result.\n", + __FILE__, __func__, __LINE__); + return -EBUSY; + } + + dpa_cls_wrp_dbg(("DEBUG: classifier_wrp %s (%d) <--\n", __func__, + __LINE__)); + + return ret; +} + +static long do_ioctl_modify_mpls_hm(unsigned long args, bool compat_mode) +{ + struct ioc_dpa_cls_hm_mpls_params kparam; +#ifdef CONFIG_COMPAT + long ret = 0; + struct compat_ioc_dpa_cls_hm_mpls_params uparam; + + if (compat_mode) { + if (copy_from_user(&uparam, (void *) args, sizeof(uparam))) { + pr_err("ERROR: %s, %s (%d): Read failed: user " + "space args.\n", __FILE__, __func__, __LINE__); + return -EBUSY; + } + + /* Transfer the data into the kernel space params: */ + ret = dpa_cls_hm_mpls_params_compatcpy(&kparam, &uparam); + if (ret < 0) + return ret; + + } else +#endif /* CONFIG_COMPAT */ + if (copy_from_user(&kparam, (void *) args, sizeof(kparam))) { + pr_err("ERROR: %s, %s (%d): Read failed: user space " + "args.\n", __FILE__, __func__, __LINE__); + return -EBUSY; + } + + dpa_cls_wrp_dbg(("DEBUG: classifier_wrp %s (%d)\n", __func__, + __LINE__)); + + return dpa_classif_modify_mpls_hm(kparam.hmd, &kparam.mpls_params, + kparam.modify_flags); +} + +static long do_ioctl_mcast_create_group(unsigned long args, bool compat_mode) +{ + long ret = 0; + struct ioc_dpa_cls_mcast_group_params kparam; + struct dpa_cls_tbl_policer_params policer_params; +#ifdef CONFIG_COMPAT + struct compat_ioc_dpa_cls_mcast_group_params uparam; + if (compat_mode) { + if (copy_from_user(&uparam, (void *) args, sizeof(uparam))) { + pr_err("ERROR: %s, %s (%d): Read failed: user " + "space args.\n", __FILE__, __func__, __LINE__); + return -EBUSY; + } + + kparam.mcast_grp_params.first_member_params.policer_params = + &policer_params; + /* + * Transfer the data into the kernel space params: + */ + ret = dpa_cls_mcast_group_params_compatcpy(&kparam, &uparam); + if (ret < 0) + return ret; + + } else +#endif /* CONFIG_COMPAT */ + { + if (copy_from_user(&kparam, (void *) args, sizeof(kparam))) { + pr_err("ERROR: %s, %s (%d): Read failed: user space " + "args.\n", __FILE__, __func__, __LINE__); + return -EBUSY; + } + + if (kparam.mcast_grp_params.first_member_params. + policer_params) { + if (copy_from_user(&policer_params, + kparam.mcast_grp_params. + first_member_params.policer_params, + sizeof(policer_params))) { + pr_err("ERROR: %s, %s (%d): Read failed: " + "policer params.\n", __FILE__, __func__, + __LINE__); + return -EBUSY; + } + kparam.mcast_grp_params.first_member_params. + policer_params = + &policer_params; + } + } + /* + * Translate FM_PCD file descriptor + */ + if (!kparam.mcast_grp_params.group) { + kparam.mcast_grp_params.fm_pcd = + translate_fm_pcd_handle(kparam. + mcast_grp_params.fm_pcd); + if (!kparam.mcast_grp_params.fm_pcd) + return -EINVAL; + } + +#if (DPAA_VERSION >= 11) + ret = dpa_classif_mcast_create_group(&kparam.mcast_grp_params, + &kparam.grpd); +#else + pr_err("ERROR: %s, %s (%d): Multicast not supported on this" + "platform.\n", __FILE__, __func__, __LINE__); + return -EINVAL; +#endif + + if (ret < 0) + return ret; + +#ifdef CONFIG_COMPAT + if (compat_mode) { + uparam.grpd = kparam.grpd; + if (copy_to_user((void *) args, &uparam, sizeof(uparam))) { + pr_err("ERROR: %s, %s (%d): Write failed: result.\n", + __FILE__, __func__, __LINE__); + return -EBUSY; + } + } else +#endif /* CONFIG_COMPAT */ + if (copy_to_user((void *) args, &kparam, sizeof(kparam))) { + pr_err("ERROR: %s, %s (%d): Write failed: result.\n", + __FILE__, __func__, __LINE__); + return -EBUSY; + } + + dpa_cls_wrp_dbg(("DEBUG: classifier_wrp %s (%d) <--\n", __func__, + __LINE__)); + + return ret; +} + +static long do_ioctl_mcast_add_member(unsigned long args, bool compat_mode) +{ + long ret = 0; + struct ioc_dpa_cls_mcast_member_params kparam; + struct dpa_cls_tbl_policer_params policer_params; +#ifdef CONFIG_COMPAT + struct compat_ioc_dpa_cls_mcast_member_params uparam; + if (compat_mode) { + if (copy_from_user(&uparam, (void *) args, sizeof(uparam))) { + pr_err("ERROR: %s, %s (%d): Read failed: user " + "space args.\n", __FILE__, __func__, __LINE__); + return -EBUSY; + } + + kparam.member_params.policer_params = &policer_params; + /* + * Transfer the data into the kernel space params: + */ + ret = dpa_cls_mcast_member_params_compatcpy(&kparam, &uparam); + if (ret < 0) + return ret; + + } else +#endif /* CONFIG_COMPAT */ + { + if (copy_from_user(&kparam, (void *) args, sizeof(kparam))) { + pr_err("ERROR: %s, %s (%d): Read failed: user space " + "args.\n", __FILE__, __func__, __LINE__); + return -EBUSY; + } + + if (kparam.member_params.policer_params) { + if (copy_from_user(&policer_params, + kparam.member_params.policer_params, + sizeof(policer_params))) { + pr_err("ERROR: %s, %s (%d): Read failed: " + "policer params.\n", __FILE__, __func__, + __LINE__); + return -EBUSY; + } + + kparam.member_params.policer_params = &policer_params; + } + } +#if (DPAA_VERSION >= 11) + ret = dpa_classif_mcast_add_member(kparam.grpd, &kparam.member_params, + &kparam.md); + if (ret < 0) + return ret; +#else + pr_err("ERROR: %s, %s (%d): Multicast not supported on this" + "platform.\n", __FILE__, __func__, __LINE__); + return -EINVAL; +#endif + +#ifdef CONFIG_COMPAT + if (compat_mode) { + uparam.md = kparam.md; + if (copy_to_user((void *) args, &uparam, sizeof(uparam))) { + pr_err("ERROR: %s, %s (%d): Write failed: result.\n", + __FILE__, __func__, __LINE__); + return -EBUSY; + } + } else +#endif /* CONFIG_COMPAT */ + if (copy_to_user((void *) args, &kparam, sizeof(kparam))) { + pr_err("ERROR: %s, %s (%d): Write failed: result.\n", + __FILE__, __func__, __LINE__); + return -EBUSY; + } + + dpa_cls_wrp_dbg(("DEBUG: classifier_wrp %s (%d) <--\n", __func__, + __LINE__)); + + return ret; +} + + +static long do_ioctl_table_modify_miss_action(unsigned long args, + bool compat_mode) +{ + struct ioc_dpa_cls_tbl_miss_action kparam; + struct dpa_cls_tbl_policer_params policer_params; +#ifdef CONFIG_COMPAT + long ret = 0; + struct compat_ioc_dpa_cls_tbl_miss_action uparam; + + /* Prepare arguments */ + if (compat_mode) { + if (copy_from_user(&uparam, (void *) args, sizeof(uparam))) { + pr_err("ERROR: %s, %s (%d): Read failed: user " + "space args.\n", __FILE__, __func__, __LINE__); + return -EBUSY; + } + + kparam.miss_action.enq_params.policer_params = &policer_params; + /* Transfer the data into the kernel space params: */ + ret = dpa_cls_tbl_miss_action_params_compatcpy(&kparam, + &uparam); + if (ret < 0) + return ret; + } else +#endif /* CONFIG_COMPAT */ + { + if (copy_from_user(&kparam, (void *) args, sizeof(kparam))) { + pr_err("ERROR: %s, %s (%d): Read failed: user " + "space args.\n", __FILE__, __func__, __LINE__); + return -EBUSY; + } + + if (kparam.miss_action.enq_params.policer_params) { + if (copy_from_user(&policer_params, + kparam.miss_action.enq_params.policer_params, + sizeof(policer_params))) { + pr_err("ERROR: %s, %s (%d): Read failed: " + "policer params.\n", __FILE__, __func__, + __LINE__); + return -EBUSY; + } + + kparam.miss_action.enq_params.policer_params = + &policer_params; + } + } + dpa_cls_wrp_dbg(("DEBUG: classifier_wrp %s (%d)\n", __func__, + __LINE__)); + + /* Call function */ + return dpa_classif_table_modify_miss_action(kparam.td, + &kparam.miss_action); +} + +static long do_ioctl_table_insert_entry(unsigned long args, bool compat_mode) +{ + long ret = 0; + struct ioc_dpa_cls_tbl_entry_params kparam; + struct dpa_cls_tbl_policer_params policer_params; + uint8_t key_buf[DPA_OFFLD_MAXENTRYKEYSIZE]; + uint8_t mask_buf[DPA_OFFLD_MAXENTRYKEYSIZE]; +#ifdef CONFIG_COMPAT + struct compat_ioc_dpa_cls_tbl_entry_params uparam; + + /* Prepare arguments */ + if (compat_mode) { + if (copy_from_user(&uparam, (void *) args, sizeof(uparam))) { + pr_err("ERROR: %s, %s (%d): Read failed: user space " + "args.\n", __FILE__, __func__, __LINE__); + return -EBUSY; + } + + kparam.key.byte = key_buf; + kparam.key.mask = mask_buf; + kparam.key.size = DPA_OFFLD_MAXENTRYKEYSIZE; + + kparam.action.enq_params.policer_params = &policer_params; + + /* Transfer the data into the kernel space params: */ + ret = dpa_cls_tbl_entry_params_compatcpy(&kparam, &uparam); + if (ret < 0) + return ret; + } else +#endif /* CONFIG_COMPAT */ + { + if (copy_from_user(&kparam, (void *) args, sizeof(kparam))) { + pr_err("ERROR: %s, %s (%d): Read failed: user space " + "args.\n", __FILE__, __func__, __LINE__); + return -EBUSY; + } + + COPY_KEY_PARAMS; + + /* Check if we need to copy also the policer params */ + if ((kparam.action.type == DPA_CLS_TBL_ACTION_ENQ) && + (kparam.action.enq_params.policer_params)) { + if (copy_from_user(&policer_params, + kparam.action.enq_params.policer_params, + sizeof(policer_params))) { + pr_err("ERROR: %s, %s (%d): Read failed: " + "policer params.\n", __FILE__, __func__, + __LINE__); + return -EBUSY; + } + kparam.action.enq_params.policer_params = &policer_params; + } + } + + dpa_cls_wrp_dbg(("DEBUG: classifier_wrp %s (%d) -->\n", __func__, + __LINE__)); + + /* Call function */ + ret = dpa_classif_table_insert_entry(kparam.td, + &kparam.key, + &kparam.action, + kparam.priority, + &kparam.entry_id); + if (ret < 0) + return ret; + + /* In case of success return results to user space */ +#ifdef CONFIG_COMPAT + if (compat_mode) { + uparam.entry_id = kparam.entry_id; + + if (copy_to_user((void *) args, &uparam, sizeof(uparam))) { + pr_err("ERROR: %s, %s (%d): Write failed: result.\n", + __FILE__, __func__, __LINE__); + return -EBUSY; + } + } else +#endif /* CONFIG_COMPAT */ + if (copy_to_user((void *) args, &kparam, sizeof(kparam))) { + pr_err("ERROR: %s, %s (%d): Write failed: result.\n", + __FILE__, __func__, __LINE__); + return -EBUSY; + } + + dpa_cls_wrp_dbg(("DEBUG: classifier_wrp %s (%d) <--\n", __func__, + __LINE__)); + + return ret; +} + +static long do_ioctl_table_modify_entry_by_key(unsigned long args, + bool compat_mode) +{ + struct ioc_dpa_cls_tbl_entry_mod_by_key kparam; + struct dpa_offload_lookup_key new_key; + struct dpa_cls_tbl_action action; + struct dpa_cls_tbl_policer_params policer_params; + uint8_t key_buf[DPA_OFFLD_MAXENTRYKEYSIZE]; + uint8_t new_key_buf[DPA_OFFLD_MAXENTRYKEYSIZE]; + uint8_t mask_buf[DPA_OFFLD_MAXENTRYKEYSIZE]; + uint8_t new_mask_buf[DPA_OFFLD_MAXENTRYKEYSIZE]; +#ifdef CONFIG_COMPAT + long ret = 0; + struct compat_ioc_dpa_cls_tbl_entry_mod_by_key uparam; + + /* Prepare arguments */ + if (compat_mode) { + if (copy_from_user(&uparam, (void *) args, sizeof(uparam))) { + pr_err("ERROR: %s, %s (%d): Read failed: user " + "space args.\n", __FILE__, __func__, __LINE__); + return -EBUSY; + } + + kparam.key.byte = key_buf; + kparam.key.mask = mask_buf; + kparam.key.size = DPA_OFFLD_MAXENTRYKEYSIZE; + + new_key.byte = new_key_buf; + new_key.mask = new_mask_buf; + new_key.size = DPA_OFFLD_MAXENTRYKEYSIZE; + + kparam.mod_params.key = &new_key; + kparam.mod_params.action = &action; + kparam.mod_params.action->enq_params.policer_params = + &policer_params; + + /* Transfer the data into the kernel space params: */ + ret = dpa_cls_tbl_entry_mod_by_key_params_compatcpy(&kparam, + &uparam); + if (ret < 0) + return ret; + } else +#endif /* CONFIG_COMPAT */ + { + if (copy_from_user(&kparam, (void *) args, sizeof(kparam))) { + pr_err("ERROR: %s, %s (%d): Read failed: user " + "space args.\n", __FILE__, __func__, __LINE__); + return -EBUSY; + } + + COPY_KEY_PARAMS; + + /* Check if we need to copy the new key */ + COPY_NEW_KEY_PARAMS; + + if (kparam.mod_params.action) { + if (copy_from_user(&action, + kparam.mod_params.action, + sizeof(struct dpa_cls_tbl_action))) { + pr_err("ERROR: %s, %s (%d): Read failed: " + "new action params.\n", __FILE__, + __func__, __LINE__); + return -EBUSY; + } + kparam.mod_params.action = &action; + + /* Check if we need to copy policer params */ + if ((kparam.mod_params.action->type == + DPA_CLS_TBL_ACTION_ENQ) && + (kparam.mod_params.action->enq_params. + policer_params)) { + if (copy_from_user(&policer_params, + kparam.mod_params. + action->enq_params. + policer_params, + sizeof(policer_params))) { + pr_err("ERROR: %s, %s (%d): Read " + "failed: new policer params.\n", __FILE__, + __func__, __LINE__); + return -EBUSY; + } + kparam.mod_params.action->enq_params. + policer_params = + &policer_params; + } + } + } + + dpa_cls_wrp_dbg(("DEBUG: classifier_wrp %s (%d)\n", __func__, + __LINE__)); + + /* Call function */ + return dpa_classif_table_modify_entry_by_key(kparam.td, + &kparam.key, + &kparam.mod_params); + +} + +static long do_ioctl_table_modify_entry_by_ref(unsigned long args, + bool compat_mode) +{ + struct ioc_dpa_cls_tbl_entry_mod_by_ref kparam; + struct dpa_offload_lookup_key new_key; + struct dpa_cls_tbl_action action; + struct dpa_cls_tbl_policer_params policer_params; + uint8_t new_key_buf[DPA_OFFLD_MAXENTRYKEYSIZE]; + uint8_t new_mask_buf[DPA_OFFLD_MAXENTRYKEYSIZE]; +#ifdef CONFIG_COMPAT + long ret = 0; + struct compat_ioc_dpa_cls_tbl_entry_mod_by_ref uparam; + + /* Prepare arguments */ + if (compat_mode) { + if (copy_from_user(&uparam, (void *) args, sizeof(uparam))) { + pr_err("ERROR: %s, %s (%d): Read failed: user " + "space args.\n", __FILE__, __func__, __LINE__); + return -EBUSY; + } + + new_key.byte = new_key_buf; + new_key.mask = new_mask_buf; + new_key.size = DPA_OFFLD_MAXENTRYKEYSIZE; + + memset(&kparam, 0, + sizeof(struct ioc_dpa_cls_tbl_entry_mod_by_ref)); + kparam.mod_params.key = &new_key; + kparam.mod_params.action = &action; + kparam.mod_params.action->enq_params.policer_params = + &policer_params; + + /* Transfer the data into the kernel space params: */ + ret = dpa_cls_tbl_entry_mod_by_ref_params_compatcpy(&kparam, + &uparam); + if (ret < 0) + return ret; + } else +#endif /* CONFIG_COMPAT */ + { + if (copy_from_user(&kparam, (void *) args, sizeof(kparam))) { + pr_err("ERROR: %s, %s (%d): Read failed: user " + "space args.\n", __FILE__, __func__, __LINE__); + return -EBUSY; + } + + /* Check if we need to copy the new key */ + COPY_NEW_KEY_PARAMS; + + if (kparam.mod_params.action) { + if (copy_from_user(&action, + kparam.mod_params.action, + sizeof(struct dpa_cls_tbl_action))) { + pr_err("ERROR: %s, %s (%d): Read failed: " + "new action params.\n", __FILE__, + __func__, __LINE__); + return -EBUSY; + } + kparam.mod_params.action = &action; + + /* Check if we need to copy policer params */ + if ((kparam.mod_params.action->type == + DPA_CLS_TBL_ACTION_ENQ) && + (kparam.mod_params.action->enq_params. + policer_params)) { + if (copy_from_user(&policer_params, + kparam.mod_params. + action->enq_params. + policer_params, + sizeof(policer_params))) { + pr_err("ERROR: %s, %s (%d): Read " + "failed: new policer params.\n", __FILE__, + __func__, __LINE__); + return -EBUSY; + } + kparam.mod_params.action->enq_params. + policer_params = + &policer_params; + } + } + } + + dpa_cls_wrp_dbg(("DEBUG: classifier_wrp %s (%d)\n", __func__, + __LINE__)); + + /* Call function */ + return dpa_classif_table_modify_entry_by_ref(kparam.td, + kparam.entry_id, + &kparam.mod_params); +} + +static long do_ioctl_table_lookup_by_key(unsigned long args, bool compat_mode) +{ + long ret = 0; + struct ioc_dpa_cls_tbl_lookup_by_key kparam; + uint8_t key_buf[DPA_OFFLD_MAXENTRYKEYSIZE]; + uint8_t mask_buf[DPA_OFFLD_MAXENTRYKEYSIZE]; +#ifdef CONFIG_COMPAT + struct compat_ioc_dpa_cls_tbl_lookup_by_key uparam; + + /* Prepare arguments */ + if (compat_mode) { + if (copy_from_user(&uparam, (void *) args, sizeof(uparam))) { + pr_err("ERROR: %s, %s (%d): Read failed: user space " + "args.\n", __FILE__, __func__, __LINE__); + return -EBUSY; + } + + kparam.key.byte = key_buf; + kparam.key.mask = mask_buf; + kparam.key.size = DPA_OFFLD_MAXENTRYKEYSIZE; + + /* Transfer the data into the kernel space params: */ + ret = dpa_cls_tbl_lookup_by_key_params_compatcpy(&kparam, + &uparam); + if (ret < 0) + return ret; + } else +#endif /* CONFIG_COMPAT */ + { + if (copy_from_user(&kparam, (void *) args, sizeof(kparam))) { + pr_err("ERROR: %s, %s (%d): Read failed: user space " + "args.\n", __FILE__, __func__, __LINE__); + return -EBUSY; + } + + COPY_KEY_PARAMS; + } + + dpa_cls_wrp_dbg(("DEBUG: classifier_wrp %s (%d) -->\n", __func__, + __LINE__)); + + /* Call function */ + ret = dpa_classif_table_lookup_by_key(kparam.td, + &kparam.key, + &kparam.action); + if (ret < 0) + return ret; + + /* Return results to user space */ +#ifdef CONFIG_COMPAT + if (compat_mode) { + ret = dpa_cls_tbl_action_params_rcompatcpy(&uparam.action, + &kparam.action); + if (ret < 0) + return ret; + + if (copy_to_user((void *) args, &uparam, sizeof(uparam))) { + pr_err("ERROR: %s, %s (%d): Write failed: result.\n", + __FILE__, __func__, __LINE__); + return -EBUSY; + } + } else +#endif /* CONFIG_COMPAT */ + if (copy_to_user((void *) args, &kparam, sizeof(kparam))) { + pr_err("ERROR: %s, %s (%d): Write failed: result.\n", + __FILE__, __func__, __LINE__); + return -EBUSY; + } + + dpa_cls_wrp_dbg(("DEBUG: classifier_wrp %s (%d) <--\n", __func__, + __LINE__)); + + return ret; +} + +static long do_ioctl_table_lookup_by_ref(unsigned long args, bool compat_mode) +{ + long ret = 0; + struct ioc_dpa_cls_tbl_lookup_by_ref kparam; +#ifdef CONFIG_COMPAT + struct compat_ioc_dpa_cls_tbl_lookup_by_ref uparam; + + /* Prepare arguments */ + if (compat_mode) { + if (copy_from_user(&uparam, (void *) args, sizeof(uparam))) { + pr_err("ERROR: %s, %s (%d): Read failed: user space " + "args.\n", __FILE__, __func__, __LINE__); + return -EBUSY; + } + + /* Transfer the data into the kernel space params: */ + ret = dpa_cls_tbl_lookup_by_ref_params_compatcpy(&kparam, + &uparam); + if (ret < 0) + return ret; + } else +#endif /* CONFIG_COMPAT */ + /* Prepare arguments */ + if (copy_from_user(&kparam, (void *) args, sizeof(kparam))) { + pr_err("ERROR: %s, %s (%d): Read failed: user space " + "args.\n", __FILE__, __func__, __LINE__); + return -EBUSY; + } + + dpa_cls_wrp_dbg(("DEBUG: classifier_wrp %s (%d) -->\n", __func__, + __LINE__)); + + /* Call function */ + ret = dpa_classif_table_lookup_by_ref(kparam.td, + kparam.entry_id, + &kparam.action); + if (ret < 0) + return ret; + + /* Return results to user space */ +#ifdef CONFIG_COMPAT + if (compat_mode) { + ret = dpa_cls_tbl_action_params_rcompatcpy(&uparam.action, + &kparam.action); + if (ret < 0) + return ret; + + if (copy_to_user((void *)args, &uparam, sizeof(uparam))) { + pr_err("ERROR: %s, %s (%d): Write failed: result.\n", + __FILE__, __func__, __LINE__); + return -EBUSY; + } + } else +#endif /* CONFIG_COMPAT */ + if (copy_to_user((void *) args, &kparam, sizeof(kparam))) { + pr_err("ERROR: %s, %s (%d): Write failed: result.\n", + __FILE__, __func__, __LINE__); + return -EBUSY; + } + + dpa_cls_wrp_dbg(("DEBUG: classifier_wrp %s (%d) <--\n", __func__, + __LINE__)); + + return ret; +} + +static long do_ioctl_table_delete_entry_by_key(unsigned long args, + bool compat_mode) +{ + struct ioc_dpa_cls_tbl_entry_by_key kparam; + uint8_t key_buf[DPA_OFFLD_MAXENTRYKEYSIZE]; + uint8_t mask_buf[DPA_OFFLD_MAXENTRYKEYSIZE]; +#ifdef CONFIG_COMPAT + long ret = 0; + struct compat_ioc_dpa_cls_tbl_entry_by_key uparam; + + /* Prepare arguments */ + if (compat_mode) { + if (copy_from_user(&uparam, (void *) args, sizeof(uparam))) { + pr_err("ERROR: %s, %s (%d): Read failed: user " + "space args.\n", __FILE__, __func__, __LINE__); + return -EBUSY; + } + + kparam.key.byte = key_buf; + kparam.key.mask = mask_buf; + kparam.key.size = DPA_OFFLD_MAXENTRYKEYSIZE; + + /* Transfer the data into the kernel space params: */ + ret = dpa_cls_tbl_entry_by_key_params_compatcpy(&kparam, + &uparam); + if (ret < 0) + return ret; + } else +#endif /* CONFIG_COMPAT */ + { + /* Prepare arguments */ + if (copy_from_user(&kparam, (void *) args, sizeof(kparam))) { + pr_err("ERROR: %s, %s (%d): Read failed: user " + "space args.\n", __FILE__, __func__, __LINE__); + return -EBUSY; + } + + COPY_KEY_PARAMS; + } + + dpa_cls_wrp_dbg(("DEBUG: classifier_wrp %s (%d)\n", __func__, + __LINE__)); + + /* Call function */ + return dpa_classif_table_delete_entry_by_key(kparam.td, + &kparam.key); +} + +static long do_ioctl_table_get_stats_by_key(unsigned long args, + bool compat_mode) +{ + long ret = 0; + struct ioc_dpa_cls_tbl_entry_stats_by_key kparam; + uint8_t key_buf[DPA_OFFLD_MAXENTRYKEYSIZE]; + uint8_t mask_buf[DPA_OFFLD_MAXENTRYKEYSIZE]; +#ifdef CONFIG_COMPAT + struct compat_ioc_dpa_cls_tbl_entry_stats_by_key uparam; + + /* Prepare arguments */ + if (compat_mode) { + if (copy_from_user(&uparam, (void *) args, sizeof(uparam))) { + pr_err("ERROR: %s, %s (%d): Read failed: user " + "space args.\n", __FILE__, __func__, __LINE__); + return -EBUSY; + } + + kparam.key.byte = key_buf; + kparam.key.mask = mask_buf; + kparam.key.size = DPA_OFFLD_MAXENTRYKEYSIZE; + + /* Transfer the data into the kernel space params: */ + ret = dpa_cls_tbl_entry_stats_by_key_params_compatcpy(&kparam, + &uparam); + if (ret < 0) + return ret; + } else +#endif /* CONFIG_COMPAT */ + { + /* Prepare arguments */ + if (copy_from_user(&kparam, (void *) args, sizeof(kparam))) { + pr_err("ERROR: %s, %s (%d): Read failed: user space " + "args.\n", __FILE__, __func__, __LINE__); + return -EBUSY; + } + + COPY_KEY_PARAMS; + } + + dpa_cls_wrp_dbg(("DEBUG: classifier_wrp %s (%d) -->\n", __func__, + __LINE__)); + + /* Call function */ + ret = dpa_classif_table_get_entry_stats_by_key(kparam.td, + &kparam.key, + &kparam.stats); + if (ret < 0) + return ret; + + /* Return results to user space */ +#ifdef CONFIG_COMPAT + if (compat_mode) { + memcpy(&uparam.stats, &kparam.stats, + sizeof(struct dpa_cls_tbl_entry_stats)); + + if (copy_to_user((void *) args, &uparam, sizeof(uparam))) { + pr_err("ERROR: %s, %s (%d): Write failed: result.\n", + __FILE__, __func__, __LINE__); + return -EBUSY; + } + } else +#endif /* CONFIG_COMPAT */ + if (copy_to_user((void *) args, &kparam, sizeof(kparam))) { + pr_err("ERROR: %s, %s (%d): Write failed: result.\n", + __FILE__, __func__, __LINE__); + return -EBUSY; + } + + dpa_cls_wrp_dbg(("DEBUG: classifier_wrp %s (%d) <--\n", __func__, + __LINE__)); + + return ret; +} + +void *translate_fm_pcd_handle(void *fm_pcd) +{ + struct file *fm_pcd_file; + t_LnxWrpFmDev *fm_wrapper_dev; + + fm_pcd_file = fcheck((unsigned long)fm_pcd); + if (!fm_pcd_file) { + pr_err("ERROR: %s, %s (%d): Could not translate PCD handle " + "fm_pcd=0x%p.\n", __FILE__, __func__, __LINE__, fm_pcd); + return NULL; + } + fm_wrapper_dev = (t_LnxWrpFmDev *)fm_pcd_file->private_data; + BUG_ON(!fm_wrapper_dev); + BUG_ON(!fm_wrapper_dev->h_PcdDev); + + return (void *)fm_wrapper_dev->h_PcdDev; +} + +#ifdef CONFIG_COMPAT + +int dpa_cls_tbl_entry_by_key_params_compatcpy( + struct ioc_dpa_cls_tbl_entry_by_key *kparam, + const struct compat_ioc_dpa_cls_tbl_entry_by_key *uparam) +{ + kparam->td = uparam->td; + return dpa_lookup_key_params_compatcpy(&kparam->key, &uparam->key); +} + +int dpa_cls_tbl_entry_stats_by_key_params_compatcpy( + struct ioc_dpa_cls_tbl_entry_stats_by_key *kparam, + const struct compat_ioc_dpa_cls_tbl_entry_stats_by_key *uparam) +{ + int err = 0; + + kparam->td = uparam->td; + + err = dpa_lookup_key_params_compatcpy(&kparam->key, &uparam->key); + if (err < 0) + return err; + + memcpy(&kparam->stats, + &uparam->stats, + sizeof(struct dpa_cls_tbl_entry_stats)); + + return 0; +} + +int dpa_lookup_key_params_compatcpy( + struct dpa_offload_lookup_key *kparam, + const struct compat_ioc_dpa_offld_lookup_key *uparam) +{ + BUG_ON(!uparam->byte); + BUG_ON(!kparam->byte); + BUG_ON(kparam->size < uparam->size); + BUG_ON(uparam->size <= 0); + + kparam->size = uparam->size; + if (copy_from_user(kparam->byte, compat_ptr(uparam->byte), + uparam->size)) { + pr_err("ERROR: %s, %s (%d): Read failed: lookup key.\n", + __FILE__, __func__, __LINE__); + return -EBUSY; + } + + if (compat_ptr(uparam->mask)) { + BUG_ON(!kparam->mask); + if (copy_from_user(kparam->mask, compat_ptr(uparam->mask), + uparam->size)) { + pr_err("ERROR: %s, %s (%d): Read failed: key mask.\n", + __FILE__, __func__, __LINE__); + return -EBUSY; + } + } else + kparam->mask = NULL; + + return 0; +} + +int dpa_cls_tbl_entry_params_compatcpy( + struct ioc_dpa_cls_tbl_entry_params *kparam, + const struct compat_ioc_dpa_cls_tbl_entry_params *uparam) +{ + int err; + + kparam->td = uparam->td; + kparam->priority = uparam->priority; + kparam->entry_id = uparam->entry_id; + + err = dpa_lookup_key_params_compatcpy(&kparam->key, &uparam->key); + if (err < 0) + return err; + + return dpa_cls_tbl_action_params_compatcpy(&kparam->action, + &uparam->action); +} + +int dpa_cls_tbl_action_params_compatcpy( + struct dpa_cls_tbl_action *kparam, + const struct dpa_cls_compat_tbl_action *uparam) +{ + kparam->type = uparam->type; + kparam->enable_statistics = uparam->enable_statistics; + + switch (uparam->type) { + case DPA_CLS_TBL_ACTION_ENQ: + kparam->enq_params.override_fqid = + uparam->enq_params.override_fqid; + kparam->enq_params.new_fqid = + uparam->enq_params.new_fqid; + kparam->enq_params.hmd = uparam->enq_params.hmd; + kparam->enq_params.new_rel_vsp_id = + uparam->enq_params.new_rel_vsp_id; + if (compat_ptr(uparam->enq_params.policer_params)) { + BUG_ON(!kparam->enq_params.policer_params); + if (copy_from_user(kparam->enq_params.policer_params, + compat_ptr(uparam->enq_params.policer_params), + sizeof(struct dpa_cls_tbl_policer_params))) { + pr_err("ERROR: %s, %s (%d): Read failed: " + "policer params.\n", __FILE__, __func__, + __LINE__); + return -EBUSY; + } + } else + kparam->enq_params.policer_params = NULL; + break; + case DPA_CLS_TBL_ACTION_NEXT_TABLE: + kparam->next_table_params.next_td = + uparam->next_table_params.next_td; + break; + case DPA_CLS_TBL_ACTION_MCAST: + kparam->mcast_params.grpd = uparam->mcast_params.grpd; + kparam->mcast_params.hmd = uparam->mcast_params.hmd; + break; + default: + break; + } + + return 0; +} + +int dpa_cls_tbl_action_params_rcompatcpy( + struct dpa_cls_compat_tbl_action *uparam, + const struct dpa_cls_tbl_action *kparam) +{ + uparam->type = kparam->type; + uparam->enable_statistics = kparam->enable_statistics; + + switch (kparam->type) { + case DPA_CLS_TBL_ACTION_ENQ: + uparam->enq_params.override_fqid = + kparam->enq_params.override_fqid; + uparam->enq_params.new_fqid = + kparam->enq_params.new_fqid; + uparam->enq_params.hmd = kparam->enq_params.hmd; + + /* + * Policer params structure address has no meaning in user + * space + */ + uparam->enq_params.policer_params = 0; + + break; + case DPA_CLS_TBL_ACTION_NEXT_TABLE: + uparam->next_table_params.next_td = + kparam->next_table_params.next_td; + break; + default: + break; + } + + return 0; +} + +int dpa_cls_tbl_params_compatcpy( + struct ioc_dpa_cls_tbl_params *kparam, + const struct compat_ioc_dpa_cls_tbl_params *uparam) +{ + kparam->table_params.cc_node = compat_get_id2ptr( + uparam->table_params.cc_node, + FM_MAP_TYPE_PCD_NODE); + if (compat_ptr(uparam->table_params.distribution)) + kparam->table_params.distribution = compat_get_id2ptr( + uparam->table_params.distribution, + FM_MAP_TYPE_PCD_NODE); + if (compat_ptr(uparam->table_params.classification)) + kparam->table_params.classification = compat_get_id2ptr( + uparam->table_params.classification, + FM_MAP_TYPE_PCD_NODE); + + kparam->table_params.type = uparam->table_params.type; + kparam->table_params.entry_mgmt = uparam->table_params.entry_mgmt; + kparam->table_params.prefilled_entries = + uparam->table_params.prefilled_entries; + + switch (uparam->table_params.type) { + case DPA_CLS_TBL_INDEXED: + memcpy(&kparam->table_params.indexed_params, + &uparam->table_params.indexed_params, + sizeof(struct dpa_cls_tbl_indexed_params)); + break; + case DPA_CLS_TBL_HASH: + memcpy(&kparam->table_params.hash_params, + &uparam->table_params.hash_params, + sizeof(struct dpa_cls_tbl_hash_params)); + + break; + case DPA_CLS_TBL_EXACT_MATCH: + memcpy(&kparam->table_params.exact_match_params, + &uparam->table_params.exact_match_params, + sizeof(struct dpa_cls_tbl_exact_match_params)); + + break; + } + + return 0; +} + +int dpa_cls_tbl_params_rcompatcpy( + struct compat_ioc_dpa_cls_tbl_params *uparam, + const struct ioc_dpa_cls_tbl_params *kparam) +{ + uparam->table_params.cc_node = compat_get_ptr2id( + kparam->table_params.cc_node, + FM_MAP_TYPE_PCD_NODE); + if (kparam->table_params.distribution) + uparam->table_params.distribution = compat_get_ptr2id( + kparam->table_params.distribution, + FM_MAP_TYPE_PCD_NODE); + if (kparam->table_params.classification) + uparam->table_params.classification = compat_get_ptr2id( + kparam->table_params.classification, + FM_MAP_TYPE_PCD_NODE); + + uparam->table_params.type = kparam->table_params.type; + uparam->table_params.entry_mgmt = kparam->table_params.entry_mgmt; + uparam->table_params.prefilled_entries = + kparam->table_params.prefilled_entries; + + switch (kparam->table_params.type) { + case DPA_CLS_TBL_INDEXED: + memcpy(&uparam->table_params.indexed_params, + &kparam->table_params.indexed_params, + sizeof(struct dpa_cls_tbl_indexed_params)); + break; + case DPA_CLS_TBL_HASH: + memcpy(&uparam->table_params.hash_params, + &kparam->table_params.hash_params, + sizeof(struct dpa_cls_tbl_hash_params)); + + break; + case DPA_CLS_TBL_EXACT_MATCH: + memcpy(&uparam->table_params.exact_match_params, + &kparam->table_params.exact_match_params, + sizeof(struct dpa_cls_tbl_exact_match_params)); + + break; + } + + return 0; +} + +int dpa_cls_tbl_miss_action_params_compatcpy( + struct ioc_dpa_cls_tbl_miss_action *kparam, + const struct compat_ioc_dpa_cls_tbl_miss_action *uparam) +{ + kparam->td = uparam->td; + + return dpa_cls_tbl_action_params_compatcpy(&kparam->miss_action, + &uparam->miss_action); +} + +int dpa_cls_tbl_entry_mod_by_key_params_compatcpy( + struct ioc_dpa_cls_tbl_entry_mod_by_key *kparam, + const struct compat_ioc_dpa_cls_tbl_entry_mod_by_key *uparam) +{ + int err; + + kparam->td = uparam->td; + + err = dpa_lookup_key_params_compatcpy(&kparam->key, &uparam->key); + if (err < 0) + return err; + + return dpa_cls_tbl_entry_mod_params_compatcpy(&kparam->mod_params, + &uparam->mod_params); +} + +int dpa_cls_tbl_entry_mod_params_compatcpy( + struct dpa_cls_tbl_entry_mod_params *kparam, + const struct dpa_cls_compat_tbl_entry_mod_params *uparam) +{ + int err = 0; + + kparam->type = uparam->type; + + if (compat_ptr(uparam->key)) { + struct compat_ioc_dpa_offld_lookup_key key; + + BUG_ON(!kparam->key); + if (copy_from_user(&key, compat_ptr(uparam->key), + sizeof(struct compat_ioc_dpa_offld_lookup_key))) { + pr_err("ERROR: %s, %s (%d): Read failed: New key " + "parameters.\n", __FILE__, __func__, __LINE__); + return -EBUSY; + } + + err = dpa_lookup_key_params_compatcpy(kparam->key, &key); + } else + kparam->key = NULL; + + if (err < 0) + return err; + + if (compat_ptr(uparam->action)) { + struct dpa_cls_compat_tbl_action action; + + BUG_ON(!kparam->action); + + if (copy_from_user(&action, compat_ptr(uparam->action), + sizeof(struct dpa_cls_compat_tbl_action))) { + pr_err("ERROR: %s, %s (%d): Read failed: New action " + "parameters.\n", __FILE__, __func__, __LINE__); + return -EBUSY; + } + + err = dpa_cls_tbl_action_params_compatcpy(kparam->action, + &action); + } else + kparam->action = NULL; + + return err; +} + +int dpa_cls_tbl_entry_mod_by_ref_params_compatcpy( + struct ioc_dpa_cls_tbl_entry_mod_by_ref *kparam, + const struct compat_ioc_dpa_cls_tbl_entry_mod_by_ref *uparam) +{ + kparam->td = uparam->td; + kparam->entry_id = uparam->entry_id; + + return dpa_cls_tbl_entry_mod_params_compatcpy(&kparam->mod_params, + &uparam->mod_params); +} + +int dpa_cls_tbl_lookup_by_key_params_compatcpy( + struct ioc_dpa_cls_tbl_lookup_by_key *kparam, + const struct compat_ioc_dpa_cls_tbl_lookup_by_key *uparam) +{ + kparam->td = uparam->td; + + return dpa_lookup_key_params_compatcpy(&kparam->key, &uparam->key); +} + +int dpa_cls_tbl_lookup_by_ref_params_compatcpy( + struct ioc_dpa_cls_tbl_lookup_by_ref *kparam, + const struct compat_ioc_dpa_cls_tbl_lookup_by_ref *uparam) +{ + kparam->td = uparam->td; + kparam->entry_id = uparam->entry_id; + + return 0; +} + +int dpa_cls_hm_remove_params_compatcpy( + struct ioc_dpa_cls_hm_remove_params *kparam, + const struct compat_ioc_dpa_cls_hm_remove_params *uparam) +{ + kparam->rm_params.type = uparam->rm_params.type; + memcpy(&kparam->rm_params.custom, &uparam->rm_params.custom, + sizeof(struct dpa_cls_hm_custom_rm_params)); + + kparam->rm_params.fm_pcd = compat_ptr(uparam->rm_params.fm_pcd); + kparam->next_hmd = uparam->next_hmd; + kparam->hmd = uparam->hmd; + + if (uparam->res.remove_node) + kparam->res.remove_node = compat_get_id2ptr( + uparam->res.remove_node, + FM_MAP_TYPE_PCD_NODE); + else + kparam->res.remove_node = NULL; + + kparam->chain_head = uparam->chain_head; + kparam->modify_flags = uparam->modify_flags; + + return 0; +} + +int dpa_cls_hm_insert_params_compatcpy( + struct ioc_dpa_cls_hm_insert_params *kparam, + const struct compat_ioc_dpa_cls_hm_insert_params *uparam) +{ + int type; + + kparam->ins_params.type = uparam->ins_params.type; + + type = kparam->ins_params.type; + switch (type) { + case DPA_CLS_HM_INSERT_CUSTOM: + kparam->ins_params.custom.offset = uparam->ins_params. + custom.offset; + kparam->ins_params.custom.size = uparam->ins_params. + custom.size; + kparam->ins_params.custom.data = compat_ptr(uparam->ins_params. + custom.data); + break; + case DPA_CLS_HM_INSERT_ETHERNET: + memcpy(&kparam->ins_params.eth, &uparam->ins_params.eth, + sizeof(struct dpa_cls_hm_eth_ins_params)); + break; + case DPA_CLS_HM_INSERT_PPPoE: + memcpy(&kparam->ins_params.pppoe, &uparam->ins_params.pppoe, + sizeof(struct dpa_cls_hm_pppoe_ins_params)); + break; + case DPA_CLS_HM_INSERT_PPP: + kparam->ins_params.ppp_pid = uparam->ins_params.ppp_pid; + break; + default: + break; + } + + kparam->ins_params.fm_pcd = compat_ptr(uparam->ins_params.fm_pcd); + kparam->next_hmd = uparam->next_hmd; + kparam->hmd = uparam->hmd; + if (uparam->res.insert_node) + kparam->res.insert_node = compat_get_id2ptr( + uparam->res.insert_node, + FM_MAP_TYPE_PCD_NODE); + else + kparam->res.insert_node = NULL; + + kparam->chain_head = uparam->chain_head; + kparam->modify_flags = uparam->modify_flags; + + return 0; +} + +int dpa_cls_hm_vlan_params_compatcpy( + struct ioc_dpa_cls_hm_vlan_params *kparam, + const struct compat_ioc_dpa_cls_hm_vlan_params *uparam) +{ + int type; + + kparam->vlan_params.type = uparam->vlan_params.type; + type = kparam->vlan_params.type; + switch (type) { + case DPA_CLS_HM_VLAN_INGRESS: + memcpy(&kparam->vlan_params.ingress, + &uparam->vlan_params.ingress, + sizeof(struct dpa_cls_hm_ingress_vlan_params)); + break; + case DPA_CLS_HM_VLAN_EGRESS: + memcpy(&kparam->vlan_params.egress, + &uparam->vlan_params.egress, + sizeof(struct dpa_cls_hm_egress_vlan_params)); + break; + default: + break; + } + + kparam->vlan_params.fm_pcd = compat_ptr(uparam->vlan_params.fm_pcd); + kparam->next_hmd = uparam->next_hmd; + kparam->hmd = uparam->hmd; + + if (uparam->res.vlan_node) + kparam->res.vlan_node = compat_get_id2ptr( + uparam->res.vlan_node, + FM_MAP_TYPE_PCD_NODE); + else + kparam->res.vlan_node = NULL; + + kparam->chain_head = uparam->chain_head; + kparam->modify_flags = uparam->modify_flags; + + return 0; +} + +int dpa_cls_hm_nat_params_compatcpy( + struct ioc_dpa_cls_hm_nat_params *kparam, + const struct compat_ioc_dpa_cls_hm_nat_params *uparam) +{ + int type; + kparam->nat_params.flags = uparam->nat_params.flags; + kparam->nat_params.proto = uparam->nat_params.proto; + kparam->nat_params.type = uparam->nat_params.type; + + if (kparam->nat_params.type == DPA_CLS_HM_NAT_TYPE_NAT_PT) { + kparam->nat_params.nat_pt.type = uparam->nat_params.nat_pt.type; + type = kparam->nat_params.nat_pt.type; + switch (type) { + case DPA_CLS_HM_NAT_PT_IPv6_TO_IPv4: + kparam->nat_params.nat_pt.new_header.ipv4.options_size = + uparam->nat_params.nat_pt.new_header.ipv4.options_size; + kparam->nat_params.nat_pt.new_header.ipv4.options = + compat_ptr(uparam->nat_params.nat_pt.new_header.ipv4. + options); + memcpy(&kparam->nat_params.nat_pt.new_header.ipv4. + header, &uparam->nat_params.nat_pt.new_header. + ipv4.header, sizeof(struct iphdr)); + break; + case DPA_CLS_HM_NAT_PT_IPv4_TO_IPv6: + memcpy(&kparam->nat_params.nat_pt.new_header.ipv6, + &uparam->nat_params.nat_pt.new_header.ipv6, + sizeof(struct ipv6_header)); + break; + default: + break; + } + } else if (kparam->nat_params.type == DPA_CLS_HM_NAT_TYPE_TRADITIONAL) + memcpy(&kparam->nat_params.nat, &uparam->nat_params.nat, + sizeof(struct dpa_cls_hm_traditional_nat_params)); + + kparam->nat_params.fm_pcd = compat_ptr(uparam->nat_params.fm_pcd); + kparam->nat_params.sport = uparam->nat_params.sport; + kparam->nat_params.dport = uparam->nat_params.dport; + kparam->next_hmd = uparam->next_hmd; + kparam->hmd = uparam->hmd; + + if (uparam->res.l3_update_node) + kparam->res.l3_update_node = compat_get_id2ptr( + uparam->res.l3_update_node, + FM_MAP_TYPE_PCD_NODE); + else + kparam->res.l3_update_node = NULL; + + if (uparam->res.l4_update_node) + kparam->res.l4_update_node = compat_get_id2ptr( + uparam->res.l4_update_node, + FM_MAP_TYPE_PCD_NODE); + else + kparam->res.l4_update_node = NULL; + + kparam->chain_head = uparam->chain_head; + kparam->modify_flags = uparam->modify_flags; + + return 0; +} + +int dpa_cls_hm_update_params_compatcpy( + struct ioc_dpa_cls_hm_update_params *kparam, + const struct compat_ioc_dpa_cls_hm_update_params *uparam) +{ + int op_flags; + + kparam->update_params.op_flags = uparam->update_params.op_flags; + op_flags = kparam->update_params.op_flags; + memcpy(&kparam->update_params.update, &uparam->update_params.update, + sizeof(kparam->update_params.update)); + memcpy(&kparam->update_params.ip_frag_params, + &uparam->update_params.ip_frag_params, + sizeof(kparam->update_params.ip_frag_params)); + + switch (op_flags) { + case DPA_CLS_HM_REPLACE_IPv4_BY_IPv6: + memcpy(&kparam->update_params.replace.new_ipv6_hdr, + &uparam->update_params.replace.new_ipv6_hdr, + sizeof(struct ipv6_header)); + break; + case DPA_CLS_HM_REPLACE_IPv6_BY_IPv4: + kparam->update_params.replace.new_ipv4_hdr.options_size = + uparam->update_params.replace.new_ipv4_hdr.options_size; + kparam->update_params.replace.new_ipv4_hdr.options = + compat_ptr(uparam->update_params.replace.new_ipv4_hdr. + options); + memcpy(&kparam->update_params.replace.new_ipv4_hdr.header, + &uparam->update_params.replace.new_ipv4_hdr.header, + sizeof(struct iphdr)); + break; + default: + break; + } + + + kparam->update_params.fm_pcd = compat_ptr(uparam->update_params.fm_pcd); + kparam->next_hmd = uparam->next_hmd; + kparam->hmd = uparam->hmd; + + if (uparam->res.update_node) + kparam->res.update_node = compat_get_id2ptr( + uparam->res.update_node, + FM_MAP_TYPE_PCD_NODE); + else + kparam->res.update_node = NULL; + + if (uparam->res.ip_frag_node) + kparam->res.ip_frag_node = compat_get_id2ptr( + uparam->res.ip_frag_node, + FM_MAP_TYPE_PCD_NODE); + else + kparam->res.ip_frag_node = NULL; + + kparam->chain_head = uparam->chain_head; + kparam->modify_flags = uparam->modify_flags; + + return 0; +} + +int dpa_cls_hm_fwd_params_compatcpy( + struct ioc_dpa_cls_hm_fwd_params *kparam, + const struct compat_ioc_dpa_cls_hm_fwd_params *uparam) +{ + int type; + + kparam->fwd_params.out_if_type = uparam->fwd_params.out_if_type; + kparam->fwd_params.fm_pcd = compat_ptr(uparam->fwd_params.fm_pcd); + + type = kparam->fwd_params.out_if_type; + switch (type) { + case DPA_CLS_HM_IF_TYPE_ETHERNET: + memcpy(&kparam->fwd_params.eth, &uparam->fwd_params.eth, + sizeof(struct dpa_cls_hm_fwd_l2_param)); + break; + case DPA_CLS_HM_IF_TYPE_PPPoE: + memcpy(&kparam->fwd_params.pppoe, &uparam->fwd_params.pppoe, + sizeof(struct dpa_cls_hm_fwd_pppoe_param)); + break; + case DPA_CLS_HM_IF_TYPE_PPP: + memcpy(&kparam->fwd_params.ppp, &uparam->fwd_params.ppp, + sizeof(struct dpa_cls_hm_fwd_ppp_param)); + break; + default: + break; + } + + memcpy(&kparam->fwd_params.ip_frag_params, + &uparam->fwd_params.ip_frag_params, + sizeof(struct dpa_cls_hm_ip_frag_params)); + + kparam->next_hmd = uparam->next_hmd; + kparam->hmd = uparam->hmd; + + if (uparam->res.fwd_node) + kparam->res.fwd_node = compat_get_id2ptr(uparam->res.fwd_node, + FM_MAP_TYPE_PCD_NODE); + else + kparam->res.fwd_node = NULL; + + if (uparam->res.pppoe_node) + kparam->res.pppoe_node = compat_get_id2ptr( + uparam->res.pppoe_node, + FM_MAP_TYPE_PCD_NODE); + else + kparam->res.pppoe_node = NULL; + + if (uparam->res.ip_frag_node) + kparam->res.ip_frag_node = compat_get_id2ptr( + uparam->res.ip_frag_node, + FM_MAP_TYPE_PCD_NODE); + else + kparam->res.ip_frag_node = NULL; + + kparam->chain_head = uparam->chain_head; + kparam->modify_flags = uparam->modify_flags; + + return 0; +} + +int dpa_cls_hm_mpls_params_compatcpy( + struct ioc_dpa_cls_hm_mpls_params *kparam, + const struct compat_ioc_dpa_cls_hm_mpls_params *uparam) +{ + kparam->mpls_params.type = uparam->mpls_params.type; + memcpy(kparam->mpls_params.mpls_hdr, uparam->mpls_params.mpls_hdr, + sizeof(struct mpls_header) * DPA_CLS_HM_MAX_MPLS_LABELS); + kparam->mpls_params.num_labels = uparam->mpls_params.num_labels; + kparam->mpls_params.fm_pcd = compat_ptr(uparam->mpls_params.fm_pcd); + kparam->next_hmd = uparam->next_hmd; + kparam->hmd = uparam->hmd; + + if (uparam->res.ins_rm_node) + kparam->res.ins_rm_node = compat_get_id2ptr( + uparam->res.ins_rm_node, + FM_MAP_TYPE_PCD_NODE); + else + kparam->res.ins_rm_node = NULL; + + kparam->chain_head = uparam->chain_head; + kparam->modify_flags = uparam->modify_flags; + + return 0; +} + +int dpa_cls_mcast_group_params_compatcpy( + struct ioc_dpa_cls_mcast_group_params *kparam, + const struct compat_ioc_dpa_cls_mcast_group_params *uparam) +{ + kparam->mcast_grp_params.max_members = + uparam->mcast_grp_params.max_members; + kparam->mcast_grp_params.fm_pcd = compat_ptr(uparam->mcast_grp_params. + fm_pcd); + kparam->mcast_grp_params.first_member_params.override_fqid = + uparam->mcast_grp_params.first_member_params.override_fqid; + kparam->mcast_grp_params.first_member_params.new_fqid = + uparam->mcast_grp_params.first_member_params.new_fqid; + kparam->mcast_grp_params.first_member_params.new_rel_vsp_id = + uparam->mcast_grp_params.first_member_params.new_rel_vsp_id; + if (compat_ptr(uparam->mcast_grp_params.first_member_params. + policer_params)) { + if (copy_from_user(kparam->mcast_grp_params.first_member_params. + policer_params, + compat_ptr(uparam->mcast_grp_params.first_member_params. + policer_params), + sizeof(struct dpa_cls_tbl_policer_params))) { + pr_err("ERROR: %s, %s (%d): Read failed: " + "policer params.\n", __FILE__, __func__, + __LINE__); + return -EBUSY; + } + } else + kparam->mcast_grp_params.first_member_params.policer_params = + NULL; + + kparam->mcast_grp_params.first_member_params.hmd = + uparam->mcast_grp_params.first_member_params.hmd; + kparam->mcast_grp_params.prefilled_members = + uparam->mcast_grp_params.prefilled_members; + + if (uparam->mcast_grp_params.group) + kparam->mcast_grp_params.group = compat_get_id2ptr( + uparam->mcast_grp_params.group, + FM_MAP_TYPE_PCD_NODE); + else + kparam->mcast_grp_params.group = NULL; + + if (compat_ptr(uparam->mcast_grp_params.distribution)) + kparam->mcast_grp_params.distribution = compat_get_id2ptr( + uparam->mcast_grp_params.distribution, + FM_MAP_TYPE_PCD_NODE); + else + kparam->mcast_grp_params.distribution = NULL; + + if (compat_ptr(uparam->mcast_grp_params.classification)) + kparam->mcast_grp_params.classification = compat_get_id2ptr( + uparam->mcast_grp_params.classification, + FM_MAP_TYPE_PCD_NODE); + else + kparam->mcast_grp_params.classification = NULL; + + return 0; +} + +int dpa_cls_mcast_member_params_compatcpy( + struct ioc_dpa_cls_mcast_member_params *kparam, + const struct compat_ioc_dpa_cls_mcast_member_params *uparam) +{ + kparam->grpd = uparam->grpd; + kparam->member_params.hmd = uparam->member_params.hmd; + kparam->member_params.new_fqid = uparam->member_params.new_fqid; + kparam->member_params.override_fqid = + uparam->member_params.override_fqid; + kparam->member_params.new_rel_vsp_id = + uparam->member_params.new_rel_vsp_id; + if (compat_ptr(uparam->member_params.policer_params)) { + if (copy_from_user(kparam->member_params.policer_params, + compat_ptr(uparam->member_params.policer_params), + sizeof(struct dpa_cls_tbl_policer_params))) { + pr_err("ERROR: %s, %s (%d): Read failed: " + "policer params.\n", __FILE__, __func__, + __LINE__); + return -EBUSY; + } + } else + kparam->member_params.policer_params = NULL; + + return 0; +} + +#endif /* CONFIG_COMPAT */ diff --git a/drivers/staging/fsl_dpa_offload/wrp_dpa_classifier.h b/drivers/staging/fsl_dpa_offload/wrp_dpa_classifier.h new file mode 100644 index 0000000..411a332 --- /dev/null +++ b/drivers/staging/fsl_dpa_offload/wrp_dpa_classifier.h @@ -0,0 +1,86 @@ + +/* Copyright 2008-2012 Freescale Semiconductor, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Freescale Semiconductor nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * + * ALTERNATIVELY, this software may be distributed under the terms of the + * GNU General Public License ("GPL") as published by the Free Software + * Foundation, either version 2 of that License or (at your option) any + * later version. + * + * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Internal DPA Classifier Wrapper Application Programming Interface + */ + +#ifndef __WRP_DPA_CLASSIFIER_H +#define __WRP_DPA_CLASSIFIER_H + + +/* Other includes */ +#include "linux/fs.h" + + +#define WRP_DPA_CLS_CDEVNAME "dpa_classifier" + + +int wrp_dpa_classif_init(void); + +int wrp_dpa_classif_exit(void); + +int wrp_dpa_classif_open(struct inode *inode, struct file *filp); + +int wrp_dpa_classif_release(struct inode *inode, struct file *filp); + +ssize_t wrp_dpa_classif_read( + struct file *filp, + char __user *buf, + size_t len, + loff_t *offp); + +ssize_t wrp_dpa_classif_write( + struct file *filp, + const char __user *buf, + size_t len, + loff_t *offp); + +long wrp_dpa_classif_ioctl( + struct file *filp, + unsigned int cmd, + unsigned long args); + +long wrp_dpa_classif_do_ioctl( + struct file *filp, + unsigned int cmd, + unsigned long args, + bool compat_mode); + +#ifdef CONFIG_COMPAT +long wrp_dpa_classif_compat_ioctl( + struct file *filp, + unsigned int cmd, + unsigned long args); +#endif + +#endif /* __WRP_DPA_CLASSIFIER_H */ -- cgit v0.10.2