* Re: [PATCH 1/2] hp100: Fix a possible sleep-in-atomic bug in hp100_login_to_vg_hub
From: Jia-Ju Bai @ 2017-12-14 3:56 UTC (permalink / raw)
To: David Miller; +Cc: perex, floeff, acme, netdev, linux-kernel
In-Reply-To: <20171213.223432.393103915049464102.davem@davemloft.net>
Sorry,
I think I know your meaning now.
Maybe we can unlock the spinlock before "schedule_timeout_interruptible"
and then lock again?
Like:
spin_unlock(...);
schedule_timeout_interruptible(1);
spin_lock(...);
Best wishes,
Jia-Ju Bai
On 2017/12/14 11:34, David Miller wrote:
> From: Jia-Ju Bai <baijiaju1990@gmail.com>
> Date: Thu, 14 Dec 2017 11:13:15 +0800
>
>> Thanks for reply :)
>> I think I should use "udelay(100000/HZ)" instead, do you think it is
>> right?
> The delay is too long, please do not ignore that part of my critique
> of your change.
>
> You cannot delay so long under a lock, that's why the code is trying
> to use a sleeping delay.
>
> I'm not going to explain this problem another time.
^ permalink raw reply
* Re: [PATCH 1/2] hp100: Fix a possible sleep-in-atomic bug in hp100_login_to_vg_hub
From: David Miller @ 2017-12-14 3:34 UTC (permalink / raw)
To: baijiaju1990; +Cc: perex, floeff, acme, netdev, linux-kernel
In-Reply-To: <18472c42-4eaf-7189-a16f-489a706cba3e@gmail.com>
From: Jia-Ju Bai <baijiaju1990@gmail.com>
Date: Thu, 14 Dec 2017 11:13:15 +0800
> Thanks for reply :)
> I think I should use "udelay(100000/HZ)" instead, do you think it is
> right?
The delay is too long, please do not ignore that part of my critique
of your change.
You cannot delay so long under a lock, that's why the code is trying
to use a sleeping delay.
I'm not going to explain this problem another time.
^ permalink raw reply
* Re: [PATCH 1/2] hp100: Fix a possible sleep-in-atomic bug in hp100_login_to_vg_hub
From: Jia-Ju Bai @ 2017-12-14 3:31 UTC (permalink / raw)
To: David Miller; +Cc: perex, floeff, acme, netdev, linux-kernel
In-Reply-To: <18472c42-4eaf-7189-a16f-489a706cba3e@gmail.com>
Sorry, I made a mistake in last e-mail.
Maybe "mdelay(1000/HZ)" or "udelay(1000000/HZ)" .
Which one do you think is right?
Thanks,
Jia-Ju Bai
On 2017/12/14 11:13, Jia-Ju Bai wrote:
> Thanks for reply :)
> I think I should use "udelay(100000/HZ)" instead, do you think it is
> right?
>
>
> Thanks,
> Jia-Ju Bai
>
>
> On 2017/12/14 5:20, David Miller wrote:
>> I want you to review all of your patches and resend them after you
>> have checked them carefully.
>>
>> The first patch I even looked at, this one, is buggy.
>>
>> You changed a schedule_timeout_interruptible(1) into a udelay(10)
>>
>> That's not right.
>>
>> schedule_timeout_interruptible() takes a "jiffies" argument, which
>> is a completely different unit than udelay() takes. You would have
>> to scale the argument to udelay() in some way using HZ.
>>
>> Furthermore, the udelay argument you would come up with would
>> be way too long to be appropirate in this atomic context.
>>
>> That's why the code tries to use a sleeping timeout, a long wait is
>> necessary here.
>
^ permalink raw reply
* [PATCH v4 13/14] nubus: Add expansion_type values for various Mac models
From: Finn Thain @ 2017-12-14 3:16 UTC (permalink / raw)
To: Geert Uytterhoeven; +Cc: linux-m68k, linux-kernel, David S. Miller, netdev
In-Reply-To: <cover.1513220582.git.fthain@telegraphics.com.au>
Add an expansion slot attribute to allow drivers to properly handle
cards like Comm Slot cards and PDS cards without declaration ROMs.
This clarifies the logic for the Centris 610 model which has no
Comm Slot but has an optional on-board SONIC device.
Cc: "David S. Miller" <davem@davemloft.net>
Tested-by: Stan Johnson <userm57@yahoo.com>
Signed-off-by: Finn Thain <fthain@telegraphics.com.au>
---
arch/m68k/include/asm/macintosh.h | 9 ++-
arch/m68k/mac/config.c | 110 +++++++++++++-------------------
drivers/net/ethernet/natsemi/macsonic.c | 8 +--
3 files changed, 54 insertions(+), 73 deletions(-)
diff --git a/arch/m68k/include/asm/macintosh.h b/arch/m68k/include/asm/macintosh.h
index f42c27400dbc..9b840c03ebb7 100644
--- a/arch/m68k/include/asm/macintosh.h
+++ b/arch/m68k/include/asm/macintosh.h
@@ -33,7 +33,7 @@ struct mac_model
char ide_type;
char scc_type;
char ether_type;
- char nubus_type;
+ char expansion_type;
char floppy_type;
};
@@ -73,8 +73,11 @@ struct mac_model
#define MAC_ETHER_SONIC 1
#define MAC_ETHER_MACE 2
-#define MAC_NO_NUBUS 0
-#define MAC_NUBUS 1
+#define MAC_EXP_NONE 0
+#define MAC_EXP_PDS 1 /* Accepts only a PDS card */
+#define MAC_EXP_NUBUS 2 /* Accepts only NuBus card(s) */
+#define MAC_EXP_PDS_NUBUS 3 /* Accepts PDS card and/or NuBus card(s) */
+#define MAC_EXP_PDS_COMM 4 /* Accepts PDS card or Comm Slot card */
#define MAC_FLOPPY_IWM 0
#define MAC_FLOPPY_SWIM_ADDR1 1
diff --git a/arch/m68k/mac/config.c b/arch/m68k/mac/config.c
index 16cd5cea5207..d3d435248a24 100644
--- a/arch/m68k/mac/config.c
+++ b/arch/m68k/mac/config.c
@@ -212,7 +212,7 @@ static struct mac_model mac_data_table[] = {
.via_type = MAC_VIA_II,
.scsi_type = MAC_SCSI_OLD,
.scc_type = MAC_SCC_II,
- .nubus_type = MAC_NUBUS,
+ .expansion_type = MAC_EXP_NUBUS,
.floppy_type = MAC_FLOPPY_IWM,
},
@@ -227,7 +227,7 @@ static struct mac_model mac_data_table[] = {
.via_type = MAC_VIA_II,
.scsi_type = MAC_SCSI_OLD,
.scc_type = MAC_SCC_II,
- .nubus_type = MAC_NUBUS,
+ .expansion_type = MAC_EXP_NUBUS,
.floppy_type = MAC_FLOPPY_IWM,
}, {
.ident = MAC_MODEL_IIX,
@@ -236,7 +236,7 @@ static struct mac_model mac_data_table[] = {
.via_type = MAC_VIA_II,
.scsi_type = MAC_SCSI_OLD,
.scc_type = MAC_SCC_II,
- .nubus_type = MAC_NUBUS,
+ .expansion_type = MAC_EXP_NUBUS,
.floppy_type = MAC_FLOPPY_SWIM_ADDR2,
}, {
.ident = MAC_MODEL_IICX,
@@ -245,7 +245,7 @@ static struct mac_model mac_data_table[] = {
.via_type = MAC_VIA_II,
.scsi_type = MAC_SCSI_OLD,
.scc_type = MAC_SCC_II,
- .nubus_type = MAC_NUBUS,
+ .expansion_type = MAC_EXP_NUBUS,
.floppy_type = MAC_FLOPPY_SWIM_ADDR2,
}, {
.ident = MAC_MODEL_SE30,
@@ -254,7 +254,7 @@ static struct mac_model mac_data_table[] = {
.via_type = MAC_VIA_II,
.scsi_type = MAC_SCSI_OLD,
.scc_type = MAC_SCC_II,
- .nubus_type = MAC_NUBUS,
+ .expansion_type = MAC_EXP_PDS,
.floppy_type = MAC_FLOPPY_SWIM_ADDR2,
},
@@ -272,7 +272,7 @@ static struct mac_model mac_data_table[] = {
.via_type = MAC_VIA_IICI,
.scsi_type = MAC_SCSI_OLD,
.scc_type = MAC_SCC_II,
- .nubus_type = MAC_NUBUS,
+ .expansion_type = MAC_EXP_NUBUS,
.floppy_type = MAC_FLOPPY_SWIM_ADDR2,
}, {
.ident = MAC_MODEL_IIFX,
@@ -281,7 +281,7 @@ static struct mac_model mac_data_table[] = {
.via_type = MAC_VIA_IICI,
.scsi_type = MAC_SCSI_IIFX,
.scc_type = MAC_SCC_IOP,
- .nubus_type = MAC_NUBUS,
+ .expansion_type = MAC_EXP_PDS_NUBUS,
.floppy_type = MAC_FLOPPY_SWIM_IOP,
}, {
.ident = MAC_MODEL_IISI,
@@ -290,7 +290,7 @@ static struct mac_model mac_data_table[] = {
.via_type = MAC_VIA_IICI,
.scsi_type = MAC_SCSI_OLD,
.scc_type = MAC_SCC_II,
- .nubus_type = MAC_NUBUS,
+ .expansion_type = MAC_EXP_PDS_NUBUS,
.floppy_type = MAC_FLOPPY_SWIM_ADDR2,
}, {
.ident = MAC_MODEL_IIVI,
@@ -299,7 +299,7 @@ static struct mac_model mac_data_table[] = {
.via_type = MAC_VIA_IICI,
.scsi_type = MAC_SCSI_LC,
.scc_type = MAC_SCC_II,
- .nubus_type = MAC_NUBUS,
+ .expansion_type = MAC_EXP_NUBUS,
.floppy_type = MAC_FLOPPY_SWIM_ADDR2,
}, {
.ident = MAC_MODEL_IIVX,
@@ -308,7 +308,7 @@ static struct mac_model mac_data_table[] = {
.via_type = MAC_VIA_IICI,
.scsi_type = MAC_SCSI_LC,
.scc_type = MAC_SCC_II,
- .nubus_type = MAC_NUBUS,
+ .expansion_type = MAC_EXP_NUBUS,
.floppy_type = MAC_FLOPPY_SWIM_ADDR2,
},
@@ -323,7 +323,6 @@ static struct mac_model mac_data_table[] = {
.via_type = MAC_VIA_IICI,
.scsi_type = MAC_SCSI_LC,
.scc_type = MAC_SCC_II,
- .nubus_type = MAC_NUBUS,
.floppy_type = MAC_FLOPPY_SWIM_ADDR2,
}, {
.ident = MAC_MODEL_CCL,
@@ -332,7 +331,7 @@ static struct mac_model mac_data_table[] = {
.via_type = MAC_VIA_IICI,
.scsi_type = MAC_SCSI_LC,
.scc_type = MAC_SCC_II,
- .nubus_type = MAC_NUBUS,
+ .expansion_type = MAC_EXP_PDS,
.floppy_type = MAC_FLOPPY_SWIM_ADDR2,
}, {
.ident = MAC_MODEL_CCLII,
@@ -341,7 +340,7 @@ static struct mac_model mac_data_table[] = {
.via_type = MAC_VIA_IICI,
.scsi_type = MAC_SCSI_LC,
.scc_type = MAC_SCC_II,
- .nubus_type = MAC_NUBUS,
+ .expansion_type = MAC_EXP_PDS,
.floppy_type = MAC_FLOPPY_SWIM_ADDR2,
},
@@ -356,7 +355,7 @@ static struct mac_model mac_data_table[] = {
.via_type = MAC_VIA_IICI,
.scsi_type = MAC_SCSI_LC,
.scc_type = MAC_SCC_II,
- .nubus_type = MAC_NUBUS,
+ .expansion_type = MAC_EXP_PDS,
.floppy_type = MAC_FLOPPY_SWIM_ADDR2,
}, {
.ident = MAC_MODEL_LCII,
@@ -365,7 +364,7 @@ static struct mac_model mac_data_table[] = {
.via_type = MAC_VIA_IICI,
.scsi_type = MAC_SCSI_LC,
.scc_type = MAC_SCC_II,
- .nubus_type = MAC_NUBUS,
+ .expansion_type = MAC_EXP_PDS,
.floppy_type = MAC_FLOPPY_SWIM_ADDR2,
}, {
.ident = MAC_MODEL_LCIII,
@@ -374,7 +373,7 @@ static struct mac_model mac_data_table[] = {
.via_type = MAC_VIA_IICI,
.scsi_type = MAC_SCSI_LC,
.scc_type = MAC_SCC_II,
- .nubus_type = MAC_NUBUS,
+ .expansion_type = MAC_EXP_PDS,
.floppy_type = MAC_FLOPPY_SWIM_ADDR2,
},
@@ -395,7 +394,7 @@ static struct mac_model mac_data_table[] = {
.via_type = MAC_VIA_QUADRA,
.scsi_type = MAC_SCSI_QUADRA,
.scc_type = MAC_SCC_QUADRA,
- .nubus_type = MAC_NUBUS,
+ .expansion_type = MAC_EXP_PDS,
.floppy_type = MAC_FLOPPY_SWIM_ADDR1,
}, {
.ident = MAC_MODEL_Q605_ACC,
@@ -404,7 +403,7 @@ static struct mac_model mac_data_table[] = {
.via_type = MAC_VIA_QUADRA,
.scsi_type = MAC_SCSI_QUADRA,
.scc_type = MAC_SCC_QUADRA,
- .nubus_type = MAC_NUBUS,
+ .expansion_type = MAC_EXP_PDS,
.floppy_type = MAC_FLOPPY_SWIM_ADDR1,
}, {
.ident = MAC_MODEL_Q610,
@@ -414,7 +413,7 @@ static struct mac_model mac_data_table[] = {
.scsi_type = MAC_SCSI_QUADRA,
.scc_type = MAC_SCC_QUADRA,
.ether_type = MAC_ETHER_SONIC,
- .nubus_type = MAC_NUBUS,
+ .expansion_type = MAC_EXP_PDS_NUBUS,
.floppy_type = MAC_FLOPPY_SWIM_ADDR1,
}, {
.ident = MAC_MODEL_Q630,
@@ -424,8 +423,7 @@ static struct mac_model mac_data_table[] = {
.scsi_type = MAC_SCSI_QUADRA,
.ide_type = MAC_IDE_QUADRA,
.scc_type = MAC_SCC_QUADRA,
- .ether_type = MAC_ETHER_SONIC,
- .nubus_type = MAC_NUBUS,
+ .expansion_type = MAC_EXP_PDS_COMM,
.floppy_type = MAC_FLOPPY_SWIM_ADDR1,
}, {
.ident = MAC_MODEL_Q650,
@@ -435,7 +433,7 @@ static struct mac_model mac_data_table[] = {
.scsi_type = MAC_SCSI_QUADRA,
.scc_type = MAC_SCC_QUADRA,
.ether_type = MAC_ETHER_SONIC,
- .nubus_type = MAC_NUBUS,
+ .expansion_type = MAC_EXP_PDS_NUBUS,
.floppy_type = MAC_FLOPPY_SWIM_ADDR1,
},
/* The Q700 does have a NS Sonic */
@@ -447,7 +445,7 @@ static struct mac_model mac_data_table[] = {
.scsi_type = MAC_SCSI_QUADRA2,
.scc_type = MAC_SCC_QUADRA,
.ether_type = MAC_ETHER_SONIC,
- .nubus_type = MAC_NUBUS,
+ .expansion_type = MAC_EXP_PDS_NUBUS,
.floppy_type = MAC_FLOPPY_SWIM_ADDR1,
}, {
.ident = MAC_MODEL_Q800,
@@ -457,7 +455,7 @@ static struct mac_model mac_data_table[] = {
.scsi_type = MAC_SCSI_QUADRA,
.scc_type = MAC_SCC_QUADRA,
.ether_type = MAC_ETHER_SONIC,
- .nubus_type = MAC_NUBUS,
+ .expansion_type = MAC_EXP_PDS_NUBUS,
.floppy_type = MAC_FLOPPY_SWIM_ADDR1,
}, {
.ident = MAC_MODEL_Q840,
@@ -467,7 +465,7 @@ static struct mac_model mac_data_table[] = {
.scsi_type = MAC_SCSI_QUADRA3,
.scc_type = MAC_SCC_PSC,
.ether_type = MAC_ETHER_MACE,
- .nubus_type = MAC_NUBUS,
+ .expansion_type = MAC_EXP_NUBUS,
.floppy_type = MAC_FLOPPY_AV,
}, {
.ident = MAC_MODEL_Q900,
@@ -477,7 +475,7 @@ static struct mac_model mac_data_table[] = {
.scsi_type = MAC_SCSI_QUADRA2,
.scc_type = MAC_SCC_IOP,
.ether_type = MAC_ETHER_SONIC,
- .nubus_type = MAC_NUBUS,
+ .expansion_type = MAC_EXP_PDS_NUBUS,
.floppy_type = MAC_FLOPPY_SWIM_IOP,
}, {
.ident = MAC_MODEL_Q950,
@@ -487,7 +485,7 @@ static struct mac_model mac_data_table[] = {
.scsi_type = MAC_SCSI_QUADRA2,
.scc_type = MAC_SCC_IOP,
.ether_type = MAC_ETHER_SONIC,
- .nubus_type = MAC_NUBUS,
+ .expansion_type = MAC_EXP_PDS_NUBUS,
.floppy_type = MAC_FLOPPY_SWIM_IOP,
},
@@ -502,7 +500,7 @@ static struct mac_model mac_data_table[] = {
.via_type = MAC_VIA_IICI,
.scsi_type = MAC_SCSI_LC,
.scc_type = MAC_SCC_II,
- .nubus_type = MAC_NUBUS,
+ .expansion_type = MAC_EXP_PDS,
.floppy_type = MAC_FLOPPY_SWIM_ADDR2,
}, {
.ident = MAC_MODEL_P475,
@@ -511,7 +509,7 @@ static struct mac_model mac_data_table[] = {
.via_type = MAC_VIA_QUADRA,
.scsi_type = MAC_SCSI_QUADRA,
.scc_type = MAC_SCC_II,
- .nubus_type = MAC_NUBUS,
+ .expansion_type = MAC_EXP_PDS,
.floppy_type = MAC_FLOPPY_SWIM_ADDR1,
}, {
.ident = MAC_MODEL_P475F,
@@ -520,7 +518,7 @@ static struct mac_model mac_data_table[] = {
.via_type = MAC_VIA_QUADRA,
.scsi_type = MAC_SCSI_QUADRA,
.scc_type = MAC_SCC_II,
- .nubus_type = MAC_NUBUS,
+ .expansion_type = MAC_EXP_PDS,
.floppy_type = MAC_FLOPPY_SWIM_ADDR1,
}, {
.ident = MAC_MODEL_P520,
@@ -529,7 +527,7 @@ static struct mac_model mac_data_table[] = {
.via_type = MAC_VIA_IICI,
.scsi_type = MAC_SCSI_LC,
.scc_type = MAC_SCC_II,
- .nubus_type = MAC_NUBUS,
+ .expansion_type = MAC_EXP_PDS,
.floppy_type = MAC_FLOPPY_SWIM_ADDR2,
}, {
.ident = MAC_MODEL_P550,
@@ -538,7 +536,7 @@ static struct mac_model mac_data_table[] = {
.via_type = MAC_VIA_IICI,
.scsi_type = MAC_SCSI_LC,
.scc_type = MAC_SCC_II,
- .nubus_type = MAC_NUBUS,
+ .expansion_type = MAC_EXP_PDS,
.floppy_type = MAC_FLOPPY_SWIM_ADDR2,
},
/* These have the comm slot, and therefore possibly SONIC ethernet */
@@ -549,8 +547,7 @@ static struct mac_model mac_data_table[] = {
.via_type = MAC_VIA_QUADRA,
.scsi_type = MAC_SCSI_QUADRA,
.scc_type = MAC_SCC_II,
- .ether_type = MAC_ETHER_SONIC,
- .nubus_type = MAC_NUBUS,
+ .expansion_type = MAC_EXP_PDS_COMM,
.floppy_type = MAC_FLOPPY_SWIM_ADDR1,
}, {
.ident = MAC_MODEL_P588,
@@ -560,8 +557,7 @@ static struct mac_model mac_data_table[] = {
.scsi_type = MAC_SCSI_QUADRA,
.ide_type = MAC_IDE_QUADRA,
.scc_type = MAC_SCC_II,
- .ether_type = MAC_ETHER_SONIC,
- .nubus_type = MAC_NUBUS,
+ .expansion_type = MAC_EXP_PDS_COMM,
.floppy_type = MAC_FLOPPY_SWIM_ADDR1,
}, {
.ident = MAC_MODEL_TV,
@@ -570,7 +566,6 @@ static struct mac_model mac_data_table[] = {
.via_type = MAC_VIA_IICI,
.scsi_type = MAC_SCSI_LC,
.scc_type = MAC_SCC_II,
- .nubus_type = MAC_NUBUS,
.floppy_type = MAC_FLOPPY_SWIM_ADDR2,
}, {
.ident = MAC_MODEL_P600,
@@ -579,7 +574,7 @@ static struct mac_model mac_data_table[] = {
.via_type = MAC_VIA_IICI,
.scsi_type = MAC_SCSI_LC,
.scc_type = MAC_SCC_II,
- .nubus_type = MAC_NUBUS,
+ .expansion_type = MAC_EXP_NUBUS,
.floppy_type = MAC_FLOPPY_SWIM_ADDR2,
},
@@ -596,7 +591,7 @@ static struct mac_model mac_data_table[] = {
.scsi_type = MAC_SCSI_QUADRA,
.scc_type = MAC_SCC_QUADRA,
.ether_type = MAC_ETHER_SONIC,
- .nubus_type = MAC_NUBUS,
+ .expansion_type = MAC_EXP_PDS_NUBUS,
.floppy_type = MAC_FLOPPY_SWIM_ADDR1,
}, {
.ident = MAC_MODEL_C650,
@@ -606,7 +601,7 @@ static struct mac_model mac_data_table[] = {
.scsi_type = MAC_SCSI_QUADRA,
.scc_type = MAC_SCC_QUADRA,
.ether_type = MAC_ETHER_SONIC,
- .nubus_type = MAC_NUBUS,
+ .expansion_type = MAC_EXP_PDS_NUBUS,
.floppy_type = MAC_FLOPPY_SWIM_ADDR1,
}, {
.ident = MAC_MODEL_C660,
@@ -616,7 +611,7 @@ static struct mac_model mac_data_table[] = {
.scsi_type = MAC_SCSI_QUADRA3,
.scc_type = MAC_SCC_PSC,
.ether_type = MAC_ETHER_MACE,
- .nubus_type = MAC_NUBUS,
+ .expansion_type = MAC_EXP_PDS_NUBUS,
.floppy_type = MAC_FLOPPY_AV,
},
@@ -633,7 +628,6 @@ static struct mac_model mac_data_table[] = {
.via_type = MAC_VIA_QUADRA,
.scsi_type = MAC_SCSI_OLD,
.scc_type = MAC_SCC_QUADRA,
- .nubus_type = MAC_NUBUS,
.floppy_type = MAC_FLOPPY_SWIM_ADDR2,
}, {
.ident = MAC_MODEL_PB145,
@@ -642,7 +636,6 @@ static struct mac_model mac_data_table[] = {
.via_type = MAC_VIA_QUADRA,
.scsi_type = MAC_SCSI_OLD,
.scc_type = MAC_SCC_QUADRA,
- .nubus_type = MAC_NUBUS,
.floppy_type = MAC_FLOPPY_SWIM_ADDR2,
}, {
.ident = MAC_MODEL_PB150,
@@ -652,7 +645,6 @@ static struct mac_model mac_data_table[] = {
.scsi_type = MAC_SCSI_OLD,
.ide_type = MAC_IDE_PB,
.scc_type = MAC_SCC_QUADRA,
- .nubus_type = MAC_NUBUS,
.floppy_type = MAC_FLOPPY_SWIM_ADDR2,
}, {
.ident = MAC_MODEL_PB160,
@@ -661,7 +653,6 @@ static struct mac_model mac_data_table[] = {
.via_type = MAC_VIA_QUADRA,
.scsi_type = MAC_SCSI_OLD,
.scc_type = MAC_SCC_QUADRA,
- .nubus_type = MAC_NUBUS,
.floppy_type = MAC_FLOPPY_SWIM_ADDR2,
}, {
.ident = MAC_MODEL_PB165,
@@ -670,7 +661,6 @@ static struct mac_model mac_data_table[] = {
.via_type = MAC_VIA_QUADRA,
.scsi_type = MAC_SCSI_OLD,
.scc_type = MAC_SCC_QUADRA,
- .nubus_type = MAC_NUBUS,
.floppy_type = MAC_FLOPPY_SWIM_ADDR2,
}, {
.ident = MAC_MODEL_PB165C,
@@ -679,7 +669,6 @@ static struct mac_model mac_data_table[] = {
.via_type = MAC_VIA_QUADRA,
.scsi_type = MAC_SCSI_OLD,
.scc_type = MAC_SCC_QUADRA,
- .nubus_type = MAC_NUBUS,
.floppy_type = MAC_FLOPPY_SWIM_ADDR2,
}, {
.ident = MAC_MODEL_PB170,
@@ -688,7 +677,6 @@ static struct mac_model mac_data_table[] = {
.via_type = MAC_VIA_QUADRA,
.scsi_type = MAC_SCSI_OLD,
.scc_type = MAC_SCC_QUADRA,
- .nubus_type = MAC_NUBUS,
.floppy_type = MAC_FLOPPY_SWIM_ADDR2,
}, {
.ident = MAC_MODEL_PB180,
@@ -697,7 +685,6 @@ static struct mac_model mac_data_table[] = {
.via_type = MAC_VIA_QUADRA,
.scsi_type = MAC_SCSI_OLD,
.scc_type = MAC_SCC_QUADRA,
- .nubus_type = MAC_NUBUS,
.floppy_type = MAC_FLOPPY_SWIM_ADDR2,
}, {
.ident = MAC_MODEL_PB180C,
@@ -706,7 +693,6 @@ static struct mac_model mac_data_table[] = {
.via_type = MAC_VIA_QUADRA,
.scsi_type = MAC_SCSI_OLD,
.scc_type = MAC_SCC_QUADRA,
- .nubus_type = MAC_NUBUS,
.floppy_type = MAC_FLOPPY_SWIM_ADDR2,
}, {
.ident = MAC_MODEL_PB190,
@@ -716,7 +702,6 @@ static struct mac_model mac_data_table[] = {
.scsi_type = MAC_SCSI_LATE,
.ide_type = MAC_IDE_BABOON,
.scc_type = MAC_SCC_QUADRA,
- .nubus_type = MAC_NUBUS,
.floppy_type = MAC_FLOPPY_SWIM_ADDR2,
}, {
.ident = MAC_MODEL_PB520,
@@ -726,7 +711,6 @@ static struct mac_model mac_data_table[] = {
.scsi_type = MAC_SCSI_LATE,
.scc_type = MAC_SCC_QUADRA,
.ether_type = MAC_ETHER_SONIC,
- .nubus_type = MAC_NUBUS,
.floppy_type = MAC_FLOPPY_SWIM_ADDR2,
},
@@ -743,7 +727,7 @@ static struct mac_model mac_data_table[] = {
.via_type = MAC_VIA_IICI,
.scsi_type = MAC_SCSI_DUO,
.scc_type = MAC_SCC_QUADRA,
- .nubus_type = MAC_NUBUS,
+ .expansion_type = MAC_EXP_NUBUS,
.floppy_type = MAC_FLOPPY_SWIM_ADDR2,
}, {
.ident = MAC_MODEL_PB230,
@@ -752,7 +736,7 @@ static struct mac_model mac_data_table[] = {
.via_type = MAC_VIA_IICI,
.scsi_type = MAC_SCSI_DUO,
.scc_type = MAC_SCC_QUADRA,
- .nubus_type = MAC_NUBUS,
+ .expansion_type = MAC_EXP_NUBUS,
.floppy_type = MAC_FLOPPY_SWIM_ADDR2,
}, {
.ident = MAC_MODEL_PB250,
@@ -761,7 +745,7 @@ static struct mac_model mac_data_table[] = {
.via_type = MAC_VIA_IICI,
.scsi_type = MAC_SCSI_DUO,
.scc_type = MAC_SCC_QUADRA,
- .nubus_type = MAC_NUBUS,
+ .expansion_type = MAC_EXP_NUBUS,
.floppy_type = MAC_FLOPPY_SWIM_ADDR2,
}, {
.ident = MAC_MODEL_PB270C,
@@ -770,7 +754,7 @@ static struct mac_model mac_data_table[] = {
.via_type = MAC_VIA_IICI,
.scsi_type = MAC_SCSI_DUO,
.scc_type = MAC_SCC_QUADRA,
- .nubus_type = MAC_NUBUS,
+ .expansion_type = MAC_EXP_NUBUS,
.floppy_type = MAC_FLOPPY_SWIM_ADDR2,
}, {
.ident = MAC_MODEL_PB280,
@@ -779,7 +763,7 @@ static struct mac_model mac_data_table[] = {
.via_type = MAC_VIA_IICI,
.scsi_type = MAC_SCSI_DUO,
.scc_type = MAC_SCC_QUADRA,
- .nubus_type = MAC_NUBUS,
+ .expansion_type = MAC_EXP_NUBUS,
.floppy_type = MAC_FLOPPY_SWIM_ADDR2,
}, {
.ident = MAC_MODEL_PB280C,
@@ -788,7 +772,7 @@ static struct mac_model mac_data_table[] = {
.via_type = MAC_VIA_IICI,
.scsi_type = MAC_SCSI_DUO,
.scc_type = MAC_SCC_QUADRA,
- .nubus_type = MAC_NUBUS,
+ .expansion_type = MAC_EXP_NUBUS,
.floppy_type = MAC_FLOPPY_SWIM_ADDR2,
},
@@ -1100,14 +1084,12 @@ int __init mac_platform_init(void)
* Ethernet device
*/
- switch (macintosh_config->ether_type) {
- case MAC_ETHER_SONIC:
+ if (macintosh_config->ether_type == MAC_ETHER_SONIC ||
+ macintosh_config->expansion_type == MAC_EXP_PDS_COMM)
platform_device_register_simple("macsonic", -1, NULL, 0);
- break;
- case MAC_ETHER_MACE:
+
+ if (macintosh_config->ether_type == MAC_ETHER_MACE)
platform_device_register_simple("macmace", -1, NULL, 0);
- break;
- }
return 0;
}
diff --git a/drivers/net/ethernet/natsemi/macsonic.c b/drivers/net/ethernet/natsemi/macsonic.c
index 313fe5e0184b..b922ab5cedea 100644
--- a/drivers/net/ethernet/natsemi/macsonic.c
+++ b/drivers/net/ethernet/natsemi/macsonic.c
@@ -311,7 +311,7 @@ static int mac_onboard_sonic_probe(struct net_device *dev)
{
struct sonic_local* lp = netdev_priv(dev);
int sr;
- int commslot = 0;
+ bool commslot = macintosh_config->expansion_type == MAC_EXP_PDS_COMM;
if (!MACH_IS_MAC)
return -ENODEV;
@@ -322,10 +322,7 @@ static int mac_onboard_sonic_probe(struct net_device *dev)
Ethernet (BTW, the Ethernet *is* always at the same
address, and nothing else lives there, at least if Apple's
documentation is to be believed) */
- if (macintosh_config->ident == MAC_MODEL_Q630 ||
- macintosh_config->ident == MAC_MODEL_P588 ||
- macintosh_config->ident == MAC_MODEL_P575 ||
- macintosh_config->ident == MAC_MODEL_C610) {
+ if (commslot || macintosh_config->ident == MAC_MODEL_C610) {
int card_present;
card_present = hwreg_present((void*)ONBOARD_SONIC_REGISTERS);
@@ -333,7 +330,6 @@ static int mac_onboard_sonic_probe(struct net_device *dev)
printk("none.\n");
return -ENODEV;
}
- commslot = 1;
}
printk("yes\n");
--
2.13.6
^ permalink raw reply related
* [PATCH v4 11/14] nubus: Rename struct nubus_dev
From: Finn Thain @ 2017-12-14 3:16 UTC (permalink / raw)
To: Geert Uytterhoeven
Cc: linux-m68k, linux-kernel, David S. Miller,
Bartlomiej Zolnierkiewicz, netdev, linux-fbdev
In-Reply-To: <cover.1513220582.git.fthain@telegraphics.com.au>
It is misleading to call a functional resource a "device". In adopting
the Linux Driver Model, the struct device will be embedded in struct
nubus_board. That will compound the terminlogy problem because drivers
will bind with boards, not with functional resources. Avoid this by
renaming struct nubus_dev as struct nubus_rsrc. "Functional resource"
is the vendor's terminology so this helps avoid confusion.
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Acked-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Tested-by: Stan Johnson <userm57@yahoo.com>
Signed-off-by: Finn Thain <fthain@telegraphics.com.au>
---
drivers/net/ethernet/8390/mac8390.c | 26 ++++----
drivers/net/ethernet/natsemi/macsonic.c | 22 +++----
drivers/nubus/nubus.c | 105 ++++++++++++++++----------------
drivers/nubus/proc.c | 15 ++---
drivers/video/fbdev/macfb.c | 2 +-
include/linux/nubus.h | 30 +++++----
6 files changed, 98 insertions(+), 102 deletions(-)
diff --git a/drivers/net/ethernet/8390/mac8390.c b/drivers/net/ethernet/8390/mac8390.c
index 9497f18eaba0..929ff6419621 100644
--- a/drivers/net/ethernet/8390/mac8390.c
+++ b/drivers/net/ethernet/8390/mac8390.c
@@ -123,7 +123,8 @@ enum mac8390_access {
};
extern int mac8390_memtest(struct net_device *dev);
-static int mac8390_initdev(struct net_device *dev, struct nubus_dev *ndev,
+static int mac8390_initdev(struct net_device *dev,
+ struct nubus_rsrc *ndev,
enum mac8390_type type);
static int mac8390_open(struct net_device *dev);
@@ -169,11 +170,11 @@ static void word_memcpy_tocard(unsigned long tp, const void *fp, int count);
static void word_memcpy_fromcard(void *tp, unsigned long fp, int count);
static u32 mac8390_msg_enable;
-static enum mac8390_type __init mac8390_ident(struct nubus_dev *dev)
+static enum mac8390_type __init mac8390_ident(struct nubus_rsrc *fres)
{
- switch (dev->dr_sw) {
+ switch (fres->dr_sw) {
case NUBUS_DRSW_3COM:
- switch (dev->dr_hw) {
+ switch (fres->dr_hw) {
case NUBUS_DRHW_APPLE_SONIC_NB:
case NUBUS_DRHW_APPLE_SONIC_LC:
case NUBUS_DRHW_SONNET:
@@ -184,7 +185,7 @@ static enum mac8390_type __init mac8390_ident(struct nubus_dev *dev)
break;
case NUBUS_DRSW_APPLE:
- switch (dev->dr_hw) {
+ switch (fres->dr_hw) {
case NUBUS_DRHW_ASANTE_LC:
return MAC8390_NONE;
case NUBUS_DRHW_CABLETRON:
@@ -201,7 +202,7 @@ static enum mac8390_type __init mac8390_ident(struct nubus_dev *dev)
case NUBUS_DRSW_TECHWORKS:
case NUBUS_DRSW_DAYNA2:
case NUBUS_DRSW_DAYNA_LC:
- if (dev->dr_hw == NUBUS_DRHW_CABLETRON)
+ if (fres->dr_hw == NUBUS_DRHW_CABLETRON)
return MAC8390_CABLETRON;
else
return MAC8390_APPLE;
@@ -212,7 +213,7 @@ static enum mac8390_type __init mac8390_ident(struct nubus_dev *dev)
break;
case NUBUS_DRSW_KINETICS:
- switch (dev->dr_hw) {
+ switch (fres->dr_hw) {
case NUBUS_DRHW_INTERLAN:
return MAC8390_INTERLAN;
default:
@@ -225,8 +226,8 @@ static enum mac8390_type __init mac8390_ident(struct nubus_dev *dev)
* These correspond to Dayna Sonic cards
* which use the macsonic driver
*/
- if (dev->dr_hw == NUBUS_DRHW_SMC9194 ||
- dev->dr_hw == NUBUS_DRHW_INTERLAN)
+ if (fres->dr_hw == NUBUS_DRHW_SMC9194 ||
+ fres->dr_hw == NUBUS_DRHW_INTERLAN)
return MAC8390_NONE;
else
return MAC8390_DAYNA;
@@ -289,7 +290,8 @@ static int __init mac8390_memsize(unsigned long membase)
return i * 0x1000;
}
-static bool __init mac8390_init(struct net_device *dev, struct nubus_dev *ndev,
+static bool __init mac8390_init(struct net_device *dev,
+ struct nubus_rsrc *ndev,
enum mac8390_type cardtype)
{
struct nubus_dir dir;
@@ -394,7 +396,7 @@ static bool __init mac8390_init(struct net_device *dev, struct nubus_dev *ndev,
struct net_device * __init mac8390_probe(int unit)
{
struct net_device *dev;
- struct nubus_dev *ndev = NULL;
+ struct nubus_rsrc *ndev = NULL;
int err = -ENODEV;
struct ei_device *ei_local;
@@ -489,7 +491,7 @@ static const struct net_device_ops mac8390_netdev_ops = {
};
static int __init mac8390_initdev(struct net_device *dev,
- struct nubus_dev *ndev,
+ struct nubus_rsrc *ndev,
enum mac8390_type type)
{
static u32 fwrd4_offsets[16] = {
diff --git a/drivers/net/ethernet/natsemi/macsonic.c b/drivers/net/ethernet/natsemi/macsonic.c
index a42433fb6949..14f3fb50dc21 100644
--- a/drivers/net/ethernet/natsemi/macsonic.c
+++ b/drivers/net/ethernet/natsemi/macsonic.c
@@ -428,26 +428,26 @@ static int mac_nubus_sonic_ethernet_addr(struct net_device *dev,
return 0;
}
-static int macsonic_ident(struct nubus_dev *ndev)
+static int macsonic_ident(struct nubus_rsrc *fres)
{
- if (ndev->dr_hw == NUBUS_DRHW_ASANTE_LC &&
- ndev->dr_sw == NUBUS_DRSW_SONIC_LC)
+ if (fres->dr_hw == NUBUS_DRHW_ASANTE_LC &&
+ fres->dr_sw == NUBUS_DRSW_SONIC_LC)
return MACSONIC_DAYNALINK;
- if (ndev->dr_hw == NUBUS_DRHW_SONIC &&
- ndev->dr_sw == NUBUS_DRSW_APPLE) {
+ if (fres->dr_hw == NUBUS_DRHW_SONIC &&
+ fres->dr_sw == NUBUS_DRSW_APPLE) {
/* There has to be a better way to do this... */
- if (strstr(ndev->board->name, "DuoDock"))
+ if (strstr(fres->board->name, "DuoDock"))
return MACSONIC_DUODOCK;
else
return MACSONIC_APPLE;
}
- if (ndev->dr_hw == NUBUS_DRHW_SMC9194 &&
- ndev->dr_sw == NUBUS_DRSW_DAYNA)
+ if (fres->dr_hw == NUBUS_DRHW_SMC9194 &&
+ fres->dr_sw == NUBUS_DRSW_DAYNA)
return MACSONIC_DAYNA;
- if (ndev->dr_hw == NUBUS_DRHW_APPLE_SONIC_LC &&
- ndev->dr_sw == 0) { /* huh? */
+ if (fres->dr_hw == NUBUS_DRHW_APPLE_SONIC_LC &&
+ fres->dr_sw == 0) { /* huh? */
return MACSONIC_APPLE16;
}
return -1;
@@ -456,7 +456,7 @@ static int macsonic_ident(struct nubus_dev *ndev)
static int mac_nubus_sonic_probe(struct net_device *dev)
{
static int slots;
- struct nubus_dev* ndev = NULL;
+ struct nubus_rsrc *ndev = NULL;
struct sonic_local* lp = netdev_priv(dev);
unsigned long base_addr, prom_addr;
u16 sonic_dcr;
diff --git a/drivers/nubus/nubus.c b/drivers/nubus/nubus.c
index b0d8aa721173..324f6e4407c8 100644
--- a/drivers/nubus/nubus.c
+++ b/drivers/nubus/nubus.c
@@ -32,7 +32,7 @@
/* Globals */
-struct nubus_dev *nubus_devices;
+struct nubus_rsrc *nubus_func_rsrcs;
struct nubus_board *nubus_boards;
/* Meaning of "bytelanes":
@@ -228,12 +228,11 @@ int nubus_get_root_dir(const struct nubus_board *board,
EXPORT_SYMBOL(nubus_get_root_dir);
/* This is a slyly renamed version of the above */
-int nubus_get_func_dir(const struct nubus_dev *dev,
- struct nubus_dir *dir)
+int nubus_get_func_dir(const struct nubus_rsrc *fres, struct nubus_dir *dir)
{
- dir->ptr = dir->base = dev->directory;
+ dir->ptr = dir->base = fres->directory;
dir->done = 0;
- dir->mask = dev->board->lanes;
+ dir->mask = fres->board->lanes;
return 0;
}
EXPORT_SYMBOL(nubus_get_func_dir);
@@ -306,11 +305,10 @@ EXPORT_SYMBOL(nubus_rewinddir);
/* Driver interface functions, more or less like in pci.c */
-struct nubus_dev*
-nubus_find_type(unsigned short category, unsigned short type,
- const struct nubus_dev *from)
+struct nubus_rsrc *nubus_find_type(unsigned short category, unsigned short type,
+ const struct nubus_rsrc *from)
{
- struct nubus_dev *itor = from ? from->next : nubus_devices;
+ struct nubus_rsrc *itor = from ? from->next : nubus_func_rsrcs;
while (itor) {
if (itor->category == category && itor->type == type)
@@ -321,10 +319,10 @@ nubus_find_type(unsigned short category, unsigned short type,
}
EXPORT_SYMBOL(nubus_find_type);
-struct nubus_dev*
-nubus_find_slot(unsigned int slot, const struct nubus_dev *from)
+struct nubus_rsrc *nubus_find_slot(unsigned int slot,
+ const struct nubus_rsrc *from)
{
- struct nubus_dev *itor = from ? from->next : nubus_devices;
+ struct nubus_rsrc *itor = from ? from->next : nubus_func_rsrcs;
while (itor) {
if (itor->board->slot == slot)
@@ -403,19 +401,19 @@ static int __init nubus_get_display_vidmode(struct nubus_board *board,
return 0;
}
-static int __init nubus_get_display_resource(struct nubus_dev *dev,
+static int __init nubus_get_display_resource(struct nubus_rsrc *fres,
struct proc_dir_entry *procdir,
const struct nubus_dirent *ent)
{
switch (ent->type) {
case NUBUS_RESID_GAMMADIR:
pr_debug(" gamma directory offset: 0x%06x\n", ent->data);
- nubus_get_block_rsrc_dir(dev->board, procdir, ent);
+ nubus_get_block_rsrc_dir(fres->board, procdir, ent);
break;
case 0x0080 ... 0x0085:
pr_debug(" mode 0x%02x info offset: 0x%06x\n",
ent->type, ent->data);
- nubus_get_display_vidmode(dev->board, procdir, ent);
+ nubus_get_display_vidmode(fres->board, procdir, ent);
break;
default:
pr_debug(" unknown resource 0x%02x, data 0x%06x\n",
@@ -425,7 +423,7 @@ static int __init nubus_get_display_resource(struct nubus_dev *dev,
return 0;
}
-static int __init nubus_get_network_resource(struct nubus_dev *dev,
+static int __init nubus_get_network_resource(struct nubus_rsrc *fres,
struct proc_dir_entry *procdir,
const struct nubus_dirent *ent)
{
@@ -447,7 +445,7 @@ static int __init nubus_get_network_resource(struct nubus_dev *dev,
return 0;
}
-static int __init nubus_get_cpu_resource(struct nubus_dev *dev,
+static int __init nubus_get_cpu_resource(struct nubus_rsrc *fres,
struct proc_dir_entry *procdir,
const struct nubus_dirent *ent)
{
@@ -480,19 +478,19 @@ static int __init nubus_get_cpu_resource(struct nubus_dev *dev,
return 0;
}
-static int __init nubus_get_private_resource(struct nubus_dev *dev,
+static int __init nubus_get_private_resource(struct nubus_rsrc *fres,
struct proc_dir_entry *procdir,
const struct nubus_dirent *ent)
{
- switch (dev->category) {
+ switch (fres->category) {
case NUBUS_CAT_DISPLAY:
- nubus_get_display_resource(dev, procdir, ent);
+ nubus_get_display_resource(fres, procdir, ent);
break;
case NUBUS_CAT_NETWORK:
- nubus_get_network_resource(dev, procdir, ent);
+ nubus_get_network_resource(fres, procdir, ent);
break;
case NUBUS_CAT_CPU:
- nubus_get_cpu_resource(dev, procdir, ent);
+ nubus_get_cpu_resource(fres, procdir, ent);
break;
default:
pr_debug(" unknown resource 0x%02x, data 0x%06x\n",
@@ -502,24 +500,25 @@ static int __init nubus_get_private_resource(struct nubus_dev *dev,
return 0;
}
-static struct nubus_dev * __init
+static struct nubus_rsrc * __init
nubus_get_functional_resource(struct nubus_board *board, int slot,
const struct nubus_dirent *parent)
{
struct nubus_dir dir;
struct nubus_dirent ent;
- struct nubus_dev *dev;
+ struct nubus_rsrc *fres;
pr_debug(" Functional resource 0x%02x:\n", parent->type);
nubus_get_subdir(parent, &dir);
dir.procdir = nubus_proc_add_rsrc_dir(board->procdir, parent, board);
/* Actually we should probably panic if this fails */
- if ((dev = kzalloc(sizeof(*dev), GFP_ATOMIC)) == NULL)
+ fres = kzalloc(sizeof(*fres), GFP_ATOMIC);
+ if (!fres)
return NULL;
- dev->resid = parent->type;
- dev->directory = dir.base;
- dev->board = board;
+ fres->resid = parent->type;
+ fres->directory = dir.base;
+ fres->board = board;
while (nubus_readdir(&dir, &ent) != -1) {
switch (ent.type) {
@@ -528,10 +527,10 @@ nubus_get_functional_resource(struct nubus_board *board, int slot,
unsigned short nbtdata[4];
nubus_get_rsrc_mem(nbtdata, &ent, 8);
- dev->category = nbtdata[0];
- dev->type = nbtdata[1];
- dev->dr_sw = nbtdata[2];
- dev->dr_hw = nbtdata[3];
+ fres->category = nbtdata[0];
+ fres->type = nbtdata[1];
+ fres->dr_sw = nbtdata[2];
+ fres->dr_hw = nbtdata[3];
pr_debug(" type: [cat 0x%x type 0x%x sw 0x%x hw 0x%x]\n",
nbtdata[0], nbtdata[1], nbtdata[2], nbtdata[3]);
nubus_proc_add_rsrc_mem(dir.procdir, &ent, 8);
@@ -589,11 +588,11 @@ nubus_get_functional_resource(struct nubus_board *board, int slot,
default:
/* Local/Private resources have their own
function */
- nubus_get_private_resource(dev, dir.procdir, &ent);
+ nubus_get_private_resource(fres, dir.procdir, &ent);
}
}
- return dev;
+ return fres;
}
/* This is *really* cool. */
@@ -727,7 +726,6 @@ static int __init nubus_get_board_resource(struct nubus_board *board, int slot,
return 0;
}
-/* Add a board (might be many devices) to the list */
static struct nubus_board * __init nubus_add_board(int slot, int bytelanes)
{
struct nubus_board *board;
@@ -799,10 +797,11 @@ static struct nubus_board * __init nubus_add_board(int slot, int bytelanes)
pr_debug("Slot %X resources:\n", slot);
/* Each slot should have one board resource and any number of
- functional resources. So we'll fill in some fields in the
- struct nubus_board from the board resource, then walk down
- the list of functional resources, spinning out a nubus_dev
- for each of them. */
+ * functional resources. So we'll fill in some fields in the
+ * struct nubus_board from the board resource, then walk down
+ * the list of functional resources, spinning out a nubus_rsrc
+ * for each of them.
+ */
if (nubus_readdir(&dir, &ent) == -1) {
/* We can't have this! */
pr_err("Slot %X: Board resource not found!\n", slot);
@@ -817,32 +816,32 @@ static struct nubus_board * __init nubus_add_board(int slot, int bytelanes)
nubus_get_board_resource(board, slot, &ent);
while (nubus_readdir(&dir, &ent) != -1) {
- struct nubus_dev *dev;
- struct nubus_dev **devp;
+ struct nubus_rsrc *fres;
+ struct nubus_rsrc **fresp;
- dev = nubus_get_functional_resource(board, slot, &ent);
- if (dev == NULL)
+ fres = nubus_get_functional_resource(board, slot, &ent);
+ if (fres == NULL)
continue;
/* Resources should appear in ascending ID order. This sanity
* check prevents duplicate resource IDs.
*/
- if (dev->resid <= prev_resid) {
- kfree(dev);
+ if (fres->resid <= prev_resid) {
+ kfree(fres);
continue;
}
- prev_resid = dev->resid;
+ prev_resid = fres->resid;
/* We zeroed this out above */
- if (board->first_dev == NULL)
- board->first_dev = dev;
+ if (board->first_func_rsrc == NULL)
+ board->first_func_rsrc = fres;
- /* Put it on the global NuBus device chain. Keep entries in order. */
- for (devp = &nubus_devices; *devp != NULL;
- devp = &((*devp)->next))
+ /* Put it on the func. resource list. Keep entries in order. */
+ for (fresp = &nubus_func_rsrcs; *fresp != NULL;
+ fresp = &((*fresp)->next))
/* spin */;
- *devp = dev;
- dev->next = NULL;
+ *fresp = fres;
+ fres->next = NULL;
}
/* Put it on the global NuBus board chain. Keep entries in order. */
diff --git a/drivers/nubus/proc.c b/drivers/nubus/proc.c
index ad8b0648a6c0..9ffaafdb3d2c 100644
--- a/drivers/nubus/proc.c
+++ b/drivers/nubus/proc.c
@@ -36,17 +36,14 @@
static int
nubus_devices_proc_show(struct seq_file *m, void *v)
{
- struct nubus_dev *dev = nubus_devices;
+ struct nubus_rsrc *fres = nubus_func_rsrcs;
- while (dev) {
+ while (fres) {
seq_printf(m, "%x\t%04x %04x %04x %04x",
- dev->board->slot,
- dev->category,
- dev->type,
- dev->dr_sw,
- dev->dr_hw);
- seq_printf(m, "\t%08lx\n", dev->board->slot_addr);
- dev = dev->next;
+ fres->board->slot, fres->category, fres->type,
+ fres->dr_sw, fres->dr_hw);
+ seq_printf(m, "\t%08lx\n", fres->board->slot_addr);
+ fres = fres->next;
}
return 0;
}
diff --git a/drivers/video/fbdev/macfb.c b/drivers/video/fbdev/macfb.c
index cda7587cbc86..e86a2796e3d9 100644
--- a/drivers/video/fbdev/macfb.c
+++ b/drivers/video/fbdev/macfb.c
@@ -556,7 +556,7 @@ static void __init iounmap_macfb(void)
static int __init macfb_init(void)
{
int video_cmap_len, video_is_nubus = 0;
- struct nubus_dev* ndev = NULL;
+ struct nubus_rsrc *ndev = NULL;
char *option = NULL;
int err;
diff --git a/include/linux/nubus.h b/include/linux/nubus.h
index 0e40c9d6b977..8a40505a52ef 100644
--- a/include/linux/nubus.h
+++ b/include/linux/nubus.h
@@ -33,7 +33,7 @@ struct nubus_dirent {
struct nubus_board {
struct nubus_board *next;
- struct nubus_dev *first_dev;
+ struct nubus_rsrc *first_func_rsrc;
/* Only 9-E actually exist, though 0-8 are also theoretically
possible, and 0 is a special case which represents the
@@ -62,11 +62,11 @@ struct nubus_board {
struct proc_dir_entry *procdir;
};
-struct nubus_dev {
- /* Next link in device list */
- struct nubus_dev *next;
+struct nubus_rsrc {
+ /* Next link in list */
+ struct nubus_rsrc *next;
- /* The functional resource ID of this device */
+ /* The functional resource ID */
unsigned char resid;
/* These are mostly here for convenience; we could always read
them from the ROMs if we wanted to */
@@ -81,8 +81,8 @@ struct nubus_dev {
struct nubus_board *board;
};
-/* This is all NuBus devices (used to find devices later on) */
-extern struct nubus_dev *nubus_devices;
+/* This is all NuBus functional resources (used to find devices later on) */
+extern struct nubus_rsrc *nubus_func_rsrcs;
/* This is all NuBus cards */
extern struct nubus_board *nubus_boards;
@@ -115,13 +115,12 @@ static inline void nubus_proc_add_rsrc(struct proc_dir_entry *procdir,
const struct nubus_dirent *ent) {}
#endif
-/* If we need more precision we can add some more of these */
-struct nubus_dev *nubus_find_type(unsigned short category,
- unsigned short type,
- const struct nubus_dev *from);
-/* Might have more than one device in a slot, you know... */
-struct nubus_dev *nubus_find_slot(unsigned int slot,
- const struct nubus_dev *from);
+struct nubus_rsrc *nubus_find_type(unsigned short category,
+ unsigned short type,
+ const struct nubus_rsrc *from);
+
+struct nubus_rsrc *nubus_find_slot(unsigned int slot,
+ const struct nubus_rsrc *from);
/* These are somewhat more NuBus-specific. They all return 0 for
success and -1 for failure, as you'd expect. */
@@ -134,8 +133,7 @@ int nubus_get_root_dir(const struct nubus_board *board,
int nubus_get_board_dir(const struct nubus_board* board,
struct nubus_dir* dir);
/* The functional directory */
-int nubus_get_func_dir(const struct nubus_dev *dev,
- struct nubus_dir *dir);
+int nubus_get_func_dir(const struct nubus_rsrc *fres, struct nubus_dir *dir);
/* These work on any directory gotten via the above */
int nubus_readdir(struct nubus_dir *dir,
--
2.13.6
^ permalink raw reply related
* [PATCH v4 12/14] nubus: Adopt standard linked list implementation
From: Finn Thain @ 2017-12-14 3:16 UTC (permalink / raw)
To: Geert Uytterhoeven
Cc: linux-m68k, linux-kernel, David S. Miller,
Bartlomiej Zolnierkiewicz, netdev, linux-fbdev
In-Reply-To: <cover.1513220582.git.fthain@telegraphics.com.au>
This increases code re-use and improves readability.
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Acked-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Tested-by: Stan Johnson <userm57@yahoo.com>
Signed-off-by: Finn Thain <fthain@telegraphics.com.au>
---
drivers/net/ethernet/8390/mac8390.c | 7 +++--
drivers/net/ethernet/cirrus/mac89x0.c | 6 +++--
drivers/net/ethernet/natsemi/macsonic.c | 8 +++---
drivers/nubus/nubus.c | 45 ++++++++-------------------------
drivers/nubus/proc.c | 11 +++-----
drivers/video/fbdev/macfb.c | 8 +++---
include/linux/nubus.h | 15 +++++------
7 files changed, 40 insertions(+), 60 deletions(-)
diff --git a/drivers/net/ethernet/8390/mac8390.c b/drivers/net/ethernet/8390/mac8390.c
index 929ff6419621..2f91ce8dc614 100644
--- a/drivers/net/ethernet/8390/mac8390.c
+++ b/drivers/net/ethernet/8390/mac8390.c
@@ -416,8 +416,11 @@ struct net_device * __init mac8390_probe(int unit)
if (unit >= 0)
sprintf(dev->name, "eth%d", unit);
- while ((ndev = nubus_find_type(NUBUS_CAT_NETWORK, NUBUS_TYPE_ETHERNET,
- ndev))) {
+ for_each_func_rsrc(ndev) {
+ if (ndev->category != NUBUS_CAT_NETWORK ||
+ ndev->type != NUBUS_TYPE_ETHERNET)
+ continue;
+
/* Have we seen it already? */
if (slots & (1 << ndev->board->slot))
continue;
diff --git a/drivers/net/ethernet/cirrus/mac89x0.c b/drivers/net/ethernet/cirrus/mac89x0.c
index f910f0f386d6..977d4c2c759d 100644
--- a/drivers/net/ethernet/cirrus/mac89x0.c
+++ b/drivers/net/ethernet/cirrus/mac89x0.c
@@ -187,6 +187,7 @@ struct net_device * __init mac89x0_probe(int unit)
unsigned long ioaddr;
unsigned short sig;
int err = -ENODEV;
+ struct nubus_rsrc *fres;
if (!MACH_IS_MAC)
return ERR_PTR(-ENODEV);
@@ -207,8 +208,9 @@ struct net_device * __init mac89x0_probe(int unit)
/* We might have to parameterize this later */
slot = 0xE;
/* Get out now if there's a real NuBus card in slot E */
- if (nubus_find_slot(slot, NULL) != NULL)
- goto out;
+ for_each_func_rsrc(fres)
+ if (fres->board->slot == slot)
+ goto out;
/* The pseudo-ISA bits always live at offset 0x300 (gee,
wonder why...) */
diff --git a/drivers/net/ethernet/natsemi/macsonic.c b/drivers/net/ethernet/natsemi/macsonic.c
index 14f3fb50dc21..313fe5e0184b 100644
--- a/drivers/net/ethernet/natsemi/macsonic.c
+++ b/drivers/net/ethernet/natsemi/macsonic.c
@@ -464,9 +464,11 @@ static int mac_nubus_sonic_probe(struct net_device *dev)
int reg_offset, dma_bitmode;
/* Find the first SONIC that hasn't been initialized already */
- while ((ndev = nubus_find_type(NUBUS_CAT_NETWORK,
- NUBUS_TYPE_ETHERNET, ndev)) != NULL)
- {
+ for_each_func_rsrc(ndev) {
+ if (ndev->category != NUBUS_CAT_NETWORK ||
+ ndev->type != NUBUS_TYPE_ETHERNET)
+ continue;
+
/* Have we seen it already? */
if (slots & (1<<ndev->board->slot))
continue;
diff --git a/drivers/nubus/nubus.c b/drivers/nubus/nubus.c
index 324f6e4407c8..380f320c050f 100644
--- a/drivers/nubus/nubus.c
+++ b/drivers/nubus/nubus.c
@@ -32,7 +32,7 @@
/* Globals */
-struct nubus_rsrc *nubus_func_rsrcs;
+LIST_HEAD(nubus_func_rsrcs);
struct nubus_board *nubus_boards;
/* Meaning of "bytelanes":
@@ -305,33 +305,20 @@ EXPORT_SYMBOL(nubus_rewinddir);
/* Driver interface functions, more or less like in pci.c */
-struct nubus_rsrc *nubus_find_type(unsigned short category, unsigned short type,
- const struct nubus_rsrc *from)
+struct nubus_rsrc *nubus_first_rsrc_or_null(void)
{
- struct nubus_rsrc *itor = from ? from->next : nubus_func_rsrcs;
-
- while (itor) {
- if (itor->category == category && itor->type == type)
- return itor;
- itor = itor->next;
- }
- return NULL;
+ return list_first_entry_or_null(&nubus_func_rsrcs, struct nubus_rsrc,
+ list);
}
-EXPORT_SYMBOL(nubus_find_type);
+EXPORT_SYMBOL(nubus_first_rsrc_or_null);
-struct nubus_rsrc *nubus_find_slot(unsigned int slot,
- const struct nubus_rsrc *from)
+struct nubus_rsrc *nubus_next_rsrc_or_null(struct nubus_rsrc *from)
{
- struct nubus_rsrc *itor = from ? from->next : nubus_func_rsrcs;
-
- while (itor) {
- if (itor->board->slot == slot)
- return itor;
- itor = itor->next;
- }
- return NULL;
+ if (list_is_last(&from->list, &nubus_func_rsrcs))
+ return NULL;
+ return list_next_entry(from, list);
}
-EXPORT_SYMBOL(nubus_find_slot);
+EXPORT_SYMBOL(nubus_next_rsrc_or_null);
int
nubus_find_rsrc(struct nubus_dir *dir, unsigned char rsrc_type,
@@ -817,7 +804,6 @@ static struct nubus_board * __init nubus_add_board(int slot, int bytelanes)
while (nubus_readdir(&dir, &ent) != -1) {
struct nubus_rsrc *fres;
- struct nubus_rsrc **fresp;
fres = nubus_get_functional_resource(board, slot, &ent);
if (fres == NULL)
@@ -832,16 +818,7 @@ static struct nubus_board * __init nubus_add_board(int slot, int bytelanes)
}
prev_resid = fres->resid;
- /* We zeroed this out above */
- if (board->first_func_rsrc == NULL)
- board->first_func_rsrc = fres;
-
- /* Put it on the func. resource list. Keep entries in order. */
- for (fresp = &nubus_func_rsrcs; *fresp != NULL;
- fresp = &((*fresp)->next))
- /* spin */;
- *fresp = fres;
- fres->next = NULL;
+ list_add_tail(&fres->list, &nubus_func_rsrcs);
}
/* Put it on the global NuBus board chain. Keep entries in order. */
diff --git a/drivers/nubus/proc.c b/drivers/nubus/proc.c
index 9ffaafdb3d2c..ccaaec4ed291 100644
--- a/drivers/nubus/proc.c
+++ b/drivers/nubus/proc.c
@@ -36,15 +36,12 @@
static int
nubus_devices_proc_show(struct seq_file *m, void *v)
{
- struct nubus_rsrc *fres = nubus_func_rsrcs;
+ struct nubus_rsrc *fres;
- while (fres) {
- seq_printf(m, "%x\t%04x %04x %04x %04x",
+ for_each_func_rsrc(fres)
+ seq_printf(m, "%x\t%04x %04x %04x %04x\t%08lx\n",
fres->board->slot, fres->category, fres->type,
- fres->dr_sw, fres->dr_hw);
- seq_printf(m, "\t%08lx\n", fres->board->slot_addr);
- fres = fres->next;
- }
+ fres->dr_sw, fres->dr_hw, fres->board->slot_addr);
return 0;
}
diff --git a/drivers/video/fbdev/macfb.c b/drivers/video/fbdev/macfb.c
index e86a2796e3d9..e707e617bf1c 100644
--- a/drivers/video/fbdev/macfb.c
+++ b/drivers/video/fbdev/macfb.c
@@ -670,15 +670,17 @@ static int __init macfb_init(void)
* code is really broken :-)
*/
- while ((ndev = nubus_find_type(NUBUS_CAT_DISPLAY,
- NUBUS_TYPE_VIDEO, ndev)))
- {
+ for_each_func_rsrc(ndev) {
unsigned long base = ndev->board->slot_addr;
if (mac_bi_data.videoaddr < base ||
mac_bi_data.videoaddr - base > 0xFFFFFF)
continue;
+ if (ndev->category != NUBUS_CAT_DISPLAY ||
+ ndev->type != NUBUS_TYPE_VIDEO)
+ continue;
+
video_is_nubus = 1;
slot_addr = (unsigned char *)base;
diff --git a/include/linux/nubus.h b/include/linux/nubus.h
index 8a40505a52ef..aee7c50e9a2e 100644
--- a/include/linux/nubus.h
+++ b/include/linux/nubus.h
@@ -33,7 +33,6 @@ struct nubus_dirent {
struct nubus_board {
struct nubus_board *next;
- struct nubus_rsrc *first_func_rsrc;
/* Only 9-E actually exist, though 0-8 are also theoretically
possible, and 0 is a special case which represents the
@@ -63,8 +62,7 @@ struct nubus_board {
};
struct nubus_rsrc {
- /* Next link in list */
- struct nubus_rsrc *next;
+ struct list_head list;
/* The functional resource ID */
unsigned char resid;
@@ -82,7 +80,7 @@ struct nubus_rsrc {
};
/* This is all NuBus functional resources (used to find devices later on) */
-extern struct nubus_rsrc *nubus_func_rsrcs;
+extern struct list_head nubus_func_rsrcs;
/* This is all NuBus cards */
extern struct nubus_board *nubus_boards;
@@ -115,12 +113,11 @@ static inline void nubus_proc_add_rsrc(struct proc_dir_entry *procdir,
const struct nubus_dirent *ent) {}
#endif
-struct nubus_rsrc *nubus_find_type(unsigned short category,
- unsigned short type,
- const struct nubus_rsrc *from);
+struct nubus_rsrc *nubus_first_rsrc_or_null(void);
+struct nubus_rsrc *nubus_next_rsrc_or_null(struct nubus_rsrc *from);
-struct nubus_rsrc *nubus_find_slot(unsigned int slot,
- const struct nubus_rsrc *from);
+#define for_each_func_rsrc(f) \
+ for (f = nubus_first_rsrc_or_null(); f; f = nubus_next_rsrc_or_null(f))
/* These are somewhat more NuBus-specific. They all return 0 for
success and -1 for failure, as you'd expect. */
--
2.13.6
^ permalink raw reply related
* Re: [PATCH 1/2] hp100: Fix a possible sleep-in-atomic bug in hp100_login_to_vg_hub
From: Jia-Ju Bai @ 2017-12-14 3:13 UTC (permalink / raw)
To: David Miller; +Cc: perex, floeff, acme, netdev, linux-kernel
In-Reply-To: <20171213.162032.129766742729458957.davem@davemloft.net>
Thanks for reply :)
I think I should use "udelay(100000/HZ)" instead, do you think it is right?
Thanks,
Jia-Ju Bai
On 2017/12/14 5:20, David Miller wrote:
> I want you to review all of your patches and resend them after you
> have checked them carefully.
>
> The first patch I even looked at, this one, is buggy.
>
> You changed a schedule_timeout_interruptible(1) into a udelay(10)
>
> That's not right.
>
> schedule_timeout_interruptible() takes a "jiffies" argument, which
> is a completely different unit than udelay() takes. You would have
> to scale the argument to udelay() in some way using HZ.
>
> Furthermore, the udelay argument you would come up with would
> be way too long to be appropirate in this atomic context.
>
> That's why the code tries to use a sleeping timeout, a long wait is
> necessary here.
^ permalink raw reply
* Re: [BUG] skge: a possible sleep-in-atomic bug in skge_remove
From: Jia-Ju Bai @ 2017-12-14 3:06 UTC (permalink / raw)
To: Stephen Hemminger
Cc: David Miller, mlindner, shemminger, shemminger, netdev,
linux-kernel
In-Reply-To: <20171213085006.7093c27e@xeon-e3>
On 2017/12/14 0:50, Stephen Hemminger wrote:
> On Wed, 13 Dec 2017 15:42:56 +0800
> Jia-Ju Bai <baijiaju1990@gmail.com> wrote:
>
>> On 2017/12/13 13:18, Stephen Hemminger wrote:
>>> On Tue, 12 Dec 2017 20:57:01 -0500 (EST)
>>> David Miller <davem@davemloft.net> wrote:
>>>
>>>> From: Stephen Hemminger <stephen@networkplumber.org>
>>>> Date: Tue, 12 Dec 2017 10:22:40 -0800
>>>>
>>>>> On Tue, 12 Dec 2017 08:34:45 -0500 (EST)
>>>>> David Miller <davem@davemloft.net> wrote:
>>>>>
>>>>>> From: Jia-Ju Bai <baijiaju1990@gmail.com>
>>>>>> Date: Tue, 12 Dec 2017 16:38:12 +0800
>>>>>>
>>>>>>> According to drivers/net/ethernet/marvell/skge.c, the driver may sleep
>>>>>>> under a spinlock.
>>>>>>> The function call path is:
>>>>>>> skge_remove (acquire the spinlock)
>>>>>>> free_irq --> may sleep
>>>>>>>
>>>>>>> I do not find a good way to fix it, so I only report.
>>>>>>> This possible bug is found by my static analysis tool (DSAC) and
>>>>>>> checked by my code review.
>>>>>> This was added by:
>>>>>>
>>>>>> commit a9e9fd7182332d0cf5f3e601df3e71dd431b70d7
>>>>>> Author: Stephen Hemminger <shemminger@vyatta.com>
>>>>>> Date: Tue Sep 27 13:41:37 2011 -0400
>>>>>>
>>>>>> skge: handle irq better on single port card
>>>>>>
>>>>>> I think the free_irq() can be moved below the unlock.
>>>>>>
>>>>>> Stephen, please take a look.
>>>>> The IRQ was being free twice.
>>>>> How did you see it, I really doubt any multi-port SKGE cards
>>>>> still exist.
>>>> He sees it by reading the code, please take a look at this
>>>> and move the free_irq() out of the spin locked section since
>>>> it can sleep.
>>> Thanks, I was hoping for some automated static analysis tool.
>> This bug was found by an automated static analysis tool named DSAC,
>> which is written by myself.
>> Then I manually checked driver source code, and finally sent the bug report.
> Thanks.
> Would it be possible to put tool in tools directory and then have
> it automated by kbuild robot?
Hi,
Thanks for your appreciation of my tool :)
I think it is possible. But before releasing, I need to improve it to
solve some problems:
1. It produces some false positives and negatives. Thus I need
developer's response and confirmation of my bug reports, to help me to
improve my tool's accuracy.
2. It is based on Clang-3.2 (a LLVM-based compiler, not GCC), and some
driver code cannot compile normally. Maybe I should re-implement my tool
based on a recent Clang version.
3. Some software is needed when running my tool, thus as MySQL (maybe I
directly can write to files, instead of database in the future) and
Clang (Clang is necessary).
I think it may be difficult to directly put my tool in "tools"
directory. But with some configuration, it is possible to run it
automatically in a testing environment.
I also plan to open this tool in the future, after finishing the
improvements :)
Thanks,
Jia-Ju Bai
^ permalink raw reply
* [PATCH v2] ARM64: dts: meson-axg: add ethernet mac controller
From: Yixun Lan @ 2017-12-14 3:02 UTC (permalink / raw)
To: devicetree, Kevin Hilman
Cc: Neil Armstrong, Jerome Brunet, Giuseppe Cavallaro,
Alexandre Torgue, Carlo Caione, Yixun Lan, linux-amlogic,
linux-arm-kernel, linux-kernel, netdev
Add DT info for the stmmac ethernet MAC which found in
the Amlogic's Meson-AXG SoC, also describe the ethernet
pinctrl & clock information here.
This is tested in the S400 dev board which use a RTL8211F PHY,
and the pins connect to the 'eth_rgmii_y_pins' group.
Reviewed-by: Neil Armstrong <narmstrong@baylibre.com>
Signed-off-by: Yixun Lan <yixun.lan@amlogic.com>
---
Changes in v2 since [1]:
- rebase to kevin's v4.16/dt64 branch
- add Neil's Reviewed-by
- move clock info to board.dts instead of in soc.dtsi
- drop "meson-axg-dwmac" compatible string, since we didn't use this
we could re-add it later when we really need.
- note: to make ethernet work properly,it depend on clock & pinctrl[2],
to compile the DTS, the patch [3] is required.
the code part will be taken via clock & pinctrl subsystem tree.
[1]
http://lists.infradead.org/pipermail/linux-amlogic/2017-November/005301.html
[2]
http://lists.infradead.org/pipermail/linux-amlogic/2017-December/005735.html
http://lists.infradead.org/pipermail/linux-amlogic/2017-December/005694.html
[3]
http://lists.infradead.org/pipermail/linux-amlogic/2017-December/005738.html
---
arch/arm64/boot/dts/amlogic/meson-axg-s400.dts | 11 ++++++
arch/arm64/boot/dts/amlogic/meson-axg.dtsi | 50 ++++++++++++++++++++++++++
2 files changed, 61 insertions(+)
diff --git a/arch/arm64/boot/dts/amlogic/meson-axg-s400.dts b/arch/arm64/boot/dts/amlogic/meson-axg-s400.dts
index 70eca1f8736a..138de3bc7cc8 100644
--- a/arch/arm64/boot/dts/amlogic/meson-axg-s400.dts
+++ b/arch/arm64/boot/dts/amlogic/meson-axg-s400.dts
@@ -20,3 +20,14 @@
&uart_AO {
status = "okay";
};
+
+ðmac {
+ status = "okay";
+ clocks = <&clkc CLKID_ETH>,
+ <&clkc CLKID_FCLK_DIV2>,
+ <&clkc CLKID_MPLL2>;
+ clock-names = "stmmaceth", "clkin0", "clkin1";
+ phy-mode = "rgmii";
+ pinctrl-0 = <ð_rgmii_y_pins>;
+ pinctrl-names = "default";
+};
diff --git a/arch/arm64/boot/dts/amlogic/meson-axg.dtsi b/arch/arm64/boot/dts/amlogic/meson-axg.dtsi
index d356ce74ad89..106234fda765 100644
--- a/arch/arm64/boot/dts/amlogic/meson-axg.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-axg.dtsi
@@ -7,6 +7,7 @@
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/clock/axg-clkc.h>
/ {
compatible = "amlogic,meson-axg";
@@ -148,6 +149,15 @@
#address-cells = <0>;
};
+ ethmac: ethernet@ff3f0000 {
+ compatible = "amlogic,meson-gxbb-dwmac", "snps,dwmac";
+ reg = <0x0 0xff3f0000 0x0 0x10000
+ 0x0 0xff634540 0x0 0x8>;
+ interrupts = <GIC_SPI 8 IRQ_TYPE_EDGE_RISING>;
+ interrupt-names = "macirq";
+ status = "disabled";
+ };
+
hiubus: bus@ff63c000 {
compatible = "simple-bus";
reg = <0x0 0xff63c000 0x0 0x1c00>;
@@ -194,6 +204,46 @@
#gpio-cells = <2>;
gpio-ranges = <&pinctrl_periphs 0 0 86>;
};
+
+ eth_rgmii_x_pins: eth-x-rgmii {
+ mux {
+ groups = "eth_mdio_x",
+ "eth_mdc_x",
+ "eth_rgmii_rx_clk_x",
+ "eth_rx_dv_x",
+ "eth_rxd0_x",
+ "eth_rxd1_x",
+ "eth_rxd2_rgmii",
+ "eth_rxd3_rgmii",
+ "eth_rgmii_tx_clk",
+ "eth_txen_x",
+ "eth_txd0_x",
+ "eth_txd1_x",
+ "eth_txd2_rgmii",
+ "eth_txd3_rgmii";
+ function = "eth";
+ };
+ };
+
+ eth_rgmii_y_pins: eth-y-rgmii {
+ mux {
+ groups = "eth_mdio_y",
+ "eth_mdc_y",
+ "eth_rgmii_rx_clk_y",
+ "eth_rx_dv_y",
+ "eth_rxd0_y",
+ "eth_rxd1_y",
+ "eth_rxd2_rgmii",
+ "eth_rxd3_rgmii",
+ "eth_rgmii_tx_clk",
+ "eth_txen_y",
+ "eth_txd0_y",
+ "eth_txd1_y",
+ "eth_txd2_rgmii",
+ "eth_txd3_rgmii";
+ function = "eth";
+ };
+ };
};
};
--
2.15.1
^ permalink raw reply related
* Re: [bpf-next V1-RFC PATCH 01/14] xdp: base API for new XDP rx-queue info concept
From: David Ahern @ 2017-12-14 2:34 UTC (permalink / raw)
To: Jesper Dangaard Brouer, Daniel Borkmann, Alexei Starovoitov
Cc: netdev, gospo, bjorn.topel, michael.chan
In-Reply-To: <151316396600.14967.5648145904814220715.stgit@firesoul>
On 12/13/17 4:19 AM, Jesper Dangaard Brouer wrote:
> +
> +void xdp_rxq_info_unreg(struct xdp_rxq_info *xdp_rxq)
> +{
> + xdp_rxq->reg_state = REG_STATE_UNREGISTRED;
> +}
> +EXPORT_SYMBOL_GPL(xdp_rxq_info_unreg);
> +
> +void xdp_rxq_info_init(struct xdp_rxq_info *xdp_rxq)
> +{
> + if (xdp_rxq->reg_state == REG_STATE_REGISTRED) {
> + WARN(1, "Missing unregister, handled but fix driver\n");
> + xdp_rxq_info_unreg(xdp_rxq);
> + }
> + memset(xdp_rxq, 0, sizeof(*xdp_rxq));
> + xdp_rxq->queue_index = U32_MAX;
> + xdp_rxq->reg_state = REG_STATE_NEW;
> +}
> +EXPORT_SYMBOL_GPL(xdp_rxq_info_init);
> +
> +void xdp_rxq_info_reg(struct xdp_rxq_info *xdp_rxq)
> +{
> + WARN(!xdp_rxq->dev, "Missing net_device from driver");
> + WARN(xdp_rxq->queue_index == U32_MAX, "Miss queue_index from driver");
> + WARN(!(xdp_rxq->reg_state == REG_STATE_NEW),"API violation, miss init");
> + xdp_rxq->reg_state = REG_STATE_REGISTRED;
> +}
> +EXPORT_SYMBOL_GPL(xdp_rxq_info_reg);
>
Rather than WARN()'s why not make the _reg and _init functions return an
int that indicates an error? For example you don't want to continue if
the dev is expected but missing.
^ permalink raw reply
* Re: [bpf-next V1-RFC PATCH 08/14] nfp: setup xdp_rxq_info
From: Jakub Kicinski @ 2017-12-14 2:34 UTC (permalink / raw)
To: Jesper Dangaard Brouer
Cc: Daniel Borkmann, Alexei Starovoitov, dsahern, oss-drivers,
Simon Horman, netdev, gospo, bjorn.topel, michael.chan
In-Reply-To: <151316400161.14967.13516011331263133183.stgit@firesoul>
On Wed, 13 Dec 2017 12:20:01 +0100, Jesper Dangaard Brouer wrote:
> Driver hook points for xdp_rxq_info:
> * init+reg: nfp_net_rx_ring_alloc
> * unreg : nfp_net_rx_ring_free
>
> In struct nfp_net_rx_ring moved member @size into a hole on 64-bit.
> Thus, the size remaines the same after adding member @xdp_rxq.
>
> Cc: oss-drivers@netronome.com
> Cc: Jakub Kicinski <jakub.kicinski@netronome.com>
> Cc: Simon Horman <simon.horman@netronome.com>
> Signed-off-by: Jesper Dangaard Brouer <brouer@redhat.com>
> diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net.h b/drivers/net/ethernet/netronome/nfp/nfp_net.h
> index 3801c52098d5..0e564cfabe7e 100644
> --- a/drivers/net/ethernet/netronome/nfp/nfp_net.h
> +++ b/drivers/net/ethernet/netronome/nfp/nfp_net.h
> @@ -47,6 +47,7 @@
> #include <linux/netdevice.h>
> #include <linux/pci.h>
> #include <linux/io-64-nonatomic-hi-lo.h>
> +#include <net/xdp.h>
>
> #include "nfp_net_ctrl.h"
>
> @@ -350,6 +351,7 @@ struct nfp_net_rx_buf {
> * @rxds: Virtual address of FL/RX ring in host memory
> * @dma: DMA address of the FL/RX ring
> * @size: Size, in bytes, of the FL/RX ring (needed to free)
> + * @xdp_rxq: RX-ring info avail for XDP
> */
> struct nfp_net_rx_ring {
> struct nfp_net_r_vector *r_vec;
> @@ -361,13 +363,14 @@ struct nfp_net_rx_ring {
> u32 idx;
>
> int fl_qcidx;
> + unsigned int size;
> u8 __iomem *qcp_fl;
>
> struct nfp_net_rx_buf *rxbufs;
> struct nfp_net_rx_desc *rxds;
>
> dma_addr_t dma;
> - unsigned int size;
> + struct xdp_rxq_info xdp_rxq;
> } ____cacheline_aligned;
The @size member is not in the hole on purpose. IIRC all the members
up to @dma are in the first cacheline. All things which are not needed
on the fast path are after @dma. IOW @size is not used on the fast
path and the hole is for fast path stuff :)
> /**
> diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
> index ad3e9f6a61e5..6474aecd0451 100644
> --- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
> +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
> @@ -2252,6 +2253,7 @@ static void nfp_net_rx_ring_free(struct nfp_net_rx_ring *rx_ring)
> struct nfp_net_r_vector *r_vec = rx_ring->r_vec;
> struct nfp_net_dp *dp = &r_vec->nfp_net->dp;
>
> + xdp_rxq_info_unreg(&rx_ring->xdp_rxq);
> kfree(rx_ring->rxbufs);
>
> if (rx_ring->rxds)
> @@ -2277,6 +2279,12 @@ nfp_net_rx_ring_alloc(struct nfp_net_dp *dp, struct nfp_net_rx_ring *rx_ring)
> {
> int sz;
>
> + /* XDP RX-queue info */
> + xdp_rxq_info_init(&rx_ring->xdp_rxq);
> + rx_ring->xdp_rxq.dev = dp->netdev;
> + rx_ring->xdp_rxq.queue_index = rx_ring->idx;
> + xdp_rxq_info_reg(&rx_ring->xdp_rxq);
> +
> rx_ring->cnt = dp->rxd_cnt;
> rx_ring->size = sizeof(*rx_ring->rxds) * rx_ring->cnt;
> rx_ring->rxds = dma_zalloc_coherent(dp->dev, rx_ring->size,
The nfp driver implements the prepare/commit for reallocating rings.
I don't think it matters now, but there can be 2 sets of rings with the
same ID allocated during reconfiguration (see nfp_net_ring_reconfig()).
Maybe place the register/unregister in nfp_net_open_stack() and
nfp_net_close_stack() respectively?
Perhaps that won't be necessary, only cleaner :) I'm not sure how is
the redirect between drivers intended to work WRT freeing rings and
unloading drivers while packets fly...
^ permalink raw reply
* Re: [PATCH iproute2] ip: add vxcan to help text
From: Stephen Hemminger @ 2017-12-14 2:20 UTC (permalink / raw)
To: Oliver Hartkopp; +Cc: linux-can, netdev
In-Reply-To: <20171213202128.4424-1-socketcan@hartkopp.net>
On Wed, 13 Dec 2017 21:21:28 +0100
Oliver Hartkopp <socketcan@hartkopp.net> wrote:
> Add missing tag 'vxcan' inside the help text which was missing in commit
> efe459c76d35f ('ip: link add vxcan support').
>
> Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
Applied. Could you also fix the man page?
^ permalink raw reply
* Re: [patch iproute2] tc: fix json array closing
From: Stephen Hemminger @ 2017-12-14 2:19 UTC (permalink / raw)
To: Jiri Pirko; +Cc: netdev
In-Reply-To: <20171213195616.2548-1-jiri@resnulli.us>
On Wed, 13 Dec 2017 20:56:16 +0100
Jiri Pirko <jiri@resnulli.us> wrote:
> From: Jiri Pirko <jiri@mellanox.com>
>
> Fixes: 2704bd625583 ("tc: jsonify actions core")
> Signed-off-by: Jiri Pirko <jiri@mellanox.com>
Good catch. Applied
^ permalink raw reply
* Re: [PATCH net-next 0/4] ERSPAN version 2 (type III) support
From: William Tu @ 2017-12-14 2:08 UTC (permalink / raw)
To: Stephen Hemminger; +Cc: Linux Kernel Network Developers
In-Reply-To: <20171213175446.18c98648@xeon-e3>
On Wed, Dec 13, 2017 at 5:54 PM, Stephen Hemminger
<stephen@networkplumber.org> wrote:
> On Wed, 13 Dec 2017 16:38:54 -0800
> William Tu <u9012063@gmail.com> wrote:
>
>> ERSPAN has two versions, v1 (type II) and v2 (type III). This patch
>> series add support for erspan v2 based on existing erspan v1
>> implementation. The first patch refactors the existing erspan v1's
>> header structure, making it extensible to put additional v2's header.
>> The second and third patch introduces erspan v2's implementation to
>> ipv4 and ipv6 erspan, for both native mode and collect metadata mode.
>> Finally, test cases are added under the samples/bpf.
>>
>> Note:
>> ERSPAN version 2 has many features and this patch does not implement
>> all. One major use case of version 2 over version 1 is its timestamp
>> and direction. So the traffic collector is able to distinguish the
>> mirrorred traffic better. Other features such as SGT (security group
>> tag), FT (frame type) for carrying non-ethernet packet, and optional
>> subheader are not implemented yet.
>>
>> Example commandline for ERSPAN version 2:
>> ip link add dev ip6erspan11 type ip6erspan seq key 102 \
>> local fc00:100::2 remote fc00:100::1 \
>> erspan_ver 2 erspan_dir 1 erspan_hwid 17
>>
>> The corresponding iproute2 patch:
>> https://marc.info/?l=linux-netdev&m=151321141525106&w=2
>
>
> If this is accepted to net-next you will need to
> resubmit the iproute2 patch.
Hi Stephen,
Yes, I noticed that I forgot to update the iproute2 man page. Thanks
William
^ permalink raw reply
* Re: [PATCH net-next 0/4] ERSPAN version 2 (type III) support
From: Stephen Hemminger @ 2017-12-14 1:54 UTC (permalink / raw)
To: William Tu; +Cc: netdev
In-Reply-To: <1513211938-8749-1-git-send-email-u9012063@gmail.com>
On Wed, 13 Dec 2017 16:38:54 -0800
William Tu <u9012063@gmail.com> wrote:
> ERSPAN has two versions, v1 (type II) and v2 (type III). This patch
> series add support for erspan v2 based on existing erspan v1
> implementation. The first patch refactors the existing erspan v1's
> header structure, making it extensible to put additional v2's header.
> The second and third patch introduces erspan v2's implementation to
> ipv4 and ipv6 erspan, for both native mode and collect metadata mode.
> Finally, test cases are added under the samples/bpf.
>
> Note:
> ERSPAN version 2 has many features and this patch does not implement
> all. One major use case of version 2 over version 1 is its timestamp
> and direction. So the traffic collector is able to distinguish the
> mirrorred traffic better. Other features such as SGT (security group
> tag), FT (frame type) for carrying non-ethernet packet, and optional
> subheader are not implemented yet.
>
> Example commandline for ERSPAN version 2:
> ip link add dev ip6erspan11 type ip6erspan seq key 102 \
> local fc00:100::2 remote fc00:100::1 \
> erspan_ver 2 erspan_dir 1 erspan_hwid 17
>
> The corresponding iproute2 patch:
> https://marc.info/?l=linux-netdev&m=151321141525106&w=2
If this is accepted to net-next you will need to
resubmit the iproute2 patch.
^ permalink raw reply
* Re: [PATCH v6 2/3] sock: Move the socket inuse to namespace.
From: Tonghao Zhang @ 2017-12-14 1:22 UTC (permalink / raw)
To: Cong Wang
Cc: David Miller, Eric Dumazet, Willem de Bruijn, Pavel Emelyanov,
Linux Kernel Network Developers
In-Reply-To: <CAM_iQpUQb-khaHfNnvvdey69ok-FzLHUs2MmHKo2hUO0BUOKyg@mail.gmail.com>
On Wed, Dec 13, 2017 at 2:04 AM, Cong Wang <xiyou.wangcong@gmail.com> wrote:
> On Sun, Dec 10, 2017 at 7:12 AM, Tonghao Zhang <xiangxia.m.yue@gmail.com> wrote:
>> diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
>> index b797832..6c191fb 100644
>> --- a/net/core/net_namespace.c
>> +++ b/net/core/net_namespace.c
>> @@ -363,6 +363,13 @@ static struct net *net_alloc(void)
>> if (!net)
>> goto out_free;
>>
>> +#ifdef CONFIG_PROC_FS
>> + net->core.sock_inuse = alloc_percpu(int);
>> + if (!net->core.sock_inuse) {
>> + kmem_cache_free(net_cachep, net);
>> + goto out_free;
>> + }
>> +#endif
>> rcu_assign_pointer(net->gen, ng);
>> out:
>> return net;
>> @@ -374,6 +381,9 @@ static struct net *net_alloc(void)
>>
>> static void net_free(struct net *net)
>> {
>> +#ifdef CONFIG_PROC_FS
>> + free_percpu(net->core.sock_inuse);
>> +#endif
>> kfree(rcu_access_pointer(net->gen));
>> kmem_cache_free(net_cachep, net);
>> }
>
> Putting socket code in net_namespace.c doesn't look good.
hi cong,
Thanks for your work. If we dont alloc the in the net_alloc, it's
better to counter the sock for userspace
while the sock created in kernel will be omitted.
^ permalink raw reply
* Re: [PATCH 1/2] hp100: Fix a possible sleep-in-atomic bug in hp100_login_to_vg_hub
From: Joe Perches @ 2017-12-14 1:21 UTC (permalink / raw)
To: Jia-Ju Bai, perex, floeff, acme; +Cc: netdev, linux-kernel
In-Reply-To: <1513158468-14382-1-git-send-email-baijiaju1990@gmail.com>
On Wed, 2017-12-13 at 17:47 +0800, Jia-Ju Bai wrote:
> The driver may sleep under a spinlock.
> The function call path is:
> hp100_set_multicast_list (acquire the spinlock)
> hp100_login_to_vg_hub
> schedule_timeout_interruptible --> may sleep
>
> To fix it, schedule_timeout_interruptible is replaced with udelay.
>
> This bug is found by my static analysis tool(DSAC) and checked by my code review.
Are there any current working VG/AnyLan network installations?
I rather doubt it.
^ permalink raw reply
* Re: [patch net-next v3 05/10] net: sched: keep track of offloaded filters and check tc offload feature
From: Jakub Kicinski @ 2017-12-14 1:05 UTC (permalink / raw)
To: Jiri Pirko
Cc: netdev, davem, jhs, xiyou.wangcong, mlxsw, andrew, vivien.didelot,
f.fainelli, michael.chan, ganeshgr, saeedm, matanb, leonro,
idosch, simon.horman, pieter.jansenvanvuuren, john.hurley,
alexander.h.duyck, ogerlitz, john.fastabend, daniel
In-Reply-To: <20171213151038.29665-6-jiri@resnulli.us>
On Wed, 13 Dec 2017 16:10:33 +0100, Jiri Pirko wrote:
> From: Jiri Pirko <jiri@mellanox.com>
>
> During block bind, we need to check tc offload feature. If it is
> disabled yet still the block contains offloaded filters, forbid the
> bind. Also forbid to register callback for a block that already
> containes offloaded filters, as the play back is not supported now.
> For keeping track of offloaded filters there is a new counter
> introduced, alongside with couple of helpers called from cls_* code.
> These helpers set and clear TCA_CLS_FLAGS_IN_HW flag.
>
> Signed-off-by: Jiri Pirko <jiri@mellanox.com>
> diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
> index de9dbcb..ac25142 100644
> --- a/net/sched/cls_api.c
> +++ b/net/sched/cls_api.c
> @@ -266,31 +266,50 @@ void tcf_chain_put(struct tcf_chain *chain)
> }
> EXPORT_SYMBOL(tcf_chain_put);
>
> -static void tcf_block_offload_cmd(struct tcf_block *block, struct Qdisc *q,
> +static bool tcf_block_offload_in_use(struct tcf_block *block)
> +{
> + return block->offloadcnt;
> +}
> +
> +static void tcf_block_offload_cmd(struct tcf_block *block,
> + struct net_device *dev,
> struct tcf_block_ext_info *ei,
> enum tc_block_command command)
> {
> - struct net_device *dev = q->dev_queue->dev;
> struct tc_block_offload bo = {};
>
> - if (!dev->netdev_ops->ndo_setup_tc)
> - return;
> bo.command = command;
> bo.binder_type = ei->binder_type;
> bo.block = block;
> dev->netdev_ops->ndo_setup_tc(dev, TC_SETUP_BLOCK, &bo);
> }
>
> -static void tcf_block_offload_bind(struct tcf_block *block, struct Qdisc *q,
> - struct tcf_block_ext_info *ei)
> +static int tcf_block_offload_bind(struct tcf_block *block, struct Qdisc *q,
> + struct tcf_block_ext_info *ei)
> {
> - tcf_block_offload_cmd(block, q, ei, TC_BLOCK_BIND);
> + struct net_device *dev = q->dev_queue->dev;
> +
> + if (!dev->netdev_ops->ndo_setup_tc)
> + return 0;
> +
> + /* If tc offload feature is disabled and the block we try to bind
> + * to already has some offloaded filters, forbid to bind.
> + */
> + if (!tc_can_offload(dev) && tcf_block_offload_in_use(block))
> + return -EOPNOTSUPP;
I don't understand the tc_can_offload(dev) check here. The flow is -
on bind if TC offloads are enabled the new port will get a TC_BLOCK_BIND
and request a register, but the register will fail since the block is
offloaded?
But the whole bind operation does not fail, so user will not see an
error. The block will get bound but port's driver has no way to
register the callback. I'm sorry if I'm just being slow here..
> + tcf_block_offload_cmd(block, dev, ei, TC_BLOCK_BIND);
> + return 0;
> }
>
> static void tcf_block_offload_unbind(struct tcf_block *block, struct Qdisc *q,
> struct tcf_block_ext_info *ei)
> {
> - tcf_block_offload_cmd(block, q, ei, TC_BLOCK_UNBIND);
> + struct net_device *dev = q->dev_queue->dev;
> +
> + if (!dev->netdev_ops->ndo_setup_tc)
> + return;
> + tcf_block_offload_cmd(block, dev, ei, TC_BLOCK_UNBIND);
> }
>
> static int
> @@ -499,10 +518,15 @@ int tcf_block_get_ext(struct tcf_block **p_block, struct Qdisc *q,
> if (err)
> goto err_chain_head_change_cb_add;
>
> - tcf_block_offload_bind(block, q, ei);
> + err = tcf_block_offload_bind(block, q, ei);
> + if (err)
> + goto err_block_offload_bind;
Would it perhaps make more sense to add a TC_BLOCK_JOIN or some such?
IIUC the problem is we don't know whether the driver/callee of the new
port is aware of previous callbacks/filters and we can't replay them.
Obviously registering new callbacks on offloaded blocks is a no-go.
For simple bind to a new port of an ASIC which already knows the rule
set, we just need to ask all callbacks if they know the port and as
long as any of them responds "yes" we are safe to assume the bind is OK.
(Existing drivers will all respond with EOPNOTSUPP to a new unknown command.)
Does that make sense?
> *p_block = block;
> return 0;
>
> +err_block_offload_bind:
> + tcf_chain_head_change_cb_del(tcf_block_chain_zero(block), ei);
> err_chain_head_change_cb_add:
> tcf_block_owner_del(block, q, ei->binder_type);
> err_block_owner_add:
> @@ -630,9 +654,16 @@ struct tcf_block_cb *__tcf_block_cb_register(struct tcf_block *block,
> {
> struct tcf_block_cb *block_cb;
>
> + /* At this point, playback of previous block cb calls is not supported,
> + * so forbid to register to block which already has some offloaded
> + * filters present.
> + */
> + if (tcf_block_offload_in_use(block))
> + return ERR_PTR(-EOPNOTSUPP);
>
> block_cb = kzalloc(sizeof(*block_cb), GFP_KERNEL);
> if (!block_cb)
> - return NULL;
> + return ERR_PTR(-ENOMEM);
> block_cb->cb = cb;
> block_cb->cb_ident = cb_ident;
> block_cb->cb_priv = cb_priv;
> @@ -648,7 +679,7 @@ int tcf_block_cb_register(struct tcf_block *block,
> struct tcf_block_cb *block_cb;
>
> block_cb = __tcf_block_cb_register(block, cb, cb_ident, cb_priv);
> - return block_cb ? 0 : -ENOMEM;
> + return IS_ERR(block_cb) ? PTR_ERR(block_cb) : 0;
> }
> EXPORT_SYMBOL(tcf_block_cb_register);
>
^ permalink raw reply
* Re: [PATCH] openvswitch: Trim off padding before L3 conntrack processing
From: Pravin Shelar @ 2017-12-14 0:58 UTC (permalink / raw)
To: Ed Swierk
Cc: ovs-dev, Linux Kernel Network Developers, Pravin Shelar,
Lance Richardson, Benjamin Warren, Keith Holleman
In-Reply-To: <1513095439-128864-1-git-send-email-eswierk@skyportsystems.com>
On Tue, Dec 12, 2017 at 8:17 AM, Ed Swierk <eswierk@skyportsystems.com> wrote:
> A short IPv4 packet may have up to 6 bytes of padding following the IP
> payload when received on an Ethernet device.
>
> In the normal IPv4 receive path, ip_rcv() trims the packet to
> ip_hdr->tot_len before invoking NF_INET_PRE_ROUTING hooks (including
> conntrack). Then any subsequent L3+ processing steps, like
> nf_checksum(), use skb->len as the length of the packet, rather than
> referring back to ip_hdr->tot_len. In the IPv6 receive path, ip6_rcv()
> does the same using ipv6_hdr->payload_len.
>
> In the OVS conntrack receive path, this trimming does not occur, so
> the checksum verification in tcp_header() fails, printing "nf_ct_tcp:
> bad TCP checksum". Extra zero bytes don't affect the checksum, but the
> length in the IP pseudoheader does. That length is based on skb->len,
> and without trimming, it doesn't match the length the sender used when
> computing the checksum.
>
> With this change, OVS conntrack trims IPv4 and IPv6 packets prior to
> L3 processing.
>
> Signed-off-by: Ed Swierk <eswierk@skyportsystems.com>
> ---
> net/openvswitch/conntrack.c | 17 +++++++++++++++++
> 1 file changed, 17 insertions(+)
>
> diff --git a/net/openvswitch/conntrack.c b/net/openvswitch/conntrack.c
> index d558e882ca0c..3a7c9215c431 100644
> --- a/net/openvswitch/conntrack.c
> +++ b/net/openvswitch/conntrack.c
> @@ -1105,12 +1105,29 @@ int ovs_ct_execute(struct net *net, struct sk_buff *skb,
> const struct ovs_conntrack_info *info)
> {
> int nh_ofs;
> + unsigned int nh_len;
> int err;
>
> /* The conntrack module expects to be working at L3. */
> nh_ofs = skb_network_offset(skb);
> skb_pull_rcsum(skb, nh_ofs);
>
> + /* Trim to L3 length since nf_checksum() doesn't expect padding. */
Can you explore if nf_checksum can be changed to avoid the padding?
> + switch (skb->protocol) {
> + case htons(ETH_P_IP):
> + nh_len = ntohs(ip_hdr(skb)->tot_len);
> + break;
> + case htons(ETH_P_IPV6):
> + nh_len = ntohs(ipv6_hdr(skb)->payload_len)
> + + sizeof(struct ipv6hdr);
> + break;
> + default:
> + nh_len = skb->len;
> + }
> + err = pskb_trim_rcsum(skb, nh_len);
> + if (err)
> + return err;
> +
In case of error skb needs to be freed.
^ permalink raw reply
* Re: [PATCH net] vxlan: Restore initial MTU setting based on lower device
From: Matthias Schiffer @ 2017-12-14 0:53 UTC (permalink / raw)
To: Stefano Brivio
Cc: David S . Miller, netdev, Junhan Yan, Jiri Benc, Hangbin Liu
In-Reply-To: <20171214013148.3da52cc9@elisabeth>
[-- Attachment #1.1: Type: text/plain, Size: 3044 bytes --]
On 12/14/2017 01:31 AM, Stefano Brivio wrote:
> On Thu, 14 Dec 2017 01:25:40 +0100
> Matthias Schiffer <mschiffer@universe-factory.net> wrote:
>
>> On 12/14/2017 01:10 AM, Stefano Brivio wrote:
>>> On Thu, 14 Dec 2017 00:57:32 +0100
>>> Matthias Schiffer <mschiffer@universe-factory.net> wrote:
>>>
>>>> As you note, there is another occurrence of this calculation in
>>>> vxlan_config_apply():
>>>>
>>>>
>>>> [...]
>>>> if (lowerdev) {
>>>> [...]
>>>> max_mtu = lowerdev->mtu - (use_ipv6 ? VXLAN6_HEADROOM :
>>>> VXLAN_HEADROOM);
>>>> }
>>>>
>>>> if (dev->mtu > max_mtu)
>>>> dev->mtu = max_mtu;
>>>> [...]
>>>>
>>>>
>>>> Unless I'm overlooking something, this should already do the same thing and
>>>> your patch is redundant.
>>>
>>> The code above sets max_mtu, and only if dev->mtu exceeds that, the
>>> latter is then clamped.
>>>
>>> What my patch does is to actually set dev->mtu to that value, no matter
>>> what's the previous value set by ether_setup() (only on creation, and
>>> only if lowerdev is there), just like the previous behaviour used to be.
>>>
>>> Let's consider these two cases, on the existing code:
>>>
>>> 1. lowerdev->mtu is 1500:
>>> - ether_setup(), called by vxlan_setup(), sets dev->mtu to 1500
>>> - here max_mtu is 1450
>>> - we enter the second if clause above (dev->mtu > max_mtu)
>>> - at the end of vxlan_config_apply(), dev->mtu will be 1450
>>>
>>> which is consistent with the previous behaviour.
>>>
>>> 2. lowerdev->mtu is 9000:
>>> - ether_setup(), called by vxlan_setup(), sets dev->mtu to 1500
>>> - here max_mtu is 8950
>>> - we do not enter the second if clause above (dev->mtu < max_mtu)
>>> - at the end of vxlan_config_apply(), dev->mtu will still be 1500
>>>
>>> which is not consistent with the previous behaviour, where it used to
>>> be 8950 instead.
>>
>> Ah, thank you for the explanation, I was missing the context that this was
>> about higher rather than lower MTUs.
>>
>> Personally, I would prefer a change like the following, as it does not
>> introduce another duplication of the MTU calculation (not tested at all):
>>
>>> --- a/drivers/net/vxlan.c
>>> +++ b/drivers/net/vxlan.c
>>> @@ -3105,7 +3105,7 @@ static void vxlan_config_apply(struct net_device *dev,
>>> VXLAN_HEADROOM);
>>> }
>>>
>>> - if (dev->mtu > max_mtu)
>>> + if (dev->mtu > max_mtu || (!changelink && !conf->mtu))
>>> dev->mtu = max_mtu;
>
> You would also need to check that lowerdev is present, though.
>
> Otherwise, you're changing the behaviour again, that is, if lowerdev is
> not present, we want to keep 1500 and not set ETH_MAX_MTU (65535).
>
> Sure you can change the if condition to reflect that, but IMHO it
> becomes quite awkward.
>
Hmm, right. So here's a
Reviewed-by: Matthias Schiffer <mschiffer@universe-factory.net>
for the minimal change for -stable.
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply
* Re: [patch net-next v3 00/10] net: sched: allow qdiscs to share filter block instances
From: Jakub Kicinski @ 2017-12-14 0:46 UTC (permalink / raw)
To: Jiri Pirko, David Ahern
Cc: netdev, davem, jhs, xiyou.wangcong, mlxsw, andrew, vivien.didelot,
f.fainelli, michael.chan, ganeshgr, saeedm, matanb, leonro,
idosch, simon.horman, pieter.jansenvanvuuren, john.hurley,
alexander.h.duyck, ogerlitz, john.fastabend, daniel
In-Reply-To: <20171213184241.GL2031@nanopsycho>
On Wed, 13 Dec 2017 19:42:41 +0100, Jiri Pirko wrote:
> >>>> I plan to do it as a follow-up patch. But this is how things are done
> >>>> now and have to continue to work.
> >>>
> >>> Why is that? You are introducing the notion of a shared block with this
> >>> patch set. What is the legacy "how things are done now" you are
> >>> referring to?
> >>
> >> Well, the filter add/del should just work no matter if the block behind is
> >> shared or not.
> >
> >My argument is that modifying a shared block instance via a dev should
> >not be allowed. Those changes should only be allowed via the shared
> >block. So if a user puts adds a shared block to the device and then
> >attempts to add a filter via the device it should not be allowed.
>
> I don't see why. The handle is the qdisc here.
If you look at it from Linux perspective that makes sense. For people
coming from switching world the fact that we use qdiscs as a handle for
ACL blocks is an implementation detail.. is that the argument here?
^ permalink raw reply
* [PATCH net-next 4/4] samples/bpf: add erspan v2 sample code
From: William Tu @ 2017-12-14 0:38 UTC (permalink / raw)
To: netdev
In-Reply-To: <1513211938-8749-1-git-send-email-u9012063@gmail.com>
Extend the existing tests for ipv4 ipv6 erspan version 2.
Signed-off-by: William Tu <u9012063@gmail.com>
---
samples/bpf/tcbpf2_kern.c | 77 +++++++++++++++++++++++++++++++++++++-----
samples/bpf/test_tunnel_bpf.sh | 38 +++++++++++++++------
2 files changed, 96 insertions(+), 19 deletions(-)
diff --git a/samples/bpf/tcbpf2_kern.c b/samples/bpf/tcbpf2_kern.c
index 79ad061079dd..f6bbf8f50da3 100644
--- a/samples/bpf/tcbpf2_kern.c
+++ b/samples/bpf/tcbpf2_kern.c
@@ -35,12 +35,22 @@ struct geneve_opt {
u8 opt_data[8]; /* hard-coded to 8 byte */
};
+struct erspan_md2 {
+ __be32 timestamp;
+ __be16 sgt;
+ __be16 flags;
+};
+
struct vxlan_metadata {
u32 gbp;
};
struct erspan_metadata {
- __be32 index;
+ union {
+ __be32 index;
+ struct erspan_md2 md2;
+ } u;
+ int version;
};
SEC("gre_set_tunnel")
@@ -143,7 +153,18 @@ int _erspan_set_tunnel(struct __sk_buff *skb)
return TC_ACT_SHOT;
}
- md.index = htonl(123);
+ __builtin_memset(&md, 0, sizeof(md));
+#ifdef ERSPAN_V1
+ md.version = 1;
+ md.u.index = htonl(123);
+#else
+ u8 direction = 1;
+ u16 hwid = 7;
+
+ md.version = 2;
+ md.u.md2.flags = htons((direction << 3) | (hwid << 4));
+#endif
+
ret = bpf_skb_set_tunnel_opt(skb, &md, sizeof(md));
if (ret < 0) {
ERROR(ret);
@@ -156,7 +177,7 @@ int _erspan_set_tunnel(struct __sk_buff *skb)
SEC("erspan_get_tunnel")
int _erspan_get_tunnel(struct __sk_buff *skb)
{
- char fmt[] = "key %d remote ip 0x%x erspan index 0x%x\n";
+ char fmt[] = "key %d remote ip 0x%x erspan version %d\n";
struct bpf_tunnel_key key;
struct erspan_metadata md;
u32 index;
@@ -174,9 +195,22 @@ int _erspan_get_tunnel(struct __sk_buff *skb)
return TC_ACT_SHOT;
}
- index = bpf_ntohl(md.index);
bpf_trace_printk(fmt, sizeof(fmt),
- key.tunnel_id, key.remote_ipv4, index);
+ key.tunnel_id, key.remote_ipv4, md.version);
+
+#ifdef ERSPAN_V1
+ char fmt2[] = "\tindex %x\n";
+
+ index = bpf_ntohl(md.u.index);
+ bpf_trace_printk(fmt2, sizeof(fmt2), index);
+#else
+ char fmt2[] = "\tdirection %d hwid %x timestamp %u\n";
+
+ bpf_trace_printk(fmt2, sizeof(fmt2),
+ (ntohs(md.u.md2.flags) >> 3) & 0x1,
+ (ntohs(md.u.md2.flags) >> 4) & 0x3f,
+ bpf_ntohl(md.u.md2.timestamp));
+#endif
return TC_ACT_OK;
}
@@ -201,7 +235,19 @@ int _ip4ip6erspan_set_tunnel(struct __sk_buff *skb)
return TC_ACT_SHOT;
}
- md.index = htonl(123);
+ __builtin_memset(&md, 0, sizeof(md));
+
+#ifdef ERSPAN_V1
+ md.u.index = htonl(123);
+ md.version = 1;
+#else
+ u8 direction = 0;
+ u16 hwid = 17;
+
+ md.version = 2;
+ md.u.md2.flags = htons((direction << 3) | (hwid << 4));
+#endif
+
ret = bpf_skb_set_tunnel_opt(skb, &md, sizeof(md));
if (ret < 0) {
ERROR(ret);
@@ -214,7 +260,7 @@ int _ip4ip6erspan_set_tunnel(struct __sk_buff *skb)
SEC("ip4ip6erspan_get_tunnel")
int _ip4ip6erspan_get_tunnel(struct __sk_buff *skb)
{
- char fmt[] = "key %d remote ip6 ::%x erspan index 0x%x\n";
+ char fmt[] = "ip6erspan get key %d remote ip6 ::%x erspan version %d\n";
struct bpf_tunnel_key key;
struct erspan_metadata md;
u32 index;
@@ -232,9 +278,22 @@ int _ip4ip6erspan_get_tunnel(struct __sk_buff *skb)
return TC_ACT_SHOT;
}
- index = bpf_ntohl(md.index);
bpf_trace_printk(fmt, sizeof(fmt),
- key.tunnel_id, key.remote_ipv6[0], index);
+ key.tunnel_id, key.remote_ipv4, md.version);
+
+#ifdef ERSPAN_V1
+ char fmt2[] = "\tindex %x\n";
+
+ index = bpf_ntohl(md.u.index);
+ bpf_trace_printk(fmt2, sizeof(fmt2), index);
+#else
+ char fmt2[] = "\tdirection %d hwid %x timestamp %u\n";
+
+ bpf_trace_printk(fmt2, sizeof(fmt2),
+ (ntohs(md.u.md2.flags) >> 3) & 0x1,
+ (ntohs(md.u.md2.flags) >> 4) & 0x3f,
+ bpf_ntohl(md.u.md2.timestamp));
+#endif
return TC_ACT_OK;
}
diff --git a/samples/bpf/test_tunnel_bpf.sh b/samples/bpf/test_tunnel_bpf.sh
index f53efb62f699..ae7f7c38309b 100755
--- a/samples/bpf/test_tunnel_bpf.sh
+++ b/samples/bpf/test_tunnel_bpf.sh
@@ -59,8 +59,17 @@ function add_ip6gretap_tunnel {
function add_erspan_tunnel {
# in namespace
- ip netns exec at_ns0 \
- ip link add dev $DEV_NS type $TYPE seq key 2 local 172.16.1.100 remote 172.16.1.200 erspan 123
+ if [ "$1" == "v1" ]; then
+ ip netns exec at_ns0 \
+ ip link add dev $DEV_NS type $TYPE seq key 2 \
+ local 172.16.1.100 remote 172.16.1.200 \
+ erspan_ver 1 erspan 123
+ else
+ ip netns exec at_ns0 \
+ ip link add dev $DEV_NS type $TYPE seq key 2 \
+ local 172.16.1.100 remote 172.16.1.200 \
+ erspan_ver 2 erspan_dir 1 erspan_hwid 3
+ fi
ip netns exec at_ns0 ip link set dev $DEV_NS up
ip netns exec at_ns0 ip addr add dev $DEV_NS 10.1.1.100/24
@@ -79,10 +88,17 @@ function add_ip6erspan_tunnel {
ip link set dev veth1 up
# in namespace
- ip netns exec at_ns0 \
- ip link add dev $DEV_NS type $TYPE seq key 2 erspan 123 \
- local ::11 remote ::22
-
+ if [ "$1" == "v1" ]; then
+ ip netns exec at_ns0 \
+ ip link add dev $DEV_NS type $TYPE seq key 2 \
+ local ::11 remote ::22 \
+ erspan_ver 1 erspan 123
+ else
+ ip netns exec at_ns0 \
+ ip link add dev $DEV_NS type $TYPE seq key 2 \
+ local ::11 remote ::22 \
+ erspan_ver 2 erspan_dir 1 erspan_hwid 7
+ fi
ip netns exec at_ns0 ip addr add dev $DEV_NS 10.1.1.100/24
ip netns exec at_ns0 ip link set dev $DEV_NS up
@@ -199,7 +215,7 @@ function test_erspan {
DEV_NS=erspan00
DEV=erspan11
config_device
- add_erspan_tunnel
+ add_erspan_tunnel $1
attach_bpf $DEV erspan_set_tunnel erspan_get_tunnel
ping -c 1 10.1.1.100
ip netns exec at_ns0 ping -c 1 10.1.1.200
@@ -211,7 +227,7 @@ function test_ip6erspan {
DEV_NS=ip6erspan00
DEV=ip6erspan11
config_device
- add_ip6erspan_tunnel
+ add_ip6erspan_tunnel $1
attach_bpf $DEV ip4ip6erspan_set_tunnel ip4ip6erspan_get_tunnel
ping6 -c 3 ::11
ip netns exec at_ns0 ping -c 1 10.1.1.200
@@ -288,9 +304,11 @@ test_ip6gre
echo "Testing IP6GRETAP tunnel..."
test_ip6gretap
echo "Testing ERSPAN tunnel..."
-test_erspan
+test_erspan v1
+test_erspan v2
echo "Testing IP6ERSPAN tunnel..."
-test_ip6erspan
+test_ip6erspan v1
+test_ip6erspan v2
echo "Testing VXLAN tunnel..."
test_vxlan
echo "Testing GENEVE tunnel..."
--
2.7.4
^ permalink raw reply related
* [PATCH net-next 3/4] ip6_gre: add erspan v2 support
From: William Tu @ 2017-12-14 0:38 UTC (permalink / raw)
To: netdev
In-Reply-To: <1513211938-8749-1-git-send-email-u9012063@gmail.com>
Similar to support for ipv4 erspan, this patch adds
erspan v2 to ip6erspan tunnel.
Signed-off-by: William Tu <u9012063@gmail.com>
---
include/net/ip6_tunnel.h | 3 ++
net/ipv6/ip6_gre.c | 120 ++++++++++++++++++++++++++++++++++++++++-------
2 files changed, 107 insertions(+), 16 deletions(-)
diff --git a/include/net/ip6_tunnel.h b/include/net/ip6_tunnel.h
index 109a5a8877ef..236e40ba06bf 100644
--- a/include/net/ip6_tunnel.h
+++ b/include/net/ip6_tunnel.h
@@ -37,6 +37,9 @@ struct __ip6_tnl_parm {
__u32 fwmark;
__u32 index; /* ERSPAN type II index */
+ __u8 erspan_ver; /* ERSPAN version */
+ __u8 dir; /* direction */
+ __u16 hwid; /* hwid */
};
/* IPv6 tunnel */
diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c
index 1303d0c44c36..5c9c65f1d5c2 100644
--- a/net/ipv6/ip6_gre.c
+++ b/net/ipv6/ip6_gre.c
@@ -553,13 +553,28 @@ static int ip6erspan_rcv(struct sk_buff *skb, int gre_hdr_len,
return PACKET_REJECT;
memcpy(md, pkt_md, sizeof(*md));
+ md->version = ver;
info->key.tun_flags |= TUNNEL_ERSPAN_OPT;
info->options_len = sizeof(*md);
ip6_tnl_rcv(tunnel, skb, tpi, tun_dst, log_ecn_error);
} else {
- tunnel->parms.index = ntohl(pkt_md->u.index);
+ tunnel->parms.erspan_ver = ver;
+
+ if (ver == 1) {
+ tunnel->parms.index = ntohl(pkt_md->u.index);
+ } else {
+ u16 md2_flags;
+ u16 dir, hwid;
+
+ md2_flags = ntohs(pkt_md->u.md2.flags);
+ dir = (md2_flags & DIR_MASK) >> DIR_OFFSET;
+ hwid = (md2_flags & HWID_MASK) >> HWID_OFFSET;
+ tunnel->parms.dir = dir;
+ tunnel->parms.hwid = hwid;
+ }
+
ip6_tnl_rcv(tunnel, skb, tpi, NULL, log_ecn_error);
}
@@ -582,7 +597,8 @@ static int gre_rcv(struct sk_buff *skb)
if (iptunnel_pull_header(skb, hdr_len, tpi.proto, false))
goto drop;
- if (unlikely(tpi.proto == htons(ETH_P_ERSPAN))) {
+ if (unlikely(tpi.proto == htons(ETH_P_ERSPAN) ||
+ tpi.proto == htons(ETH_P_ERSPAN2))) {
if (ip6erspan_rcv(skb, hdr_len, &tpi) == PACKET_RCVD)
return 0;
goto drop;
@@ -927,9 +943,24 @@ static netdev_tx_t ip6erspan_tunnel_xmit(struct sk_buff *skb,
if (!md)
goto tx_err;
- erspan_build_header(skb, tunnel_id_to_key32(key->tun_id),
- ntohl(md->u.index), truncate, false);
-
+ if (md->version == 1) {
+ erspan_build_header(skb,
+ tunnel_id_to_key32(key->tun_id),
+ ntohl(md->u.index), truncate,
+ false);
+ } else if (md->version == 2) {
+ u16 md2_flags;
+ u16 dir, hwid;
+
+ md2_flags = ntohs(md->u.md2.flags);
+ dir = (md2_flags & DIR_MASK) >> DIR_OFFSET;
+ hwid = (md2_flags & HWID_MASK) >> HWID_OFFSET;
+
+ erspan_build_header_v2(skb,
+ tunnel_id_to_key32(key->tun_id),
+ dir, hwid, truncate,
+ false);
+ }
} else {
switch (skb->protocol) {
case htons(ETH_P_IP):
@@ -949,8 +980,15 @@ static netdev_tx_t ip6erspan_tunnel_xmit(struct sk_buff *skb,
break;
}
- erspan_build_header(skb, t->parms.o_key, t->parms.index,
- truncate, false);
+ if (t->parms.erspan_ver == 1)
+ erspan_build_header(skb, t->parms.o_key,
+ t->parms.index,
+ truncate, false);
+ else
+ erspan_build_header_v2(skb, t->parms.o_key,
+ t->parms.dir,
+ t->parms.hwid,
+ truncate, false);
fl6.daddr = t->parms.raddr;
}
@@ -1514,7 +1552,7 @@ static int ip6erspan_tap_validate(struct nlattr *tb[], struct nlattr *data[],
struct netlink_ext_ack *extack)
{
__be16 flags = 0;
- int ret;
+ int ret, ver = 0;
if (!data)
return 0;
@@ -1543,12 +1581,35 @@ static int ip6erspan_tap_validate(struct nlattr *tb[], struct nlattr *data[],
(ntohl(nla_get_be32(data[IFLA_GRE_OKEY])) & ~ID_MASK))
return -EINVAL;
- if (data[IFLA_GRE_ERSPAN_INDEX]) {
- u32 index = nla_get_u32(data[IFLA_GRE_ERSPAN_INDEX]);
-
- if (index & ~INDEX_MASK)
+ if (data[IFLA_GRE_ERSPAN_VER]) {
+ ver = nla_get_u8(data[IFLA_GRE_ERSPAN_VER]);
+ if (ver != 1 && ver != 2)
return -EINVAL;
}
+
+ if (ver == 1) {
+ if (data[IFLA_GRE_ERSPAN_INDEX]) {
+ u32 index = nla_get_u32(data[IFLA_GRE_ERSPAN_INDEX]);
+
+ if (index & ~INDEX_MASK)
+ return -EINVAL;
+ }
+ } else if (ver == 2) {
+ if (data[IFLA_GRE_ERSPAN_DIR]) {
+ u16 dir = nla_get_u8(data[IFLA_GRE_ERSPAN_DIR]);
+
+ if (dir & ~(DIR_MASK >> DIR_OFFSET))
+ return -EINVAL;
+ }
+
+ if (data[IFLA_GRE_ERSPAN_HWID]) {
+ u16 hwid = nla_get_u16(data[IFLA_GRE_ERSPAN_HWID]);
+
+ if (hwid & ~(HWID_MASK >> HWID_OFFSET))
+ return -EINVAL;
+ }
+ }
+
return 0;
}
@@ -1598,11 +1659,21 @@ static void ip6gre_netlink_parms(struct nlattr *data[],
if (data[IFLA_GRE_FWMARK])
parms->fwmark = nla_get_u32(data[IFLA_GRE_FWMARK]);
- if (data[IFLA_GRE_ERSPAN_INDEX])
- parms->index = nla_get_u32(data[IFLA_GRE_ERSPAN_INDEX]);
-
if (data[IFLA_GRE_COLLECT_METADATA])
parms->collect_md = true;
+
+ if (data[IFLA_GRE_ERSPAN_VER])
+ parms->erspan_ver = nla_get_u8(data[IFLA_GRE_ERSPAN_VER]);
+
+ if (parms->erspan_ver == 1) {
+ if (data[IFLA_GRE_ERSPAN_INDEX])
+ parms->index = nla_get_u32(data[IFLA_GRE_ERSPAN_INDEX]);
+ } else if (parms->erspan_ver == 2) {
+ if (data[IFLA_GRE_ERSPAN_DIR])
+ parms->dir = nla_get_u8(data[IFLA_GRE_ERSPAN_DIR]);
+ if (data[IFLA_GRE_ERSPAN_HWID])
+ parms->hwid = nla_get_u16(data[IFLA_GRE_ERSPAN_HWID]);
+ }
}
static int ip6gre_tap_init(struct net_device *dev)
@@ -1664,7 +1735,7 @@ static int ip6erspan_tap_init(struct net_device *dev)
tunnel->tun_hlen = 8;
tunnel->hlen = tunnel->tun_hlen + tunnel->encap_hlen +
- sizeof(struct erspan_base_hdr) + ERSPAN_V1_MDSIZE;
+ erspan_hdr_len(tunnel->parms.erspan_ver);
t_hlen = tunnel->hlen + sizeof(struct ipv6hdr);
dev->hard_header_len = LL_MAX_HEADER + t_hlen;
@@ -1932,6 +2003,19 @@ static int ip6gre_fill_info(struct sk_buff *skb, const struct net_device *dev)
goto nla_put_failure;
}
+ if (nla_put_u8(skb, IFLA_GRE_ERSPAN_VER, p->erspan_ver))
+ goto nla_put_failure;
+
+ if (p->erspan_ver == 1) {
+ if (nla_put_u32(skb, IFLA_GRE_ERSPAN_INDEX, p->index))
+ goto nla_put_failure;
+ } else if (p->erspan_ver == 2) {
+ if (nla_put_u8(skb, IFLA_GRE_ERSPAN_DIR, p->dir))
+ goto nla_put_failure;
+ if (nla_put_u16(skb, IFLA_GRE_ERSPAN_HWID, p->hwid))
+ goto nla_put_failure;
+ }
+
return 0;
nla_put_failure:
@@ -1957,6 +2041,9 @@ static const struct nla_policy ip6gre_policy[IFLA_GRE_MAX + 1] = {
[IFLA_GRE_COLLECT_METADATA] = { .type = NLA_FLAG },
[IFLA_GRE_FWMARK] = { .type = NLA_U32 },
[IFLA_GRE_ERSPAN_INDEX] = { .type = NLA_U32 },
+ [IFLA_GRE_ERSPAN_VER] = { .type = NLA_U8 },
+ [IFLA_GRE_ERSPAN_DIR] = { .type = NLA_U8 },
+ [IFLA_GRE_ERSPAN_HWID] = { .type = NLA_U16 },
};
static void ip6erspan_tap_setup(struct net_device *dev)
@@ -2078,4 +2165,5 @@ MODULE_AUTHOR("D. Kozlov (xeb@mail.ru)");
MODULE_DESCRIPTION("GRE over IPv6 tunneling device");
MODULE_ALIAS_RTNL_LINK("ip6gre");
MODULE_ALIAS_RTNL_LINK("ip6gretap");
+MODULE_ALIAS_RTNL_LINK("ip6erspan");
MODULE_ALIAS_NETDEV("ip6gre0");
--
2.7.4
^ permalink raw reply related
* [PATCH net-next 2/4] net: erspan: introduce erspan v2 for ip_gre
From: William Tu @ 2017-12-14 0:38 UTC (permalink / raw)
To: netdev
In-Reply-To: <1513211938-8749-1-git-send-email-u9012063@gmail.com>
The patch adds support for erspan version 2. Not all features are
supported in this patch. The SGT (security group tag), GRA (timestamp
granularity), FT (frame type) are set to fixed value. Only hardware
ID and direction are configurable. Optional subheader is also not
supported.
Signed-off-by: William Tu <u9012063@gmail.com>
---
include/net/erspan.h | 120 ++++++++++++++++++++++++++++++++++++++++-
include/net/ip_tunnels.h | 5 +-
include/uapi/linux/if_ether.h | 1 +
include/uapi/linux/if_tunnel.h | 3 ++
net/ipv4/ip_gre.c | 105 ++++++++++++++++++++++++++++++------
5 files changed, 216 insertions(+), 18 deletions(-)
diff --git a/include/net/erspan.h b/include/net/erspan.h
index 70c40c7c75b2..acdf6843095d 100644
--- a/include/net/erspan.h
+++ b/include/net/erspan.h
@@ -24,11 +24,29 @@
* | Reserved | Index |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
+ *
+ * ERSPAN Version 2 (Type III) header (12 octets [42:49])
+ * 0 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Ver | VLAN | COS |BSO|T| Session ID |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Timestamp |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | SGT |P| FT | Hw ID |D|Gra|O|
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ * Platform Specific SubHeader (8 octets, optional)
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Platf ID | Platform Specific Info |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Platform Specific Info |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
* GRE proto ERSPAN type II = 0x88BE, type III = 0x22EB
*/
#define ERSPAN_VERSION 0x1 /* ERSPAN type II */
-
#define VER_MASK 0xf000
#define VLAN_MASK 0x0fff
#define COS_MASK 0xe000
@@ -37,6 +55,28 @@
#define ID_MASK 0x03ff
#define INDEX_MASK 0xfffff
+#define ERSPAN_VERSION2 0x2 /* ERSPAN type III*/
+#define BSO_MASK EN_MASK
+#define SGT_MASK 0xffff0000
+#define P_MASK 0x8000
+#define FT_MASK 0x7c00
+#define HWID_MASK 0x03f0
+#define DIR_MASK 0x0008
+#define GRA_MASK 0x0006
+#define O_MASK 0x0001
+
+/* ERSPAN version 2 metadata header */
+struct erspan_md2 {
+ __be32 timestamp;
+ __be16 sgt; /* security group tag */
+ __be16 flags;
+#define P_OFFSET 15
+#define FT_OFFSET 10
+#define HWID_OFFSET 4
+#define DIR_OFFSET 3
+#define GRA_OFFSET 1
+};
+
enum erspan_encap_type {
ERSPAN_ENCAP_NOVLAN = 0x0, /* originally without VLAN tag */
ERSPAN_ENCAP_ISL = 0x1, /* originally ISL encapsulated */
@@ -48,8 +88,10 @@ enum erspan_encap_type {
#define ERSPAN_V2_MDSIZE 8
struct erspan_metadata {
union {
- __be32 index; /* Version 1 (type II)*/
+ __be32 index; /* Version 1 (type II)*/
+ struct erspan_md2 md2; /* Version 2 (type III) */
} u;
+ int version;
};
struct erspan_base_hdr {
@@ -58,6 +100,7 @@ struct erspan_base_hdr {
__be16 session_id;
#define COS_OFFSET 13
#define EN_OFFSET 11
+#define BSO_OFFSET EN_OFFSET
#define T_OFFSET 10
};
@@ -123,4 +166,77 @@ static inline void erspan_build_header(struct sk_buff *skb,
ersmd->u.index = htonl(index & INDEX_MASK);
}
+/* ERSPAN GRA: timestamp granularity
+ * 00b --> granularity = 100 microseconds
+ * 01b --> granularity = 100 nanoseconds
+ * 10b --> granularity = IEEE 1588
+ * Here we only support 100 microseconds.
+ */
+static inline __be32 erspan_get_timestamp(void)
+{
+ u64 h_usecs;
+ ktime_t kt;
+
+ kt = ktime_get_real();
+ h_usecs = ktime_divns(kt, 100 * NSEC_PER_USEC);
+
+ /* ERSPAN base header only has 32-bit,
+ * so it wraps around 4 days.
+ */
+ return htonl((u32)h_usecs);
+}
+
+static inline void erspan_build_header_v2(struct sk_buff *skb,
+ __be32 id, u8 direction, u16 hwid,
+ bool truncate, bool is_ipv4)
+{
+ struct ethhdr *eth = eth_hdr(skb);
+ struct erspan_base_hdr *ershdr;
+ struct erspan_metadata *md;
+ struct qtag_prefix {
+ __be16 eth_type;
+ __be16 tci;
+ } *qp;
+ u16 vlan_tci = 0;
+ u16 session_id;
+ u8 gra = 0; /* 100 usec */
+ u8 bso = 0; /* Bad/Short/Oversized */
+ u8 sgt = 0;
+ u8 tos;
+
+ tos = is_ipv4 ? ip_hdr(skb)->tos :
+ (ipv6_hdr(skb)->priority << 4) +
+ (ipv6_hdr(skb)->flow_lbl[0] >> 4);
+
+ /* Unlike v1, v2 does not have En field,
+ * so only extract vlan tci field.
+ */
+ if (eth->h_proto == htons(ETH_P_8021Q)) {
+ qp = (struct qtag_prefix *)(skb->data + 2 * ETH_ALEN);
+ vlan_tci = ntohs(qp->tci);
+ }
+
+ skb_push(skb, sizeof(*ershdr) + ERSPAN_V2_MDSIZE);
+ ershdr = (struct erspan_base_hdr *)skb->data;
+ memset(ershdr, 0, sizeof(*ershdr) + ERSPAN_V2_MDSIZE);
+
+ /* Build base header */
+ ershdr->ver_vlan = htons((vlan_tci & VLAN_MASK) |
+ (ERSPAN_VERSION2 << VER_OFFSET));
+ session_id = (u16)(ntohl(id) & ID_MASK) |
+ ((tos_to_cos(tos) << COS_OFFSET) & COS_MASK) |
+ (bso << BSO_OFFSET & BSO_MASK) |
+ ((truncate << T_OFFSET) & T_MASK);
+ ershdr->session_id = htons(session_id);
+
+ /* Build metadata */
+ md = (struct erspan_metadata *)(ershdr + 1);
+ md->u.md2.timestamp = erspan_get_timestamp();
+ md->u.md2.sgt = htons(sgt);
+ md->u.md2.flags = htons(((1 << P_OFFSET) & P_MASK) |
+ ((hwid << HWID_OFFSET) & HWID_MASK) |
+ ((direction << DIR_OFFSET) & DIR_MASK) |
+ ((gra << GRA_OFFSET) & GRA_MASK));
+}
+
#endif
diff --git a/include/net/ip_tunnels.h b/include/net/ip_tunnels.h
index 24628f6b09bf..1f16773cfd76 100644
--- a/include/net/ip_tunnels.h
+++ b/include/net/ip_tunnels.h
@@ -116,8 +116,11 @@ struct ip_tunnel {
u32 o_seqno; /* The last output seqno */
int tun_hlen; /* Precalculated header length */
- /* This field used only by ERSPAN */
+ /* These four fields used only by ERSPAN */
u32 index; /* ERSPAN type II index */
+ u8 erspan_ver; /* ERSPAN version */
+ u8 dir; /* ERSPAN direction */
+ u16 hwid; /* ERSPAN hardware ID */
struct dst_cache dst_cache;
diff --git a/include/uapi/linux/if_ether.h b/include/uapi/linux/if_ether.h
index 3ee3bf7c8526..87b7529fcdfe 100644
--- a/include/uapi/linux/if_ether.h
+++ b/include/uapi/linux/if_ether.h
@@ -47,6 +47,7 @@
#define ETH_P_PUP 0x0200 /* Xerox PUP packet */
#define ETH_P_PUPAT 0x0201 /* Xerox PUP Addr Trans packet */
#define ETH_P_TSN 0x22F0 /* TSN (IEEE 1722) packet */
+#define ETH_P_ERSPAN2 0x22EB /* ERSPAN version 2 (type III) */
#define ETH_P_IP 0x0800 /* Internet Protocol packet */
#define ETH_P_X25 0x0805 /* CCITT X.25 */
#define ETH_P_ARP 0x0806 /* Address Resolution packet */
diff --git a/include/uapi/linux/if_tunnel.h b/include/uapi/linux/if_tunnel.h
index e68dadbd6d45..1b3d148c4560 100644
--- a/include/uapi/linux/if_tunnel.h
+++ b/include/uapi/linux/if_tunnel.h
@@ -137,6 +137,9 @@ enum {
IFLA_GRE_IGNORE_DF,
IFLA_GRE_FWMARK,
IFLA_GRE_ERSPAN_INDEX,
+ IFLA_GRE_ERSPAN_VER,
+ IFLA_GRE_ERSPAN_DIR,
+ IFLA_GRE_ERSPAN_HWID,
__IFLA_GRE_MAX,
};
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
index 3e37402147f3..004800b923c6 100644
--- a/net/ipv4/ip_gre.c
+++ b/net/ipv4/ip_gre.c
@@ -315,11 +315,26 @@ static int erspan_rcv(struct sk_buff *skb, struct tnl_ptk_info *tpi,
return PACKET_REJECT;
memcpy(md, pkt_md, sizeof(*md));
+ md->version = ver;
+
info = &tun_dst->u.tun_info;
info->key.tun_flags |= TUNNEL_ERSPAN_OPT;
info->options_len = sizeof(*md);
} else {
- tunnel->index = ntohl(pkt_md->u.index);
+ tunnel->erspan_ver = ver;
+ if (ver == 1) {
+ tunnel->index = ntohl(pkt_md->u.index);
+ } else {
+ u16 md2_flags;
+ u16 dir, hwid;
+
+ md2_flags = ntohs(pkt_md->u.md2.flags);
+ dir = (md2_flags & DIR_MASK) >> DIR_OFFSET;
+ hwid = (md2_flags & HWID_MASK) >> HWID_OFFSET;
+ tunnel->dir = dir;
+ tunnel->hwid = hwid;
+ }
+
}
skb_reset_mac_header(skb);
@@ -413,7 +428,8 @@ static int gre_rcv(struct sk_buff *skb)
if (hdr_len < 0)
goto drop;
- if (unlikely(tpi.proto == htons(ETH_P_ERSPAN))) {
+ if (unlikely(tpi.proto == htons(ETH_P_ERSPAN) ||
+ tpi.proto == htons(ETH_P_ERSPAN2))) {
if (erspan_rcv(skb, &tpi, hdr_len) == PACKET_RCVD)
return 0;
}
@@ -568,6 +584,7 @@ static void erspan_fb_xmit(struct sk_buff *skb, struct net_device *dev,
bool truncate = false;
struct flowi4 fl;
int tunnel_hlen;
+ int version;
__be16 df;
tun_info = skb_tunnel_info(skb);
@@ -576,9 +593,13 @@ static void erspan_fb_xmit(struct sk_buff *skb, struct net_device *dev,
goto err_free_skb;
key = &tun_info->key;
+ md = ip_tunnel_info_opts(tun_info);
+ if (!md)
+ goto err_free_rt;
/* ERSPAN has fixed 8 byte GRE header */
- tunnel_hlen = 8 + sizeof(struct erspan_base_hdr) + ERSPAN_V1_MDSIZE;
+ version = md->version;
+ tunnel_hlen = 8 + erspan_hdr_len(version);
rt = prepare_fb_xmit(skb, dev, &fl, tunnel_hlen);
if (!rt)
@@ -592,12 +613,23 @@ static void erspan_fb_xmit(struct sk_buff *skb, struct net_device *dev,
truncate = true;
}
- md = ip_tunnel_info_opts(tun_info);
- if (!md)
- goto err_free_rt;
+ if (version == 1) {
+ erspan_build_header(skb, tunnel_id_to_key32(key->tun_id),
+ ntohl(md->u.index), truncate, true);
+ } else if (version == 2) {
+ u16 md2_flags;
+ u8 direction;
+ u16 hwid;
- erspan_build_header(skb, tunnel_id_to_key32(key->tun_id),
- ntohl(md->u.index), truncate, true);
+ md2_flags = ntohs(md->u.md2.flags);
+ direction = (md2_flags & DIR_MASK) >> DIR_OFFSET;
+ hwid = (md2_flags & HWID_MASK) >> HWID_OFFSET;
+
+ erspan_build_header_v2(skb, tunnel_id_to_key32(key->tun_id),
+ direction, hwid, truncate, true);
+ } else {
+ goto err_free_rt;
+ }
gre_build_header(skb, 8, TUNNEL_SEQ,
htons(ETH_P_ERSPAN), 0, htonl(tunnel->o_seqno++));
@@ -699,8 +731,14 @@ static netdev_tx_t erspan_xmit(struct sk_buff *skb,
}
/* Push ERSPAN header */
- erspan_build_header(skb, tunnel->parms.o_key, tunnel->index,
- truncate, true);
+ if (tunnel->erspan_ver == 1)
+ erspan_build_header(skb, tunnel->parms.o_key, tunnel->index,
+ truncate, true);
+ else
+ erspan_build_header_v2(skb, tunnel->parms.o_key,
+ tunnel->dir, tunnel->hwid,
+ truncate, true);
+
tunnel->parms.o_flags &= ~TUNNEL_KEY;
__gre_xmit(skb, dev, &tunnel->parms.iph, htons(ETH_P_ERSPAN));
return NETDEV_TX_OK;
@@ -1172,13 +1210,32 @@ static int ipgre_netlink_parms(struct net_device *dev,
if (data[IFLA_GRE_FWMARK])
*fwmark = nla_get_u32(data[IFLA_GRE_FWMARK]);
- if (data[IFLA_GRE_ERSPAN_INDEX]) {
- t->index = nla_get_u32(data[IFLA_GRE_ERSPAN_INDEX]);
+ if (data[IFLA_GRE_ERSPAN_VER]) {
+ t->erspan_ver = nla_get_u8(data[IFLA_GRE_ERSPAN_VER]);
- if (t->index & ~INDEX_MASK)
+ if (t->erspan_ver != 1 && t->erspan_ver != 2)
return -EINVAL;
}
+ if (t->erspan_ver == 1) {
+ if (data[IFLA_GRE_ERSPAN_INDEX]) {
+ t->index = nla_get_u32(data[IFLA_GRE_ERSPAN_INDEX]);
+ if (t->index & ~INDEX_MASK)
+ return -EINVAL;
+ }
+ } else if (t->erspan_ver == 2) {
+ if (data[IFLA_GRE_ERSPAN_DIR]) {
+ t->dir = nla_get_u8(data[IFLA_GRE_ERSPAN_DIR]);
+ if (t->dir & ~(DIR_MASK >> DIR_OFFSET))
+ return -EINVAL;
+ }
+ if (data[IFLA_GRE_ERSPAN_HWID]) {
+ t->hwid = nla_get_u16(data[IFLA_GRE_ERSPAN_HWID]);
+ if (t->hwid & ~(HWID_MASK >> HWID_OFFSET))
+ return -EINVAL;
+ }
+ }
+
return 0;
}
@@ -1245,7 +1302,7 @@ static int erspan_tunnel_init(struct net_device *dev)
tunnel->tun_hlen = 8;
tunnel->parms.iph.protocol = IPPROTO_GRE;
tunnel->hlen = tunnel->tun_hlen + tunnel->encap_hlen +
- sizeof(struct erspan_base_hdr) + ERSPAN_V1_MDSIZE;
+ erspan_hdr_len(tunnel->erspan_ver);
t_hlen = tunnel->hlen + sizeof(struct iphdr);
dev->needed_headroom = LL_MAX_HEADER + t_hlen + 4;
@@ -1375,6 +1432,12 @@ static size_t ipgre_get_size(const struct net_device *dev)
nla_total_size(4) +
/* IFLA_GRE_ERSPAN_INDEX */
nla_total_size(4) +
+ /* IFLA_GRE_ERSPAN_VER */
+ nla_total_size(1) +
+ /* IFLA_GRE_ERSPAN_DIR */
+ nla_total_size(1) +
+ /* IFLA_GRE_ERSPAN_HWID */
+ nla_total_size(2) +
0;
}
@@ -1417,9 +1480,18 @@ static int ipgre_fill_info(struct sk_buff *skb, const struct net_device *dev)
goto nla_put_failure;
}
- if (t->index)
+ if (nla_put_u8(skb, IFLA_GRE_ERSPAN_VER, t->erspan_ver))
+ goto nla_put_failure;
+
+ if (t->erspan_ver == 1) {
if (nla_put_u32(skb, IFLA_GRE_ERSPAN_INDEX, t->index))
goto nla_put_failure;
+ } else if (t->erspan_ver == 2) {
+ if (nla_put_u8(skb, IFLA_GRE_ERSPAN_DIR, t->dir))
+ goto nla_put_failure;
+ if (nla_put_u16(skb, IFLA_GRE_ERSPAN_HWID, t->hwid))
+ goto nla_put_failure;
+ }
return 0;
@@ -1455,6 +1527,9 @@ static const struct nla_policy ipgre_policy[IFLA_GRE_MAX + 1] = {
[IFLA_GRE_IGNORE_DF] = { .type = NLA_U8 },
[IFLA_GRE_FWMARK] = { .type = NLA_U32 },
[IFLA_GRE_ERSPAN_INDEX] = { .type = NLA_U32 },
+ [IFLA_GRE_ERSPAN_VER] = { .type = NLA_U8 },
+ [IFLA_GRE_ERSPAN_DIR] = { .type = NLA_U8 },
+ [IFLA_GRE_ERSPAN_HWID] = { .type = NLA_U16 },
};
static struct rtnl_link_ops ipgre_link_ops __read_mostly = {
--
2.7.4
^ permalink raw reply related
* [PATCH net-next 1/4] net: erspan: refactor existing erspan code
From: William Tu @ 2017-12-14 0:38 UTC (permalink / raw)
To: netdev
In-Reply-To: <1513211938-8749-1-git-send-email-u9012063@gmail.com>
The patch refactors the existing erspan implementation in order
to support erspan version 2, which has additional metadata. So, in
stead of having one 'struct erspanhdr' holding erspan version 1,
breaks it into 'struct erspan_base_hdr' and 'struct erspan_metadata'.
Signed-off-by: William Tu <u9012063@gmail.com>
---
include/net/erspan.h | 34 ++++++++++++++++++++++++----------
net/ipv4/ip_gre.c | 27 +++++++++++++++++----------
net/ipv6/ip6_gre.c | 25 ++++++++++++++++---------
net/openvswitch/flow_netlink.c | 8 ++++----
4 files changed, 61 insertions(+), 33 deletions(-)
diff --git a/include/net/erspan.h b/include/net/erspan.h
index 6e758d08c9ee..70c40c7c75b2 100644
--- a/include/net/erspan.h
+++ b/include/net/erspan.h
@@ -15,7 +15,7 @@
* s, Recur, Flags, Version fields only S (bit 03) is set to 1. The
* other fields are set to zero, so only a sequence number follows.
*
- * ERSPAN Type II header (8 octets [42:49])
+ * ERSPAN Version 1 (Type II) header (8 octets [42:49])
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
@@ -27,7 +27,7 @@
* GRE proto ERSPAN type II = 0x88BE, type III = 0x22EB
*/
-#define ERSPAN_VERSION 0x1
+#define ERSPAN_VERSION 0x1 /* ERSPAN type II */
#define VER_MASK 0xf000
#define VLAN_MASK 0x0fff
@@ -44,20 +44,29 @@ enum erspan_encap_type {
ERSPAN_ENCAP_INFRAME = 0x3, /* VLAN tag perserved in frame */
};
+#define ERSPAN_V1_MDSIZE 4
+#define ERSPAN_V2_MDSIZE 8
struct erspan_metadata {
- __be32 index; /* type II */
+ union {
+ __be32 index; /* Version 1 (type II)*/
+ } u;
};
-struct erspanhdr {
+struct erspan_base_hdr {
__be16 ver_vlan;
#define VER_OFFSET 12
__be16 session_id;
#define COS_OFFSET 13
#define EN_OFFSET 11
#define T_OFFSET 10
- struct erspan_metadata md;
};
+static inline int erspan_hdr_len(int version)
+{
+ return sizeof(struct erspan_base_hdr) +
+ (version == 1 ? ERSPAN_V1_MDSIZE : ERSPAN_V2_MDSIZE);
+}
+
static inline u8 tos_to_cos(u8 tos)
{
u8 dscp, cos;
@@ -73,7 +82,8 @@ static inline void erspan_build_header(struct sk_buff *skb,
{
struct ethhdr *eth = eth_hdr(skb);
enum erspan_encap_type enc_type;
- struct erspanhdr *ershdr;
+ struct erspan_base_hdr *ershdr;
+ struct erspan_metadata *ersmd;
struct qtag_prefix {
__be16 eth_type;
__be16 tci;
@@ -96,17 +106,21 @@ static inline void erspan_build_header(struct sk_buff *skb,
enc_type = ERSPAN_ENCAP_INFRAME;
}
- skb_push(skb, sizeof(*ershdr));
- ershdr = (struct erspanhdr *)skb->data;
- memset(ershdr, 0, sizeof(*ershdr));
+ skb_push(skb, sizeof(*ershdr) + ERSPAN_V1_MDSIZE);
+ ershdr = (struct erspan_base_hdr *)skb->data;
+ memset(ershdr, 0, sizeof(*ershdr) + ERSPAN_V1_MDSIZE);
+ /* Build base header */
ershdr->ver_vlan = htons((vlan_tci & VLAN_MASK) |
(ERSPAN_VERSION << VER_OFFSET));
ershdr->session_id = htons((u16)(ntohl(id) & ID_MASK) |
((tos_to_cos(tos) << COS_OFFSET) & COS_MASK) |
(enc_type << EN_OFFSET & EN_MASK) |
((truncate << T_OFFSET) & T_MASK));
- ershdr->md.index = htonl(index & INDEX_MASK);
+
+ /* Build metadata */
+ ersmd = (struct erspan_metadata *)(ershdr + 1);
+ ersmd->u.index = htonl(index & INDEX_MASK);
}
#endif
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
index d828821d88d7..3e37402147f3 100644
--- a/net/ipv4/ip_gre.c
+++ b/net/ipv4/ip_gre.c
@@ -256,34 +256,41 @@ static int erspan_rcv(struct sk_buff *skb, struct tnl_ptk_info *tpi,
{
struct net *net = dev_net(skb->dev);
struct metadata_dst *tun_dst = NULL;
+ struct erspan_base_hdr *ershdr;
+ struct erspan_metadata *pkt_md;
struct ip_tunnel_net *itn;
struct ip_tunnel *tunnel;
- struct erspanhdr *ershdr;
const struct iphdr *iph;
- __be32 index;
+ int ver;
int len;
itn = net_generic(net, erspan_net_id);
len = gre_hdr_len + sizeof(*ershdr);
+ /* Check based hdr len */
if (unlikely(!pskb_may_pull(skb, len)))
return -ENOMEM;
iph = ip_hdr(skb);
- ershdr = (struct erspanhdr *)(skb->data + gre_hdr_len);
+ ershdr = (struct erspan_base_hdr *)(skb->data + gre_hdr_len);
+ ver = (ntohs(ershdr->ver_vlan) & VER_MASK) >> VER_OFFSET;
/* The original GRE header does not have key field,
* Use ERSPAN 10-bit session ID as key.
*/
tpi->key = cpu_to_be32(ntohs(ershdr->session_id) & ID_MASK);
- index = ershdr->md.index;
+ pkt_md = (struct erspan_metadata *)(ershdr + 1);
tunnel = ip_tunnel_lookup(itn, skb->dev->ifindex,
tpi->flags | TUNNEL_KEY,
iph->saddr, iph->daddr, tpi->key);
if (tunnel) {
+ len = gre_hdr_len + erspan_hdr_len(ver);
+ if (unlikely(!pskb_may_pull(skb, len)))
+ return -ENOMEM;
+
if (__iptunnel_pull_header(skb,
- gre_hdr_len + sizeof(*ershdr),
+ len,
htons(ETH_P_TEB),
false, false) < 0)
goto drop;
@@ -307,12 +314,12 @@ static int erspan_rcv(struct sk_buff *skb, struct tnl_ptk_info *tpi,
if (!md)
return PACKET_REJECT;
- md->index = index;
+ memcpy(md, pkt_md, sizeof(*md));
info = &tun_dst->u.tun_info;
info->key.tun_flags |= TUNNEL_ERSPAN_OPT;
info->options_len = sizeof(*md);
} else {
- tunnel->index = ntohl(index);
+ tunnel->index = ntohl(pkt_md->u.index);
}
skb_reset_mac_header(skb);
@@ -571,7 +578,7 @@ static void erspan_fb_xmit(struct sk_buff *skb, struct net_device *dev,
key = &tun_info->key;
/* ERSPAN has fixed 8 byte GRE header */
- tunnel_hlen = 8 + sizeof(struct erspanhdr);
+ tunnel_hlen = 8 + sizeof(struct erspan_base_hdr) + ERSPAN_V1_MDSIZE;
rt = prepare_fb_xmit(skb, dev, &fl, tunnel_hlen);
if (!rt)
@@ -590,7 +597,7 @@ static void erspan_fb_xmit(struct sk_buff *skb, struct net_device *dev,
goto err_free_rt;
erspan_build_header(skb, tunnel_id_to_key32(key->tun_id),
- ntohl(md->index), truncate, true);
+ ntohl(md->u.index), truncate, true);
gre_build_header(skb, 8, TUNNEL_SEQ,
htons(ETH_P_ERSPAN), 0, htonl(tunnel->o_seqno++));
@@ -1238,7 +1245,7 @@ static int erspan_tunnel_init(struct net_device *dev)
tunnel->tun_hlen = 8;
tunnel->parms.iph.protocol = IPPROTO_GRE;
tunnel->hlen = tunnel->tun_hlen + tunnel->encap_hlen +
- sizeof(struct erspanhdr);
+ sizeof(struct erspan_base_hdr) + ERSPAN_V1_MDSIZE;
t_hlen = tunnel->hlen + sizeof(struct iphdr);
dev->needed_headroom = LL_MAX_HEADER + t_hlen + 4;
diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c
index 4562579797d1..1303d0c44c36 100644
--- a/net/ipv6/ip6_gre.c
+++ b/net/ipv6/ip6_gre.c
@@ -501,25 +501,32 @@ static int ip6gre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi)
static int ip6erspan_rcv(struct sk_buff *skb, int gre_hdr_len,
struct tnl_ptk_info *tpi)
{
+ struct erspan_base_hdr *ershdr;
+ struct erspan_metadata *pkt_md;
const struct ipv6hdr *ipv6h;
- struct erspanhdr *ershdr;
struct ip6_tnl *tunnel;
- __be32 index;
+ u8 ver;
ipv6h = ipv6_hdr(skb);
- ershdr = (struct erspanhdr *)skb->data;
+ ershdr = (struct erspan_base_hdr *)skb->data;
if (unlikely(!pskb_may_pull(skb, sizeof(*ershdr))))
return PACKET_REJECT;
+ ver = (ntohs(ershdr->ver_vlan) & VER_MASK) >> VER_OFFSET;
tpi->key = cpu_to_be32(ntohs(ershdr->session_id) & ID_MASK);
- index = ershdr->md.index;
+ pkt_md = (struct erspan_metadata *)(ershdr + 1);
tunnel = ip6gre_tunnel_lookup(skb->dev,
&ipv6h->saddr, &ipv6h->daddr, tpi->key,
tpi->proto);
if (tunnel) {
- if (__iptunnel_pull_header(skb, sizeof(*ershdr),
+ int len = erspan_hdr_len(ver);
+
+ if (unlikely(!pskb_may_pull(skb, len)))
+ return -ENOMEM;
+
+ if (__iptunnel_pull_header(skb, len,
htons(ETH_P_TEB),
false, false) < 0)
return PACKET_REJECT;
@@ -545,14 +552,14 @@ static int ip6erspan_rcv(struct sk_buff *skb, int gre_hdr_len,
if (!md)
return PACKET_REJECT;
- md->index = index;
+ memcpy(md, pkt_md, sizeof(*md));
info->key.tun_flags |= TUNNEL_ERSPAN_OPT;
info->options_len = sizeof(*md);
ip6_tnl_rcv(tunnel, skb, tpi, tun_dst, log_ecn_error);
} else {
- tunnel->parms.index = ntohl(index);
+ tunnel->parms.index = ntohl(pkt_md->u.index);
ip6_tnl_rcv(tunnel, skb, tpi, NULL, log_ecn_error);
}
@@ -921,7 +928,7 @@ static netdev_tx_t ip6erspan_tunnel_xmit(struct sk_buff *skb,
goto tx_err;
erspan_build_header(skb, tunnel_id_to_key32(key->tun_id),
- ntohl(md->index), truncate, false);
+ ntohl(md->u.index), truncate, false);
} else {
switch (skb->protocol) {
@@ -1657,7 +1664,7 @@ static int ip6erspan_tap_init(struct net_device *dev)
tunnel->tun_hlen = 8;
tunnel->hlen = tunnel->tun_hlen + tunnel->encap_hlen +
- sizeof(struct erspanhdr);
+ sizeof(struct erspan_base_hdr) + ERSPAN_V1_MDSIZE;
t_hlen = tunnel->hlen + sizeof(struct ipv6hdr);
dev->hard_header_len = LL_MAX_HEADER + t_hlen;
diff --git a/net/openvswitch/flow_netlink.c b/net/openvswitch/flow_netlink.c
index 624ea74353dd..bce1f78b0de5 100644
--- a/net/openvswitch/flow_netlink.c
+++ b/net/openvswitch/flow_netlink.c
@@ -644,12 +644,12 @@ static int erspan_tun_opt_from_nlattr(const struct nlattr *attr,
BUILD_BUG_ON(sizeof(opts) > sizeof(match->key->tun_opts));
memset(&opts, 0, sizeof(opts));
- opts.index = nla_get_be32(attr);
+ opts.u.index = nla_get_be32(attr);
/* Index has only 20-bit */
- if (ntohl(opts.index) & ~INDEX_MASK) {
+ if (ntohl(opts.u.index) & ~INDEX_MASK) {
OVS_NLERR(log, "ERSPAN index number %x too large.",
- ntohl(opts.index));
+ ntohl(opts.u.index));
return -EINVAL;
}
@@ -907,7 +907,7 @@ static int __ip_tun_to_nlattr(struct sk_buff *skb,
return -EMSGSIZE;
else if (output->tun_flags & TUNNEL_ERSPAN_OPT &&
nla_put_be32(skb, OVS_TUNNEL_KEY_ATTR_ERSPAN_OPTS,
- ((struct erspan_metadata *)tun_opts)->index))
+ ((struct erspan_metadata *)tun_opts)->u.index))
return -EMSGSIZE;
}
--
2.7.4
^ permalink raw reply related
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