Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'cpsw-add-MQPRIO-and-CBS-Qdisc-offload'

Ivan Khoronzhuk says:

====================
net: ethernet: ti: cpsw: add MQPRIO and CBS Qdisc offload

This series adds MQPRIO and CBS Qdisc offload for TI cpsw driver.
It potentially can be used in audio video bridging (AVB) and time
sensitive networking (TSN).

Patchset was tested on AM572x EVM and BBB boards. Last patch from this
series adds detailed description of configuration with examples. For
consistency reasons, in role of talker and listener, tools from
patchset "TSN: Add qdisc based config interface for CBS" were used and
can be seen here: https://www.spinics.net/lists/netdev/msg460869.html

Based on net-next/master

v5..v4:
- corrected typo of "am57xx" board name, no functional changes

v4..v3:
- nothing, just rebase

v3..v2:
- corrected typo of "shaper" word, no functional changes

v2..v1:
- changed name cpsw.txt on ti-cpsw.txt
- changed name cpsw_set_tc() on cpsw_set_mqprio()
====================

Signed-off-by: David S. Miller <davem@davemloft.net>

+913 -22
+540
Documentation/networking/ti-cpsw.txt
··· 1 + * Texas Instruments CPSW ethernet driver 2 + 3 + Multiqueue & CBS & MQPRIO 4 + ===================================================================== 5 + ===================================================================== 6 + 7 + The cpsw has 3 CBS shapers for each external ports. This document 8 + describes MQPRIO and CBS Qdisc offload configuration for cpsw driver 9 + based on examples. It potentially can be used in audio video bridging 10 + (AVB) and time sensitive networking (TSN). 11 + 12 + The following examples were tested on AM572x EVM and BBB boards. 13 + 14 + Test setup 15 + ========== 16 + 17 + Under consideration two examples with AM572x EVM running cpsw driver 18 + in dual_emac mode. 19 + 20 + Several prerequisites: 21 + - TX queues must be rated starting from txq0 that has highest priority 22 + - Traffic classes are used starting from 0, that has highest priority 23 + - CBS shapers should be used with rated queues 24 + - The bandwidth for CBS shapers has to be set a little bit more then 25 + potential incoming rate, thus, rate of all incoming tx queues has 26 + to be a little less 27 + - Real rates can differ, due to discreetness 28 + - Map skb-priority to txq is not enough, also skb-priority to l2 prio 29 + map has to be created with ip or vconfig tool 30 + - Any l2/socket prio (0 - 7) for classes can be used, but for 31 + simplicity default values are used: 3 and 2 32 + - only 2 classes tested: A and B, but checked and can work with more, 33 + maximum allowed 4, but only for 3 rate can be set. 34 + 35 + Test setup for examples 36 + ======================= 37 + +-------------------------------+ 38 + |--+ | 39 + | | Workstation0 | 40 + |E | MAC 18:03:73:66:87:42 | 41 + +-----------------------------+ +--|t | | 42 + | | 1 | E | | |h |./tsn_listener -d \ | 43 + | Target board: | 0 | t |--+ |0 | 18:03:73:66:87:42 -i eth0 \| 44 + | AM572x EVM | 0 | h | | | -s 1500 | 45 + | | 0 | 0 | |--+ | 46 + | Only 2 classes: |Mb +---| +-------------------------------+ 47 + | class A, class B | | 48 + | | +---| +-------------------------------+ 49 + | | 1 | E | |--+ | 50 + | | 0 | t | | | Workstation1 | 51 + | | 0 | h |--+ |E | MAC 20:cf:30:85:7d:fd | 52 + | |Mb | 1 | +--|t | | 53 + +-----------------------------+ |h |./tsn_listener -d \ | 54 + |0 | 20:cf:30:85:7d:fd -i eth0 \| 55 + | | -s 1500 | 56 + |--+ | 57 + +-------------------------------+ 58 + 59 + ********************************************************************* 60 + ********************************************************************* 61 + ********************************************************************* 62 + Example 1: One port tx AVB configuration scheme for target board 63 + ---------------------------------------------------------------------- 64 + (prints and scheme for AM572x evm, applicable for single port boards) 65 + 66 + tc - traffic class 67 + txq - transmit queue 68 + p - priority 69 + f - fifo (cpsw fifo) 70 + S - shaper configured 71 + 72 + +------------------------------------------------------------------+ u 73 + | +---------------+ +---------------+ +------+ +------+ | s 74 + | | | | | | | | | | e 75 + | | App 1 | | App 2 | | Apps | | Apps | | r 76 + | | Class A | | Class B | | Rest | | Rest | | 77 + | | Eth0 | | Eth0 | | Eth0 | | Eth1 | | s 78 + | | VLAN100 | | VLAN100 | | | | | | | | p 79 + | | 40 Mb/s | | 20 Mb/s | | | | | | | | a 80 + | | SO_PRIORITY=3 | | SO_PRIORITY=2 | | | | | | | | c 81 + | | | | | | | | | | | | | | e 82 + | +---|-----------+ +---|-----------+ +---|--+ +---|--+ | 83 + +-----|------------------|------------------|--------|-------------+ 84 + +-+ +------------+ | | 85 + | | +-----------------+ +--+ 86 + | | | | 87 + +---|-------|-------------|-----------------------|----------------+ 88 + | +----+ +----+ +----+ +----+ +----+ | 89 + | | p3 | | p2 | | p1 | | p0 | | p0 | | k 90 + | \ / \ / \ / \ / \ / | e 91 + | \ / \ / \ / \ / \ / | r 92 + | \/ \/ \/ \/ \/ | n 93 + | | | | | | e 94 + | | | +-----+ | | l 95 + | | | | | | 96 + | +----+ +----+ +----+ +----+ | s 97 + | |tc0 | |tc1 | |tc2 | |tc0 | | p 98 + | \ / \ / \ / \ / | a 99 + | \ / \ / \ / \ / | c 100 + | \/ \/ \/ \/ | e 101 + | | | +-----+ | | 102 + | | | | | | | 103 + | | | | | | | 104 + | | | | | | | 105 + | +----+ +----+ +----+ +----+ +----+ | 106 + | |txq0| |txq1| |txq2| |txq3| |txq4| | 107 + | \ / \ / \ / \ / \ / | 108 + | \ / \ / \ / \ / \ / | 109 + | \/ \/ \/ \/ \/ | 110 + | +-|------|------|------|--+ +--|--------------+ | 111 + | | | | | | | Eth0.100 | | Eth1 | | 112 + +---|------|------|------|------------------------|----------------+ 113 + | | | | | 114 + p p p p | 115 + 3 2 0-1, 4-7 <- L2 priority | 116 + | | | | | 117 + | | | | | 118 + +---|------|------|------|------------------------|----------------+ 119 + | | | | | |----------+ | 120 + | +----+ +----+ +----+ +----+ +----+ | 121 + | |dma7| |dma6| |dma5| |dma4| |dma3| | 122 + | \ / \ / \ / \ / \ / | c 123 + | \S / \S / \ / \ / \ / | p 124 + | \/ \/ \/ \/ \/ | s 125 + | | | | +----- | | w 126 + | | | | | | | 127 + | | | | | | | d 128 + | +----+ +----+ +----+p p+----+ | r 129 + | | | | | | |o o| | | i 130 + | | f3 | | f2 | | f0 |r r| f0 | | v 131 + | |tc0 | |tc1 | |tc2 |t t|tc0 | | e 132 + | \CBS / \CBS / \CBS /1 2\CBS / | r 133 + | \S / \S / \ / \ / | 134 + | \/ \/ \/ \/ | 135 + +------------------------------------------------------------------+ 136 + ========================================Eth==========================> 137 + 138 + 1) 139 + // Add 4 tx queues, for interface Eth0, and 1 tx queue for Eth1 140 + $ ethtool -L eth0 rx 1 tx 5 141 + rx unmodified, ignoring 142 + 143 + 2) 144 + // Check if num of queues is set correctly: 145 + $ ethtool -l eth0 146 + Channel parameters for eth0: 147 + Pre-set maximums: 148 + RX: 8 149 + TX: 8 150 + Other: 0 151 + Combined: 0 152 + Current hardware settings: 153 + RX: 1 154 + TX: 5 155 + Other: 0 156 + Combined: 0 157 + 158 + 3) 159 + // TX queues must be rated starting from 0, so set bws for tx0 and tx1 160 + // Set rates 40 and 20 Mb/s appropriately. 161 + // Pay attention, real speed can differ a bit due to discreetness. 162 + // Leave last 2 tx queues not rated. 163 + $ echo 40 > /sys/class/net/eth0/queues/tx-0/tx_maxrate 164 + $ echo 20 > /sys/class/net/eth0/queues/tx-1/tx_maxrate 165 + 166 + 4) 167 + // Check maximum rate of tx (cpdma) queues: 168 + $ cat /sys/class/net/eth0/queues/tx-*/tx_maxrate 169 + 40 170 + 20 171 + 0 172 + 0 173 + 0 174 + 175 + 5) 176 + // Map skb->priority to traffic class: 177 + // 3pri -> tc0, 2pri -> tc1, (0,1,4-7)pri -> tc2 178 + // Map traffic class to transmit queue: 179 + // tc0 -> txq0, tc1 -> txq1, tc2 -> (txq2, txq3) 180 + $ tc qdisc replace dev eth0 handle 100: parent root mqprio num_tc 3 \ 181 + map 2 2 1 0 2 2 2 2 2 2 2 2 2 2 2 2 queues 1@0 1@1 2@2 hw 1 182 + 183 + 5a) 184 + // As two interface sharing same set of tx queues, assign all traffic 185 + // coming to interface Eth1 to separate queue in order to not mix it 186 + // with traffic from interface Eth0, so use separate txq to send 187 + // packets to Eth1, so all prio -> tc0 and tc0 -> txq4 188 + // Here hw 0, so here still default configuration for eth1 in hw 189 + $ tc qdisc replace dev eth1 handle 100: parent root mqprio num_tc 1 \ 190 + map 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 queues 1@4 hw 0 191 + 192 + 6) 193 + // Check classes settings 194 + $ tc -g class show dev eth0 195 + +---(100:ffe2) mqprio 196 + | +---(100:3) mqprio 197 + | +---(100:4) mqprio 198 + | 199 + +---(100:ffe1) mqprio 200 + | +---(100:2) mqprio 201 + | 202 + +---(100:ffe0) mqprio 203 + +---(100:1) mqprio 204 + 205 + $ tc -g class show dev eth1 206 + +---(100:ffe0) mqprio 207 + +---(100:5) mqprio 208 + 209 + 7) 210 + // Set rate for class A - 41 Mbit (tc0, txq0) using CBS Qdisc 211 + // Set it +1 Mb for reserve (important!) 212 + // here only idle slope is important, others arg are ignored 213 + // Pay attention, real speed can differ a bit due to discreetness 214 + $ tc qdisc add dev eth0 parent 100:1 cbs locredit -1438 \ 215 + hicredit 62 sendslope -959000 idleslope 41000 offload 1 216 + net eth0: set FIFO3 bw = 50 217 + 218 + 8) 219 + // Set rate for class B - 21 Mbit (tc1, txq1) using CBS Qdisc: 220 + // Set it +1 Mb for reserve (important!) 221 + $ tc qdisc add dev eth0 parent 100:2 cbs locredit -1468 \ 222 + hicredit 65 sendslope -979000 idleslope 21000 offload 1 223 + net eth0: set FIFO2 bw = 30 224 + 225 + 9) 226 + // Create vlan 100 to map sk->priority to vlan qos 227 + $ ip link add link eth0 name eth0.100 type vlan id 100 228 + 8021q: 802.1Q VLAN Support v1.8 229 + 8021q: adding VLAN 0 to HW filter on device eth0 230 + 8021q: adding VLAN 0 to HW filter on device eth1 231 + net eth0: Adding vlanid 100 to vlan filter 232 + 233 + 10) 234 + // Map skb->priority to L2 prio, 1 to 1 235 + $ ip link set eth0.100 type vlan \ 236 + egress 0:0 1:1 2:2 3:3 4:4 5:5 6:6 7:7 237 + 238 + 11) 239 + // Check egress map for vlan 100 240 + $ cat /proc/net/vlan/eth0.100 241 + [...] 242 + INGRESS priority mappings: 0:0 1:0 2:0 3:0 4:0 5:0 6:0 7:0 243 + EGRESS priority mappings: 0:0 1:1 2:2 3:3 4:4 5:5 6:6 7:7 244 + 245 + 12) 246 + // Run your appropriate tools with socket option "SO_PRIORITY" 247 + // to 3 for class A and/or to 2 for class B 248 + // (I took at https://www.spinics.net/lists/netdev/msg460869.html) 249 + ./tsn_talker -d 18:03:73:66:87:42 -i eth0.100 -p3 -s 1500& 250 + ./tsn_talker -d 18:03:73:66:87:42 -i eth0.100 -p2 -s 1500& 251 + 252 + 13) 253 + // run your listener on workstation (should be in same vlan) 254 + // (I took at https://www.spinics.net/lists/netdev/msg460869.html) 255 + ./tsn_listener -d 18:03:73:66:87:42 -i enp5s0 -s 1500 256 + Receiving data rate: 39012 kbps 257 + Receiving data rate: 39012 kbps 258 + Receiving data rate: 39012 kbps 259 + Receiving data rate: 39012 kbps 260 + Receiving data rate: 39012 kbps 261 + Receiving data rate: 39012 kbps 262 + Receiving data rate: 39012 kbps 263 + Receiving data rate: 39012 kbps 264 + Receiving data rate: 39012 kbps 265 + Receiving data rate: 39012 kbps 266 + Receiving data rate: 39012 kbps 267 + Receiving data rate: 39012 kbps 268 + Receiving data rate: 39000 kbps 269 + 270 + 14) 271 + // Restore default configuration if needed 272 + $ ip link del eth0.100 273 + $ tc qdisc del dev eth1 root 274 + $ tc qdisc del dev eth0 root 275 + net eth0: Prev FIFO2 is shaped 276 + net eth0: set FIFO3 bw = 0 277 + net eth0: set FIFO2 bw = 0 278 + $ ethtool -L eth0 rx 1 tx 1 279 + 280 + ********************************************************************* 281 + ********************************************************************* 282 + ********************************************************************* 283 + Example 2: Two port tx AVB configuration scheme for target board 284 + ---------------------------------------------------------------------- 285 + (prints and scheme for AM572x evm, for dual emac boards only) 286 + 287 + +------------------------------------------------------------------+ u 288 + | +----------+ +----------+ +------+ +----------+ +----------+ | s 289 + | | | | | | | | | | | | e 290 + | | App 1 | | App 2 | | Apps | | App 3 | | App 4 | | r 291 + | | Class A | | Class B | | Rest | | Class B | | Class A | | 292 + | | Eth0 | | Eth0 | | | | | Eth1 | | Eth1 | | s 293 + | | VLAN100 | | VLAN100 | | | | | VLAN100 | | VLAN100 | | p 294 + | | 40 Mb/s | | 20 Mb/s | | | | | 10 Mb/s | | 30 Mb/s | | a 295 + | | SO_PRI=3 | | SO_PRI=2 | | | | | SO_PRI=3 | | SO_PRI=2 | | c 296 + | | | | | | | | | | | | | | | | | e 297 + | +---|------+ +---|------+ +---|--+ +---|------+ +---|------+ | 298 + +-----|-------------|-------------|---------|-------------|--------+ 299 + +-+ +-------+ | +----------+ +----+ 300 + | | +-------+------+ | | 301 + | | | | | | 302 + +---|-------|-------------|--------------|-------------|-------|---+ 303 + | +----+ +----+ +----+ +----+ +----+ +----+ +----+ +----+ | 304 + | | p3 | | p2 | | p1 | | p0 | | p0 | | p1 | | p2 | | p3 | | k 305 + | \ / \ / \ / \ / \ / \ / \ / \ / | e 306 + | \ / \ / \ / \ / \ / \ / \ / \ / | r 307 + | \/ \/ \/ \/ \/ \/ \/ \/ | n 308 + | | | | | | | | e 309 + | | | +----+ +----+ | | | l 310 + | | | | | | | | 311 + | +----+ +----+ +----+ +----+ +----+ +----+ | s 312 + | |tc0 | |tc1 | |tc2 | |tc2 | |tc1 | |tc0 | | p 313 + | \ / \ / \ / \ / \ / \ / | a 314 + | \ / \ / \ / \ / \ / \ / | c 315 + | \/ \/ \/ \/ \/ \/ | e 316 + | | | +-----+ +-----+ | | | 317 + | | | | | | | | | | 318 + | | | | | | | | | | 319 + | | | | | E E | | | | | 320 + | +----+ +----+ +----+ +----+ t t +----+ +----+ +----+ +----+ | 321 + | |txq0| |txq1| |txq4| |txq5| h h |txq6| |txq7| |txq3| |txq2| | 322 + | \ / \ / \ / \ / 0 1 \ / \ / \ / \ / | 323 + | \ / \ / \ / \ / . . \ / \ / \ / \ / | 324 + | \/ \/ \/ \/ 1 1 \/ \/ \/ \/ | 325 + | +-|------|------|------|--+ 0 0 +-|------|------|------|--+ | 326 + | | | | | | | 0 0 | | | | | | | 327 + +---|------|------|------|---------------|------|------|------|----+ 328 + | | | | | | | | 329 + p p p p p p p p 330 + 3 2 0-1, 4-7 <-L2 pri-> 0-1, 4-7 2 3 331 + | | | | | | | | 332 + | | | | | | | | 333 + +---|------|------|------|---------------|------|------|------|----+ 334 + | | | | | | | | | | 335 + | +----+ +----+ +----+ +----+ +----+ +----+ +----+ +----+ | 336 + | |dma7| |dma6| |dma3| |dma2| |dma1| |dma0| |dma4| |dma5| | 337 + | \ / \ / \ / \ / \ / \ / \ / \ / | c 338 + | \S / \S / \ / \ / \ / \ / \S / \S / | p 339 + | \/ \/ \/ \/ \/ \/ \/ \/ | s 340 + | | | | +----- | | | | | w 341 + | | | | | +----+ | | | | 342 + | | | | | | | | | | d 343 + | +----+ +----+ +----+p p+----+ +----+ +----+ | r 344 + | | | | | | |o o| | | | | | | i 345 + | | f3 | | f2 | | f0 |r CPSW r| f3 | | f2 | | f0 | | v 346 + | |tc0 | |tc1 | |tc2 |t t|tc0 | |tc1 | |tc2 | | e 347 + | \CBS / \CBS / \CBS /1 2\CBS / \CBS / \CBS / | r 348 + | \S / \S / \ / \S / \S / \ / | 349 + | \/ \/ \/ \/ \/ \/ | 350 + +------------------------------------------------------------------+ 351 + ========================================Eth==========================> 352 + 353 + 1) 354 + // Add 8 tx queues, for interface Eth0, but they are common, so are accessed 355 + // by two interfaces Eth0 and Eth1. 356 + $ ethtool -L eth1 rx 1 tx 8 357 + rx unmodified, ignoring 358 + 359 + 2) 360 + // Check if num of queues is set correctly: 361 + $ ethtool -l eth0 362 + Channel parameters for eth0: 363 + Pre-set maximums: 364 + RX: 8 365 + TX: 8 366 + Other: 0 367 + Combined: 0 368 + Current hardware settings: 369 + RX: 1 370 + TX: 8 371 + Other: 0 372 + Combined: 0 373 + 374 + 3) 375 + // TX queues must be rated starting from 0, so set bws for tx0 and tx1 for Eth0 376 + // and for tx2 and tx3 for Eth1. That is, rates 40 and 20 Mb/s appropriately 377 + // for Eth0 and 30 and 10 Mb/s for Eth1. 378 + // Real speed can differ a bit due to discreetness 379 + // Leave last 4 tx queues as not rated 380 + $ echo 40 > /sys/class/net/eth0/queues/tx-0/tx_maxrate 381 + $ echo 20 > /sys/class/net/eth0/queues/tx-1/tx_maxrate 382 + $ echo 30 > /sys/class/net/eth1/queues/tx-2/tx_maxrate 383 + $ echo 10 > /sys/class/net/eth1/queues/tx-3/tx_maxrate 384 + 385 + 4) 386 + // Check maximum rate of tx (cpdma) queues: 387 + $ cat /sys/class/net/eth0/queues/tx-*/tx_maxrate 388 + 40 389 + 20 390 + 30 391 + 10 392 + 0 393 + 0 394 + 0 395 + 0 396 + 397 + 5) 398 + // Map skb->priority to traffic class for Eth0: 399 + // 3pri -> tc0, 2pri -> tc1, (0,1,4-7)pri -> tc2 400 + // Map traffic class to transmit queue: 401 + // tc0 -> txq0, tc1 -> txq1, tc2 -> (txq4, txq5) 402 + $ tc qdisc replace dev eth0 handle 100: parent root mqprio num_tc 3 \ 403 + map 2 2 1 0 2 2 2 2 2 2 2 2 2 2 2 2 queues 1@0 1@1 2@4 hw 1 404 + 405 + 6) 406 + // Check classes settings 407 + $ tc -g class show dev eth0 408 + +---(100:ffe2) mqprio 409 + | +---(100:5) mqprio 410 + | +---(100:6) mqprio 411 + | 412 + +---(100:ffe1) mqprio 413 + | +---(100:2) mqprio 414 + | 415 + +---(100:ffe0) mqprio 416 + +---(100:1) mqprio 417 + 418 + 7) 419 + // Set rate for class A - 41 Mbit (tc0, txq0) using CBS Qdisc for Eth0 420 + // here only idle slope is important, others ignored 421 + // Real speed can differ a bit due to discreetness 422 + $ tc qdisc add dev eth0 parent 100:1 cbs locredit -1470 \ 423 + hicredit 62 sendslope -959000 idleslope 41000 offload 1 424 + net eth0: set FIFO3 bw = 50 425 + 426 + 8) 427 + // Set rate for class B - 21 Mbit (tc1, txq1) using CBS Qdisc for Eth0 428 + $ tc qdisc add dev eth0 parent 100:2 cbs locredit -1470 \ 429 + hicredit 65 sendslope -979000 idleslope 21000 offload 1 430 + net eth0: set FIFO2 bw = 30 431 + 432 + 9) 433 + // Create vlan 100 to map sk->priority to vlan qos for Eth0 434 + $ ip link add link eth0 name eth0.100 type vlan id 100 435 + net eth0: Adding vlanid 100 to vlan filter 436 + 437 + 10) 438 + // Map skb->priority to L2 prio for Eth0.100, one to one 439 + $ ip link set eth0.100 type vlan \ 440 + egress 0:0 1:1 2:2 3:3 4:4 5:5 6:6 7:7 441 + 442 + 11) 443 + // Check egress map for vlan 100 444 + $ cat /proc/net/vlan/eth0.100 445 + [...] 446 + INGRESS priority mappings: 0:0 1:0 2:0 3:0 4:0 5:0 6:0 7:0 447 + EGRESS priority mappings: 0:0 1:1 2:2 3:3 4:4 5:5 6:6 7:7 448 + 449 + 12) 450 + // Map skb->priority to traffic class for Eth1: 451 + // 3pri -> tc0, 2pri -> tc1, (0,1,4-7)pri -> tc2 452 + // Map traffic class to transmit queue: 453 + // tc0 -> txq2, tc1 -> txq3, tc2 -> (txq6, txq7) 454 + $ tc qdisc replace dev eth1 handle 100: parent root mqprio num_tc 3 \ 455 + map 2 2 1 0 2 2 2 2 2 2 2 2 2 2 2 2 queues 1@2 1@3 2@6 hw 1 456 + 457 + 13) 458 + // Check classes settings 459 + $ tc -g class show dev eth1 460 + +---(100:ffe2) mqprio 461 + | +---(100:7) mqprio 462 + | +---(100:8) mqprio 463 + | 464 + +---(100:ffe1) mqprio 465 + | +---(100:4) mqprio 466 + | 467 + +---(100:ffe0) mqprio 468 + +---(100:3) mqprio 469 + 470 + 14) 471 + // Set rate for class A - 31 Mbit (tc0, txq2) using CBS Qdisc for Eth1 472 + // here only idle slope is important, others ignored 473 + // Set it +1 Mb for reserve (important!) 474 + $ tc qdisc add dev eth1 parent 100:3 cbs locredit -1453 \ 475 + hicredit 47 sendslope -969000 idleslope 31000 offload 1 476 + net eth1: set FIFO3 bw = 31 477 + 478 + 15) 479 + // Set rate for class B - 11 Mbit (tc1, txq3) using CBS Qdisc for Eth1 480 + // Set it +1 Mb for reserve (important!) 481 + $ tc qdisc add dev eth1 parent 100:4 cbs locredit -1483 \ 482 + hicredit 34 sendslope -989000 idleslope 11000 offload 1 483 + net eth1: set FIFO2 bw = 11 484 + 485 + 16) 486 + // Create vlan 100 to map sk->priority to vlan qos for Eth1 487 + $ ip link add link eth1 name eth1.100 type vlan id 100 488 + net eth1: Adding vlanid 100 to vlan filter 489 + 490 + 17) 491 + // Map skb->priority to L2 prio for Eth1.100, one to one 492 + $ ip link set eth1.100 type vlan \ 493 + egress 0:0 1:1 2:2 3:3 4:4 5:5 6:6 7:7 494 + 495 + 18) 496 + // Check egress map for vlan 100 497 + $ cat /proc/net/vlan/eth1.100 498 + [...] 499 + INGRESS priority mappings: 0:0 1:0 2:0 3:0 4:0 5:0 6:0 7:0 500 + EGRESS priority mappings: 0:0 1:1 2:2 3:3 4:4 5:5 6:6 7:7 501 + 502 + 19) 503 + // Run appropriate tools with socket option "SO_PRIORITY" to 3 504 + // for class A and to 2 for class B. For both interfaces 505 + ./tsn_talker -d 18:03:73:66:87:42 -i eth0.100 -p2 -s 1500& 506 + ./tsn_talker -d 18:03:73:66:87:42 -i eth0.100 -p3 -s 1500& 507 + ./tsn_talker -d 20:cf:30:85:7d:fd -i eth1.100 -p2 -s 1500& 508 + ./tsn_talker -d 20:cf:30:85:7d:fd -i eth1.100 -p3 -s 1500& 509 + 510 + 20) 511 + // run your listener on workstation (should be in same vlan) 512 + // (I took at https://www.spinics.net/lists/netdev/msg460869.html) 513 + ./tsn_listener -d 18:03:73:66:87:42 -i enp5s0 -s 1500 514 + Receiving data rate: 39012 kbps 515 + Receiving data rate: 39012 kbps 516 + Receiving data rate: 39012 kbps 517 + Receiving data rate: 39012 kbps 518 + Receiving data rate: 39012 kbps 519 + Receiving data rate: 39012 kbps 520 + Receiving data rate: 39012 kbps 521 + Receiving data rate: 39012 kbps 522 + Receiving data rate: 39012 kbps 523 + Receiving data rate: 39012 kbps 524 + Receiving data rate: 39012 kbps 525 + Receiving data rate: 39012 kbps 526 + Receiving data rate: 39000 kbps 527 + 528 + 21) 529 + // Restore default configuration if needed 530 + $ ip link del eth1.100 531 + $ ip link del eth0.100 532 + $ tc qdisc del dev eth1 root 533 + net eth1: Prev FIFO2 is shaped 534 + net eth1: set FIFO3 bw = 0 535 + net eth1: set FIFO2 bw = 0 536 + $ tc qdisc del dev eth0 root 537 + net eth0: Prev FIFO2 is shaped 538 + net eth0: set FIFO3 bw = 0 539 + net eth0: set FIFO2 bw = 0 540 + $ ethtool -L eth0 rx 1 tx 1
+358 -6
drivers/net/ethernet/ti/cpsw.c
··· 39 39 #include <linux/sys_soc.h> 40 40 41 41 #include <linux/pinctrl/consumer.h> 42 + #include <net/pkt_cls.h> 42 43 43 44 #include "cpsw.h" 44 45 #include "cpsw_ale.h" 45 46 #include "cpts.h" 46 47 #include "davinci_cpdma.h" 48 + 49 + #include <net/pkt_sched.h> 47 50 48 51 #define CPSW_DEBUG (NETIF_MSG_HW | NETIF_MSG_WOL | \ 49 52 NETIF_MSG_DRV | NETIF_MSG_LINK | \ ··· 156 153 #define IRQ_NUM 2 157 154 #define CPSW_MAX_QUEUES 8 158 155 #define CPSW_CPDMA_DESCS_POOL_SIZE_DEFAULT 256 156 + #define CPSW_FIFO_QUEUE_TYPE_SHIFT 16 157 + #define CPSW_FIFO_SHAPE_EN_SHIFT 16 158 + #define CPSW_FIFO_RATE_EN_SHIFT 20 159 + #define CPSW_TC_NUM 4 160 + #define CPSW_FIFO_SHAPERS_NUM (CPSW_TC_NUM - 1) 161 + #define CPSW_PCT_MASK 0x7f 159 162 160 163 #define CPSW_RX_VLAN_ENCAP_HDR_PRIO_SHIFT 29 161 164 #define CPSW_RX_VLAN_ENCAP_HDR_PRIO_MSK GENMASK(2, 0) ··· 463 454 u8 mac_addr[ETH_ALEN]; 464 455 bool rx_pause; 465 456 bool tx_pause; 457 + bool mqprio_hw; 458 + int fifo_bw[CPSW_TC_NUM]; 459 + int shp_cfg_speed; 466 460 u32 emac_port; 467 461 struct cpsw_common *cpsw; 468 462 }; ··· 980 968 981 969 /* process every unprocessed channel */ 982 970 ch_map = cpdma_ctrl_txchs_state(cpsw->dma); 983 - for (ch = 0, num_tx = 0; ch_map; ch_map >>= 1, ch++) { 984 - if (!(ch_map & 0x01)) 971 + for (ch = 0, num_tx = 0; ch_map & 0xff; ch_map <<= 1, ch++) { 972 + if (!(ch_map & 0x80)) 985 973 continue; 986 974 987 975 txv = &cpsw->txv[ch]; ··· 1090 1078 slave_write(slave, mac_lo(priv->mac_addr), SA_LO); 1091 1079 } 1092 1080 1081 + static bool cpsw_shp_is_off(struct cpsw_priv *priv) 1082 + { 1083 + struct cpsw_common *cpsw = priv->cpsw; 1084 + struct cpsw_slave *slave; 1085 + u32 shift, mask, val; 1086 + 1087 + val = readl_relaxed(&cpsw->regs->ptype); 1088 + 1089 + slave = &cpsw->slaves[cpsw_slave_index(cpsw, priv)]; 1090 + shift = CPSW_FIFO_SHAPE_EN_SHIFT + 3 * slave->slave_num; 1091 + mask = 7 << shift; 1092 + val = val & mask; 1093 + 1094 + return !val; 1095 + } 1096 + 1097 + static void cpsw_fifo_shp_on(struct cpsw_priv *priv, int fifo, int on) 1098 + { 1099 + struct cpsw_common *cpsw = priv->cpsw; 1100 + struct cpsw_slave *slave; 1101 + u32 shift, mask, val; 1102 + 1103 + val = readl_relaxed(&cpsw->regs->ptype); 1104 + 1105 + slave = &cpsw->slaves[cpsw_slave_index(cpsw, priv)]; 1106 + shift = CPSW_FIFO_SHAPE_EN_SHIFT + 3 * slave->slave_num; 1107 + mask = (1 << --fifo) << shift; 1108 + val = on ? val | mask : val & ~mask; 1109 + 1110 + writel_relaxed(val, &cpsw->regs->ptype); 1111 + } 1112 + 1093 1113 static void _cpsw_adjust_link(struct cpsw_slave *slave, 1094 1114 struct cpsw_priv *priv, bool *link) 1095 1115 { ··· 1161 1117 mac_control |= BIT(4); 1162 1118 1163 1119 *link = true; 1120 + 1121 + if (priv->shp_cfg_speed && 1122 + priv->shp_cfg_speed != slave->phy->speed && 1123 + !cpsw_shp_is_off(priv)) 1124 + dev_warn(priv->dev, 1125 + "Speed was changed, CBS shaper speeds are changed!"); 1164 1126 } else { 1165 1127 mac_control = 0; 1166 1128 /* disable forwarding */ ··· 1628 1578 soft_reset_slave(slave); 1629 1579 } 1630 1580 1581 + static int cpsw_tc_to_fifo(int tc, int num_tc) 1582 + { 1583 + if (tc == num_tc - 1) 1584 + return 0; 1585 + 1586 + return CPSW_FIFO_SHAPERS_NUM - tc; 1587 + } 1588 + 1589 + static int cpsw_set_fifo_bw(struct cpsw_priv *priv, int fifo, int bw) 1590 + { 1591 + struct cpsw_common *cpsw = priv->cpsw; 1592 + u32 val = 0, send_pct, shift; 1593 + struct cpsw_slave *slave; 1594 + int pct = 0, i; 1595 + 1596 + if (bw > priv->shp_cfg_speed * 1000) 1597 + goto err; 1598 + 1599 + /* shaping has to stay enabled for highest fifos linearly 1600 + * and fifo bw no more then interface can allow 1601 + */ 1602 + slave = &cpsw->slaves[cpsw_slave_index(cpsw, priv)]; 1603 + send_pct = slave_read(slave, SEND_PERCENT); 1604 + for (i = CPSW_FIFO_SHAPERS_NUM; i > 0; i--) { 1605 + if (!bw) { 1606 + if (i >= fifo || !priv->fifo_bw[i]) 1607 + continue; 1608 + 1609 + dev_warn(priv->dev, "Prev FIFO%d is shaped", i); 1610 + continue; 1611 + } 1612 + 1613 + if (!priv->fifo_bw[i] && i > fifo) { 1614 + dev_err(priv->dev, "Upper FIFO%d is not shaped", i); 1615 + return -EINVAL; 1616 + } 1617 + 1618 + shift = (i - 1) * 8; 1619 + if (i == fifo) { 1620 + send_pct &= ~(CPSW_PCT_MASK << shift); 1621 + val = DIV_ROUND_UP(bw, priv->shp_cfg_speed * 10); 1622 + if (!val) 1623 + val = 1; 1624 + 1625 + send_pct |= val << shift; 1626 + pct += val; 1627 + continue; 1628 + } 1629 + 1630 + if (priv->fifo_bw[i]) 1631 + pct += (send_pct >> shift) & CPSW_PCT_MASK; 1632 + } 1633 + 1634 + if (pct >= 100) 1635 + goto err; 1636 + 1637 + slave_write(slave, send_pct, SEND_PERCENT); 1638 + priv->fifo_bw[fifo] = bw; 1639 + 1640 + dev_warn(priv->dev, "set FIFO%d bw = %d\n", fifo, 1641 + DIV_ROUND_CLOSEST(val * priv->shp_cfg_speed, 100)); 1642 + 1643 + return 0; 1644 + err: 1645 + dev_err(priv->dev, "Bandwidth doesn't fit in tc configuration"); 1646 + return -EINVAL; 1647 + } 1648 + 1649 + static int cpsw_set_fifo_rlimit(struct cpsw_priv *priv, int fifo, int bw) 1650 + { 1651 + struct cpsw_common *cpsw = priv->cpsw; 1652 + struct cpsw_slave *slave; 1653 + u32 tx_in_ctl_rg, val; 1654 + int ret; 1655 + 1656 + ret = cpsw_set_fifo_bw(priv, fifo, bw); 1657 + if (ret) 1658 + return ret; 1659 + 1660 + slave = &cpsw->slaves[cpsw_slave_index(cpsw, priv)]; 1661 + tx_in_ctl_rg = cpsw->version == CPSW_VERSION_1 ? 1662 + CPSW1_TX_IN_CTL : CPSW2_TX_IN_CTL; 1663 + 1664 + if (!bw) 1665 + cpsw_fifo_shp_on(priv, fifo, bw); 1666 + 1667 + val = slave_read(slave, tx_in_ctl_rg); 1668 + if (cpsw_shp_is_off(priv)) { 1669 + /* disable FIFOs rate limited queues */ 1670 + val &= ~(0xf << CPSW_FIFO_RATE_EN_SHIFT); 1671 + 1672 + /* set type of FIFO queues to normal priority mode */ 1673 + val &= ~(3 << CPSW_FIFO_QUEUE_TYPE_SHIFT); 1674 + 1675 + /* set type of FIFO queues to be rate limited */ 1676 + if (bw) 1677 + val |= 2 << CPSW_FIFO_QUEUE_TYPE_SHIFT; 1678 + else 1679 + priv->shp_cfg_speed = 0; 1680 + } 1681 + 1682 + /* toggle a FIFO rate limited queue */ 1683 + if (bw) 1684 + val |= BIT(fifo + CPSW_FIFO_RATE_EN_SHIFT); 1685 + else 1686 + val &= ~BIT(fifo + CPSW_FIFO_RATE_EN_SHIFT); 1687 + slave_write(slave, val, tx_in_ctl_rg); 1688 + 1689 + /* FIFO transmit shape enable */ 1690 + cpsw_fifo_shp_on(priv, fifo, bw); 1691 + return 0; 1692 + } 1693 + 1694 + /* Defaults: 1695 + * class A - prio 3 1696 + * class B - prio 2 1697 + * shaping for class A should be set first 1698 + */ 1699 + static int cpsw_set_cbs(struct net_device *ndev, 1700 + struct tc_cbs_qopt_offload *qopt) 1701 + { 1702 + struct cpsw_priv *priv = netdev_priv(ndev); 1703 + struct cpsw_common *cpsw = priv->cpsw; 1704 + struct cpsw_slave *slave; 1705 + int prev_speed = 0; 1706 + int tc, ret, fifo; 1707 + u32 bw = 0; 1708 + 1709 + tc = netdev_txq_to_tc(priv->ndev, qopt->queue); 1710 + 1711 + /* enable channels in backward order, as highest FIFOs must be rate 1712 + * limited first and for compliance with CPDMA rate limited channels 1713 + * that also used in bacward order. FIFO0 cannot be rate limited. 1714 + */ 1715 + fifo = cpsw_tc_to_fifo(tc, ndev->num_tc); 1716 + if (!fifo) { 1717 + dev_err(priv->dev, "Last tc%d can't be rate limited", tc); 1718 + return -EINVAL; 1719 + } 1720 + 1721 + /* do nothing, it's disabled anyway */ 1722 + if (!qopt->enable && !priv->fifo_bw[fifo]) 1723 + return 0; 1724 + 1725 + /* shapers can be set if link speed is known */ 1726 + slave = &cpsw->slaves[cpsw_slave_index(cpsw, priv)]; 1727 + if (slave->phy && slave->phy->link) { 1728 + if (priv->shp_cfg_speed && 1729 + priv->shp_cfg_speed != slave->phy->speed) 1730 + prev_speed = priv->shp_cfg_speed; 1731 + 1732 + priv->shp_cfg_speed = slave->phy->speed; 1733 + } 1734 + 1735 + if (!priv->shp_cfg_speed) { 1736 + dev_err(priv->dev, "Link speed is not known"); 1737 + return -1; 1738 + } 1739 + 1740 + ret = pm_runtime_get_sync(cpsw->dev); 1741 + if (ret < 0) { 1742 + pm_runtime_put_noidle(cpsw->dev); 1743 + return ret; 1744 + } 1745 + 1746 + bw = qopt->enable ? qopt->idleslope : 0; 1747 + ret = cpsw_set_fifo_rlimit(priv, fifo, bw); 1748 + if (ret) { 1749 + priv->shp_cfg_speed = prev_speed; 1750 + prev_speed = 0; 1751 + } 1752 + 1753 + if (bw && prev_speed) 1754 + dev_warn(priv->dev, 1755 + "Speed was changed, CBS shaper speeds are changed!"); 1756 + 1757 + pm_runtime_put_sync(cpsw->dev); 1758 + return ret; 1759 + } 1760 + 1761 + static void cpsw_cbs_resume(struct cpsw_slave *slave, struct cpsw_priv *priv) 1762 + { 1763 + int fifo, bw; 1764 + 1765 + for (fifo = CPSW_FIFO_SHAPERS_NUM; fifo > 0; fifo--) { 1766 + bw = priv->fifo_bw[fifo]; 1767 + if (!bw) 1768 + continue; 1769 + 1770 + cpsw_set_fifo_rlimit(priv, fifo, bw); 1771 + } 1772 + } 1773 + 1774 + static void cpsw_mqprio_resume(struct cpsw_slave *slave, struct cpsw_priv *priv) 1775 + { 1776 + struct cpsw_common *cpsw = priv->cpsw; 1777 + u32 tx_prio_map = 0; 1778 + int i, tc, fifo; 1779 + u32 tx_prio_rg; 1780 + 1781 + if (!priv->mqprio_hw) 1782 + return; 1783 + 1784 + for (i = 0; i < 8; i++) { 1785 + tc = netdev_get_prio_tc_map(priv->ndev, i); 1786 + fifo = CPSW_FIFO_SHAPERS_NUM - tc; 1787 + tx_prio_map |= fifo << (4 * i); 1788 + } 1789 + 1790 + tx_prio_rg = cpsw->version == CPSW_VERSION_1 ? 1791 + CPSW1_TX_PRI_MAP : CPSW2_TX_PRI_MAP; 1792 + 1793 + slave_write(slave, tx_prio_map, tx_prio_rg); 1794 + } 1795 + 1796 + /* restore resources after port reset */ 1797 + static void cpsw_restore(struct cpsw_priv *priv) 1798 + { 1799 + /* restore MQPRIO offload */ 1800 + for_each_slave(priv, cpsw_mqprio_resume, priv); 1801 + 1802 + /* restore CBS offload */ 1803 + for_each_slave(priv, cpsw_cbs_resume, priv); 1804 + } 1805 + 1631 1806 static int cpsw_ndo_open(struct net_device *ndev) 1632 1807 { 1633 1808 struct cpsw_priv *priv = netdev_priv(ndev); ··· 1931 1656 dev_err(priv->dev, "error registering cpts device\n"); 1932 1657 1933 1658 } 1659 + 1660 + cpsw_restore(priv); 1934 1661 1935 1662 /* Enable Interrupt pacing if configured */ 1936 1663 if (cpsw->coal_intvl != 0) { ··· 2468 2191 return ret; 2469 2192 } 2470 2193 2194 + static int cpsw_set_mqprio(struct net_device *ndev, void *type_data) 2195 + { 2196 + struct tc_mqprio_qopt_offload *mqprio = type_data; 2197 + struct cpsw_priv *priv = netdev_priv(ndev); 2198 + struct cpsw_common *cpsw = priv->cpsw; 2199 + int fifo, num_tc, count, offset; 2200 + struct cpsw_slave *slave; 2201 + u32 tx_prio_map = 0; 2202 + int i, tc, ret; 2203 + 2204 + num_tc = mqprio->qopt.num_tc; 2205 + if (num_tc > CPSW_TC_NUM) 2206 + return -EINVAL; 2207 + 2208 + if (mqprio->mode != TC_MQPRIO_MODE_DCB) 2209 + return -EINVAL; 2210 + 2211 + ret = pm_runtime_get_sync(cpsw->dev); 2212 + if (ret < 0) { 2213 + pm_runtime_put_noidle(cpsw->dev); 2214 + return ret; 2215 + } 2216 + 2217 + if (num_tc) { 2218 + for (i = 0; i < 8; i++) { 2219 + tc = mqprio->qopt.prio_tc_map[i]; 2220 + fifo = cpsw_tc_to_fifo(tc, num_tc); 2221 + tx_prio_map |= fifo << (4 * i); 2222 + } 2223 + 2224 + netdev_set_num_tc(ndev, num_tc); 2225 + for (i = 0; i < num_tc; i++) { 2226 + count = mqprio->qopt.count[i]; 2227 + offset = mqprio->qopt.offset[i]; 2228 + netdev_set_tc_queue(ndev, i, count, offset); 2229 + } 2230 + } 2231 + 2232 + if (!mqprio->qopt.hw) { 2233 + /* restore default configuration */ 2234 + netdev_reset_tc(ndev); 2235 + tx_prio_map = TX_PRIORITY_MAPPING; 2236 + } 2237 + 2238 + priv->mqprio_hw = mqprio->qopt.hw; 2239 + 2240 + offset = cpsw->version == CPSW_VERSION_1 ? 2241 + CPSW1_TX_PRI_MAP : CPSW2_TX_PRI_MAP; 2242 + 2243 + slave = &cpsw->slaves[cpsw_slave_index(cpsw, priv)]; 2244 + slave_write(slave, tx_prio_map, offset); 2245 + 2246 + pm_runtime_put_sync(cpsw->dev); 2247 + 2248 + return 0; 2249 + } 2250 + 2251 + static int cpsw_ndo_setup_tc(struct net_device *ndev, enum tc_setup_type type, 2252 + void *type_data) 2253 + { 2254 + switch (type) { 2255 + case TC_SETUP_QDISC_CBS: 2256 + return cpsw_set_cbs(ndev, type_data); 2257 + 2258 + case TC_SETUP_QDISC_MQPRIO: 2259 + return cpsw_set_mqprio(ndev, type_data); 2260 + 2261 + default: 2262 + return -EOPNOTSUPP; 2263 + } 2264 + } 2265 + 2471 2266 static const struct net_device_ops cpsw_netdev_ops = { 2472 2267 .ndo_open = cpsw_ndo_open, 2473 2268 .ndo_stop = cpsw_ndo_stop, ··· 2555 2206 #endif 2556 2207 .ndo_vlan_rx_add_vid = cpsw_ndo_vlan_rx_add_vid, 2557 2208 .ndo_vlan_rx_kill_vid = cpsw_ndo_vlan_rx_kill_vid, 2209 + .ndo_setup_tc = cpsw_ndo_setup_tc, 2558 2210 }; 2559 2211 2560 2212 static int cpsw_get_regs_len(struct net_device *ndev) ··· 2782 2432 void (*handler)(void *, int, int); 2783 2433 struct netdev_queue *queue; 2784 2434 struct cpsw_vector *vec; 2785 - int ret, *ch; 2435 + int ret, *ch, vch; 2786 2436 2787 2437 if (rx) { 2788 2438 ch = &cpsw->rx_ch_num; ··· 2795 2445 } 2796 2446 2797 2447 while (*ch < ch_num) { 2798 - vec[*ch].ch = cpdma_chan_create(cpsw->dma, *ch, handler, rx); 2448 + vch = rx ? *ch : 7 - *ch; 2449 + vec[*ch].ch = cpdma_chan_create(cpsw->dma, vch, handler, rx); 2799 2450 queue = netdev_get_tx_queue(priv->ndev, *ch); 2800 2451 queue->tx_maxrate = 0; 2801 2452 ··· 3333 2982 u32 slave_offset, sliver_offset, slave_size; 3334 2983 const struct soc_device_attribute *soc; 3335 2984 struct cpsw_common *cpsw; 3336 - int ret = 0, i; 2985 + int ret = 0, i, ch; 3337 2986 int irq; 3338 2987 3339 2988 cpsw = devm_kzalloc(&pdev->dev, sizeof(struct cpsw_common), GFP_KERNEL); ··· 3508 3157 if (soc) 3509 3158 cpsw->quirk_irq = 1; 3510 3159 3511 - cpsw->txv[0].ch = cpdma_chan_create(cpsw->dma, 0, cpsw_tx_handler, 0); 3160 + ch = cpsw->quirk_irq ? 0 : 7; 3161 + cpsw->txv[0].ch = cpdma_chan_create(cpsw->dma, ch, cpsw_tx_handler, 0); 3512 3162 if (IS_ERR(cpsw->txv[0].ch)) { 3513 3163 dev_err(priv->dev, "error initializing tx dma channel\n"); 3514 3164 ret = PTR_ERR(cpsw->txv[0].ch);
+15 -16
drivers/net/ethernet/ti/davinci_cpdma.c
··· 406 406 struct cpdma_chan *chan; 407 407 u32 old_rate = ch->rate; 408 408 u32 new_rmask = 0; 409 - int rlim = 1; 409 + int rlim = 0; 410 410 int i; 411 411 412 - *prio_mode = 0; 413 412 for (i = tx_chan_num(0); i < tx_chan_num(CPDMA_MAX_CHANNELS); i++) { 414 413 chan = ctlr->channels[i]; 415 - if (!chan) { 416 - rlim = 0; 414 + if (!chan) 417 415 continue; 418 - } 419 416 420 417 if (chan == ch) 421 418 chan->rate = rate; 422 419 423 420 if (chan->rate) { 424 - if (rlim) { 425 - new_rmask |= chan->mask; 426 - } else { 427 - ch->rate = old_rate; 428 - dev_err(ctlr->dev, "Prev channel of %dch is not rate limited\n", 429 - chan->chan_num); 430 - return -EINVAL; 431 - } 432 - } else { 433 - *prio_mode = 1; 434 - rlim = 0; 421 + rlim = 1; 422 + new_rmask |= chan->mask; 423 + continue; 435 424 } 425 + 426 + if (rlim) 427 + goto err; 436 428 } 437 429 438 430 *rmask = new_rmask; 431 + *prio_mode = rlim; 439 432 return 0; 433 + 434 + err: 435 + ch->rate = old_rate; 436 + dev_err(ctlr->dev, "Upper cpdma ch%d is not rate limited\n", 437 + chan->chan_num); 438 + return -EINVAL; 440 439 } 441 440 442 441 static u32 cpdma_chan_set_factors(struct cpdma_ctlr *ctlr,