kernel: delete Linux 5.4 config and patches
[openwrt/staging/chunkeey.git] / target / linux / layerscape / patches-5.4 / 701-net-0334-net-tsn-netlink-interface-for-APP-layer-to-config-TS.patch
diff --git a/target/linux/layerscape/patches-5.4/701-net-0334-net-tsn-netlink-interface-for-APP-layer-to-config-TS.patch b/target/linux/layerscape/patches-5.4/701-net-0334-net-tsn-netlink-interface-for-APP-layer-to-config-TS.patch
deleted file mode 100644 (file)
index 33de677..0000000
+++ /dev/null
@@ -1,5113 +0,0 @@
-From e478ab518612f1a821968e1bb5b08b01b10085b0 Mon Sep 17 00:00:00 2001
-From: Po Liu <Po.Liu@nxp.com>
-Date: Tue, 15 Oct 2019 16:11:40 +0800
-Subject: [PATCH] net:tsn: netlink interface for APP layer to config TSN
- capability hardware ports
-
-This patch provids netlink method to configure the TSN protocols hardwares.
-TSN guaranteed packet transport with bounded low latency, low packet delay
-variation, and low packet loss by hardware and software methods.
-
-The three basic components of TSN are:
-
-1. Time synchronization: This was implement by 8021AS which base on the
-   IEEE1588 precision Time Protocol. This is configured by the other way
-   in kernel.
-   8021AS not included in this patch.
-
-2. Scheduling and traffic shaping and per-stream filter policing:
-   This patch support Qbv/Qci/Qbu/8021CB/Qav etc.
-
-3. Selection of communication paths:
-   This patch not support the pure software only TSN protocols(like Qcc)
-   but hardware related configuration.
-
-TSN Protocols supports by this patch: Qbv/Qci/Qbu/Credit-base Shaper(Qav).
-This patch verified on NXP ls1028ardb board.
-
-Signed-off-by: Po Liu <Po.Liu@nxp.com>
----
- include/net/tsn.h        |  114 ++
- include/uapi/linux/tsn.h | 1207 +++++++++++++++
- net/Kconfig              |    1 +
- net/Makefile             |    3 +
- net/tsn/Kconfig          |   15 +
- net/tsn/Makefile         |    1 +
- net/tsn/genl_tsn.c       | 3696 ++++++++++++++++++++++++++++++++++++++++++++++
- 7 files changed, 5037 insertions(+)
- create mode 100644 include/net/tsn.h
- create mode 100644 include/uapi/linux/tsn.h
- create mode 100644 net/tsn/Kconfig
- create mode 100644 net/tsn/Makefile
- create mode 100644 net/tsn/genl_tsn.c
-
---- /dev/null
-+++ b/include/net/tsn.h
-@@ -0,0 +1,114 @@
-+/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
-+/* Copyright 2017-2019 NXP */
-+
-+#ifndef __TSN_H__
-+#define __TSN_H__
-+
-+#include <linux/notifier.h>
-+#include <uapi/linux/tsn.h>
-+
-+enum tsn_notifier_type {
-+      TSN_QBV_CONFIGCHANGETIME_ARRIVE = 1,
-+};
-+
-+struct tsn_notifier_info {
-+      struct net_device *dev;
-+      union {
-+              struct tsn_qbv_conf qbv_notify;
-+              struct tsn_qci_psfp_sgi_conf qci_notify;
-+      } ntdata;
-+};
-+
-+static inline struct net_device *
-+tsn_notifier_info_to_dev(const struct tsn_notifier_info *info)
-+{
-+      return info->dev;
-+}
-+
-+struct tsn_ops {
-+      void (*device_init)(struct net_device *ndev);
-+      void (*device_deinit)(struct net_device *ndev);
-+      u32 (*get_capability)(struct net_device *ndev);
-+      /* Qbv standard */
-+      int (*qbv_set)(struct net_device *ndev, struct tsn_qbv_conf *qbvconf);
-+      int (*qbv_get)(struct net_device *ndev, struct tsn_qbv_conf *qbvconf);
-+      int (*qbv_get_status)(struct net_device *ndev,
-+                              struct tsn_qbv_status *qbvstat);
-+      int (*cb_streamid_set)(struct net_device *ndev, u32 index,
-+                              bool enable, struct tsn_cb_streamid *sid);
-+      int (*cb_streamid_get)(struct net_device *ndev, u32 index,
-+                              struct tsn_cb_streamid *sid);
-+      int (*cb_streamid_counters_get)(struct net_device *ndev, u32 index,
-+                              struct tsn_cb_streamid_counters *sidcounter);
-+      int (*qci_get_maxcap)(struct net_device *ndev,
-+                              struct tsn_qci_psfp_stream_param *qcicapa);
-+      int (*qci_sfi_set)(struct net_device *ndev, u32 index, bool enable,
-+                              struct tsn_qci_psfp_sfi_conf *sficonf);
-+      /* return: 0 stream filter instance not valid
-+       * 1 stream filter instance valid
-+       * -1 error happened
-+       */
-+      int (*qci_sfi_get)(struct net_device *ndev, u32 index,
-+                              struct tsn_qci_psfp_sfi_conf *sficonf);
-+      int (*qci_sfi_counters_get)(struct net_device *ndev, u32 index,
-+                              struct tsn_qci_psfp_sfi_counters *sficounter);
-+      int (*qci_sgi_set)(struct net_device *ndev, u32 index,
-+                              struct tsn_qci_psfp_sgi_conf *sgiconf);
-+      int (*qci_sgi_get)(struct net_device *ndev, u32 index,
-+                              struct tsn_qci_psfp_sgi_conf *sgiconf);
-+      int (*qci_sgi_status_get)(struct net_device *ndev, u16 index,
-+                              struct tsn_psfp_sgi_status *sgistat);
-+      int (*qci_fmi_set)(struct net_device *ndev, u32 index, bool enable,
-+                              struct tsn_qci_psfp_fmi *fmi);
-+      int (*qci_fmi_get)(struct net_device *ndev, u32 index,
-+                              struct tsn_qci_psfp_fmi *fmi,
-+                              struct tsn_qci_psfp_fmi_counters *counters);
-+      int (*cbs_set)(struct net_device *ndev, u8 tc, u8 bw);
-+      int (*cbs_get)(struct net_device *ndev, u8 tc);
-+      /* To set a 8 bits vector shows 8 traffic classes
-+       * preemtable(1) or express(0)
-+       */
-+      int (*qbu_set)(struct net_device *ndev, u8 ptvector);
-+      /* To get port preemtion status */
-+      int (*qbu_get)(struct net_device *ndev,
-+                              struct tsn_preempt_status *preemptstat);
-+      int (*tsd_set)(struct net_device *ndev, struct tsn_tsd *tsd);
-+      int (*tsd_get)(struct net_device *ndev, struct tsn_tsd_status *stats);
-+      int (*ct_set)(struct net_device *ndev, u8 cut_thru);
-+      int (*cbgen_set)(struct net_device *ndev, u32 index,
-+                       struct tsn_seq_gen_conf *seqgen);
-+      int (*cbrec_set)(struct net_device *ndev, u32 index,
-+                       struct tsn_seq_rec_conf *seqrec);
-+      int (*cb_get)(struct net_device *ndev, u32 index,
-+                    struct tsn_cb_status  *c);
-+      int (*dscp_set)(struct net_device *ndev, bool enable,
-+                      const u8 dscp_ix,
-+                      struct tsn_qos_switch_dscp_conf *c);
-+};
-+
-+enum ethdev_type {
-+      TSN_SWITCH,
-+      TSN_ENDPOINT,
-+};
-+
-+#define GROUP_OFFSET_SWITCH 256
-+
-+struct tsn_port {
-+      u16 groupid;
-+      struct tsn_ops *tsnops;
-+      struct net_device *netdev;
-+      struct list_head list;
-+      enum ethdev_type type;
-+      u8 tc_nums;
-+      struct tsn_notifier_info nd;
-+};
-+
-+struct tsn_port *tsn_get_port(struct net_device *ndev);
-+int register_tsn_notifier(struct notifier_block *nb);
-+int unregister_tsn_notifier(struct notifier_block *nb);
-+int call_tsn_notifiers(unsigned long val, struct net_device *dev,
-+                           struct tsn_notifier_info *info);
-+int tsn_port_register(struct net_device *netdev,
-+                              struct tsn_ops *tsnops, u16 groupid);
-+void tsn_port_unregister(struct net_device *netdev);
-+#endif
---- /dev/null
-+++ b/include/uapi/linux/tsn.h
-@@ -0,0 +1,1207 @@
-+/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
-+/* Copyright 2017-2019 NXP */
-+
-+#ifndef __UAPI_GENL_TSN_H
-+#define __UAPI_GENL_TSN_H
-+
-+#define       TSN_GENL_NAME           "TSN_GEN_CTRL"
-+#define       TSN_GENL_VERSION        0x1
-+
-+#define MAX_USER_SIZE 0
-+#define MAX_ATTR_SIZE 3072
-+#define MAX_TOTAL_MSG_SIZE  (MAX_USER_SIZE + MAX_ATTR_SIZE)
-+#define MAX_ENTRY_SIZE 2048
-+#define MAX_ENTRY_NUMBER 128
-+#define MAX_IFNAME_COUNT 64
-+
-+#define TSN_MULTICAST_GROUP_QBV       "qbv"
-+#define TSN_MULTICAST_GROUP_QCI       "qci"
-+
-+/* multicast groups */
-+enum tsn_multicast_groups {
-+      TSN_MCGRP_QBV,
-+      TSN_MCGRP_QCI,
-+      TSN_MCGRP_MAX
-+};
-+
-+enum tsn_capability {
-+      TSN_CAP_QBV = 0x1,
-+      TSN_CAP_QCI = 0x2,
-+      TSN_CAP_QBU = 0x4,
-+      TSN_CAP_CBS = 0x8, /* Credit-based Shapter Qav */
-+      TSN_CAP_CB  = 0x10, /* 8021CB redundancy and replication */
-+      TSN_CAP_TBS = 0x20, /* Time Based schedule */
-+      TSN_CAP_CTH = 0x40, /* cut through */
-+};
-+
-+/*
-+ * Commands sent from userspace
-+ * Not versioned. New commands should only be inserted at the enum's end
-+ * prior to __TSN_CMD_MAX
-+ */
-+
-+enum {
-+      TSN_CMD_UNSPEC = 0,     /* Reserved */
-+      TSN_CMD_QBV_SET,
-+      TSN_CMD_QBV_GET,
-+      TSN_CMD_QBV_GET_STATUS,
-+      TSN_CMD_CB_STREAMID_SET,
-+      TSN_CMD_CB_STREAMID_GET,
-+      TSN_CMD_CB_STREAMID_GET_COUNTS,
-+      TSN_CMD_QCI_CAP_GET, /* Qci capability get length capability get */
-+      TSN_CMD_QCI_SFI_SET,
-+      TSN_CMD_QCI_SFI_GET,
-+      TSN_CMD_QCI_SFI_GET_COUNTS,
-+      TSN_CMD_QCI_SGI_SET,
-+      TSN_CMD_QCI_SGI_GET,
-+      TSN_CMD_QCI_SGI_GET_STATUS,
-+      TSN_CMD_QCI_FMI_SET,
-+      TSN_CMD_QCI_FMI_GET,
-+      TSN_CMD_CBS_SET,
-+      TSN_CMD_CBS_GET,
-+      TSN_CMD_QBU_SET,
-+      TSN_CMD_QBU_GET_STATUS,
-+      TSN_CMD_QAV_SET_CBS,
-+      TSN_CMD_QAV_GET_CBS,
-+      TSN_CMD_TSD_SET,
-+      TSN_CMD_TSD_GET,
-+      TSN_CMD_CT_SET,
-+      TSN_CMD_CBGEN_SET,
-+      TSN_CMD_CBREC_SET,
-+      TSN_CMD_CBSTAT_GET,
-+      TSN_CMD_PCPMAP_SET_UNUSE,
-+      TSN_CMD_DSCP_SET,
-+      TSN_CMD_ECHO,                   /* user->kernel request/get-response */
-+      TSN_CMD_REPLY,                  /* kernel->user event */
-+      TSN_CMD_CAP_GET,
-+      __TSN_CMD_MAX,
-+};
-+#define TSN_CMD_MAX (__TSN_CMD_MAX - 1)
-+
-+
-+enum {
-+      TSN_CMD_ATTR_UNSPEC = 0,
-+      TSN_CMD_ATTR_MESG,              /* demo message  */
-+      TSN_CMD_ATTR_DATA,              /* demo data */
-+      TSN_ATTR_IFNAME,
-+      TSN_ATTR_PORT_NUMBER,
-+      TSN_ATTR_QBV,
-+      TSN_ATTR_STREAM_IDENTIFY, /* stream identify */
-+      TSN_ATTR_QCI_SP,                /* psfp port capbility parameters */
-+      TSN_ATTR_QCI_SFI,               /* psfp stream filter instance */
-+      TSN_ATTR_QCI_SGI,               /* psfp stream gate instance */
-+      TSN_ATTR_QCI_FMI,               /* psfp flow meter instance */
-+      TSN_ATTR_CBS,                   /* credit-based shaper */
-+      TSN_ATTR_TSD,                   /* Time Specific Departure */
-+      TSN_ATTR_QBU,                   /* preemption */
-+      TSN_ATTR_CT,                    /* cut through */
-+      TSN_ATTR_CBGEN,                 /* 802.1CB sequence generate */
-+      TSN_ATTR_CBREC,                 /* 802.1CB sequence recover */
-+      TSN_ATTR_CBSTAT,                 /* 802.1CB status */
-+      TSN_ATTR_PCPMAP_UNUSE,
-+      TSN_ATTR_DSCP,
-+      TSN_ATTR_CAP,           /* TSN capbility */
-+      __TSN_CMD_ATTR_MAX,
-+};
-+#define TSN_CMD_ATTR_MAX (__TSN_CMD_ATTR_MAX - 1)
-+
-+enum {
-+      TSN_CAP_ATTR_UNSPEC,
-+      TSN_CAP_ATTR_QBV,
-+      TSN_CAP_ATTR_QCI,
-+      TSN_CAP_ATTR_QBU,
-+      TSN_CAP_ATTR_CBS,
-+      TSN_CAP_ATTR_CB,
-+      TSN_CAP_ATTR_TBS,
-+      TSN_CAP_ATTR_CTH,
-+      __TSN_CAP_ATTR_MAX,
-+      TSN_CAP_ATTR_MAX = __TSN_CAP_ATTR_MAX - 1,
-+};
-+
-+enum {
-+      TSN_QBU_ATTR_UNSPEC,
-+      TSN_QBU_ATTR_ADMIN_STATE,
-+      TSN_QBU_ATTR_HOLD_ADVANCE,
-+      TSN_QBU_ATTR_RELEASE_ADVANCE,
-+      TSN_QBU_ATTR_ACTIVE,
-+      TSN_QBU_ATTR_HOLD_REQUEST,
-+      __TSN_QBU_ATTR_MAX,
-+      TSN_QBU_ATTR_MAX = __TSN_QBU_ATTR_MAX - 1,
-+};
-+
-+enum {
-+      TSN_CBS_ATTR_UNSPEC,
-+      TSN_CBS_ATTR_TC_INDEX,
-+      TSN_CBS_ATTR_BW,
-+      __TSN_CBS_ATTR_MAX,
-+      TSN_CBS_ATTR_MAX = __TSN_CBS_ATTR_MAX - 1,
-+};
-+
-+enum {
-+      TSN_TSD_ATTR_UNSPEC,
-+      TSN_TSD_ATTR_DISABLE,
-+      TSN_TSD_ATTR_ENABLE,
-+      TSN_TSD_ATTR_PERIOD,
-+      TSN_TSD_ATTR_MAX_FRM_NUM,
-+      TSN_TSD_ATTR_CYCLE_NUM,
-+      TSN_TSD_ATTR_LOSS_STEPS,
-+      TSN_TSD_ATTR_SYN_IMME,
-+      __TSN_TSD_ATTR_MAX,
-+      TSN_TSD_ATTR_MAX = __TSN_TSD_ATTR_MAX - 1,
-+};
-+
-+enum {
-+      TSN_STREAMID_ATTR_UNSPEC,
-+      TSN_STREAMID_ATTR_INDEX,
-+      TSN_STREAMID_ATTR_ENABLE,
-+      TSN_STREAMID_ATTR_DISABLE,
-+      TSN_STREAMID_ATTR_STREAM_HANDLE,
-+      TSN_STREAMID_ATTR_IFOP,
-+      TSN_STREAMID_ATTR_OFOP,
-+      TSN_STREAMID_ATTR_IFIP,
-+      TSN_STREAMID_ATTR_OFIP,
-+      TSN_STREAMID_ATTR_TYPE,
-+      TSN_STREAMID_ATTR_NDMAC,
-+      TSN_STREAMID_ATTR_NTAGGED,
-+      TSN_STREAMID_ATTR_NVID,
-+      TSN_STREAMID_ATTR_SMAC,
-+      TSN_STREAMID_ATTR_STAGGED,
-+      TSN_STREAMID_ATTR_SVID,
-+      TSN_STREAMID_ATTR_COUNTERS_PSI,
-+      TSN_STREAMID_ATTR_COUNTERS_PSO,
-+      TSN_STREAMID_ATTR_COUNTERS_PSPPI,
-+      TSN_STREAMID_ATTR_COUNTERS_PSPPO,
-+      __TSN_STREAMID_ATTR_MAX,
-+      TSN_STREAMID_ATTR_MAX = __TSN_STREAMID_ATTR_MAX - 1,
-+};
-+
-+enum {
-+      TSN_QCI_STREAM_ATTR_UNSPEC = 0,
-+      TSN_QCI_STREAM_ATTR_MAX_SFI,
-+      TSN_QCI_STREAM_ATTR_MAX_SGI,
-+      TSN_QCI_STREAM_ATTR_MAX_FMI,
-+      TSN_QCI_STREAM_ATTR_SLM,
-+      __TSN_QCI_STREAM_ATTR_MAX,
-+      TSN_QCI_STREAM_ATTR_MAX = __TSN_QCI_STREAM_ATTR_MAX - 1,
-+};
-+
-+enum {
-+      TSN_QCI_SFI_ATTR_UNSPEC = 0,
-+      TSN_QCI_SFI_ATTR_INDEX,
-+      TSN_QCI_SFI_ATTR_ENABLE,
-+      TSN_QCI_SFI_ATTR_DISABLE,
-+      TSN_QCI_SFI_ATTR_STREAM_HANDLE,
-+      TSN_QCI_SFI_ATTR_PRIO_SPEC,
-+      TSN_QCI_SFI_ATTR_GATE_ID,
-+      TSN_QCI_SFI_ATTR_FILTER_TYPE,
-+      TSN_QCI_SFI_ATTR_FLOW_ID,
-+      TSN_QCI_SFI_ATTR_MAXSDU,
-+      TSN_QCI_SFI_ATTR_COUNTERS,
-+      TSN_QCI_SFI_ATTR_OVERSIZE_ENABLE,
-+      TSN_QCI_SFI_ATTR_OVERSIZE,
-+      __TSN_QCI_SFI_ATTR_MAX,
-+      TSN_QCI_SFI_ATTR_MAX = __TSN_QCI_SFI_ATTR_MAX - 1,
-+};
-+
-+enum {
-+      TSN_QCI_SFI_ATTR_COUNTERS_UNSPEC = 0,
-+      TSN_QCI_SFI_ATTR_MATCH,
-+      TSN_QCI_SFI_ATTR_PASS,
-+      TSN_QCI_SFI_ATTR_DROP,
-+      TSN_QCI_SFI_ATTR_SDU_DROP,
-+      TSN_QCI_SFI_ATTR_SDU_PASS,
-+      TSN_QCI_SFI_ATTR_RED,
-+      __TSN_QCI_SFI_ATTR_COUNT_MAX,
-+      TSN_QCI_SFI_ATTR_COUNT_MAX = __TSN_QCI_SFI_ATTR_COUNT_MAX - 1,
-+};
-+
-+enum {
-+      TSN_QCI_SGI_ATTR_UNSPEC = 0,
-+      TSN_QCI_SGI_ATTR_INDEX,
-+      TSN_QCI_SGI_ATTR_ENABLE,
-+      TSN_QCI_SGI_ATTR_DISABLE,
-+      TSN_QCI_SGI_ATTR_CONFCHANGE,
-+      TSN_QCI_SGI_ATTR_IRXEN,         /* Invalid rx enable*/
-+      TSN_QCI_SGI_ATTR_IRX,
-+      TSN_QCI_SGI_ATTR_OEXEN,         /* Octet exceed enable */
-+      TSN_QCI_SGI_ATTR_OEX,
-+      TSN_QCI_SGI_ATTR_ADMINENTRY,
-+      TSN_QCI_SGI_ATTR_OPERENTRY,
-+      TSN_QCI_SGI_ATTR_CCTIME,        /* config change time */
-+      TSN_QCI_SGI_ATTR_TICKG,
-+      TSN_QCI_SGI_ATTR_CUTIME,
-+      TSN_QCI_SGI_ATTR_CPENDING,
-+      TSN_QCI_SGI_ATTR_CCERROR,
-+      __TSN_QCI_SGI_ATTR_MAX,
-+      TSN_QCI_SGI_ATTR_MAX = __TSN_QCI_SGI_ATTR_MAX - 1,
-+};
-+
-+enum {
-+      TSN_SGI_ATTR_CTRL_UNSPEC = 0,
-+      TSN_SGI_ATTR_CTRL_INITSTATE,
-+      TSN_SGI_ATTR_CTRL_LEN,
-+      TSN_SGI_ATTR_CTRL_CYTIME,
-+      TSN_SGI_ATTR_CTRL_CYTIMEEX,
-+      TSN_SGI_ATTR_CTRL_BTIME,
-+      TSN_SGI_ATTR_CTRL_INITIPV,
-+      TSN_SGI_ATTR_CTRL_GCLENTRY,
-+      __TSN_SGI_ATTR_CTRL_MAX,
-+      TSN_SGI_ATTR_CTRL_MAX = __TSN_SGI_ATTR_CTRL_MAX - 1,
-+};
-+
-+enum {
-+      TSN_SGI_ATTR_GCL_UNSPEC = 0,
-+      TSN_SGI_ATTR_GCL_GATESTATE,
-+      TSN_SGI_ATTR_GCL_IPV,
-+      TSN_SGI_ATTR_GCL_INTERVAL,
-+      TSN_SGI_ATTR_GCL_OCTMAX,
-+      __TSN_SGI_ATTR_GCL_MAX,
-+      TSN_SGI_ATTR_GCL_MAX = __TSN_SGI_ATTR_GCL_MAX - 1,
-+};
-+
-+enum {
-+      TSN_QCI_FMI_ATTR_UNSPEC = 0,
-+      TSN_QCI_FMI_ATTR_INDEX,
-+      TSN_QCI_FMI_ATTR_ENABLE,
-+      TSN_QCI_FMI_ATTR_DISABLE,
-+      TSN_QCI_FMI_ATTR_CIR,
-+      TSN_QCI_FMI_ATTR_CBS,
-+      TSN_QCI_FMI_ATTR_EIR,
-+      TSN_QCI_FMI_ATTR_EBS,
-+      TSN_QCI_FMI_ATTR_CF,
-+      TSN_QCI_FMI_ATTR_CM,
-+      TSN_QCI_FMI_ATTR_DROPYL,
-+      TSN_QCI_FMI_ATTR_MAREDEN,
-+      TSN_QCI_FMI_ATTR_MARED,
-+      TSN_QCI_FMI_ATTR_COUNTERS,
-+      __TSN_QCI_FMI_ATTR_MAX,
-+      TSN_QCI_FMI_ATTR_MAX = __TSN_QCI_FMI_ATTR_MAX - 1,
-+};
-+
-+enum {
-+      TSN_QBV_ATTR_UNSPEC,
-+      TSN_QBV_ATTR_ENABLE,
-+      TSN_QBV_ATTR_DISABLE,
-+      TSN_QBV_ATTR_CONFIGCHANGE,
-+      TSN_QBV_ATTR_CONFIGCHANGETIME,
-+      TSN_QBV_ATTR_MAXSDU,
-+      TSN_QBV_ATTR_GRANULARITY,
-+      TSN_QBV_ATTR_CURRENTTIME,
-+      TSN_QBV_ATTR_CONFIGPENDING,
-+      TSN_QBV_ATTR_CONFIGCHANGEERROR,
-+      TSN_QBV_ATTR_ADMINENTRY,
-+      TSN_QBV_ATTR_OPERENTRY,
-+      TSN_QBV_ATTR_LISTMAX,
-+      __TSN_QBV_ATTR_MAX,
-+      TSN_QBV_ATTR_MAX = __TSN_QBV_ATTR_MAX - 1,
-+};
-+
-+enum {
-+      TSN_QBV_ATTR_CTRL_UNSPEC,
-+      TSN_QBV_ATTR_CTRL_LISTCOUNT,
-+      TSN_QBV_ATTR_CTRL_GATESTATE,
-+      TSN_QBV_ATTR_CTRL_CYCLETIME,
-+      TSN_QBV_ATTR_CTRL_CYCLETIMEEXT,
-+      TSN_QBV_ATTR_CTRL_BASETIME,
-+      TSN_QBV_ATTR_CTRL_LISTENTRY,
-+      __TSN_QBV_ATTR_CTRL_MAX,
-+      TSN_QBV_ATTR_CTRL_MAX = __TSN_QBV_ATTR_CTRL_MAX - 1,
-+};
-+
-+enum {
-+      TSN_QBV_ATTR_ENTRY_UNSPEC,
-+      TSN_QBV_ATTR_ENTRY_ID,
-+      TSN_QBV_ATTR_ENTRY_GC,
-+      TSN_QBV_ATTR_ENTRY_TM,
-+      __TSN_QBV_ATTR_ENTRY_MAX,
-+      TSN_QBV_ATTR_ENTRY_MAX = __TSN_QBV_ATTR_ENTRY_MAX - 1,
-+};
-+
-+enum {
-+      TSN_CT_ATTR_UNSPEC,
-+      TSN_CT_ATTR_QUEUE_STATE,
-+      __TSN_CT_ATTR_MAX,
-+      TSN_CT_ATTR_MAX = __TSN_CT_ATTR_MAX - 1,
-+};
-+
-+enum {
-+      TSN_CBGEN_ATTR_UNSPEC,
-+      TSN_CBGEN_ATTR_INDEX,
-+      TSN_CBGEN_ATTR_PORT_MASK,
-+      TSN_CBGEN_ATTR_SPLIT_MASK,
-+      TSN_CBGEN_ATTR_SEQ_LEN,
-+      TSN_CBGEN_ATTR_SEQ_NUM,
-+      __TSN_CBGEN_ATTR_MAX,
-+      TSN_CBGEN_ATTR_MAX = __TSN_CBGEN_ATTR_MAX - 1,
-+};
-+
-+enum {
-+      TSN_CBREC_ATTR_UNSPEC,
-+      TSN_CBREC_ATTR_INDEX,
-+      TSN_CBREC_ATTR_SEQ_LEN,
-+      TSN_CBREC_ATTR_HIS_LEN,
-+      TSN_CBREC_ATTR_TAG_POP_EN,
-+      __TSN_CBREC_ATTR_MAX,
-+      TSN_CBREC_ATTR_MAX = __TSN_CBREC_ATTR_MAX - 1,
-+};
-+
-+enum {
-+      TSN_CBSTAT_ATTR_UNSPEC,
-+      TSN_CBSTAT_ATTR_INDEX,
-+      TSN_CBSTAT_ATTR_GEN_REC,
-+      TSN_CBSTAT_ATTR_ERR,
-+      TSN_CBSTAT_ATTR_SEQ_NUM,
-+      TSN_CBSTAT_ATTR_SEQ_LEN,
-+      TSN_CBSTAT_ATTR_SPLIT_MASK,
-+      TSN_CBSTAT_ATTR_PORT_MASK,
-+      TSN_CBSTAT_ATTR_HIS_LEN,
-+      TSN_CBSTAT_ATTR_SEQ_HIS,
-+      __TSN_CBSTAT_ATTR_MAX,
-+      TSN_CBSTAT_ATTR_MAX = __TSN_CBSTAT_ATTR_MAX - 1,
-+};
-+
-+enum {
-+      TSN_DSCP_ATTR_UNSPEC,
-+      TSN_DSCP_ATTR_DISABLE,
-+      TSN_DSCP_ATTR_INDEX,
-+      TSN_DSCP_ATTR_COS,
-+      TSN_DSCP_ATTR_DPL,
-+      __TSN_DSCP_ATTR_MAX,
-+      TSN_DSCP_ATTR_MAX = __TSN_DSCP_ATTR_MAX - 1,
-+};
-+
-+#define ptptime_t __u64
-+
-+#define MAX_QUEUE_CNT 8
-+
-+struct tsn_preempt_status {
-+      /* The value of admin_state shows a 8-bits vector value for showing
-+       * the framePreemptionAdminStatus parameter and PreemptionPriority
-+       * for the traffic class. Bit-7 is the highest priority traffic class
-+       * and the bit-0 is the lowest priority traffic class.
-+       * The bit is express (0) and is preemptible (1).
-+       */
-+      __u8 admin_state;
-+      /* The value of the holdAdvance parameter for the port in nanoseconds.
-+       * There is no default value; the holdAdvance is a property of the
-+       * underlying MAC." This parameter corresponds to the holdAdvance
-+       * parameter in 802.1Qbu.
-+       */
-+      __u32 hold_advance;
-+
-+      /* The value of the releaseAdvance parameter for the port in
-+       * nanoseconds.  There is no default value; the releaseAdvance is a
-+       * property of the underlying MAC." This parameter corresponds to the
-+       * releaseAdvance parameter in 802.1Qbu.
-+       */
-+      __u32 release_advance;
-+
-+      /* The value is active (TRUE) when preemption is operationally active
-+       * for the port, and idle (FALSE) otherwise.  This parameter corresponds
-+       * to the preemptionActive parameter in 802.1Qbu.
-+       */
-+      __u8 preemption_active;
-+
-+      /* The value is hold (1) when the sequence of gate operations for
-+       * the port has executed a Set-And-Hold-MAC operation, and release
-+       * (2) when the sequence of gate operations has executed a
-+       * Set-And-Release-MAC operation. The value of this object is release
-+       * (FALSE) on system initialization.  This parameter corresponds to the
-+       * holdRequest parameter in 802.1Qbu.
-+       */
-+      __u8 hold_request;
-+};
-+
-+enum tsn_tx_mode  {
-+      TX_MODE_STRICT,
-+      TX_MODE_CBS,
-+      TX_MODE_ETS,
-+      TX_MODE_VENDOR_DEFINE = 255,
-+};
-+
-+#define QUEUE_TX_MASK ((1 << TX_MODE_STRICT) | (1 << TX_MODE_CBS) \
-+                      | (1 << TX_MODE_ETS) | (1 << TX_MODE_VENDOR_DEFINE))
-+
-+struct cbs_status {
-+      __u8 delta_bw; /* percentage, 0~100 */
-+      __u32 idleslope;
-+      __s32 sendslope;
-+      __u32 maxframesize;
-+      __u32 hicredit;
-+      __s32 locredit;
-+      __u32 maxninference;
-+};
-+
-+struct tx_queue {
-+      /* tx_queue_capbility shows the queue's capability mask.
-+       * refer the enum tsn_tx_mode
-+       */
-+      __u8 capability;
-+
-+      /* tx_queue_mode is current queue working mode */
-+      __u8 mode;
-+
-+      /* prio is showing the queue priority */
-+      __u8 prio;
-+
-+      /* mstat shows the status data of cbs or priority */
-+      union {
-+              struct cbs_status cbs;
-+      };
-+};
-+
-+struct port_status {
-+      /* txqueue_cnt shows how many queues in this port */
-+      __u8 queue_cnt;
-+
-+      /* max_rate(Mbit/s) is the port transmit rate current port is setting */
-+      __u32 max_rate;
-+
-+      /* tsn_capability mask the tsn capability */
-+      __u32 tsn_capability;
-+};
-+
-+enum tsn_cb_streamid_type {
-+      STREAMID_RESERVED = 0,
-+      /* Null Stream identification */
-+      STREAMID_NULL,
-+      /* Source MAC and VLAN Stream identification */
-+      STREAMID_SMAC_VLAN,
-+      /* Active Destination MAC and VLAN stream identification */
-+      STREAMID_DMAC_VLAN,
-+      /* IP stream identification */
-+      STREAMID_IP,
-+};
-+
-+/* When instantiating an instance of the Null Stream identification function
-+ * 8021CB(6.4) for a particular input Stream, the managed objects in the
-+ * following subsections serve as the tsnStreamIdParameters managed object
-+ * 8021CB claus(9.1.1.7).
-+ */
-+struct tsn_cb_null_streamid {
-+      /* tsnCpeNullDownDestMac. Specifies the destination_address that
-+       * identifies a packet in an Enhanced Internal Sublayer Service (EISS)
-+       * indication primitive, to the Null Stream identification function.
-+       */
-+      __u64 dmac;
-+
-+      /* tsnCpeNullDownTagged. It can take the following values:
-+       * 1 tagged: A frame must have a VLAN tag to be recognized as belonging
-+       * to the Stream.
-+       * 2 priority: A frame must be untagged, or have a VLAN tag with a VLAN
-+       * ID = 0 to be recognized as belonging to the Stream.
-+       * 3 all: A frame is recognized as belonging to the Stream whether
-+       * tagged or not.
-+       */
-+      __u8 tagged;
-+
-+      /* tsnCpeNullDownVlan. Specifies the vlan_identifier parameter that
-+       * identifies a packet in an EISS indication primitive to the Null
-+       * Stream identification function. A value of 0 indicates that the vlan
-+       * _identifier parameter is ignored on EISS indication primitives.
-+       */
-+      __u16 vid;
-+};
-+
-+struct tsn_cb_source_streamid {
-+      __u64 smac;
-+      __u8 tagged;
-+      __u16 vid;
-+};
-+
-+struct tsn_cb_dest_streamid {
-+      __u64 down_dmac;
-+      __u8 down_tagged;
-+      __u16 down_vid;
-+      __u8 down_prio;
-+      __u64 up_dmac;
-+      __u8 up_tagged;
-+      __u16 up_vid;
-+      __u8 up_prio;
-+};
-+
-+struct tsn_cb_ip_streamid {
-+      __u64 dmac;
-+      __u8 tagged;
-+      __u16 vid;
-+      __u64 siph;
-+      __u64 sipl;
-+      __u64 diph;
-+      __u64 dipl;
-+      __u8 dscp;
-+      __u8 npt;
-+      __u16 sport;
-+      __u16 dport;
-+};
-+
-+/* 802.1CB stream identify table clause 9.1 */
-+struct tsn_cb_streamid {
-+      /* The objects in a given entry of the Stream identity table are used
-+       * to control packets whose stream_handle subparameter is equal to the
-+       * entry tsnStreamIdHandle object.
-+       */
-+      __s32 handle;
-+
-+      /* The list of ports on which an in-facing Stream identification
-+       * function in the output (towards the system forwarding function)
-+       * direction Only Active Destination MAC and VLAN Stream identification
-+       * (or nothing) can be configured.
-+       */
-+      __u32 ifac_oport;
-+
-+      /* The list of ports on which an out-facing Stream identification
-+       * function in the output (towards the physical interface) direction.
-+       * Only Active Destination MAC and VLAN Stream identification
-+       * (or nothing) can be configured.
-+       */
-+      __u32 ofac_oport;
-+
-+      /* The list of ports on which an in-facing Stream identification
-+       * function in the input (coming from the system forwarding function)
-+       * direction
-+       */
-+      __u32 ifac_iport;
-+
-+      /* The list of ports on which an out-facing Stream identification
-+       * function in the input (coming from the physical interface) direction
-+       * .
-+       */
-+      __u32 ofac_iport;
-+
-+      /* An enumerated value indicating the method used to identify packets
-+       * belonging to the Stream.
-+       * The Organizationally Unique Identifier (OUI) or Company Identifier
-+       * (CID) to identify the organization defining the enumerated type
-+       * should be: 00-80-C2
-+       * 1: null stream identification
-+       * 2: source mac and vlan stream identification
-+       * 3: activ destination mac and vlan stream identification
-+       * 4: ip stream identifaciton
-+       */
-+      __u8 type;
-+
-+      /* tsnStreamIdParameters The number of controlling parameters for a
-+       * Stream identification method, their types and values, are specific
-+       * to the tsnStreamIdIdentificationType
-+       */
-+      union {
-+              struct tsn_cb_null_streamid nid;
-+              struct tsn_cb_source_streamid sid;
-+              struct tsn_cb_dest_streamid did;
-+              struct tsn_cb_ip_streamid iid;
-+      } para;
-+};
-+
-+/* Following counters are instantiated for each port on which the Stream
-+ * identification function (6.2) is configured. The counters are indexed by
-+ * port number, facing (in-facing or out-facing), and stream_handle value
-+ * (tsnStreamIdHandle, 9.1.1.1).
-+ */
-+struct tsn_cb_streamid_counters {
-+      struct {
-+              __u64 input;
-+              __u64 output;
-+      } per_stream;
-+
-+      struct {
-+              __u64 input;
-+              __u64 output;
-+      } per_streamport[32];
-+};
-+
-+/* 802.1Qci Stream Parameter Table, read from port */
-+struct tsn_qci_psfp_stream_param {
-+      /* MaxStreamFilterInstances.
-+       * The maximum number of Stream Filter instances supported by this
-+       * Bridge component.
-+       */
-+      __s32 max_sf_instance;
-+
-+      /* MaxStreamGateInstances
-+       * The maximum number of Stream Gate instances supported by this Bridge
-+       * component.
-+       */
-+      __s32 max_sg_instance;
-+
-+      /* MaxFlowMeterInstances
-+       * The maximum number of Flow Meter instances supported by this Bridge
-+       * component.
-+       */
-+      __s32 max_fm_instance;
-+
-+      /* SupportedListMax
-+       * The maximum value supported by this Bridge component of the
-+       * AdminControlListLength and OperControlListLength parameters.
-+       */
-+      __s32 supported_list_max;
-+};
-+
-+/* 802.1Qci Stream Filter Instance Table, counters part only. */
-+struct tsn_qci_psfp_sfi_counters {
-+      /* The MatchingFramesCount counter counts received frames that match
-+       * this stream filter.
-+       */
-+      __u64 matching_frames_count;
-+
-+      /* The PassingFramesCount counter counts received frames that pass the
-+       * gate associated with this stream filter.
-+       */
-+      __u64 passing_frames_count;
-+
-+      /* The NotPassingFramesCount counter counts received frames that do not
-+       * pass the gate associated with this stream filter.
-+       */
-+      __u64 not_passing_frames_count;
-+
-+      /* The PassingSDUCount counter counts received frames that pass the SDU
-+       * size filter specification associated with this stream filter.
-+       */
-+      __u64 passing_sdu_count;
-+
-+      /* The NotPassingSDUCount counter counts received frames that do not
-+       * pass the SDU size filter specification associated with this stream
-+       * filter.
-+       */
-+      __u64 not_passing_sdu_count;
-+
-+      /* The  REDFramesCount counter counts received random early detection
-+       * (RED) frames associated with this stream filter.
-+       */
-+      __u64 red_frames_count;
-+};
-+
-+/* 802.1Qci Stream Filter Instance Table, configuration part only. */
-+struct tsn_qci_psfp_sfi_conf {
-+
-+      /* The StreamHandleSpec parameter contains a stream identifier
-+       * specification value. A value of -1 denotes the wild card value; zero
-+       * or positive values denote stream identifier values.
-+       */
-+      __s32 stream_handle_spec;
-+
-+      /* The PrioritySpec parameter contains a priority specification value.
-+       * A value of -1 denotes the wild card value; zero or positive values
-+       * denote priority values.
-+       */
-+      __s8 priority_spec;
-+
-+      /* The StreamGateInstanceID parameter contains the index of an entry in
-+       * the Stream Gate Table.
-+       */
-+      __u32 stream_gate_instance_id;
-+
-+      /* The filter specifications. The actions specified in a filter
-+       * specification can result in a frame passing or failing the specified
-+       * filter. Frames that fail a filter are discarded.
-+       */
-+      struct {
-+              /* The MaximumSDUSize parameter specifies the maximum allowed
-+               * frame size for the stream. Any frame exceeding this value
-+               * will be dropped.  A value of 0 denote that the MaximumSDUSize
-+               * filter is disabled for this stream.
-+               */
-+              __u16 maximum_sdu_size;
-+
-+              /* The FlowMeterInstanceID parameter contains the index of an
-+               * entry in the Flow Meter Table.  A value of -1 denotes that
-+               * no flow meter is assigned; zero or positive values denote
-+               * flow meter IDs.
-+               */
-+              __s32 flow_meter_instance_id;
-+      } stream_filter;
-+
-+      /* The StreamBlockedDueToOversizeFrameEnable object contains a Boolean
-+       * value that indicates whether the StreamBlockedDueToOversizeFrame
-+       * function is enabled (TRUE) or disabled (FALSE).
-+       */
-+      __u8 block_oversize_enable;
-+
-+      /* The StreamBlockedDueToOversizeFrame object contains a Boolean value
-+       * that indicates whether, if the StreamBlockedDueToOversizeFrame
-+       * function is enabled, all frames are to be discarded (TRUE) or not
-+       * (FALSE).
-+       */
-+      __u8 block_oversize;
-+};
-+
-+/* 802.1Qci Stream Gate Control List Entry. */
-+struct tsn_qci_psfp_gcl {
-+      /* The GateState parameter specifies a desired state, open (true) or
-+       * closed (false), for the stream gate.
-+       */
-+      __u8 gate_state;
-+
-+      /* An IPV is encoded as a signed integer.  A negative denotes the null
-+       * value; zero or positive values denote internal priority values.
-+       */
-+      __s8 ipv;
-+
-+      /* A TimeInterval is encoded in 4 octets as a 32-bit unsigned integer,
-+       * representing a number of nanoseconds.
-+       */
-+      __u32 time_interval;
-+
-+      /* The maximum number of octets that are permitted to pass the gate
-+       * during the specified TimeInterval.  If zero, there is no maximum.
-+       */
-+      __u32 octet_max;
-+
-+};
-+
-+/* 802.1Qci Stream Gate Admin/Operation common list control parameters */
-+struct tsn_qci_sg_control {
-+      /* The administrative/operation value of the GateStates parameter
-+       * for the stream gate.  A value of false indicates closed;
-+       * a value of true indicates open.
-+       */
-+      __u8 gate_states;
-+
-+      /* The administrative/operation value of the ListMax parameter for the
-+       * gate. The integer value indicates the number of entries (TLVs) in
-+       * the AdminControlList/OperControlList.
-+       */
-+      __u8 control_list_length;
-+
-+      /* The administrative/operation value of the CycleTime parameter for
-+       * the gate.  The value is an unsigned integer number of nanoseconds.
-+       */
-+      __u32 cycle_time;
-+
-+      /* The administrative/operation value of the CycleTimeExtension
-+       * parameter for the gate.  The value is an unsigned integer number
-+       * of nanoseconds.
-+       */
-+      __u32 cycle_time_extension;
-+
-+      /* The administrative/operation value of the BaseTime parameter for the
-+       * gate.  The value is a representation of a PTPtime value, consisting
-+       * of a 48-bit integer number of seconds and a 32-bit integer number of
-+       * nanoseconds.
-+       */
-+      ptptime_t base_time;
-+
-+      /* The administrative/operation value of the IPV parameter for the gate.
-+       * A value of -1 denotes the null value; zero or positive values denote
-+       * internal priority values.
-+       */
-+      __s8 init_ipv;
-+
-+      /* control_list contend the gate control list of
-+       * administrative/operation
-+       */
-+      struct tsn_qci_psfp_gcl *gcl;
-+};
-+
-+/* 802.1Qci Stream Gate Instance Table, configuration part only. */
-+struct tsn_qci_psfp_sgi_conf {
-+      /* The GateEnabled parameter determines whether the stream gate is
-+       * active (true) or inactive (false).
-+       */
-+      __u8 gate_enabled;
-+
-+      /* The ConfigChange parameter signals the start of a configuration
-+       * change when it is set to TRUE. This should only be done when the
-+       * various administrative parameters are all set to appropriate values.
-+       */
-+      __u8 config_change;
-+
-+      /* admin control parameters with admin control list */
-+      struct tsn_qci_sg_control admin;
-+
-+      /* The GateClosedDueToInvalidRxEnable object contains a Boolean value
-+       * that indicates whether the GateClosedDueToInvalidRx function is
-+       * enabled (TRUE) or disabled (FALSE).
-+       */
-+      __u8 block_invalid_rx_enable;
-+
-+      /* The GateClosedDueToInvalidRx object contains a Boolean value that
-+       * indicates whether, if the GateClosedDueToInvalidRx function is
-+       * enabled, all frames are to be discarded (TRUE) or not (FALSE).
-+       */
-+      __u8 block_invalid_rx;
-+
-+      /* The GateClosedDueToOctetsExceededEnable object contains a Boolean
-+       * value that indicates whether the GateClosedDueToOctetsExceeded
-+       * function is enabled (TRUE) or disabled (FALSE).
-+       */
-+      __u8 block_octets_exceeded_enable;
-+
-+      /* The GateClosedDueToOctetsExceeded object contains a Boolean value
-+       * that indicates whether, if the GateClosedDueToOctetsExceeded
-+       * function is enabled, all frames are to be discarded (TRUE) or not
-+       * (FALSE).
-+       */
-+      __u8 block_octets_exceeded;
-+};
-+
-+/* 802.1Qci Stream Gate Instance Table, status part only. */
-+struct tsn_psfp_sgi_status {
-+
-+      /* admin control parameters with admin control list */
-+      struct tsn_qci_sg_control oper;
-+
-+      /* The PTPtime at which the next config change is scheduled to occur.
-+       * The value is a representation of a PTPtime value, consisting of a
-+       * 48-bit integer number of seconds and a 32-bit integer number of
-+       * nanoseconds.
-+       */
-+      ptptime_t config_change_time;
-+
-+      /* The granularity of the cycle time clock, represented as an unsigned
-+       * number of tenths of nanoseconds.
-+       */
-+      __u32 tick_granularity;
-+
-+      /* The current time, in PTPtime, as maintained by the local system.
-+       * The value is a representation of a PTPtime value, consisting of a
-+       * 48-bit integer number of seconds and a 32-bit integer number of
-+       * nanoseconds.
-+       */
-+      ptptime_t current_time;
-+
-+      /* The value of the ConfigPending state machine variable.  The value is
-+       * TRUE if a configuration change is in progress but has not yet
-+       * completed.
-+       */
-+      __u8 config_pending;
-+
-+      /* A counter of the number of times that a re-configuration of the
-+       * traffic schedule has been requested with the old schedule still
-+       * running and the requested base time was in the past.
-+       */
-+      __u64 config_change_error;
-+
-+};
-+
-+/* 802.1Qci Flow Meter Instance Table. */
-+struct tsn_qci_psfp_fmi {
-+      /* The FlowMeterCIR parameter contains an integer value that represents
-+       * the CIR value for the flow meter, in kbit/s.
-+       */
-+      __u32 cir;
-+
-+      /* The FlowMeterCBS parameter contains an integer value that represents
-+       * the CBS value for the flow meter, in octets.
-+       */
-+      __u32 cbs;
-+
-+      /* The FlowMeterEIR parameter contains an integer value that represents
-+       * the EIR value for the flow meter, in kbit/s.
-+       */
-+      __u32 eir;
-+
-+      /* The FlowMeterEBS parameter contains an integer value that represents
-+       * the EBS value for the flow meter, in octets.
-+       */
-+      __u32 ebs;
-+
-+      /* The FlowMeterCF parameter contains a Boolean value that represents
-+       * the CF value for the flow meter, as a Boolean value indicating no
-+       * coupling (FALSE) or coupling (TRUE).
-+       */
-+      __u8 cf;
-+
-+      /* The FlowMeterCM parameter contains a Boolean value that represents
-+       * the CM value for the flow meter, as a Boolean value indicating
-+       * colorBlind (FALSE) or colorAware (TRUE).
-+       */
-+      __u8 cm;
-+
-+      /* The FlowMeterDropOnYellow parameter contains a Boolean value that
-+       * indicates whether yellow frames are dropped (TRUE) or have
-+       * drop_eligible set to TRUE (FALSE).
-+       */
-+      __u8 drop_on_yellow;
-+
-+      /* The FlowMeterMarkAllFramesRedEnable parameter contains a Boolean
-+       * value that indicates whether the MarkAllFramesRed function
-+       * is enabled (TRUE) or disabled (FALSE).
-+       */
-+      __u8 mark_red_enable;
-+
-+      /* The FlowMeterMarkAllFramesRed parameter contains a Boolean value
-+       * that indicates whether, if the MarkAllFramesRed function is enabled,
-+       * all frames are to be discarded (TRUE) or not (FALSE).
-+       */
-+      __u8 mark_red;
-+};
-+
-+struct tsn_qci_psfp_fmi_counters {
-+      __u64 bytecount;
-+      __u64 drop;
-+      __u64 dr0_green;
-+      __u64 dr1_green;
-+      __u64 dr2_yellow;
-+      __u64 remark_yellow;
-+      __u64 dr3_red;
-+      __u64 remark_red;
-+};
-+
-+/* 802.1cb */
-+struct tsn_seq_gen_conf {
-+
-+      /* The InputPortMask parameter contains a port mask.
-+       * If the packet is from input port belonging to this
-+       * port mask then it's on known stream and sequence
-+       * generation parameters can be applied.
-+       */
-+      __u8 iport_mask;
-+
-+      /* The SplitMask parameter contains a output port mask
-+       * used to add redundant paths.
-+       */
-+      __u8 split_mask;
-+
-+      /* The SequenceSpaceLenLog parameter is a value to specifies
-+       * number of bits to be used for sequence number.
-+       */
-+      __u8 seq_len;
-+
-+      /* The SequenceNumber parameter is a value to used for
-+       * outgoing packet's sequence number generation.
-+       */
-+      __u32 seq_num;
-+};
-+
-+struct tsn_seq_rec_conf {
-+
-+      /* The SequenceSpaceLenLog parameter is a value to specifies
-+       * number of bits to be used for sequence number.
-+       */
-+      __u8 seq_len;
-+
-+      /* The HistorySpaceLenLog parameter is a value to specifies
-+       * number of bits to be used for history register.
-+       */
-+      __u8 his_len;
-+
-+      /* The RTagPopEnable parameter contains a __u8 to enable removal
-+       * of redundancy tag from the packet.
-+       */
-+      __u8 rtag_pop_en;
-+};
-+
-+struct tsn_cb_status {
-+
-+      /* The GenRecover parameter contains a value specifies type
-+       * of stream sequence parameters:
-+       *      0: Stream sequence parameters are for generation.
-+       *      1: Stream sequence parameters are for recovery.
-+       */
-+      __u8 gen_rec;
-+
-+      /* The ErrStatus parameter indicates stream's error status
-+       * 1: This switch is expected to sequence the stream,
-+       *    but the incoming packet has sequence number.
-+       * 2: This switch is expected to recover the stream,
-+       *    but the incoming packet is NONSEQ.
-+       */
-+      __u8 err;
-+
-+      /* The SequenceNumber parameter is a value to used for
-+       * outgoing packet's sequence number generation.
-+       */
-+      __u32 seq_num;
-+
-+      /* The SequenceSpaceLenLog parameter is a value to specifies
-+       * number of bits to be used for sequence number.
-+       */
-+      __u8 seq_len;
-+
-+      /* The SplitMask parameter contains a output port mask
-+       * used to add redundant paths.
-+       */
-+      __u8 split_mask;
-+
-+      /* The InputPortMask parameter contains a port mask.
-+       * If the packet is from input port belonging to this
-+       * port mask then it's on known stream and sequence
-+       * generation parameters can be applied.
-+       */
-+      __u8 iport_mask;
-+
-+      /* The HistorySpaceLenLog parameter is a value to specifies
-+       * number of bits to be used for history register.
-+       */
-+      __u8 his_len;
-+
-+      /* The SequenceHistory parameter Maintains history of sequence
-+       * numbers of received packets.
-+       */
-+      __u32 seq_his;
-+};
-+
-+/* An entry for gate control list */
-+struct tsn_qbv_entry {
-+      /* Octet represent the gate states for the corresponding traffic
-+       * classes.
-+       * The MS bit corresponds to traffic class 7.
-+       * The LS bit to traffic class 0.
-+       * A bit value of 0 indicates closed;
-+       * A bit value of 1 indicates open.
-+       */
-+      __u8 gate_state;
-+
-+      /* A TimeInterval is encoded in 4 octets as a 32-bit unsigned integer,
-+       * representing a number of nanoseconds.
-+       */
-+      __u32 time_interval;
-+};
-+
-+/* The administrative/operation time and gate list */
-+struct tsn_qbv_basic {
-+      /* The administrative/operation value of the GateStates parameter for
-+       * the Port.
-+       * The bits of the octet represent the gate states for the
-+       * corresponding traffic classes; the MS bit corresponds to traffic
-+       * class 7, the LS bit to traffic class 0. A bit value of 0 indicates
-+       * closed; a bit value of 1 indicates open.
-+       * The value of this object MUST be retained
-+       * across reinitializations of the management system.
-+       */
-+      __u8 gate_states;
-+
-+      /* The administrative/operation value of the ListMax parameter for the
-+       * port. The integer value indicates the number of entries (TLVs) in
-+       * the AdminControlList. The value of this object MUST be retained
-+       * across reinitializations of the management system.
-+       */
-+      __u32 control_list_length;
-+
-+      /* The administrative/operation value of the AdminCycleTime
-+       * parameter for the Port. The numerator and denominator together
-+       * represent the cycle time as a rational number of seconds.  The value
-+       * of this object MUST be retained across reinitializations of the
-+       * management system.
-+       */
-+      __u32 cycle_time;
-+
-+      /* The administrative/operation value of the CycleTimeExtension
-+       * parameter for the Port. The value is an unsigned integer number of
-+       * nanoseconds.
-+       * The value of this object MUST be retained across reinitializations
-+       * of the management system.
-+       */
-+
-+      __u32 cycle_time_extension;
-+
-+      /* The administrative/operation value of the BaseTime parameter for the
-+       * Port.  The value is a representation of a PTPtime value, consisting
-+       * of a 48-bit integer number of seconds and a 32-bit integer number of
-+       * nanoseconds.
-+       * The value of this object MUST be retained across reinitializations of
-+       * the management system.
-+       */
-+      ptptime_t base_time;
-+
-+      /* admin_control_list represent the AdminControlList/OperControlList.
-+       * The administrative version of the gate control list for the Port.
-+       */
-+      struct tsn_qbv_entry *control_list;
-+};
-+
-+struct tsn_qbv_conf {
-+      /* The GateEnabled parameter determines whether traffic scheduling is
-+       * active (true) or inactive (false).  The value of this object MUST be
-+       * retained across reinitializations of the management system.
-+       */
-+      __u8 gate_enabled;
-+
-+      /* The maxsdu parameter denoting the maximum SDU size supported by the
-+       * queue.
-+       */
-+      __u32 maxsdu;
-+
-+      /* The ConfigChange parameter signals the start of a configuration
-+       * change when it is set to TRUE. This should only be done when the
-+       * various administrative parameters are all set to appropriate values.
-+       */
-+      __u8 config_change;
-+
-+      /* The admin parameter signals the admin relate cycletime, basictime,
-+       * gatelist paraters.
-+       */
-+      struct tsn_qbv_basic admin;
-+};
-+
-+/* 802.1Qbv (Time Aware Shaper) port status */
-+struct tsn_qbv_status {
-+      /* The PTPtime at which the next config change is scheduled to occur.
-+       * The value is a representation of a PTPtime value, consisting of a
-+       * 48-bit integer number of seconds and a 32-bit integer number of
-+       * nanoseconds.  The value of this object MUST be retained across
-+       * reinitializations of the management system.
-+       */
-+      ptptime_t config_change_time;
-+
-+      /* The granularity of the cycle time clock, represented as an unsigned
-+       * number of tenths of nanoseconds.  The value of this object MUST be
-+       * retained across reinitializations of the management system.
-+       */
-+      __u32 tick_granularity;
-+
-+      /* The current time, in PTPtime, as maintained by the local system.
-+       * The value is a representation of a PTPtime value, consisting of a
-+       * 48-bit integer number of seconds and a 32-bit integer number of
-+       * nanoseconds.
-+       */
-+      ptptime_t  current_time;
-+
-+      /* The value of the ConfigPending state machine variable.  The value is
-+       * TRUE if a configuration change is in progress but has not yet
-+       * completed.
-+       */
-+      __u8 config_pending;
-+
-+      /* A counter of the number of times that a re-configuration of the
-+       * traffic schedule has been requested with the old schedule still
-+       * running and the requested base time was in the past.
-+       */
-+      __u64 config_change_error;
-+
-+      /* The maximum value supported by this Port of the
-+       * AdminControlListLength and OperControlListLength parameters.
-+       */
-+      __u32 supported_list_max;
-+
-+      /* Operation settings parameters and Oper gate list */
-+      struct tsn_qbv_basic oper;
-+};
-+
-+/* Time Specific Departure parameters */
-+struct tsn_tsd {
-+      __u8 enable;
-+
-+      /* The cycle time, in units of microsecond(us)*/
-+      __u32 period;
-+
-+      /* The maximum number of frames which could be transmitted on one cycle
-+       *  The exceeding frames will be transmitted on next cycle.
-+       */
-+      __u32 maxFrameNum;
-+
-+      /* Specify the time of the first cycle begins.
-+       *      1:  begin when the queue get the first frame to transmit.
-+       *      2:  begin immediately at the end of setting function.
-+       */
-+      __u32 syn_flag;
-+};
-+
-+struct tsn_tsd_status {
-+      __u8 enable;
-+      __u32 period;
-+      __u32 maxFrameNum;
-+      __u32 flag;
-+      __u32 cycleNum;
-+      __u32 loss_steps;
-+};
-+
-+struct tsn_qos_switch_dscp_conf {
-+      __u8 trust;
-+      __u8 cos;
-+      __u8 dpl;
-+      __u8 remark;
-+      __u8 dscp; /* New ingress translated DSCP value */
-+};
-+
-+#endif /* _UAPI_GENL_TSN_H */
---- a/net/Kconfig
-+++ b/net/Kconfig
-@@ -240,6 +240,7 @@ source "net/ieee802154/Kconfig"
- source "net/mac802154/Kconfig"
- source "net/sched/Kconfig"
- source "net/dcb/Kconfig"
-+source "net/tsn/Kconfig"
- source "net/dns_resolver/Kconfig"
- source "net/batman-adv/Kconfig"
- source "net/openvswitch/Kconfig"
---- a/net/Makefile
-+++ b/net/Makefile
-@@ -59,6 +59,9 @@ obj-$(CONFIG_CAIF)           += caif/
- ifneq ($(CONFIG_DCB),)
- obj-y                         += dcb/
- endif
-+ifneq ($(CONFIG_TSN),)
-+obj-y                                 += tsn/
-+endif
- obj-$(CONFIG_6LOWPAN)         += 6lowpan/
- obj-$(CONFIG_IEEE802154)      += ieee802154/
- obj-$(CONFIG_MAC802154)               += mac802154/
---- /dev/null
-+++ b/net/tsn/Kconfig
-@@ -0,0 +1,15 @@
-+config TSN
-+      bool "802.1 Time-Sensitive Networking support"
-+      default n
-+      depends on VLAN_8021Q && PTP_1588_CLOCK
-+      help
-+        This enables support for TSN(time sensitive networking)
-+        TSN features include:
-+              802.1Qav:
-+              802.1Qbv:
-+              802.1Qci:
-+              802.1Qbu:
-+              802.1AS:
-+              802.1CB:
-+
-+        If unsure, say N.
---- /dev/null
-+++ b/net/tsn/Makefile
-@@ -0,0 +1 @@
-+obj-$(CONFIG_TSN) += genl_tsn.o
---- /dev/null
-+++ b/net/tsn/genl_tsn.c
-@@ -0,0 +1,3696 @@
-+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
-+/* Copyright 2017-2019 NXP */
-+
-+#include <linux/module.h>
-+#include <linux/kernel.h>
-+#include <linux/init.h>
-+#include <linux/netdevice.h>
-+#include <linux/if_vlan.h>
-+#include <net/genetlink.h>
-+#include <net/netlink.h>
-+#include <linux/version.h>
-+#include <net/tsn.h>
-+
-+#define NLA_PARSE_NESTED(a, b, c, d) \
-+      nla_parse_nested_deprecated(a, b, c, d, NULL)
-+#define NLA_PUT_U64(a, b, c) nla_put_u64_64bit(a, b, c, NLA_U64)
-+
-+static struct genl_family tsn_family;
-+
-+LIST_HEAD(port_list);
-+
-+static const struct nla_policy tsn_cmd_policy[TSN_CMD_ATTR_MAX + 1] = {
-+      [TSN_CMD_ATTR_MESG]             = { .type = NLA_STRING },
-+      [TSN_CMD_ATTR_DATA]             = { .type = NLA_S32 },
-+      [TSN_ATTR_IFNAME]               = { .type = NLA_STRING },
-+      [TSN_ATTR_PORT_NUMBER]          = { .type = NLA_U8 },
-+      [TSN_ATTR_CAP]                  = { .type = NLA_NESTED  },
-+      [TSN_ATTR_QBV]                  = { .type = NLA_NESTED },
-+      [TSN_ATTR_STREAM_IDENTIFY]      = { .type = NLA_NESTED },
-+      [TSN_ATTR_QCI_SP]               = { .type = NLA_NESTED },
-+      [TSN_ATTR_QCI_SFI]              = { .type = NLA_NESTED },
-+      [TSN_ATTR_QCI_SGI]              = { .type = NLA_NESTED },
-+      [TSN_ATTR_QCI_FMI]              = { .type = NLA_NESTED },
-+      [TSN_ATTR_CBS]                  = { .type = NLA_NESTED },
-+      [TSN_ATTR_TSD]                  = { .type = NLA_NESTED },
-+      [TSN_ATTR_QBU]                  = { .type = NLA_NESTED },
-+      [TSN_ATTR_CT]                   = { .type = NLA_NESTED },
-+      [TSN_ATTR_CBGEN]                = { .type = NLA_NESTED },
-+      [TSN_ATTR_CBREC]                = { .type = NLA_NESTED },
-+      [TSN_ATTR_CBSTAT]               = { .type = NLA_NESTED },
-+      [TSN_ATTR_DSCP]                 = { .type = NLA_NESTED },
-+};
-+
-+static const struct nla_policy tsn_cap_policy[TSN_CAP_ATTR_MAX + 1] = {
-+      [TSN_CAP_ATTR_QBV]              = { .type = NLA_FLAG },
-+      [TSN_CAP_ATTR_QCI]              = { .type = NLA_FLAG },
-+      [TSN_CAP_ATTR_QBU]              = { .type = NLA_FLAG },
-+      [TSN_CAP_ATTR_CBS]              = { .type = NLA_FLAG },
-+      [TSN_CAP_ATTR_CB]               = { .type = NLA_FLAG },
-+      [TSN_CAP_ATTR_TBS]              = { .type = NLA_FLAG },
-+      [TSN_CAP_ATTR_CTH]              = { .type = NLA_FLAG },
-+};
-+
-+static const struct nla_policy qci_cap_policy[TSN_QCI_STREAM_ATTR_MAX + 1] = {
-+      [TSN_QCI_STREAM_ATTR_MAX_SFI]   = { .type = NLA_U32 },
-+      [TSN_QCI_STREAM_ATTR_MAX_SGI]   = { .type = NLA_U32 },
-+      [TSN_QCI_STREAM_ATTR_MAX_FMI]   = { .type = NLA_U32 },
-+      [TSN_QCI_STREAM_ATTR_SLM]       = { .type = NLA_U32 },
-+};
-+
-+static const struct nla_policy ct_policy[TSN_CT_ATTR_MAX + 1] = {
-+      [TSN_CT_ATTR_QUEUE_STATE]       = { .type = NLA_U8 }
-+};
-+
-+static const struct nla_policy cbgen_policy[TSN_CBGEN_ATTR_MAX + 1] = {
-+      [TSN_CBGEN_ATTR_INDEX]          = { .type = NLA_U32 },
-+      [TSN_CBGEN_ATTR_PORT_MASK]      = { .type = NLA_U8 },
-+      [TSN_CBGEN_ATTR_SPLIT_MASK]     = { .type = NLA_U8 },
-+      [TSN_CBGEN_ATTR_SEQ_LEN]        = { .type = NLA_U8 },
-+      [TSN_CBGEN_ATTR_SEQ_NUM]        = { .type = NLA_U32 },
-+};
-+
-+static const struct nla_policy cbrec_policy[TSN_CBREC_ATTR_MAX + 1] = {
-+      [TSN_CBREC_ATTR_INDEX]          = { .type = NLA_U32 },
-+      [TSN_CBREC_ATTR_SEQ_LEN]        = { .type = NLA_U8 },
-+      [TSN_CBREC_ATTR_HIS_LEN]        = { .type = NLA_U8 },
-+      [TSN_CBREC_ATTR_TAG_POP_EN]     = { .type = NLA_FLAG },
-+};
-+
-+static const struct nla_policy cbstat_policy[TSN_CBSTAT_ATTR_MAX + 1] = {
-+      [TSN_CBSTAT_ATTR_INDEX]         = { .type = NLA_U32 },
-+      [TSN_CBSTAT_ATTR_GEN_REC]       = { .type = NLA_U8 },
-+      [TSN_CBSTAT_ATTR_ERR]           = { .type = NLA_U8 },
-+      [TSN_CBSTAT_ATTR_SEQ_NUM]       = { .type = NLA_U32 },
-+      [TSN_CBSTAT_ATTR_SEQ_LEN]       = { .type = NLA_U8 },
-+      [TSN_CBSTAT_ATTR_SPLIT_MASK]    = { .type = NLA_U8 },
-+      [TSN_CBSTAT_ATTR_PORT_MASK]     = { .type = NLA_U8 },
-+      [TSN_CBSTAT_ATTR_HIS_LEN]       = { .type = NLA_U8 },
-+      [TSN_CBSTAT_ATTR_SEQ_HIS]       = { .type = NLA_U32 },
-+};
-+
-+static const struct nla_policy qbu_policy[TSN_QBU_ATTR_MAX + 1] = {
-+      [TSN_QBU_ATTR_ADMIN_STATE]      = { .type = NLA_U8 },
-+      [TSN_QBU_ATTR_HOLD_ADVANCE]     = { .type = NLA_U32},
-+      [TSN_QBU_ATTR_RELEASE_ADVANCE]  = { .type = NLA_U32},
-+      [TSN_QBU_ATTR_ACTIVE]           = { .type = NLA_FLAG},
-+      [TSN_QBU_ATTR_HOLD_REQUEST]     = { .type = NLA_U8},
-+};
-+
-+static const struct nla_policy cbs_policy[TSN_CBS_ATTR_MAX + 1] = {
-+      [TSN_CBS_ATTR_TC_INDEX]         = { .type = NLA_U8},
-+      [TSN_CBS_ATTR_BW]               = { .type = NLA_U8},
-+};
-+
-+static const struct nla_policy tsd_policy[TSN_TSD_ATTR_MAX + 1] = {
-+      [TSN_TSD_ATTR_ENABLE]                   = { .type = NLA_FLAG},
-+      [TSN_TSD_ATTR_DISABLE]                  = { .type = NLA_FLAG},
-+      [TSN_TSD_ATTR_PERIOD]                   = { .type = NLA_U32},
-+      [TSN_TSD_ATTR_MAX_FRM_NUM]              = { .type = NLA_U32},
-+      [TSN_TSD_ATTR_CYCLE_NUM]                = { .type = NLA_U32},
-+      [TSN_TSD_ATTR_LOSS_STEPS]               = { .type = NLA_U32},
-+      [TSN_TSD_ATTR_SYN_IMME]                 = { .type = NLA_FLAG},
-+};
-+
-+static const struct nla_policy qbv_policy[TSN_QBV_ATTR_MAX + 1] = {
-+      [TSN_QBV_ATTR_ADMINENTRY]       = {     .type = NLA_NESTED},
-+      [TSN_QBV_ATTR_OPERENTRY]        = { .type = NLA_NESTED},
-+      [TSN_QBV_ATTR_ENABLE]           = { .type = NLA_FLAG},
-+      [TSN_QBV_ATTR_DISABLE]          = { .type = NLA_FLAG},
-+      [TSN_QBV_ATTR_CONFIGCHANGE]     = { .type = NLA_FLAG},
-+      [TSN_QBV_ATTR_CONFIGCHANGETIME] = { .type = NLA_U64},
-+      [TSN_QBV_ATTR_MAXSDU]           = { .type = NLA_U32},
-+      [TSN_QBV_ATTR_GRANULARITY]      = { .type = NLA_U32},
-+      [TSN_QBV_ATTR_CURRENTTIME]      = { .type = NLA_U64},
-+      [TSN_QBV_ATTR_CONFIGPENDING]    = {.type = NLA_FLAG},
-+      [TSN_QBV_ATTR_CONFIGCHANGEERROR]        = { .type = NLA_U64},
-+      [TSN_QBV_ATTR_LISTMAX]          = { .type = NLA_U32},
-+};
-+
-+static const struct nla_policy qbv_ctrl_policy[TSN_QBV_ATTR_CTRL_MAX + 1] = {
-+      [TSN_QBV_ATTR_CTRL_LISTCOUNT]           = { .type = NLA_U32},
-+      [TSN_QBV_ATTR_CTRL_GATESTATE]           = { .type = NLA_U8},
-+      [TSN_QBV_ATTR_CTRL_CYCLETIME]           = { .type = NLA_U32},
-+      [TSN_QBV_ATTR_CTRL_CYCLETIMEEXT]        = { .type = NLA_U32},
-+      [TSN_QBV_ATTR_CTRL_BASETIME]            = { .type = NLA_U64},
-+      [TSN_QBV_ATTR_CTRL_LISTENTRY]           = { .type = NLA_NESTED},
-+};
-+
-+static const struct nla_policy qbv_entry_policy[TSN_QBV_ATTR_ENTRY_MAX + 1] = {
-+      [TSN_QBV_ATTR_ENTRY_ID] = { .type = NLA_U32},
-+      [TSN_QBV_ATTR_ENTRY_GC] = { .type = NLA_U8},
-+      [TSN_QBV_ATTR_ENTRY_TM] = { .type = NLA_U32},
-+};
-+
-+static const struct nla_policy cb_streamid_policy[TSN_STREAMID_ATTR_MAX + 1] = {
-+      [TSN_STREAMID_ATTR_INDEX]       = { .type = NLA_U32},
-+      [TSN_STREAMID_ATTR_ENABLE]      = { .type = NLA_FLAG},
-+      [TSN_STREAMID_ATTR_DISABLE]     = { .type = NLA_FLAG},
-+      [TSN_STREAMID_ATTR_STREAM_HANDLE]       = { .type = NLA_S32},
-+      [TSN_STREAMID_ATTR_IFOP]        = { .type = NLA_U32},
-+      [TSN_STREAMID_ATTR_OFOP]        = { .type = NLA_U32},
-+      [TSN_STREAMID_ATTR_IFIP]        = { .type = NLA_U32},
-+      [TSN_STREAMID_ATTR_OFIP]        = { .type = NLA_U32},
-+      [TSN_STREAMID_ATTR_TYPE]        = { .type = NLA_U8},
-+      [TSN_STREAMID_ATTR_NDMAC]       = { .type = NLA_U64},
-+      [TSN_STREAMID_ATTR_NTAGGED]     = { .type = NLA_U8},
-+      [TSN_STREAMID_ATTR_NVID]        = { .type = NLA_U16},
-+      [TSN_STREAMID_ATTR_SMAC]        = { .type = NLA_U64},
-+      [TSN_STREAMID_ATTR_STAGGED]     = { .type = NLA_U8},
-+      [TSN_STREAMID_ATTR_SVID]        = { .type = NLA_U16},
-+      [TSN_STREAMID_ATTR_COUNTERS_PSI] = { .type = NLA_U64},
-+      [TSN_STREAMID_ATTR_COUNTERS_PSO] = { .type = NLA_U64},
-+      [TSN_STREAMID_ATTR_COUNTERS_PSPPI] = { .type = NLA_U64},
-+      [TSN_STREAMID_ATTR_COUNTERS_PSPPO] = { .type = NLA_U64},
-+};
-+
-+static const struct nla_policy qci_sfi_policy[TSN_QCI_SFI_ATTR_MAX + 1] = {
-+      [TSN_QCI_SFI_ATTR_INDEX]                = { .type = NLA_U32},
-+      [TSN_QCI_SFI_ATTR_ENABLE]               = { .type = NLA_FLAG},
-+      [TSN_QCI_SFI_ATTR_DISABLE]              = { .type = NLA_FLAG},
-+      [TSN_QCI_SFI_ATTR_STREAM_HANDLE]        = { .type = NLA_S32},
-+      [TSN_QCI_SFI_ATTR_PRIO_SPEC]            = { .type = NLA_S8},
-+      [TSN_QCI_SFI_ATTR_GATE_ID]              = { .type = NLA_U32},
-+      [TSN_QCI_SFI_ATTR_FILTER_TYPE]          = { .type = NLA_U8},
-+      [TSN_QCI_SFI_ATTR_FLOW_ID]              = { .type = NLA_S32},
-+      [TSN_QCI_SFI_ATTR_MAXSDU]               = { .type = NLA_U16},
-+      [TSN_QCI_SFI_ATTR_COUNTERS]             = {
-+              .len = sizeof(struct tsn_qci_psfp_sfi_counters)},
-+      [TSN_QCI_SFI_ATTR_OVERSIZE_ENABLE]      = { .type = NLA_FLAG},
-+      [TSN_QCI_SFI_ATTR_OVERSIZE]             = { .type = NLA_FLAG},
-+};
-+
-+static const struct nla_policy qci_sgi_policy[] = {
-+      [TSN_QCI_SGI_ATTR_INDEX]                = { .type = NLA_U32},
-+      [TSN_QCI_SGI_ATTR_ENABLE]               = { .type = NLA_FLAG},
-+      [TSN_QCI_SGI_ATTR_DISABLE]              = { .type = NLA_FLAG},
-+      [TSN_QCI_SGI_ATTR_CONFCHANGE]           = { .type = NLA_FLAG},
-+      [TSN_QCI_SGI_ATTR_IRXEN]                = { .type = NLA_FLAG},
-+      [TSN_QCI_SGI_ATTR_IRX]                  = { .type = NLA_FLAG},
-+      [TSN_QCI_SGI_ATTR_OEXEN]                = { .type = NLA_FLAG},
-+      [TSN_QCI_SGI_ATTR_OEX]                  = { .type = NLA_FLAG},
-+      [TSN_QCI_SGI_ATTR_ADMINENTRY]           = { .type = NLA_NESTED},
-+      [TSN_QCI_SGI_ATTR_OPERENTRY]            = { .type = NLA_NESTED},
-+      [TSN_QCI_SGI_ATTR_CCTIME]               = { .type = NLA_U64},
-+      [TSN_QCI_SGI_ATTR_TICKG]                = { .type = NLA_U32},
-+      [TSN_QCI_SGI_ATTR_CUTIME]               = { .type = NLA_U64},
-+      [TSN_QCI_SGI_ATTR_CPENDING]             = { .type = NLA_FLAG},
-+      [TSN_QCI_SGI_ATTR_CCERROR]              = { .type = NLA_U64},
-+};
-+
-+static const struct nla_policy qci_sgi_ctrl_policy[] = {
-+      [TSN_SGI_ATTR_CTRL_INITSTATE]           = { .type = NLA_FLAG},
-+      [TSN_SGI_ATTR_CTRL_LEN]                 = { .type = NLA_U8},
-+      [TSN_SGI_ATTR_CTRL_CYTIME]              = { .type = NLA_U32},
-+      [TSN_SGI_ATTR_CTRL_CYTIMEEX]            = { .type = NLA_U32},
-+      [TSN_SGI_ATTR_CTRL_BTIME]               = { .type = NLA_U64},
-+      [TSN_SGI_ATTR_CTRL_INITIPV]             = { .type = NLA_S8},
-+      [TSN_SGI_ATTR_CTRL_GCLENTRY]            = { .type = NLA_NESTED},
-+};
-+
-+static const struct nla_policy qci_sgi_gcl_policy[] = {
-+      [TSN_SGI_ATTR_GCL_GATESTATE]            = { .type = NLA_FLAG},
-+      [TSN_SGI_ATTR_GCL_IPV]                  = { .type = NLA_S8},
-+      [TSN_SGI_ATTR_GCL_INTERVAL]             = { .type = NLA_U32},
-+      [TSN_SGI_ATTR_GCL_OCTMAX]               = { .type = NLA_U32},
-+};
-+
-+static const struct nla_policy qci_fmi_policy[] = {
-+      [TSN_QCI_FMI_ATTR_INDEX]        = { .type = NLA_U32},
-+      [TSN_QCI_FMI_ATTR_ENABLE]       = { .type = NLA_FLAG},
-+      [TSN_QCI_FMI_ATTR_DISABLE]      = { .type = NLA_FLAG},
-+      [TSN_QCI_FMI_ATTR_CIR]          = { .type = NLA_U32},
-+      [TSN_QCI_FMI_ATTR_CBS]          = { .type = NLA_U32},
-+      [TSN_QCI_FMI_ATTR_EIR]          = { .type = NLA_U32},
-+      [TSN_QCI_FMI_ATTR_EBS]          = { .type = NLA_U32},
-+      [TSN_QCI_FMI_ATTR_CF]           = { .type = NLA_FLAG},
-+      [TSN_QCI_FMI_ATTR_CM]           = { .type = NLA_FLAG},
-+      [TSN_QCI_FMI_ATTR_DROPYL]       = { .type = NLA_FLAG},
-+      [TSN_QCI_FMI_ATTR_MAREDEN]      = { .type = NLA_FLAG},
-+      [TSN_QCI_FMI_ATTR_MARED]        = { .type = NLA_FLAG},
-+      [TSN_QCI_FMI_ATTR_COUNTERS]     = {
-+              .len = sizeof(struct tsn_qci_psfp_fmi_counters)},
-+};
-+
-+static const struct nla_policy dscp_policy[] = {
-+      [TSN_DSCP_ATTR_INDEX]           = { .type = NLA_U32},
-+      [TSN_DSCP_ATTR_DISABLE]         = { .type = NLA_FLAG},
-+      [TSN_DSCP_ATTR_COS]             = { .type = NLA_U8},
-+      [TSN_DSCP_ATTR_DPL]             = { .type = NLA_U8},
-+};
-+
-+static ATOMIC_NOTIFIER_HEAD(tsn_notif_chain);
-+
-+/**
-+ *    register_tsn_notifier - Register notifier
-+ *    @nb: notifier_block
-+ *
-+ *    Register switch device notifier.
-+ */
-+int register_tsn_notifier(struct notifier_block *nb)
-+{
-+      return atomic_notifier_chain_register(&tsn_notif_chain, nb);
-+}
-+EXPORT_SYMBOL_GPL(register_tsn_notifier);
-+
-+/**
-+ *    unregister_tsn_notifier - Unregister notifier
-+ *    @nb: notifier_block
-+ *
-+ *    Unregister switch device notifier.
-+ */
-+int unregister_tsn_notifier(struct notifier_block *nb)
-+{
-+      return atomic_notifier_chain_unregister(&tsn_notif_chain, nb);
-+}
-+EXPORT_SYMBOL_GPL(unregister_tsn_notifier);
-+
-+/**
-+ *    call_tsn_notifiers - Call notifiers
-+ *    @val: value passed unmodified to notifier function
-+ *    @dev: port device
-+ *    @info: notifier information data
-+ *
-+ *    Call all network notifier blocks.
-+ */
-+int call_tsn_notifiers(unsigned long val, struct net_device *dev,
-+                     struct tsn_notifier_info *info)
-+{
-+      info->dev = dev;
-+      return atomic_notifier_call_chain(&tsn_notif_chain, val, info);
-+}
-+EXPORT_SYMBOL_GPL(call_tsn_notifiers);
-+
-+struct tsn_port *tsn_get_port(struct net_device *ndev)
-+{
-+      struct tsn_port *port;
-+      bool tsn_found = false;
-+
-+      list_for_each_entry(port, &port_list, list) {
-+              if (port->netdev == ndev) {
-+                      tsn_found = true;
-+                      break;
-+              }
-+      }
-+
-+      if (!tsn_found)
-+              return NULL;
-+
-+      return port;
-+}
-+EXPORT_SYMBOL_GPL(tsn_get_port);
-+
-+static int tsn_prepare_reply(struct genl_info *info, u8 cmd,
-+                           struct sk_buff **skbp, size_t size)
-+{
-+      struct sk_buff *skb;
-+      void *reply;
-+
-+      /* If new attributes are added, please revisit this allocation
-+       */
-+      skb = genlmsg_new(size, GFP_KERNEL);
-+      if (!skb)
-+              return -ENOMEM;
-+
-+      if (!info) {
-+              nlmsg_free(skb);
-+              return -EINVAL;
-+      }
-+
-+      reply = genlmsg_put_reply(skb, info, &tsn_family, 0, cmd);
-+      if (!reply) {
-+              nlmsg_free(skb);
-+              return -EINVAL;
-+      }
-+
-+      *skbp = skb;
-+      return 0;
-+}
-+
-+static int tsn_mk_reply(struct sk_buff *skb, int aggr, void *data, int len)
-+{
-+    /* add a netlink attribute to a socket buffer */
-+      return nla_put(skb, aggr, len, data);
-+}
-+
-+static int tsn_send_reply(struct sk_buff *skb, struct genl_info *info)
-+{
-+      struct genlmsghdr *genlhdr = nlmsg_data(nlmsg_hdr(skb));
-+      void *reply = genlmsg_data(genlhdr);
-+
-+      genlmsg_end(skb, reply);
-+
-+      return genlmsg_reply(skb, info);
-+}
-+
-+static int cmd_attr_echo_message(struct genl_info *info)
-+{
-+      struct nlattr *na;
-+      char *msg;
-+      struct sk_buff *rep_skb;
-+      size_t size;
-+      int ret;
-+
-+      na = info->attrs[TSN_CMD_ATTR_MESG];
-+      if (!na)
-+              return -EINVAL;
-+
-+      msg = (char *)nla_data(na);
-+      pr_info("tsn generic netlink receive echo mesg %s\n", msg);
-+
-+      size = nla_total_size(strlen(msg) + 1);
-+
-+      ret = tsn_prepare_reply(info, TSN_CMD_REPLY, &rep_skb,
-+                              size + NLMSG_ALIGN(MAX_USER_SIZE));
-+      if (ret < 0)
-+              return ret;
-+
-+      ret = tsn_mk_reply(rep_skb, TSN_CMD_ATTR_MESG, msg, size);
-+      if (ret < 0)
-+              goto err;
-+
-+      return tsn_send_reply(rep_skb, info);
-+
-+err:
-+      nlmsg_free(rep_skb);
-+      return ret;
-+}
-+
-+static int cmd_attr_echo_data(struct genl_info *info)
-+{
-+      struct nlattr *na;
-+      s32     data;
-+      struct sk_buff *rep_skb;
-+      size_t size;
-+      int ret;
-+
-+      /*read data */
-+      na = info->attrs[TSN_CMD_ATTR_DATA];
-+      if (!na)
-+              return -EINVAL;
-+
-+      data = nla_get_s32(info->attrs[TSN_CMD_ATTR_DATA]);
-+      pr_info("tsn generic netlink receive echo data %d\n", data);
-+
-+      /* send back */
-+      size = nla_total_size(sizeof(s32));
-+
-+      ret = tsn_prepare_reply(info, TSN_CMD_REPLY, &rep_skb,
-+                              size + NLMSG_ALIGN(MAX_USER_SIZE));
-+      if (ret < 0)
-+              return ret;
-+
-+      /* netlink lib func */
-+      ret = nla_put_s32(rep_skb, TSN_CMD_ATTR_DATA, data);
-+      if (ret < 0)
-+              goto err;
-+
-+      return tsn_send_reply(rep_skb, info);
-+
-+err:
-+      nlmsg_free(rep_skb);
-+      return ret;
-+}
-+
-+static int tsn_echo_cmd(struct sk_buff *skb, struct genl_info *info)
-+{
-+      if (info->attrs[TSN_CMD_ATTR_MESG])
-+              return cmd_attr_echo_message(info);
-+      else if (info->attrs[TSN_CMD_ATTR_DATA])
-+              return cmd_attr_echo_data(info);
-+
-+      return -EINVAL;
-+}
-+
-+static int tsn_simple_reply(struct genl_info *info, u32 cmd,
-+                          char *portname, s32 retvalue)
-+{
-+      struct sk_buff *rep_skb;
-+      size_t size;
-+      int ret;
-+
-+      /* send back */
-+      size = nla_total_size(strlen(portname) + 1);
-+      size += nla_total_size(sizeof(s32));
-+
-+      ret = tsn_prepare_reply(info, cmd,
-+                              &rep_skb, size + NLMSG_ALIGN(MAX_USER_SIZE));
-+      if (ret < 0)
-+              return ret;
-+
-+      /* netlink lib func */
-+      ret = nla_put_string(rep_skb, TSN_ATTR_IFNAME, portname);
-+      if (ret < 0)
-+              return ret;
-+
-+      ret = nla_put_s32(rep_skb, TSN_CMD_ATTR_DATA, retvalue);
-+      if (ret < 0)
-+              return ret;
-+
-+      return tsn_send_reply(rep_skb, info);
-+}
-+
-+struct tsn_port *tsn_init_check(struct genl_info *info,
-+                              struct net_device **ndev)
-+{
-+      struct nlattr *na;
-+      char *portname;
-+      struct net_device *netdev;
-+      struct tsn_port *port;
-+      bool tsn_found = false;
-+
-+      if (!info->attrs[TSN_ATTR_IFNAME]) {
-+              tsn_simple_reply(info, TSN_CMD_REPLY,
-+                               "no portname", -EINVAL);
-+              return NULL;
-+      }
-+
-+      na = info->attrs[TSN_ATTR_IFNAME];
-+
-+      portname = (char *)nla_data(na);
-+
-+      netdev = __dev_get_by_name(genl_info_net(info), portname);
-+      if (!netdev) {
-+              tsn_simple_reply(info, TSN_CMD_REPLY,
-+                               "error device", -ENODEV);
-+              return NULL;
-+      }
-+
-+      list_for_each_entry(port, &port_list, list) {
-+              if (port->netdev == netdev) {
-+                      tsn_found = true;
-+                      break;
-+              }
-+      }
-+
-+      if (!tsn_found) {
-+              tsn_simple_reply(info, TSN_CMD_REPLY,
-+                               netdev->name, -ENODEV);
-+              return NULL;
-+      }
-+
-+      *ndev = netdev;
-+
-+      return port;
-+}
-+
-+static int tsn_cap_get(struct sk_buff *skb, struct genl_info *info)
-+{
-+      struct sk_buff *rep_skb;
-+      struct nlattr *tsn_cap_attr;
-+      int ret;
-+      u32 cap = 0;
-+      struct net_device *netdev;
-+      struct genlmsghdr *genlhdr;
-+      const struct tsn_ops *tsnops;
-+      struct tsn_port *port;
-+
-+      port = tsn_init_check(info, &netdev);
-+      if (!port) {
-+              ret = -ENODEV;
-+              goto out;
-+      }
-+
-+      tsnops = port->tsnops;
-+      genlhdr = info->genlhdr;
-+      if (!tsnops->get_capability) {
-+              ret = -EOPNOTSUPP;
-+              goto out;
-+      }
-+
-+      cap = tsnops->get_capability(netdev);
-+      if (cap < 0) {
-+              ret = cap;
-+              goto out;
-+      }
-+
-+      /* Pad netlink reply data */
-+      ret = tsn_prepare_reply(info, genlhdr->cmd,
-+                              &rep_skb, NLMSG_ALIGN(MAX_ATTR_SIZE));
-+      if (ret < 0)
-+              goto out;
-+
-+      if (nla_put_string(rep_skb, TSN_ATTR_IFNAME, netdev->name)) {
-+              ret = -EMSGSIZE;
-+              goto err;
-+      }
-+
-+      tsn_cap_attr = nla_nest_start_noflag(rep_skb, TSN_ATTR_CAP);
-+      if (!tsn_cap_attr) {
-+              ret = -EMSGSIZE;
-+              goto err;
-+      }
-+
-+      if (cap & TSN_CAP_QBV) {
-+              if (nla_put_flag(rep_skb, TSN_CAP_ATTR_QBV))
-+                      goto err;
-+      }
-+
-+      if (cap & TSN_CAP_QCI) {
-+              if (nla_put_flag(rep_skb, TSN_CAP_ATTR_QCI))
-+                      goto err;
-+      }
-+
-+      if (cap & TSN_CAP_QBU) {
-+              if (nla_put_flag(rep_skb, TSN_CAP_ATTR_QBU))
-+                      goto err;
-+      }
-+
-+      if (cap & TSN_CAP_CBS) {
-+              if (nla_put_flag(rep_skb, TSN_CAP_ATTR_CBS))
-+                      goto err;
-+      }
-+
-+      if (cap & TSN_CAP_CB) {
-+              if (nla_put_flag(rep_skb, TSN_CAP_ATTR_CB))
-+                      goto err;
-+      }
-+
-+      if (cap & TSN_CAP_TBS) {
-+              if (nla_put_flag(rep_skb, TSN_CAP_ATTR_TBS))
-+                      goto err;
-+      }
-+
-+      if (cap & TSN_CAP_CTH) {
-+              if (nla_put_flag(rep_skb, TSN_CAP_ATTR_CTH))
-+                      goto err;
-+      }
-+
-+      nla_nest_end(rep_skb, tsn_cap_attr);
-+
-+      tsn_send_reply(rep_skb, info);
-+      return 0;
-+err:
-+      nlmsg_free(rep_skb);
-+out:
-+      if (ret < 0)
-+              tsn_simple_reply(info, TSN_CMD_REPLY, netdev->name, ret);
-+      return ret;
-+}
-+
-+static int cmd_cb_streamid_set(struct genl_info *info)
-+{
-+      struct nlattr *na, *sid[TSN_STREAMID_ATTR_MAX + 1];
-+      u32 sid_index;
-+      u8 iden_type = 1;
-+      bool enable;
-+      int ret;
-+      struct net_device *netdev;
-+      struct tsn_cb_streamid sidconf;
-+      const struct tsn_ops *tsnops;
-+      struct tsn_port *port;
-+
-+      port = tsn_init_check(info, &netdev);
-+      if (!port)
-+              return -ENODEV;
-+
-+      tsnops = port->tsnops;
-+
-+      memset(&sidconf, 0, sizeof(struct tsn_cb_streamid));
-+
-+      if (!info->attrs[TSN_ATTR_STREAM_IDENTIFY])
-+              return -EINVAL;
-+
-+      na = info->attrs[TSN_ATTR_STREAM_IDENTIFY];
-+
-+      ret = NLA_PARSE_NESTED(sid, TSN_STREAMID_ATTR_MAX,
-+                             na, cb_streamid_policy);
-+      if (ret)
-+              return -EINVAL;
-+
-+      if (!sid[TSN_STREAMID_ATTR_INDEX])
-+              return -EINVAL;
-+
-+      sid_index = nla_get_u32(sid[TSN_STREAMID_ATTR_INDEX]);
-+
-+      if (sid[TSN_STREAMID_ATTR_ENABLE])
-+              enable = true;
-+      else if (sid[TSN_STREAMID_ATTR_DISABLE])
-+              enable = false;
-+      else
-+              return -EINVAL;
-+
-+      if (!enable)
-+              goto loaddev;
-+
-+      if (sid[TSN_STREAMID_ATTR_TYPE])
-+              iden_type = nla_get_u8(sid[TSN_STREAMID_ATTR_TYPE]);
-+      else
-+              return -EINVAL;
-+
-+      sidconf.type = iden_type;
-+      switch (iden_type) {
-+      case STREAMID_NULL:
-+              if (!sid[TSN_STREAMID_ATTR_NDMAC] ||
-+                  !sid[TSN_STREAMID_ATTR_NTAGGED] ||
-+                  !sid[TSN_STREAMID_ATTR_NVID]) {
-+                      return -EINVAL;
-+              }
-+
-+              sidconf.para.nid.dmac =
-+                      nla_get_u64(sid[TSN_STREAMID_ATTR_NDMAC]);
-+              sidconf.para.nid.tagged =
-+                      nla_get_u8(sid[TSN_STREAMID_ATTR_NTAGGED]);
-+              sidconf.para.nid.vid =
-+                      nla_get_u16(sid[TSN_STREAMID_ATTR_NVID]);
-+              break;
-+      case STREAMID_SMAC_VLAN:
-+              /* TODO: not supportted yet */
-+              if (!sid[TSN_STREAMID_ATTR_SMAC] ||
-+                  !sid[TSN_STREAMID_ATTR_STAGGED] ||
-+                  !sid[TSN_STREAMID_ATTR_SVID]) {
-+                      return -EINVAL;
-+              }
-+
-+              sidconf.para.sid.smac =
-+                      nla_get_u64(sid[TSN_STREAMID_ATTR_SMAC]);
-+              sidconf.para.sid.tagged =
-+                      nla_get_u8(sid[TSN_STREAMID_ATTR_STAGGED]);
-+              sidconf.para.sid.vid =
-+                      nla_get_u16(sid[TSN_STREAMID_ATTR_SVID]);
-+              break;
-+      case STREAMID_DMAC_VLAN:
-+
-+      case STREAMID_IP:
-+
-+      default:
-+              tsn_simple_reply(info, TSN_CMD_REPLY,
-+                               netdev->name, -EINVAL);
-+              return -EINVAL;
-+      }
-+
-+      if (sid[TSN_STREAMID_ATTR_STREAM_HANDLE])
-+              sidconf.handle =
-+                      nla_get_s32(sid[TSN_STREAMID_ATTR_STREAM_HANDLE]);
-+
-+      if (sid[TSN_STREAMID_ATTR_IFOP])
-+              sidconf.ifac_oport = nla_get_u32(sid[TSN_STREAMID_ATTR_IFOP]);
-+      if (sid[TSN_STREAMID_ATTR_OFOP])
-+              sidconf.ofac_oport = nla_get_u32(sid[TSN_STREAMID_ATTR_OFOP]);
-+      if (sid[TSN_STREAMID_ATTR_IFIP])
-+              sidconf.ifac_iport = nla_get_u32(sid[TSN_STREAMID_ATTR_IFIP]);
-+      if (sid[TSN_STREAMID_ATTR_OFIP])
-+              sidconf.ofac_iport = nla_get_u32(sid[TSN_STREAMID_ATTR_OFIP]);
-+
-+loaddev:
-+      if (!tsnops->cb_streamid_set) {
-+              tsn_simple_reply(info, TSN_CMD_REPLY,
-+                               netdev->name, -EPERM);
-+              return -EOPNOTSUPP;
-+      }
-+
-+      ret = tsnops->cb_streamid_set(netdev, sid_index, enable, &sidconf);
-+      if (ret < 0) {
-+              tsn_simple_reply(info, TSN_CMD_REPLY, netdev->name, ret);
-+              return ret;
-+      }
-+
-+      /* simple reply here. To be continue */
-+      if (tsn_simple_reply(info, TSN_CMD_REPLY, netdev->name, 0))
-+              return -1;
-+
-+      return 0;
-+}
-+
-+static int tsn_cb_streamid_set(struct sk_buff *skb, struct genl_info *info)
-+{
-+      if (info->attrs[TSN_ATTR_IFNAME]) {
-+              cmd_cb_streamid_set(info);
-+              return 0;
-+      }
-+
-+      return -1;
-+}
-+
-+static int cmd_cb_streamid_get(struct genl_info *info)
-+{
-+      struct nlattr *na, *sidattr, *sid[TSN_STREAMID_ATTR_MAX + 1];
-+      u32 sid_index;
-+      struct genlmsghdr *genlhdr;
-+      struct sk_buff *rep_skb;
-+      int ret, i;
-+      int valid;
-+      struct net_device *netdev;
-+      struct tsn_cb_streamid sidconf;
-+      struct tsn_cb_streamid_counters sidcounts;
-+      const struct tsn_ops *tsnops;
-+      struct tsn_port *port;
-+
-+      port = tsn_init_check(info, &netdev);
-+      if (!port)
-+              return -ENODEV;
-+
-+      tsnops = port->tsnops;
-+
-+      memset(&sidconf, 0, sizeof(struct tsn_cb_streamid));
-+      memset(&sidcounts, 0, sizeof(struct tsn_cb_streamid_counters));
-+
-+      if (!info->attrs[TSN_ATTR_STREAM_IDENTIFY])
-+              return -EINVAL;
-+
-+      na = info->attrs[TSN_ATTR_STREAM_IDENTIFY];
-+
-+      ret = NLA_PARSE_NESTED(sid, TSN_STREAMID_ATTR_MAX,
-+                             na, cb_streamid_policy);
-+      if (ret)
-+              return -EINVAL;
-+
-+      if (!sid[TSN_STREAMID_ATTR_INDEX])
-+              return -EINVAL;
-+
-+      sid_index = nla_get_u32(sid[TSN_STREAMID_ATTR_INDEX]);
-+
-+      if (!tsnops->cb_streamid_get) {
-+              tsn_simple_reply(info, TSN_CMD_REPLY,
-+                               netdev->name, -EPERM);
-+              ret = -EINVAL;
-+              goto exit;
-+      } else {
-+              valid = tsnops->cb_streamid_get(netdev, sid_index, &sidconf);
-+              if (valid < 0) {
-+                      tsn_simple_reply(info, TSN_CMD_REPLY,
-+                                       netdev->name, valid);
-+                      return valid;
-+              }
-+      }
-+
-+      /* send back */
-+      genlhdr = info->genlhdr;
-+      ret = tsn_prepare_reply(info, genlhdr->cmd, &rep_skb,
-+                              NLMSG_ALIGN(MAX_ATTR_SIZE));
-+      if (ret < 0)
-+              return ret;
-+
-+      /* input netlink the parameters */
-+      sidattr = nla_nest_start_noflag(rep_skb, TSN_ATTR_STREAM_IDENTIFY);
-+      if (!sidattr) {
-+              ret = -EINVAL;
-+              goto err;
-+      }
-+
-+      if (nla_put_u32(rep_skb, TSN_STREAMID_ATTR_INDEX, sid_index))
-+              return -EMSGSIZE;
-+
-+      if (valid == 1) {
-+              nla_put_flag(rep_skb, TSN_STREAMID_ATTR_ENABLE);
-+      } else if (valid == 0) {
-+              nla_put_flag(rep_skb, TSN_STREAMID_ATTR_DISABLE);
-+      } else {
-+              tsn_simple_reply(info, TSN_CMD_REPLY,
-+                               netdev->name, -EINVAL);
-+              goto err;
-+      }
-+
-+      if (nla_put_s32(rep_skb,
-+                      TSN_STREAMID_ATTR_STREAM_HANDLE, sidconf.handle) ||
-+          nla_put_u32(rep_skb, TSN_STREAMID_ATTR_IFOP, sidconf.ifac_oport) ||
-+          nla_put_u32(rep_skb, TSN_STREAMID_ATTR_OFOP, sidconf.ofac_oport) ||
-+          nla_put_u32(rep_skb, TSN_STREAMID_ATTR_IFIP, sidconf.ifac_iport) ||
-+          nla_put_u32(rep_skb, TSN_STREAMID_ATTR_OFIP, sidconf.ofac_iport) ||
-+          nla_put_u8(rep_skb, TSN_STREAMID_ATTR_TYPE, sidconf.type))
-+              return -EMSGSIZE;
-+
-+      switch (sidconf.type) {
-+      case STREAMID_NULL:
-+              if (NLA_PUT_U64(rep_skb, TSN_STREAMID_ATTR_NDMAC,
-+                              sidconf.para.nid.dmac) ||
-+                  nla_put_u16(rep_skb, TSN_STREAMID_ATTR_NVID,
-+                              sidconf.para.nid.vid) ||
-+                  nla_put_u8(rep_skb, TSN_STREAMID_ATTR_NTAGGED,
-+                             sidconf.para.nid.tagged))
-+                      return -EMSGSIZE;
-+              break;
-+      case STREAMID_SMAC_VLAN:
-+              if (NLA_PUT_U64(rep_skb, TSN_STREAMID_ATTR_SMAC,
-+                              sidconf.para.sid.smac) ||
-+                  nla_put_u16(rep_skb, TSN_STREAMID_ATTR_SVID,
-+                              sidconf.para.sid.vid) ||
-+                  nla_put_u8(rep_skb, TSN_STREAMID_ATTR_STAGGED,
-+                             sidconf.para.sid.tagged))
-+                      return -EMSGSIZE;
-+              break;
-+      case STREAMID_DMAC_VLAN:
-+      case STREAMID_IP:
-+      default:
-+              tsn_simple_reply(info, TSN_CMD_REPLY,
-+                               netdev->name, -EINVAL);
-+              goto err;
-+      }
-+
-+      if (!tsnops->cb_streamid_counters_get) {
-+              tsn_simple_reply(info, TSN_CMD_REPLY,
-+                               netdev->name, -EPERM);
-+              goto err;
-+      } else {
-+              ret = tsnops->cb_streamid_counters_get(netdev,
-+                                                      sid_index,
-+                                                      &sidcounts);
-+              if (ret < 0) {
-+                      tsn_simple_reply(info, TSN_CMD_REPLY,
-+                                       netdev->name, ret);
-+                      goto err;
-+              }
-+      }
-+
-+      if (NLA_PUT_U64(rep_skb, TSN_STREAMID_ATTR_COUNTERS_PSI,
-+                      sidcounts.per_stream.input) ||
-+          NLA_PUT_U64(rep_skb, TSN_STREAMID_ATTR_COUNTERS_PSO,
-+                      sidcounts.per_stream.output))
-+              return -EMSGSIZE;
-+
-+      for (i = 0; i < 32; i++) {
-+              if (NLA_PUT_U64(rep_skb, TSN_STREAMID_ATTR_COUNTERS_PSPPI,
-+                              sidcounts.per_streamport[i].input) ||
-+                  NLA_PUT_U64(rep_skb, TSN_STREAMID_ATTR_COUNTERS_PSPPO,
-+                              sidcounts.per_streamport[i].output))
-+                      return -EMSGSIZE;
-+      }
-+
-+      nla_nest_end(rep_skb, sidattr);
-+      /* end netlink input the parameters */
-+
-+      /* netlink lib func */
-+      ret = nla_put_string(rep_skb, TSN_ATTR_IFNAME, netdev->name);
-+      if (ret < 0)
-+              goto err;
-+
-+      ret = nla_put_s32(rep_skb, TSN_CMD_ATTR_DATA, 0);
-+      if (ret < 0)
-+              goto err;
-+
-+      return tsn_send_reply(rep_skb, info);
-+
-+err:
-+      nlmsg_free(rep_skb);
-+exit:
-+      return ret;
-+}
-+
-+static int tsn_cb_streamid_get(struct sk_buff *skb, struct genl_info *info)
-+{
-+      if (info->attrs[TSN_ATTR_IFNAME]) {
-+              cmd_cb_streamid_get(info);
-+              return 0;
-+      }
-+
-+      return -1;
-+}
-+
-+static int cmb_cb_streamid_counters_get(struct genl_info *info)
-+{
-+      return 0;
-+}
-+
-+static int tsn_cb_streamid_counters_get(struct sk_buff *skb,
-+                                      struct genl_info *info)
-+{
-+      if (info->attrs[TSN_ATTR_IFNAME]) {
-+              cmb_cb_streamid_counters_get(info);
-+              return 0;
-+      }
-+
-+      return -1;
-+}
-+
-+static int tsn_qci_cap_get(struct sk_buff *skb, struct genl_info *info)
-+{
-+      struct nlattr *qci_cap;
-+      struct sk_buff *rep_skb;
-+      int ret;
-+      struct net_device *netdev;
-+      struct genlmsghdr *genlhdr;
-+      struct tsn_qci_psfp_stream_param qci_cap_status;
-+      const struct tsn_ops *tsnops;
-+      struct tsn_port *port;
-+
-+      port = tsn_init_check(info, &netdev);
-+      if (!port) {
-+              ret = -EINVAL;
-+              goto out;
-+      }
-+
-+      tsnops = port->tsnops;
-+
-+      genlhdr = info->genlhdr;
-+
-+      memset(&qci_cap_status, 0, sizeof(qci_cap_status));
-+
-+      if (!tsnops->qci_get_maxcap) {
-+              ret = -EOPNOTSUPP;
-+              goto out;
-+      }
-+
-+      ret = tsnops->qci_get_maxcap(netdev, &qci_cap_status);
-+      if (ret < 0)
-+              goto out;
-+
-+      /* Pad netlink reply data */
-+      ret = tsn_prepare_reply(info, genlhdr->cmd,
-+                              &rep_skb, NLMSG_ALIGN(MAX_ATTR_SIZE));
-+      if (ret < 0)
-+              goto out;
-+
-+      if (nla_put_string(rep_skb, TSN_ATTR_IFNAME, netdev->name)) {
-+              ret = -EMSGSIZE;
-+              goto err;
-+      }
-+
-+      qci_cap = nla_nest_start_noflag(rep_skb, TSN_ATTR_QCI_SP);
-+      if (!qci_cap) {
-+              ret = -EMSGSIZE;
-+              goto err;
-+      }
-+
-+      if (nla_put_u32(rep_skb, TSN_QCI_STREAM_ATTR_MAX_SFI,
-+                      qci_cap_status.max_sf_instance) ||
-+              nla_put_u32(rep_skb, TSN_QCI_STREAM_ATTR_MAX_SGI,
-+                          qci_cap_status.max_sg_instance) ||
-+              nla_put_u32(rep_skb, TSN_QCI_STREAM_ATTR_MAX_FMI,
-+                          qci_cap_status.max_fm_instance) ||
-+              nla_put_u32(rep_skb, TSN_QCI_STREAM_ATTR_SLM,
-+                          qci_cap_status.supported_list_max)) {
-+              ret = -EMSGSIZE;
-+              goto err;
-+      }
-+
-+      nla_nest_end(rep_skb, qci_cap);
-+
-+      tsn_send_reply(rep_skb, info);
-+
-+      return 0;
-+err:
-+      nlmsg_free(rep_skb);
-+out:
-+      if (ret < 0)
-+              tsn_simple_reply(info, TSN_CMD_REPLY, netdev->name, ret);
-+
-+      return ret;
-+}
-+
-+static int cmd_qci_sfi_set(struct genl_info *info)
-+{
-+      struct nlattr *na, *sfi[TSN_QCI_SFI_ATTR_MAX + 1];
-+      u32 sfi_handle;
-+      bool enable;
-+      int ret;
-+      struct net_device *netdev;
-+      struct tsn_qci_psfp_sfi_conf sficonf;
-+      const struct tsn_ops *tsnops;
-+      struct tsn_port *port;
-+
-+      port = tsn_init_check(info, &netdev);
-+      if (!port)
-+              return -ENODEV;
-+
-+      tsnops = port->tsnops;
-+
-+      memset(&sficonf, 0, sizeof(struct tsn_qci_psfp_sfi_conf));
-+
-+      if (!info->attrs[TSN_ATTR_QCI_SFI])
-+              return -EINVAL;
-+
-+      na = info->attrs[TSN_ATTR_QCI_SFI];
-+
-+      ret = NLA_PARSE_NESTED(sfi, TSN_QCI_SFI_ATTR_MAX, na, qci_sfi_policy);
-+      if (ret) {
-+              pr_info("tsn: parse value TSN_QCI_SFI_ATTR_MAX  error.");
-+              return -EINVAL;
-+      }
-+
-+      if (!sfi[TSN_QCI_SFI_ATTR_INDEX])
-+              return -EINVAL;
-+
-+      sfi_handle = nla_get_u32(sfi[TSN_QCI_SFI_ATTR_INDEX]);
-+
-+      if (sfi[TSN_QCI_SFI_ATTR_ENABLE]) {
-+              enable = true;
-+      } else if (sfi[TSN_QCI_SFI_ATTR_DISABLE]) {
-+              enable = false;
-+              goto loaddrive;
-+      } else {
-+              pr_err("tsn: must provde ENABLE or DISABLE attribute.\n");
-+              tsn_simple_reply(info, TSN_CMD_REPLY,
-+                               netdev->name, -EINVAL);
-+              return -EINVAL;
-+      }
-+
-+      if (!sfi[TSN_QCI_SFI_ATTR_GATE_ID]) {
-+              pr_err("tsn: must provide stream gate index\n");
-+              tsn_simple_reply(info, TSN_CMD_REPLY,
-+                               netdev->name, -EINVAL);
-+              return -EINVAL;
-+      }
-+
-+      if (!sfi[TSN_QCI_SFI_ATTR_STREAM_HANDLE])
-+              sficonf.stream_handle_spec = -1;
-+      else
-+              sficonf.stream_handle_spec =
-+                      nla_get_s32(sfi[TSN_QCI_SFI_ATTR_STREAM_HANDLE]);
-+
-+      if (!sfi[TSN_QCI_SFI_ATTR_PRIO_SPEC])
-+              sficonf.priority_spec = -1;
-+      else
-+              sficonf.priority_spec =
-+                      nla_get_s8(sfi[TSN_QCI_SFI_ATTR_PRIO_SPEC]);
-+
-+      sficonf.stream_gate_instance_id =
-+                      nla_get_u32(sfi[TSN_QCI_SFI_ATTR_GATE_ID]);
-+
-+      if (sfi[TSN_QCI_SFI_ATTR_MAXSDU])
-+              sficonf.stream_filter.maximum_sdu_size =
-+                      nla_get_u16(sfi[TSN_QCI_SFI_ATTR_MAXSDU]);
-+      else
-+              sficonf.stream_filter.maximum_sdu_size = 0;
-+
-+      if (sfi[TSN_QCI_SFI_ATTR_FLOW_ID])
-+              sficonf.stream_filter.flow_meter_instance_id =
-+                      nla_get_s32(sfi[TSN_QCI_SFI_ATTR_FLOW_ID]);
-+      else
-+              sficonf.stream_filter.flow_meter_instance_id = -1;
-+
-+      if (sfi[TSN_QCI_SFI_ATTR_OVERSIZE_ENABLE])
-+              sficonf.block_oversize_enable = true;
-+
-+      if (sfi[TSN_QCI_SFI_ATTR_OVERSIZE])
-+              sficonf.block_oversize = true;
-+
-+loaddrive:
-+      if (!tsnops->qci_sfi_set) {
-+              tsn_simple_reply(info, TSN_CMD_REPLY,
-+                               netdev->name, -EPERM);
-+              return -EINVAL;
-+      }
-+
-+      ret = tsnops->qci_sfi_set(netdev, sfi_handle, enable, &sficonf);
-+      if (ret < 0) {
-+              tsn_simple_reply(info, TSN_CMD_REPLY, netdev->name, ret);
-+              return ret;
-+      }
-+
-+      ret = tsn_simple_reply(info, TSN_CMD_REPLY, netdev->name, 0);
-+
-+      if (ret)
-+              return ret;
-+      return 0;
-+}
-+
-+static int tsn_qci_sfi_set(struct sk_buff *skb, struct genl_info *info)
-+{
-+      if (info->attrs[TSN_ATTR_IFNAME]) {
-+              cmd_qci_sfi_set(info);
-+              return 0;
-+      }
-+
-+      return -1;
-+}
-+
-+static int cmd_qci_sfi_get(struct genl_info *info)
-+{
-+      struct nlattr *na, *sfiattr;
-+      struct nlattr *sfi[TSN_QCI_SFI_ATTR_MAX + 1];
-+      u32 sfi_handle;
-+      struct sk_buff *rep_skb;
-+      int ret, valid = 0;
-+      struct net_device *netdev;
-+      struct genlmsghdr *genlhdr;
-+      struct tsn_qci_psfp_sfi_conf sficonf;
-+      struct tsn_qci_psfp_sfi_counters sficount;
-+      const struct tsn_ops *tsnops;
-+      struct tsn_port *port;
-+
-+      port = tsn_init_check(info, &netdev);
-+      if (!port)
-+              return -ENODEV;
-+
-+      tsnops = port->tsnops;
-+
-+      genlhdr = info->genlhdr;
-+
-+      if (!info->attrs[TSN_ATTR_QCI_SFI])
-+              return -EINVAL;
-+
-+      na = info->attrs[TSN_ATTR_QCI_SFI];
-+
-+      ret = NLA_PARSE_NESTED(sfi, TSN_QCI_SFI_ATTR_MAX,
-+                             na, qci_sfi_policy);
-+      if (ret)
-+              return -EINVAL;
-+
-+      if (!sfi[TSN_QCI_SFI_ATTR_INDEX])
-+              return -EINVAL;
-+
-+      sfi_handle = nla_get_u32(sfi[TSN_QCI_SFI_ATTR_INDEX]);
-+
-+      memset(&sficonf, 0, sizeof(struct tsn_qci_psfp_sfi_conf));
-+      memset(&sficount, 0, sizeof(struct tsn_qci_psfp_sfi_counters));
-+
-+      if (!tsnops->qci_sfi_get || !tsnops->qci_sfi_counters_get) {
-+              tsn_simple_reply(info, TSN_CMD_REPLY,
-+                               netdev->name, -EPERM);
-+              ret = -EINVAL;
-+              goto exit;
-+      } else {
-+              valid = tsnops->qci_sfi_get(netdev, sfi_handle, &sficonf);
-+              if (valid < 0) {
-+                      tsn_simple_reply(info, TSN_CMD_REPLY,
-+                                       netdev->name, valid);
-+                      return valid;
-+              }
-+
-+              valid = tsnops->qci_sfi_counters_get(netdev, sfi_handle,
-+                                                   &sficount);
-+              if (valid < 0) {
-+                      tsn_simple_reply(info, TSN_CMD_REPLY,
-+                                       netdev->name, valid);
-+                      return valid;
-+              }
-+      }
-+
-+      ret = tsn_prepare_reply(info, genlhdr->cmd,
-+                              &rep_skb, NLMSG_ALIGN(MAX_ATTR_SIZE));
-+      if (ret < 0)
-+              return ret;
-+
-+      if (nla_put_string(rep_skb, TSN_ATTR_IFNAME, netdev->name))
-+              goto err;
-+
-+      sfiattr = nla_nest_start_noflag(rep_skb, TSN_ATTR_QCI_SFI);
-+      if (!sfiattr) {
-+              tsn_simple_reply(info, TSN_CMD_REPLY,
-+                               netdev->name, -EINVAL);
-+              ret = -EINVAL;
-+              goto err;
-+      }
-+
-+      if (nla_put_u32(rep_skb, TSN_QCI_SFI_ATTR_INDEX, sfi_handle))
-+              return -EMSGSIZE;
-+
-+      if (valid) {
-+              if (nla_put_flag(rep_skb, TSN_QCI_SFI_ATTR_ENABLE))
-+                      return -EMSGSIZE;
-+      } else {
-+              if (nla_put_flag(rep_skb, TSN_QCI_SFI_ATTR_DISABLE))
-+                      return -EMSGSIZE;
-+      }
-+
-+      if (nla_put_s32(rep_skb, TSN_QCI_SFI_ATTR_STREAM_HANDLE,
-+                      sficonf.stream_handle_spec) ||
-+          nla_put_s8(rep_skb, TSN_QCI_SFI_ATTR_PRIO_SPEC,
-+                     sficonf.priority_spec) ||
-+          nla_put_u32(rep_skb, TSN_QCI_SFI_ATTR_GATE_ID,
-+                      sficonf.stream_gate_instance_id))
-+              return -EMSGSIZE;
-+
-+      if (sficonf.stream_filter.maximum_sdu_size)
-+              if (nla_put_u16(rep_skb, TSN_QCI_SFI_ATTR_MAXSDU,
-+                              sficonf.stream_filter.maximum_sdu_size))
-+                      return -EMSGSIZE;
-+
-+      if (sficonf.stream_filter.flow_meter_instance_id >= 0)
-+              if (nla_put_s32(rep_skb, TSN_QCI_SFI_ATTR_FLOW_ID,
-+                              sficonf.stream_filter.flow_meter_instance_id))
-+                      return -EMSGSIZE;
-+
-+      if (sficonf.block_oversize_enable)
-+              if (nla_put_flag(rep_skb, TSN_QCI_SFI_ATTR_OVERSIZE_ENABLE))
-+                      return -EMSGSIZE;
-+      if (sficonf.block_oversize)
-+              if (nla_put_flag(rep_skb, TSN_QCI_SFI_ATTR_OVERSIZE))
-+                      return -EMSGSIZE;
-+
-+      if (nla_put(rep_skb, TSN_QCI_SFI_ATTR_COUNTERS,
-+                  sizeof(struct tsn_qci_psfp_sfi_counters), &sficount))
-+              return -EMSGSIZE;
-+
-+      nla_nest_end(rep_skb, sfiattr);
-+
-+      return tsn_send_reply(rep_skb, info);
-+err:
-+      nlmsg_free(rep_skb);
-+      tsn_simple_reply(info, TSN_CMD_REPLY,
-+                       netdev->name, -EINVAL);
-+exit:
-+      return ret;
-+}
-+
-+static int tsn_qci_sfi_get(struct sk_buff *skb, struct genl_info *info)
-+{
-+      if (info->attrs[TSN_ATTR_IFNAME]) {
-+              cmd_qci_sfi_get(info);
-+              return 0;
-+      }
-+
-+      return -1;
-+}
-+
-+static int cmd_qci_sfi_counters_get(struct genl_info *info)
-+{
-+      struct nlattr *na, *sfiattr;
-+      struct nlattr *sfi[TSN_QCI_SFI_ATTR_MAX + 1];
-+      u32 sfi_handle;
-+      struct sk_buff *rep_skb;
-+      int ret;
-+      struct net_device *netdev;
-+      struct genlmsghdr *genlhdr;
-+      struct tsn_qci_psfp_sfi_counters sficount;
-+      const struct tsn_ops *tsnops;
-+      struct tsn_port *port;
-+
-+      port = tsn_init_check(info, &netdev);
-+      if (!port)
-+              return -ENODEV;
-+
-+      tsnops = port->tsnops;
-+
-+      genlhdr = info->genlhdr;
-+
-+      if (!info->attrs[TSN_ATTR_QCI_SFI])
-+              return -EINVAL;
-+
-+      na = info->attrs[TSN_ATTR_QCI_SFI];
-+
-+      ret = NLA_PARSE_NESTED(sfi, TSN_QCI_SFI_ATTR_MAX,
-+                             na, qci_sfi_policy);
-+      if (ret)
-+              return -EINVAL;
-+
-+      if (!sfi[TSN_QCI_SFI_ATTR_INDEX])
-+              return -EINVAL;
-+
-+      sfi_handle = nla_get_u32(sfi[TSN_QCI_SFI_ATTR_INDEX]);
-+
-+      memset(&sficount, 0, sizeof(struct tsn_qci_psfp_sfi_counters));
-+      if (!tsnops->qci_sfi_counters_get) {
-+              tsn_simple_reply(info, TSN_CMD_REPLY,
-+                               netdev->name, -EPERM);
-+              return -1;
-+      }
-+
-+      ret = tsnops->qci_sfi_counters_get(netdev, sfi_handle, &sficount);
-+      if (ret < 0) {
-+              tsn_simple_reply(info, TSN_CMD_REPLY,
-+                               netdev->name, ret);
-+              return ret;
-+      }
-+
-+      ret = tsn_prepare_reply(info, genlhdr->cmd, &rep_skb,
-+                              NLMSG_ALIGN(MAX_ATTR_SIZE));
-+      if (ret < 0)
-+              return ret;
-+
-+      if (nla_put_string(rep_skb, TSN_ATTR_IFNAME, netdev->name))
-+              goto err;
-+
-+      sfiattr = nla_nest_start_noflag(rep_skb, TSN_ATTR_QCI_SFI);
-+      if (!sfiattr) {
-+              ret = -EINVAL;
-+              goto err;
-+      }
-+
-+      if (nla_put_u32(rep_skb, TSN_QCI_SFI_ATTR_INDEX, sfi_handle))
-+              return -EMSGSIZE;
-+
-+      ret = tsnops->qci_sfi_counters_get(netdev, sfi_handle, &sficount);
-+      if (ret < 0) {
-+              tsn_simple_reply(info, TSN_CMD_REPLY, netdev->name, ret);
-+              return ret;
-+      }
-+
-+      if (nla_put(rep_skb, TSN_QCI_SFI_ATTR_COUNTERS,
-+                  sizeof(struct tsn_qci_psfp_sfi_counters), &sficount))
-+              return -EMSGSIZE;
-+
-+      nla_nest_end(rep_skb, sfiattr);
-+
-+      return tsn_send_reply(rep_skb, info);
-+err:
-+      nlmsg_free(rep_skb);
-+      tsn_simple_reply(info, TSN_CMD_REPLY, netdev->name, -EINVAL);
-+      return ret;
-+}
-+
-+static int tsn_qci_sfi_counters_get(struct sk_buff *skb, struct genl_info *info)
-+{
-+      if (info->attrs[TSN_ATTR_IFNAME]) {
-+              cmd_qci_sfi_counters_get(info);
-+              return 0;
-+      }
-+
-+      return -1;
-+}
-+
-+static int cmd_qci_sgi_set(struct genl_info *info)
-+{
-+      struct nlattr *na;
-+      struct nlattr *sgia[TSN_QCI_SGI_ATTR_MAX + 1];
-+      struct nlattr *admin[TSN_SGI_ATTR_CTRL_MAX + 1];
-+      int ret = 0;
-+      struct net_device *netdev;
-+      const struct tsn_ops *tsnops;
-+      struct tsn_qci_psfp_sgi_conf sgi;
-+      struct tsn_qci_psfp_gcl *gcl = NULL;
-+      u16 sgi_handle = 0;
-+      u16 listcount = 0;
-+      struct tsn_port *port;
-+
-+      port = tsn_init_check(info, &netdev);
-+      if (!port)
-+              return -ENODEV;
-+
-+      tsnops = port->tsnops;
-+
-+      memset(&sgi, 0, sizeof(struct tsn_qci_psfp_sgi_conf));
-+
-+      if (!info->attrs[TSN_ATTR_QCI_SGI]) {
-+              tsn_simple_reply(info, TSN_CMD_REPLY,
-+                               netdev->name, -EINVAL);
-+              return -EINVAL;
-+      }
-+
-+      na = info->attrs[TSN_ATTR_QCI_SGI];
-+
-+      ret = NLA_PARSE_NESTED(sgia, TSN_QCI_SGI_ATTR_MAX,
-+                             na, qci_sgi_policy);
-+      if (ret) {
-+              tsn_simple_reply(info, TSN_CMD_REPLY,
-+                               netdev->name, -EINVAL);
-+              return -EINVAL;
-+      }
-+
-+      if (sgia[TSN_QCI_SGI_ATTR_ENABLE] && sgia[TSN_QCI_SGI_ATTR_DISABLE]) {
-+              pr_err("tsn: enable or disable?\n");
-+              tsn_simple_reply(info, TSN_CMD_REPLY,
-+                               netdev->name, -EINVAL);
-+              return -1;
-+      }
-+
-+      if (sgia[TSN_QCI_SGI_ATTR_INDEX])
-+              sgi_handle = nla_get_u32(sgia[TSN_QCI_SGI_ATTR_INDEX]);
-+
-+      if (sgia[TSN_QCI_SGI_ATTR_DISABLE]) {
-+              sgi.gate_enabled = 0;
-+              goto loaddev;
-+      } else {
-+              /* set default to be enable*/
-+              sgi.gate_enabled = 1;
-+      }
-+
-+      if (sgia[TSN_QCI_SGI_ATTR_CONFCHANGE])
-+              sgi.config_change = 1;
-+
-+      if (sgia[TSN_QCI_SGI_ATTR_IRXEN])
-+              sgi.block_invalid_rx_enable = 1;
-+
-+      if (sgia[TSN_QCI_SGI_ATTR_IRX])
-+              sgi.block_invalid_rx = 1;
-+
-+      if (sgia[TSN_QCI_SGI_ATTR_OEXEN])
-+              sgi.block_octets_exceeded_enable = 1;
-+
-+      if (sgia[TSN_QCI_SGI_ATTR_OEX])
-+              sgi.block_octets_exceeded = 1;
-+
-+      if (sgia[TSN_QCI_SGI_ATTR_ADMINENTRY]) {
-+              struct nlattr *entry;
-+              int rem;
-+              int count = 0;
-+
-+              na = sgia[TSN_QCI_SGI_ATTR_ADMINENTRY];
-+              ret = NLA_PARSE_NESTED(admin, TSN_SGI_ATTR_CTRL_MAX,
-+                                     na, qci_sgi_ctrl_policy);
-+
-+              /* Other parameters in admin control */
-+              if (admin[TSN_SGI_ATTR_CTRL_INITSTATE])
-+                      sgi.admin.gate_states = 1;
-+
-+              if (admin[TSN_SGI_ATTR_CTRL_CYTIME])
-+                      sgi.admin.cycle_time =
-+                              nla_get_u32(admin[TSN_SGI_ATTR_CTRL_CYTIME]);
-+
-+              if (admin[TSN_SGI_ATTR_CTRL_CYTIMEEX])
-+                      sgi.admin.cycle_time_extension =
-+                              nla_get_u32(admin[TSN_SGI_ATTR_CTRL_CYTIMEEX]);
-+
-+              if (admin[TSN_SGI_ATTR_CTRL_BTIME])
-+                      sgi.admin.base_time =
-+                              nla_get_u64(admin[TSN_SGI_ATTR_CTRL_BTIME]);
-+
-+              if (admin[TSN_SGI_ATTR_CTRL_INITIPV])
-+                      sgi.admin.init_ipv =
-+                              nla_get_s8(admin[TSN_SGI_ATTR_CTRL_INITIPV]);
-+              else
-+                      sgi.admin.init_ipv = -1;
-+
-+              if (admin[TSN_SGI_ATTR_CTRL_LEN]) {
-+                      sgi.admin.control_list_length =
-+                              nla_get_u8(admin[TSN_SGI_ATTR_CTRL_LEN]);
-+                      listcount = sgi.admin.control_list_length;
-+              }
-+
-+              if (!listcount)
-+                      goto loaddev;
-+
-+              gcl = kmalloc_array(listcount, sizeof(*gcl), GFP_KERNEL);
-+
-+              memset(gcl, 0, listcount * sizeof(struct tsn_qci_psfp_gcl));
-+
-+              /* Check the whole admin attrs,
-+               * checkout the TSN_SGI_ATTR_CTRL_GCLENTRY attributes
-+               */
-+              nla_for_each_nested(entry, na, rem) {
-+                      struct nlattr *gcl_entry[TSN_SGI_ATTR_GCL_MAX + 1];
-+                      struct nlattr *ti, *om;
-+
-+                      if (nla_type(entry) != TSN_SGI_ATTR_CTRL_GCLENTRY)
-+                              continue;
-+
-+                      /* parse each TSN_SGI_ATTR_CTRL_GCLENTRY */
-+                      ret = NLA_PARSE_NESTED(gcl_entry, TSN_SGI_ATTR_GCL_MAX,
-+                                             entry, qci_sgi_gcl_policy);
-+                      /* Parse gate control list */
-+                      if (gcl_entry[TSN_SGI_ATTR_GCL_GATESTATE])
-+                              (gcl + count)->gate_state = 1;
-+
-+                      if (gcl_entry[TSN_SGI_ATTR_GCL_IPV])
-+                              (gcl + count)->ipv =
-+                               nla_get_s8(gcl_entry[TSN_SGI_ATTR_GCL_IPV]);
-+
-+                      if (gcl_entry[TSN_SGI_ATTR_GCL_INTERVAL]) {
-+                              ti = gcl_entry[TSN_SGI_ATTR_GCL_INTERVAL];
-+                              (gcl + count)->time_interval = nla_get_u32(ti);
-+                      }
-+
-+                      if (gcl_entry[TSN_SGI_ATTR_GCL_OCTMAX]) {
-+                              om = gcl_entry[TSN_SGI_ATTR_GCL_OCTMAX];
-+                              (gcl + count)->octet_max = nla_get_u32(om);
-+                      }
-+
-+                      count++;
-+
-+                      if (count >= listcount)
-+                              break;
-+              }
-+
-+              if (count < listcount) {
-+                      tsn_simple_reply(info, TSN_CMD_REPLY,
-+                                       netdev->name, -EINVAL);
-+                      pr_err("tsn: count less than TSN_SGI_ATTR_CTRL_LEN\n");
-+                      kfree(gcl);
-+                      return -EINVAL;
-+              }
-+
-+      } else {
-+              pr_info("tsn: no admin list parameters setting\n");
-+      }
-+
-+loaddev:
-+      if (!tsnops->qci_sgi_set) {
-+              tsn_simple_reply(info, TSN_CMD_REPLY,
-+                               netdev->name, -EPERM);
-+              kfree(gcl);
-+              return -EINVAL;
-+      }
-+
-+      sgi.admin.gcl = gcl;
-+
-+      ret = tsnops->qci_sgi_set(netdev, sgi_handle, &sgi);
-+      kfree(gcl);
-+      if (!ret)
-+              return tsn_simple_reply(info, TSN_CMD_REPLY,
-+                                      netdev->name, 0);
-+
-+      tsn_simple_reply(info, TSN_CMD_REPLY,
-+                       netdev->name, ret);
-+      return ret;
-+}
-+
-+static int tsn_qci_sgi_set(struct sk_buff *skb, struct genl_info *info)
-+{
-+      if (info->attrs[TSN_ATTR_IFNAME]) {
-+              cmd_qci_sgi_set(info);
-+              return 0;
-+      }
-+
-+      return -1;
-+}
-+
-+static int cmd_qci_sgi_get(struct genl_info *info)
-+{
-+      struct nlattr *na, *sgiattr, *adminattr, *sglattr;
-+      struct nlattr *sgi[TSN_QCI_SGI_ATTR_MAX + 1];
-+      struct sk_buff *rep_skb;
-+      int ret;
-+      struct net_device *netdev;
-+      struct genlmsghdr *genlhdr;
-+      struct tsn_qci_psfp_sgi_conf sgiadmin;
-+      struct tsn_qci_psfp_gcl *gcl = NULL;
-+      const struct tsn_ops *tsnops;
-+      u16 sgi_handle;
-+      u8 listcount, i;
-+      struct tsn_port *port;
-+
-+      port = tsn_init_check(info, &netdev);
-+      if (!port)
-+              return -ENODEV;
-+
-+      tsnops = port->tsnops;
-+
-+      if (!info->attrs[TSN_ATTR_QCI_SGI]) {
-+              tsn_simple_reply(info, TSN_CMD_REPLY,
-+                               netdev->name, -EINVAL);
-+              pr_err("tsn: no sgi handle input\n");
-+              return -EINVAL;
-+      }
-+
-+      na = info->attrs[TSN_ATTR_QCI_SGI];
-+
-+      ret = NLA_PARSE_NESTED(sgi, TSN_QCI_SGI_ATTR_MAX,
-+                             na, qci_sgi_policy);
-+      if (ret)
-+              return -EINVAL;
-+
-+      if (!sgi[TSN_QCI_SGI_ATTR_INDEX]) {
-+              tsn_simple_reply(info, TSN_CMD_REPLY,
-+                               netdev->name, -EINVAL);
-+              pr_err("tsn: no sgi handle input\n");
-+              return -EINVAL;
-+      }
-+
-+      sgi_handle = nla_get_u32(sgi[TSN_QCI_SGI_ATTR_INDEX]);
-+
-+      /* Get config data from device */
-+      genlhdr = info->genlhdr;
-+
-+      memset(&sgiadmin, 0, sizeof(struct tsn_qci_psfp_sgi_conf));
-+
-+      if (!tsnops->qci_sgi_get) {
-+              tsn_simple_reply(info, TSN_CMD_REPLY,
-+                               netdev->name, -EPERM);
-+              return -1;
-+      }
-+
-+      ret = tsnops->qci_sgi_get(netdev, sgi_handle, &sgiadmin);
-+      if (ret < 0) {
-+              tsn_simple_reply(info, TSN_CMD_REPLY,
-+                               netdev->name, ret);
-+              return ret;
-+      }
-+
-+      /* Form netlink reply data */
-+      ret = tsn_prepare_reply(info, genlhdr->cmd,
-+                              &rep_skb, NLMSG_ALIGN(MAX_ATTR_SIZE));
-+      if (ret < 0)
-+              return ret;
-+
-+      if (nla_put_string(rep_skb, TSN_ATTR_IFNAME, netdev->name))
-+              return -EMSGSIZE;
-+
-+      sgiattr = nla_nest_start_noflag(rep_skb, TSN_ATTR_QCI_SGI);
-+      if (!sgiattr)
-+              return -EMSGSIZE;
-+
-+      if (nla_put_u32(rep_skb, TSN_QCI_SGI_ATTR_INDEX, sgi_handle))
-+              return -EMSGSIZE;
-+
-+      /* Gate enable? sgiadmin.gate_enabled */
-+      if (sgiadmin.gate_enabled) {
-+              if (nla_put_flag(rep_skb, TSN_QCI_SGI_ATTR_ENABLE))
-+                      return -EMSGSIZE;
-+      } else {
-+              if (nla_put_flag(rep_skb, TSN_QCI_SGI_ATTR_DISABLE))
-+                      return -EMSGSIZE;
-+      }
-+
-+      if (sgiadmin.config_change)
-+              if (nla_put_flag(rep_skb, TSN_QCI_SGI_ATTR_CONFCHANGE))
-+                      return -EMSGSIZE;
-+
-+      if (sgiadmin.block_invalid_rx_enable)
-+              if (nla_put_flag(rep_skb, TSN_QCI_SGI_ATTR_IRXEN))
-+                      return -EMSGSIZE;
-+
-+      if (sgiadmin.block_invalid_rx)
-+              if (nla_put_flag(rep_skb, TSN_QCI_SGI_ATTR_IRX))
-+                      return -EMSGSIZE;
-+
-+      if (sgiadmin.block_octets_exceeded_enable)
-+              if (nla_put_flag(rep_skb, TSN_QCI_SGI_ATTR_OEXEN))
-+                      return -EMSGSIZE;
-+
-+      if (sgiadmin.block_octets_exceeded)
-+              if (nla_put_flag(rep_skb, TSN_QCI_SGI_ATTR_OEX))
-+                      return -EMSGSIZE;
-+
-+      /* Administration */
-+      adminattr = nla_nest_start_noflag(rep_skb, TSN_QCI_SGI_ATTR_ADMINENTRY);
-+      if (!adminattr)
-+              return -EMSGSIZE;
-+
-+      if (sgiadmin.admin.gate_states)
-+              if (nla_put_flag(rep_skb, TSN_SGI_ATTR_CTRL_INITSTATE))
-+                      return -EMSGSIZE;
-+
-+      if (nla_put_u32(rep_skb, TSN_SGI_ATTR_CTRL_CYTIME,
-+                      sgiadmin.admin.cycle_time) ||
-+          nla_put_u32(rep_skb, TSN_SGI_ATTR_CTRL_CYTIMEEX,
-+                      sgiadmin.admin.cycle_time_extension) ||
-+          NLA_PUT_U64(rep_skb, TSN_SGI_ATTR_CTRL_BTIME,
-+                      sgiadmin.admin.base_time) ||
-+          nla_put_u8(rep_skb, TSN_SGI_ATTR_CTRL_INITIPV,
-+                     sgiadmin.admin.init_ipv))
-+              return -EMSGSIZE;
-+
-+      listcount = sgiadmin.admin.control_list_length;
-+      if (!listcount)
-+              goto out1;
-+
-+      if (!sgiadmin.admin.gcl) {
-+              pr_err("error: no gate control list\n");
-+              ret = -EINVAL;
-+              goto err;
-+      }
-+
-+      gcl = sgiadmin.admin.gcl;
-+
-+      /* loop list */
-+      for (i = 0; i < listcount; i++) {
-+              s8 ipv;
-+              u32 ti, omax;
-+
-+              if (!(gcl + i)) {
-+                      pr_err("error: list count too big\n");
-+                      ret = -EINVAL;
-+                      kfree(sgiadmin.admin.gcl);
-+                      goto err;
-+              }
-+
-+              /* Adminastration entry */
-+              sglattr = nla_nest_start_noflag(rep_skb,
-+                                              TSN_SGI_ATTR_CTRL_GCLENTRY);
-+              if (!sglattr)
-+                      return -EMSGSIZE;
-+              ipv = (gcl + i)->ipv;
-+              ti = (gcl + i)->time_interval;
-+              omax = (gcl + i)->octet_max;
-+
-+              if ((gcl + i)->gate_state)
-+                      if (nla_put_flag(rep_skb, TSN_SGI_ATTR_GCL_GATESTATE))
-+                              return -EMSGSIZE;
-+
-+              if (nla_put_s8(rep_skb, TSN_SGI_ATTR_GCL_IPV, ipv) ||
-+                  nla_put_u32(rep_skb, TSN_SGI_ATTR_GCL_INTERVAL, ti) ||
-+                  nla_put_u32(rep_skb, TSN_SGI_ATTR_GCL_OCTMAX, omax))
-+                      return -EMSGSIZE;
-+
-+              /* End administration entry */
-+              nla_nest_end(rep_skb, sglattr);
-+      }
-+
-+      kfree(sgiadmin.admin.gcl);
-+      if (nla_put_u8(rep_skb, TSN_SGI_ATTR_CTRL_LEN, listcount))
-+              return -EMSGSIZE;
-+
-+out1:
-+      /* End adminastration */
-+      nla_nest_end(rep_skb, adminattr);
-+
-+      nla_nest_end(rep_skb, sgiattr);
-+
-+      return tsn_send_reply(rep_skb, info);
-+err:
-+      nlmsg_free(rep_skb);
-+      tsn_simple_reply(info, TSN_CMD_REPLY, netdev->name, ret);
-+      return ret;
-+}
-+
-+static int tsn_qci_sgi_get(struct sk_buff *skb, struct genl_info *info)
-+{
-+      if (info->attrs[TSN_ATTR_IFNAME]) {
-+              cmd_qci_sgi_get(info);
-+              return 0;
-+      }
-+
-+      return -1;
-+}
-+
-+static int cmd_qci_sgi_status_get(struct genl_info *info)
-+{
-+      struct nlattr *na, *sgiattr, *operattr, *sglattr;
-+      struct nlattr *sgi[TSN_QCI_SGI_ATTR_MAX + 1];
-+      struct sk_buff *rep_skb;
-+      int ret;
-+      struct net_device *netdev;
-+      struct genlmsghdr *genlhdr;
-+      struct tsn_psfp_sgi_status sgistat;
-+      struct tsn_qci_psfp_gcl *gcl = NULL;
-+      const struct tsn_ops *tsnops;
-+      u16 sgi_handle;
-+      u8 listcount;
-+      int valid, i;
-+      struct tsn_port *port;
-+
-+      port = tsn_init_check(info, &netdev);
-+      if (!port)
-+              return -ENODEV;
-+
-+      tsnops = port->tsnops;
-+
-+      if (!info->attrs[TSN_ATTR_QCI_SGI]) {
-+              tsn_simple_reply(info, TSN_CMD_REPLY,
-+                               netdev->name, -EINVAL);
-+              pr_err("tsn: no sgi handle input\n");
-+              return -EINVAL;
-+      }
-+
-+      na = info->attrs[TSN_ATTR_QCI_SGI];
-+
-+      ret = NLA_PARSE_NESTED(sgi, TSN_QCI_SGI_ATTR_MAX,
-+                             na, qci_sgi_policy);
-+      if (ret)
-+              return -EINVAL;
-+
-+      if (!sgi[TSN_QCI_SGI_ATTR_INDEX]) {
-+              tsn_simple_reply(info, TSN_CMD_REPLY,
-+                               netdev->name, -EINVAL);
-+              pr_err("tsn: no sgi handle input\n");
-+              return -EINVAL;
-+      }
-+
-+      sgi_handle = nla_get_u32(sgi[TSN_QCI_SGI_ATTR_INDEX]);
-+
-+      /* Get status data from device */
-+      genlhdr = info->genlhdr;
-+
-+      memset(&sgistat, 0, sizeof(struct tsn_psfp_sgi_status));
-+
-+      if (!tsnops->qci_sgi_status_get) {
-+              tsn_simple_reply(info, TSN_CMD_REPLY,
-+                               netdev->name, -EPERM);
-+              return -1;
-+      }
-+
-+      valid = tsnops->qci_sgi_status_get(netdev, sgi_handle, &sgistat);
-+      if (valid < 0) {
-+              tsn_simple_reply(info, TSN_CMD_REPLY,
-+                               netdev->name, valid);
-+              return valid;
-+      }
-+
-+      /* Form netlink reply data */
-+      ret = tsn_prepare_reply(info, genlhdr->cmd,
-+                              &rep_skb, NLMSG_ALIGN(MAX_ATTR_SIZE));
-+      if (ret < 0)
-+              return ret;
-+
-+      if (nla_put_string(rep_skb, TSN_ATTR_IFNAME, netdev->name))
-+              return -EMSGSIZE;
-+
-+      /* Down one netlink attribute level */
-+      sgiattr = nla_nest_start_noflag(rep_skb, TSN_ATTR_QCI_SGI);
-+      if (!sgiattr)
-+              return -EMSGSIZE;
-+
-+      if (nla_put_u32(rep_skb, TSN_QCI_SGI_ATTR_INDEX, sgi_handle))
-+              return -EMSGSIZE;
-+
-+      /* Gate enable */
-+      if (valid == 1) {
-+              if (nla_put_flag(rep_skb, TSN_QCI_SGI_ATTR_ENABLE))
-+                      return -EMSGSIZE;
-+      } else {
-+              if (nla_put_flag(rep_skb, TSN_QCI_SGI_ATTR_DISABLE))
-+                      return -EMSGSIZE;
-+      }
-+
-+      if (nla_put_u32(rep_skb, TSN_QCI_SGI_ATTR_TICKG,
-+                      sgistat.tick_granularity) ||
-+          NLA_PUT_U64(rep_skb, TSN_QCI_SGI_ATTR_CCTIME,
-+                      sgistat.config_change_time) ||
-+          NLA_PUT_U64(rep_skb, TSN_QCI_SGI_ATTR_CUTIME,
-+                      sgistat.current_time) ||
-+          NLA_PUT_U64(rep_skb, TSN_QCI_SGI_ATTR_CCERROR,
-+                      sgistat.config_change_error))
-+              return -EMSGSIZE;
-+
-+      if (sgistat.config_pending)
-+              if (nla_put_flag(rep_skb, TSN_QCI_SGI_ATTR_CPENDING))
-+                      return -EMSGSIZE;
-+
-+      /* operation data */
-+      operattr = nla_nest_start_noflag(rep_skb, TSN_QCI_SGI_ATTR_OPERENTRY);
-+      if (!operattr)
-+              return -EMSGSIZE;
-+
-+      if (sgistat.oper.gate_states)
-+              if (nla_put_flag(rep_skb, TSN_SGI_ATTR_CTRL_INITSTATE))
-+                      return -EMSGSIZE;
-+
-+      if (nla_put_u32(rep_skb, TSN_SGI_ATTR_CTRL_CYTIME,
-+                      sgistat.oper.cycle_time) ||
-+          nla_put_u32(rep_skb, TSN_SGI_ATTR_CTRL_CYTIMEEX,
-+                      sgistat.oper.cycle_time_extension) ||
-+          NLA_PUT_U64(rep_skb, TSN_SGI_ATTR_CTRL_BTIME,
-+                      sgistat.oper.base_time) ||
-+          nla_put_u8(rep_skb, TSN_SGI_ATTR_CTRL_INITIPV,
-+                     sgistat.oper.init_ipv))
-+              return -EMSGSIZE;
-+
-+      /* Loop list */
-+      listcount = sgistat.oper.control_list_length;
-+      if (!listcount)
-+              goto out1;
-+
-+      if (!sgistat.oper.gcl) {
-+              pr_err("error: list lenghth is not zero!\n");
-+              ret = -EINVAL;
-+              goto err;
-+      }
-+
-+      gcl = sgistat.oper.gcl;
-+
-+      /* loop list */
-+      for (i = 0; i < listcount; i++) {
-+              s8 ipv;
-+              u32 ti, omax;
-+
-+              if (!(gcl + i)) {
-+                      pr_err("error: list count too big\n");
-+                      ret = -EINVAL;
-+                      kfree(sgistat.oper.gcl);
-+                      goto err;
-+              }
-+
-+              /* Operation entry */
-+              sglattr = nla_nest_start_noflag(rep_skb,
-+                                              TSN_SGI_ATTR_CTRL_GCLENTRY);
-+              if (!sglattr)
-+                      return -EMSGSIZE;
-+              ipv = (gcl + i)->ipv;
-+              ti = (gcl + i)->time_interval;
-+              omax = (gcl + i)->octet_max;
-+
-+              if ((gcl + i)->gate_state)
-+                      if (nla_put_flag(rep_skb, TSN_SGI_ATTR_GCL_GATESTATE))
-+                              return -EMSGSIZE;
-+
-+              if (nla_put_s8(rep_skb, TSN_SGI_ATTR_GCL_IPV, ipv) ||
-+                  nla_put_u32(rep_skb, TSN_SGI_ATTR_GCL_INTERVAL, ti) ||
-+                  nla_put_u32(rep_skb, TSN_SGI_ATTR_GCL_OCTMAX, omax))
-+                      return -EMSGSIZE;
-+
-+              /* End operation entry */
-+              nla_nest_end(rep_skb, sglattr);
-+      }
-+
-+      kfree(sgistat.oper.gcl);
-+      if (nla_put_u8(rep_skb, TSN_SGI_ATTR_CTRL_LEN, listcount))
-+              return -EMSGSIZE;
-+out1:
-+      /* End operation */
-+      nla_nest_end(rep_skb, operattr);
-+
-+      nla_nest_end(rep_skb, sgiattr);
-+
-+      return tsn_send_reply(rep_skb, info);
-+err:
-+      nlmsg_free(rep_skb);
-+      tsn_simple_reply(info, TSN_CMD_REPLY, netdev->name, ret);
-+      return ret;
-+}
-+
-+static int tsn_qci_sgi_status_get(struct sk_buff *skb, struct genl_info *info)
-+{
-+      if (info->attrs[TSN_ATTR_IFNAME]) {
-+              cmd_qci_sgi_status_get(info);
-+              return 0;
-+      }
-+
-+      return -1;
-+}
-+
-+static int cmd_qci_fmi_set(struct genl_info *info)
-+{
-+      struct nlattr *na, *fmi[TSN_QCI_FMI_ATTR_MAX + 1];
-+      u32 index;
-+      int ret;
-+      struct net_device *netdev;
-+      struct tsn_qci_psfp_fmi fmiconf;
-+      const struct tsn_ops *tsnops;
-+      bool enable = 0;
-+      struct tsn_port *port;
-+
-+      port = tsn_init_check(info, &netdev);
-+      if (!port)
-+              return -ENODEV;
-+
-+      tsnops = port->tsnops;
-+
-+      memset(&fmiconf, 0, sizeof(struct tsn_qci_psfp_fmi));
-+
-+      if (!info->attrs[TSN_ATTR_QCI_FMI])
-+              return -EINVAL;
-+
-+      na = info->attrs[TSN_ATTR_QCI_FMI];
-+
-+      ret = NLA_PARSE_NESTED(fmi, TSN_QCI_FMI_ATTR_MAX, na, qci_fmi_policy);
-+      if (ret) {
-+              pr_info("tsn: parse value TSN_QCI_FMI_ATTR_MAX  error.");
-+              return -EINVAL;
-+      }
-+
-+      if (!fmi[TSN_QCI_FMI_ATTR_INDEX])
-+              return -EINVAL;
-+
-+      index = nla_get_u32(fmi[TSN_QCI_FMI_ATTR_INDEX]);
-+
-+      if (fmi[TSN_QCI_FMI_ATTR_DISABLE])
-+              goto loaddev;
-+
-+      enable = 1;
-+
-+      if (fmi[TSN_QCI_FMI_ATTR_CIR])
-+              fmiconf.cir = nla_get_u32(fmi[TSN_QCI_FMI_ATTR_CIR]);
-+
-+      if (fmi[TSN_QCI_FMI_ATTR_CBS])
-+              fmiconf.cbs = nla_get_u32(fmi[TSN_QCI_FMI_ATTR_CBS]);
-+
-+      if (fmi[TSN_QCI_FMI_ATTR_EIR])
-+              fmiconf.eir = nla_get_u32(fmi[TSN_QCI_FMI_ATTR_EIR]);
-+
-+      if (fmi[TSN_QCI_FMI_ATTR_EBS])
-+              fmiconf.ebs = nla_get_u32(fmi[TSN_QCI_FMI_ATTR_EBS]);
-+
-+      if (fmi[TSN_QCI_FMI_ATTR_CF])
-+              fmiconf.cf = 1;
-+
-+      if (fmi[TSN_QCI_FMI_ATTR_CM])
-+              fmiconf.cm = 1;
-+
-+      if (fmi[TSN_QCI_FMI_ATTR_DROPYL])
-+              fmiconf.drop_on_yellow = 1;
-+
-+      if (fmi[TSN_QCI_FMI_ATTR_MAREDEN])
-+              fmiconf.mark_red_enable = 1;
-+
-+      if (fmi[TSN_QCI_FMI_ATTR_MARED])
-+              fmiconf.mark_red = 1;
-+
-+loaddev:
-+
-+      if (!tsnops->qci_fmi_set) {
-+              tsn_simple_reply(info, TSN_CMD_REPLY,
-+                               netdev->name, -EPERM);
-+              return -EINVAL;
-+      }
-+
-+      ret = tsnops->qci_fmi_set(netdev, index, enable, &fmiconf);
-+      if (ret < 0) {
-+              tsn_simple_reply(info, TSN_CMD_REPLY, netdev->name, ret);
-+              return ret;
-+      }
-+
-+      ret = tsn_simple_reply(info, TSN_CMD_REPLY, netdev->name, 0);
-+
-+      if (ret)
-+              return ret;
-+      return 0;
-+}
-+
-+static int tsn_qci_fmi_set(struct sk_buff *skb, struct genl_info *info)
-+{
-+      if (info->attrs[TSN_ATTR_IFNAME]) {
-+              cmd_qci_fmi_set(info);
-+              return 0;
-+      }
-+
-+      return -1;
-+}
-+
-+static int cmd_qci_fmi_get(struct genl_info *info)
-+{
-+      struct nlattr *na, *fmi[TSN_QCI_FMI_ATTR_MAX + 1], *fmiattr;
-+      u32 index;
-+      struct sk_buff *rep_skb;
-+      int ret;
-+      struct net_device *netdev;
-+      struct tsn_qci_psfp_fmi fmiconf;
-+      struct tsn_qci_psfp_fmi_counters counters;
-+      const struct tsn_ops *tsnops;
-+      struct genlmsghdr *genlhdr;
-+      struct tsn_port *port;
-+
-+      port = tsn_init_check(info, &netdev);
-+      if (!port)
-+              return -ENODEV;
-+
-+      tsnops = port->tsnops;
-+
-+      if (!info->attrs[TSN_ATTR_QCI_FMI])
-+              return -EINVAL;
-+
-+      na = info->attrs[TSN_ATTR_QCI_FMI];
-+
-+      ret = NLA_PARSE_NESTED(fmi, TSN_QCI_FMI_ATTR_MAX,
-+                             na, qci_fmi_policy);
-+      if (ret) {
-+              pr_info("tsn: parse value TSN_QCI_FMI_ATTR_MAX  error.");
-+              return -EINVAL;
-+      }
-+
-+      if (!fmi[TSN_QCI_FMI_ATTR_INDEX])
-+              return -EINVAL;
-+
-+      index = nla_get_u32(fmi[TSN_QCI_FMI_ATTR_INDEX]);
-+
-+      /* Get data from device */
-+      memset(&fmiconf, 0, sizeof(struct tsn_qci_psfp_fmi));
-+      memset(&counters, 0, sizeof(struct tsn_qci_psfp_fmi_counters));
-+
-+      if (!tsnops->qci_fmi_get) {
-+              tsn_simple_reply(info, TSN_CMD_REPLY,
-+                               netdev->name, -EPERM);
-+              return -EINVAL;
-+      }
-+
-+      ret = tsnops->qci_fmi_get(netdev, index, &fmiconf, &counters);
-+      if (ret < 0) {
-+              tsn_simple_reply(info, TSN_CMD_REPLY, netdev->name, ret);
-+              return ret;
-+      }
-+
-+      genlhdr = info->genlhdr;
-+
-+      /* Form netlink reply data */
-+      ret = tsn_prepare_reply(info, genlhdr->cmd,
-+                              &rep_skb, NLMSG_ALIGN(MAX_ATTR_SIZE));
-+      if (ret < 0)
-+              return ret;
-+
-+      if (nla_put_string(rep_skb, TSN_ATTR_IFNAME, netdev->name))
-+              return -EMSGSIZE;
-+
-+      fmiattr = nla_nest_start_noflag(rep_skb, TSN_ATTR_QCI_FMI);
-+      if (!fmiattr)
-+              return -EMSGSIZE;
-+
-+      if (nla_put_u32(rep_skb, TSN_QCI_FMI_ATTR_INDEX, index) ||
-+          nla_put_u32(rep_skb, TSN_QCI_FMI_ATTR_CIR, fmiconf.cir) ||
-+          nla_put_u32(rep_skb, TSN_QCI_FMI_ATTR_CBS, fmiconf.cbs) ||
-+          nla_put_u32(rep_skb, TSN_QCI_FMI_ATTR_EIR, fmiconf.eir) ||
-+          nla_put_u32(rep_skb, TSN_QCI_FMI_ATTR_EBS, fmiconf.ebs))
-+              return -EMSGSIZE;
-+
-+      if (fmiconf.cf)
-+              if (nla_put_flag(rep_skb, TSN_QCI_FMI_ATTR_CF))
-+                      return -EMSGSIZE;
-+
-+      if (fmiconf.cm)
-+              if (nla_put_flag(rep_skb, TSN_QCI_FMI_ATTR_CM))
-+                      return -EMSGSIZE;
-+
-+      if (fmiconf.drop_on_yellow)
-+              if (nla_put_flag(rep_skb, TSN_QCI_FMI_ATTR_DROPYL))
-+                      return -EMSGSIZE;
-+
-+      if (fmiconf.mark_red_enable)
-+              if (nla_put_flag(rep_skb, TSN_QCI_FMI_ATTR_MAREDEN))
-+                      return -EMSGSIZE;
-+
-+      if (fmiconf.mark_red)
-+              if (nla_put_flag(rep_skb, TSN_QCI_FMI_ATTR_MAREDEN))
-+                      return -EMSGSIZE;
-+
-+      if (nla_put(rep_skb, TSN_QCI_FMI_ATTR_COUNTERS,
-+                  sizeof(struct tsn_qci_psfp_fmi_counters), &counters))
-+              return -EMSGSIZE;
-+
-+      nla_nest_end(rep_skb, fmiattr);
-+
-+      tsn_send_reply(rep_skb, info);
-+
-+      return 0;
-+}
-+
-+static int tsn_qci_fmi_get(struct sk_buff *skb, struct genl_info *info)
-+{
-+      if (info->attrs[TSN_ATTR_IFNAME]) {
-+              cmd_qci_fmi_get(info);
-+              return 0;
-+      }
-+
-+      return -1;
-+}
-+
-+static int cmd_qbv_set(struct genl_info *info)
-+{
-+      struct nlattr *na, *na1;
-+      struct nlattr *qbv_table;
-+      struct nlattr *qbv[TSN_QBV_ATTR_MAX + 1];
-+      struct nlattr *qbvctrl[TSN_QBV_ATTR_CTRL_MAX + 1];
-+      int rem;
-+      int ret = 0;
-+      struct net_device *netdev;
-+      struct tsn_qbv_conf qbvconfig;
-+      const struct tsn_ops *tsnops;
-+      struct tsn_qbv_entry *gatelist = NULL;
-+      int count = 0;
-+      struct tsn_port *port;
-+
-+      port = tsn_init_check(info, &netdev);
-+      if (!port)
-+              return -ENODEV;
-+
-+      tsnops = port->tsnops;
-+
-+      memset(&qbvconfig, 0, sizeof(struct tsn_qbv_conf));
-+
-+      if (!info->attrs[TSN_ATTR_QBV])
-+              return -EINVAL;
-+
-+      na = info->attrs[TSN_ATTR_QBV];
-+
-+      ret = NLA_PARSE_NESTED(qbv, TSN_QBV_ATTR_MAX, na, qbv_policy);
-+      if (ret)
-+              return -EINVAL;
-+
-+      if (qbv[TSN_QBV_ATTR_ENABLE])
-+              qbvconfig.gate_enabled = 1;
-+      else
-+              goto setdrive;
-+
-+      if (qbv[TSN_QBV_ATTR_CONFIGCHANGE])
-+              qbvconfig.config_change = 1;
-+
-+      if (!qbv[TSN_QBV_ATTR_ADMINENTRY]) {
-+              tsn_simple_reply(info, TSN_CMD_REPLY,
-+                               netdev->name, -EINVAL);
-+              return -1;
-+      }
-+
-+      na1 = qbv[TSN_QBV_ATTR_ADMINENTRY];
-+      NLA_PARSE_NESTED(qbvctrl, TSN_QBV_ATTR_CTRL_MAX,
-+                       na1, qbv_ctrl_policy);
-+
-+      if (qbvctrl[TSN_QBV_ATTR_CTRL_CYCLETIME]) {
-+              qbvconfig.admin.cycle_time =
-+                      nla_get_u32(qbvctrl[TSN_QBV_ATTR_CTRL_CYCLETIME]);
-+      }
-+
-+      if (qbvctrl[TSN_QBV_ATTR_CTRL_CYCLETIMEEXT]) {
-+              qbvconfig.admin.cycle_time_extension =
-+                      nla_get_u32(qbvctrl[TSN_QBV_ATTR_CTRL_CYCLETIMEEXT]);
-+      }
-+
-+      if (qbvctrl[TSN_QBV_ATTR_CTRL_BASETIME]) {
-+              qbvconfig.admin.base_time =
-+                      nla_get_u64(qbvctrl[TSN_QBV_ATTR_CTRL_BASETIME]);
-+      }
-+
-+      if (qbvctrl[TSN_QBV_ATTR_CTRL_GATESTATE]) {
-+              qbvconfig.admin.gate_states =
-+                      nla_get_u8(qbvctrl[TSN_QBV_ATTR_CTRL_GATESTATE]);
-+      }
-+
-+      if (qbvctrl[TSN_QBV_ATTR_CTRL_LISTCOUNT]) {
-+              int listcount;
-+
-+              listcount = nla_get_u32(qbvctrl[TSN_QBV_ATTR_CTRL_LISTCOUNT]);
-+
-+              qbvconfig.admin.control_list_length = listcount;
-+
-+              gatelist = kmalloc_array(listcount,
-+                                       sizeof(*gatelist),
-+                                       GFP_KERNEL);
-+
-+              nla_for_each_nested(qbv_table, na1, rem) {
-+                      struct nlattr *qbv_entry[TSN_QBV_ATTR_ENTRY_MAX + 1];
-+
-+                      if (nla_type(qbv_table) != TSN_QBV_ATTR_CTRL_LISTENTRY)
-+                              continue;
-+
-+                      ret = NLA_PARSE_NESTED(qbv_entry,
-+                                             TSN_QBV_ATTR_ENTRY_MAX,
-+                                             qbv_table, qbv_entry_policy);
-+                      if (ret)
-+                              return -EINVAL;
-+
-+                      (gatelist + count)->gate_state =
-+                              nla_get_u8(qbv_entry[TSN_QBV_ATTR_ENTRY_GC]);
-+                      (gatelist + count)->time_interval =
-+                              nla_get_u32(qbv_entry[TSN_QBV_ATTR_ENTRY_TM]);
-+                      count++;
-+                      if (count > listcount)
-+                              break;
-+              }
-+      }
-+
-+      if (gatelist)
-+              qbvconfig.admin.control_list = gatelist;
-+
-+setdrive:
-+      if (!tsnops->qbv_set) {
-+              tsn_simple_reply(info, TSN_CMD_REPLY,
-+                               netdev->name, -EPERM);
-+              goto err;
-+      }
-+
-+      ret = tsnops->qbv_set(netdev, &qbvconfig);
-+
-+      /* send back */
-+      if (ret < 0)
-+              tsn_simple_reply(info, TSN_CMD_REPLY,
-+                               netdev->name, ret);
-+      else
-+              tsn_simple_reply(info, TSN_CMD_REPLY,
-+                               netdev->name, 0);
-+
-+err:
-+      kfree(gatelist);
-+      return ret;
-+}
-+
-+static int tsn_qbv_set(struct sk_buff *skb, struct genl_info *info)
-+{
-+      if (info->attrs[TSN_ATTR_IFNAME]) {
-+              cmd_qbv_set(info);
-+              return 0;
-+      }
-+
-+      return -1;
-+}
-+
-+static int cmd_qbv_get(struct genl_info *info)
-+{
-+      struct nlattr *qbv, *qbvadminattr;
-+      struct sk_buff *rep_skb;
-+      int ret;
-+      int len = 0, i = 0;
-+      struct net_device *netdev;
-+      struct genlmsghdr *genlhdr;
-+      struct tsn_qbv_conf qbvconf;
-+      const struct tsn_ops *tsnops;
-+      struct tsn_port *port;
-+
-+      port = tsn_init_check(info, &netdev);
-+      if (!port)
-+              return -ENODEV;
-+
-+      tsnops = port->tsnops;
-+
-+      genlhdr = info->genlhdr;
-+
-+      memset(&qbvconf, 0, sizeof(struct tsn_qbv_conf));
-+
-+      if (!tsnops->qbv_get) {
-+              tsn_simple_reply(info, TSN_CMD_REPLY,
-+                               netdev->name, -EPERM);
-+              return -1;
-+      }
-+
-+      ret = tsnops->qbv_get(netdev, &qbvconf);
-+      if (ret < 0) {
-+              tsn_simple_reply(info, TSN_CMD_REPLY,
-+                               netdev->name, ret);
-+              return ret;
-+      }
-+
-+      ret = tsn_prepare_reply(info, genlhdr->cmd,
-+                              &rep_skb, NLMSG_ALIGN(MAX_ATTR_SIZE));
-+      if (ret < 0)
-+              return ret;
-+
-+      if (nla_put_string(rep_skb, TSN_ATTR_IFNAME, netdev->name))
-+              return -EMSGSIZE;
-+
-+      qbv = nla_nest_start_noflag(rep_skb, TSN_ATTR_QBV);
-+      if (!qbv)
-+              return -EMSGSIZE;
-+
-+      qbvadminattr = nla_nest_start_noflag(rep_skb, TSN_QBV_ATTR_ADMINENTRY);
-+      if (!qbvadminattr)
-+              return -EMSGSIZE;
-+
-+      if (qbvconf.admin.control_list) {
-+              len = qbvconf.admin.control_list_length;
-+              if (nla_put_u32(rep_skb, TSN_QBV_ATTR_CTRL_LISTCOUNT, len))
-+                      return -EMSGSIZE;
-+
-+              for (i = 0; i < len; i++) {
-+                      struct nlattr *qbv_table;
-+                      u8 gs;
-+                      u32 tp;
-+                      int glisttype = TSN_QBV_ATTR_CTRL_LISTENTRY;
-+
-+                      gs = (qbvconf.admin.control_list + i)->gate_state;
-+                      tp = (qbvconf.admin.control_list + i)->time_interval;
-+
-+                      qbv_table =
-+                              nla_nest_start_noflag(rep_skb, glisttype);
-+                      if (!qbv_table)
-+                              return -EMSGSIZE;
-+
-+                      if (nla_put_u32(rep_skb, TSN_QBV_ATTR_ENTRY_ID, i) ||
-+                          nla_put_u8(rep_skb, TSN_QBV_ATTR_ENTRY_GC, gs) ||
-+                          nla_put_u32(rep_skb, TSN_QBV_ATTR_ENTRY_TM, tp))
-+                              return -EMSGSIZE;
-+                      nla_nest_end(rep_skb, qbv_table);
-+              }
-+
-+              if (qbvconf.admin.gate_states)
-+                      if (nla_put_u8(rep_skb, TSN_QBV_ATTR_CTRL_GATESTATE,
-+                                     qbvconf.admin.gate_states))
-+                              return -EMSGSIZE;
-+
-+              if (qbvconf.admin.cycle_time)
-+                      if (nla_put_u32(rep_skb, TSN_QBV_ATTR_CTRL_CYCLETIME,
-+                                      qbvconf.admin.cycle_time))
-+                              return -EMSGSIZE;
-+
-+              if (qbvconf.admin.cycle_time_extension)
-+                      if (nla_put_u32(rep_skb, TSN_QBV_ATTR_CTRL_CYCLETIMEEXT,
-+                                      qbvconf.admin.cycle_time_extension))
-+                              return -EMSGSIZE;
-+
-+              if (qbvconf.admin.base_time)
-+                      if (NLA_PUT_U64(rep_skb, TSN_QBV_ATTR_CTRL_BASETIME,
-+                                      qbvconf.admin.base_time))
-+                              return -EMSGSIZE;
-+
-+              kfree(qbvconf.admin.control_list);
-+
-+      } else {
-+              pr_info("tsn: error get administrator data.");
-+      }
-+
-+      nla_nest_end(rep_skb, qbvadminattr);
-+
-+      if (qbvconf.gate_enabled) {
-+              if (nla_put_flag(rep_skb, TSN_QBV_ATTR_ENABLE))
-+                      return -EMSGSIZE;
-+      } else {
-+              if (nla_put_flag(rep_skb, TSN_QBV_ATTR_DISABLE))
-+                      return -EMSGSIZE;
-+      }
-+
-+      if (qbvconf.maxsdu)
-+              if (nla_put_u32(rep_skb, TSN_QBV_ATTR_MAXSDU, qbvconf.maxsdu))
-+                      return -EMSGSIZE;
-+
-+      if (qbvconf.config_change)
-+              if (nla_put_flag(rep_skb, TSN_QBV_ATTR_CONFIGCHANGE))
-+                      return -EMSGSIZE;
-+
-+      nla_nest_end(rep_skb, qbv);
-+
-+      tsn_send_reply(rep_skb, info);
-+
-+      return ret;
-+}
-+
-+static int cmd_qbv_status_get(struct genl_info *info)
-+{
-+      struct nlattr *qbv, *qbvoperattr;
-+      struct sk_buff *rep_skb;
-+      int ret;
-+      int len = 0, i = 0;
-+      struct net_device *netdev;
-+      struct genlmsghdr *genlhdr;
-+      struct tsn_qbv_status qbvstatus;
-+      const struct tsn_ops *tsnops;
-+      struct tsn_port *port;
-+
-+      port = tsn_init_check(info, &netdev);
-+      if (!port)
-+              return -ENODEV;
-+
-+      tsnops = port->tsnops;
-+
-+      genlhdr = info->genlhdr;
-+
-+      memset(&qbvstatus, 0, sizeof(struct tsn_qbv_status));
-+
-+      if (!tsnops->qbv_get_status) {
-+              tsn_simple_reply(info, TSN_CMD_REPLY,
-+                               netdev->name, -EPERM);
-+              return -1;
-+      }
-+
-+      ret = tsnops->qbv_get_status(netdev, &qbvstatus);
-+      if (ret < 0) {
-+              tsn_simple_reply(info, TSN_CMD_REPLY,
-+                               netdev->name, ret);
-+              return ret;
-+      }
-+
-+      ret = tsn_prepare_reply(info, genlhdr->cmd,
-+                              &rep_skb, NLMSG_ALIGN(MAX_ATTR_SIZE));
-+      if (ret < 0)
-+              return ret;
-+
-+      if (nla_put_string(rep_skb, TSN_ATTR_IFNAME, netdev->name))
-+              return -EMSGSIZE;
-+
-+      qbv = nla_nest_start_noflag(rep_skb, TSN_ATTR_QBV);
-+      if (!qbv)
-+              return -EMSGSIZE;
-+
-+      qbvoperattr = nla_nest_start_noflag(rep_skb, TSN_QBV_ATTR_OPERENTRY);
-+      if (!qbvoperattr)
-+              return -EMSGSIZE;
-+
-+      if (qbvstatus.oper.control_list) {
-+              len = qbvstatus.oper.control_list_length;
-+              if (nla_put_u32(rep_skb, TSN_QBV_ATTR_CTRL_LISTCOUNT, len)) {
-+                      nla_nest_cancel(rep_skb, qbvoperattr);
-+                      return -EMSGSIZE;
-+              }
-+
-+              for (i = 0; i < len; i++) {
-+                      struct nlattr *qbv_table;
-+                      u8 gs;
-+                      u32 tp;
-+                      int glisttype = TSN_QBV_ATTR_CTRL_LISTENTRY;
-+
-+                      gs = (qbvstatus.oper.control_list + i)->gate_state;
-+                      tp = (qbvstatus.oper.control_list + i)->time_interval;
-+
-+                      qbv_table = nla_nest_start_noflag(rep_skb, glisttype);
-+                      if (!qbv_table)
-+                              return -EMSGSIZE;
-+
-+                      if (nla_put_u32(rep_skb, TSN_QBV_ATTR_ENTRY_ID, i) ||
-+                          nla_put_u8(rep_skb, TSN_QBV_ATTR_ENTRY_GC, gs) ||
-+                          nla_put_u32(rep_skb, TSN_QBV_ATTR_ENTRY_TM, tp)) {
-+                              nla_nest_cancel(rep_skb, qbv_table);
-+                              return -EMSGSIZE;
-+                      }
-+
-+                      nla_nest_end(rep_skb, qbv_table);
-+              }
-+
-+              if (qbvstatus.oper.gate_states) {
-+                      if (nla_put_u8(rep_skb, TSN_QBV_ATTR_CTRL_GATESTATE,
-+                                     qbvstatus.oper.gate_states))
-+                              return -EMSGSIZE;
-+              }
-+
-+              if (qbvstatus.oper.cycle_time) {
-+                      if (nla_put_u32(rep_skb, TSN_QBV_ATTR_CTRL_CYCLETIME,
-+                                      qbvstatus.oper.cycle_time))
-+                              return -EMSGSIZE;
-+              }
-+
-+              if (qbvstatus.oper.cycle_time_extension) {
-+                      if (nla_put_u32(rep_skb, TSN_QBV_ATTR_CTRL_CYCLETIMEEXT,
-+                                      qbvstatus.oper.cycle_time_extension))
-+                              return -EMSGSIZE;
-+              }
-+
-+              if (qbvstatus.oper.base_time) {
-+                      if (NLA_PUT_U64(rep_skb, TSN_QBV_ATTR_CTRL_BASETIME,
-+                                      qbvstatus.oper.base_time))
-+                              return -EMSGSIZE;
-+              }
-+
-+              kfree(qbvstatus.oper.control_list);
-+      } else {
-+              pr_info("tsn: error get operation list data.");
-+      }
-+
-+      nla_nest_end(rep_skb, qbvoperattr);
-+
-+      if (qbvstatus.config_change_time) {
-+              if (NLA_PUT_U64(rep_skb, TSN_QBV_ATTR_CONFIGCHANGETIME,
-+                              qbvstatus.config_change_time))
-+                      return -EMSGSIZE;
-+      }
-+
-+      if (qbvstatus.tick_granularity) {
-+              if (nla_put_u32(rep_skb, TSN_QBV_ATTR_GRANULARITY,
-+                              qbvstatus.tick_granularity))
-+                      return -EMSGSIZE;
-+      }
-+
-+      if (qbvstatus.current_time) {
-+              if (NLA_PUT_U64(rep_skb, TSN_QBV_ATTR_CURRENTTIME,
-+                              qbvstatus.current_time))
-+                      return -EMSGSIZE;
-+      }
-+
-+      if (qbvstatus.config_pending) {
-+              if (nla_put_flag(rep_skb, TSN_QBV_ATTR_CONFIGPENDING))
-+                      return -EMSGSIZE;
-+      }
-+
-+      if (qbvstatus.config_change_error) {
-+              if (NLA_PUT_U64(rep_skb, TSN_QBV_ATTR_CONFIGCHANGEERROR,
-+                              qbvstatus.config_change_error))
-+                      return -EMSGSIZE;
-+      }
-+
-+      if (qbvstatus.supported_list_max) {
-+              if (nla_put_u32(rep_skb, TSN_QBV_ATTR_LISTMAX,
-+                              qbvstatus.supported_list_max))
-+                      return -EMSGSIZE;
-+      }
-+
-+      nla_nest_end(rep_skb, qbv);
-+
-+      tsn_send_reply(rep_skb, info);
-+
-+      return ret;
-+}
-+
-+static int tsn_qbv_status_get(struct sk_buff *skb, struct genl_info *info)
-+{
-+      if (info->attrs[TSN_ATTR_IFNAME])
-+              cmd_qbv_status_get(info);
-+
-+      return 0;
-+}
-+
-+static int tsn_qbv_get(struct sk_buff *skb, struct genl_info *info)
-+{
-+      if (info->attrs[TSN_ATTR_IFNAME])
-+              cmd_qbv_get(info);
-+
-+      return 0;
-+}
-+
-+static int tsn_cbs_set(struct sk_buff *skb, struct genl_info *info)
-+{
-+      struct nlattr *na;
-+      struct nlattr *cbsa[TSN_CBS_ATTR_MAX + 1];
-+      struct net_device *netdev;
-+      const struct tsn_ops *tsnops;
-+      int ret;
-+      u8 tc, bw;
-+      struct tsn_port *port;
-+
-+      port = tsn_init_check(info, &netdev);
-+      if (!port)
-+              return -ENODEV;
-+
-+      tsnops = port->tsnops;
-+
-+      if (!info->attrs[TSN_ATTR_CBS]) {
-+              tsn_simple_reply(info, TSN_CMD_REPLY,
-+                               netdev->name, -EINVAL);
-+              return -EINVAL;
-+      }
-+
-+      na = info->attrs[TSN_ATTR_CBS];
-+
-+      if (!tsnops->cbs_set) {
-+              tsn_simple_reply(info, TSN_CMD_REPLY,
-+                               netdev->name, -EPERM);
-+              return -1;
-+      }
-+
-+      ret = NLA_PARSE_NESTED(cbsa, TSN_CBS_ATTR_MAX, na, cbs_policy);
-+      if (ret) {
-+              tsn_simple_reply(info, TSN_CMD_REPLY,
-+                               netdev->name, -EINVAL);
-+              return -EINVAL;
-+      }
-+
-+      if (!cbsa[TSN_CBS_ATTR_TC_INDEX]) {
-+              pr_err("tsn: no TSN_CBS_ATTR_TC_INDEX input\n");
-+              tsn_simple_reply(info, TSN_CMD_REPLY,
-+                               netdev->name, -EINVAL);
-+              return -EINVAL;
-+      }
-+      tc = nla_get_u8(cbsa[TSN_CBS_ATTR_TC_INDEX]);
-+
-+      if (!cbsa[TSN_CBS_ATTR_BW]) {
-+              pr_err("tsn: no TSN_CBS_ATTR_BW input\n");
-+              tsn_simple_reply(info, TSN_CMD_REPLY,
-+                               netdev->name, -EINVAL);
-+              return -EINVAL;
-+      }
-+
-+      bw = nla_get_u8(cbsa[TSN_CBS_ATTR_BW]);
-+      if (bw > 100) {
-+              pr_err("tsn: TSN_CBS_ATTR_BW isn't in the range of 0~100\n");
-+              tsn_simple_reply(info, TSN_CMD_REPLY,
-+                               netdev->name, -EINVAL);
-+              return -EINVAL;
-+      }
-+
-+      ret = tsnops->cbs_set(netdev, tc, bw);
-+      if (ret < 0) {
-+              tsn_simple_reply(info, TSN_CMD_REPLY,
-+                               netdev->name, ret);
-+              return ret;
-+      }
-+
-+      tsn_simple_reply(info, TSN_CMD_REPLY,
-+                       netdev->name, 0);
-+      return 0;
-+}
-+
-+static int tsn_cbs_get(struct sk_buff *skb, struct genl_info *info)
-+{
-+      struct nlattr *na, *cbsattr;
-+      struct nlattr *cbsa[TSN_CBS_ATTR_MAX + 1];
-+      struct net_device *netdev;
-+      const struct tsn_ops *tsnops;
-+      struct sk_buff *rep_skb;
-+      int ret;
-+      struct genlmsghdr *genlhdr;
-+      u8 tc;
-+      struct tsn_port *port;
-+
-+      port = tsn_init_check(info, &netdev);
-+      if (!port)
-+              return -ENODEV;
-+
-+      tsnops = port->tsnops;
-+
-+      if (!info->attrs[TSN_ATTR_CBS]) {
-+              tsn_simple_reply(info, TSN_CMD_REPLY,
-+                               netdev->name, -EINVAL);
-+              return -EINVAL;
-+      }
-+
-+      if (!tsnops->cbs_get) {
-+              tsn_simple_reply(info, TSN_CMD_REPLY,
-+                               netdev->name, -EPERM);
-+              return -1;
-+      }
-+
-+      na = info->attrs[TSN_ATTR_CBS];
-+      ret = NLA_PARSE_NESTED(cbsa, TSN_CBS_ATTR_MAX, na, cbs_policy);
-+      if (ret) {
-+              pr_err("tsn: parse value TSN_CBS_ATTR_MAX error.");
-+              tsn_simple_reply(info, TSN_CMD_REPLY,
-+                               netdev->name, -EINVAL);
-+              return -EINVAL;
-+      }
-+
-+      /* Get status data from device */
-+      genlhdr = info->genlhdr;
-+
-+      /* Form netlink reply data */
-+      ret = tsn_prepare_reply(info, genlhdr->cmd, &rep_skb,
-+                              NLMSG_ALIGN(MAX_ATTR_SIZE));
-+      if (ret < 0)
-+              return ret;
-+
-+      if (nla_put_string(rep_skb, TSN_ATTR_IFNAME, netdev->name))
-+              return -EMSGSIZE;
-+
-+      cbsattr = nla_nest_start_noflag(rep_skb, TSN_ATTR_CBS);
-+      if (!cbsattr)
-+              return -EMSGSIZE;
-+
-+      if (!cbsa[TSN_CBS_ATTR_TC_INDEX]) {
-+              pr_err("tsn: must to specify the TSN_CBS_ATTR_TC_INDEX\n");
-+              tsn_simple_reply(info, TSN_CMD_REPLY,
-+                               netdev->name, -EINVAL);
-+              return -EINVAL;
-+      }
-+      tc = nla_get_u8(cbsa[TSN_CBS_ATTR_TC_INDEX]);
-+
-+      ret = tsnops->cbs_get(netdev, tc);
-+      if (ret < 0) {
-+              pr_err("tsn: cbs_get return error\n");
-+              tsn_simple_reply(info, TSN_CMD_REPLY,
-+                               netdev->name, ret);
-+              return ret;
-+      }
-+
-+      if (nla_put_u8(rep_skb, TSN_CBS_ATTR_BW, ret & 0XF))
-+              return -EMSGSIZE;
-+
-+      nla_nest_end(rep_skb, cbsattr);
-+      return tsn_send_reply(rep_skb, info);
-+}
-+
-+static int cmd_qbu_set(struct genl_info *info)
-+{
-+      struct nlattr *na;
-+      struct nlattr *qbua[TSN_QBU_ATTR_MAX + 1];
-+      struct net_device *netdev;
-+      const struct tsn_ops *tsnops;
-+      int ret;
-+      u8 preemptible = 0;
-+      struct tsn_port *port;
-+
-+      port = tsn_init_check(info, &netdev);
-+      if (!port)
-+              return -ENODEV;
-+
-+      tsnops = port->tsnops;
-+
-+      if (!info->attrs[TSN_ATTR_QBU]) {
-+              tsn_simple_reply(info, TSN_CMD_REPLY,
-+                               netdev->name, -EINVAL);
-+              return -EINVAL;
-+      }
-+
-+      na = info->attrs[TSN_ATTR_QBU];
-+
-+      ret = NLA_PARSE_NESTED(qbua, TSN_QBU_ATTR_MAX, na, qbu_policy);
-+      if (ret) {
-+              tsn_simple_reply(info, TSN_CMD_REPLY,
-+                               netdev->name, -EINVAL);
-+              return -EINVAL;
-+      }
-+
-+      if (qbua[TSN_QBU_ATTR_ADMIN_STATE])
-+              preemptible = nla_get_u8(qbua[TSN_QBU_ATTR_ADMIN_STATE]);
-+      else
-+              pr_info("No preemptible TSN_QBU_ATTR_ADMIN_STATE config!\n");
-+
-+      if (!tsnops->qbu_set) {
-+              tsn_simple_reply(info, TSN_CMD_REPLY,
-+                               netdev->name, -EPERM);
-+              return -EINVAL;
-+      }
-+
-+      ret = tsnops->qbu_set(netdev, preemptible);
-+      if (ret < 0) {
-+              tsn_simple_reply(info, TSN_CMD_REPLY,
-+                               netdev->name, ret);
-+              return ret;
-+      }
-+
-+      tsn_simple_reply(info, TSN_CMD_REPLY,
-+                       netdev->name, 0);
-+      return 0;
-+}
-+
-+static int tsn_qbu_set(struct sk_buff *skb, struct genl_info *info)
-+{
-+      if (info->attrs[TSN_ATTR_IFNAME])
-+              return cmd_qbu_set(info);
-+
-+      return -1;
-+}
-+
-+static int cmd_qbu_get_status(struct genl_info *info)
-+{
-+      struct nlattr *qbuattr;
-+      struct net_device *netdev;
-+      const struct tsn_ops *tsnops;
-+      struct sk_buff *rep_skb;
-+      int ret;
-+      struct genlmsghdr *genlhdr;
-+      struct tsn_preempt_status pps;
-+      struct tsn_port *port;
-+
-+      port = tsn_init_check(info, &netdev);
-+      if (!port)
-+              return -ENODEV;
-+
-+      tsnops = port->tsnops;
-+
-+      /* Get status data from device */
-+      genlhdr = info->genlhdr;
-+
-+      memset(&pps, 0, sizeof(struct tsn_preempt_status));
-+
-+      if (!tsnops->qbu_get) {
-+              tsn_simple_reply(info, TSN_CMD_REPLY,
-+                               netdev->name, -EPERM);
-+              return -1;
-+      }
-+
-+      ret = tsnops->qbu_get(netdev, &pps);
-+      if (ret < 0) {
-+              tsn_simple_reply(info, TSN_CMD_REPLY,
-+                               netdev->name, ret);
-+              return ret;
-+      }
-+
-+      /* Form netlink reply data */
-+      ret = tsn_prepare_reply(info, genlhdr->cmd,
-+                              &rep_skb, NLMSG_ALIGN(MAX_ATTR_SIZE));
-+      if (ret < 0)
-+              return ret;
-+
-+      if (nla_put_string(rep_skb, TSN_ATTR_IFNAME, netdev->name))
-+              return -EMSGSIZE;
-+
-+      qbuattr = nla_nest_start_noflag(rep_skb, TSN_ATTR_QBU);
-+      if (!qbuattr)
-+              return -EMSGSIZE;
-+
-+      if (nla_put_u8(rep_skb, TSN_QBU_ATTR_ADMIN_STATE, pps.admin_state) ||
-+          nla_put_u32(rep_skb,
-+                      TSN_QBU_ATTR_HOLD_ADVANCE, pps.hold_advance) ||
-+          nla_put_u32(rep_skb,
-+                      TSN_QBU_ATTR_RELEASE_ADVANCE, pps.release_advance))
-+              return -EMSGSIZE;
-+
-+      if (pps.preemption_active) {
-+              if (nla_put_flag(rep_skb, TSN_QBU_ATTR_ACTIVE))
-+                      return -EMSGSIZE;
-+      }
-+
-+      if (nla_put_u8(rep_skb, TSN_QBU_ATTR_HOLD_REQUEST, pps.hold_request))
-+              return -EMSGSIZE;
-+
-+      nla_nest_end(rep_skb, qbuattr);
-+
-+      return tsn_send_reply(rep_skb, info);
-+}
-+
-+static int tsn_qbu_get_status(struct sk_buff *skb, struct genl_info *info)
-+{
-+      if (info->attrs[TSN_ATTR_IFNAME])
-+              return cmd_qbu_get_status(info);
-+
-+      return -1;
-+}
-+
-+static int tsn_tsd_set(struct sk_buff *skb, struct genl_info *info)
-+{
-+      struct nlattr *na;
-+      struct nlattr *ntsd[TSN_TSD_ATTR_MAX + 1];
-+      struct net_device *netdev;
-+      const struct tsn_ops *tsnops;
-+      struct tsn_tsd tsd;
-+      int ret;
-+      struct tsn_port *port;
-+
-+      port = tsn_init_check(info, &netdev);
-+      if (!port)
-+              return -ENODEV;
-+
-+      tsnops = port->tsnops;
-+
-+      memset(&tsd, 0, sizeof(struct tsn_tsd));
-+
-+      if (!info->attrs[TSN_ATTR_TSD]) {
-+              tsn_simple_reply(info, TSN_CMD_REPLY,
-+                               netdev->name, -EINVAL);
-+              return -EINVAL;
-+      }
-+
-+      na = info->attrs[TSN_ATTR_TSD];
-+
-+      ret = NLA_PARSE_NESTED(ntsd, TSN_TSD_ATTR_MAX, na, tsd_policy);
-+      if (ret) {
-+              tsn_simple_reply(info, TSN_CMD_REPLY,
-+                               netdev->name, -EINVAL);
-+              return -EINVAL;
-+      }
-+
-+      if (!tsnops->tsd_set) {
-+              tsn_simple_reply(info, TSN_CMD_REPLY,
-+                               netdev->name, -EPERM);
-+              return -EINVAL;
-+      }
-+
-+      if (nla_get_flag(ntsd[TSN_TSD_ATTR_DISABLE])) {
-+              tsd.enable = false;
-+      } else {
-+              if (ntsd[TSN_TSD_ATTR_PERIOD])
-+                      tsd.period = nla_get_u32(ntsd[TSN_TSD_ATTR_PERIOD]);
-+
-+              if (!tsd.period) {
-+                      tsn_simple_reply(info, TSN_CMD_REPLY,
-+                                       netdev->name, -EINVAL);
-+                      return -EINVAL;
-+              }
-+
-+              if (ntsd[TSN_TSD_ATTR_MAX_FRM_NUM])
-+                      tsd.maxFrameNum =
-+                              nla_get_u32(ntsd[TSN_TSD_ATTR_MAX_FRM_NUM]);
-+
-+              if (ntsd[TSN_TSD_ATTR_SYN_IMME])
-+                      tsd.syn_flag = 2;
-+              else
-+                      tsd.syn_flag = 1;
-+
-+              tsd.enable = true;
-+      }
-+
-+      ret = tsnops->tsd_set(netdev, &tsd);
-+      if (ret < 0) {
-+              tsn_simple_reply(info, TSN_CMD_REPLY,
-+                               netdev->name, ret);
-+              return ret;
-+      }
-+
-+      tsn_simple_reply(info, TSN_CMD_REPLY,
-+                       netdev->name, 0);
-+      return 0;
-+}
-+
-+static int tsn_tsd_get(struct sk_buff *skb, struct genl_info *info)
-+{
-+      struct nlattr *na, *tsdattr;
-+      struct nlattr *tsda[TSN_TSD_ATTR_MAX + 1];
-+      struct net_device *netdev;
-+      const struct tsn_ops *tsnops;
-+      struct sk_buff *rep_skb;
-+      int ret;
-+      struct genlmsghdr *genlhdr;
-+      struct tsn_tsd_status tts;
-+      struct tsn_port *port;
-+
-+      port = tsn_init_check(info, &netdev);
-+      if (!port)
-+              return -ENODEV;
-+
-+      tsnops = port->tsnops;
-+
-+      if (!info->attrs[TSN_ATTR_TSD]) {
-+              tsn_simple_reply(info, TSN_CMD_REPLY,
-+                               netdev->name, -EINVAL);
-+              return -EINVAL;
-+      }
-+
-+      if (!tsnops->tsd_get) {
-+              tsn_simple_reply(info, TSN_CMD_REPLY,
-+                               netdev->name, -EPERM);
-+              return -1;
-+      }
-+
-+      ret = tsnops->tsd_get(netdev, &tts);
-+      if (ret < 0) {
-+              tsn_simple_reply(info, TSN_CMD_REPLY,
-+                               netdev->name, ret);
-+              return ret;
-+      }
-+
-+      na = info->attrs[TSN_ATTR_TSD];
-+
-+      ret = NLA_PARSE_NESTED(tsda, TSN_TSD_ATTR_MAX,
-+                             na, tsd_policy);
-+      if (ret) {
-+              pr_err("tsn: parse value TSN_TSD_ATTR_MAX error.");
-+              tsn_simple_reply(info, TSN_CMD_REPLY,
-+                               netdev->name, -EINVAL);
-+              return -EINVAL;
-+      }
-+
-+      /* Get status data from device */
-+      genlhdr = info->genlhdr;
-+
-+      /* Form netlink reply data */
-+      ret = tsn_prepare_reply(info, genlhdr->cmd, &rep_skb,
-+                              NLMSG_ALIGN(MAX_ATTR_SIZE));
-+      if (ret < 0)
-+              return ret;
-+
-+      if (nla_put_string(rep_skb, TSN_ATTR_IFNAME, netdev->name))
-+              return -EMSGSIZE;
-+
-+      tsdattr = nla_nest_start_noflag(rep_skb, TSN_ATTR_TSD);
-+      if (!tsdattr)
-+              return -EMSGSIZE;
-+
-+      if (nla_put_u32(rep_skb, TSN_TSD_ATTR_PERIOD, tts.period) ||
-+          nla_put_u32(rep_skb, TSN_TSD_ATTR_MAX_FRM_NUM, tts.maxFrameNum) ||
-+          nla_put_u32(rep_skb, TSN_TSD_ATTR_CYCLE_NUM, tts.cycleNum) ||
-+          nla_put_u32(rep_skb, TSN_TSD_ATTR_LOSS_STEPS, tts.loss_steps) ||
-+          nla_put_u32(rep_skb, TSN_TSD_ATTR_MAX_FRM_NUM, tts.maxFrameNum))
-+              return -EMSGSIZE;
-+
-+      if (!tts.enable) {
-+              if (nla_put_flag(rep_skb, TSN_TSD_ATTR_DISABLE))
-+                      return -EMSGSIZE;
-+      } else {
-+              if (nla_put_flag(rep_skb, TSN_TSD_ATTR_ENABLE))
-+                      return -EMSGSIZE;
-+      }
-+
-+      if (tts.flag == 2)
-+              if (nla_put_flag(rep_skb, TSN_TSD_ATTR_SYN_IMME))
-+                      return -EMSGSIZE;
-+
-+      nla_nest_end(rep_skb, tsdattr);
-+      return tsn_send_reply(rep_skb, info);
-+}
-+
-+static int tsn_ct_set(struct sk_buff *skb, struct genl_info *info)
-+{
-+      struct nlattr *na;
-+      struct nlattr *cta[TSN_CT_ATTR_MAX + 1];
-+      struct net_device *netdev;
-+      const struct tsn_ops *tsnops;
-+      int ret;
-+      u8 queue_stat;
-+      struct tsn_port *port;
-+
-+      port = tsn_init_check(info, &netdev);
-+      if (!port)
-+              return -ENODEV;
-+
-+      tsnops = port->tsnops;
-+
-+      if (!info->attrs[TSN_ATTR_CT]) {
-+              tsn_simple_reply(info, TSN_CMD_REPLY,
-+                               netdev->name, -EINVAL);
-+              return -EINVAL;
-+      }
-+
-+      na = info->attrs[TSN_ATTR_CT];
-+
-+      if (!tsnops->ct_set) {
-+              tsn_simple_reply(info, TSN_CMD_REPLY,
-+                               netdev->name, -EPERM);
-+              return -1;
-+      }
-+
-+      ret = NLA_PARSE_NESTED(cta, TSN_CT_ATTR_MAX,
-+                             na, ct_policy);
-+      if (ret) {
-+              tsn_simple_reply(info, TSN_CMD_REPLY,
-+                               netdev->name, -EINVAL);
-+              return -EINVAL;
-+      }
-+
-+      queue_stat = nla_get_u8(cta[TSN_CT_ATTR_QUEUE_STATE]);
-+
-+      ret = tsnops->ct_set(netdev, queue_stat);
-+      if (ret < 0) {
-+              tsn_simple_reply(info, TSN_CMD_REPLY,
-+                               netdev->name, ret);
-+              return ret;
-+      }
-+
-+      tsn_simple_reply(info, TSN_CMD_REPLY,
-+                       netdev->name, 0);
-+      return 0;
-+}
-+
-+static int tsn_cbgen_set(struct sk_buff *skb, struct genl_info *info)
-+{
-+      struct nlattr *na;
-+      struct nlattr *cbgena[TSN_CBGEN_ATTR_MAX + 1];
-+      struct net_device *netdev;
-+      const struct tsn_ops *tsnops;
-+      int ret;
-+      u32 index;
-+      struct tsn_seq_gen_conf sg_conf;
-+      struct tsn_port *port;
-+
-+      port = tsn_init_check(info, &netdev);
-+      if (!port)
-+              return -ENODEV;
-+
-+      tsnops = port->tsnops;
-+
-+      if (!info->attrs[TSN_ATTR_CBGEN]) {
-+              tsn_simple_reply(info, TSN_CMD_REPLY,
-+                               netdev->name, -EINVAL);
-+              return -EINVAL;
-+      }
-+
-+      na = info->attrs[TSN_ATTR_CBGEN];
-+
-+      if (!tsnops->cbgen_set) {
-+              tsn_simple_reply(info, TSN_CMD_REPLY,
-+                               netdev->name, -EPERM);
-+              return -1;
-+      }
-+
-+      ret = NLA_PARSE_NESTED(cbgena, TSN_CBGEN_ATTR_MAX,
-+                             na, cbgen_policy);
-+      if (ret) {
-+              tsn_simple_reply(info, TSN_CMD_REPLY,
-+                               netdev->name, -EINVAL);
-+              return -EINVAL;
-+      }
-+
-+      index = nla_get_u32(cbgena[TSN_CBGEN_ATTR_INDEX]);
-+
-+      memset(&sg_conf, 0, sizeof(struct tsn_seq_gen_conf));
-+      sg_conf.iport_mask = nla_get_u8(cbgena[TSN_CBGEN_ATTR_PORT_MASK]);
-+      sg_conf.split_mask = nla_get_u8(cbgena[TSN_CBGEN_ATTR_SPLIT_MASK]);
-+      sg_conf.seq_len = nla_get_u8(cbgena[TSN_CBGEN_ATTR_SEQ_LEN]);
-+      sg_conf.seq_num = nla_get_u32(cbgena[TSN_CBGEN_ATTR_SEQ_NUM]);
-+
-+      ret = tsnops->cbgen_set(netdev, index, &sg_conf);
-+      if (ret < 0) {
-+              tsn_simple_reply(info, TSN_CMD_REPLY,
-+                               netdev->name, ret);
-+              return ret;
-+      }
-+
-+      tsn_simple_reply(info, TSN_CMD_REPLY,
-+                       netdev->name, 0);
-+      return 0;
-+}
-+
-+static int tsn_cbrec_set(struct sk_buff *skb, struct genl_info *info)
-+{
-+      struct nlattr *na;
-+      struct nlattr *cbreca[TSN_CBREC_ATTR_MAX + 1];
-+      struct net_device *netdev;
-+      const struct tsn_ops *tsnops;
-+      int ret;
-+      u32 index;
-+      struct tsn_seq_rec_conf sr_conf;
-+      struct tsn_port *port;
-+
-+      port = tsn_init_check(info, &netdev);
-+      if (!port)
-+              return -ENODEV;
-+
-+      tsnops = port->tsnops;
-+
-+      if (!info->attrs[TSN_ATTR_CBREC]) {
-+              tsn_simple_reply(info, TSN_CMD_REPLY,
-+                               netdev->name, -EINVAL);
-+              return -EINVAL;
-+      }
-+
-+      na = info->attrs[TSN_ATTR_CBREC];
-+
-+      if (!tsnops->cbrec_set) {
-+              tsn_simple_reply(info, TSN_CMD_REPLY,
-+                               netdev->name, -EPERM);
-+              return -1;
-+      }
-+
-+      ret = NLA_PARSE_NESTED(cbreca, TSN_CBREC_ATTR_MAX,
-+                             na, cbrec_policy);
-+      if (ret) {
-+              tsn_simple_reply(info, TSN_CMD_REPLY,
-+                               netdev->name, -EINVAL);
-+              return -EINVAL;
-+      }
-+
-+      index = nla_get_u32(cbreca[TSN_CBREC_ATTR_INDEX]);
-+
-+      memset(&sr_conf, 0, sizeof(struct tsn_seq_rec_conf));
-+      sr_conf.seq_len = nla_get_u8(cbreca[TSN_CBREC_ATTR_SEQ_LEN]);
-+      sr_conf.his_len = nla_get_u8(cbreca[TSN_CBREC_ATTR_HIS_LEN]);
-+      sr_conf.rtag_pop_en = nla_get_flag(cbreca[TSN_CBREC_ATTR_TAG_POP_EN]);
-+
-+      ret = tsnops->cbrec_set(netdev, index, &sr_conf);
-+      if (ret < 0) {
-+              tsn_simple_reply(info, TSN_CMD_REPLY,
-+                               netdev->name, ret);
-+              return ret;
-+      }
-+
-+      tsn_simple_reply(info, TSN_CMD_REPLY,
-+                       netdev->name, 0);
-+      return 0;
-+}
-+
-+static int tsn_cbstatus_get(struct sk_buff *skb, struct genl_info *info)
-+{
-+      struct nlattr *na;
-+      struct nlattr *cba[TSN_CBSTAT_ATTR_MAX + 1];
-+      struct nlattr *cbattr;
-+      struct net_device *netdev;
-+      const struct tsn_ops *tsnops;
-+      struct sk_buff *rep_skb;
-+      int ret;
-+      unsigned int index;
-+      struct genlmsghdr *genlhdr;
-+      struct tsn_cb_status cbstat;
-+      struct tsn_port *port;
-+
-+      port = tsn_init_check(info, &netdev);
-+      if (!port)
-+              return -ENODEV;
-+
-+      tsnops = port->tsnops;
-+
-+      /* Get status data from device */
-+      genlhdr = info->genlhdr;
-+
-+      memset(&cbstat, 0, sizeof(struct tsn_cb_status));
-+
-+      if (!tsnops->cb_get) {
-+              tsn_simple_reply(info, TSN_CMD_REPLY,
-+                               netdev->name, -EPERM);
-+              return -1;
-+      }
-+
-+      na = info->attrs[TSN_ATTR_CBSTAT];
-+      ret = NLA_PARSE_NESTED(cba, TSN_CBSTAT_ATTR_MAX,
-+                             na, cbstat_policy);
-+      if (ret) {
-+              tsn_simple_reply(info, TSN_CMD_REPLY,
-+                               netdev->name, -EINVAL);
-+              return -EINVAL;
-+      }
-+
-+      index = nla_get_u32(cba[TSN_CBSTAT_ATTR_INDEX]);
-+
-+      ret = tsnops->cb_get(netdev, index, &cbstat);
-+      if (ret < 0) {
-+              tsn_simple_reply(info, TSN_CMD_REPLY,
-+                               netdev->name, ret);
-+              return ret;
-+      }
-+
-+      /* Form netlink reply data */
-+      ret = tsn_prepare_reply(info, genlhdr->cmd,
-+                              &rep_skb, NLMSG_ALIGN(MAX_ATTR_SIZE));
-+      if (ret < 0)
-+              return ret;
-+
-+      if (nla_put_string(rep_skb, TSN_ATTR_IFNAME, netdev->name))
-+              return -EMSGSIZE;
-+
-+      cbattr = nla_nest_start_noflag(rep_skb, TSN_ATTR_CBSTAT);
-+      if (!cbattr)
-+              return -EMSGSIZE;
-+
-+      if (nla_put_u8(rep_skb, TSN_CBSTAT_ATTR_GEN_REC, cbstat.gen_rec) ||
-+          nla_put_u8(rep_skb, TSN_CBSTAT_ATTR_ERR, cbstat.err) ||
-+          nla_put_u32(rep_skb, TSN_CBSTAT_ATTR_SEQ_NUM,
-+                      cbstat.seq_num) ||
-+          nla_put_u8(rep_skb, TSN_CBSTAT_ATTR_SEQ_LEN, cbstat.seq_len) ||
-+          nla_put_u8(rep_skb, TSN_CBSTAT_ATTR_SPLIT_MASK,
-+                     cbstat.split_mask) ||
-+          nla_put_u8(rep_skb, TSN_CBSTAT_ATTR_PORT_MASK,
-+                     cbstat.iport_mask) ||
-+          nla_put_u8(rep_skb, TSN_CBSTAT_ATTR_HIS_LEN, cbstat.his_len) ||
-+          nla_put_u32(rep_skb, TSN_CBSTAT_ATTR_SEQ_HIS,
-+                      cbstat.seq_his))
-+              return -EMSGSIZE;
-+
-+      nla_nest_end(rep_skb, cbattr);
-+
-+      return tsn_send_reply(rep_skb, info);
-+}
-+
-+static int tsn_dscp_set(struct sk_buff *skb, struct genl_info *info)
-+{
-+      struct nlattr *na;
-+      struct nlattr *dscpa[TSN_DSCP_ATTR_MAX + 1];
-+      struct net_device *netdev;
-+      const struct tsn_ops *tsnops;
-+      int ret;
-+      bool enable = 0;
-+      struct tsn_port *port;
-+      int dscp_ix;
-+      struct tsn_qos_switch_dscp_conf dscp_conf;
-+
-+      port = tsn_init_check(info, &netdev);
-+      if (!port)
-+              return -ENODEV;
-+
-+      tsnops = port->tsnops;
-+
-+      if (!info->attrs[TSN_ATTR_DSCP]) {
-+              tsn_simple_reply(info, TSN_CMD_REPLY,
-+                               netdev->name, -EINVAL);
-+              return -EINVAL;
-+      }
-+
-+      na = info->attrs[TSN_ATTR_DSCP];
-+
-+      if (!tsnops->dscp_set) {
-+              tsn_simple_reply(info, TSN_CMD_REPLY,
-+                               netdev->name, -EPERM);
-+              return -1;
-+      }
-+
-+      ret = NLA_PARSE_NESTED(dscpa, TSN_DSCP_ATTR_MAX,
-+                             na, dscp_policy);
-+      if (ret) {
-+              tsn_simple_reply(info, TSN_CMD_REPLY,
-+                               netdev->name, -EINVAL);
-+              return -EINVAL;
-+      }
-+
-+      enable = 1;
-+      if (dscpa[TSN_DSCP_ATTR_DISABLE])
-+              enable = 0;
-+      dscp_ix = nla_get_u32(dscpa[TSN_DSCP_ATTR_INDEX]);
-+      dscp_conf.cos = nla_get_u32(dscpa[TSN_DSCP_ATTR_COS]);
-+      dscp_conf.dpl = nla_get_u32(dscpa[TSN_DSCP_ATTR_DPL]);
-+      ret = tsnops->dscp_set(netdev, enable, dscp_ix, &dscp_conf);
-+      if (ret < 0) {
-+              tsn_simple_reply(info, TSN_CMD_REPLY,
-+                               netdev->name, ret);
-+              return ret;
-+      }
-+
-+      tsn_simple_reply(info, TSN_CMD_REPLY,
-+                       netdev->name, 0);
-+
-+      return 0;
-+}
-+
-+static const struct genl_ops tsnnl_ops[] = {
-+      {
-+              .cmd            = TSN_CMD_ECHO,
-+              .doit           = tsn_echo_cmd,
-+              .flags          = GENL_ADMIN_PERM,
-+      },
-+      {
-+              .cmd            = TSN_CMD_CAP_GET,
-+              .doit           = tsn_cap_get,
-+              .flags          = GENL_ADMIN_PERM,
-+      },
-+      {
-+              .cmd            = TSN_CMD_QBV_SET,
-+              .doit           = tsn_qbv_set,
-+              .flags          = GENL_ADMIN_PERM,
-+      },
-+      {
-+              .cmd            = TSN_CMD_QBV_GET,
-+              .doit           = tsn_qbv_get,
-+              .flags          = GENL_ADMIN_PERM,
-+      },
-+      {
-+              .cmd            = TSN_CMD_QBV_GET_STATUS,
-+              .doit           = tsn_qbv_status_get,
-+              .flags          = GENL_ADMIN_PERM,
-+      },
-+      {
-+              .cmd            = TSN_CMD_CB_STREAMID_SET,
-+              .doit           = tsn_cb_streamid_set,
-+              .flags          = GENL_ADMIN_PERM,
-+      },
-+      {
-+              .cmd            = TSN_CMD_CB_STREAMID_GET,
-+              .doit           = tsn_cb_streamid_get,
-+              .flags          = GENL_ADMIN_PERM,
-+      },
-+      {
-+              .cmd            = TSN_CMD_CB_STREAMID_GET_COUNTS,
-+              .doit           = tsn_cb_streamid_counters_get,
-+              .flags          = GENL_ADMIN_PERM,
-+      },
-+      {
-+              .cmd            = TSN_CMD_QCI_CAP_GET,
-+              .doit           = tsn_qci_cap_get,
-+              .flags          = GENL_ADMIN_PERM,
-+      },
-+      {
-+              .cmd            = TSN_CMD_QCI_SFI_SET,
-+              .doit           = tsn_qci_sfi_set,
-+              .flags          = GENL_ADMIN_PERM,
-+      },
-+      {
-+              .cmd            = TSN_CMD_QCI_SFI_GET,
-+              .doit           = tsn_qci_sfi_get,
-+              .flags          = GENL_ADMIN_PERM,
-+      },
-+      {
-+              .cmd            = TSN_CMD_QCI_SFI_GET_COUNTS,
-+              .doit           = tsn_qci_sfi_counters_get,
-+              .flags          = GENL_ADMIN_PERM,
-+      },
-+      {
-+              .cmd            = TSN_CMD_QCI_SGI_SET,
-+              .doit           = tsn_qci_sgi_set,
-+              .flags          = GENL_ADMIN_PERM,
-+      },
-+      {
-+              .cmd            = TSN_CMD_QCI_SGI_GET,
-+              .doit           = tsn_qci_sgi_get,
-+              .flags          = GENL_ADMIN_PERM,
-+      },
-+      {
-+              .cmd            = TSN_CMD_QCI_SGI_GET_STATUS,
-+              .doit           = tsn_qci_sgi_status_get,
-+              .flags          = GENL_ADMIN_PERM,
-+      },
-+      {
-+              .cmd            = TSN_CMD_QCI_FMI_SET,
-+              .doit           = tsn_qci_fmi_set,
-+              .flags          = GENL_ADMIN_PERM,
-+      },
-+      {
-+              .cmd            = TSN_CMD_QCI_FMI_GET,
-+              .doit           = tsn_qci_fmi_get,
-+              .flags          = GENL_ADMIN_PERM,
-+      },
-+      {
-+              .cmd            = TSN_CMD_CBS_SET,
-+              .doit           = tsn_cbs_set,
-+              .flags          = GENL_ADMIN_PERM,
-+      },
-+      {
-+              .cmd            = TSN_CMD_CBS_GET,
-+              .doit           = tsn_cbs_get,
-+              .flags          = GENL_ADMIN_PERM,
-+      },
-+      {
-+              .cmd            = TSN_CMD_QBU_SET,
-+              .doit           = tsn_qbu_set,
-+              .flags          = GENL_ADMIN_PERM,
-+      },
-+      {
-+              .cmd            = TSN_CMD_QBU_GET_STATUS,
-+              .doit           = tsn_qbu_get_status,
-+              .flags          = GENL_ADMIN_PERM,
-+      },
-+      {
-+              .cmd            = TSN_CMD_TSD_SET,
-+              .doit           = tsn_tsd_set,
-+              .flags          = GENL_ADMIN_PERM,
-+      },
-+      {
-+              .cmd            = TSN_CMD_TSD_GET,
-+              .doit           = tsn_tsd_get,
-+              .flags          = GENL_ADMIN_PERM,
-+      },
-+      {
-+              .cmd            = TSN_CMD_CT_SET,
-+              .doit           = tsn_ct_set,
-+              .flags          = GENL_ADMIN_PERM,
-+      },
-+      {
-+              .cmd            = TSN_CMD_CBGEN_SET,
-+              .doit           = tsn_cbgen_set,
-+              .flags          = GENL_ADMIN_PERM,
-+      },
-+      {
-+              .cmd            = TSN_CMD_CBREC_SET,
-+              .doit           = tsn_cbrec_set,
-+              .flags          = GENL_ADMIN_PERM,
-+      },
-+      {
-+              .cmd            = TSN_CMD_CBSTAT_GET,
-+              .doit           = tsn_cbstatus_get,
-+              .flags          = GENL_ADMIN_PERM,
-+      },
-+      {
-+              .cmd            = TSN_CMD_DSCP_SET,
-+              .doit           = tsn_dscp_set,
-+              .flags          = GENL_ADMIN_PERM,
-+      },
-+};
-+
-+static const struct genl_multicast_group tsn_mcgrps[] = {
-+      [TSN_MCGRP_QBV] = { .name = TSN_MULTICAST_GROUP_QBV},
-+      [TSN_MCGRP_QCI] = { .name = TSN_MULTICAST_GROUP_QCI},
-+};
-+
-+static struct genl_family tsn_family = {
-+      .name           = TSN_GENL_NAME,
-+      .version        = TSN_GENL_VERSION,
-+      .maxattr        = TSN_CMD_ATTR_MAX,
-+      .module         = THIS_MODULE,
-+      .netnsok        = true,
-+      .ops            = tsnnl_ops,
-+      .n_ops          = ARRAY_SIZE(tsnnl_ops),
-+      .mcgrps         = tsn_mcgrps,
-+      .n_mcgrps       = ARRAY_SIZE(tsn_mcgrps),
-+};
-+
-+int tsn_port_register(struct net_device *netdev,
-+                    struct tsn_ops *tsnops, u16 groupid)
-+{
-+      struct tsn_port *port;
-+
-+      if (list_empty(&port_list)) {
-+              INIT_LIST_HEAD(&port_list);
-+      } else {
-+              list_for_each_entry(port, &port_list, list) {
-+                      if (port->netdev == netdev) {
-+                              pr_info("TSN device already registered!\n");
-+                              return -1;
-+                      }
-+              }
-+      }
-+
-+      port = kzalloc(sizeof(*port), GFP_KERNEL);
-+      if (!port)
-+              return -1;
-+
-+      port->netdev = netdev;
-+      port->groupid = groupid;
-+      port->tsnops = tsnops;
-+      port->nd.dev = netdev;
-+
-+      if (groupid < GROUP_OFFSET_SWITCH)
-+              port->type = TSN_ENDPOINT;
-+      else
-+              port->type = TSN_SWITCH;
-+
-+      list_add_tail(&port->list, &port_list);
-+
-+      if (tsnops && tsnops->device_init)
-+              port->tsnops->device_init(netdev);
-+
-+      return 0;
-+}
-+EXPORT_SYMBOL(tsn_port_register);
-+
-+void tsn_port_unregister(struct net_device *netdev)
-+{
-+      struct tsn_port *p;
-+
-+      list_for_each_entry(p, &port_list, list) {
-+              if (!p || !p->netdev)
-+                      continue;
-+              if (p->netdev == netdev) {
-+                      if (p->tsnops->device_deinit)
-+                              p->tsnops->device_deinit(netdev);
-+                      list_del(&p->list);
-+                      kfree(p);
-+                      break;
-+              }
-+      }
-+}
-+EXPORT_SYMBOL(tsn_port_unregister);
-+
-+static int tsn_multicast_to_user(unsigned long event,
-+                               struct tsn_notifier_info *tsn_info)
-+{
-+      struct sk_buff *skb;
-+      struct genlmsghdr *nlh;
-+      int res;
-+      struct tsn_qbv_conf *qbvdata;
-+
-+      /* If new attributes are added, please revisit this allocation */
-+      skb = genlmsg_new(sizeof(*tsn_info), GFP_KERNEL);
-+      if (!skb) {
-+              pr_err("Allocation failure.\n");
-+              return -ENOMEM;
-+      }
-+
-+      switch (event) {
-+      case TSN_QBV_CONFIGCHANGETIME_ARRIVE:
-+              nlh = genlmsg_put(skb, 0, 1, &tsn_family,
-+                                GFP_KERNEL, TSN_CMD_QBV_SET);
-+              qbvdata = &tsn_info->ntdata.qbv_notify;
-+              res = NLA_PUT_U64(skb, TSN_QBV_ATTR_CTRL_BASETIME,
-+                                qbvdata->admin.base_time);
-+
-+              if (res) {
-+                      pr_err("put data failure!\n");
-+                      goto done;
-+              }
-+
-+              res = nla_put_u32(skb, TSN_QBV_ATTR_CTRL_CYCLETIME,
-+                                qbvdata->admin.cycle_time);
-+              if (res) {
-+                      pr_err("put data failure!\n");
-+                      goto done;
-+              }
-+
-+              if (qbvdata->gate_enabled)
-+                      res = nla_put_flag(skb, TSN_QBV_ATTR_ENABLE +
-+                                         TSN_QBV_ATTR_CTRL_MAX);
-+              else
-+                      res = nla_put_flag(skb, TSN_QBV_ATTR_DISABLE +
-+                                         TSN_QBV_ATTR_CTRL_MAX);
-+              if (res) {
-+                      pr_err("put data failure!\n");
-+                      goto done;
-+              }
-+
-+              res = nla_put_u32(skb, TSN_QBV_ATTR_CTRL_UNSPEC,
-+                                tsn_info->dev->ifindex);
-+              if (res) {
-+                      pr_err("put data failure!\n");
-+                      goto done;
-+              }
-+
-+              break;
-+      default:
-+              pr_info("event not supportted!\n");
-+              break;
-+      }
-+
-+      (void)genlmsg_end(skb, nlh);
-+
-+      res = genlmsg_multicast_allns(&tsn_family, skb, 0,
-+                                    TSN_MCGRP_QBV, GFP_KERNEL);
-+      skb = NULL;
-+      if (res && res != -ESRCH) {
-+              pr_err("genlmsg_multicast_allns error: %d\n", res);
-+              goto done;
-+      }
-+
-+      if (res == -ESRCH)
-+              res = 0;
-+
-+done:
-+      if (skb) {
-+              nlmsg_free(skb);
-+              skb = NULL;
-+      }
-+
-+      return res;
-+}
-+
-+/* called with RTNL or RCU */
-+static int tsn_event(struct notifier_block *unused,
-+                   unsigned long event, void *ptr)
-+{
-+      struct tsn_notifier_info *tsn_info;
-+      int err = NOTIFY_DONE;
-+
-+      switch (event) {
-+      case TSN_QBV_CONFIGCHANGETIME_ARRIVE:
-+              tsn_info = ptr;
-+              err = tsn_multicast_to_user(event, tsn_info);
-+              if (err) {
-+                      err = notifier_from_errno(err);
-+                      break;
-+              }
-+              break;
-+      default:
-+              pr_info("event not supportted!\n");
-+              break;
-+      }
-+
-+      return err;
-+}
-+
-+static struct notifier_block tsn_notifier = {
-+      .notifier_call = tsn_event,
-+};
-+
-+static int __init tsn_genetlink_init(void)
-+{
-+      int ret;
-+
-+      pr_info("tsn generic netlink module v%d init...\n", TSN_GENL_VERSION);
-+
-+      ret = genl_register_family(&tsn_family);
-+
-+      if (ret != 0) {
-+              pr_info("failed to init tsn generic netlink example module\n");
-+              return ret;
-+      }
-+
-+      register_tsn_notifier(&tsn_notifier);
-+
-+      return 0;
-+}
-+
-+static void __exit tsn_genetlink_exit(void)
-+{
-+      int ret;
-+
-+      ret = genl_unregister_family(&tsn_family);
-+      if (ret != 0)
-+              pr_info("failed to unregister family:%i\n", ret);
-+
-+      unregister_tsn_notifier(&tsn_notifier);
-+}
-+
-+module_init(tsn_genetlink_init);
-+module_exit(tsn_genetlink_exit);
-+MODULE_LICENSE("GPL");