@@ -57,6 +57,49 @@ static int can_validate_bittiming(struct nlattr *data[],
5757 return 0 ;
5858}
5959
60+ static int can_validate_tdc (struct nlattr * data_tdc ,
61+ struct netlink_ext_ack * extack , u32 tdc_flags )
62+ {
63+ bool tdc_manual = tdc_flags & CAN_CTRLMODE_TDC_MANUAL_MASK ;
64+ bool tdc_auto = tdc_flags & CAN_CTRLMODE_TDC_AUTO_MASK ;
65+ int err ;
66+
67+ /* CAN_CTRLMODE_TDC_{AUTO,MANUAL} are mutually exclusive */
68+ if (tdc_auto && tdc_manual )
69+ return - EOPNOTSUPP ;
70+
71+ /* If one of the CAN_CTRLMODE_TDC_* flag is set then TDC
72+ * must be set and vice-versa
73+ */
74+ if ((tdc_auto || tdc_manual ) != !!data_tdc )
75+ return - EOPNOTSUPP ;
76+
77+ /* If providing TDC parameters, at least TDCO is needed. TDCV
78+ * is needed if and only if CAN_CTRLMODE_TDC_MANUAL is set
79+ */
80+ if (data_tdc ) {
81+ struct nlattr * tb_tdc [IFLA_CAN_TDC_MAX + 1 ];
82+
83+ err = nla_parse_nested (tb_tdc , IFLA_CAN_TDC_MAX ,
84+ data_tdc , can_tdc_policy , extack );
85+ if (err )
86+ return err ;
87+
88+ if (tb_tdc [IFLA_CAN_TDC_TDCV ]) {
89+ if (tdc_auto )
90+ return - EOPNOTSUPP ;
91+ } else {
92+ if (tdc_manual )
93+ return - EOPNOTSUPP ;
94+ }
95+
96+ if (!tb_tdc [IFLA_CAN_TDC_TDCO ])
97+ return - EOPNOTSUPP ;
98+ }
99+
100+ return 0 ;
101+ }
102+
60103static int can_validate (struct nlattr * tb [], struct nlattr * data [],
61104 struct netlink_ext_ack * extack )
62105{
@@ -67,50 +110,21 @@ static int can_validate(struct nlattr *tb[], struct nlattr *data[],
67110 * - nominal/arbitration bittiming
68111 * - data bittiming
69112 * - control mode with CAN_CTRLMODE_FD set
70- * - TDC parameters are coherent (details below )
113+ * - TDC parameters are coherent (details in can_validate_tdc() )
71114 */
72115
73116 if (!data )
74117 return 0 ;
75118
76119 if (data [IFLA_CAN_CTRLMODE ]) {
77120 struct can_ctrlmode * cm = nla_data (data [IFLA_CAN_CTRLMODE ]);
78- u32 tdc_flags = cm -> flags & CAN_CTRLMODE_FD_TDC_MASK ;
79121
80122 is_can_fd = cm -> flags & cm -> mask & CAN_CTRLMODE_FD ;
81123
82- /* CAN_CTRLMODE_TDC_{AUTO,MANUAL} are mutually exclusive */
83- if (tdc_flags == CAN_CTRLMODE_FD_TDC_MASK )
84- return - EOPNOTSUPP ;
85- /* If one of the CAN_CTRLMODE_TDC_* flag is set then
86- * TDC must be set and vice-versa
87- */
88- if (!!tdc_flags != !!data [IFLA_CAN_TDC ])
89- return - EOPNOTSUPP ;
90- /* If providing TDC parameters, at least TDCO is
91- * needed. TDCV is needed if and only if
92- * CAN_CTRLMODE_TDC_MANUAL is set
93- */
94- if (data [IFLA_CAN_TDC ]) {
95- struct nlattr * tb_tdc [IFLA_CAN_TDC_MAX + 1 ];
96-
97- err = nla_parse_nested (tb_tdc , IFLA_CAN_TDC_MAX ,
98- data [IFLA_CAN_TDC ],
99- can_tdc_policy , extack );
100- if (err )
101- return err ;
102-
103- if (tb_tdc [IFLA_CAN_TDC_TDCV ]) {
104- if (tdc_flags & CAN_CTRLMODE_TDC_AUTO )
105- return - EOPNOTSUPP ;
106- } else {
107- if (tdc_flags & CAN_CTRLMODE_TDC_MANUAL )
108- return - EOPNOTSUPP ;
109- }
110-
111- if (!tb_tdc [IFLA_CAN_TDC_TDCO ])
112- return - EOPNOTSUPP ;
113- }
124+ err = can_validate_tdc (data [IFLA_CAN_TDC ], extack ,
125+ cm -> flags & CAN_CTRLMODE_FD_TDC_MASK );
126+ if (err )
127+ return err ;
114128 }
115129
116130 err = can_validate_bittiming (data , extack , IFLA_CAN_BITTIMING );
0 commit comments