* RE: MY NAME IS MRS BELLA YOSTIN MOHAMMAD
From: Mrs Bella Yostin Mohammad @ 2018-07-21 15:44 UTC (permalink / raw)
Hello Dear.
My Name is Mrs. Bella Yostin Mohammad, I got your contact from a
business directory search and I decided to contact you directly. well
am originally from South Africa, but based in London, i am searching
for a reliable and honest and understanding person to go into
partnership in investing or to guide me in setting up a lucrative
business in the Middle east countries or the Arab countries,UAE or
OMAN and Kuwait, my plan is for my Son to fly to your country to meet
with you for the discussion and process of the investment.
So am only soliciting for your guidance for partnership or to help me
in investing in any lucrative business if you are interested.
My Idea of business is to invest into Tourism business or Medical
business or Real Estates business, this is my plan and i will be happy
if you will help in explaining more of either of this business which
is better for me to invest into in your country.all i want is to
invest into a good business that will bring higher profit.
like i explained above my plan is to send my Son down to meet with you
so both of you will meet face to face and discuss more so we will know
how to go about the process for the investment..
If you are willing to assist you will never regret assisting i and my son.
mean why if you are interested reply back to me with your mobile
number so that you and my son can discuss more in details.
And also for my Son to make his arrangement to fly down to your
country to meet with you over discussing about the investment.
I look forward for your reply.
Thanks with regards
Mrs. Bella Yostin Mohammad
^ permalink raw reply
* Re: [PATCH v4 net-next 6/6] Documentation: networking: cpsw: add MQPRIO & CBS offload examples
From: Ivan Khoronzhuk @ 2018-07-21 16:46 UTC (permalink / raw)
To: Richard Cochran
Cc: davem, grygorii.strashko, corbet, akpm, netdev, linux-doc,
linux-kernel, linux-omap, vinicius.gomes, henrik,
jesus.sanchez-palencia, ilias.apalodimas, p-varis, spatton,
francois.ozog, yogeshs, nsekhar, andrew
In-Reply-To: <20180721151028.fxjlxordxpsiohwo@localhost>
On Sat, Jul 21, 2018 at 08:10:29AM -0700, Richard Cochran wrote:
>On Sat, Jul 21, 2018 at 02:59:23PM +0300, Ivan Khoronzhuk wrote:
>> This document describes MQPRIO and CBS Qdisc offload configuration
>> for cpsw driver based on examples. It potentially can be used in
>> audio video bridging (AVB) and time sensitive networking (TSN).
>>
>> Reviewed-by: Grygorii Strashko <grygorii.strashko@ti.com>
>> Signed-off-by: Ivan Khoronzhuk <ivan.khoronzhuk@linaro.org>
>> ---
>> Documentation/networking/ti-cpsw.txt | 540 +++++++++++++++++++++++++++
>> 1 file changed, 540 insertions(+)
>> create mode 100644 Documentation/networking/ti-cpsw.txt
>>
>> diff --git a/Documentation/networking/ti-cpsw.txt b/Documentation/networking/ti-cpsw.txt
>> new file mode 100644
>> index 000000000000..1e840346cae1
>> --- /dev/null
>> +++ b/Documentation/networking/ti-cpsw.txt
>> @@ -0,0 +1,540 @@
>> +* Texas Instruments CPSW ethernet driver
>> +
>> +Multiqueue & CBS & MQPRIO
>> +=====================================================================
>> +=====================================================================
>> +
>> +The cpsw has 3 CBS shapers for each external ports. This document
>> +describes MQPRIO and CBS Qdisc offload configuration for cpsw driver
>> +based on examples. It potentially can be used in audio video bridging
>> +(AVB) and time sensitive networking (TSN).
>> +
>> +The following examples was tested on AM572x EVM and BBB boards.
>> +
>> +Test setup
>> +==========
>> +
>> +Under consideration two examples with AM52xx EVM running cpsw driver
>> +in dual_emac mode.
>
>s/AM52xx/AM572x ?
yes, AM572x
>
>Also, there are more mentions of AM52xx, below.
I'll correct.
>
>Thanks,
>Richard
>
>
>> +
>> +Several prerequisites:
>> +- TX queues must be rated starting from txq0 that has highest priority
>> +- Traffic classes are used starting from 0, that has highest priority
>> +- CBS shapers should be used with rated queues
>> +- The bandwidth for CBS shapers has to be set a little bit more then
>> + potential incoming rate, thus, rate of all incoming tx queues has
>> + to be a little less
>> +- Real rates can differ, due to discreetness
>> +- Map skb-priority to txq is not enough, also skb-priority to l2 prio
>> + map has to be created with ip or vconfig tool
>> +- Any l2/socket prio (0 - 7) for classes can be used, but for
>> + simplicity default values are used: 3 and 2
>> +- only 2 classes tested: A and B, but checked and can work with more,
>> + maximum allowed 4, but only for 3 rate can be set.
>> +
>> +Test setup for examples
>> +=======================
>> + +-------------------------------+
>> + |--+ |
>> + | | Workstation0 |
>> + |E | MAC 18:03:73:66:87:42 |
>> ++-----------------------------+ +--|t | |
>> +| | 1 | E | | |h |./tsn_listener -d \ |
>> +| Target board: | 0 | t |--+ |0 | 18:03:73:66:87:42 -i eth0 \|
>> +| AM572x EVM | 0 | h | | | -s 1500 |
>> +| | 0 | 0 | |--+ |
>> +| Only 2 classes: |Mb +---| +-------------------------------+
>> +| class A, class B | |
>> +| | +---| +-------------------------------+
>> +| | 1 | E | |--+ |
>> +| | 0 | t | | | Workstation1 |
>> +| | 0 | h |--+ |E | MAC 20:cf:30:85:7d:fd |
>> +| |Mb | 1 | +--|t | |
>> ++-----------------------------+ |h |./tsn_listener -d \ |
>> + |0 | 20:cf:30:85:7d:fd -i eth0 \|
>> + | | -s 1500 |
>> + |--+ |
>> + +-------------------------------+
>> +
>> +*********************************************************************
>> +*********************************************************************
>> +*********************************************************************
>> +Example 1: One port tx AVB configuration scheme for target board
>> +----------------------------------------------------------------------
>> +(prints and scheme for AM52xx evm, applicable for single port boards)
>> +
>> +tc - traffic class
>> +txq - transmit queue
>> +p - priority
>> +f - fifo (cpsw fifo)
>> +S - shaper configured
>> +
>> ++------------------------------------------------------------------+ u
>> +| +---------------+ +---------------+ +------+ +------+ | s
>> +| | | | | | | | | | e
>> +| | App 1 | | App 2 | | Apps | | Apps | | r
>> +| | Class A | | Class B | | Rest | | Rest | |
>> +| | Eth0 | | Eth0 | | Eth0 | | Eth1 | | s
>> +| | VLAN100 | | VLAN100 | | | | | | | | p
>> +| | 40 Mb/s | | 20 Mb/s | | | | | | | | a
>> +| | SO_PRIORITY=3 | | SO_PRIORITY=2 | | | | | | | | c
>> +| | | | | | | | | | | | | | e
>> +| +---|-----------+ +---|-----------+ +---|--+ +---|--+ |
>> ++-----|------------------|------------------|--------|-------------+
>> + +-+ +------------+ | |
>> + | | +-----------------+ +--+
>> + | | | |
>> ++---|-------|-------------|-----------------------|----------------+
>> +| +----+ +----+ +----+ +----+ +----+ |
>> +| | p3 | | p2 | | p1 | | p0 | | p0 | | k
>> +| \ / \ / \ / \ / \ / | e
>> +| \ / \ / \ / \ / \ / | r
>> +| \/ \/ \/ \/ \/ | n
>> +| | | | | | e
>> +| | | +-----+ | | l
>> +| | | | | |
>> +| +----+ +----+ +----+ +----+ | s
>> +| |tc0 | |tc1 | |tc2 | |tc0 | | p
>> +| \ / \ / \ / \ / | a
>> +| \ / \ / \ / \ / | c
>> +| \/ \/ \/ \/ | e
>> +| | | +-----+ | |
>> +| | | | | | |
>> +| | | | | | |
>> +| | | | | | |
>> +| +----+ +----+ +----+ +----+ +----+ |
>> +| |txq0| |txq1| |txq2| |txq3| |txq4| |
>> +| \ / \ / \ / \ / \ / |
>> +| \ / \ / \ / \ / \ / |
>> +| \/ \/ \/ \/ \/ |
>> +| +-|------|------|------|--+ +--|--------------+ |
>> +| | | | | | | Eth0.100 | | Eth1 | |
>> ++---|------|------|------|------------------------|----------------+
>> + | | | | |
>> + p p p p |
>> + 3 2 0-1, 4-7 <- L2 priority |
>> + | | | | |
>> + | | | | |
>> ++---|------|------|------|------------------------|----------------+
>> +| | | | | |----------+ |
>> +| +----+ +----+ +----+ +----+ +----+ |
>> +| |dma7| |dma6| |dma5| |dma4| |dma3| |
>> +| \ / \ / \ / \ / \ / | c
>> +| \S / \S / \ / \ / \ / | p
>> +| \/ \/ \/ \/ \/ | s
>> +| | | | +----- | | w
>> +| | | | | | |
>> +| | | | | | | d
>> +| +----+ +----+ +----+p p+----+ | r
>> +| | | | | | |o o| | | i
>> +| | f3 | | f2 | | f0 |r r| f0 | | v
>> +| |tc0 | |tc1 | |tc2 |t t|tc0 | | e
>> +| \CBS / \CBS / \CBS /1 2\CBS / | r
>> +| \S / \S / \ / \ / |
>> +| \/ \/ \/ \/ |
>> ++------------------------------------------------------------------+
>> +========================================Eth==========================>
>> +
>> +1)
>> +// Add 4 tx queues, for interface Eth0, and 1 tx queue for Eth1
>> +$ ethtool -L eth0 rx 1 tx 5
>> +rx unmodified, ignoring
>> +
>> +2)
>> +// Check if num of queues is set correctly:
>> +$ ethtool -l eth0
>> +Channel parameters for eth0:
>> +Pre-set maximums:
>> +RX: 8
>> +TX: 8
>> +Other: 0
>> +Combined: 0
>> +Current hardware settings:
>> +RX: 1
>> +TX: 5
>> +Other: 0
>> +Combined: 0
>> +
>> +3)
>> +// TX queues must be rated starting from 0, so set bws for tx0 and tx1
>> +// Set rates 40 and 20 Mb/s appropriately.
>> +// Pay attention, real speed can differ a bit due to discreetness.
>> +// Leave last 2 tx queues not rated.
>> +$ echo 40 > /sys/class/net/eth0/queues/tx-0/tx_maxrate
>> +$ echo 20 > /sys/class/net/eth0/queues/tx-1/tx_maxrate
>> +
>> +4)
>> +// Check maximum rate of tx (cpdma) queues:
>> +$ cat /sys/class/net/eth0/queues/tx-*/tx_maxrate
>> +40
>> +20
>> +0
>> +0
>> +0
>> +
>> +5)
>> +// Map skb->priority to traffic class:
>> +// 3pri -> tc0, 2pri -> tc1, (0,1,4-7)pri -> tc2
>> +// Map traffic class to transmit queue:
>> +// tc0 -> txq0, tc1 -> txq1, tc2 -> (txq2, txq3)
>> +$ tc qdisc replace dev eth0 handle 100: parent root mqprio num_tc 3 \
>> +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
>> +
>> +5a)
>> +// As two interface sharing same set of tx queues, assign all traffic
>> +// coming to interface Eth1 to separate queue in order to not mix it
>> +// with traffic from interface Eth0, so use separate txq to send
>> +// packets to Eth1, so all prio -> tc0 and tc0 -> txq4
>> +// Here hw 0, so here still default configuration for eth1 in hw
>> +$ tc qdisc replace dev eth1 handle 100: parent root mqprio num_tc 1 \
>> +map 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 queues 1@4 hw 0
>> +
>> +6)
>> +// Check classes settings
>> +$ tc -g class show dev eth0
>> ++---(100:ffe2) mqprio
>> +| +---(100:3) mqprio
>> +| +---(100:4) mqprio
>> +|
>> ++---(100:ffe1) mqprio
>> +| +---(100:2) mqprio
>> +|
>> ++---(100:ffe0) mqprio
>> + +---(100:1) mqprio
>> +
>> +$ tc -g class show dev eth1
>> ++---(100:ffe0) mqprio
>> + +---(100:5) mqprio
>> +
>> +7)
>> +// Set rate for class A - 41 Mbit (tc0, txq0) using CBS Qdisc
>> +// Set it +1 Mb for reserve (important!)
>> +// here only idle slope is important, others arg are ignored
>> +// Pay attention, real speed can differ a bit due to discreetness
>> +$ tc qdisc add dev eth0 parent 100:1 cbs locredit -1438 \
>> +hicredit 62 sendslope -959000 idleslope 41000 offload 1
>> +net eth0: set FIFO3 bw = 50
>> +
>> +8)
>> +// Set rate for class B - 21 Mbit (tc1, txq1) using CBS Qdisc:
>> +// Set it +1 Mb for reserve (important!)
>> +$ tc qdisc add dev eth0 parent 100:2 cbs locredit -1468 \
>> +hicredit 65 sendslope -979000 idleslope 21000 offload 1
>> +net eth0: set FIFO2 bw = 30
>> +
>> +9)
>> +// Create vlan 100 to map sk->priority to vlan qos
>> +$ ip link add link eth0 name eth0.100 type vlan id 100
>> +8021q: 802.1Q VLAN Support v1.8
>> +8021q: adding VLAN 0 to HW filter on device eth0
>> +8021q: adding VLAN 0 to HW filter on device eth1
>> +net eth0: Adding vlanid 100 to vlan filter
>> +
>> +10)
>> +// Map skb->priority to L2 prio, 1 to 1
>> +$ ip link set eth0.100 type vlan \
>> +egress 0:0 1:1 2:2 3:3 4:4 5:5 6:6 7:7
>> +
>> +11)
>> +// Check egress map for vlan 100
>> +$ cat /proc/net/vlan/eth0.100
>> +[...]
>> +INGRESS priority mappings: 0:0 1:0 2:0 3:0 4:0 5:0 6:0 7:0
>> +EGRESS priority mappings: 0:0 1:1 2:2 3:3 4:4 5:5 6:6 7:7
>> +
>> +12)
>> +// Run your appropriate tools with socket option "SO_PRIORITY"
>> +// to 3 for class A and/or to 2 for class B
>> +// (I took at https://www.spinics.net/lists/netdev/msg460869.html)
>> +./tsn_talker -d 18:03:73:66:87:42 -i eth0.100 -p3 -s 1500&
>> +./tsn_talker -d 18:03:73:66:87:42 -i eth0.100 -p2 -s 1500&
>> +
>> +13)
>> +// run your listener on workstation (should be in same vlan)
>> +// (I took at https://www.spinics.net/lists/netdev/msg460869.html)
>> +./tsn_listener -d 18:03:73:66:87:42 -i enp5s0 -s 1500
>> +Receiving data rate: 39012 kbps
>> +Receiving data rate: 39012 kbps
>> +Receiving data rate: 39012 kbps
>> +Receiving data rate: 39012 kbps
>> +Receiving data rate: 39012 kbps
>> +Receiving data rate: 39012 kbps
>> +Receiving data rate: 39012 kbps
>> +Receiving data rate: 39012 kbps
>> +Receiving data rate: 39012 kbps
>> +Receiving data rate: 39012 kbps
>> +Receiving data rate: 39012 kbps
>> +Receiving data rate: 39012 kbps
>> +Receiving data rate: 39000 kbps
>> +
>> +14)
>> +// Restore default configuration if needed
>> +$ ip link del eth0.100
>> +$ tc qdisc del dev eth1 root
>> +$ tc qdisc del dev eth0 root
>> +net eth0: Prev FIFO2 is shaped
>> +net eth0: set FIFO3 bw = 0
>> +net eth0: set FIFO2 bw = 0
>> +$ ethtool -L eth0 rx 1 tx 1
>> +
>> +*********************************************************************
>> +*********************************************************************
>> +*********************************************************************
>> +Example 2: Two port tx AVB configuration scheme for target board
>> +----------------------------------------------------------------------
>> +(prints and scheme for AM52xx evm, for dual emac boards only)
>> +
>> ++------------------------------------------------------------------+ u
>> +| +----------+ +----------+ +------+ +----------+ +----------+ | s
>> +| | | | | | | | | | | | e
>> +| | App 1 | | App 2 | | Apps | | App 3 | | App 4 | | r
>> +| | Class A | | Class B | | Rest | | Class B | | Class A | |
>> +| | Eth0 | | Eth0 | | | | | Eth1 | | Eth1 | | s
>> +| | VLAN100 | | VLAN100 | | | | | VLAN100 | | VLAN100 | | p
>> +| | 40 Mb/s | | 20 Mb/s | | | | | 10 Mb/s | | 30 Mb/s | | a
>> +| | SO_PRI=3 | | SO_PRI=2 | | | | | SO_PRI=3 | | SO_PRI=2 | | c
>> +| | | | | | | | | | | | | | | | | e
>> +| +---|------+ +---|------+ +---|--+ +---|------+ +---|------+ |
>> ++-----|-------------|-------------|---------|-------------|--------+
>> + +-+ +-------+ | +----------+ +----+
>> + | | +-------+------+ | |
>> + | | | | | |
>> ++---|-------|-------------|--------------|-------------|-------|---+
>> +| +----+ +----+ +----+ +----+ +----+ +----+ +----+ +----+ |
>> +| | p3 | | p2 | | p1 | | p0 | | p0 | | p1 | | p2 | | p3 | | k
>> +| \ / \ / \ / \ / \ / \ / \ / \ / | e
>> +| \ / \ / \ / \ / \ / \ / \ / \ / | r
>> +| \/ \/ \/ \/ \/ \/ \/ \/ | n
>> +| | | | | | | | e
>> +| | | +----+ +----+ | | | l
>> +| | | | | | | |
>> +| +----+ +----+ +----+ +----+ +----+ +----+ | s
>> +| |tc0 | |tc1 | |tc2 | |tc2 | |tc1 | |tc0 | | p
>> +| \ / \ / \ / \ / \ / \ / | a
>> +| \ / \ / \ / \ / \ / \ / | c
>> +| \/ \/ \/ \/ \/ \/ | e
>> +| | | +-----+ +-----+ | | |
>> +| | | | | | | | | |
>> +| | | | | | | | | |
>> +| | | | | E E | | | | |
>> +| +----+ +----+ +----+ +----+ t t +----+ +----+ +----+ +----+ |
>> +| |txq0| |txq1| |txq4| |txq5| h h |txq6| |txq7| |txq3| |txq2| |
>> +| \ / \ / \ / \ / 0 1 \ / \ / \ / \ / |
>> +| \ / \ / \ / \ / . . \ / \ / \ / \ / |
>> +| \/ \/ \/ \/ 1 1 \/ \/ \/ \/ |
>> +| +-|------|------|------|--+ 0 0 +-|------|------|------|--+ |
>> +| | | | | | | 0 0 | | | | | | |
>> ++---|------|------|------|---------------|------|------|------|----+
>> + | | | | | | | |
>> + p p p p p p p p
>> + 3 2 0-1, 4-7 <-L2 pri-> 0-1, 4-7 2 3
>> + | | | | | | | |
>> + | | | | | | | |
>> ++---|------|------|------|---------------|------|------|------|----+
>> +| | | | | | | | | |
>> +| +----+ +----+ +----+ +----+ +----+ +----+ +----+ +----+ |
>> +| |dma7| |dma6| |dma3| |dma2| |dma1| |dma0| |dma4| |dma5| |
>> +| \ / \ / \ / \ / \ / \ / \ / \ / | c
>> +| \S / \S / \ / \ / \ / \ / \S / \S / | p
>> +| \/ \/ \/ \/ \/ \/ \/ \/ | s
>> +| | | | +----- | | | | | w
>> +| | | | | +----+ | | | |
>> +| | | | | | | | | | d
>> +| +----+ +----+ +----+p p+----+ +----+ +----+ | r
>> +| | | | | | |o o| | | | | | | i
>> +| | f3 | | f2 | | f0 |r CPSW r| f3 | | f2 | | f0 | | v
>> +| |tc0 | |tc1 | |tc2 |t t|tc0 | |tc1 | |tc2 | | e
>> +| \CBS / \CBS / \CBS /1 2\CBS / \CBS / \CBS / | r
>> +| \S / \S / \ / \S / \S / \ / |
>> +| \/ \/ \/ \/ \/ \/ |
>> ++------------------------------------------------------------------+
>> +========================================Eth==========================>
>> +
>> +1)
>> +// Add 8 tx queues, for interface Eth0, but they are common, so are accessed
>> +// by two interfaces Eth0 and Eth1.
>> +$ ethtool -L eth1 rx 1 tx 8
>> +rx unmodified, ignoring
>> +
>> +2)
>> +// Check if num of queues is set correctly:
>> +$ ethtool -l eth0
>> +Channel parameters for eth0:
>> +Pre-set maximums:
>> +RX: 8
>> +TX: 8
>> +Other: 0
>> +Combined: 0
>> +Current hardware settings:
>> +RX: 1
>> +TX: 8
>> +Other: 0
>> +Combined: 0
>> +
>> +3)
>> +// TX queues must be rated starting from 0, so set bws for tx0 and tx1 for Eth0
>> +// and for tx2 and tx3 for Eth1. That is, rates 40 and 20 Mb/s appropriately
>> +// for Eth0 and 30 and 10 Mb/s for Eth1.
>> +// Real speed can differ a bit due to discreetness
>> +// Leave last 4 tx queues as not rated
>> +$ echo 40 > /sys/class/net/eth0/queues/tx-0/tx_maxrate
>> +$ echo 20 > /sys/class/net/eth0/queues/tx-1/tx_maxrate
>> +$ echo 30 > /sys/class/net/eth1/queues/tx-2/tx_maxrate
>> +$ echo 10 > /sys/class/net/eth1/queues/tx-3/tx_maxrate
>> +
>> +4)
>> +// Check maximum rate of tx (cpdma) queues:
>> +$ cat /sys/class/net/eth0/queues/tx-*/tx_maxrate
>> +40
>> +20
>> +30
>> +10
>> +0
>> +0
>> +0
>> +0
>> +
>> +5)
>> +// Map skb->priority to traffic class for Eth0:
>> +// 3pri -> tc0, 2pri -> tc1, (0,1,4-7)pri -> tc2
>> +// Map traffic class to transmit queue:
>> +// tc0 -> txq0, tc1 -> txq1, tc2 -> (txq4, txq5)
>> +$ tc qdisc replace dev eth0 handle 100: parent root mqprio num_tc 3 \
>> +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
>> +
>> +6)
>> +// Check classes settings
>> +$ tc -g class show dev eth0
>> ++---(100:ffe2) mqprio
>> +| +---(100:5) mqprio
>> +| +---(100:6) mqprio
>> +|
>> ++---(100:ffe1) mqprio
>> +| +---(100:2) mqprio
>> +|
>> ++---(100:ffe0) mqprio
>> + +---(100:1) mqprio
>> +
>> +7)
>> +// Set rate for class A - 41 Mbit (tc0, txq0) using CBS Qdisc for Eth0
>> +// here only idle slope is important, others ignored
>> +// Real speed can differ a bit due to discreetness
>> +$ tc qdisc add dev eth0 parent 100:1 cbs locredit -1470 \
>> +hicredit 62 sendslope -959000 idleslope 41000 offload 1
>> +net eth0: set FIFO3 bw = 50
>> +
>> +8)
>> +// Set rate for class B - 21 Mbit (tc1, txq1) using CBS Qdisc for Eth0
>> +$ tc qdisc add dev eth0 parent 100:2 cbs locredit -1470 \
>> +hicredit 65 sendslope -979000 idleslope 21000 offload 1
>> +net eth0: set FIFO2 bw = 30
>> +
>> +9)
>> +// Create vlan 100 to map sk->priority to vlan qos for Eth0
>> +$ ip link add link eth0 name eth0.100 type vlan id 100
>> +net eth0: Adding vlanid 100 to vlan filter
>> +
>> +10)
>> +// Map skb->priority to L2 prio for Eth0.100, one to one
>> +$ ip link set eth0.100 type vlan \
>> +egress 0:0 1:1 2:2 3:3 4:4 5:5 6:6 7:7
>> +
>> +11)
>> +// Check egress map for vlan 100
>> +$ cat /proc/net/vlan/eth0.100
>> +[...]
>> +INGRESS priority mappings: 0:0 1:0 2:0 3:0 4:0 5:0 6:0 7:0
>> +EGRESS priority mappings: 0:0 1:1 2:2 3:3 4:4 5:5 6:6 7:7
>> +
>> +12)
>> +// Map skb->priority to traffic class for Eth1:
>> +// 3pri -> tc0, 2pri -> tc1, (0,1,4-7)pri -> tc2
>> +// Map traffic class to transmit queue:
>> +// tc0 -> txq2, tc1 -> txq3, tc2 -> (txq6, txq7)
>> +$ tc qdisc replace dev eth1 handle 100: parent root mqprio num_tc 3 \
>> +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
>> +
>> +13)
>> +// Check classes settings
>> +$ tc -g class show dev eth1
>> ++---(100:ffe2) mqprio
>> +| +---(100:7) mqprio
>> +| +---(100:8) mqprio
>> +|
>> ++---(100:ffe1) mqprio
>> +| +---(100:4) mqprio
>> +|
>> ++---(100:ffe0) mqprio
>> + +---(100:3) mqprio
>> +
>> +14)
>> +// Set rate for class A - 31 Mbit (tc0, txq2) using CBS Qdisc for Eth1
>> +// here only idle slope is important, others ignored
>> +// Set it +1 Mb for reserve (important!)
>> +$ tc qdisc add dev eth1 parent 100:3 cbs locredit -1453 \
>> +hicredit 47 sendslope -969000 idleslope 31000 offload 1
>> +net eth1: set FIFO3 bw = 31
>> +
>> +15)
>> +// Set rate for class B - 11 Mbit (tc1, txq3) using CBS Qdisc for Eth1
>> +// Set it +1 Mb for reserve (important!)
>> +$ tc qdisc add dev eth1 parent 100:4 cbs locredit -1483 \
>> +hicredit 34 sendslope -989000 idleslope 11000 offload 1
>> +net eth1: set FIFO2 bw = 11
>> +
>> +16)
>> +// Create vlan 100 to map sk->priority to vlan qos for Eth1
>> +$ ip link add link eth1 name eth1.100 type vlan id 100
>> +net eth1: Adding vlanid 100 to vlan filter
>> +
>> +17)
>> +// Map skb->priority to L2 prio for Eth1.100, one to one
>> +$ ip link set eth1.100 type vlan \
>> +egress 0:0 1:1 2:2 3:3 4:4 5:5 6:6 7:7
>> +
>> +18)
>> +// Check egress map for vlan 100
>> +$ cat /proc/net/vlan/eth1.100
>> +[...]
>> +INGRESS priority mappings: 0:0 1:0 2:0 3:0 4:0 5:0 6:0 7:0
>> +EGRESS priority mappings: 0:0 1:1 2:2 3:3 4:4 5:5 6:6 7:7
>> +
>> +19)
>> +// Run appropriate tools with socket option "SO_PRIORITY" to 3
>> +// for class A and to 2 for class B. For both interfaces
>> +./tsn_talker -d 18:03:73:66:87:42 -i eth0.100 -p2 -s 1500&
>> +./tsn_talker -d 18:03:73:66:87:42 -i eth0.100 -p3 -s 1500&
>> +./tsn_talker -d 20:cf:30:85:7d:fd -i eth1.100 -p2 -s 1500&
>> +./tsn_talker -d 20:cf:30:85:7d:fd -i eth1.100 -p3 -s 1500&
>> +
>> +20)
>> +// run your listener on workstation (should be in same vlan)
>> +// (I took at https://www.spinics.net/lists/netdev/msg460869.html)
>> +./tsn_listener -d 18:03:73:66:87:42 -i enp5s0 -s 1500
>> +Receiving data rate: 39012 kbps
>> +Receiving data rate: 39012 kbps
>> +Receiving data rate: 39012 kbps
>> +Receiving data rate: 39012 kbps
>> +Receiving data rate: 39012 kbps
>> +Receiving data rate: 39012 kbps
>> +Receiving data rate: 39012 kbps
>> +Receiving data rate: 39012 kbps
>> +Receiving data rate: 39012 kbps
>> +Receiving data rate: 39012 kbps
>> +Receiving data rate: 39012 kbps
>> +Receiving data rate: 39012 kbps
>> +Receiving data rate: 39000 kbps
>> +
>> +21)
>> +// Restore default configuration if needed
>> +$ ip link del eth1.100
>> +$ ip link del eth0.100
>> +$ tc qdisc del dev eth1 root
>> +net eth1: Prev FIFO2 is shaped
>> +net eth1: set FIFO3 bw = 0
>> +net eth1: set FIFO2 bw = 0
>> +$ tc qdisc del dev eth0 root
>> +net eth0: Prev FIFO2 is shaped
>> +net eth0: set FIFO3 bw = 0
>> +net eth0: set FIFO2 bw = 0
>> +$ ethtool -L eth0 rx 1 tx 1
>> --
>> 2.17.1
>>
--
Regards,
Ivan Khoronzhuk
^ permalink raw reply
* Re: [PATCH net-next 0/9] Misc. cleanups for HNS3 ethernet driver
From: David Miller @ 2018-07-21 17:17 UTC (permalink / raw)
To: salil.mehta
Cc: yisen.zhuang, lipeng321, mehta.salil, netdev, linux-kernel,
linuxarm
In-Reply-To: <20180719144706.644-1-salil.mehta@huawei.com>
From: Salil Mehta <salil.mehta@huawei.com>
Date: Thu, 19 Jul 2018 15:46:57 +0100
> This patch-set presents some cleanups for HNS3 Ethernet Driver.
Series applied.
^ permalink raw reply
* Re: [PATCH V4 net-next 0/3] tcp: improve setsockopt() TCP_USER_TIMEOUT accuracy
From: David Miller @ 2018-07-21 17:29 UTC (permalink / raw)
To: jmaxwell37
Cc: edumazet, ncardwell, David.Laight, kuznet, yoshfuji, netdev,
linux-kernel, jmaxwell
In-Reply-To: <20180719011444.4694-1-jmaxwell37@gmail.com>
From: Jon Maxwell <jmaxwell37@gmail.com>
Date: Thu, 19 Jul 2018 11:14:41 +1000
> The patch was becoming bigger based on feedback therefore I have
> implemented a series of 3 commits instead in V4.
>
> This series is a continuation based on V3 here and associated feedback:
>
> https://patchwork.kernel.org/patch/10516195/
Series applied, thanks.
^ permalink raw reply
* [PATCH net-next v6 0/4] net: vhost: improve performance when enable busyloop
From: xiangxia.m.yue @ 2018-07-21 18:03 UTC (permalink / raw)
To: jasowang; +Cc: netdev, virtualization, mst
From: Tonghao Zhang <xiangxia.m.yue@gmail.com>
This patches improve the guest receive performance.
On the handle_tx side, we poll the sock receive queue
at the same time. handle_rx do that in the same way.
For more performance report, see patch 4.
v5->v6:
rebase the codes.
Tonghao Zhang (4):
net: vhost: lock the vqs one by one
net: vhost: replace magic number of lock annotation
net: vhost: factor out busy polling logic to vhost_net_busy_poll()
net: vhost: add rx busy polling in tx path
drivers/vhost/net.c | 148 +++++++++++++++++++++++++++++---------------------
drivers/vhost/vhost.c | 24 +++-----
2 files changed, 94 insertions(+), 78 deletions(-)
--
1.8.3.1
^ permalink raw reply
* Re: [PATCH bpf 3/3] bpf: Introduce BPF_ANNOTATE_KV_PAIR
From: Martin KaFai Lau @ 2018-07-21 17:06 UTC (permalink / raw)
To: netdev; +Cc: Alexei Starovoitov, Daniel Borkmann, kernel-team
In-Reply-To: <20180721013933.2975241-4-kafai@fb.com>
On Fri, Jul 20, 2018 at 06:39:33PM -0700, Martin KaFai Lau wrote:
> This patch introduces BPF_ANNOTATE_KV_PAIR to signal the
> bpf loader about the btf key_type and value_type of a bpf map.
> Please refer to the changes in test_btf_haskv.c for its usage.
> Both iproute2 and libbpf loader will then have the same
> convention to find out the map's btf_key_type_id and
> btf_value_type_id from a map's name.
>
> Fixes: 8a138aed4a80 ("bpf: btf: Add BTF support to libbpf")
> Suggested-by: Daniel Borkmann <daniel@iogearbox.net>
> Signed-off-by: Martin KaFai Lau <kafai@fb.com>
> ---
> tools/lib/bpf/btf.c | 8 +++
> tools/lib/bpf/btf.h | 1 +
> tools/lib/bpf/libbpf.c | 71 +++++++++++---------
> tools/testing/selftests/bpf/bpf_helpers.h | 9 +++
> tools/testing/selftests/bpf/test_btf_haskv.c | 7 +-
> 5 files changed, 59 insertions(+), 37 deletions(-)
>
> diff --git a/tools/lib/bpf/btf.c b/tools/lib/bpf/btf.c
> index ce77b5b57912..748f0b11361d 100644
> --- a/tools/lib/bpf/btf.c
> +++ b/tools/lib/bpf/btf.c
> @@ -288,6 +288,14 @@ __s32 btf__find_by_name(const struct btf *btf, const char *type_name)
> return -ENOENT;
> }
>
> +const struct btf_type *btf__type_by_id(const struct btf *btf, __u32 id)
> +{
> + if (!id || id > btf->nr_types)
> + return ERR_PTR(-EINVAL);
> +
> + return btf->types[id];
> +}
> +
> void btf__free(struct btf *btf)
> {
> if (!btf)
> diff --git a/tools/lib/bpf/btf.h b/tools/lib/bpf/btf.h
> index ed3a84370ccc..38ebf66613e4 100644
> --- a/tools/lib/bpf/btf.h
> +++ b/tools/lib/bpf/btf.h
> @@ -16,6 +16,7 @@ typedef int (*btf_print_fn_t)(const char *, ...)
> void btf__free(struct btf *btf);
> struct btf *btf__new(__u8 *data, __u32 size, btf_print_fn_t err_log);
> __s32 btf__find_by_name(const struct btf *btf, const char *type_name);
> +const struct btf_type *btf__type_by_id(const struct btf *btf, __u32 id);
> __s64 btf__resolve_size(const struct btf *btf, __u32 type_id);
> int btf__fd(const struct btf *btf);
>
> diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
> index 6deb4fe4fffe..5ff7755efa6b 100644
> --- a/tools/lib/bpf/libbpf.c
> +++ b/tools/lib/bpf/libbpf.c
> @@ -36,6 +36,7 @@
> #include <linux/err.h>
> #include <linux/kernel.h>
> #include <linux/bpf.h>
> +#include <linux/btf.h>
> #include <linux/list.h>
> #include <linux/limits.h>
> #include <sys/stat.h>
> @@ -1014,63 +1015,69 @@ bpf_program__collect_reloc(struct bpf_program *prog, GElf_Shdr *shdr,
>
> static int bpf_map_find_btf_info(struct bpf_map *map, const struct btf *btf)
> {
> + const struct btf_type *container_type;
> + const struct btf_member *key, *value;
> + __s32 key_id, value_id, container_id;
> struct bpf_map_def *def = &map->def;
> const size_t max_name = 256;
> + char container_name[max_name];
> __s64 key_size, value_size;
> - __s32 key_id, value_id;
> - char name[max_name];
>
> - /* Find key type by name from BTF */
> - if (snprintf(name, max_name, "%s_key", map->name) == max_name) {
> - pr_warning("map:%s length of BTF key_type:%s_key is too long\n",
> + if (snprintf(container_name, max_name, "____btf_map_%s", map->name) ==
> + max_name) {
> + pr_warning("map:%s length of '____btf_map_%s' is too long\n",
> map->name, map->name);
> return -EINVAL;
> }
>
> - key_id = btf__find_by_name(btf, name);
> - if (key_id < 0) {
> - pr_debug("map:%s key_type:%s cannot be found in BTF\n",
> - map->name, name);
> - return key_id;
> + container_id = btf__find_by_name(btf, container_name);
> + if (container_id < 0) {
> + pr_debug("map:%s container_name:%s cannot be found in BTF. Missing BPF_ANNOTATE_KV_PAIR?\n",
> + map->name, container_name);
> + return container_id;
> }
>
> - key_size = btf__resolve_size(btf, key_id);
> - if (key_size < 0) {
> - pr_warning("map:%s key_type:%s cannot get the BTF type_size\n",
> - map->name, name);
> - return key_size;
> + container_type = btf__type_by_id(btf, container_id);
> + if (IS_ERR(container_type)) {
> + pr_warning("map:%s cannot find BTF type for container_id:%u\n",
> + map->name, container_id);
> + return PTR_ERR(container_type);
> }
>
> - if (def->key_size != key_size) {
> - pr_warning("map:%s key_type:%s has BTF type_size:%u != key_size:%u\n",
> - map->name, name, (unsigned int)key_size, def->key_size);
> + if (BTF_INFO_KIND(container_type->info) != BTF_KIND_STRUCT &&
> + BTF_INFO_VLEN(container_type->info) < 2) {
There is a mistake in this check. I will spin v2.
> + pr_warning("map:%s container_name:%s is an invalid container struct\n",
> + map->name, container_name);
> return -EINVAL;
> }
>
> - /* Find value type from BTF */
> - if (snprintf(name, max_name, "%s_value", map->name) == max_name) {
> - pr_warning("map:%s length of BTF value_type:%s_value is too long\n",
> - map->name, map->name);
> - return -EINVAL;
> + key = (struct btf_member *)(container_type + 1);
> + value = key + 1;
> + key_id = key->type;
> + value_id = value->type;
> +
> + key_size = btf__resolve_size(btf, key_id);
> + if (key_size < 0) {
> + pr_warning("map:%s invalid BTF key_type_size\n",
> + map->name);
> + return key_size;
> }
>
> - value_id = btf__find_by_name(btf, name);
> - if (value_id < 0) {
> - pr_debug("map:%s value_type:%s cannot be found in BTF\n",
> - map->name, name);
> - return value_id;
> + if (def->key_size != key_size) {
> + pr_warning("map:%s btf_key_type_size:%u != map_def_key_size:%u\n",
> + map->name, (__u32)key_size, def->key_size);
> + return -EINVAL;
> }
>
> value_size = btf__resolve_size(btf, value_id);
> if (value_size < 0) {
> - pr_warning("map:%s value_type:%s cannot get the BTF type_size\n",
> - map->name, name);
> + pr_warning("map:%s invalid BTF value_type_size\n", map->name);
> return value_size;
> }
>
> if (def->value_size != value_size) {
> - pr_warning("map:%s value_type:%s has BTF type_size:%u != value_size:%u\n",
> - map->name, name, (unsigned int)value_size, def->value_size);
> + pr_warning("map:%s btf_value_type_size:%u != map_def_value_size:%u\n",
> + map->name, (__u32)value_size, def->value_size);
> return -EINVAL;
> }
>
> diff --git a/tools/testing/selftests/bpf/bpf_helpers.h b/tools/testing/selftests/bpf/bpf_helpers.h
> index f2f28b6c8915..0ce47b46df70 100644
> --- a/tools/testing/selftests/bpf/bpf_helpers.h
> +++ b/tools/testing/selftests/bpf/bpf_helpers.h
> @@ -158,6 +158,15 @@ struct bpf_map_def {
> unsigned int numa_node;
> };
>
> +#define BPF_ANNOTATE_KV_PAIR(name, type_key, type_val) \
> + struct ____btf_map_##name { \
> + type_key key; \
> + type_val value; \
> + }; \
> + struct ____btf_map_##name \
> + __attribute__ ((section(".maps." #name), used)) \
> + ____btf_map_##name = { }
> +
> static int (*bpf_skb_load_bytes)(void *ctx, int off, void *to, int len) =
> (void *) BPF_FUNC_skb_load_bytes;
> static int (*bpf_skb_store_bytes)(void *ctx, int off, void *from, int len, int flags) =
> diff --git a/tools/testing/selftests/bpf/test_btf_haskv.c b/tools/testing/selftests/bpf/test_btf_haskv.c
> index 8c7ca096ecf2..b21b876f475d 100644
> --- a/tools/testing/selftests/bpf/test_btf_haskv.c
> +++ b/tools/testing/selftests/bpf/test_btf_haskv.c
> @@ -10,11 +10,6 @@ struct ipv_counts {
> unsigned int v6;
> };
>
> -typedef int btf_map_key;
> -typedef struct ipv_counts btf_map_value;
> -btf_map_key dumm_key;
> -btf_map_value dummy_value;
> -
> struct bpf_map_def SEC("maps") btf_map = {
> .type = BPF_MAP_TYPE_ARRAY,
> .key_size = sizeof(int),
> @@ -22,6 +17,8 @@ struct bpf_map_def SEC("maps") btf_map = {
> .max_entries = 4,
> };
>
> +BPF_ANNOTATE_KV_PAIR(btf_map, int, struct ipv_counts);
> +
> struct dummy_tracepoint_args {
> unsigned long long pad;
> struct sock *sock;
> --
> 2.17.1
>
^ permalink raw reply
* Re: [PATCH net-next 00/11] s390/qeth: updates 2018-07-19
From: David Miller @ 2018-07-21 17:17 UTC (permalink / raw)
To: jwi; +Cc: netdev, linux-s390, schwidefsky, heiko.carstens, raspl, ubraun
In-Reply-To: <20180719104358.79696-1-jwi@linux.ibm.com>
From: Julian Wiedmann <jwi@linux.ibm.com>
Date: Thu, 19 Jul 2018 12:43:47 +0200
> please apply one more round of qeth patches to net-next.
> This brings additional performance improvements for the transmit code,
> and some refactoring to pave the way for using netdev_priv.
> Also, two minor fixes for rare corner cases.
Series applied, thanks Julian.
^ permalink raw reply
* Re: [pull request][net 0/8] Mellanox, mlx5 fixes 2018-07-18
From: David Miller @ 2018-07-21 17:20 UTC (permalink / raw)
To: saeedm; +Cc: netdev
In-Reply-To: <20180719012612.25907-1-saeedm@mellanox.com>
From: Saeed Mahameed <saeedm@mellanox.com>
Date: Wed, 18 Jul 2018 18:26:04 -0700
> The following series provides fixes to mlx5 core and net device driver.
>
> Please pull and let me know if there's any problem.
Pulled, thanks Saeed.
Based upon the thread with Or, it would be useful to do some auditing
and make sure all tunnels set skb->encapsulation.
> For -stable v4.7
> net/mlx5e: Don't allow aRFS for encapsulated packets
> net/mlx5e: Fix quota counting in aRFS expire flow
>
> For -stable v4.15
> net/mlx5e: Only allow offloading decap egress (egdev) flows
> net/mlx5e: Refine ets validation function
> net/mlx5: Adjust clock overflow work period
>
> For -stable v4.17
> net/mlx5: E-Switch, UBSAN fix undefined behavior in mlx5_eswitch_mode
Queued up.
Thanks.
^ permalink raw reply
* Re: [PATCH net] bonding: set default miimon value for non-arp modes if not set
From: David Miller @ 2018-07-21 17:26 UTC (permalink / raw)
To: jarod; +Cc: linux-kernel, j.vosburgh, vfalico, andy, maheshb, netdev, stable
In-Reply-To: <20180718184936.16037-1-jarod@redhat.com>
From: Jarod Wilson <jarod@redhat.com>
Date: Wed, 18 Jul 2018 14:49:36 -0400
> For some time now, if you load the bonding driver and configure bond
> parameters via sysfs using minimal config options, such as specifying
> nothing but the mode, relying on defaults for everything else, modes
> that cannot use arp monitoring (802.3ad, balance-tlb, balance-alb) all
> wind up with both arp_interval=0 (as it should be) and miimon=0, which
> means the miimon monitor thread never actually runs. This is particularly
> problematic for 802.3ad.
...
> I believe this became a major issue as of commit 4d2c0cda0744, which for
> 802.3ad bonds, sets slave->link = BOND_LINK_DOWN, with a comment about
> relying on link monitoring via miimon to set it correctly, but since the
> miimon work queue never runs, the link just stays marked down.
>
> If we simply tweak bond_option_mode_set() slightly, we can check for the
> non-arp modes having no miimon value set, and insert BOND_DEFAULT_MIIMON,
> which gets things back in full working order. This problem exists as far
> back as 4.14, and might be worth fixing in all stable trees since, though
> the work-around is to simply specify an miimon value yourself.
>
> Reported-by: Bob Ball <ball@umich.edu>
...
> Signed-off-by: Jarod Wilson <jarod@redhat.com>
Applied and queued up for -stable, thank you.
^ permalink raw reply
* [PATCH net-next v6 1/4] net: vhost: lock the vqs one by one
From: xiangxia.m.yue @ 2018-07-21 18:03 UTC (permalink / raw)
To: jasowang; +Cc: mst, makita.toshiaki, virtualization, netdev, Tonghao Zhang
In-Reply-To: <1532196242-2998-1-git-send-email-xiangxia.m.yue@gmail.com>
From: Tonghao Zhang <xiangxia.m.yue@gmail.com>
This patch changes the way that lock all vqs
at the same, to lock them one by one. It will
be used for next patch to avoid the deadlock.
Signed-off-by: Tonghao Zhang <xiangxia.m.yue@gmail.com>
Acked-by: Jason Wang <jasowang@redhat.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
---
drivers/vhost/vhost.c | 24 +++++++-----------------
1 file changed, 7 insertions(+), 17 deletions(-)
diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
index a502f1a..a1c06e7 100644
--- a/drivers/vhost/vhost.c
+++ b/drivers/vhost/vhost.c
@@ -294,8 +294,11 @@ static void vhost_vq_meta_reset(struct vhost_dev *d)
{
int i;
- for (i = 0; i < d->nvqs; ++i)
+ for (i = 0; i < d->nvqs; ++i) {
+ mutex_lock(&d->vqs[i]->mutex);
__vhost_vq_meta_reset(d->vqs[i]);
+ mutex_unlock(&d->vqs[i]->mutex);
+ }
}
static void vhost_vq_reset(struct vhost_dev *dev,
@@ -890,20 +893,6 @@ static inline void __user *__vhost_get_user(struct vhost_virtqueue *vq,
#define vhost_get_used(vq, x, ptr) \
vhost_get_user(vq, x, ptr, VHOST_ADDR_USED)
-static void vhost_dev_lock_vqs(struct vhost_dev *d)
-{
- int i = 0;
- for (i = 0; i < d->nvqs; ++i)
- mutex_lock_nested(&d->vqs[i]->mutex, i);
-}
-
-static void vhost_dev_unlock_vqs(struct vhost_dev *d)
-{
- int i = 0;
- for (i = 0; i < d->nvqs; ++i)
- mutex_unlock(&d->vqs[i]->mutex);
-}
-
static int vhost_new_umem_range(struct vhost_umem *umem,
u64 start, u64 size, u64 end,
u64 userspace_addr, int perm)
@@ -953,7 +942,10 @@ static void vhost_iotlb_notify_vq(struct vhost_dev *d,
if (msg->iova <= vq_msg->iova &&
msg->iova + msg->size - 1 > vq_msg->iova &&
vq_msg->type == VHOST_IOTLB_MISS) {
+ mutex_lock(&node->vq->mutex);
vhost_poll_queue(&node->vq->poll);
+ mutex_unlock(&node->vq->mutex);
+
list_del(&node->node);
kfree(node);
}
@@ -985,7 +977,6 @@ static int vhost_process_iotlb_msg(struct vhost_dev *dev,
int ret = 0;
mutex_lock(&dev->mutex);
- vhost_dev_lock_vqs(dev);
switch (msg->type) {
case VHOST_IOTLB_UPDATE:
if (!dev->iotlb) {
@@ -1019,7 +1010,6 @@ static int vhost_process_iotlb_msg(struct vhost_dev *dev,
break;
}
- vhost_dev_unlock_vqs(dev);
mutex_unlock(&dev->mutex);
return ret;
--
1.8.3.1
^ permalink raw reply related
* [PATCH net-next v6 2/4] net: vhost: replace magic number of lock annotation
From: xiangxia.m.yue @ 2018-07-21 18:04 UTC (permalink / raw)
To: jasowang; +Cc: mst, makita.toshiaki, virtualization, netdev, Tonghao Zhang
In-Reply-To: <1532196242-2998-1-git-send-email-xiangxia.m.yue@gmail.com>
From: Tonghao Zhang <xiangxia.m.yue@gmail.com>
Use the VHOST_NET_VQ_XXX as a subclass for mutex_lock_nested.
Signed-off-by: Tonghao Zhang <xiangxia.m.yue@gmail.com>
Acked-by: Jason Wang <jasowang@redhat.com>
---
drivers/vhost/net.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c
index b224036..321264c 100644
--- a/drivers/vhost/net.c
+++ b/drivers/vhost/net.c
@@ -490,7 +490,7 @@ static void handle_tx(struct vhost_net *net)
bool zcopy, zcopy_used;
int sent_pkts = 0;
- mutex_lock(&vq->mutex);
+ mutex_lock_nested(&vq->mutex, VHOST_NET_VQ_TX);
sock = vq->private_data;
if (!sock)
goto out;
@@ -667,7 +667,7 @@ static int vhost_net_rx_peek_head_len(struct vhost_net *net, struct sock *sk,
/* Flush batched heads first */
vhost_rx_signal_used(rnvq);
/* Both tx vq and rx socket were polled here */
- mutex_lock_nested(&tvq->mutex, 1);
+ mutex_lock_nested(&tvq->mutex, VHOST_NET_VQ_TX);
vhost_disable_notify(&net->dev, tvq);
preempt_disable();
@@ -809,7 +809,7 @@ static void handle_rx(struct vhost_net *net)
__virtio16 num_buffers;
int recv_pkts = 0;
- mutex_lock_nested(&vq->mutex, 0);
+ mutex_lock_nested(&vq->mutex, VHOST_NET_VQ_RX);
sock = vq->private_data;
if (!sock)
goto out;
--
1.8.3.1
^ permalink raw reply related
* [PATCH net-next v6 3/4] net: vhost: factor out busy polling logic to vhost_net_busy_poll()
From: xiangxia.m.yue @ 2018-07-21 18:04 UTC (permalink / raw)
To: jasowang; +Cc: mst, makita.toshiaki, virtualization, netdev, Tonghao Zhang
In-Reply-To: <1532196242-2998-1-git-send-email-xiangxia.m.yue@gmail.com>
From: Tonghao Zhang <xiangxia.m.yue@gmail.com>
Factor out generic busy polling logic and will be
used for in tx path in the next patch. And with the patch,
qemu can set differently the busyloop_timeout for rx queue.
Signed-off-by: Tonghao Zhang <xiangxia.m.yue@gmail.com>
---
drivers/vhost/net.c | 114 ++++++++++++++++++++++++++++++++++------------------
1 file changed, 74 insertions(+), 40 deletions(-)
diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c
index 321264c..2dc937e 100644
--- a/drivers/vhost/net.c
+++ b/drivers/vhost/net.c
@@ -428,6 +428,78 @@ static int vhost_net_enable_vq(struct vhost_net *n,
return vhost_poll_start(poll, sock->file);
}
+static int sk_has_rx_data(struct sock *sk)
+{
+ struct socket *sock = sk->sk_socket;
+
+ if (sock->ops->peek_len)
+ return sock->ops->peek_len(sock);
+
+ return skb_queue_empty(&sk->sk_receive_queue);
+}
+
+static void vhost_net_busy_poll_vq_check(struct vhost_net *net,
+ struct vhost_virtqueue *rvq,
+ struct vhost_virtqueue *tvq,
+ bool rx)
+{
+ struct socket *sock = rvq->private_data;
+
+ if (rx) {
+ if (!vhost_vq_avail_empty(&net->dev, tvq)) {
+ vhost_poll_queue(&tvq->poll);
+ } else if (unlikely(vhost_enable_notify(&net->dev, tvq))) {
+ vhost_disable_notify(&net->dev, tvq);
+ vhost_poll_queue(&tvq->poll);
+ }
+ } else if ((sock && sk_has_rx_data(sock->sk)) &&
+ !vhost_vq_avail_empty(&net->dev, rvq)) {
+ vhost_poll_queue(&rvq->poll);
+ }
+}
+
+static void vhost_net_busy_poll(struct vhost_net *net,
+ struct vhost_virtqueue *rvq,
+ struct vhost_virtqueue *tvq,
+ bool *busyloop_intr,
+ bool rx)
+{
+ unsigned long busyloop_timeout;
+ unsigned long endtime;
+ struct socket *sock;
+ struct vhost_virtqueue *vq = rx ? tvq : rvq;
+
+ mutex_lock_nested(&vq->mutex, rx ? VHOST_NET_VQ_TX: VHOST_NET_VQ_RX);
+ vhost_disable_notify(&net->dev, vq);
+ sock = rvq->private_data;
+
+ busyloop_timeout = rx ? rvq->busyloop_timeout:
+ tvq->busyloop_timeout;
+
+ preempt_disable();
+ endtime = busy_clock() + busyloop_timeout;
+
+ while (vhost_can_busy_poll(endtime)) {
+ if (vhost_has_work(&net->dev)) {
+ *busyloop_intr = true;
+ break;
+ }
+
+ if ((sock && sk_has_rx_data(sock->sk) &&
+ !vhost_vq_avail_empty(&net->dev, rvq)) ||
+ !vhost_vq_avail_empty(&net->dev, tvq))
+ break;
+
+ cpu_relax();
+ }
+
+ preempt_enable();
+
+ vhost_net_busy_poll_vq_check(net, rvq, tvq, rx);
+
+ mutex_unlock(&vq->mutex);
+}
+
static int vhost_net_tx_get_vq_desc(struct vhost_net *net,
struct vhost_virtqueue *vq,
struct iovec iov[], unsigned int iov_size,
@@ -631,16 +703,6 @@ static int peek_head_len(struct vhost_net_virtqueue *rvq, struct sock *sk)
return len;
}
-static int sk_has_rx_data(struct sock *sk)
-{
- struct socket *sock = sk->sk_socket;
-
- if (sock->ops->peek_len)
- return sock->ops->peek_len(sock);
-
- return skb_queue_empty(&sk->sk_receive_queue);
-}
-
static void vhost_rx_signal_used(struct vhost_net_virtqueue *nvq)
{
struct vhost_virtqueue *vq = &nvq->vq;
@@ -660,41 +722,13 @@ static int vhost_net_rx_peek_head_len(struct vhost_net *net, struct sock *sk,
struct vhost_net_virtqueue *tnvq = &net->vqs[VHOST_NET_VQ_TX];
struct vhost_virtqueue *rvq = &rnvq->vq;
struct vhost_virtqueue *tvq = &tnvq->vq;
- unsigned long uninitialized_var(endtime);
int len = peek_head_len(rnvq, sk);
- if (!len && tvq->busyloop_timeout) {
+ if (!len && rvq->busyloop_timeout) {
/* Flush batched heads first */
vhost_rx_signal_used(rnvq);
/* Both tx vq and rx socket were polled here */
- mutex_lock_nested(&tvq->mutex, VHOST_NET_VQ_TX);
- vhost_disable_notify(&net->dev, tvq);
-
- preempt_disable();
- endtime = busy_clock() + tvq->busyloop_timeout;
-
- while (vhost_can_busy_poll(endtime)) {
- if (vhost_has_work(&net->dev)) {
- *busyloop_intr = true;
- break;
- }
- if ((sk_has_rx_data(sk) &&
- !vhost_vq_avail_empty(&net->dev, rvq)) ||
- !vhost_vq_avail_empty(&net->dev, tvq))
- break;
- cpu_relax();
- }
-
- preempt_enable();
-
- if (!vhost_vq_avail_empty(&net->dev, tvq)) {
- vhost_poll_queue(&tvq->poll);
- } else if (unlikely(vhost_enable_notify(&net->dev, tvq))) {
- vhost_disable_notify(&net->dev, tvq);
- vhost_poll_queue(&tvq->poll);
- }
-
- mutex_unlock(&tvq->mutex);
+ vhost_net_busy_poll(net, rvq, tvq, busyloop_intr, true);
len = peek_head_len(rnvq, sk);
}
--
1.8.3.1
^ permalink raw reply related
* [PATCH net-next v6 4/4] net: vhost: add rx busy polling in tx path
From: xiangxia.m.yue @ 2018-07-21 18:04 UTC (permalink / raw)
To: jasowang; +Cc: mst, makita.toshiaki, virtualization, netdev, Tonghao Zhang
In-Reply-To: <1532196242-2998-1-git-send-email-xiangxia.m.yue@gmail.com>
From: Tonghao Zhang <xiangxia.m.yue@gmail.com>
This patch improves the guest receive performance.
On the handle_tx side, we poll the sock receive queue at the
same time. handle_rx do that in the same way.
We set the poll-us=100us and use the netperf to test throughput
and mean latency. When running the tests, the vhost-net kthread
of that VM, is alway 100% CPU. The commands are shown as below.
Rx performance is greatly improved by this patch. There is not
notable performance change on tx with this series though. This
patch is useful for bi-directional traffic.
netperf -H IP -t TCP_STREAM -l 20 -- -O "THROUGHPUT, THROUGHPUT_UNITS, MEAN_LATENCY"
Topology:
[Host] ->linux bridge -> tap vhost-net ->[Guest]
TCP_STREAM:
* Without the patch: 19842.95 Mbps, 6.50 us mean latency
* With the patch: 37373.10 Mbps, 3.43 us mean latency
Signed-off-by: Tonghao Zhang <xiangxia.m.yue@gmail.com>
---
drivers/vhost/net.c | 30 +++++++++++-------------------
1 file changed, 11 insertions(+), 19 deletions(-)
diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c
index 2dc937e..a562828 100644
--- a/drivers/vhost/net.c
+++ b/drivers/vhost/net.c
@@ -501,29 +501,21 @@ static void vhost_net_busy_poll(struct vhost_net *net,
}
static int vhost_net_tx_get_vq_desc(struct vhost_net *net,
- struct vhost_virtqueue *vq,
+ struct vhost_virtqueue *tvq,
struct iovec iov[], unsigned int iov_size,
unsigned int *out_num, unsigned int *in_num,
bool *busyloop_intr)
{
- unsigned long uninitialized_var(endtime);
- int r = vhost_get_vq_desc(vq, vq->iov, ARRAY_SIZE(vq->iov),
- out_num, in_num, NULL, NULL);
-
- if (r == vq->num && vq->busyloop_timeout) {
- preempt_disable();
- endtime = busy_clock() + vq->busyloop_timeout;
- while (vhost_can_busy_poll(endtime)) {
- if (vhost_has_work(vq->dev)) {
- *busyloop_intr = true;
- break;
- }
- if (!vhost_vq_avail_empty(vq->dev, vq))
- break;
- cpu_relax();
- }
- preempt_enable();
- r = vhost_get_vq_desc(vq, vq->iov, ARRAY_SIZE(vq->iov),
+ struct vhost_net_virtqueue *rnvq = &net->vqs[VHOST_NET_VQ_RX];
+ struct vhost_virtqueue *rvq = &rnvq->vq;
+
+ int r = vhost_get_vq_desc(tvq, tvq->iov, ARRAY_SIZE(tvq->iov),
+ out_num, in_num, NULL, NULL);
+
+ if (r == tvq->num && tvq->busyloop_timeout) {
+ vhost_net_busy_poll(net, rvq, tvq, busyloop_intr, false);
+
+ r = vhost_get_vq_desc(tvq, tvq->iov, ARRAY_SIZE(tvq->iov),
out_num, in_num, NULL, NULL);
}
--
1.8.3.1
^ permalink raw reply related
* [PATCH v2 bpf 3/3] bpf: Introduce BPF_ANNOTATE_KV_PAIR
From: Martin KaFai Lau @ 2018-07-21 18:20 UTC (permalink / raw)
To: netdev; +Cc: Alexei Starovoitov, Daniel Borkmann, kernel-team
In-Reply-To: <20180721182043.1401089-1-kafai@fb.com>
This patch introduces BPF_ANNOTATE_KV_PAIR to signal the
bpf loader about the btf key_type and value_type of a bpf map.
Please refer to the changes in test_btf_haskv.c for its usage.
Both iproute2 and libbpf loader will then have the same
convention to find out the map's btf_key_type_id and
btf_value_type_id from a map's name.
Fixes: 8a138aed4a80 ("bpf: btf: Add BTF support to libbpf")
Suggested-by: Daniel Borkmann <daniel@iogearbox.net>
Signed-off-by: Martin KaFai Lau <kafai@fb.com>
---
tools/lib/bpf/btf.c | 7 +-
tools/lib/bpf/btf.h | 2 +
tools/lib/bpf/libbpf.c | 75 +++++++++++---------
tools/testing/selftests/bpf/bpf_helpers.h | 9 +++
tools/testing/selftests/bpf/test_btf_haskv.c | 7 +-
5 files changed, 56 insertions(+), 44 deletions(-)
diff --git a/tools/lib/bpf/btf.c b/tools/lib/bpf/btf.c
index ce77b5b57912..321a99e648ed 100644
--- a/tools/lib/bpf/btf.c
+++ b/tools/lib/bpf/btf.c
@@ -189,8 +189,7 @@ static int btf_parse_type_sec(struct btf *btf, btf_print_fn_t err_log)
return 0;
}
-static const struct btf_type *btf_type_by_id(const struct btf *btf,
- __u32 type_id)
+const struct btf_type *btf__type_by_id(const struct btf *btf, __u32 type_id)
{
if (type_id > btf->nr_types)
return NULL;
@@ -233,7 +232,7 @@ __s64 btf__resolve_size(const struct btf *btf, __u32 type_id)
__s64 size = -1;
int i;
- t = btf_type_by_id(btf, type_id);
+ t = btf__type_by_id(btf, type_id);
for (i = 0; i < MAX_RESOLVE_DEPTH && !btf_type_is_void_or_null(t);
i++) {
size = btf_type_size(t);
@@ -258,7 +257,7 @@ __s64 btf__resolve_size(const struct btf *btf, __u32 type_id)
return -EINVAL;
}
- t = btf_type_by_id(btf, type_id);
+ t = btf__type_by_id(btf, type_id);
}
if (size < 0)
diff --git a/tools/lib/bpf/btf.h b/tools/lib/bpf/btf.h
index ed3a84370ccc..e2a09a155f84 100644
--- a/tools/lib/bpf/btf.h
+++ b/tools/lib/bpf/btf.h
@@ -9,6 +9,7 @@
#define BTF_ELF_SEC ".BTF"
struct btf;
+struct btf_type;
typedef int (*btf_print_fn_t)(const char *, ...)
__attribute__((format(printf, 1, 2)));
@@ -16,6 +17,7 @@ typedef int (*btf_print_fn_t)(const char *, ...)
void btf__free(struct btf *btf);
struct btf *btf__new(__u8 *data, __u32 size, btf_print_fn_t err_log);
__s32 btf__find_by_name(const struct btf *btf, const char *type_name);
+const struct btf_type *btf__type_by_id(const struct btf *btf, __u32 id);
__s64 btf__resolve_size(const struct btf *btf, __u32 type_id);
int btf__fd(const struct btf *btf);
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index 6deb4fe4fffe..d881d370616c 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -36,6 +36,7 @@
#include <linux/err.h>
#include <linux/kernel.h>
#include <linux/bpf.h>
+#include <linux/btf.h>
#include <linux/list.h>
#include <linux/limits.h>
#include <sys/stat.h>
@@ -1014,68 +1015,72 @@ bpf_program__collect_reloc(struct bpf_program *prog, GElf_Shdr *shdr,
static int bpf_map_find_btf_info(struct bpf_map *map, const struct btf *btf)
{
+ const struct btf_type *container_type;
+ const struct btf_member *key, *value;
struct bpf_map_def *def = &map->def;
const size_t max_name = 256;
+ char container_name[max_name];
__s64 key_size, value_size;
- __s32 key_id, value_id;
- char name[max_name];
+ __s32 container_id;
- /* Find key type by name from BTF */
- if (snprintf(name, max_name, "%s_key", map->name) == max_name) {
- pr_warning("map:%s length of BTF key_type:%s_key is too long\n",
+ if (snprintf(container_name, max_name, "____btf_map_%s", map->name) ==
+ max_name) {
+ pr_warning("map:%s length of '____btf_map_%s' is too long\n",
map->name, map->name);
return -EINVAL;
}
- key_id = btf__find_by_name(btf, name);
- if (key_id < 0) {
- pr_debug("map:%s key_type:%s cannot be found in BTF\n",
- map->name, name);
- return key_id;
+ container_id = btf__find_by_name(btf, container_name);
+ if (container_id < 0) {
+ pr_debug("map:%s container_name:%s cannot be found in BTF. Missing BPF_ANNOTATE_KV_PAIR?\n",
+ map->name, container_name);
+ return container_id;
}
- key_size = btf__resolve_size(btf, key_id);
- if (key_size < 0) {
- pr_warning("map:%s key_type:%s cannot get the BTF type_size\n",
- map->name, name);
- return key_size;
+ container_type = btf__type_by_id(btf, container_id);
+ if (!container_type) {
+ pr_warning("map:%s cannot find BTF type for container_id:%u\n",
+ map->name, container_id);
+ return -EINVAL;
}
- if (def->key_size != key_size) {
- pr_warning("map:%s key_type:%s has BTF type_size:%u != key_size:%u\n",
- map->name, name, (unsigned int)key_size, def->key_size);
+ if (BTF_INFO_KIND(container_type->info) != BTF_KIND_STRUCT ||
+ BTF_INFO_VLEN(container_type->info) < 2) {
+ pr_warning("map:%s container_name:%s is an invalid container struct\n",
+ map->name, container_name);
return -EINVAL;
}
- /* Find value type from BTF */
- if (snprintf(name, max_name, "%s_value", map->name) == max_name) {
- pr_warning("map:%s length of BTF value_type:%s_value is too long\n",
- map->name, map->name);
- return -EINVAL;
+ key = (struct btf_member *)(container_type + 1);
+ value = key + 1;
+
+ key_size = btf__resolve_size(btf, key->type);
+ if (key_size < 0) {
+ pr_warning("map:%s invalid BTF key_type_size\n",
+ map->name);
+ return key_size;
}
- value_id = btf__find_by_name(btf, name);
- if (value_id < 0) {
- pr_debug("map:%s value_type:%s cannot be found in BTF\n",
- map->name, name);
- return value_id;
+ if (def->key_size != key_size) {
+ pr_warning("map:%s btf_key_type_size:%u != map_def_key_size:%u\n",
+ map->name, (__u32)key_size, def->key_size);
+ return -EINVAL;
}
- value_size = btf__resolve_size(btf, value_id);
+ value_size = btf__resolve_size(btf, value->type);
if (value_size < 0) {
- pr_warning("map:%s value_type:%s cannot get the BTF type_size\n",
- map->name, name);
+ pr_warning("map:%s invalid BTF value_type_size\n", map->name);
return value_size;
}
if (def->value_size != value_size) {
- pr_warning("map:%s value_type:%s has BTF type_size:%u != value_size:%u\n",
- map->name, name, (unsigned int)value_size, def->value_size);
+ pr_warning("map:%s btf_value_type_size:%u != map_def_value_size:%u\n",
+ map->name, (__u32)value_size, def->value_size);
return -EINVAL;
}
- map->btf_key_type_id = key_id;
- map->btf_value_type_id = value_id;
+ map->btf_key_type_id = key->type;
+ map->btf_value_type_id = value->type;
return 0;
}
diff --git a/tools/testing/selftests/bpf/bpf_helpers.h b/tools/testing/selftests/bpf/bpf_helpers.h
index f2f28b6c8915..810de20e8e26 100644
--- a/tools/testing/selftests/bpf/bpf_helpers.h
+++ b/tools/testing/selftests/bpf/bpf_helpers.h
@@ -158,6 +158,15 @@ struct bpf_map_def {
unsigned int numa_node;
};
+#define BPF_ANNOTATE_KV_PAIR(name, type_key, type_val) \
+ struct ____btf_map_##name { \
+ type_key key; \
+ type_val value; \
+ }; \
+ struct ____btf_map_##name \
+ __attribute__ ((section(".maps." #name), used)) \
+ ____btf_map_##name = { }
+
static int (*bpf_skb_load_bytes)(void *ctx, int off, void *to, int len) =
(void *) BPF_FUNC_skb_load_bytes;
static int (*bpf_skb_store_bytes)(void *ctx, int off, void *from, int len, int flags) =
diff --git a/tools/testing/selftests/bpf/test_btf_haskv.c b/tools/testing/selftests/bpf/test_btf_haskv.c
index 8c7ca096ecf2..b21b876f475d 100644
--- a/tools/testing/selftests/bpf/test_btf_haskv.c
+++ b/tools/testing/selftests/bpf/test_btf_haskv.c
@@ -10,11 +10,6 @@ struct ipv_counts {
unsigned int v6;
};
-typedef int btf_map_key;
-typedef struct ipv_counts btf_map_value;
-btf_map_key dumm_key;
-btf_map_value dummy_value;
-
struct bpf_map_def SEC("maps") btf_map = {
.type = BPF_MAP_TYPE_ARRAY,
.key_size = sizeof(int),
@@ -22,6 +17,8 @@ struct bpf_map_def SEC("maps") btf_map = {
.max_entries = 4,
};
+BPF_ANNOTATE_KV_PAIR(btf_map, int, struct ipv_counts);
+
struct dummy_tracepoint_args {
unsigned long long pad;
struct sock *sock;
--
2.17.1
^ permalink raw reply related
* [PATCH v2 bpf 1/3] bpf: btf: Sync uapi btf.h to tools
From: Martin KaFai Lau @ 2018-07-21 18:20 UTC (permalink / raw)
To: netdev; +Cc: Alexei Starovoitov, Daniel Borkmann, kernel-team
In-Reply-To: <20180721182043.1401089-1-kafai@fb.com>
This patch sync the uapi btf.h to tools/
Fixes: 36fc3c8c282c bpf: btf: Clean up BTF_INT_BITS() in uapi btf.h
Signed-off-by: Martin KaFai Lau <kafai@fb.com>
---
tools/include/uapi/linux/btf.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tools/include/uapi/linux/btf.h b/tools/include/uapi/linux/btf.h
index 0b5ddbe135a4..972265f32871 100644
--- a/tools/include/uapi/linux/btf.h
+++ b/tools/include/uapi/linux/btf.h
@@ -76,7 +76,7 @@ struct btf_type {
*/
#define BTF_INT_ENCODING(VAL) (((VAL) & 0x0f000000) >> 24)
#define BTF_INT_OFFSET(VAL) (((VAL & 0x00ff0000)) >> 16)
-#define BTF_INT_BITS(VAL) ((VAL) & 0x0000ffff)
+#define BTF_INT_BITS(VAL) ((VAL) & 0x000000ff)
/* Attributes stored in the BTF_INT_ENCODING */
#define BTF_INT_SIGNED (1 << 0)
--
2.17.1
^ permalink raw reply related
* [PATCH v2 bpf 2/3] bpf: Replace [u]int32_t and [u]int64_t in libbpf
From: Martin KaFai Lau @ 2018-07-21 18:20 UTC (permalink / raw)
To: netdev; +Cc: Alexei Starovoitov, Daniel Borkmann, kernel-team
In-Reply-To: <20180721182043.1401089-1-kafai@fb.com>
This patch replaces [u]int32_t and [u]int64_t usage with
__[su]32 and __[su]64. The same change goes for [u]int16_t
and [u]int8_t.
Fixes: 8a138aed4a80 ("bpf: btf: Add BTF support to libbpf")
Signed-off-by: Martin KaFai Lau <kafai@fb.com>
---
tools/lib/bpf/btf.c | 28 +++++++++++++---------------
tools/lib/bpf/btf.h | 8 ++++----
tools/lib/bpf/libbpf.c | 12 ++++++------
tools/lib/bpf/libbpf.h | 4 ++--
4 files changed, 25 insertions(+), 27 deletions(-)
diff --git a/tools/lib/bpf/btf.c b/tools/lib/bpf/btf.c
index 8c54a4b6f187..ce77b5b57912 100644
--- a/tools/lib/bpf/btf.c
+++ b/tools/lib/bpf/btf.c
@@ -2,7 +2,6 @@
/* Copyright (c) 2018 Facebook */
#include <stdlib.h>
-#include <stdint.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
@@ -27,13 +26,13 @@ struct btf {
struct btf_type **types;
const char *strings;
void *nohdr_data;
- uint32_t nr_types;
- uint32_t types_size;
- uint32_t data_size;
+ __u32 nr_types;
+ __u32 types_size;
+ __u32 data_size;
int fd;
};
-static const char *btf_name_by_offset(const struct btf *btf, uint32_t offset)
+static const char *btf_name_by_offset(const struct btf *btf, __u32 offset)
{
if (offset < btf->hdr->str_len)
return &btf->strings[offset];
@@ -151,7 +150,7 @@ static int btf_parse_type_sec(struct btf *btf, btf_print_fn_t err_log)
while (next_type < end_type) {
struct btf_type *t = next_type;
- uint16_t vlen = BTF_INFO_VLEN(t->info);
+ __u16 vlen = BTF_INFO_VLEN(t->info);
int err;
next_type += sizeof(*t);
@@ -191,7 +190,7 @@ static int btf_parse_type_sec(struct btf *btf, btf_print_fn_t err_log)
}
static const struct btf_type *btf_type_by_id(const struct btf *btf,
- uint32_t type_id)
+ __u32 type_id)
{
if (type_id > btf->nr_types)
return NULL;
@@ -226,12 +225,12 @@ static int64_t btf_type_size(const struct btf_type *t)
#define MAX_RESOLVE_DEPTH 32
-int64_t btf__resolve_size(const struct btf *btf, uint32_t type_id)
+__s64 btf__resolve_size(const struct btf *btf, __u32 type_id)
{
const struct btf_array *array;
const struct btf_type *t;
- uint32_t nelems = 1;
- int64_t size = -1;
+ __u32 nelems = 1;
+ __s64 size = -1;
int i;
t = btf_type_by_id(btf, type_id);
@@ -271,9 +270,9 @@ int64_t btf__resolve_size(const struct btf *btf, uint32_t type_id)
return nelems * size;
}
-int32_t btf__find_by_name(const struct btf *btf, const char *type_name)
+__s32 btf__find_by_name(const struct btf *btf, const char *type_name)
{
- uint32_t i;
+ __u32 i;
if (!strcmp(type_name, "void"))
return 0;
@@ -302,10 +301,9 @@ void btf__free(struct btf *btf)
free(btf);
}
-struct btf *btf__new(uint8_t *data, uint32_t size,
- btf_print_fn_t err_log)
+struct btf *btf__new(__u8 *data, __u32 size, btf_print_fn_t err_log)
{
- uint32_t log_buf_size = 0;
+ __u32 log_buf_size = 0;
char *log_buf = NULL;
struct btf *btf;
int err;
diff --git a/tools/lib/bpf/btf.h b/tools/lib/bpf/btf.h
index 74bb344035bb..ed3a84370ccc 100644
--- a/tools/lib/bpf/btf.h
+++ b/tools/lib/bpf/btf.h
@@ -4,7 +4,7 @@
#ifndef __BPF_BTF_H
#define __BPF_BTF_H
-#include <stdint.h>
+#include <linux/types.h>
#define BTF_ELF_SEC ".BTF"
@@ -14,9 +14,9 @@ typedef int (*btf_print_fn_t)(const char *, ...)
__attribute__((format(printf, 1, 2)));
void btf__free(struct btf *btf);
-struct btf *btf__new(uint8_t *data, uint32_t size, btf_print_fn_t err_log);
-int32_t btf__find_by_name(const struct btf *btf, const char *type_name);
-int64_t btf__resolve_size(const struct btf *btf, uint32_t type_id);
+struct btf *btf__new(__u8 *data, __u32 size, btf_print_fn_t err_log);
+__s32 btf__find_by_name(const struct btf *btf, const char *type_name);
+__s64 btf__resolve_size(const struct btf *btf, __u32 type_id);
int btf__fd(const struct btf *btf);
#endif
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index a1e96b5de5ff..6deb4fe4fffe 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -216,8 +216,8 @@ struct bpf_map {
size_t offset;
int map_ifindex;
struct bpf_map_def def;
- uint32_t btf_key_type_id;
- uint32_t btf_value_type_id;
+ __u32 btf_key_type_id;
+ __u32 btf_value_type_id;
void *priv;
bpf_map_clear_priv_t clear_priv;
};
@@ -1016,8 +1016,8 @@ static int bpf_map_find_btf_info(struct bpf_map *map, const struct btf *btf)
{
struct bpf_map_def *def = &map->def;
const size_t max_name = 256;
- int64_t key_size, value_size;
- int32_t key_id, value_id;
+ __s64 key_size, value_size;
+ __s32 key_id, value_id;
char name[max_name];
/* Find key type by name from BTF */
@@ -2089,12 +2089,12 @@ const char *bpf_map__name(struct bpf_map *map)
return map ? map->name : NULL;
}
-uint32_t bpf_map__btf_key_type_id(const struct bpf_map *map)
+__u32 bpf_map__btf_key_type_id(const struct bpf_map *map)
{
return map ? map->btf_key_type_id : 0;
}
-uint32_t bpf_map__btf_value_type_id(const struct bpf_map *map)
+__u32 bpf_map__btf_value_type_id(const struct bpf_map *map)
{
return map ? map->btf_value_type_id : 0;
}
diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h
index 09976531aa74..b33ae02f7d0e 100644
--- a/tools/lib/bpf/libbpf.h
+++ b/tools/lib/bpf/libbpf.h
@@ -244,8 +244,8 @@ bpf_map__next(struct bpf_map *map, struct bpf_object *obj);
int bpf_map__fd(struct bpf_map *map);
const struct bpf_map_def *bpf_map__def(struct bpf_map *map);
const char *bpf_map__name(struct bpf_map *map);
-uint32_t bpf_map__btf_key_type_id(const struct bpf_map *map);
-uint32_t bpf_map__btf_value_type_id(const struct bpf_map *map);
+__u32 bpf_map__btf_key_type_id(const struct bpf_map *map);
+__u32 bpf_map__btf_value_type_id(const struct bpf_map *map);
typedef void (*bpf_map_clear_priv_t)(struct bpf_map *, void *);
int bpf_map__set_priv(struct bpf_map *map, void *priv,
--
2.17.1
^ permalink raw reply related
* [PATCH v2 bpf 0/3] Introduce BPF_ANNOTATE_KV_PAIR
From: Martin KaFai Lau @ 2018-07-21 18:20 UTC (permalink / raw)
To: netdev; +Cc: Alexei Starovoitov, Daniel Borkmann, kernel-team
The series allows the BPF loader to figure out
the btf_key_id and btf_value_id from a map's name
by using BPF_ANNOTATE_KV_PAIR. It also removes
the old 'typedef' way which requires two separate
typedefs (one for the key and one for the value).
By doing this, iproute2 and libbpf have one
consistent way to figure out the btf_key_type_id and
btf_value_type_id for a map.
The first two patches are some prep/cleanup works.
The last patch introduces BPF_ANNOTATE_KV_PAIR.
v2:
- Fix the incorrect '&&' check on container_type
in bpf_map_find_btf_info().
- Expose the existing static btf_type_by_id() instead of
creating a new one.
Martin KaFai Lau (3):
bpf: btf: Sync uapi btf.h to tools
bpf: Replace [u]int32_t and [u]int64_t in libbpf
bpf: Introduce BPF_ANNOTATE_KV_PAIR
tools/include/uapi/linux/btf.h | 2 +-
tools/lib/bpf/btf.c | 33 ++++----
tools/lib/bpf/btf.h | 10 ++-
tools/lib/bpf/libbpf.c | 85 +++++++++++---------
tools/lib/bpf/libbpf.h | 4 +-
tools/testing/selftests/bpf/bpf_helpers.h | 9 +++
tools/testing/selftests/bpf/test_btf_haskv.c | 7 +-
7 files changed, 80 insertions(+), 70 deletions(-)
--
2.17.1
^ permalink raw reply
* Re: [RFC PATCH ghak90 (was ghak32) V3 09/10] debug audit: read container ID of a process
From: Richard Guy Briggs @ 2018-07-21 19:21 UTC (permalink / raw)
To: Paul Moore
Cc: simo, jlayton, carlos, linux-api, containers, linux-kernel,
Eric Paris, dhowells, linux-audit, ebiederm, luto, netdev,
linux-fsdevel, cgroups, serge, viro
In-Reply-To: <CAHC9VhRhHJV87g+4b2BMxnrpgPvNYMBa1RUQzK3xrK1yugBYzQ@mail.gmail.com>
On 2018-07-20 18:15, Paul Moore wrote:
> On Wed, Jun 6, 2018 at 1:02 PM Richard Guy Briggs <rgb@redhat.com> wrote:
> > Add support for reading the audit container identifier from the proc
> > filesystem.
> >
> > This is a read from the proc entry of the form
> > /proc/PID/audit_containerid where PID is the process ID of the task
> > whose audit container identifier is sought.
> >
> > The read expects up to a u64 value (unset: 18446744073709551615).
> >
> > Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
> > ---
> > fs/proc/base.c | 20 ++++++++++++++++++--
> > 1 file changed, 18 insertions(+), 2 deletions(-)
> >
> > diff --git a/fs/proc/base.c b/fs/proc/base.c
> > index 318dff4..ca8bfe2 100644
> > --- a/fs/proc/base.c
> > +++ b/fs/proc/base.c
> > @@ -1303,6 +1303,21 @@ static ssize_t proc_sessionid_read(struct file * file, char __user * buf,
> > .llseek = generic_file_llseek,
> > };
> >
> > +static ssize_t proc_contid_read(struct file *file, char __user *buf,
> > + size_t count, loff_t *ppos)
> > +{
> > + struct inode *inode = file_inode(file);
> > + struct task_struct *task = get_proc_task(inode);
> > + ssize_t length;
> > + char tmpbuf[TMPBUFLEN*2];
> > +
> > + if (!task)
> > + return -ESRCH;
> > + length = scnprintf(tmpbuf, TMPBUFLEN*2, "%llu", audit_get_contid(task));
> > + put_task_struct(task);
> > + return simple_read_from_buffer(buf, count, ppos, tmpbuf, length);
> > +}
>
> While I still remain very nervous about opening the audit container ID
> up for abuse by making it accessible, I understand that this would
> make things a lot easier us (e.g. testing) and perhaps the container
> engines as well. In order to limit the potential for abuse, what do
> you think about restricting read access to those processes which have
> CAP_AUDIT_CONTROL, similar to what we do for setting the audit
> container ID?
That seems like a reasonable restriction.
> > static ssize_t proc_contid_write(struct file *file, const char __user *buf,
> > size_t count, loff_t *ppos)
> > {
> > @@ -1333,6 +1348,7 @@ static ssize_t proc_contid_write(struct file *file, const char __user *buf,
> > }
> >
> > static const struct file_operations proc_contid_operations = {
> > + .read = proc_contid_read,
> > .write = proc_contid_write,
> > .llseek = generic_file_llseek,
> > };
> > @@ -3030,7 +3046,7 @@ static int proc_pid_patch_state(struct seq_file *m, struct pid_namespace *ns,
> > #ifdef CONFIG_AUDITSYSCALL
> > REG("loginuid", S_IWUSR|S_IRUGO, proc_loginuid_operations),
> > REG("sessionid", S_IRUGO, proc_sessionid_operations),
> > - REG("audit_containerid", S_IWUSR, proc_contid_operations),
> > + REG("audit_containerid", S_IWUSR|S_IRUSR, proc_contid_operations),
> > #endif
> > #ifdef CONFIG_FAULT_INJECTION
> > REG("make-it-fail", S_IRUGO|S_IWUSR, proc_fault_inject_operations),
> > @@ -3422,7 +3438,7 @@ static int proc_tid_comm_permission(struct inode *inode, int mask)
> > #ifdef CONFIG_AUDITSYSCALL
> > REG("loginuid", S_IWUSR|S_IRUGO, proc_loginuid_operations),
> > REG("sessionid", S_IRUGO, proc_sessionid_operations),
> > - REG("audit_containerid", S_IWUSR, proc_contid_operations),
> > + REG("audit_containerid", S_IWUSR|S_IRUSR, proc_contid_operations),
> > #endif
> > #ifdef CONFIG_FAULT_INJECTION
> > REG("make-it-fail", S_IRUGO|S_IWUSR, proc_fault_inject_operations),
>
> --
> paul moore
> www.paul-moore.com
- RGB
--
Richard Guy Briggs <rgb@redhat.com>
Sr. S/W Engineer, Kernel Security, Base Operating Systems
Remote, Ottawa, Red Hat Canada
IRC: rgb, SunRaycer
Voice: +1.647.777.2635, Internal: (81) 32635
^ permalink raw reply
* [PATCH 0/4] net: Add support for Lantiq / Intel vrx200 network
From: Hauke Mehrtens @ 2018-07-21 19:13 UTC (permalink / raw)
To: davem
Cc: netdev, andrew, vivien.didelot, f.fainelli, john, linux-mips, dev,
hauke.mehrtens, Hauke Mehrtens
This adds basic support for the GSWIP (Gigabit Switch) found in the
VRX200 SoC.
There are different versions of this IP core used in different SoCs, but
this driver was currently only tested on the VRX200 SoC line, for other
SoCs this driver probably need some adoptions to work.
I also plan to add Layer 2 offloading to the DSA driver and later also
layer 3 offloading which is supported by the PPE HW block.
Hauke Mehrtens (4):
MIPS: lantiq: Do not enable IRQs in dma open
net: dsa: Add Lantiq / Intel GSWIP tag support
net: lantiq: Add Lantiq / Intel vrx200 Ethernet driver
net: dsa: Add Lantiq / Intel DSA driver for vrx200
MAINTAINERS | 9 +
arch/mips/lantiq/xway/dma.c | 1 -
arch/mips/lantiq/xway/sysctrl.c | 2 +-
drivers/net/dsa/Kconfig | 8 +
drivers/net/dsa/Makefile | 1 +
drivers/net/dsa/lantiq-gswip.c | 750 +++++++++++++++++++++++++++++++++++
drivers/net/dsa/lantiq_pce.h | 153 +++++++
drivers/net/ethernet/Kconfig | 6 +
drivers/net/ethernet/Makefile | 1 +
drivers/net/ethernet/lantiq_etop.c | 1 +
drivers/net/ethernet/lantiq_xrx200.c | 609 ++++++++++++++++++++++++++++
include/net/dsa.h | 1 +
net/dsa/Kconfig | 3 +
net/dsa/Makefile | 1 +
net/dsa/dsa.c | 3 +
net/dsa/dsa_priv.h | 3 +
net/dsa/tag_gswip.c | 110 +++++
17 files changed, 1660 insertions(+), 2 deletions(-)
create mode 100644 drivers/net/dsa/lantiq-gswip.c
create mode 100644 drivers/net/dsa/lantiq_pce.h
create mode 100644 drivers/net/ethernet/lantiq_xrx200.c
create mode 100644 net/dsa/tag_gswip.c
--
2.11.0
^ permalink raw reply
* [PATCH 1/4] MIPS: lantiq: Do not enable IRQs in dma open
From: Hauke Mehrtens @ 2018-07-21 19:13 UTC (permalink / raw)
To: davem
Cc: netdev, andrew, vivien.didelot, f.fainelli, john, linux-mips, dev,
hauke.mehrtens, Hauke Mehrtens
In-Reply-To: <20180721191358.13952-1-hauke@hauke-m.de>
When a DMA channel is opened the IRQ should not get activated
automatically, this allows it to pull data out manually without the help
of interrupts. This is needed for a workaround in the vrx200 Ethernet
driver.
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
---
arch/mips/lantiq/xway/dma.c | 1 -
drivers/net/ethernet/lantiq_etop.c | 1 +
2 files changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/mips/lantiq/xway/dma.c b/arch/mips/lantiq/xway/dma.c
index 4b9fbb6744ad..3a90bb4edacc 100644
--- a/arch/mips/lantiq/xway/dma.c
+++ b/arch/mips/lantiq/xway/dma.c
@@ -106,7 +106,6 @@ ltq_dma_open(struct ltq_dma_channel *ch)
spin_lock_irqsave(<q_dma_lock, flag);
ltq_dma_w32(ch->nr, LTQ_DMA_CS);
ltq_dma_w32_mask(0, DMA_CHAN_ON, LTQ_DMA_CCTRL);
- ltq_dma_w32_mask(0, 1 << ch->nr, LTQ_DMA_IRNEN);
spin_unlock_irqrestore(<q_dma_lock, flag);
}
EXPORT_SYMBOL_GPL(ltq_dma_open);
diff --git a/drivers/net/ethernet/lantiq_etop.c b/drivers/net/ethernet/lantiq_etop.c
index afc810069440..c978a857a25c 100644
--- a/drivers/net/ethernet/lantiq_etop.c
+++ b/drivers/net/ethernet/lantiq_etop.c
@@ -438,6 +438,7 @@ ltq_etop_open(struct net_device *dev)
if (!IS_TX(i) && (!IS_RX(i)))
continue;
ltq_dma_open(&ch->dma);
+ ltq_dma_enable_irq(&ch->dma);
napi_enable(&ch->napi);
}
phy_start(dev->phydev);
--
2.11.0
^ permalink raw reply related
* [PATCH 2/4] net: dsa: Add Lantiq / Intel GSWIP tag support
From: Hauke Mehrtens @ 2018-07-21 19:13 UTC (permalink / raw)
To: davem
Cc: netdev, andrew, vivien.didelot, f.fainelli, john, linux-mips, dev,
hauke.mehrtens, Hauke Mehrtens
In-Reply-To: <20180721191358.13952-1-hauke@hauke-m.de>
This handles the tag added by the PMAC on the VRX200 SoC line.
The GSWIP uses internally a GSWIP special tag which is located after the
Ethernet header. The PMAC which connects the GSWIP to the CPU converts
this special tag used by the GSWIP into the PMAC special tag which is
added in front of the Ethernet header.
This was tested with GSWIP 2.0 found in the VRX200 SoCs, other GSWIP
versions use slightly different PMAC special tags
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
---
MAINTAINERS | 6 +++
include/net/dsa.h | 1 +
net/dsa/Kconfig | 3 ++
net/dsa/Makefile | 1 +
net/dsa/dsa.c | 3 ++
net/dsa/dsa_priv.h | 3 ++
net/dsa/tag_gswip.c | 110 ++++++++++++++++++++++++++++++++++++++++++++++++++++
7 files changed, 127 insertions(+)
create mode 100644 net/dsa/tag_gswip.c
diff --git a/MAINTAINERS b/MAINTAINERS
index 192d7f73fd01..741718ff9b79 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -8009,6 +8009,12 @@ S: Maintained
F: net/l3mdev
F: include/net/l3mdev.h
+LANTIQ / INTEL Ethernet drivers
+M: Hauke Mehrtens <hauke@hauke-m.de>
+L: netdev@vger.kernel.org
+S: Maintained
+F: net/dsa/tag_gswip.c
+
LANTIQ MIPS ARCHITECTURE
M: John Crispin <john@phrozen.org>
L: linux-mips@linux-mips.org
diff --git a/include/net/dsa.h b/include/net/dsa.h
index fdbd6082945d..60bc8952e29b 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -35,6 +35,7 @@ enum dsa_tag_protocol {
DSA_TAG_PROTO_BRCM_PREPEND,
DSA_TAG_PROTO_DSA,
DSA_TAG_PROTO_EDSA,
+ DSA_TAG_PROTO_GSWIP,
DSA_TAG_PROTO_KSZ,
DSA_TAG_PROTO_LAN9303,
DSA_TAG_PROTO_MTK,
diff --git a/net/dsa/Kconfig b/net/dsa/Kconfig
index 4183e4ba27a5..48c41918fb35 100644
--- a/net/dsa/Kconfig
+++ b/net/dsa/Kconfig
@@ -38,6 +38,9 @@ config NET_DSA_TAG_DSA
config NET_DSA_TAG_EDSA
bool
+config NET_DSA_TAG_GSWIP
+ bool
+
config NET_DSA_TAG_KSZ
bool
diff --git a/net/dsa/Makefile b/net/dsa/Makefile
index 9e4d3536f977..6e721f7a2947 100644
--- a/net/dsa/Makefile
+++ b/net/dsa/Makefile
@@ -9,6 +9,7 @@ dsa_core-$(CONFIG_NET_DSA_TAG_BRCM) += tag_brcm.o
dsa_core-$(CONFIG_NET_DSA_TAG_BRCM_PREPEND) += tag_brcm.o
dsa_core-$(CONFIG_NET_DSA_TAG_DSA) += tag_dsa.o
dsa_core-$(CONFIG_NET_DSA_TAG_EDSA) += tag_edsa.o
+dsa_core-$(CONFIG_NET_DSA_TAG_GSWIP) += tag_gswip.o
dsa_core-$(CONFIG_NET_DSA_TAG_KSZ) += tag_ksz.o
dsa_core-$(CONFIG_NET_DSA_TAG_LAN9303) += tag_lan9303.o
dsa_core-$(CONFIG_NET_DSA_TAG_MTK) += tag_mtk.o
diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c
index e63c554e0623..81212109c507 100644
--- a/net/dsa/dsa.c
+++ b/net/dsa/dsa.c
@@ -54,6 +54,9 @@ const struct dsa_device_ops *dsa_device_ops[DSA_TAG_LAST] = {
#ifdef CONFIG_NET_DSA_TAG_EDSA
[DSA_TAG_PROTO_EDSA] = &edsa_netdev_ops,
#endif
+#ifdef CONFIG_NET_DSA_TAG_GSWIP
+ [DSA_TAG_PROTO_GSWIP] = &gswip_netdev_ops,
+#endif
#ifdef CONFIG_NET_DSA_TAG_KSZ
[DSA_TAG_PROTO_KSZ] = &ksz_netdev_ops,
#endif
diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h
index 3964c6f7a7c0..824ca07a30aa 100644
--- a/net/dsa/dsa_priv.h
+++ b/net/dsa/dsa_priv.h
@@ -205,6 +205,9 @@ extern const struct dsa_device_ops dsa_netdev_ops;
/* tag_edsa.c */
extern const struct dsa_device_ops edsa_netdev_ops;
+/* tag_gswip.c */
+extern const struct dsa_device_ops gswip_netdev_ops;
+
/* tag_ksz.c */
extern const struct dsa_device_ops ksz_netdev_ops;
diff --git a/net/dsa/tag_gswip.c b/net/dsa/tag_gswip.c
new file mode 100644
index 000000000000..cb559768c87f
--- /dev/null
+++ b/net/dsa/tag_gswip.c
@@ -0,0 +1,110 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Intel / Lantiq GSWIP tag support
+ *
+ * Copyright (C) 2017 - 2018 Hauke Mehrtens <hauke@hauke-m.de>
+ */
+
+#include <linux/bitops.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <net/dsa.h>
+
+#include "dsa_priv.h"
+
+
+#define GSWIP_TX_HEADER_LEN 4
+
+/* special tag in TX path header */
+/* Byte 0 */
+#define GSWIP_TX_DPID_EN BIT(0)
+#define GSWIP_TX_PORT_MAP_SHIFT 1
+#define GSWIP_TX_PORT_MAP_MASK GENMASK(6, 1)
+
+/* Byte 1 */
+#define GSWIP_TX_CLASS_SHIFT 0
+#define GSWIP_TX_CLASS_MASK GENMASK(3, 0)
+#define GSWIP_TX_CLASS_EN BIT(4)
+#define GSWIP_TX_LRN_DIS BIT(5)
+#define GSWIP_TX_PORT_MAP_SEL BIT(6)
+#define GSWIP_TX_PORT_MAP_EN BIT(7)
+
+/* Byte 2 */
+#define GSWIP_TX_DPID_SHIFT 0 /* destination group ID */
+#define GSWIP_TX_DPID_ELAN 0
+#define GSWIP_TX_DPID_EWAN 1
+#define GSWIP_TX_DPID_CPU 2
+#define GSWIP_TX_DPID_APP1 3
+#define GSWIP_TX_DPID_APP2 4
+#define GSWIP_TX_DPID_APP3 5
+#define GSWIP_TX_DPID_APP4 6
+#define GSWIP_TX_DPID_APP5 7
+
+/* Byte 3 */
+#define GSWIP_TX_CRCGEN_DIS BIT(23)
+#define GSWIP_TX_SLPID_SHIFT 0 /* source port ID */
+#define GSWIP_TX_SLPID_CPU 2
+#define GSWIP_TX_SLPID_APP1 3
+#define GSWIP_TX_SLPID_APP2 4
+#define GSWIP_TX_SLPID_APP3 5
+#define GSWIP_TX_SLPID_APP4 6
+#define GSWIP_TX_SLPID_APP5 7
+
+
+#define GSWIP_RX_HEADER_LEN 8
+
+/* special tag in RX path header */
+/* Byte 7 */
+#define GSWIP_RX_SPPID_SHIFT 4
+#define GSWIP_RX_SPPID_MASK GENMASK(6, 4)
+
+
+static struct sk_buff *gswip_tag_xmit(struct sk_buff *skb,
+ struct net_device *dev)
+{
+ struct dsa_port *dp = dsa_slave_to_port(dev);
+ int err;
+ u8 *gswip_tag;
+
+ err = skb_cow_head(skb, GSWIP_TX_HEADER_LEN);
+ if (err)
+ return NULL;
+
+ skb_push(skb, GSWIP_TX_HEADER_LEN);
+
+ gswip_tag = skb->data;
+ gswip_tag[0] = GSWIP_TX_SLPID_CPU;
+ gswip_tag[1] = GSWIP_TX_DPID_ELAN;
+ gswip_tag[2] = GSWIP_TX_PORT_MAP_EN | GSWIP_TX_PORT_MAP_SEL;
+ gswip_tag[3] = BIT(dp->index + GSWIP_TX_PORT_MAP_SHIFT) & GSWIP_TX_PORT_MAP_MASK;
+ gswip_tag[3] |= GSWIP_TX_DPID_EN;
+
+ return skb;
+}
+
+static struct sk_buff *gswip_tag_rcv(struct sk_buff *skb,
+ struct net_device *dev,
+ struct packet_type *pt)
+{
+ int port;
+ u8 *gswip_tag;
+
+ if (unlikely(!pskb_may_pull(skb, GSWIP_RX_HEADER_LEN)))
+ return NULL;
+
+ gswip_tag = ((u8 *)skb->data) - ETH_HLEN;
+ skb_pull_rcsum(skb, GSWIP_RX_HEADER_LEN);
+
+ /* Get source port information */
+ port = (gswip_tag[7] & GSWIP_RX_SPPID_MASK) >> GSWIP_RX_SPPID_SHIFT;
+ skb->dev = dsa_master_find_slave(dev, 0, port);
+ if (!skb->dev)
+ return NULL;
+
+ return skb;
+}
+
+const struct dsa_device_ops gswip_netdev_ops = {
+ .xmit = gswip_tag_xmit,
+ .rcv = gswip_tag_rcv,
+};
--
2.11.0
^ permalink raw reply related
* [PATCH 3/4] net: lantiq: Add Lantiq / Intel vrx200 Ethernet driver
From: Hauke Mehrtens @ 2018-07-21 19:13 UTC (permalink / raw)
To: davem
Cc: netdev, andrew, vivien.didelot, f.fainelli, john, linux-mips, dev,
hauke.mehrtens, Hauke Mehrtens
In-Reply-To: <20180721191358.13952-1-hauke@hauke-m.de>
This drives the PMAC between the GSWIP Switch and the CPU in the VRX200
SoC. This is currently only the very basic version of the Ethernet
driver.
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
---
MAINTAINERS | 2 +
arch/mips/lantiq/xway/sysctrl.c | 2 +-
drivers/net/ethernet/Kconfig | 6 +
drivers/net/ethernet/Makefile | 1 +
drivers/net/ethernet/lantiq_xrx200.c | 609 +++++++++++++++++++++++++++++++++++
5 files changed, 619 insertions(+), 1 deletion(-)
create mode 100644 drivers/net/ethernet/lantiq_xrx200.c
diff --git a/MAINTAINERS b/MAINTAINERS
index 741718ff9b79..cc0607a58c51 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -8014,6 +8014,8 @@ M: Hauke Mehrtens <hauke@hauke-m.de>
L: netdev@vger.kernel.org
S: Maintained
F: net/dsa/tag_gswip.c
+F: drivers/net/ethernet/lantiq_xrx200.c
+F: drivers/net/dsa/lantiq_pce.h
LANTIQ MIPS ARCHITECTURE
M: John Crispin <john@phrozen.org>
diff --git a/arch/mips/lantiq/xway/sysctrl.c b/arch/mips/lantiq/xway/sysctrl.c
index e0af39b33e28..c704312ef7d5 100644
--- a/arch/mips/lantiq/xway/sysctrl.c
+++ b/arch/mips/lantiq/xway/sysctrl.c
@@ -536,7 +536,7 @@ void __init ltq_soc_init(void)
clkdev_add_pmu(NULL, "ahb", 1, 0, PMU_AHBM | PMU_AHBS);
clkdev_add_pmu("1da00000.usif", "NULL", 1, 0, PMU_USIF);
- clkdev_add_pmu("1e108000.eth", NULL, 0, 0,
+ clkdev_add_pmu("1e10b308.eth", NULL, 0, 0,
PMU_SWITCH | PMU_PPE_DPLUS | PMU_PPE_DPLUM |
PMU_PPE_EMA | PMU_PPE_TC | PMU_PPE_SLL01 |
PMU_PPE_QSB | PMU_PPE_TOP);
diff --git a/drivers/net/ethernet/Kconfig b/drivers/net/ethernet/Kconfig
index af766fd61151..1767f2ee1795 100644
--- a/drivers/net/ethernet/Kconfig
+++ b/drivers/net/ethernet/Kconfig
@@ -109,6 +109,12 @@ config LANTIQ_ETOP
---help---
Support for the MII0 inside the Lantiq SoC
+config LANTIQ_XRX200
+ tristate "Lantiq SoC XRX200 driver"
+ depends on SOC_TYPE_XWAY
+ ---help---
+ Support for the PMAC of the GSWIP inside the Lantiq VRX200 VDSL SoC
+
source "drivers/net/ethernet/marvell/Kconfig"
source "drivers/net/ethernet/mediatek/Kconfig"
source "drivers/net/ethernet/mellanox/Kconfig"
diff --git a/drivers/net/ethernet/Makefile b/drivers/net/ethernet/Makefile
index 8fbfe9ce2fa5..839322f353ca 100644
--- a/drivers/net/ethernet/Makefile
+++ b/drivers/net/ethernet/Makefile
@@ -50,6 +50,7 @@ obj-$(CONFIG_NET_VENDOR_XSCALE) += xscale/
obj-$(CONFIG_JME) += jme.o
obj-$(CONFIG_KORINA) += korina.o
obj-$(CONFIG_LANTIQ_ETOP) += lantiq_etop.o
+obj-$(CONFIG_LANTIQ_XRX200) += lantiq_xrx200.o
obj-$(CONFIG_NET_VENDOR_MARVELL) += marvell/
obj-$(CONFIG_NET_VENDOR_MEDIATEK) += mediatek/
obj-$(CONFIG_NET_VENDOR_MELLANOX) += mellanox/
diff --git a/drivers/net/ethernet/lantiq_xrx200.c b/drivers/net/ethernet/lantiq_xrx200.c
new file mode 100644
index 000000000000..e31a6ce3c84c
--- /dev/null
+++ b/drivers/net/ethernet/lantiq_xrx200.c
@@ -0,0 +1,609 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Lantiq / Intel PMAC driver for XRX200 SoCs
+ *
+ * Copyright (C) 2010 Lantiq Deutschland
+ * Copyright (C) 2012 John Crispin <blogic@openwrt.org>
+ * Copyright (C) 2017 - 2018 Hauke Mehrtens <hauke@hauke-m.de>
+ */
+
+#include <linux/etherdevice.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+
+#include <linux/of_net.h>
+#include <linux/of_platform.h>
+
+#include <xway_dma.h>
+
+/* DMA */
+#define XRX200_DMA_DATA_LEN 0x600
+#define XRX200_DMA_RX 0
+#define XRX200_DMA_TX 1
+
+
+/* cpu port mac */
+#define PMAC_RX_IPG 0x0024
+#define PMAC_RX_IPG_MASK 0xf
+
+#define PMAC_HD_CTL 0x0000
+/* Add Ethernet header to packets from DMA to PMAC */
+#define PMAC_HD_CTL_ADD BIT(0)
+/* Add VLAN tag to Packets from DMA to PMAC */
+#define PMAC_HD_CTL_TAG BIT(1)
+/* Add CRC to packets from DMA to PMAC */
+#define PMAC_HD_CTL_AC BIT(2)
+/* Add status header to packets from PMAC to DMA */
+#define PMAC_HD_CTL_AS BIT(3)
+/* Remove CRC from packets from PMAC to DMA */
+#define PMAC_HD_CTL_RC BIT(4)
+/* Remove Layer-2 header from packets from PMAC to DMA */
+#define PMAC_HD_CTL_RL2 BIT(5)
+/* Status header is present from DMA to PMAC */
+#define PMAC_HD_CTL_RXSH BIT(6)
+/* Add special tag from PMAC to switch */
+#define PMAC_HD_CTL_AST BIT(7)
+/* Remove specail Tag from PMAC to DMA */
+#define PMAC_HD_CTL_RST BIT(8)
+/* Check CRC from DMA to PMAC */
+#define PMAC_HD_CTL_CCRC BIT(9)
+/* Enable reaction to Pause frames in the PMAC */
+#define PMAC_HD_CTL_FC BIT(10)
+
+
+struct xrx200_chan {
+ int tx_free;
+
+ struct tasklet_struct tasklet;
+ struct napi_struct napi;
+ struct ltq_dma_channel dma;
+ struct sk_buff *skb[LTQ_DESC_NUM];
+
+ struct xrx200_priv *priv;
+};
+
+struct xrx200_priv {
+ struct net_device_stats stats;
+
+ struct clk *clk;
+
+ struct xrx200_chan chan_tx;
+ struct xrx200_chan chan_rx;
+
+ struct net_device *net_dev;
+ struct device *dev;
+
+ __iomem void *pmac_reg;
+};
+
+static u32 xrx200_pmac_r32(struct xrx200_priv *priv, u32 offset)
+{
+ return __raw_readl(priv->pmac_reg + offset);
+}
+
+static void xrx200_pmac_w32(struct xrx200_priv *priv, u32 val, u32 offset)
+{
+ return __raw_writel(val, priv->pmac_reg + offset);
+}
+
+static void xrx200_pmac_mask(struct xrx200_priv *priv, u32 clear, u32 set,
+ u32 offset)
+{
+ u32 val = xrx200_pmac_r32(priv, offset);
+
+ val &= ~(clear);
+ val |= set;
+ xrx200_pmac_w32(priv, val, offset);
+}
+
+/* drop all the packets from the DMA ring */
+static void xrx200_flush_dma(struct xrx200_chan *ch)
+{
+ int i;
+
+ for (i = 0; i < LTQ_DESC_NUM; i++) {
+ struct ltq_dma_desc *desc = &ch->dma.desc_base[ch->dma.desc];
+
+ if ((desc->ctl & (LTQ_DMA_OWN | LTQ_DMA_C)) != LTQ_DMA_C)
+ break;
+
+ desc->ctl = LTQ_DMA_OWN | LTQ_DMA_RX_OFFSET(NET_IP_ALIGN) |
+ XRX200_DMA_DATA_LEN;
+ ch->dma.desc++;
+ ch->dma.desc %= LTQ_DESC_NUM;
+ }
+}
+
+static int xrx200_open(struct net_device *dev)
+{
+ struct xrx200_priv *priv = netdev_priv(dev);
+
+ ltq_dma_open(&priv->chan_tx.dma);
+ ltq_dma_enable_irq(&priv->chan_tx.dma);
+
+ napi_enable(&priv->chan_rx.napi);
+ ltq_dma_open(&priv->chan_rx.dma);
+ /* The boot loader does not always deactivate the receiving of frames
+ * on the ports and then some packets queue up in the PPE buffers.
+ * They already passed the PMAC so they do not have the tags
+ * configured here. Read the these packets here and drop them.
+ * The HW should have written them into memory after 10us
+ */
+ udelay(10);
+ xrx200_flush_dma(&priv->chan_rx);
+ ltq_dma_enable_irq(&priv->chan_rx.dma);
+
+ netif_wake_queue(dev);
+
+ return 0;
+}
+
+static int xrx200_close(struct net_device *dev)
+{
+ struct xrx200_priv *priv = netdev_priv(dev);
+
+ netif_stop_queue(dev);
+
+ napi_disable(&priv->chan_rx.napi);
+ ltq_dma_close(&priv->chan_rx.dma);
+
+ ltq_dma_close(&priv->chan_tx.dma);
+
+ return 0;
+}
+
+static int xrx200_alloc_skb(struct xrx200_chan *ch)
+{
+ int ret = 0;
+
+#define DMA_PAD (NET_IP_ALIGN + NET_SKB_PAD)
+ ch->skb[ch->dma.desc] = dev_alloc_skb(XRX200_DMA_DATA_LEN + DMA_PAD);
+ if (!ch->skb[ch->dma.desc]) {
+ ret = -ENOMEM;
+ goto skip;
+ }
+
+ skb_reserve(ch->skb[ch->dma.desc], NET_SKB_PAD);
+ ch->dma.desc_base[ch->dma.desc].addr = dma_map_single(ch->priv->dev,
+ ch->skb[ch->dma.desc]->data, XRX200_DMA_DATA_LEN,
+ DMA_FROM_DEVICE);
+ if (unlikely(dma_mapping_error(ch->priv->dev,
+ ch->dma.desc_base[ch->dma.desc].addr))) {
+ dev_kfree_skb_any(ch->skb[ch->dma.desc]);
+ ret = -ENOMEM;
+ goto skip;
+ }
+
+ ch->dma.desc_base[ch->dma.desc].addr =
+ CPHYSADDR(ch->skb[ch->dma.desc]->data);
+ skb_reserve(ch->skb[ch->dma.desc], NET_IP_ALIGN);
+
+skip:
+ ch->dma.desc_base[ch->dma.desc].ctl =
+ LTQ_DMA_OWN | LTQ_DMA_RX_OFFSET(NET_IP_ALIGN) |
+ XRX200_DMA_DATA_LEN;
+
+ return ret;
+}
+
+static int xrx200_hw_receive(struct xrx200_chan *ch)
+{
+ struct xrx200_priv *priv = ch->priv;
+ struct ltq_dma_desc *desc = &ch->dma.desc_base[ch->dma.desc];
+ struct sk_buff *skb = ch->skb[ch->dma.desc];
+ int len = (desc->ctl & LTQ_DMA_SIZE_MASK);
+ int ret;
+
+ ret = xrx200_alloc_skb(ch);
+
+ ch->dma.desc++;
+ ch->dma.desc %= LTQ_DESC_NUM;
+
+ if (ret) {
+ netdev_err(priv->net_dev,
+ "failed to allocate new rx buffer\n");
+ return ret;
+ }
+
+ skb_put(skb, len);
+ skb->dev = priv->net_dev;
+ skb->protocol = eth_type_trans(skb, priv->net_dev);
+ netif_receive_skb(skb);
+ priv->stats.rx_packets++;
+ priv->stats.rx_bytes += len;
+
+ return 0;
+}
+
+static int xrx200_poll_rx(struct napi_struct *napi, int budget)
+{
+ struct xrx200_chan *ch = container_of(napi,
+ struct xrx200_chan, napi);
+ int rx = 0;
+ int ret;
+
+ while (rx < budget) {
+ struct ltq_dma_desc *desc = &ch->dma.desc_base[ch->dma.desc];
+
+ if ((desc->ctl & (LTQ_DMA_OWN | LTQ_DMA_C)) == LTQ_DMA_C) {
+ ret = xrx200_hw_receive(ch);
+ if (ret)
+ return ret;
+ rx++;
+ } else {
+ break;
+ }
+ }
+
+ if (rx < budget) {
+ napi_complete(&ch->napi);
+ ltq_dma_enable_irq(&ch->dma);
+ }
+
+ return rx;
+}
+
+static void xrx200_tx_housekeeping(unsigned long ptr)
+{
+ struct xrx200_chan *ch = (struct xrx200_chan *)ptr;
+ int pkts = 0;
+ int bytes = 0;
+
+ ltq_dma_ack_irq(&ch->dma);
+ while ((ch->dma.desc_base[ch->tx_free].ctl &
+ (LTQ_DMA_OWN | LTQ_DMA_C)) == LTQ_DMA_C) {
+ struct sk_buff *skb = ch->skb[ch->tx_free];
+
+ pkts++;
+ bytes += skb->len;
+ ch->skb[ch->tx_free] = NULL;
+ dev_kfree_skb(skb);
+ memset(&ch->dma.desc_base[ch->tx_free], 0,
+ sizeof(struct ltq_dma_desc));
+ ch->tx_free++;
+ ch->tx_free %= LTQ_DESC_NUM;
+ }
+ ltq_dma_enable_irq(&ch->dma);
+
+ netdev_completed_queue(ch->priv->net_dev, pkts, bytes);
+
+ if (!pkts)
+ return;
+
+ netif_wake_queue(ch->priv->net_dev);
+}
+
+static struct net_device_stats *xrx200_get_stats(struct net_device *dev)
+{
+ struct xrx200_priv *priv = netdev_priv(dev);
+
+ return &priv->stats;
+}
+
+static int xrx200_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ struct xrx200_priv *priv = netdev_priv(dev);
+ struct xrx200_chan *ch;
+ struct ltq_dma_desc *desc;
+ u32 byte_offset;
+ dma_addr_t mapping;
+ int len;
+
+ ch = &priv->chan_tx;
+
+ desc = &ch->dma.desc_base[ch->dma.desc];
+
+ skb->dev = dev;
+ len = skb->len < ETH_ZLEN ? ETH_ZLEN : skb->len;
+
+ /* dma needs to start on a 16 byte aligned address */
+ byte_offset = CPHYSADDR(skb->data) % 16;
+
+ if ((desc->ctl & (LTQ_DMA_OWN | LTQ_DMA_C)) || ch->skb[ch->dma.desc]) {
+ netdev_err(dev, "tx ring full\n");
+ netif_stop_queue(dev);
+ return NETDEV_TX_BUSY;
+ }
+
+ ch->skb[ch->dma.desc] = skb;
+
+ netif_trans_update(dev);
+
+ mapping = dma_map_single(priv->dev, skb->data, len, DMA_TO_DEVICE);
+ if (unlikely(dma_mapping_error(priv->dev, mapping)))
+ goto err_drop;
+
+ desc->addr = mapping - byte_offset;
+ /* Make sure the address is written before we give it to HW */
+ wmb();
+ desc->ctl = LTQ_DMA_OWN | LTQ_DMA_SOP | LTQ_DMA_EOP |
+ LTQ_DMA_TX_OFFSET(byte_offset) | (len & LTQ_DMA_SIZE_MASK);
+ ch->dma.desc++;
+ ch->dma.desc %= LTQ_DESC_NUM;
+ if (ch->dma.desc == ch->tx_free)
+ netif_stop_queue(dev);
+
+ netdev_sent_queue(dev, skb->len);
+ priv->stats.tx_packets++;
+ priv->stats.tx_bytes += len;
+
+ return NETDEV_TX_OK;
+
+err_drop:
+ dev_kfree_skb(skb);
+ priv->stats.tx_dropped++;
+ priv->stats.tx_errors++;
+ return NETDEV_TX_OK;
+}
+
+static const struct net_device_ops xrx200_netdev_ops = {
+ .ndo_open = xrx200_open,
+ .ndo_stop = xrx200_close,
+ .ndo_start_xmit = xrx200_start_xmit,
+ .ndo_set_mac_address = eth_mac_addr,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_change_mtu = eth_change_mtu,
+ .ndo_get_stats = xrx200_get_stats,
+};
+
+static irqreturn_t xrx200_dma_irq_tx(int irq, void *ptr)
+{
+ struct xrx200_priv *priv = ptr;
+ struct xrx200_chan *ch = &priv->chan_tx;
+
+ ltq_dma_disable_irq(&ch->dma);
+ ltq_dma_ack_irq(&ch->dma);
+
+ tasklet_schedule(&ch->tasklet);
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t xrx200_dma_irq_rx(int irq, void *ptr)
+{
+ struct xrx200_priv *priv = ptr;
+ struct xrx200_chan *ch = &priv->chan_rx;
+
+ ltq_dma_disable_irq(&ch->dma);
+ ltq_dma_ack_irq(&ch->dma);
+
+ napi_schedule(&ch->napi);
+
+ return IRQ_HANDLED;
+}
+
+static int xrx200_dma_init(struct xrx200_priv *priv)
+{
+ struct xrx200_chan *ch_rx = &priv->chan_rx;
+ struct xrx200_chan *ch_tx = &priv->chan_tx;
+ int ret = 0;
+ int i;
+
+ ltq_dma_init_port(DMA_PORT_ETOP);
+
+ ch_rx->dma.nr = XRX200_DMA_RX;
+ ch_rx->priv = priv;
+
+ ltq_dma_alloc_rx(&ch_rx->dma);
+ for (ch_rx->dma.desc = 0; ch_rx->dma.desc < LTQ_DESC_NUM;
+ ch_rx->dma.desc++) {
+ ret = xrx200_alloc_skb(ch_rx);
+ if (ret)
+ goto rx_free;
+ }
+ ch_rx->dma.desc = 0;
+ ret = devm_request_irq(priv->dev, ch_rx->dma.irq, xrx200_dma_irq_rx, 0,
+ "xrx200_net_rx", priv);
+ if (ret) {
+ dev_err(priv->dev, "failed to request RX irq %d\n",
+ ch_rx->dma.irq);
+ goto rx_ring_free;
+ }
+
+ ch_tx->dma.nr = XRX200_DMA_TX;
+ ch_tx->priv = priv;
+
+ ltq_dma_alloc_tx(&ch_tx->dma);
+ ret = devm_request_irq(priv->dev, ch_tx->dma.irq, xrx200_dma_irq_tx, 0,
+ "xrx200_net_tx", priv);
+ if (ret) {
+ dev_err(priv->dev, "failed to request TX irq %d\n",
+ ch_tx->dma.irq);
+ goto tx_free;
+ }
+
+ return ret;
+
+tx_free:
+ ltq_dma_free(&ch_tx->dma);
+
+rx_ring_free:
+ /* free the allocated RX ring */
+ for (i = 0; i < LTQ_DESC_NUM; i++) {
+ if (priv->chan_rx.skb[i])
+ dev_kfree_skb_any(priv->chan_rx.skb[i]);
+ }
+
+rx_free:
+ ltq_dma_free(&ch_rx->dma);
+ return ret;
+}
+
+static void xrx200_hw_cleanup(struct xrx200_priv *priv)
+{
+ int i;
+
+ ltq_dma_free(&priv->chan_tx.dma);
+ ltq_dma_free(&priv->chan_rx.dma);
+
+ /* free the allocated RX ring */
+ for (i = 0; i < LTQ_DESC_NUM; i++)
+ dev_kfree_skb_any(priv->chan_rx.skb[i]);
+}
+
+static int xrx200_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct device_node *np = dev->of_node;
+ struct resource *res;
+ struct device_node *phy_np;
+ struct of_phandle_iterator it;
+ struct xrx200_priv *priv;
+ struct net_device *net_dev;
+ const u8 *mac;
+ int err;
+
+ /* alloc the network device */
+ net_dev = devm_alloc_etherdev(dev, sizeof(struct xrx200_priv));
+ if (!net_dev)
+ return -ENOMEM;
+
+ priv = netdev_priv(net_dev);
+ priv->net_dev = net_dev;
+ priv->dev = dev;
+
+ net_dev->netdev_ops = &xrx200_netdev_ops;
+ SET_NETDEV_DEV(net_dev, dev);
+ net_dev->min_mtu = ETH_ZLEN;
+ net_dev->max_mtu = XRX200_DMA_DATA_LEN;
+
+ /* load the memory ranges */
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(dev, "failed to get resources\n");
+ return -ENOENT;
+ }
+
+ priv->pmac_reg = devm_ioremap_resource(dev, res);
+ if (!priv->pmac_reg) {
+ dev_err(dev, "failed to request and remap io ranges\n");
+ return -ENOMEM;
+ }
+
+ priv->chan_rx.dma.irq = platform_get_irq_byname(pdev, "rx");
+ if (priv->chan_rx.dma.irq < 0) {
+ dev_err(dev, "failed to get RX IRQ, %i\n",
+ priv->chan_rx.dma.irq);
+ return -ENOENT;
+ }
+ priv->chan_tx.dma.irq = platform_get_irq_byname(pdev, "tx");
+ if (priv->chan_tx.dma.irq < 0) {
+ dev_err(dev, "failed to get TX IRQ, %i\n",
+ priv->chan_tx.dma.irq);
+ return -ENOENT;
+ }
+
+ /* Make sure the firmware of the embedded GPHY is loaded before,
+ * otherwise they will not be detectable on the MDIO bus.
+ */
+ of_for_each_phandle(&it, err, np, "lantiq,phys", NULL, 0) {
+ phy_np = it.node;
+ if (phy_np) {
+ struct platform_device *phy = of_find_device_by_node(phy_np);
+
+ of_node_put(phy_np);
+ if (!platform_get_drvdata(phy))
+ return -EPROBE_DEFER;
+ }
+ }
+
+ /* get the clock */
+ priv->clk = devm_clk_get(dev, NULL);
+ if (IS_ERR(priv->clk)) {
+ dev_err(dev, "failed to get clock\n");
+ return PTR_ERR(priv->clk);
+ }
+
+ mac = of_get_mac_address(np);
+ if (mac && is_valid_ether_addr(mac))
+ ether_addr_copy(net_dev->dev_addr, mac);
+ else
+ eth_hw_addr_random(net_dev);
+
+ /* bring up the dma engine and IP core */
+ err = xrx200_dma_init(priv);
+ if (err)
+ return err;
+
+ /* enable clock gate */
+ err = clk_prepare_enable(priv->clk);
+ if (err)
+ goto err_uninit_dma;
+
+ /* set IPG to 12 */
+ xrx200_pmac_mask(priv, PMAC_RX_IPG_MASK, 0xb, PMAC_RX_IPG);
+
+ /* enable status header, enable CRC */
+ xrx200_pmac_mask(priv, 0,
+ PMAC_HD_CTL_RST | PMAC_HD_CTL_AST | PMAC_HD_CTL_RXSH |
+ PMAC_HD_CTL_AS | PMAC_HD_CTL_AC | PMAC_HD_CTL_RC,
+ PMAC_HD_CTL);
+
+ tasklet_init(&priv->chan_tx.tasklet, xrx200_tx_housekeeping,
+ (u32) &priv->chan_tx);
+
+ /* setup NAPI */
+ netif_napi_add(net_dev, &priv->chan_rx.napi, xrx200_poll_rx, 32);
+
+ platform_set_drvdata(pdev, priv);
+
+ err = register_netdev(net_dev);
+ if (err)
+ goto err_unprepare_clk;
+ return err;
+
+err_unprepare_clk:
+ clk_disable_unprepare(priv->clk);
+
+err_uninit_dma:
+ xrx200_hw_cleanup(priv);
+
+ return 0;
+}
+
+
+
+static int xrx200_remove(struct platform_device *pdev)
+{
+ struct xrx200_priv *priv = platform_get_drvdata(pdev);
+ struct net_device *net_dev = priv->net_dev;
+
+ /* free stack related instances */
+ netif_stop_queue(net_dev);
+ netif_napi_del(&priv->chan_rx.napi);
+
+ /* remove the actual device */
+ unregister_netdev(net_dev);
+
+ /* release the clock */
+ clk_disable_unprepare(priv->clk);
+
+ /* shut down hardware */
+ xrx200_hw_cleanup(priv);
+
+ return 0;
+}
+
+static const struct of_device_id xrx200_match[] = {
+ { .compatible = "lantiq,xrx200-net" },
+ {},
+};
+MODULE_DEVICE_TABLE(of, xrx200_match);
+
+static struct platform_driver xrx200_driver = {
+ .probe = xrx200_probe,
+ .remove = xrx200_remove,
+ .driver = {
+ .name = "lantiq,xrx200-net",
+ .of_match_table = xrx200_match,
+ },
+};
+
+module_platform_driver(xrx200_driver);
+
+MODULE_AUTHOR("John Crispin <blogic@openwrt.org>");
+MODULE_DESCRIPTION("Lantiq SoC XRX200 ethernet");
+MODULE_LICENSE("GPL");
--
2.11.0
^ permalink raw reply related
* [PATCH 4/4] net: dsa: Add Lantiq / Intel DSA driver for vrx200
From: Hauke Mehrtens @ 2018-07-21 19:13 UTC (permalink / raw)
To: davem
Cc: netdev, andrew, vivien.didelot, f.fainelli, john, linux-mips, dev,
hauke.mehrtens, Hauke Mehrtens
In-Reply-To: <20180721191358.13952-1-hauke@hauke-m.de>
This adds the DSA driver for the GSWIP Switch found in the VRX200 SoC.
This switch is integrated in the DSL SoC, this SoC uses a GSWIP version
2.0, there are other SoCs using different versions of this IP block, but
this driver was only tested with the version found in the VRX200.
Currently only the basic features are implemented which will forward all
packages to the CPU and let the CPU do the forwarding. The hardware also
support Layer 2 offloading which is not yet implemented in this driver.
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
---
MAINTAINERS | 1 +
drivers/net/dsa/Kconfig | 8 +
drivers/net/dsa/Makefile | 1 +
drivers/net/dsa/lantiq-gswip.c | 750 +++++++++++++++++++++++++++++++++++++++++
drivers/net/dsa/lantiq_pce.h | 153 +++++++++
5 files changed, 913 insertions(+)
create mode 100644 drivers/net/dsa/lantiq-gswip.c
create mode 100644 drivers/net/dsa/lantiq_pce.h
diff --git a/MAINTAINERS b/MAINTAINERS
index cc0607a58c51..761446ff9dd7 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -8016,6 +8016,7 @@ S: Maintained
F: net/dsa/tag_gswip.c
F: drivers/net/ethernet/lantiq_xrx200.c
F: drivers/net/dsa/lantiq_pce.h
+F: drivers/net/dsa/intel-gswip.c
LANTIQ MIPS ARCHITECTURE
M: John Crispin <john@phrozen.org>
diff --git a/drivers/net/dsa/Kconfig b/drivers/net/dsa/Kconfig
index 2b81b97e994f..f1280aa3f9bd 100644
--- a/drivers/net/dsa/Kconfig
+++ b/drivers/net/dsa/Kconfig
@@ -23,6 +23,14 @@ config NET_DSA_LOOP
This enables support for a fake mock-up switch chip which
exercises the DSA APIs.
+config NET_DSA_GSWIP
+ tristate "Intel / Lantiq GSWIP"
+ depends on NET_DSA
+ select NET_DSA_TAG_GSWIP
+ ---help---
+ This enables support for the Intel / Lantiq GSWIP 2.0 found in
+ the xrx200 / VR9 SoC.
+
config NET_DSA_MT7530
tristate "Mediatek MT7530 Ethernet switch support"
depends on NET_DSA
diff --git a/drivers/net/dsa/Makefile b/drivers/net/dsa/Makefile
index 15c2a831edf1..11143d860a95 100644
--- a/drivers/net/dsa/Makefile
+++ b/drivers/net/dsa/Makefile
@@ -5,6 +5,7 @@ obj-$(CONFIG_NET_DSA_LOOP) += dsa_loop.o
ifdef CONFIG_NET_DSA_LOOP
obj-$(CONFIG_FIXED_PHY) += dsa_loop_bdinfo.o
endif
+obj-$(CONFIG_NET_DSA_GSWIP) += lantiq-gswip.o
obj-$(CONFIG_NET_DSA_MT7530) += mt7530.o
obj-$(CONFIG_NET_DSA_MV88E6060) += mv88e6060.o
obj-$(CONFIG_NET_DSA_QCA8K) += qca8k.o
diff --git a/drivers/net/dsa/lantiq-gswip.c b/drivers/net/dsa/lantiq-gswip.c
new file mode 100644
index 000000000000..b6e64ba7ff12
--- /dev/null
+++ b/drivers/net/dsa/lantiq-gswip.c
@@ -0,0 +1,750 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Lantiq / Intel GSWIP switch driver for VRX200 SoCs
+ *
+ * Copyright (C) 2010 Lantiq Deutschland
+ * Copyright (C) 2012 John Crispin <blogic@openwrt.org>
+ * Copyright (C) 2017 - 2018 Hauke Mehrtens <hauke@hauke-m.de>
+ */
+
+#include <linux/etherdevice.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/if_vlan.h>
+#include <linux/if_bridge.h>
+#include <net/dsa.h>
+
+#include <linux/of_net.h>
+#include <linux/of_mdio.h>
+#include <linux/of_platform.h>
+#include <linux/version.h>
+
+#include "lantiq_pce.h"
+
+
+/* GSWIP MDIO Registers */
+#define GSWIP_MDIO_GLOB 0x00
+#define GSWIP_MDIO_GLOB_ENABLE BIT(15)
+#define GSWIP_MDIO_CTRL 0x08
+#define GSWIP_MDIO_CTRL_BUSY BIT(12)
+#define GSWIP_MDIO_CTRL_RD BIT(11)
+#define GSWIP_MDIO_CTRL_WR BIT(10)
+#define GSWIP_MDIO_CTRL_PHYAD_MASK 0x1f
+#define GSWIP_MDIO_CTRL_PHYAD_SHIFT 5
+#define GSWIP_MDIO_CTRL_REGAD_MASK 0x1f
+#define GSWIP_MDIO_READ 0x09
+#define GSWIP_MDIO_WRITE 0x0A
+#define GSWIP_MDIO_MDC_CFG0 0x0B
+#define GSWIP_MDIO_MDC_CFG1 0x0C
+#define GSWIP_MDIO_PHYp(p) (0x15 - (p))
+#define GSWIP_MDIO_PHY_LINK_DOWN 0x4000
+#define GSWIP_MDIO_PHY_LINK_UP 0x2000
+#define GSWIP_MDIO_PHY_SPEED_M10 0x0000
+#define GSWIP_MDIO_PHY_SPEED_M100 0x0800
+#define GSWIP_MDIO_PHY_SPEED_G1 0x1000
+#define GSWIP_MDIO_PHY_FDUP_EN 0x0200
+#define GSWIP_MDIO_PHY_FDUP_DIS 0x0600
+#define GSWIP_MDIO_PHY_FCONTX_EN 0x0100
+#define GSWIP_MDIO_PHY_FCONTX_DIS 0x0180
+#define GSWIP_MDIO_PHY_FCONRX_EN 0x0020
+#define GSWIP_MDIO_PHY_FCONRX_DIS 0x0060
+#define GSWIP_MDIO_PHY_LINK_MASK 0x6000
+#define GSWIP_MDIO_PHY_SPEED_MASK 0x1800
+#define GSWIP_MDIO_PHY_FDUP_MASK 0x0600
+#define GSWIP_MDIO_PHY_FCONTX_MASK 0x0180
+#define GSWIP_MDIO_PHY_FCONRX_MASK 0x0060
+#define GSWIP_MDIO_PHY_ADDR_MASK 0x001f
+#define GSWIP_MDIO_PHY_MASK (GSWIP_MDIO_PHY_ADDR_MASK | \
+ GSWIP_MDIO_PHY_FCONRX_MASK | \
+ GSWIP_MDIO_PHY_FCONTX_MASK | \
+ GSWIP_MDIO_PHY_LINK_MASK | \
+ GSWIP_MDIO_PHY_SPEED_MASK | \
+ GSWIP_MDIO_PHY_FDUP_MASK)
+
+/* GSWIP MII Registers */
+#define GSWIP_MII_CFGp(p) ((p) * 2)
+#define GSWIP_MII_CFG_EN BIT(14)
+#define GSWIP_MII_CFG_MODE_MIIP 0x0
+#define GSWIP_MII_CFG_MODE_MIIM 0x1
+#define GSWIP_MII_CFG_MODE_RMIIP 0x2
+#define GSWIP_MII_CFG_MODE_RMIIM 0x3
+#define GSWIP_MII_CFG_MODE_RGMII 0x4
+#define GSWIP_MII_CFG_MODE_MASK 0xf
+#define GSWIP_MII_CFG_RATE_M2P5 0x00
+#define GSWIP_MII_CFG_RATE_M25 0x10
+#define GSWIP_MII_CFG_RATE_M125 0x20
+#define GSWIP_MII_CFG_RATE_M50 0x30
+#define GSWIP_MII_CFG_RATE_AUTO 0x40
+#define GSWIP_MII_CFG_RATE_MASK 0x70
+
+/* GSWIP Core Registers */
+#define GSWIP_ETHSW_SWRES 0x000
+#define GSWIP_ETHSW_SWRES_R1 BIT(1) /* GSWIP Software reset */
+#define GSWIP_ETHSW_SWRES_R0 BIT(0) /* GSWIP Hardware reset */
+
+#define GSWIP_BM_RAM_VAL(x) (0x043 - (x))
+#define GSWIP_BM_RAM_ADDR 0x044
+#define GSWIP_BM_RAM_CTRL 0x045
+#define GSWIP_BM_RAM_CTRL_BAS BIT(15)
+#define GSWIP_BM_RAM_CTRL_OPMOD BIT(5)
+#define GSWIP_BM_RAM_CTRL_ADDR_MASK GENMASK(4, 0)
+#define GSWIP_BM_QUEUE_GCTRL 0x04A
+#define GSWIP_BM_QUEUE_GCTRL_GL_MOD BIT(10)
+/* buffer management Port Configuration Register */
+#define GSWIP_BM_PCFGp(p) (0x080 + ((p) * 2))
+#define GSWIP_BM_PCFG_CNTEN BIT(0) /* RMON Counter Enable */
+#define GSWIP_BM_PCFG_IGCNT BIT(1) /* Ingres Special Tag RMON count */
+/* buffer management Port Control Register */
+#define GSWIP_BM_RMON_CTRLp(p) (0x81 + ((p) * 2))
+#define GSWIP_BM_CTRL_RMON_RAM1_RES BIT(0) /* Software Reset for RMON RAM 1 */
+#define GSWIP_BM_CTRL_RMON_RAM2_RES BIT(1) /* Software Reset for RMON RAM 2 */
+
+/* PCE */
+#define GSWIP_PCE_TBL_KEY(x) (0x447 - (x))
+#define GSWIP_PCE_TBL_MASK 0x448
+#define GSWIP_PCE_TBL_VAL(x) (0x44D - (x))
+#define GSWIP_PCE_TBL_ADDR 0x44E
+#define GSWIP_PCE_TBL_CTRL 0x44F
+#define GSWIP_PCE_TBL_CTRL_BAS BIT(15)
+#define GSWIP_PCE_TBL_CTRL_TYPE BIT(13)
+#define GSWIP_PCE_TBL_CTRL_VLD BIT(12)
+#define GSWIP_PCE_TBL_CTRL_KEYFORM BIT(11)
+#define GSWIP_PCE_TBL_CTRL_GMAP_MASK GENMASK(10, 7)
+#define GSWIP_PCE_TBL_CTRL_OPMOD_MASK GENMASK(6, 5)
+#define GSWIP_PCE_TBL_CTRL_OPMOD_ADRD 0x00
+#define GSWIP_PCE_TBL_CTRL_OPMOD_ADWR 0x20
+#define GSWIP_PCE_TBL_CTRL_OPMOD_KSRD 0x40
+#define GSWIP_PCE_TBL_CTRL_OPMOD_KSWR 0x60
+#define GSWIP_PCE_TBL_CTRL_ADDR_MASK GENMASK(4, 0)
+#define GSWIP_PCE_PMAP1 0x453 /* Monitoring port map */
+#define GSWIP_PCE_PMAP2 0x454 /* Default Multicast port map */
+#define GSWIP_PCE_PMAP3 0x455 /* Default Unknown Unicast port map */
+#define GSWIP_PCE_GCTRL_0 0x456
+#define GSWIP_PCE_GCTRL_0_MC_VALID BIT(3)
+#define GSWIP_PCE_GCTRL_0_VLAN BIT(14) /* VLAN aware Switching */
+#define GSWIP_PCE_GCTRL_1 0x457
+#define GSWIP_PCE_GCTRL_1_MAC_GLOCK BIT(2) /* MAC Address table lock */
+#define GSWIP_PCE_GCTRL_1_MAC_GLOCK_MOD BIT(3) /* Mac address table lock forwarding mode */
+#define GSWIP_PCE_PCTRL_0p(p) (0x480 + ((p) * 0xA))
+#define GSWIP_PCE_PCTRL_0_INGRESS BIT(11)
+#define GSWIP_PCE_PCTRL_0_PSTATE_LISTEN 0x0
+#define GSWIP_PCE_PCTRL_0_PSTATE_RX 0x1
+#define GSWIP_PCE_PCTRL_0_PSTATE_TX 0x2
+#define GSWIP_PCE_PCTRL_0_PSTATE_LEARNING 0x3
+#define GSWIP_PCE_PCTRL_0_PSTATE_FORWARDING 0x7
+#define GSWIP_PCE_PCTRL_0_PSTATE_MASK GENMASK(2, 0)
+
+#define GSWIP_MAC_FLEN 0x8C5
+#define GSWIP_MAC_CTRL_2p(p) (0x905 + ((p) * 0xC))
+#define GSWIP_MAC_CTRL_2_MLEN BIT(3) /* Maximum Untagged Frame Lnegth */
+
+/* Ethernet Switch Fetch DMA Port Control Register */
+#define GSWIP_FDMA_PCTRLp(p) (0xA80 + ((p) * 0x6))
+#define GSWIP_FDMA_PCTRL_EN BIT(0) /* FDMA Port Enable */
+#define GSWIP_FDMA_PCTRL_STEN BIT(1) /* Special Tag Insertion Enable */
+#define GSWIP_FDMA_PCTRL_VLANMOD_MASK GENMASK(4, 3) /* VLAN Modification Control */
+#define GSWIP_FDMA_PCTRL_VLANMOD_SHIFT 3 /* VLAN Modification Control */
+#define GSWIP_FDMA_PCTRL_VLANMOD_DIS (0x0 << GSWIP_FDMA_PCTRL_VLANMOD_SHIFT)
+#define GSWIP_FDMA_PCTRL_VLANMOD_PRIO (0x1 << GSWIP_FDMA_PCTRL_VLANMOD_SHIFT)
+#define GSWIP_FDMA_PCTRL_VLANMOD_ID (0x2 << GSWIP_FDMA_PCTRL_VLANMOD_SHIFT)
+#define GSWIP_FDMA_PCTRL_VLANMOD_BOTH (0x3 << GSWIP_FDMA_PCTRL_VLANMOD_SHIFT)
+
+/* Ethernet Switch Store DMA Port Control Register */
+#define GSWIP_SDMA_PCTRLp(p) (0xBC0 + ((p) * 0x6))
+#define GSWIP_SDMA_PCTRL_EN BIT(0) /* SDMA Port Enable */
+#define GSWIP_SDMA_PCTRL_FCEN BIT(1) /* Flow Control Enable */
+#define GSWIP_SDMA_PCTRL_PAUFWD BIT(1) /* Pause Frame Forwarding */
+
+struct gswip_priv {
+ __iomem void *gswip;
+ __iomem void *mdio;
+ __iomem void *mii;
+ int cpu_port;
+ struct dsa_switch *ds;
+ struct device *dev;
+};
+
+struct gswip_rmon_cnt_desc {
+ unsigned int size;
+ unsigned int offset;
+ const char *name;
+};
+
+#define MIB_DESC(_size, _offset, _name) {.size = _size, .offset = _offset, .name = _name}
+
+static const struct gswip_rmon_cnt_desc gswip_rmon_cnt[] = {
+ /** Receive Packet Count (only packets that are accepted and not discarded). */
+ MIB_DESC(1, 0x1F, "RxGoodPkts"),
+ /** Receive Unicast Packet Count. */
+ MIB_DESC(1, 0x23, "RxUnicastPkts"),
+ /** Receive Multicast Packet Count. */
+ MIB_DESC(1, 0x22, "RxMulticastPkts"),
+ /** Receive FCS Error Packet Count. */
+ MIB_DESC(1, 0x21, "RxFCSErrorPkts"),
+ /** Receive Undersize Good Packet Count. */
+ MIB_DESC(1, 0x1D, "RxUnderSizeGoodPkts"),
+ /** Receive Undersize Error Packet Count. */
+ MIB_DESC(1, 0x1E, "RxUnderSizeErrorPkts"),
+ /** Receive Oversize Good Packet Count. */
+ MIB_DESC(1, 0x1B, "RxOversizeGoodPkts"),
+ /** Receive Oversize Error Packet Count. */
+ MIB_DESC(1, 0x1C, "RxOversizeErrorPkts"),
+ /** Receive Good Pause Packet Count. */
+ MIB_DESC(1, 0x20, "RxGoodPausePkts"),
+ /** Receive Align Error Packet Count. */
+ MIB_DESC(1, 0x1A, "RxAlignErrorPkts"),
+ /** Receive Size 64 Packet Count. */
+ MIB_DESC(1, 0x12, "Rx64BytePkts"),
+ /** Receive Size 65-127 Packet Count. */
+ MIB_DESC(1, 0x13, "Rx127BytePkts"),
+ /** Receive Size 128-255 Packet Count. */
+ MIB_DESC(1, 0x14, "Rx255BytePkts"),
+ /** Receive Size 256-511 Packet Count. */
+ MIB_DESC(1, 0x15, "Rx511BytePkts"),
+ /** Receive Size 512-1023 Packet Count. */
+ MIB_DESC(1, 0x16, "Rx1023BytePkts"),
+ /** Receive Size 1024-1522 (or more, if configured) Packet Count. */
+ MIB_DESC(1, 0x17, "RxMaxBytePkts"),
+ /** Receive Dropped Packet Count. */
+ MIB_DESC(1, 0x18, "RxDroppedPkts"),
+ /** Filtered Packet Count. */
+ MIB_DESC(1, 0x19, "RxFilteredPkts"),
+ /** Receive Good Byte Count (64 bit). */
+ MIB_DESC(2, 0x24, "RxGoodBytes"),
+ /** Receive Bad Byte Count (64 bit). */
+ MIB_DESC(2, 0x26, "RxBadBytes"),
+ /** Transmit Dropped Packet Count, based on Congestion Management. */
+ MIB_DESC(1, 0x11, "TxAcmDroppedPkts"),
+ /** Transmit Packet Count. */
+ MIB_DESC(1, 0x0C, "TxGoodPkts"),
+ /** Transmit Unicast Packet Count. */
+ MIB_DESC(1, 0x06, "TxUnicastPkts"),
+ /** Transmit Multicast Packet Count. */
+ MIB_DESC(1, 0x07, "TxMulticastPkts"),
+ /** Transmit Size 64 Packet Count. */
+ MIB_DESC(1, 0x00, "Tx64BytePkts"),
+ /** Transmit Size 65-127 Packet Count. */
+ MIB_DESC(1, 0x01, "Tx127BytePkts"),
+ /** Transmit Size 128-255 Packet Count. */
+ MIB_DESC(1, 0x02, "Tx255BytePkts"),
+ /** Transmit Size 256-511 Packet Count. */
+ MIB_DESC(1, 0x03, "Tx511BytePkts"),
+ /** Transmit Size 512-1023 Packet Count. */
+ MIB_DESC(1, 0x04, "Tx1023BytePkts"),
+ /** Transmit Size 1024-1522 (or more, if configured) Packet Count. */
+ MIB_DESC(1, 0x05, "TxMaxBytePkts"),
+ /** Transmit Single Collision Count. */
+ MIB_DESC(1, 0x08, "TxSingleCollCount"),
+ /** Transmit Multiple Collision Count. */
+ MIB_DESC(1, 0x09, "TxMultCollCount"),
+ /** Transmit Late Collision Count. */
+ MIB_DESC(1, 0x0A, "TxLateCollCount"),
+ /** Transmit Excessive Collision Count. */
+ MIB_DESC(1, 0x0B, "TxExcessCollCount"),
+ /** Transmit Pause Packet Count. */
+ MIB_DESC(1, 0x0D, "TxPauseCount"),
+ /** Transmit Drop Packet Count. */
+ MIB_DESC(1, 0x10, "TxDroppedPkts"),
+ /** Transmit Good Byte Count (64 bit). */
+ MIB_DESC(2, 0x0E, "TxGoodBytes"),
+};
+
+static u32 gswip_switch_r(struct gswip_priv *priv, u32 offset)
+{
+ return __raw_readl(priv->gswip + (offset * 4));
+}
+
+static void gswip_switch_w(struct gswip_priv *priv, u32 val, u32 offset)
+{
+ return __raw_writel(val, priv->gswip + (offset * 4));
+}
+
+static void gswip_switch_mask(struct gswip_priv *priv, u32 clear, u32 set,
+ u32 offset)
+{
+ u32 val = gswip_switch_r(priv, offset);
+
+ val &= ~(clear);
+ val |= set;
+ gswip_switch_w(priv, val, offset);
+}
+
+static u32 gswip_mdio_r(struct gswip_priv *priv, u32 offset)
+{
+ return __raw_readl(priv->mdio + (offset * 4));
+}
+
+static void gswip_mdio_w(struct gswip_priv *priv, u32 val, u32 offset)
+{
+ return __raw_writel(val, priv->mdio + (offset * 4));
+}
+
+static void gswip_mdio_mask(struct gswip_priv *priv, u32 clear, u32 set,
+ u32 offset)
+{
+ u32 val = gswip_mdio_r(priv, offset);
+
+ val &= ~(clear);
+ val |= set;
+ gswip_mdio_w(priv, val, offset);
+}
+
+static u32 gswip_mii_r(struct gswip_priv *priv, u32 offset)
+{
+ return __raw_readl(priv->mii + (offset * 4));
+}
+
+static void gswip_mii_w(struct gswip_priv *priv, u32 val, u32 offset)
+{
+ return __raw_writel(val, priv->mii + (offset * 4));
+}
+
+static void gswip_mii_mask(struct gswip_priv *priv, u32 clear, u32 set,
+ u32 offset)
+{
+ u32 val = gswip_mii_r(priv, offset);
+
+ val &= ~(clear);
+ val |= set;
+ gswip_mii_w(priv, val, offset);
+}
+
+static int xrx200_mdio_poll(struct gswip_priv *priv)
+{
+ int cnt = 10000;
+
+ while (likely(cnt--)) {
+ u32 ctrl = gswip_mdio_r(priv, GSWIP_MDIO_CTRL);
+
+ if ((ctrl & GSWIP_MDIO_CTRL_BUSY) == 0)
+ return 0;
+ cpu_relax();
+ }
+
+ return 1;
+}
+
+static int xrx200_mdio_wr(struct mii_bus *bus, int addr, int reg, u16 val)
+{
+ struct gswip_priv *priv = bus->priv;
+
+ if (xrx200_mdio_poll(priv))
+ return -EIO;
+
+ gswip_mdio_w(priv, val, GSWIP_MDIO_WRITE);
+ gswip_mdio_w(priv, GSWIP_MDIO_CTRL_BUSY | GSWIP_MDIO_CTRL_WR |
+ ((addr & GSWIP_MDIO_CTRL_PHYAD_MASK) << GSWIP_MDIO_CTRL_PHYAD_SHIFT) |
+ (reg & GSWIP_MDIO_CTRL_REGAD_MASK),
+ GSWIP_MDIO_CTRL);
+
+ return 0;
+}
+
+static int xrx200_mdio_rd(struct mii_bus *bus, int addr, int reg)
+{
+ struct gswip_priv *priv = bus->priv;
+
+ if (xrx200_mdio_poll(priv))
+ return -EIO;
+
+ gswip_mdio_w(priv, GSWIP_MDIO_CTRL_BUSY | GSWIP_MDIO_CTRL_RD |
+ ((addr & GSWIP_MDIO_CTRL_PHYAD_MASK) << GSWIP_MDIO_CTRL_PHYAD_SHIFT) |
+ (reg & GSWIP_MDIO_CTRL_REGAD_MASK),
+ GSWIP_MDIO_CTRL);
+
+ if (xrx200_mdio_poll(priv))
+ return -EIO;
+
+ return gswip_mdio_r(priv, GSWIP_MDIO_READ);
+}
+
+static int gswip_mdio(struct gswip_priv *priv, struct device_node *mdio_np)
+{
+ struct dsa_switch *ds = priv->ds;
+
+ ds->slave_mii_bus = devm_mdiobus_alloc(priv->dev);
+ if (!ds->slave_mii_bus)
+ return -ENOMEM;
+
+ ds->slave_mii_bus->priv = priv;
+ ds->slave_mii_bus->read = xrx200_mdio_rd;
+ ds->slave_mii_bus->write = xrx200_mdio_wr;
+ ds->slave_mii_bus->name = "lantiq,xrx200-mdio";
+ snprintf(ds->slave_mii_bus->id, MII_BUS_ID_SIZE, "%x", 0);
+ ds->slave_mii_bus->parent = priv->dev;
+ ds->slave_mii_bus->phy_mask = ~ds->phys_mii_mask;
+
+ return of_mdiobus_register(ds->slave_mii_bus, mdio_np);
+}
+
+static void gswip_wait_pce_tbl_ready(struct gswip_priv *priv)
+{
+ while (gswip_switch_r(priv, GSWIP_PCE_TBL_CTRL) & GSWIP_PCE_TBL_CTRL_BAS)
+ cond_resched();
+}
+
+static int gswip_port_enable(struct dsa_switch *ds, int port,
+ struct phy_device *phy)
+{
+ struct gswip_priv *priv = (struct gswip_priv *)ds->priv;
+
+ /* RMON Counter Enable for port */
+ gswip_switch_w(priv, GSWIP_BM_PCFG_CNTEN, GSWIP_BM_PCFGp(port));
+
+ /* enable port fetch/store dma & VLAN Modification */
+ gswip_switch_mask(priv, 0, GSWIP_FDMA_PCTRL_EN |
+ GSWIP_FDMA_PCTRL_VLANMOD_BOTH,
+ GSWIP_FDMA_PCTRLp(port));
+ gswip_switch_mask(priv, 0, GSWIP_SDMA_PCTRL_EN,
+ GSWIP_SDMA_PCTRLp(port));
+ gswip_switch_mask(priv, 0, GSWIP_PCE_PCTRL_0_INGRESS,
+ GSWIP_PCE_PCTRL_0p(port));
+
+ return 0;
+}
+
+static void gswip_port_disable(struct dsa_switch *ds, int port,
+ struct phy_device *phy)
+{
+ struct gswip_priv *priv = (struct gswip_priv *)ds->priv;
+
+ gswip_switch_mask(priv, GSWIP_FDMA_PCTRL_EN, 0,
+ GSWIP_FDMA_PCTRLp(port));
+ gswip_switch_mask(priv, GSWIP_SDMA_PCTRL_EN, 0,
+ GSWIP_SDMA_PCTRLp(port));
+}
+
+static void xrx200_pci_microcode(struct gswip_priv *priv)
+{
+ int i;
+
+ gswip_switch_mask(priv, GSWIP_PCE_TBL_CTRL_ADDR_MASK |
+ GSWIP_PCE_TBL_CTRL_OPMOD_MASK,
+ GSWIP_PCE_TBL_CTRL_OPMOD_ADWR, GSWIP_PCE_TBL_CTRL);
+ gswip_switch_w(priv, 0, GSWIP_PCE_TBL_MASK);
+
+ for (i = 0; i < ARRAY_SIZE(gswip_pce_microcode); i++) {
+ gswip_switch_w(priv, i, GSWIP_PCE_TBL_ADDR);
+ gswip_switch_w(priv, gswip_pce_microcode[i].val_0,
+ GSWIP_PCE_TBL_VAL(0));
+ gswip_switch_w(priv, gswip_pce_microcode[i].val_1,
+ GSWIP_PCE_TBL_VAL(1));
+ gswip_switch_w(priv, gswip_pce_microcode[i].val_2,
+ GSWIP_PCE_TBL_VAL(2));
+ gswip_switch_w(priv, gswip_pce_microcode[i].val_3,
+ GSWIP_PCE_TBL_VAL(3));
+
+ // start the table access:
+ gswip_switch_mask(priv, 0, GSWIP_PCE_TBL_CTRL_BAS,
+ GSWIP_PCE_TBL_CTRL);
+ gswip_wait_pce_tbl_ready(priv);
+ }
+
+ /* tell the switch that the microcode is loaded */
+ gswip_switch_mask(priv, 0, GSWIP_PCE_GCTRL_0_MC_VALID,
+ GSWIP_PCE_GCTRL_0);
+}
+
+static int gswip_setup(struct dsa_switch *ds)
+{
+ struct gswip_priv *priv = ds->priv;
+ int i;
+
+ gswip_switch_w(priv, GSWIP_ETHSW_SWRES_R0, GSWIP_ETHSW_SWRES);
+ usleep_range(5000, 10000);
+ gswip_switch_w(priv, 0, GSWIP_ETHSW_SWRES);
+
+ /* disable port fetch/store dma, assume CPU port is last port */
+ for (i = 0; i <= priv->cpu_port; i++)
+ gswip_port_disable(ds, i, NULL);
+
+ /* enable Switch */
+ gswip_mdio_mask(priv, 0, GSWIP_MDIO_GLOB_ENABLE, GSWIP_MDIO_GLOB);
+
+ xrx200_pci_microcode(priv);
+
+ /* Default unknown Broadcast/Multicast/Unicast port maps */
+ gswip_switch_w(priv, BIT(priv->cpu_port), GSWIP_PCE_PMAP1);
+ gswip_switch_w(priv, BIT(priv->cpu_port), GSWIP_PCE_PMAP2);
+ gswip_switch_w(priv, BIT(priv->cpu_port), GSWIP_PCE_PMAP3);
+
+ /* disable auto polling */
+ gswip_mdio_w(priv, 0x0, GSWIP_MDIO_MDC_CFG0);
+
+ /* enable special tag insertion on cpu port */
+ gswip_switch_mask(priv, 0, GSWIP_FDMA_PCTRL_STEN,
+ GSWIP_FDMA_PCTRLp(priv->cpu_port));
+
+ gswip_switch_mask(priv, 0, GSWIP_MAC_CTRL_2_MLEN,
+ GSWIP_MAC_CTRL_2p(priv->cpu_port));
+ gswip_switch_w(priv, VLAN_ETH_FRAME_LEN + 8, GSWIP_MAC_FLEN);
+ gswip_switch_mask(priv, 0, GSWIP_BM_QUEUE_GCTRL_GL_MOD,
+ GSWIP_BM_QUEUE_GCTRL);
+
+ /* VLAN aware Switching */
+ gswip_switch_mask(priv, 0, GSWIP_PCE_GCTRL_0_VLAN, GSWIP_PCE_GCTRL_0);
+
+ /* Mac Address Table Lock */
+ gswip_switch_mask(priv, 0, GSWIP_PCE_GCTRL_1_MAC_GLOCK |
+ GSWIP_PCE_GCTRL_1_MAC_GLOCK_MOD,
+ GSWIP_PCE_GCTRL_1);
+
+ gswip_port_enable(ds, priv->cpu_port, NULL);
+ return 0;
+}
+
+static void gswip_adjust_link(struct dsa_switch *ds, int port,
+ struct phy_device *phydev)
+{
+ struct gswip_priv *priv = (struct gswip_priv *)ds->priv;
+ u16 phyaddr = phydev->mdio.addr & GSWIP_MDIO_PHY_ADDR_MASK;
+ u16 miirate = 0;
+ u16 miimode;
+ u16 lcl_adv = 0, rmt_adv = 0;
+ u8 flowctrl;
+
+ /* do not run this for the CPU port 6 */
+ if (port >= priv->cpu_port)
+ return;
+
+ miimode = gswip_mdio_r(priv, GSWIP_MII_CFGp(port));
+ miimode &= GSWIP_MII_CFG_MODE_MASK;
+
+ switch (phydev->speed) {
+ case SPEED_1000:
+ phyaddr |= GSWIP_MDIO_PHY_SPEED_G1;
+ miirate = GSWIP_MII_CFG_RATE_M125;
+ break;
+
+ case SPEED_100:
+ phyaddr |= GSWIP_MDIO_PHY_SPEED_M100;
+ switch (miimode) {
+ case GSWIP_MII_CFG_MODE_RMIIM:
+ case GSWIP_MII_CFG_MODE_RMIIP:
+ miirate = GSWIP_MII_CFG_RATE_M50;
+ break;
+ default:
+ miirate = GSWIP_MII_CFG_RATE_M25;
+ break;
+ }
+ break;
+
+ default:
+ phyaddr |= GSWIP_MDIO_PHY_SPEED_M10;
+ miirate = GSWIP_MII_CFG_RATE_M2P5;
+ break;
+ }
+
+ if (phydev->link)
+ phyaddr |= GSWIP_MDIO_PHY_LINK_UP;
+ else
+ phyaddr |= GSWIP_MDIO_PHY_LINK_DOWN;
+
+ if (phydev->duplex == DUPLEX_FULL)
+ phyaddr |= GSWIP_MDIO_PHY_FDUP_EN;
+ else
+ phyaddr |= GSWIP_MDIO_PHY_FDUP_DIS;
+
+ if (phydev->pause)
+ rmt_adv = LPA_PAUSE_CAP;
+ if (phydev->asym_pause)
+ rmt_adv |= LPA_PAUSE_ASYM;
+
+ if (phydev->advertising & ADVERTISED_Pause)
+ lcl_adv |= ADVERTISE_PAUSE_CAP;
+ if (phydev->advertising & ADVERTISED_Asym_Pause)
+ lcl_adv |= ADVERTISE_PAUSE_ASYM;
+
+ flowctrl = mii_resolve_flowctrl_fdx(lcl_adv, rmt_adv);
+
+ if (flowctrl & FLOW_CTRL_TX)
+ phyaddr |= GSWIP_MDIO_PHY_FCONTX_EN;
+ else
+ phyaddr |= GSWIP_MDIO_PHY_FCONTX_DIS;
+ if (flowctrl & FLOW_CTRL_RX)
+ phyaddr |= GSWIP_MDIO_PHY_FCONRX_EN;
+ else
+ phyaddr |= GSWIP_MDIO_PHY_FCONRX_DIS;
+
+ gswip_mdio_mask(priv, GSWIP_MDIO_PHY_MASK, phyaddr,
+ GSWIP_MDIO_PHYp(port));
+ gswip_mii_mask(priv, GSWIP_MII_CFG_RATE_MASK, miirate,
+ GSWIP_MII_CFGp(port));
+}
+
+static enum dsa_tag_protocol gswip_get_tag_protocol(struct dsa_switch *ds,
+ int port)
+{
+ return DSA_TAG_PROTO_GSWIP;
+}
+
+static void gswip_get_strings(struct dsa_switch *ds, int port, u32 stringset,
+ uint8_t *data)
+{
+ int i;
+
+ if (stringset != ETH_SS_STATS)
+ return;
+
+ for (i = 0; i < ARRAY_SIZE(gswip_rmon_cnt); i++)
+ strncpy(data + i * ETH_GSTRING_LEN, gswip_rmon_cnt[i].name,
+ ETH_GSTRING_LEN);
+}
+
+static u32 gswip_bcm_ram_entry_read(struct gswip_priv *priv, u32 table,
+ u32 index)
+{
+ u32 result;
+
+ gswip_switch_w(priv, index, GSWIP_BM_RAM_ADDR);
+ gswip_switch_mask(priv, GSWIP_BM_RAM_CTRL_ADDR_MASK |
+ GSWIP_BM_RAM_CTRL_OPMOD,
+ table | GSWIP_BM_RAM_CTRL_BAS,
+ GSWIP_BM_RAM_CTRL);
+
+ while (gswip_switch_r(priv, GSWIP_BM_RAM_CTRL) & GSWIP_BM_RAM_CTRL_BAS)
+ cond_resched();
+
+ result = gswip_switch_r(priv, GSWIP_BM_RAM_VAL(0));
+ result |= gswip_switch_r(priv, GSWIP_BM_RAM_VAL(1)) << 16;
+
+ return result;
+}
+
+static void gswip_get_ethtool_stats(struct dsa_switch *ds, int port,
+ uint64_t *data)
+{
+ struct gswip_priv *priv = ds->priv;
+ const struct gswip_rmon_cnt_desc *rmon_cnt;
+ int i;
+ u64 high;
+
+ for (i = 0; i < ARRAY_SIZE(gswip_rmon_cnt); i++) {
+ rmon_cnt = &gswip_rmon_cnt[i];
+
+ data[i] = gswip_bcm_ram_entry_read(priv, port,
+ rmon_cnt->offset);
+ if (rmon_cnt->size == 2) {
+ high = gswip_bcm_ram_entry_read(priv, port,
+ rmon_cnt->offset + 1);
+ data[i] |= high << 32;
+ }
+ }
+}
+
+static int gswip_get_sset_count(struct dsa_switch *ds, int port, int sset)
+{
+ if (sset != ETH_SS_STATS)
+ return 0;
+
+ return ARRAY_SIZE(gswip_rmon_cnt);
+}
+
+static const struct dsa_switch_ops gswip_switch_ops = {
+ .get_tag_protocol = gswip_get_tag_protocol,
+ .setup = gswip_setup,
+ .adjust_link = gswip_adjust_link,
+ .port_enable = gswip_port_enable,
+ .port_disable = gswip_port_disable,
+ .get_strings = gswip_get_strings,
+ .get_ethtool_stats = gswip_get_ethtool_stats,
+ .get_sset_count = gswip_get_sset_count,
+};
+
+static int gswip_probe(struct platform_device *pdev)
+{
+ struct gswip_priv *priv;
+ struct resource *gswip_res, *mdio_res, *mii_res;
+ struct device_node *mdio_np;
+ struct device *dev = &pdev->dev;
+ int err;
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ gswip_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ priv->gswip = devm_ioremap_resource(dev, gswip_res);
+ if (!priv->gswip)
+ return -ENOMEM;
+
+ mdio_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ priv->mdio = devm_ioremap_resource(dev, mdio_res);
+ if (!priv->mdio)
+ return -ENOMEM;
+
+ mii_res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
+ priv->mii = devm_ioremap_resource(dev, mii_res);
+ if (!priv->mii)
+ return -ENOMEM;
+
+ priv->ds = dsa_switch_alloc(dev, DSA_MAX_PORTS);
+ if (!priv->ds)
+ return -ENOMEM;
+
+ priv->ds->priv = priv;
+ priv->ds->ops = &gswip_switch_ops;
+ priv->dev = dev;
+ priv->cpu_port = 6;
+
+ /* bring up the mdio bus */
+ mdio_np = of_find_compatible_node(pdev->dev.of_node, NULL,
+ "lantiq,xrx200-mdio");
+ if (mdio_np) {
+ err = gswip_mdio(priv, mdio_np);
+ if (err) {
+ dev_err(dev, "mdio probe failed\n");
+ return err;
+ }
+ }
+
+ platform_set_drvdata(pdev, priv);
+
+ err = dsa_register_switch(priv->ds);
+ if (err) {
+ dev_err(dev, "dsa switch register failed: %i\n", err);
+ if (mdio_np)
+ mdiobus_unregister(priv->ds->slave_mii_bus);
+ }
+
+ return err;
+}
+
+static int gswip_remove(struct platform_device *pdev)
+{
+ struct gswip_priv *priv = platform_get_drvdata(pdev);
+
+ if (!priv)
+ return 0;
+
+ /* disable the switch */
+ gswip_mdio_mask(priv, GSWIP_MDIO_GLOB_ENABLE, 0, GSWIP_MDIO_GLOB);
+
+ dsa_unregister_switch(priv->ds);
+
+ if (priv->ds->slave_mii_bus)
+ mdiobus_unregister(priv->ds->slave_mii_bus);
+
+ return 0;
+}
+
+static const struct of_device_id gswip_of_match[] = {
+ { .compatible = "lantiq,xrx200-gswip" },
+ {},
+};
+MODULE_DEVICE_TABLE(of, xrx200_match);
+
+static struct platform_driver gswip_driver = {
+ .probe = gswip_probe,
+ .remove = gswip_remove,
+ .driver = {
+ .name = "gswip",
+ .of_match_table = gswip_of_match,
+ },
+};
+
+module_platform_driver(gswip_driver);
+
+MODULE_AUTHOR("Hauke Mehrtens <hauke@hauke-m.de>");
+MODULE_DESCRIPTION("Intel / Lantiq GSWIP driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/net/dsa/lantiq_pce.h b/drivers/net/dsa/lantiq_pce.h
new file mode 100644
index 000000000000..aa57d9fe7089
--- /dev/null
+++ b/drivers/net/dsa/lantiq_pce.h
@@ -0,0 +1,153 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * PCE microcode extracted from UGW 7.1.1 switch api
+ *
+ * Copyright (c) 2012, 2014, 2015 Lantiq Deutschland GmbH
+ * Copyright (C) 2012 John Crispin <blogic@openwrt.org>
+ * Copyright (C) 2017 - 2018 Hauke Mehrtens <hauke@hauke-m.de>
+ */
+
+enum {
+ OUT_MAC0 = 0,
+ OUT_MAC1,
+ OUT_MAC2,
+ OUT_MAC3,
+ OUT_MAC4,
+ OUT_MAC5,
+ OUT_ETHTYP,
+ OUT_VTAG0,
+ OUT_VTAG1,
+ OUT_ITAG0,
+ OUT_ITAG1, /*10 */
+ OUT_ITAG2,
+ OUT_ITAG3,
+ OUT_IP0,
+ OUT_IP1,
+ OUT_IP2,
+ OUT_IP3,
+ OUT_SIP0,
+ OUT_SIP1,
+ OUT_SIP2,
+ OUT_SIP3, /*20*/
+ OUT_SIP4,
+ OUT_SIP5,
+ OUT_SIP6,
+ OUT_SIP7,
+ OUT_DIP0,
+ OUT_DIP1,
+ OUT_DIP2,
+ OUT_DIP3,
+ OUT_DIP4,
+ OUT_DIP5, /*30*/
+ OUT_DIP6,
+ OUT_DIP7,
+ OUT_SESID,
+ OUT_PROT,
+ OUT_APP0,
+ OUT_APP1,
+ OUT_IGMP0,
+ OUT_IGMP1,
+ OUT_IPOFF, /*39*/
+ OUT_NONE = 63,
+};
+
+/* parser's microcode length type */
+#define INSTR 0
+#define IPV6 1
+#define LENACCU 2
+
+/* parser's microcode flag type */
+enum {
+ FLAG_ITAG = 0,
+ FLAG_VLAN,
+ FLAG_SNAP,
+ FLAG_PPPOE,
+ FLAG_IPV6,
+ FLAG_IPV6FL,
+ FLAG_IPV4,
+ FLAG_IGMP,
+ FLAG_TU,
+ FLAG_HOP,
+ FLAG_NN1, /*10 */
+ FLAG_NN2,
+ FLAG_END,
+ FLAG_NO, /*13*/
+};
+
+struct gswip_pce_microcode {
+ u16 val_3;
+ u16 val_2;
+ u16 val_1;
+ u16 val_0;
+};
+
+#define MC_ENTRY(val, msk, ns, out, len, type, flags, ipv4_len) \
+ { val, msk, (ns << 10 | out << 4 | len >> 1),\
+ (len & 1) << 15 | type << 13 | flags << 9 | ipv4_len << 8 }
+static const struct gswip_pce_microcode gswip_pce_microcode[] = {
+ /* value mask ns fields L type flags ipv4_len */
+ MC_ENTRY(0x88c3, 0xFFFF, 1, OUT_ITAG0, 4, INSTR, FLAG_ITAG, 0),
+ MC_ENTRY(0x8100, 0xFFFF, 2, OUT_VTAG0, 2, INSTR, FLAG_VLAN, 0),
+ MC_ENTRY(0x88A8, 0xFFFF, 1, OUT_VTAG0, 2, INSTR, FLAG_VLAN, 0),
+ MC_ENTRY(0x8100, 0xFFFF, 1, OUT_VTAG0, 2, INSTR, FLAG_VLAN, 0),
+ MC_ENTRY(0x8864, 0xFFFF, 17, OUT_ETHTYP, 1, INSTR, FLAG_NO, 0),
+ MC_ENTRY(0x0800, 0xFFFF, 21, OUT_ETHTYP, 1, INSTR, FLAG_NO, 0),
+ MC_ENTRY(0x86DD, 0xFFFF, 22, OUT_ETHTYP, 1, INSTR, FLAG_NO, 0),
+ MC_ENTRY(0x8863, 0xFFFF, 16, OUT_ETHTYP, 1, INSTR, FLAG_NO, 0),
+ MC_ENTRY(0x0000, 0xF800, 10, OUT_NONE, 0, INSTR, FLAG_NO, 0),
+ MC_ENTRY(0x0000, 0x0000, 40, OUT_ETHTYP, 1, INSTR, FLAG_NO, 0),
+ MC_ENTRY(0x0600, 0x0600, 40, OUT_ETHTYP, 1, INSTR, FLAG_NO, 0),
+ MC_ENTRY(0x0000, 0x0000, 12, OUT_NONE, 1, INSTR, FLAG_NO, 0),
+ MC_ENTRY(0xAAAA, 0xFFFF, 14, OUT_NONE, 1, INSTR, FLAG_NO, 0),
+ MC_ENTRY(0x0000, 0x0000, 41, OUT_NONE, 0, INSTR, FLAG_NO, 0),
+ MC_ENTRY(0x0300, 0xFF00, 41, OUT_NONE, 0, INSTR, FLAG_SNAP, 0),
+ MC_ENTRY(0x0000, 0x0000, 41, OUT_NONE, 0, INSTR, FLAG_NO, 0),
+ MC_ENTRY(0x0000, 0x0000, 41, OUT_DIP7, 3, INSTR, FLAG_NO, 0),
+ MC_ENTRY(0x0000, 0x0000, 18, OUT_DIP7, 3, INSTR, FLAG_PPPOE, 0),
+ MC_ENTRY(0x0021, 0xFFFF, 21, OUT_NONE, 1, INSTR, FLAG_NO, 0),
+ MC_ENTRY(0x0057, 0xFFFF, 22, OUT_NONE, 1, INSTR, FLAG_NO, 0),
+ MC_ENTRY(0x0000, 0x0000, 40, OUT_NONE, 0, INSTR, FLAG_NO, 0),
+ MC_ENTRY(0x4000, 0xF000, 24, OUT_IP0, 4, INSTR, FLAG_IPV4, 1),
+ MC_ENTRY(0x6000, 0xF000, 27, OUT_IP0, 3, INSTR, FLAG_IPV6, 0),
+ MC_ENTRY(0x0000, 0x0000, 41, OUT_NONE, 0, INSTR, FLAG_NO, 0),
+ MC_ENTRY(0x0000, 0x0000, 25, OUT_IP3, 2, INSTR, FLAG_NO, 0),
+ MC_ENTRY(0x0000, 0x0000, 26, OUT_SIP0, 4, INSTR, FLAG_NO, 0),
+ MC_ENTRY(0x0000, 0x0000, 40, OUT_NONE, 0, LENACCU, FLAG_NO, 0),
+ MC_ENTRY(0x1100, 0xFF00, 39, OUT_PROT, 1, INSTR, FLAG_NO, 0),
+ MC_ENTRY(0x0600, 0xFF00, 39, OUT_PROT, 1, INSTR, FLAG_NO, 0),
+ MC_ENTRY(0x0000, 0xFF00, 33, OUT_IP3, 17, INSTR, FLAG_HOP, 0),
+ MC_ENTRY(0x2B00, 0xFF00, 33, OUT_IP3, 17, INSTR, FLAG_NN1, 0),
+ MC_ENTRY(0x3C00, 0xFF00, 33, OUT_IP3, 17, INSTR, FLAG_NN2, 0),
+ MC_ENTRY(0x0000, 0x0000, 39, OUT_PROT, 1, INSTR, FLAG_NO, 0),
+ MC_ENTRY(0x0000, 0x00E0, 35, OUT_NONE, 0, INSTR, FLAG_NO, 0),
+ MC_ENTRY(0x0000, 0x0000, 40, OUT_NONE, 0, INSTR, FLAG_NO, 0),
+ MC_ENTRY(0x0000, 0xFF00, 33, OUT_NONE, 0, IPV6, FLAG_HOP, 0),
+ MC_ENTRY(0x2B00, 0xFF00, 33, OUT_NONE, 0, IPV6, FLAG_NN1, 0),
+ MC_ENTRY(0x3C00, 0xFF00, 33, OUT_NONE, 0, IPV6, FLAG_NN2, 0),
+ MC_ENTRY(0x0000, 0x0000, 40, OUT_PROT, 1, IPV6, FLAG_NO, 0),
+ MC_ENTRY(0x0000, 0x0000, 40, OUT_SIP0, 16, INSTR, FLAG_NO, 0),
+ MC_ENTRY(0x0000, 0x0000, 41, OUT_APP0, 4, INSTR, FLAG_IGMP, 0),
+ MC_ENTRY(0x0000, 0x0000, 41, OUT_NONE, 0, INSTR, FLAG_END, 0),
+ MC_ENTRY(0x0000, 0x0000, 41, OUT_NONE, 0, INSTR, FLAG_END, 0),
+ MC_ENTRY(0x0000, 0x0000, 41, OUT_NONE, 0, INSTR, FLAG_END, 0),
+ MC_ENTRY(0x0000, 0x0000, 41, OUT_NONE, 0, INSTR, FLAG_END, 0),
+ MC_ENTRY(0x0000, 0x0000, 41, OUT_NONE, 0, INSTR, FLAG_END, 0),
+ MC_ENTRY(0x0000, 0x0000, 41, OUT_NONE, 0, INSTR, FLAG_END, 0),
+ MC_ENTRY(0x0000, 0x0000, 41, OUT_NONE, 0, INSTR, FLAG_END, 0),
+ MC_ENTRY(0x0000, 0x0000, 41, OUT_NONE, 0, INSTR, FLAG_END, 0),
+ MC_ENTRY(0x0000, 0x0000, 41, OUT_NONE, 0, INSTR, FLAG_END, 0),
+ MC_ENTRY(0x0000, 0x0000, 41, OUT_NONE, 0, INSTR, FLAG_END, 0),
+ MC_ENTRY(0x0000, 0x0000, 41, OUT_NONE, 0, INSTR, FLAG_END, 0),
+ MC_ENTRY(0x0000, 0x0000, 41, OUT_NONE, 0, INSTR, FLAG_END, 0),
+ MC_ENTRY(0x0000, 0x0000, 41, OUT_NONE, 0, INSTR, FLAG_END, 0),
+ MC_ENTRY(0x0000, 0x0000, 41, OUT_NONE, 0, INSTR, FLAG_END, 0),
+ MC_ENTRY(0x0000, 0x0000, 41, OUT_NONE, 0, INSTR, FLAG_END, 0),
+ MC_ENTRY(0x0000, 0x0000, 41, OUT_NONE, 0, INSTR, FLAG_END, 0),
+ MC_ENTRY(0x0000, 0x0000, 41, OUT_NONE, 0, INSTR, FLAG_END, 0),
+ MC_ENTRY(0x0000, 0x0000, 41, OUT_NONE, 0, INSTR, FLAG_END, 0),
+ MC_ENTRY(0x0000, 0x0000, 41, OUT_NONE, 0, INSTR, FLAG_END, 0),
+ MC_ENTRY(0x0000, 0x0000, 41, OUT_NONE, 0, INSTR, FLAG_END, 0),
+ MC_ENTRY(0x0000, 0x0000, 41, OUT_NONE, 0, INSTR, FLAG_END, 0),
+ MC_ENTRY(0x0000, 0x0000, 41, OUT_NONE, 0, INSTR, FLAG_END, 0),
+ MC_ENTRY(0x0000, 0x0000, 41, OUT_NONE, 0, INSTR, FLAG_END, 0),
+};
--
2.11.0
^ permalink raw reply related
* Re: [RFC PATCH ghak90 (was ghak32) V3 02/10] audit: log container info of syscalls
From: Richard Guy Briggs @ 2018-07-21 20:29 UTC (permalink / raw)
To: Paul Moore, Steve Grubb
Cc: simo, carlos, linux-api, containers, linux-kernel, Eric Paris,
dhowells, linux-audit, ebiederm, luto, netdev, linux-fsdevel,
cgroups, serge, viro
In-Reply-To: <CAHC9VhS0-4XSEFFPLrOvAiSYv-XDLG-yGyB4ULRGz=AnwE6diQ@mail.gmail.com>
On 2018-07-20 18:13, Paul Moore wrote:
> On Wed, Jun 6, 2018 at 1:00 PM Richard Guy Briggs <rgb@redhat.com> wrote:
> > Create a new audit record AUDIT_CONTAINER to document the audit
> > container identifier of a process if it is present.
> >
> > Called from audit_log_exit(), syscalls are covered.
> >
> > A sample raw event:
> > type=SYSCALL msg=audit(1519924845.499:257): arch=c000003e syscall=257 success=yes exit=3 a0=ffffff9c a1=56374e1cef30 a2=241 a3=1b6 items=2 ppid=606 pid=635 auid=0 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts0 ses=3 comm="bash" exe="/usr/bin/bash" subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 key="tmpcontainerid"
> > type=CWD msg=audit(1519924845.499:257): cwd="/root"
> > type=PATH msg=audit(1519924845.499:257): item=0 name="/tmp/" inode=13863 dev=00:27 mode=041777 ouid=0 ogid=0 rdev=00:00 obj=system_u:object_r:tmp_t:s0 nametype= PARENT cap_fp=0000000000000000 cap_fi=0000000000000000 cap_fe=0 cap_fver=0
> > type=PATH msg=audit(1519924845.499:257): item=1 name="/tmp/tmpcontainerid" inode=17729 dev=00:27 mode=0100644 ouid=0 ogid=0 rdev=00:00 obj=unconfined_u:object_r:user_tmp_t:s0 nametype=CREATE cap_fp=0000000000000000 cap_fi=0000000000000000 cap_fe=0 cap_fver=0
> > type=PROCTITLE msg=audit(1519924845.499:257): proctitle=62617368002D6300736C65657020313B206563686F2074657374203E202F746D702F746D70636F6E7461696E65726964
> > type=CONTAINER msg=audit(1519924845.499:257): op=task contid=123458
> >
> > See: https://github.com/linux-audit/audit-kernel/issues/90
> > See: https://github.com/linux-audit/audit-userspace/issues/51
> > See: https://github.com/linux-audit/audit-testsuite/issues/64
> > See: https://github.com/linux-audit/audit-kernel/wiki/RFE-Audit-Container-ID
> > Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
> > ---
> > include/linux/audit.h | 7 +++++++
> > include/uapi/linux/audit.h | 1 +
> > kernel/audit.c | 23 +++++++++++++++++++++++
> > kernel/auditsc.c | 3 +++
> > 4 files changed, 34 insertions(+)
>
> ...
>
> > --- a/include/uapi/linux/audit.h
> > +++ b/include/uapi/linux/audit.h
> > @@ -115,6 +115,7 @@
> > #define AUDIT_REPLACE 1329 /* Replace auditd if this packet unanswerd */
> > #define AUDIT_KERN_MODULE 1330 /* Kernel Module events */
> > #define AUDIT_FANOTIFY 1331 /* Fanotify access decision */
> > +#define AUDIT_CONTAINER 1332 /* Container ID */
>
> I'm not sure I'm completely sold on the AUDIT_CONTAINER_ID and
> AUDIT_CONTAINER record type names. From what I can tell
> AUDIT_CONTAINER_ID seems to be used for audit container ID management
> operations, e.g. setting the ID, whereas the AUDIT_CONTAINER is used
> to tag events with the corresponding audit container ID. Assuming
> that is correct, it seems like AUDIT_CONTAINER might be better served
> if it was named AUDIT_CONTAINER_ID and if we could change
> AUDIT_CONTAINER_ID to AUDIT_CONTAINER_OP/MGMT/etc. Thoughts?
Please see discussion at:
https://www.redhat.com/archives/linux-audit/2018-May/msg00101.html
I'm fine with changing AUDIT_CONTAINER_ID to AUDIT_CONTAINER_OP/MGMT/etc.
> > #define AUDIT_AVC 1400 /* SE Linux avc denial or grant */
> > #define AUDIT_SELINUX_ERR 1401 /* Internal SE Linux Errors */
> > diff --git a/kernel/audit.c b/kernel/audit.c
> > index e7478cb..5e150c6 100644
> > --- a/kernel/audit.c
> > +++ b/kernel/audit.c
> > @@ -2048,6 +2048,29 @@ void audit_log_session_info(struct audit_buffer *ab)
> > audit_log_format(ab, " auid=%u ses=%u", auid, sessionid);
> > }
> >
> > +/*
> > + * audit_log_contid - report container info
> > + * @tsk: task to be recorded
> > + * @context: task or local context for record
> > + * @op: contid string description
> > + */
> > +int audit_log_contid(struct task_struct *tsk,
> > + struct audit_context *context, char *op)
> > +{
> > + struct audit_buffer *ab;
> > +
> > + if (!audit_contid_set(tsk))
> > + return 0;
> > + /* Generate AUDIT_CONTAINER record with container ID */
> > + ab = audit_log_start(context, GFP_KERNEL, AUDIT_CONTAINER);
> > + if (!ab)
> > + return -ENOMEM;
> > + audit_log_format(ab, "op=%s contid=%llu",
> > + op, audit_get_contid(tsk));
>
> Can you explain your reason for including an "op" field in this record
> type? I've been looking at the rest of the patches in this patchset
> and it seems to be used more as an indicator of the record's
> generating context rather than any sort of audit container ID
> operation.
"action" might work, but that's netfilter and numeric... "kind"?
Nothing else really seems to fit from a field name, type or lack of
searchability perspective.
Steve, do you have an opinion?
> > + audit_log_end(ab);
> > + return 0;
> > +}
>
> --
> paul moore
> www.paul-moore.com
- RGB
--
Richard Guy Briggs <rgb@redhat.com>
Sr. S/W Engineer, Kernel Security, Base Operating Systems
Remote, Ottawa, Red Hat Canada
IRC: rgb, SunRaycer
Voice: +1.647.777.2635, Internal: (81) 32635
^ permalink raw reply
* [PATCH] net: prevent ISA drivers from building on PPC32
From: Randy Dunlap @ 2018-07-21 19:59 UTC (permalink / raw)
To: PowerPC, Michael Ellerman, netdev@vger.kernel.org, David Miller
From: Randy Dunlap <rdunlap@infradead.org>
Prevent drivers from building on PPC32 if they use isa_bus_to_virt(),
isa_virt_to_bus(), or isa_page_to_bus(), which are not available and
thus cause build errors.
../drivers/net/ethernet/3com/3c515.c: In function 'corkscrew_open':
../drivers/net/ethernet/3com/3c515.c:824:9: error: implicit declaration of function 'isa_virt_to_bus'; did you mean 'virt_to_bus'? [-Werror=implicit-function-declaration]
../drivers/net/ethernet/amd/lance.c: In function 'lance_rx':
../drivers/net/ethernet/amd/lance.c:1203:23: error: implicit declaration of function 'isa_bus_to_virt'; did you mean 'bus_to_virt'? [-Werror=implicit-function-declaration]
../drivers/net/ethernet/amd/ni65.c: In function 'ni65_init_lance':
../drivers/net/ethernet/amd/ni65.c:585:20: error: implicit declaration of function 'isa_virt_to_bus'; did you mean 'virt_to_bus'? [-Werror=implicit-function-declaration]
../drivers/net/ethernet/cirrus/cs89x0.c: In function 'net_open':
../drivers/net/ethernet/cirrus/cs89x0.c:897:20: error: implicit declaration of function 'isa_virt_to_bus'; did you mean 'virt_to_bus'? [-Werror=implicit-function-declaration]
Signed-off-by: Randy Dunlap <rdunlap@infradead.org>
Suggested-by: Michael Ellerman <mpe@ellerman.id.au>
---
in cirrus/Kconfig, CS89x0 should probably also depend on ISA_DMA_API.
drivers/net/ethernet/3com/Kconfig | 2 +-
drivers/net/ethernet/amd/Kconfig | 4 ++--
drivers/net/ethernet/cirrus/Kconfig | 1 +
3 files changed, 4 insertions(+), 3 deletions(-)
--- linux-next-20180720.orig/drivers/net/ethernet/3com/Kconfig
+++ linux-next-20180720/drivers/net/ethernet/3com/Kconfig
@@ -32,7 +32,7 @@ config EL3
config 3C515
tristate "3c515 ISA \"Fast EtherLink\""
- depends on ISA && ISA_DMA_API
+ depends on ISA && ISA_DMA_API && !PPC32
---help---
If you have a 3Com ISA EtherLink XL "Corkscrew" 3c515 Fast Ethernet
network card, say Y here.
--- linux-next-20180720.orig/drivers/net/ethernet/amd/Kconfig
+++ linux-next-20180720/drivers/net/ethernet/amd/Kconfig
@@ -44,7 +44,7 @@ config AMD8111_ETH
config LANCE
tristate "AMD LANCE and PCnet (AT1500 and NE2100) support"
- depends on ISA && ISA_DMA_API && !ARM
+ depends on ISA && ISA_DMA_API && !ARM && !PPC32
---help---
If you have a network (Ethernet) card of this type, say Y here.
Some LinkSys cards are of this type.
@@ -138,7 +138,7 @@ config PCMCIA_NMCLAN
config NI65
tristate "NI6510 support"
- depends on ISA && ISA_DMA_API && !ARM
+ depends on ISA && ISA_DMA_API && !ARM && !PPC32
---help---
If you have a network (Ethernet) card of this type, say Y here.
--- linux-next-20180720.orig/drivers/net/ethernet/cirrus/Kconfig
+++ linux-next-20180720/drivers/net/ethernet/cirrus/Kconfig
@@ -19,6 +19,7 @@ if NET_VENDOR_CIRRUS
config CS89x0
tristate "CS89x0 support"
depends on ISA || EISA || ARM
+ depends on !PPC32
---help---
Support for CS89x0 chipset based Ethernet cards. If you have a
network (Ethernet) card of this type, say Y and read the file
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox