* pull request (net): ipsec 2017-10-09
From: Steffen Klassert @ 2017-10-09 7:16 UTC (permalink / raw)
To: David Miller; +Cc: Herbert Xu, Steffen Klassert, netdev
1) Fix some error paths of the IPsec offloading API.
2) Fix a NULL pointer dereference when IPsec is used
with vti. From Alexey Kodanev.
3) Don't call xfrm_policy_cache_flush under xfrm_state_lock,
it triggers several locking warnings. From Artem Savkov.
Please pull or let me know if there are problems.
Thanks!
The following changes since commit 1f4f554a72be0d8c164c2f5bc6ba939a1c624fb4:
net: qualcomm: rmnet: Fix a double free (2017-09-09 14:33:27 -0700)
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec.git master
for you to fetch changes up to dd269db84908d4d3f7c0efed85bf9d8939fb0b9b:
xfrm: don't call xfrm_policy_cache_flush under xfrm_state_lock (2017-09-28 09:39:05 +0200)
----------------------------------------------------------------
Alexey Kodanev (1):
vti: fix NULL dereference in xfrm_input()
Artem Savkov (1):
xfrm: don't call xfrm_policy_cache_flush under xfrm_state_lock
Steffen Klassert (2):
xfrm: Fix deletion of offloaded SAs on failure.
xfrm: Fix negative device refcount on offload failure.
net/xfrm/xfrm_device.c | 1 +
net/xfrm/xfrm_input.c | 6 ++++--
net/xfrm/xfrm_state.c | 4 ++--
net/xfrm/xfrm_user.c | 1 +
4 files changed, 8 insertions(+), 4 deletions(-)
^ permalink raw reply
* [PATCH 4/4] xfrm: don't call xfrm_policy_cache_flush under xfrm_state_lock
From: Steffen Klassert @ 2017-10-09 7:16 UTC (permalink / raw)
To: David Miller; +Cc: Herbert Xu, Steffen Klassert, netdev
In-Reply-To: <1507533399-29399-1-git-send-email-steffen.klassert@secunet.com>
From: Artem Savkov <asavkov@redhat.com>
I might be wrong but it doesn't look like xfrm_state_lock is required
for xfrm_policy_cache_flush and calling it under this lock triggers both
"sleeping function called from invalid context" and "possible circular
locking dependency detected" warnings on flush.
Fixes: ec30d78c14a8 xfrm: add xdst pcpu cache
Signed-off-by: Artem Savkov <asavkov@redhat.com>
Acked-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
---
net/xfrm/xfrm_state.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index 0dab1cd..1221347 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -732,12 +732,12 @@ int xfrm_state_flush(struct net *net, u8 proto, bool task_valid)
}
}
}
+out:
+ spin_unlock_bh(&net->xfrm.xfrm_state_lock);
if (cnt) {
err = 0;
xfrm_policy_cache_flush();
}
-out:
- spin_unlock_bh(&net->xfrm.xfrm_state_lock);
return err;
}
EXPORT_SYMBOL(xfrm_state_flush);
--
2.7.4
^ permalink raw reply related
* [PATCH 3/4] vti: fix NULL dereference in xfrm_input()
From: Steffen Klassert @ 2017-10-09 7:16 UTC (permalink / raw)
To: David Miller; +Cc: Herbert Xu, Steffen Klassert, netdev
In-Reply-To: <1507533399-29399-1-git-send-email-steffen.klassert@secunet.com>
From: Alexey Kodanev <alexey.kodanev@oracle.com>
Can be reproduced with LTP tests:
# icmp-uni-vti.sh -p ah -a sha256 -m tunnel -S fffffffe -k 1 -s 10
IPv4:
RIP: 0010:xfrm_input+0x7f9/0x870
...
Call Trace:
<IRQ>
vti_input+0xaa/0x110 [ip_vti]
? skb_free_head+0x21/0x40
vti_rcv+0x33/0x40 [ip_vti]
xfrm4_ah_rcv+0x33/0x60
ip_local_deliver_finish+0x94/0x1e0
ip_local_deliver+0x6f/0xe0
? ip_route_input_noref+0x28/0x50
...
# icmp-uni-vti.sh -6 -p ah -a sha256 -m tunnel -S fffffffe -k 1 -s 10
IPv6:
RIP: 0010:xfrm_input+0x7f9/0x870
...
Call Trace:
<IRQ>
xfrm6_rcv_tnl+0x3c/0x40
vti6_rcv+0xd5/0xe0 [ip6_vti]
xfrm6_ah_rcv+0x33/0x60
ip6_input_finish+0xee/0x460
ip6_input+0x3f/0xb0
ip6_rcv_finish+0x45/0xa0
ipv6_rcv+0x34b/0x540
xfrm_input() invokes xfrm_rcv_cb() -> vti_rcv_cb(), the last callback
might call skb_scrub_packet(), which in turn can reset secpath.
Fix it by adding a check that skb->sp is not NULL.
Fixes: 7e9e9202bccc ("xfrm: Clear RX SKB secpath xfrm_offload")
Signed-off-by: Alexey Kodanev <alexey.kodanev@oracle.com>
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
---
net/xfrm/xfrm_input.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/net/xfrm/xfrm_input.c b/net/xfrm/xfrm_input.c
index 2515cd2..8ac9d32 100644
--- a/net/xfrm/xfrm_input.c
+++ b/net/xfrm/xfrm_input.c
@@ -429,7 +429,8 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
nf_reset(skb);
if (decaps) {
- skb->sp->olen = 0;
+ if (skb->sp)
+ skb->sp->olen = 0;
skb_dst_drop(skb);
gro_cells_receive(&gro_cells, skb);
return 0;
@@ -440,7 +441,8 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
err = x->inner_mode->afinfo->transport_finish(skb, xfrm_gro || async);
if (xfrm_gro) {
- skb->sp->olen = 0;
+ if (skb->sp)
+ skb->sp->olen = 0;
skb_dst_drop(skb);
gro_cells_receive(&gro_cells, skb);
return err;
--
2.7.4
^ permalink raw reply related
* pull-request: mac80211 2017-10-09
From: Johannes Berg @ 2017-10-09 7:40 UTC (permalink / raw)
To: David Miller; +Cc: netdev, linux-wireless
Hi Dave,
The QCA folks found another netlink problem - we were missing validation
of some attributes. It's not super problematic since one can only read a
few bytes beyond the message (and that memory must exist), but here's the
fix for it.
I thought perhaps we can make nla_parse_nested() require a policy, but
given the two-stage validation/parsing in regular netlink that won't work.
Please pull and let me know if there's any problem.
Thanks,
johannes
The following changes since commit 9f775ead5e570e7e19015b9e4e2f3dd6e71a5935:
l2tp: fix l2tp_eth module loading (2017-10-01 22:35:07 -0700)
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211.git tags/mac80211-for-davem-2017-10-09
for you to fetch changes up to ad670233c9e1d5feb365d870e30083ef1b889177:
nl80211: Define policy for packet pattern attributes (2017-10-04 14:39:21 +0200)
----------------------------------------------------------------
Just a single fix for a missing netlink attribute validation.
----------------------------------------------------------------
Peng Xu (1):
nl80211: Define policy for packet pattern attributes
net/wireless/nl80211.c | 14 ++++++++++++--
1 file changed, 12 insertions(+), 2 deletions(-)
^ permalink raw reply
* [PATCH net-next 0/7] A few cleanup for hns3 ethernet driver
From: Yunsheng Lin @ 2017-10-09 7:43 UTC (permalink / raw)
To: davem
Cc: huangdaode, xuwei5, liguozhu, Yisen.Zhuang, gabriele.paoloni,
john.garry, linuxarm, yisen.zhuang, salil.mehta, lipeng321,
netdev, linux-kernel
This patchset contains a few cleanup for hns3 ethernet driver.
No functional change intended.
Yunsheng Lin (7):
net: hns3: Cleanup for shifting true in hns3 driver
net: hns3: Add hns3_get_handle macro in hns3 driver
net: hns3: Cleanup indentation for Kconfig in the the hisilicon folder
net: hns3: Consistently using GENMASK in hns3 driver
net: hns3: Cleanup for struct that used to send cmd to firmware
net: hns3: Cleanup for endian issue in hns3 driver
net: hns3: Cleanup for non-static function in hns3 driver
drivers/net/ethernet/hisilicon/Kconfig | 6 +-
.../net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c | 16 +-
.../net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h | 130 +++----
.../ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 385 +++++++++++----------
.../ethernet/hisilicon/hns3/hns3pf/hclge_main.h | 4 +-
.../net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c | 26 +-
.../ethernet/hisilicon/hns3/hns3pf/hns3_dcbnl.c | 18 +-
.../net/ethernet/hisilicon/hns3/hns3pf/hns3_enet.c | 61 +---
.../net/ethernet/hisilicon/hns3/hns3pf/hns3_enet.h | 3 +
.../ethernet/hisilicon/hns3/hns3pf/hns3_ethtool.c | 42 +--
10 files changed, 344 insertions(+), 347 deletions(-)
--
1.9.1
^ permalink raw reply
* [PATCH net-next 1/7] net: hns3: Cleanup for shifting true in hns3 driver
From: Yunsheng Lin @ 2017-10-09 7:43 UTC (permalink / raw)
To: davem
Cc: huangdaode, xuwei5, liguozhu, Yisen.Zhuang, gabriele.paoloni,
john.garry, linuxarm, yisen.zhuang, salil.mehta, lipeng321,
netdev, linux-kernel
In-Reply-To: <1507535041-204956-1-git-send-email-linyunsheng@huawei.com>
This patch fixes a shifting true in hclge_main module.
Signed-off-by: Yunsheng Lin <linyunsheng@huawei.com>
---
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
index 1a13614..5c1bf12 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
@@ -1687,7 +1687,7 @@ static int hclge_rx_priv_buf_alloc(struct hclge_dev *hdev,
req->buf_num[i] =
cpu_to_le16(priv->buf_size >> HCLGE_BUF_UNIT_S);
req->buf_num[i] |=
- cpu_to_le16(true << HCLGE_TC0_PRI_BUF_EN_B);
+ cpu_to_le16(1 << HCLGE_TC0_PRI_BUF_EN_B);
}
req->shared_buf =
--
1.9.1
^ permalink raw reply related
* [PATCH net-next 2/7] net: hns3: Add hns3_get_handle macro in hns3 driver
From: Yunsheng Lin @ 2017-10-09 7:43 UTC (permalink / raw)
To: davem
Cc: huangdaode, xuwei5, liguozhu, Yisen.Zhuang, gabriele.paoloni,
john.garry, linuxarm, yisen.zhuang, salil.mehta, lipeng321,
netdev, linux-kernel
In-Reply-To: <1507535041-204956-1-git-send-email-linyunsheng@huawei.com>
There are many places that will need to get the handle
of netdev, so add a macro to get the handle of netdev.
Signed-off-by: Yunsheng Lin <linyunsheng@huawei.com>
---
.../ethernet/hisilicon/hns3/hns3pf/hns3_dcbnl.c | 18 ++++------
.../net/ethernet/hisilicon/hns3/hns3pf/hns3_enet.c | 39 ++++++++--------------
.../net/ethernet/hisilicon/hns3/hns3pf/hns3_enet.h | 3 ++
.../ethernet/hisilicon/hns3/hns3pf/hns3_ethtool.c | 38 ++++++++-------------
4 files changed, 35 insertions(+), 63 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hns3_dcbnl.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hns3_dcbnl.c
index 9832172..925619a 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hns3_dcbnl.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hns3_dcbnl.c
@@ -13,8 +13,7 @@
static
int hns3_dcbnl_ieee_getets(struct net_device *ndev, struct ieee_ets *ets)
{
- struct hns3_nic_priv *priv = netdev_priv(ndev);
- struct hnae3_handle *h = priv->ae_handle;
+ struct hnae3_handle *h = hns3_get_handle(ndev);
if (h->kinfo.dcb_ops->ieee_getets)
return h->kinfo.dcb_ops->ieee_getets(h, ets);
@@ -25,8 +24,7 @@ int hns3_dcbnl_ieee_getets(struct net_device *ndev, struct ieee_ets *ets)
static
int hns3_dcbnl_ieee_setets(struct net_device *ndev, struct ieee_ets *ets)
{
- struct hns3_nic_priv *priv = netdev_priv(ndev);
- struct hnae3_handle *h = priv->ae_handle;
+ struct hnae3_handle *h = hns3_get_handle(ndev);
if (h->kinfo.dcb_ops->ieee_setets)
return h->kinfo.dcb_ops->ieee_setets(h, ets);
@@ -37,8 +35,7 @@ int hns3_dcbnl_ieee_setets(struct net_device *ndev, struct ieee_ets *ets)
static
int hns3_dcbnl_ieee_getpfc(struct net_device *ndev, struct ieee_pfc *pfc)
{
- struct hns3_nic_priv *priv = netdev_priv(ndev);
- struct hnae3_handle *h = priv->ae_handle;
+ struct hnae3_handle *h = hns3_get_handle(ndev);
if (h->kinfo.dcb_ops->ieee_getpfc)
return h->kinfo.dcb_ops->ieee_getpfc(h, pfc);
@@ -49,8 +46,7 @@ int hns3_dcbnl_ieee_getpfc(struct net_device *ndev, struct ieee_pfc *pfc)
static
int hns3_dcbnl_ieee_setpfc(struct net_device *ndev, struct ieee_pfc *pfc)
{
- struct hns3_nic_priv *priv = netdev_priv(ndev);
- struct hnae3_handle *h = priv->ae_handle;
+ struct hnae3_handle *h = hns3_get_handle(ndev);
if (h->kinfo.dcb_ops->ieee_setpfc)
return h->kinfo.dcb_ops->ieee_setpfc(h, pfc);
@@ -61,8 +57,7 @@ int hns3_dcbnl_ieee_setpfc(struct net_device *ndev, struct ieee_pfc *pfc)
/* DCBX configuration */
static u8 hns3_dcbnl_getdcbx(struct net_device *ndev)
{
- struct hns3_nic_priv *priv = netdev_priv(ndev);
- struct hnae3_handle *h = priv->ae_handle;
+ struct hnae3_handle *h = hns3_get_handle(ndev);
if (h->kinfo.dcb_ops->getdcbx)
return h->kinfo.dcb_ops->getdcbx(h);
@@ -73,8 +68,7 @@ static u8 hns3_dcbnl_getdcbx(struct net_device *ndev)
/* return 0 if successful, otherwise fail */
static u8 hns3_dcbnl_setdcbx(struct net_device *ndev, u8 mode)
{
- struct hns3_nic_priv *priv = netdev_priv(ndev);
- struct hnae3_handle *h = priv->ae_handle;
+ struct hnae3_handle *h = hns3_get_handle(ndev);
if (h->kinfo.dcb_ops->setdcbx)
return h->kinfo.dcb_ops->setdcbx(h, mode);
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hns3_enet.c
index c315065..c2a0537 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hns3_enet.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hns3_enet.c
@@ -198,8 +198,7 @@ static void hns3_vector_gl_rl_init(struct hns3_enet_tqp_vector *tqp_vector)
static int hns3_nic_set_real_num_queue(struct net_device *netdev)
{
- struct hns3_nic_priv *priv = netdev_priv(netdev);
- struct hnae3_handle *h = priv->ae_handle;
+ struct hnae3_handle *h = hns3_get_handle(netdev);
struct hnae3_knic_private_info *kinfo = &h->kinfo;
unsigned int queue_size = kinfo->rss_size * kinfo->num_tc;
int ret;
@@ -307,8 +306,7 @@ static int hns3_nic_net_stop(struct net_device *netdev)
void hns3_set_multicast_list(struct net_device *netdev)
{
- struct hns3_nic_priv *priv = netdev_priv(netdev);
- struct hnae3_handle *h = priv->ae_handle;
+ struct hnae3_handle *h = hns3_get_handle(netdev);
struct netdev_hw_addr *ha = NULL;
if (h->ae_algo->ops->set_mc_addr) {
@@ -321,8 +319,7 @@ void hns3_set_multicast_list(struct net_device *netdev)
static int hns3_nic_uc_sync(struct net_device *netdev,
const unsigned char *addr)
{
- struct hns3_nic_priv *priv = netdev_priv(netdev);
- struct hnae3_handle *h = priv->ae_handle;
+ struct hnae3_handle *h = hns3_get_handle(netdev);
if (h->ae_algo->ops->add_uc_addr)
return h->ae_algo->ops->add_uc_addr(h, addr);
@@ -333,8 +330,7 @@ static int hns3_nic_uc_sync(struct net_device *netdev,
static int hns3_nic_uc_unsync(struct net_device *netdev,
const unsigned char *addr)
{
- struct hns3_nic_priv *priv = netdev_priv(netdev);
- struct hnae3_handle *h = priv->ae_handle;
+ struct hnae3_handle *h = hns3_get_handle(netdev);
if (h->ae_algo->ops->rm_uc_addr)
return h->ae_algo->ops->rm_uc_addr(h, addr);
@@ -345,8 +341,7 @@ static int hns3_nic_uc_unsync(struct net_device *netdev,
static int hns3_nic_mc_sync(struct net_device *netdev,
const unsigned char *addr)
{
- struct hns3_nic_priv *priv = netdev_priv(netdev);
- struct hnae3_handle *h = priv->ae_handle;
+ struct hnae3_handle *h = hns3_get_handle(netdev);
if (h->ae_algo->ops->add_mc_addr)
return h->ae_algo->ops->add_mc_addr(h, addr);
@@ -357,8 +352,7 @@ static int hns3_nic_mc_sync(struct net_device *netdev,
static int hns3_nic_mc_unsync(struct net_device *netdev,
const unsigned char *addr)
{
- struct hns3_nic_priv *priv = netdev_priv(netdev);
- struct hnae3_handle *h = priv->ae_handle;
+ struct hnae3_handle *h = hns3_get_handle(netdev);
if (h->ae_algo->ops->rm_mc_addr)
return h->ae_algo->ops->rm_mc_addr(h, addr);
@@ -368,8 +362,7 @@ static int hns3_nic_mc_unsync(struct net_device *netdev,
void hns3_nic_set_rx_mode(struct net_device *netdev)
{
- struct hns3_nic_priv *priv = netdev_priv(netdev);
- struct hnae3_handle *h = priv->ae_handle;
+ struct hnae3_handle *h = hns3_get_handle(netdev);
if (h->ae_algo->ops->set_promisc_mode) {
if (netdev->flags & IFF_PROMISC)
@@ -1025,8 +1018,7 @@ static netdev_tx_t hns3_nic_net_xmit(struct sk_buff *skb,
static int hns3_nic_net_set_mac_address(struct net_device *netdev, void *p)
{
- struct hns3_nic_priv *priv = netdev_priv(netdev);
- struct hnae3_handle *h = priv->ae_handle;
+ struct hnae3_handle *h = hns3_get_handle(netdev);
struct sockaddr *mac_addr = p;
int ret;
@@ -1208,8 +1200,7 @@ static void hns3_nic_udp_tunnel_del(struct net_device *netdev,
static int hns3_setup_tc(struct net_device *netdev, u8 tc)
{
- struct hns3_nic_priv *priv = netdev_priv(netdev);
- struct hnae3_handle *h = priv->ae_handle;
+ struct hnae3_handle *h = hns3_get_handle(netdev);
struct hnae3_knic_private_info *kinfo = &h->kinfo;
unsigned int i;
int ret;
@@ -1259,8 +1250,7 @@ static int hns3_nic_setup_tc(struct net_device *dev, enum tc_setup_type type,
static int hns3_vlan_rx_add_vid(struct net_device *netdev,
__be16 proto, u16 vid)
{
- struct hns3_nic_priv *priv = netdev_priv(netdev);
- struct hnae3_handle *h = priv->ae_handle;
+ struct hnae3_handle *h = hns3_get_handle(netdev);
int ret = -EIO;
if (h->ae_algo->ops->set_vlan_filter)
@@ -1272,8 +1262,7 @@ static int hns3_vlan_rx_add_vid(struct net_device *netdev,
static int hns3_vlan_rx_kill_vid(struct net_device *netdev,
__be16 proto, u16 vid)
{
- struct hns3_nic_priv *priv = netdev_priv(netdev);
- struct hnae3_handle *h = priv->ae_handle;
+ struct hnae3_handle *h = hns3_get_handle(netdev);
int ret = -EIO;
if (h->ae_algo->ops->set_vlan_filter)
@@ -1285,8 +1274,7 @@ static int hns3_vlan_rx_kill_vid(struct net_device *netdev,
static int hns3_ndo_set_vf_vlan(struct net_device *netdev, int vf, u16 vlan,
u8 qos, __be16 vlan_proto)
{
- struct hns3_nic_priv *priv = netdev_priv(netdev);
- struct hnae3_handle *h = priv->ae_handle;
+ struct hnae3_handle *h = hns3_get_handle(netdev);
int ret = -EIO;
if (h->ae_algo->ops->set_vf_vlan_filter)
@@ -1298,8 +1286,7 @@ static int hns3_ndo_set_vf_vlan(struct net_device *netdev, int vf, u16 vlan,
static int hns3_nic_change_mtu(struct net_device *netdev, int new_mtu)
{
- struct hns3_nic_priv *priv = netdev_priv(netdev);
- struct hnae3_handle *h = priv->ae_handle;
+ struct hnae3_handle *h = hns3_get_handle(netdev);
bool if_running = netif_running(netdev);
int ret;
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hns3_enet.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hns3_enet.h
index 481eada..dd8d40c 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hns3_enet.h
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hns3_enet.h
@@ -587,6 +587,9 @@ static inline void hns3_write_reg(void __iomem *base, u32 reg, u32 value)
#define hns3_for_each_ring(pos, head) \
for (pos = (head).ring; pos; pos = pos->next)
+#define hns3_get_handle(ndev) \
+ (((struct hns3_nic_priv *)netdev_priv(ndev))->ae_handle)
+
void hns3_ethtool_set_ops(struct net_device *netdev);
int hns3_clean_tx_ring(struct hns3_enet_ring *ring, int budget);
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hns3_ethtool.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hns3_ethtool.c
index d636399..a892a15 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hns3_ethtool.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hns3_ethtool.c
@@ -102,8 +102,7 @@ static void hns3_driv_to_eth_caps(u32 caps, struct ethtool_link_ksettings *cmd,
static int hns3_get_sset_count(struct net_device *netdev, int stringset)
{
- struct hns3_nic_priv *priv = netdev_priv(netdev);
- struct hnae3_handle *h = priv->ae_handle;
+ struct hnae3_handle *h = hns3_get_handle(netdev);
const struct hnae3_ae_ops *ops = h->ae_algo->ops;
if (!ops->get_sset_count)
@@ -164,8 +163,7 @@ static u8 *hns3_get_strings_tqps(struct hnae3_handle *handle, u8 *data)
static void hns3_get_strings(struct net_device *netdev, u32 stringset, u8 *data)
{
- struct hns3_nic_priv *priv = netdev_priv(netdev);
- struct hnae3_handle *h = priv->ae_handle;
+ struct hnae3_handle *h = hns3_get_handle(netdev);
const struct hnae3_ae_ops *ops = h->ae_algo->ops;
char *buff = (char *)data;
@@ -220,8 +218,7 @@ static u64 *hns3_get_stats_tqps(struct hnae3_handle *handle, u64 *data)
void hns3_get_stats(struct net_device *netdev, struct ethtool_stats *stats,
u64 *data)
{
- struct hns3_nic_priv *priv = netdev_priv(netdev);
- struct hnae3_handle *h = priv->ae_handle;
+ struct hnae3_handle *h = hns3_get_handle(netdev);
u64 *p = data;
if (!h->ae_algo->ops->get_stats || !h->ae_algo->ops->update_stats) {
@@ -262,10 +259,7 @@ static void hns3_get_drvinfo(struct net_device *netdev,
static u32 hns3_get_link(struct net_device *netdev)
{
- struct hns3_nic_priv *priv = netdev_priv(netdev);
- struct hnae3_handle *h;
-
- h = priv->ae_handle;
+ struct hnae3_handle *h = hns3_get_handle(netdev);
if (h->ae_algo && h->ae_algo->ops && h->ae_algo->ops->get_status)
return h->ae_algo->ops->get_status(h);
@@ -277,7 +271,8 @@ static void hns3_get_ringparam(struct net_device *netdev,
struct ethtool_ringparam *param)
{
struct hns3_nic_priv *priv = netdev_priv(netdev);
- int queue_num = priv->ae_handle->kinfo.num_tqps;
+ struct hnae3_handle *h = priv->ae_handle;
+ int queue_num = h->kinfo.num_tqps;
param->tx_max_pending = HNS3_RING_MAX_PENDING;
param->rx_max_pending = HNS3_RING_MAX_PENDING;
@@ -289,8 +284,7 @@ static void hns3_get_ringparam(struct net_device *netdev,
static void hns3_get_pauseparam(struct net_device *netdev,
struct ethtool_pauseparam *param)
{
- struct hns3_nic_priv *priv = netdev_priv(netdev);
- struct hnae3_handle *h = priv->ae_handle;
+ struct hnae3_handle *h = hns3_get_handle(netdev);
if (h->ae_algo && h->ae_algo->ops && h->ae_algo->ops->get_pauseparam)
h->ae_algo->ops->get_pauseparam(h, ¶m->autoneg,
@@ -300,8 +294,7 @@ static void hns3_get_pauseparam(struct net_device *netdev,
static int hns3_get_link_ksettings(struct net_device *netdev,
struct ethtool_link_ksettings *cmd)
{
- struct hns3_nic_priv *priv = netdev_priv(netdev);
- struct hnae3_handle *h = priv->ae_handle;
+ struct hnae3_handle *h = hns3_get_handle(netdev);
u32 supported_caps;
u32 advertised_caps;
u8 media_type = HNAE3_MEDIA_TYPE_UNKNOWN;
@@ -392,8 +385,7 @@ static int hns3_get_link_ksettings(struct net_device *netdev,
static u32 hns3_get_rss_key_size(struct net_device *netdev)
{
- struct hns3_nic_priv *priv = netdev_priv(netdev);
- struct hnae3_handle *h = priv->ae_handle;
+ struct hnae3_handle *h = hns3_get_handle(netdev);
if (!h->ae_algo || !h->ae_algo->ops ||
!h->ae_algo->ops->get_rss_key_size)
@@ -404,8 +396,7 @@ static u32 hns3_get_rss_key_size(struct net_device *netdev)
static u32 hns3_get_rss_indir_size(struct net_device *netdev)
{
- struct hns3_nic_priv *priv = netdev_priv(netdev);
- struct hnae3_handle *h = priv->ae_handle;
+ struct hnae3_handle *h = hns3_get_handle(netdev);
if (!h->ae_algo || !h->ae_algo->ops ||
!h->ae_algo->ops->get_rss_indir_size)
@@ -417,8 +408,7 @@ static u32 hns3_get_rss_indir_size(struct net_device *netdev)
static int hns3_get_rss(struct net_device *netdev, u32 *indir, u8 *key,
u8 *hfunc)
{
- struct hns3_nic_priv *priv = netdev_priv(netdev);
- struct hnae3_handle *h = priv->ae_handle;
+ struct hnae3_handle *h = hns3_get_handle(netdev);
if (!h->ae_algo || !h->ae_algo->ops || !h->ae_algo->ops->get_rss)
return -EOPNOTSUPP;
@@ -429,8 +419,7 @@ static int hns3_get_rss(struct net_device *netdev, u32 *indir, u8 *key,
static int hns3_set_rss(struct net_device *netdev, const u32 *indir,
const u8 *key, const u8 hfunc)
{
- struct hns3_nic_priv *priv = netdev_priv(netdev);
- struct hnae3_handle *h = priv->ae_handle;
+ struct hnae3_handle *h = hns3_get_handle(netdev);
if (!h->ae_algo || !h->ae_algo->ops || !h->ae_algo->ops->set_rss)
return -EOPNOTSUPP;
@@ -454,8 +443,7 @@ static int hns3_get_rxnfc(struct net_device *netdev,
struct ethtool_rxnfc *cmd,
u32 *rule_locs)
{
- struct hns3_nic_priv *priv = netdev_priv(netdev);
- struct hnae3_handle *h = priv->ae_handle;
+ struct hnae3_handle *h = hns3_get_handle(netdev);
if (!h->ae_algo || !h->ae_algo->ops || !h->ae_algo->ops->get_tc_size)
return -EOPNOTSUPP;
--
1.9.1
^ permalink raw reply related
* [PATCH net-next 3/7] net: hns3: Cleanup indentation for Kconfig in the the hisilicon folder
From: Yunsheng Lin @ 2017-10-09 7:43 UTC (permalink / raw)
To: davem
Cc: huangdaode, xuwei5, liguozhu, Yisen.Zhuang, gabriele.paoloni,
john.garry, linuxarm, yisen.zhuang, salil.mehta, lipeng321,
netdev, linux-kernel
In-Reply-To: <1507535041-204956-1-git-send-email-linyunsheng@huawei.com>
This patch fixes a few indentation for Kconfig file in the
hisilicon folder.
Signed-off-by: Yunsheng Lin <linyunsheng@huawei.com>
---
drivers/net/ethernet/hisilicon/Kconfig | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/Kconfig b/drivers/net/ethernet/hisilicon/Kconfig
index 9d7cb03..30000b6 100644
--- a/drivers/net/ethernet/hisilicon/Kconfig
+++ b/drivers/net/ethernet/hisilicon/Kconfig
@@ -78,7 +78,7 @@ config HNS_ENET
config HNS3
tristate "Hisilicon Network Subsystem Support HNS3 (Framework)"
- depends on PCI
+ depends on PCI
---help---
This selects the framework support for Hisilicon Network Subsystem 3.
This layer facilitates clients like ENET, RoCE and user-space ethernet
@@ -87,7 +87,7 @@ config HNS3
config HNS3_HCLGE
tristate "Hisilicon HNS3 HCLGE Acceleration Engine & Compatibility Layer Support"
- depends on PCI_MSI
+ depends on PCI_MSI
depends on HNS3
---help---
This selects the HNS3_HCLGE network acceleration engine & its hardware
@@ -96,7 +96,7 @@ config HNS3_HCLGE
config HNS3_ENET
tristate "Hisilicon HNS3 Ethernet Device Support"
- depends on 64BIT && PCI
+ depends on 64BIT && PCI
depends on HNS3 && HNS3_HCLGE
---help---
This selects the Ethernet Driver for Hisilicon Network Subsystem 3 for hip08
--
1.9.1
^ permalink raw reply related
* [PATCH net-next 4/7] net: hns3: Consistently using GENMASK in hns3 driver
From: Yunsheng Lin @ 2017-10-09 7:43 UTC (permalink / raw)
To: davem
Cc: huangdaode, xuwei5, liguozhu, Yisen.Zhuang, gabriele.paoloni,
john.garry, linuxarm, yisen.zhuang, salil.mehta, lipeng321,
netdev, linux-kernel
In-Reply-To: <1507535041-204956-1-git-send-email-linyunsheng@huawei.com>
This patch uses GENMASK to generate bit mask whenever
possible in hns3 driver.
Signed-off-by: Yunsheng Lin <linyunsheng@huawei.com>
---
.../net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h | 48 +++++++++++-----------
.../ethernet/hisilicon/hns3/hns3pf/hclge_main.h | 4 +-
2 files changed, 26 insertions(+), 26 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h
index 6b6d28e..9cff7db 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h
@@ -250,11 +250,11 @@ struct hclge_ctrl_vector_chain {
u8 int_vector_id;
u8 int_cause_num;
#define HCLGE_INT_TYPE_S 0
-#define HCLGE_INT_TYPE_M 0x3
+#define HCLGE_INT_TYPE_M GENMASK(1, 0)
#define HCLGE_TQP_ID_S 2
-#define HCLGE_TQP_ID_M (0x7ff << HCLGE_TQP_ID_S)
+#define HCLGE_TQP_ID_M GENMASK(12, 2)
#define HCLGE_INT_GL_IDX_S 13
-#define HCLGE_INT_GL_IDX_M (0x3 << HCLGE_INT_GL_IDX_S)
+#define HCLGE_INT_GL_IDX_M GENMASK(14, 13)
__le16 tqp_type_and_id[HCLGE_VECTOR_ELEMENTS_PER_CMD];
u8 vfid;
u8 rsv;
@@ -372,28 +372,28 @@ struct hclge_pf_res {
};
#define HCLGE_CFG_OFFSET_S 0
-#define HCLGE_CFG_OFFSET_M 0xfffff /* Byte (8-10.3) */
+#define HCLGE_CFG_OFFSET_M GENMASK(19, 0)
#define HCLGE_CFG_RD_LEN_S 24
-#define HCLGE_CFG_RD_LEN_M (0xf << HCLGE_CFG_RD_LEN_S)
+#define HCLGE_CFG_RD_LEN_M GENMASK(27, 24)
#define HCLGE_CFG_RD_LEN_BYTES 16
#define HCLGE_CFG_RD_LEN_UNIT 4
#define HCLGE_CFG_VMDQ_S 0
-#define HCLGE_CFG_VMDQ_M (0xff << HCLGE_CFG_VMDQ_S)
+#define HCLGE_CFG_VMDQ_M GENMASK(7, 0)
#define HCLGE_CFG_TC_NUM_S 8
-#define HCLGE_CFG_TC_NUM_M (0xff << HCLGE_CFG_TC_NUM_S)
+#define HCLGE_CFG_TC_NUM_M GENMASK(15, 8)
#define HCLGE_CFG_TQP_DESC_N_S 16
-#define HCLGE_CFG_TQP_DESC_N_M (0xffff << HCLGE_CFG_TQP_DESC_N_S)
+#define HCLGE_CFG_TQP_DESC_N_M GENMASK(31, 16)
#define HCLGE_CFG_PHY_ADDR_S 0
-#define HCLGE_CFG_PHY_ADDR_M (0x1f << HCLGE_CFG_PHY_ADDR_S)
+#define HCLGE_CFG_PHY_ADDR_M GENMASK(4, 0)
#define HCLGE_CFG_MEDIA_TP_S 8
-#define HCLGE_CFG_MEDIA_TP_M (0xff << HCLGE_CFG_MEDIA_TP_S)
+#define HCLGE_CFG_MEDIA_TP_M GENMASK(15, 8)
#define HCLGE_CFG_RX_BUF_LEN_S 16
-#define HCLGE_CFG_RX_BUF_LEN_M (0xffff << HCLGE_CFG_RX_BUF_LEN_S)
+#define HCLGE_CFG_RX_BUF_LEN_M GENMASK(31, 16)
#define HCLGE_CFG_MAC_ADDR_H_S 0
-#define HCLGE_CFG_MAC_ADDR_H_M (0xffff << HCLGE_CFG_MAC_ADDR_H_S)
+#define HCLGE_CFG_MAC_ADDR_H_M GENMASK(15, 0)
#define HCLGE_CFG_DEFAULT_SPEED_S 16
-#define HCLGE_CFG_DEFAULT_SPEED_M (0xff << HCLGE_CFG_DEFAULT_SPEED_S)
+#define HCLGE_CFG_DEFAULT_SPEED_M GENMASK(23, 16)
struct hclge_cfg_param {
__le32 offset;
@@ -441,9 +441,9 @@ struct hclge_rss_indirection_table {
};
#define HCLGE_RSS_TC_OFFSET_S 0
-#define HCLGE_RSS_TC_OFFSET_M (0x3ff << HCLGE_RSS_TC_OFFSET_S)
+#define HCLGE_RSS_TC_OFFSET_M GENMASK(9, 0)
#define HCLGE_RSS_TC_SIZE_S 12
-#define HCLGE_RSS_TC_SIZE_M (0x7 << HCLGE_RSS_TC_SIZE_S)
+#define HCLGE_RSS_TC_SIZE_M GENMASK(14, 12)
#define HCLGE_RSS_TC_VALID_B 15
struct hclge_rss_tc_mode {
u16 rss_tc_mode[HCLGE_MAX_TC_NUM];
@@ -501,7 +501,7 @@ struct hclge_config_mac_mode {
};
#define HCLGE_CFG_SPEED_S 0
-#define HCLGE_CFG_SPEED_M (0x3f << HCLGE_CFG_SPEED_S)
+#define HCLGE_CFG_SPEED_M GENMASK(5, 0)
#define HCLGE_CFG_DUPLEX_B 7
#define HCLGE_CFG_DUPLEX_M BIT(HCLGE_CFG_DUPLEX_B)
@@ -518,7 +518,7 @@ struct hclge_config_mac_speed_dup {
#define HCLGE_QUERY_AN_B 0
#define HCLGE_QUERY_DUPLEX_B 2
-#define HCLGE_QUERY_SPEED_M (0x1f << HCLGE_QUERY_SPEED_S)
+#define HCLGE_QUERY_SPEED_M GENMASK(4, 0)
#define HCLGE_QUERY_AN_M BIT(HCLGE_QUERY_AN_B)
#define HCLGE_QUERY_DUPLEX_M BIT(HCLGE_QUERY_DUPLEX_B)
@@ -528,7 +528,7 @@ struct hclge_query_an_speed_dup {
u8 rsv[23];
};
-#define HCLGE_RING_ID_MASK 0x3ff
+#define HCLGE_RING_ID_MASK GENMASK(9, 0)
#define HCLGE_TQP_ENABLE_B 0
#define HCLGE_MAC_CFG_AN_EN_B 0
@@ -565,9 +565,9 @@ enum hclge_mac_vlan_tbl_opcode {
#define HCLGE_MAC_EPORT_SW_EN_B 0xc
#define HCLGE_MAC_EPORT_TYPE_B 0xb
#define HCLGE_MAC_EPORT_VFID_S 0x3
-#define HCLGE_MAC_EPORT_VFID_M (0xff << HCLGE_MAC_EPORT_VFID_S)
+#define HCLGE_MAC_EPORT_VFID_M GENMASK(10, 3)
#define HCLGE_MAC_EPORT_PFID_S 0x0
-#define HCLGE_MAC_EPORT_PFID_M (0x7 << HCLGE_MAC_EPORT_PFID_S)
+#define HCLGE_MAC_EPORT_PFID_M GENMASK(2, 0)
struct hclge_mac_vlan_tbl_entry {
u8 flags;
u8 resp_code;
@@ -583,7 +583,7 @@ struct hclge_mac_vlan_tbl_entry {
};
#define HCLGE_CFG_MTA_MAC_SEL_S 0x0
-#define HCLGE_CFG_MTA_MAC_SEL_M (0x3 << HCLGE_CFG_MTA_MAC_SEL_S)
+#define HCLGE_CFG_MTA_MAC_SEL_M GENMASK(1, 0)
#define HCLGE_CFG_MTA_MAC_EN_B 0x7
struct hclge_mta_filter_mode {
u8 dmac_sel_en; /* Use lowest 2 bit as sel_mode, bit 7 as enable */
@@ -599,7 +599,7 @@ struct hclge_cfg_func_mta_filter {
#define HCLGE_CFG_MTA_ITEM_ACCEPT_B 0x0
#define HCLGE_CFG_MTA_ITEM_IDX_S 0x0
-#define HCLGE_CFG_MTA_ITEM_IDX_M (0xfff << HCLGE_CFG_MTA_ITEM_IDX_S)
+#define HCLGE_CFG_MTA_ITEM_IDX_M GENMASK(11, 0)
struct hclge_cfg_func_mta_item {
u16 item_idx; /* Only used lowest 12 bit */
u8 accept; /* Only used lowest 1 bit */
@@ -670,10 +670,10 @@ struct hclge_cfg_tx_queue_pointer {
};
#define HCLGE_TSO_MSS_MIN_S 0
-#define HCLGE_TSO_MSS_MIN_M (0x3FFF << HCLGE_TSO_MSS_MIN_S)
+#define HCLGE_TSO_MSS_MIN_M GENMASK(13, 0)
#define HCLGE_TSO_MSS_MAX_S 16
-#define HCLGE_TSO_MSS_MAX_M (0x3FFF << HCLGE_TSO_MSS_MAX_S)
+#define HCLGE_TSO_MSS_MAX_M GENMASK(29, 16)
struct hclge_cfg_tso_status {
__le16 tso_mss_min;
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h
index 7c66c00..79c1a06 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h
@@ -32,7 +32,7 @@
#define HCLGE_VECTOR_VF_OFFSET 0x100000
#define HCLGE_RSS_IND_TBL_SIZE 512
-#define HCLGE_RSS_SET_BITMAP_MSK 0xffff
+#define HCLGE_RSS_SET_BITMAP_MSK GENMASK(15, 0)
#define HCLGE_RSS_KEY_SIZE 40
#define HCLGE_RSS_HASH_ALGO_TOEPLITZ 0
#define HCLGE_RSS_HASH_ALGO_SIMPLE 1
@@ -65,7 +65,7 @@
#define HCLGE_PHY_CSS_REG 17
#define HCLGE_PHY_MDIX_CTRL_S (5)
-#define HCLGE_PHY_MDIX_CTRL_M (3 << HCLGE_PHY_MDIX_CTRL_S)
+#define HCLGE_PHY_MDIX_CTRL_M GENMASK(6, 5)
#define HCLGE_PHY_MDIX_STATUS_B (6)
#define HCLGE_PHY_SPEED_DUP_RESOLVE_B (11)
--
1.9.1
^ permalink raw reply related
* [PATCH net-next 5/7] net: hns3: Cleanup for struct that used to send cmd to firmware
From: Yunsheng Lin @ 2017-10-09 7:43 UTC (permalink / raw)
To: davem
Cc: huangdaode, xuwei5, liguozhu, Yisen.Zhuang, gabriele.paoloni,
john.garry, linuxarm, yisen.zhuang, salil.mehta, lipeng321,
netdev, linux-kernel
In-Reply-To: <1507535041-204956-1-git-send-email-linyunsheng@huawei.com>
The hclge_tm module has already added _cmd to the end of struct
that used to send cmd to firmware. This will help us finding the
endian issues.
This patch adds the _cmd to the end of struct that used to send
cmd to firmware in hclge_main module.
Signed-off-by: Yunsheng Lin <linyunsheng@huawei.com>
---
.../net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c | 4 +-
.../net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h | 72 ++++-----
.../ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 163 +++++++++++----------
3 files changed, 120 insertions(+), 119 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c
index 8b511e6..648b64b 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c
@@ -279,12 +279,12 @@ int hclge_cmd_send(struct hclge_hw *hw, struct hclge_desc *desc, int num)
enum hclge_cmd_status hclge_cmd_query_firmware_version(struct hclge_hw *hw,
u32 *version)
{
- struct hclge_query_version *resp;
+ struct hclge_query_version_cmd *resp;
struct hclge_desc desc;
int ret;
hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_QUERY_FW_VER, 1);
- resp = (struct hclge_query_version *)desc.data;
+ resp = (struct hclge_query_version_cmd *)desc.data;
ret = hclge_cmd_send(hw, &desc, 1);
if (!ret)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h
index 9cff7db..d2ff0e3 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h
@@ -221,12 +221,12 @@ enum hclge_opcode_type {
#define HCLGE_RCB_INIT_QUERY_TIMEOUT 10
#define HCLGE_RCB_INIT_FLAG_EN_B 0
#define HCLGE_RCB_INIT_FLAG_FINI_B 8
-struct hclge_config_rcb_init {
+struct hclge_config_rcb_init_cmd {
__le16 rcb_init_flag;
u8 rsv[22];
};
-struct hclge_tqp_map {
+struct hclge_tqp_map_cmd {
__le16 tqp_id; /* Absolute tqp id for in this pf */
u8 tqp_vf; /* VF id */
#define HCLGE_TQP_MAP_TYPE_PF 0
@@ -246,7 +246,7 @@ enum hclge_int_type {
HCLGE_INT_EVENT,
};
-struct hclge_ctrl_vector_chain {
+struct hclge_ctrl_vector_chain_cmd {
u8 int_vector_id;
u8 int_cause_num;
#define HCLGE_INT_TYPE_S 0
@@ -263,18 +263,18 @@ struct hclge_ctrl_vector_chain {
#define HCLGE_TC_NUM 8
#define HCLGE_TC0_PRI_BUF_EN_B 15 /* Bit 15 indicate enable or not */
#define HCLGE_BUF_UNIT_S 7 /* Buf size is united by 128 bytes */
-struct hclge_tx_buff_alloc {
+struct hclge_tx_buff_alloc_cmd {
__le16 tx_pkt_buff[HCLGE_TC_NUM];
u8 tx_buff_rsv[8];
};
-struct hclge_rx_priv_buff {
+struct hclge_rx_priv_buff_cmd {
__le16 buf_num[HCLGE_TC_NUM];
__le16 shared_buf;
u8 rsv[6];
};
-struct hclge_query_version {
+struct hclge_query_version_cmd {
__le32 firmware;
__le32 firmware_rsv[5];
};
@@ -328,14 +328,14 @@ struct hclge_pkt_buf_alloc {
};
#define HCLGE_RX_COM_WL_EN_B 15
-struct hclge_rx_com_wl_buf {
+struct hclge_rx_com_wl_buf_cmd {
__le16 high_wl;
__le16 low_wl;
u8 rsv[20];
};
#define HCLGE_RX_PKT_EN_B 15
-struct hclge_rx_pkt_buf {
+struct hclge_rx_pkt_buf_cmd {
__le16 high_pkt;
__le16 low_pkt;
u8 rsv[20];
@@ -348,7 +348,7 @@ struct hclge_rx_pkt_buf {
#define HCLGE_PF_MAC_NUM_MASK 0x3
#define HCLGE_PF_STATE_MAIN BIT(HCLGE_PF_STATE_MAIN_B)
#define HCLGE_PF_STATE_DONE BIT(HCLGE_PF_STATE_DONE_B)
-struct hclge_func_status {
+struct hclge_func_status_cmd {
__le32 vf_rst_state[4];
u8 pf_state;
u8 mac_id;
@@ -359,7 +359,7 @@ struct hclge_func_status {
u8 rsv[2];
};
-struct hclge_pf_res {
+struct hclge_pf_res_cmd {
__le16 tqp_num;
__le16 buf_size;
__le16 msixcap_localid_ba_nic;
@@ -395,7 +395,7 @@ struct hclge_pf_res {
#define HCLGE_CFG_DEFAULT_SPEED_S 16
#define HCLGE_CFG_DEFAULT_SPEED_M GENMASK(23, 16)
-struct hclge_cfg_param {
+struct hclge_cfg_param_cmd {
__le32 offset;
__le32 rsv;
__le32 param[4];
@@ -405,7 +405,7 @@ struct hclge_cfg_param {
#define HCLGE_DESC_NUM 0x40
#define HCLGE_ALLOC_VALID_B 0
-struct hclge_vf_num {
+struct hclge_vf_num_cmd {
u8 alloc_valid;
u8 rsv[23];
};
@@ -413,13 +413,13 @@ struct hclge_vf_num {
#define HCLGE_RSS_DEFAULT_OUTPORT_B 4
#define HCLGE_RSS_HASH_KEY_OFFSET_B 4
#define HCLGE_RSS_HASH_KEY_NUM 16
-struct hclge_rss_config {
+struct hclge_rss_config_cmd {
u8 hash_config;
u8 rsv[7];
u8 hash_key[HCLGE_RSS_HASH_KEY_NUM];
};
-struct hclge_rss_input_tuple {
+struct hclge_rss_input_tuple_cmd {
u8 ipv4_tcp_en;
u8 ipv4_udp_en;
u8 ipv4_sctp_en;
@@ -433,7 +433,7 @@ struct hclge_rss_input_tuple {
#define HCLGE_RSS_CFG_TBL_SIZE 16
-struct hclge_rss_indirection_table {
+struct hclge_rss_indirection_table_cmd {
u16 start_table_index;
u16 rss_set_bitmap;
u8 rsv[4];
@@ -445,14 +445,14 @@ struct hclge_rss_indirection_table {
#define HCLGE_RSS_TC_SIZE_S 12
#define HCLGE_RSS_TC_SIZE_M GENMASK(14, 12)
#define HCLGE_RSS_TC_VALID_B 15
-struct hclge_rss_tc_mode {
+struct hclge_rss_tc_mode_cmd {
u16 rss_tc_mode[HCLGE_MAX_TC_NUM];
u8 rsv[8];
};
#define HCLGE_LINK_STS_B 0
#define HCLGE_LINK_STATUS BIT(HCLGE_LINK_STS_B)
-struct hclge_link_status {
+struct hclge_link_status_cmd {
u8 status;
u8 rsv[23];
};
@@ -467,7 +467,7 @@ struct hclge_promisc_param {
#define HCLGE_PROMISC_EN_UC 0x1
#define HCLGE_PROMISC_EN_MC 0x2
#define HCLGE_PROMISC_EN_BC 0x4
-struct hclge_promisc_cfg {
+struct hclge_promisc_cfg_cmd {
u8 flag;
u8 vf_id;
__le16 rsv0;
@@ -495,7 +495,7 @@ enum hclge_promisc_type {
#define HCLGE_MAC_TX_UNDER_MIN_ERR_B 21
#define HCLGE_MAC_TX_OVERSIZE_TRUNCATE_B 22
-struct hclge_config_mac_mode {
+struct hclge_config_mac_mode_cmd {
__le32 txrx_pad_fcs_loop_en;
u8 rsv[20];
};
@@ -506,7 +506,7 @@ struct hclge_config_mac_mode {
#define HCLGE_CFG_DUPLEX_B 7
#define HCLGE_CFG_DUPLEX_M BIT(HCLGE_CFG_DUPLEX_B)
-struct hclge_config_mac_speed_dup {
+struct hclge_config_mac_speed_dup_cmd {
u8 speed_dup;
#define HCLGE_CFG_MAC_SPEED_CHANGE_EN_B 0
@@ -522,7 +522,7 @@ struct hclge_config_mac_speed_dup {
#define HCLGE_QUERY_AN_M BIT(HCLGE_QUERY_AN_B)
#define HCLGE_QUERY_DUPLEX_M BIT(HCLGE_QUERY_DUPLEX_B)
-struct hclge_query_an_speed_dup {
+struct hclge_query_an_speed_dup_cmd {
u8 an_syn_dup_speed;
u8 pause;
u8 rsv[23];
@@ -539,7 +539,7 @@ struct hclge_query_an_speed_dup {
#define HCLGE_MAC_CFG_AN_EN BIT(HCLGE_MAC_CFG_AN_EN_B)
-struct hclge_config_auto_neg {
+struct hclge_config_auto_neg_cmd {
__le32 cfg_an_cmd_flag;
u8 rsv[20];
};
@@ -548,7 +548,7 @@ struct hclge_config_auto_neg {
#define HCLGE_MAC_MAX_MTU 9728
#define HCLGE_MAC_UPLINK_PORT 0x100
-struct hclge_config_max_frm_size {
+struct hclge_config_max_frm_size_cmd {
__le16 max_frm_size;
u8 rsv[22];
};
@@ -568,7 +568,7 @@ enum hclge_mac_vlan_tbl_opcode {
#define HCLGE_MAC_EPORT_VFID_M GENMASK(10, 3)
#define HCLGE_MAC_EPORT_PFID_S 0x0
#define HCLGE_MAC_EPORT_PFID_M GENMASK(2, 0)
-struct hclge_mac_vlan_tbl_entry {
+struct hclge_mac_vlan_tbl_entry_cmd {
u8 flags;
u8 resp_code;
__le16 vlan_tag;
@@ -585,13 +585,13 @@ struct hclge_mac_vlan_tbl_entry {
#define HCLGE_CFG_MTA_MAC_SEL_S 0x0
#define HCLGE_CFG_MTA_MAC_SEL_M GENMASK(1, 0)
#define HCLGE_CFG_MTA_MAC_EN_B 0x7
-struct hclge_mta_filter_mode {
+struct hclge_mta_filter_mode_cmd {
u8 dmac_sel_en; /* Use lowest 2 bit as sel_mode, bit 7 as enable */
u8 rsv[23];
};
#define HCLGE_CFG_FUNC_MTA_ACCEPT_B 0x0
-struct hclge_cfg_func_mta_filter {
+struct hclge_cfg_func_mta_filter_cmd {
u8 accept; /* Only used lowest 1 bit */
u8 function_id;
u8 rsv[22];
@@ -600,13 +600,13 @@ struct hclge_cfg_func_mta_filter {
#define HCLGE_CFG_MTA_ITEM_ACCEPT_B 0x0
#define HCLGE_CFG_MTA_ITEM_IDX_S 0x0
#define HCLGE_CFG_MTA_ITEM_IDX_M GENMASK(11, 0)
-struct hclge_cfg_func_mta_item {
+struct hclge_cfg_func_mta_item_cmd {
u16 item_idx; /* Only used lowest 12 bit */
u8 accept; /* Only used lowest 1 bit */
u8 rsv[21];
};
-struct hclge_mac_vlan_add {
+struct hclge_mac_vlan_add_cmd {
__le16 flags;
__le16 mac_addr_hi16;
__le32 mac_addr_lo32;
@@ -619,7 +619,7 @@ struct hclge_mac_vlan_add {
};
#define HNS3_MAC_VLAN_CFG_FLAG_BIT 0
-struct hclge_mac_vlan_remove {
+struct hclge_mac_vlan_remove_cmd {
__le16 flags;
__le16 mac_addr_hi16;
__le32 mac_addr_lo32;
@@ -631,20 +631,20 @@ struct hclge_mac_vlan_remove {
u8 rsv[4];
};
-struct hclge_vlan_filter_ctrl {
+struct hclge_vlan_filter_ctrl_cmd {
u8 vlan_type;
u8 vlan_fe;
u8 rsv[22];
};
-struct hclge_vlan_filter_pf_cfg {
+struct hclge_vlan_filter_pf_cfg_cmd {
u8 vlan_offset;
u8 vlan_cfg;
u8 rsv[2];
u8 vlan_offset_bitmap[20];
};
-struct hclge_vlan_filter_vf_cfg {
+struct hclge_vlan_filter_vf_cfg_cmd {
u16 vlan_id;
u8 resp_code;
u8 rsv;
@@ -653,14 +653,14 @@ struct hclge_vlan_filter_vf_cfg {
u8 vf_bitmap[16];
};
-struct hclge_cfg_com_tqp_queue {
+struct hclge_cfg_com_tqp_queue_cmd {
__le16 tqp_id;
__le16 stream_id;
u8 enable;
u8 rsv[19];
};
-struct hclge_cfg_tx_queue_pointer {
+struct hclge_cfg_tx_queue_pointer_cmd {
__le16 tqp_id;
__le16 tx_tail;
__le16 tx_head;
@@ -675,7 +675,7 @@ struct hclge_cfg_tx_queue_pointer {
#define HCLGE_TSO_MSS_MAX_S 16
#define HCLGE_TSO_MSS_MAX_M GENMASK(29, 16)
-struct hclge_cfg_tso_status {
+struct hclge_cfg_tso_status_cmd {
__le16 tso_mss_min;
__le16 tso_mss_max;
u8 rsv[20];
@@ -685,7 +685,7 @@ struct hclge_cfg_tso_status {
#define HCLGE_TSO_MSS_MAX 9668
#define HCLGE_TQP_RESET_B 0
-struct hclge_reset_tqp_queue {
+struct hclge_reset_tqp_queue_cmd {
__le16 tqp_id;
u8 reset_req;
u8 ready_to_reset;
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
index 5c1bf12..5103f23 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
@@ -820,7 +820,7 @@ static void hclge_get_stats(struct hnae3_handle *handle, u64 *data)
}
static int hclge_parse_func_status(struct hclge_dev *hdev,
- struct hclge_func_status *status)
+ struct hclge_func_status_cmd *status)
{
if (!(status->pf_state & HCLGE_PF_STATE_DONE))
return -EINVAL;
@@ -837,13 +837,13 @@ static int hclge_parse_func_status(struct hclge_dev *hdev,
static int hclge_query_function_status(struct hclge_dev *hdev)
{
- struct hclge_func_status *req;
+ struct hclge_func_status_cmd *req;
struct hclge_desc desc;
int timeout = 0;
int ret;
hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_QUERY_FUNC_STATUS, true);
- req = (struct hclge_func_status *)desc.data;
+ req = (struct hclge_func_status_cmd *)desc.data;
do {
ret = hclge_cmd_send(&hdev->hw, &desc, 1);
@@ -868,7 +868,7 @@ static int hclge_query_function_status(struct hclge_dev *hdev)
static int hclge_query_pf_resource(struct hclge_dev *hdev)
{
- struct hclge_pf_res *req;
+ struct hclge_pf_res_cmd *req;
struct hclge_desc desc;
int ret;
@@ -880,7 +880,7 @@ static int hclge_query_pf_resource(struct hclge_dev *hdev)
return ret;
}
- req = (struct hclge_pf_res *)desc.data;
+ req = (struct hclge_pf_res_cmd *)desc.data;
hdev->num_tqps = __le16_to_cpu(req->tqp_num);
hdev->pkt_buf_size = __le16_to_cpu(req->buf_size) << HCLGE_BUF_UNIT_S;
@@ -938,12 +938,12 @@ static int hclge_parse_speed(int speed_cmd, int *speed)
static void hclge_parse_cfg(struct hclge_cfg *cfg, struct hclge_desc *desc)
{
- struct hclge_cfg_param *req;
+ struct hclge_cfg_param_cmd *req;
u64 mac_addr_tmp_high;
u64 mac_addr_tmp;
int i;
- req = (struct hclge_cfg_param *)desc[0].data;
+ req = (struct hclge_cfg_param_cmd *)desc[0].data;
/* get the configuration */
cfg->vmdq_vport_num = hnae_get_field(__le32_to_cpu(req->param[0]),
@@ -978,7 +978,7 @@ static void hclge_parse_cfg(struct hclge_cfg *cfg, struct hclge_desc *desc)
for (i = 0; i < ETH_ALEN; i++)
cfg->mac_addr[i] = (mac_addr_tmp >> (8 * i)) & 0xff;
- req = (struct hclge_cfg_param *)desc[1].data;
+ req = (struct hclge_cfg_param_cmd *)desc[1].data;
cfg->numa_node_map = __le32_to_cpu(req->param[0]);
}
@@ -989,11 +989,11 @@ static void hclge_parse_cfg(struct hclge_cfg *cfg, struct hclge_desc *desc)
static int hclge_get_cfg(struct hclge_dev *hdev, struct hclge_cfg *hcfg)
{
struct hclge_desc desc[HCLGE_PF_CFG_DESC_NUM];
- struct hclge_cfg_param *req;
+ struct hclge_cfg_param_cmd *req;
int i, ret;
for (i = 0; i < HCLGE_PF_CFG_DESC_NUM; i++) {
- req = (struct hclge_cfg_param *)desc[i].data;
+ req = (struct hclge_cfg_param_cmd *)desc[i].data;
hclge_cmd_setup_basic_desc(&desc[i], HCLGE_OPC_GET_CFG_PARAM,
true);
hnae_set_field(req->offset, HCLGE_CFG_OFFSET_M,
@@ -1099,12 +1099,12 @@ static int hclge_configure(struct hclge_dev *hdev)
static int hclge_config_tso(struct hclge_dev *hdev, int tso_mss_min,
int tso_mss_max)
{
- struct hclge_cfg_tso_status *req;
+ struct hclge_cfg_tso_status_cmd *req;
struct hclge_desc desc;
hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_TSO_GENERIC_CONFIG, false);
- req = (struct hclge_cfg_tso_status *)desc.data;
+ req = (struct hclge_cfg_tso_status_cmd *)desc.data;
hnae_set_field(req->tso_mss_min, HCLGE_TSO_MSS_MIN_M,
HCLGE_TSO_MSS_MIN_S, tso_mss_min);
hnae_set_field(req->tso_mss_max, HCLGE_TSO_MSS_MIN_M,
@@ -1144,13 +1144,13 @@ static int hclge_alloc_tqps(struct hclge_dev *hdev)
static int hclge_map_tqps_to_func(struct hclge_dev *hdev, u16 func_id,
u16 tqp_pid, u16 tqp_vid, bool is_pf)
{
- struct hclge_tqp_map *req;
+ struct hclge_tqp_map_cmd *req;
struct hclge_desc desc;
int ret;
hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_SET_TQP_MAP, false);
- req = (struct hclge_tqp_map *)desc.data;
+ req = (struct hclge_tqp_map_cmd *)desc.data;
req->tqp_id = cpu_to_le16(tqp_pid);
req->tqp_vf = cpu_to_le16(func_id);
req->tqp_flag = !is_pf << HCLGE_TQP_MAP_TYPE_B |
@@ -1340,12 +1340,12 @@ static int hclge_cmd_alloc_tx_buff(struct hclge_dev *hdev,
/* TX buffer size is unit by 128 byte */
#define HCLGE_BUF_SIZE_UNIT_SHIFT 7
#define HCLGE_BUF_SIZE_UPDATE_EN_MSK BIT(15)
- struct hclge_tx_buff_alloc *req;
+ struct hclge_tx_buff_alloc_cmd *req;
struct hclge_desc desc;
int ret;
u8 i;
- req = (struct hclge_tx_buff_alloc *)desc.data;
+ req = (struct hclge_tx_buff_alloc_cmd *)desc.data;
hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_TX_BUFF_ALLOC, 0);
for (i = 0; i < HCLGE_TC_NUM; i++) {
@@ -1672,13 +1672,13 @@ int hclge_rx_buffer_calc(struct hclge_dev *hdev,
static int hclge_rx_priv_buf_alloc(struct hclge_dev *hdev,
struct hclge_pkt_buf_alloc *buf_alloc)
{
- struct hclge_rx_priv_buff *req;
+ struct hclge_rx_priv_buff_cmd *req;
struct hclge_desc desc;
int ret;
int i;
hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_RX_PRIV_BUFF_ALLOC, false);
- req = (struct hclge_rx_priv_buff *)desc.data;
+ req = (struct hclge_rx_priv_buff_cmd *)desc.data;
/* Alloc private buffer TCs */
for (i = 0; i < HCLGE_MAX_TC_NUM; i++) {
@@ -2000,11 +2000,11 @@ static void hclge_check_speed_dup(struct hclge_dev *hdev, int duplex, int speed)
int hclge_cfg_mac_speed_dup(struct hclge_dev *hdev, int speed, u8 duplex)
{
- struct hclge_config_mac_speed_dup *req;
+ struct hclge_config_mac_speed_dup_cmd *req;
struct hclge_desc desc;
int ret;
- req = (struct hclge_config_mac_speed_dup *)desc.data;
+ req = (struct hclge_config_mac_speed_dup_cmd *)desc.data;
hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_CONFIG_SPEED_DUP, false);
@@ -2075,12 +2075,12 @@ static int hclge_cfg_mac_speed_dup_h(struct hnae3_handle *handle, int speed,
static int hclge_query_mac_an_speed_dup(struct hclge_dev *hdev, int *speed,
u8 *duplex)
{
- struct hclge_query_an_speed_dup *req;
+ struct hclge_query_an_speed_dup_cmd *req;
struct hclge_desc desc;
int speed_tmp;
int ret;
- req = (struct hclge_query_an_speed_dup *)desc.data;
+ req = (struct hclge_query_an_speed_dup_cmd *)desc.data;
hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_QUERY_AN_RESULT, true);
ret = hclge_cmd_send(&hdev->hw, &desc, 1);
@@ -2108,11 +2108,11 @@ static int hclge_query_mac_an_speed_dup(struct hclge_dev *hdev, int *speed,
static int hclge_query_autoneg_result(struct hclge_dev *hdev)
{
struct hclge_mac *mac = &hdev->hw.mac;
- struct hclge_query_an_speed_dup *req;
+ struct hclge_query_an_speed_dup_cmd *req;
struct hclge_desc desc;
int ret;
- req = (struct hclge_query_an_speed_dup *)desc.data;
+ req = (struct hclge_query_an_speed_dup_cmd *)desc.data;
hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_QUERY_AN_RESULT, true);
ret = hclge_cmd_send(&hdev->hw, &desc, 1);
@@ -2129,13 +2129,13 @@ static int hclge_query_autoneg_result(struct hclge_dev *hdev)
static int hclge_set_autoneg_en(struct hclge_dev *hdev, bool enable)
{
- struct hclge_config_auto_neg *req;
+ struct hclge_config_auto_neg_cmd *req;
struct hclge_desc desc;
int ret;
hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_CONFIG_AN_MODE, false);
- req = (struct hclge_config_auto_neg *)desc.data;
+ req = (struct hclge_config_auto_neg_cmd *)desc.data;
hnae_set_bit(req->cfg_an_cmd_flag, HCLGE_MAC_CFG_AN_EN_B, !!enable);
ret = hclge_cmd_send(&hdev->hw, &desc, 1);
@@ -2214,7 +2214,7 @@ static void hclge_task_schedule(struct hclge_dev *hdev)
static int hclge_get_mac_link_status(struct hclge_dev *hdev)
{
- struct hclge_link_status *req;
+ struct hclge_link_status_cmd *req;
struct hclge_desc desc;
int link_status;
int ret;
@@ -2227,7 +2227,7 @@ static int hclge_get_mac_link_status(struct hclge_dev *hdev)
return ret;
}
- req = (struct hclge_link_status *)desc.data;
+ req = (struct hclge_link_status_cmd *)desc.data;
link_status = req->status & HCLGE_LINK_STATUS;
return !!link_status;
@@ -2451,7 +2451,7 @@ static u32 hclge_get_rss_indir_size(struct hnae3_handle *handle)
static int hclge_get_rss_algo(struct hclge_dev *hdev)
{
- struct hclge_rss_config *req;
+ struct hclge_rss_config_cmd *req;
struct hclge_desc desc;
int rss_hash_algo;
int ret;
@@ -2465,7 +2465,7 @@ static int hclge_get_rss_algo(struct hclge_dev *hdev)
return ret;
}
- req = (struct hclge_rss_config *)desc.data;
+ req = (struct hclge_rss_config_cmd *)desc.data;
rss_hash_algo = (req->hash_config & HCLGE_RSS_HASH_ALGO_MASK);
if (rss_hash_algo == HCLGE_RSS_HASH_ALGO_TOEPLITZ)
@@ -2477,13 +2477,13 @@ static int hclge_get_rss_algo(struct hclge_dev *hdev)
static int hclge_set_rss_algo_key(struct hclge_dev *hdev,
const u8 hfunc, const u8 *key)
{
- struct hclge_rss_config *req;
+ struct hclge_rss_config_cmd *req;
struct hclge_desc desc;
int key_offset;
int key_size;
int ret;
- req = (struct hclge_rss_config *)desc.data;
+ req = (struct hclge_rss_config_cmd *)desc.data;
for (key_offset = 0; key_offset < 3; key_offset++) {
hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_RSS_GENERIC_CONFIG,
@@ -2514,12 +2514,12 @@ static int hclge_set_rss_algo_key(struct hclge_dev *hdev,
static int hclge_set_rss_indir_table(struct hclge_dev *hdev, const u32 *indir)
{
- struct hclge_rss_indirection_table *req;
+ struct hclge_rss_indirection_table_cmd *req;
struct hclge_desc desc;
int i, j;
int ret;
- req = (struct hclge_rss_indirection_table *)desc.data;
+ req = (struct hclge_rss_indirection_table_cmd *)desc.data;
for (i = 0; i < HCLGE_RSS_CFG_TBL_NUM; i++) {
hclge_cmd_setup_basic_desc
@@ -2546,13 +2546,13 @@ static int hclge_set_rss_indir_table(struct hclge_dev *hdev, const u32 *indir)
static int hclge_set_rss_tc_mode(struct hclge_dev *hdev, u16 *tc_valid,
u16 *tc_size, u16 *tc_offset)
{
- struct hclge_rss_tc_mode *req;
+ struct hclge_rss_tc_mode_cmd *req;
struct hclge_desc desc;
int ret;
int i;
hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_RSS_TC_MODE, false);
- req = (struct hclge_rss_tc_mode *)desc.data;
+ req = (struct hclge_rss_tc_mode_cmd *)desc.data;
for (i = 0; i < HCLGE_MAX_TC_NUM; i++) {
hnae_set_bit(req->rss_tc_mode[i], HCLGE_RSS_TC_VALID_B,
@@ -2577,13 +2577,13 @@ static int hclge_set_rss_input_tuple(struct hclge_dev *hdev)
{
#define HCLGE_RSS_INPUT_TUPLE_OTHER 0xf
#define HCLGE_RSS_INPUT_TUPLE_SCTP 0x1f
- struct hclge_rss_input_tuple *req;
+ struct hclge_rss_input_tuple_cmd *req;
struct hclge_desc desc;
int ret;
hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_RSS_INPUT_TUPLE, false);
- req = (struct hclge_rss_input_tuple *)desc.data;
+ req = (struct hclge_rss_input_tuple_cmd *)desc.data;
req->ipv4_tcp_en = HCLGE_RSS_INPUT_TUPLE_OTHER;
req->ipv4_udp_en = HCLGE_RSS_INPUT_TUPLE_OTHER;
req->ipv4_sctp_en = HCLGE_RSS_INPUT_TUPLE_SCTP;
@@ -2750,7 +2750,7 @@ int hclge_map_vport_ring_to_vector(struct hclge_vport *vport, int vector_id,
struct hnae3_ring_chain_node *ring_chain)
{
struct hclge_dev *hdev = vport->back;
- struct hclge_ctrl_vector_chain *req;
+ struct hclge_ctrl_vector_chain_cmd *req;
struct hnae3_ring_chain_node *node;
struct hclge_desc desc;
int ret;
@@ -2758,7 +2758,7 @@ int hclge_map_vport_ring_to_vector(struct hclge_vport *vport, int vector_id,
hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_ADD_RING_TO_VECTOR, false);
- req = (struct hclge_ctrl_vector_chain *)desc.data;
+ req = (struct hclge_ctrl_vector_chain_cmd *)desc.data;
req->int_vector_id = vector_id;
i = 0;
@@ -2831,7 +2831,7 @@ static int hclge_unmap_ring_from_vector(
{
struct hclge_vport *vport = hclge_get_vport(handle);
struct hclge_dev *hdev = vport->back;
- struct hclge_ctrl_vector_chain *req;
+ struct hclge_ctrl_vector_chain_cmd *req;
struct hnae3_ring_chain_node *node;
struct hclge_desc desc;
int i, vector_id;
@@ -2846,7 +2846,7 @@ static int hclge_unmap_ring_from_vector(
hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_DEL_RING_TO_VECTOR, false);
- req = (struct hclge_ctrl_vector_chain *)desc.data;
+ req = (struct hclge_ctrl_vector_chain_cmd *)desc.data;
req->int_vector_id = vector_id;
i = 0;
@@ -2898,13 +2898,13 @@ static int hclge_unmap_ring_from_vector(
int hclge_cmd_set_promisc_mode(struct hclge_dev *hdev,
struct hclge_promisc_param *param)
{
- struct hclge_promisc_cfg *req;
+ struct hclge_promisc_cfg_cmd *req;
struct hclge_desc desc;
int ret;
hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_CFG_PROMISC_MODE, false);
- req = (struct hclge_promisc_cfg *)desc.data;
+ req = (struct hclge_promisc_cfg_cmd *)desc.data;
req->vf_id = param->vf_id;
req->flag = (param->enable << HCLGE_PROMISC_EN_B);
@@ -2946,8 +2946,8 @@ static void hclge_set_promisc_mode(struct hnae3_handle *handle, u32 en)
static void hclge_cfg_mac_mode(struct hclge_dev *hdev, bool enable)
{
struct hclge_desc desc;
- struct hclge_config_mac_mode *req =
- (struct hclge_config_mac_mode *)desc.data;
+ struct hclge_config_mac_mode_cmd *req =
+ (struct hclge_config_mac_mode_cmd *)desc.data;
int ret;
hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_CONFIG_MAC_MODE, false);
@@ -2980,8 +2980,8 @@ static int hclge_tqp_enable(struct hclge_dev *hdev, int tqp_id,
int stream_id, bool enable)
{
struct hclge_desc desc;
- struct hclge_cfg_com_tqp_queue *req =
- (struct hclge_cfg_com_tqp_queue *)desc.data;
+ struct hclge_cfg_com_tqp_queue_cmd *req =
+ (struct hclge_cfg_com_tqp_queue_cmd *)desc.data;
int ret;
hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_CFG_COM_TQP_QUEUE, false);
@@ -3174,7 +3174,7 @@ static bool hclge_is_all_function_id_zero(struct hclge_desc *desc)
return true;
}
-static void hclge_prepare_mac_addr(struct hclge_mac_vlan_tbl_entry *new_req,
+static void hclge_prepare_mac_addr(struct hclge_mac_vlan_tbl_entry_cmd *new_req,
const u8 *addr)
{
const unsigned char *mac_addr = addr;
@@ -3201,11 +3201,11 @@ static int hclge_set_mta_filter_mode(struct hclge_dev *hdev,
enum hclge_mta_dmac_sel_type mta_mac_sel,
bool enable)
{
- struct hclge_mta_filter_mode *req;
+ struct hclge_mta_filter_mode_cmd *req;
struct hclge_desc desc;
int ret;
- req = (struct hclge_mta_filter_mode *)desc.data;
+ req = (struct hclge_mta_filter_mode_cmd *)desc.data;
hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_MTA_MAC_MODE_CFG, false);
hnae_set_bit(req->dmac_sel_en, HCLGE_CFG_MTA_MAC_EN_B,
@@ -3228,11 +3228,11 @@ int hclge_cfg_func_mta_filter(struct hclge_dev *hdev,
u8 func_id,
bool enable)
{
- struct hclge_cfg_func_mta_filter *req;
+ struct hclge_cfg_func_mta_filter_cmd *req;
struct hclge_desc desc;
int ret;
- req = (struct hclge_cfg_func_mta_filter *)desc.data;
+ req = (struct hclge_cfg_func_mta_filter_cmd *)desc.data;
hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_MTA_MAC_FUNC_CFG, false);
hnae_set_bit(req->accept, HCLGE_CFG_FUNC_MTA_ACCEPT_B,
@@ -3255,11 +3255,11 @@ static int hclge_set_mta_table_item(struct hclge_vport *vport,
bool enable)
{
struct hclge_dev *hdev = vport->back;
- struct hclge_cfg_func_mta_item *req;
+ struct hclge_cfg_func_mta_item_cmd *req;
struct hclge_desc desc;
int ret;
- req = (struct hclge_cfg_func_mta_item *)desc.data;
+ req = (struct hclge_cfg_func_mta_item_cmd *)desc.data;
hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_MTA_TBL_ITEM_CFG, false);
hnae_set_bit(req->accept, HCLGE_CFG_MTA_ITEM_ACCEPT_B, enable);
@@ -3279,7 +3279,7 @@ static int hclge_set_mta_table_item(struct hclge_vport *vport,
}
static int hclge_remove_mac_vlan_tbl(struct hclge_vport *vport,
- struct hclge_mac_vlan_tbl_entry *req)
+ struct hclge_mac_vlan_tbl_entry_cmd *req)
{
struct hclge_dev *hdev = vport->back;
struct hclge_desc desc;
@@ -3288,7 +3288,7 @@ static int hclge_remove_mac_vlan_tbl(struct hclge_vport *vport,
hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_MAC_VLAN_REMOVE, false);
- memcpy(desc.data, req, sizeof(struct hclge_mac_vlan_tbl_entry));
+ memcpy(desc.data, req, sizeof(struct hclge_mac_vlan_tbl_entry_cmd));
ret = hclge_cmd_send(&hdev->hw, &desc, 1);
if (ret) {
@@ -3304,7 +3304,7 @@ static int hclge_remove_mac_vlan_tbl(struct hclge_vport *vport,
}
static int hclge_lookup_mac_vlan_tbl(struct hclge_vport *vport,
- struct hclge_mac_vlan_tbl_entry *req,
+ struct hclge_mac_vlan_tbl_entry_cmd *req,
struct hclge_desc *desc,
bool is_mc)
{
@@ -3317,7 +3317,7 @@ static int hclge_lookup_mac_vlan_tbl(struct hclge_vport *vport,
desc[0].flag |= cpu_to_le16(HCLGE_CMD_FLAG_NEXT);
memcpy(desc[0].data,
req,
- sizeof(struct hclge_mac_vlan_tbl_entry));
+ sizeof(struct hclge_mac_vlan_tbl_entry_cmd));
hclge_cmd_setup_basic_desc(&desc[1],
HCLGE_OPC_MAC_VLAN_ADD,
true);
@@ -3329,7 +3329,7 @@ static int hclge_lookup_mac_vlan_tbl(struct hclge_vport *vport,
} else {
memcpy(desc[0].data,
req,
- sizeof(struct hclge_mac_vlan_tbl_entry));
+ sizeof(struct hclge_mac_vlan_tbl_entry_cmd));
ret = hclge_cmd_send(&hdev->hw, desc, 1);
}
if (ret) {
@@ -3345,7 +3345,7 @@ static int hclge_lookup_mac_vlan_tbl(struct hclge_vport *vport,
}
static int hclge_add_mac_vlan_tbl(struct hclge_vport *vport,
- struct hclge_mac_vlan_tbl_entry *req,
+ struct hclge_mac_vlan_tbl_entry_cmd *req,
struct hclge_desc *mc_desc)
{
struct hclge_dev *hdev = vport->back;
@@ -3359,7 +3359,8 @@ static int hclge_add_mac_vlan_tbl(struct hclge_vport *vport,
hclge_cmd_setup_basic_desc(&desc,
HCLGE_OPC_MAC_VLAN_ADD,
false);
- memcpy(desc.data, req, sizeof(struct hclge_mac_vlan_tbl_entry));
+ memcpy(desc.data, req,
+ sizeof(struct hclge_mac_vlan_tbl_entry_cmd));
ret = hclge_cmd_send(&hdev->hw, &desc, 1);
resp_code = (desc.data[0] >> 8) & 0xff;
cfg_status = hclge_get_mac_vlan_cmd_status(vport, desc.retval,
@@ -3373,7 +3374,7 @@ static int hclge_add_mac_vlan_tbl(struct hclge_vport *vport,
mc_desc[2].flag &= cpu_to_le16(~HCLGE_CMD_FLAG_WR);
mc_desc[2].flag &= cpu_to_le16(~HCLGE_CMD_FLAG_NEXT);
memcpy(mc_desc[0].data, req,
- sizeof(struct hclge_mac_vlan_tbl_entry));
+ sizeof(struct hclge_mac_vlan_tbl_entry_cmd));
ret = hclge_cmd_send(&hdev->hw, mc_desc, 3);
resp_code = (mc_desc[0].data[0] >> 8) & 0xff;
cfg_status = hclge_get_mac_vlan_cmd_status(vport,
@@ -3404,7 +3405,7 @@ int hclge_add_uc_addr_common(struct hclge_vport *vport,
const unsigned char *addr)
{
struct hclge_dev *hdev = vport->back;
- struct hclge_mac_vlan_tbl_entry req;
+ struct hclge_mac_vlan_tbl_entry_cmd req;
enum hclge_cmd_status status;
/* mac addr check */
@@ -3454,7 +3455,7 @@ int hclge_rm_uc_addr_common(struct hclge_vport *vport,
const unsigned char *addr)
{
struct hclge_dev *hdev = vport->back;
- struct hclge_mac_vlan_tbl_entry req;
+ struct hclge_mac_vlan_tbl_entry_cmd req;
enum hclge_cmd_status status;
/* mac addr check */
@@ -3488,7 +3489,7 @@ int hclge_add_mc_addr_common(struct hclge_vport *vport,
const unsigned char *addr)
{
struct hclge_dev *hdev = vport->back;
- struct hclge_mac_vlan_tbl_entry req;
+ struct hclge_mac_vlan_tbl_entry_cmd req;
struct hclge_desc desc[3];
u16 tbl_idx;
int status;
@@ -3539,7 +3540,7 @@ int hclge_rm_mc_addr_common(struct hclge_vport *vport,
const unsigned char *addr)
{
struct hclge_dev *hdev = vport->back;
- struct hclge_mac_vlan_tbl_entry req;
+ struct hclge_mac_vlan_tbl_entry_cmd req;
enum hclge_cmd_status status;
struct hclge_desc desc[3];
u16 tbl_idx;
@@ -3622,13 +3623,13 @@ static int hclge_set_mac_addr(struct hnae3_handle *handle, void *p)
static int hclge_set_vlan_filter_ctrl(struct hclge_dev *hdev, u8 vlan_type,
bool filter_en)
{
- struct hclge_vlan_filter_ctrl *req;
+ struct hclge_vlan_filter_ctrl_cmd *req;
struct hclge_desc desc;
int ret;
hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_VLAN_FILTER_CTRL, false);
- req = (struct hclge_vlan_filter_ctrl *)desc.data;
+ req = (struct hclge_vlan_filter_ctrl_cmd *)desc.data;
req->vlan_type = vlan_type;
req->vlan_fe = filter_en;
@@ -3646,8 +3647,8 @@ int hclge_set_vf_vlan_common(struct hclge_dev *hdev, int vfid,
bool is_kill, u16 vlan, u8 qos, __be16 proto)
{
#define HCLGE_MAX_VF_BYTES 16
- struct hclge_vlan_filter_vf_cfg *req0;
- struct hclge_vlan_filter_vf_cfg *req1;
+ struct hclge_vlan_filter_vf_cfg_cmd *req0;
+ struct hclge_vlan_filter_vf_cfg_cmd *req1;
struct hclge_desc desc[2];
u8 vf_byte_val;
u8 vf_byte_off;
@@ -3663,8 +3664,8 @@ int hclge_set_vf_vlan_common(struct hclge_dev *hdev, int vfid,
vf_byte_off = vfid / 8;
vf_byte_val = 1 << (vfid % 8);
- req0 = (struct hclge_vlan_filter_vf_cfg *)desc[0].data;
- req1 = (struct hclge_vlan_filter_vf_cfg *)desc[1].data;
+ req0 = (struct hclge_vlan_filter_vf_cfg_cmd *)desc[0].data;
+ req1 = (struct hclge_vlan_filter_vf_cfg_cmd *)desc[1].data;
req0->vlan_id = vlan;
req0->vlan_cfg = is_kill;
@@ -3707,7 +3708,7 @@ static int hclge_set_port_vlan_filter(struct hnae3_handle *handle,
{
struct hclge_vport *vport = hclge_get_vport(handle);
struct hclge_dev *hdev = vport->back;
- struct hclge_vlan_filter_pf_cfg *req;
+ struct hclge_vlan_filter_pf_cfg_cmd *req;
struct hclge_desc desc;
u8 vlan_offset_byte_val;
u8 vlan_offset_byte;
@@ -3720,7 +3721,7 @@ static int hclge_set_port_vlan_filter(struct hnae3_handle *handle,
vlan_offset_byte = (vlan_id % 160) / 8;
vlan_offset_byte_val = 1 << (vlan_id % 8);
- req = (struct hclge_vlan_filter_pf_cfg *)desc.data;
+ req = (struct hclge_vlan_filter_pf_cfg_cmd *)desc.data;
req->vlan_offset = vlan_offset_160;
req->vlan_cfg = is_kill;
req->vlan_offset_bitmap[vlan_offset_byte] = vlan_offset_byte_val;
@@ -3782,7 +3783,7 @@ static int hclge_init_vlan_config(struct hclge_dev *hdev)
static int hclge_set_mtu(struct hnae3_handle *handle, int new_mtu)
{
struct hclge_vport *vport = hclge_get_vport(handle);
- struct hclge_config_max_frm_size *req;
+ struct hclge_config_max_frm_size_cmd *req;
struct hclge_dev *hdev = vport->back;
struct hclge_desc desc;
int ret;
@@ -3793,7 +3794,7 @@ static int hclge_set_mtu(struct hnae3_handle *handle, int new_mtu)
hdev->mps = new_mtu;
hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_CONFIG_MAX_FRM_SIZE, false);
- req = (struct hclge_config_max_frm_size *)desc.data;
+ req = (struct hclge_config_max_frm_size_cmd *)desc.data;
req->max_frm_size = cpu_to_le16(new_mtu);
ret = hclge_cmd_send(&hdev->hw, &desc, 1);
@@ -3808,13 +3809,13 @@ static int hclge_set_mtu(struct hnae3_handle *handle, int new_mtu)
static int hclge_send_reset_tqp_cmd(struct hclge_dev *hdev, u16 queue_id,
bool enable)
{
- struct hclge_reset_tqp_queue *req;
+ struct hclge_reset_tqp_queue_cmd *req;
struct hclge_desc desc;
int ret;
hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_RESET_TQP_QUEUE, false);
- req = (struct hclge_reset_tqp_queue *)desc.data;
+ req = (struct hclge_reset_tqp_queue_cmd *)desc.data;
req->tqp_id = cpu_to_le16(queue_id & HCLGE_RING_ID_MASK);
hnae_set_bit(req->reset_req, HCLGE_TQP_RESET_B, enable);
@@ -3830,13 +3831,13 @@ static int hclge_send_reset_tqp_cmd(struct hclge_dev *hdev, u16 queue_id,
static int hclge_get_reset_status(struct hclge_dev *hdev, u16 queue_id)
{
- struct hclge_reset_tqp_queue *req;
+ struct hclge_reset_tqp_queue_cmd *req;
struct hclge_desc desc;
int ret;
hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_RESET_TQP_QUEUE, true);
- req = (struct hclge_reset_tqp_queue *)desc.data;
+ req = (struct hclge_reset_tqp_queue_cmd *)desc.data;
req->tqp_id = cpu_to_le16(queue_id & HCLGE_RING_ID_MASK);
ret = hclge_cmd_send(&hdev->hw, &desc, 1);
--
1.9.1
^ permalink raw reply related
* [PATCH net-next 6/7] net: hns3: Cleanup for endian issue in hns3 driver
From: Yunsheng Lin @ 2017-10-09 7:44 UTC (permalink / raw)
To: davem
Cc: huangdaode, xuwei5, liguozhu, Yisen.Zhuang, gabriele.paoloni,
john.garry, linuxarm, yisen.zhuang, salil.mehta, lipeng321,
netdev, linux-kernel
In-Reply-To: <1507535041-204956-1-git-send-email-linyunsheng@huawei.com>
This patch fixes a lot of endian issues detected by sparse.
Signed-off-by: Yunsheng Lin <linyunsheng@huawei.com>
---
.../net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c | 8 +-
.../net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h | 10 +-
.../ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 206 ++++++++++++---------
.../net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c | 26 ++-
.../net/ethernet/hisilicon/hns3/hns3pf/hns3_enet.c | 4 +-
5 files changed, 145 insertions(+), 109 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c
index 648b64b..05985d8 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c
@@ -208,7 +208,7 @@ int hclge_cmd_send(struct hclge_hw *hw, struct hclge_desc *desc, int num)
* which will be use for hardware to write back
*/
ntc = hw->cmq.csq.next_to_use;
- opcode = desc[0].opcode;
+ opcode = le16_to_cpu(desc[0].opcode);
while (handle < num) {
desc_to_use = &hw->cmq.csq.desc[hw->cmq.csq.next_to_use];
*desc_to_use = desc[handle];
@@ -225,7 +225,7 @@ int hclge_cmd_send(struct hclge_hw *hw, struct hclge_desc *desc, int num)
* If the command is sync, wait for the firmware to write back,
* if multi descriptors to be sent, use the first one to check
*/
- if (HCLGE_SEND_SYNC(desc->flag)) {
+ if (HCLGE_SEND_SYNC(le16_to_cpu(desc->flag))) {
do {
if (hclge_cmd_csq_done(hw))
break;
@@ -244,9 +244,9 @@ int hclge_cmd_send(struct hclge_hw *hw, struct hclge_desc *desc, int num)
pr_debug("Get cmd desc:\n");
if (likely(!hclge_is_special_opcode(opcode)))
- desc_ret = desc[handle].retval;
+ desc_ret = le16_to_cpu(desc[handle].retval);
else
- desc_ret = desc[0].retval;
+ desc_ret = le16_to_cpu(desc[0].retval);
if ((enum hclge_cmd_return_status)desc_ret ==
HCLGE_CMD_EXEC_SUCCESS)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h
index d2ff0e3..8f3ba02a 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h
@@ -434,8 +434,8 @@ struct hclge_rss_input_tuple_cmd {
#define HCLGE_RSS_CFG_TBL_SIZE 16
struct hclge_rss_indirection_table_cmd {
- u16 start_table_index;
- u16 rss_set_bitmap;
+ __le16 start_table_index;
+ __le16 rss_set_bitmap;
u8 rsv[4];
u8 rss_result[HCLGE_RSS_CFG_TBL_SIZE];
};
@@ -446,7 +446,7 @@ struct hclge_rss_indirection_table_cmd {
#define HCLGE_RSS_TC_SIZE_M GENMASK(14, 12)
#define HCLGE_RSS_TC_VALID_B 15
struct hclge_rss_tc_mode_cmd {
- u16 rss_tc_mode[HCLGE_MAX_TC_NUM];
+ __le16 rss_tc_mode[HCLGE_MAX_TC_NUM];
u8 rsv[8];
};
@@ -601,7 +601,7 @@ struct hclge_cfg_func_mta_filter_cmd {
#define HCLGE_CFG_MTA_ITEM_IDX_S 0x0
#define HCLGE_CFG_MTA_ITEM_IDX_M GENMASK(11, 0)
struct hclge_cfg_func_mta_item_cmd {
- u16 item_idx; /* Only used lowest 12 bit */
+ __le16 item_idx; /* Only used lowest 12 bit */
u8 accept; /* Only used lowest 1 bit */
u8 rsv[21];
};
@@ -645,7 +645,7 @@ struct hclge_vlan_filter_pf_cfg_cmd {
};
struct hclge_vlan_filter_vf_cfg_cmd {
- u16 vlan_id;
+ __le16 vlan_id;
u8 resp_code;
u8 rsv;
u8 vlan_cfg;
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
index 5103f23..6115c2f 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
@@ -362,7 +362,7 @@ static int hclge_64_bit_update_stats(struct hclge_dev *hdev)
#define HCLGE_64_BIT_RTN_DATANUM 4
u64 *data = (u64 *)(&hdev->hw_stats.all_64_bit_stats);
struct hclge_desc desc[HCLGE_64_BIT_CMD_NUM];
- u64 *desc_data;
+ __le64 *desc_data;
int i, k, n;
int ret;
@@ -376,14 +376,14 @@ static int hclge_64_bit_update_stats(struct hclge_dev *hdev)
for (i = 0; i < HCLGE_64_BIT_CMD_NUM; i++) {
if (unlikely(i == 0)) {
- desc_data = (u64 *)(&desc[i].data[0]);
+ desc_data = (__le64 *)(&desc[i].data[0]);
n = HCLGE_64_BIT_RTN_DATANUM - 1;
} else {
- desc_data = (u64 *)(&desc[i]);
+ desc_data = (__le64 *)(&desc[i]);
n = HCLGE_64_BIT_RTN_DATANUM;
}
for (k = 0; k < n; k++) {
- *data++ += cpu_to_le64(*desc_data);
+ *data++ += le64_to_cpu(*desc_data);
desc_data++;
}
}
@@ -411,7 +411,7 @@ static int hclge_32_bit_update_stats(struct hclge_dev *hdev)
struct hclge_desc desc[HCLGE_32_BIT_CMD_NUM];
struct hclge_32_bit_stats *all_32_bit_stats;
- u32 *desc_data;
+ __le32 *desc_data;
int i, k, n;
u64 *data;
int ret;
@@ -431,21 +431,27 @@ static int hclge_32_bit_update_stats(struct hclge_dev *hdev)
hclge_reset_partial_32bit_counter(all_32_bit_stats);
for (i = 0; i < HCLGE_32_BIT_CMD_NUM; i++) {
if (unlikely(i == 0)) {
+ __le16 *desc_data_16bit;
+
all_32_bit_stats->igu_rx_err_pkt +=
- cpu_to_le32(desc[i].data[0]);
+ le32_to_cpu(desc[i].data[0]);
+
+ desc_data_16bit = (__le16 *)&desc[i].data[1];
all_32_bit_stats->igu_rx_no_eof_pkt +=
- cpu_to_le32(desc[i].data[1] & 0xffff);
+ le16_to_cpu(*desc_data_16bit);
+
+ desc_data_16bit++;
all_32_bit_stats->igu_rx_no_sof_pkt +=
- cpu_to_le32((desc[i].data[1] >> 16) & 0xffff);
+ le16_to_cpu(*desc_data_16bit);
- desc_data = (u32 *)(&desc[i].data[2]);
+ desc_data = &desc[i].data[2];
n = HCLGE_32_BIT_RTN_DATANUM - 4;
} else {
- desc_data = (u32 *)(&desc[i]);
+ desc_data = (__le32 *)&desc[i];
n = HCLGE_32_BIT_RTN_DATANUM;
}
for (k = 0; k < n; k++) {
- *data++ += cpu_to_le32(*desc_data);
+ *data++ += le32_to_cpu(*desc_data);
desc_data++;
}
}
@@ -460,7 +466,7 @@ static int hclge_mac_update_stats(struct hclge_dev *hdev)
u64 *data = (u64 *)(&hdev->hw_stats.mac_stats);
struct hclge_desc desc[HCLGE_MAC_CMD_NUM];
- u64 *desc_data;
+ __le64 *desc_data;
int i, k, n;
int ret;
@@ -475,14 +481,14 @@ static int hclge_mac_update_stats(struct hclge_dev *hdev)
for (i = 0; i < HCLGE_MAC_CMD_NUM; i++) {
if (unlikely(i == 0)) {
- desc_data = (u64 *)(&desc[i].data[0]);
+ desc_data = (__le64 *)(&desc[i].data[0]);
n = HCLGE_RTN_DATA_NUM - 2;
} else {
- desc_data = (u64 *)(&desc[i]);
+ desc_data = (__le64 *)(&desc[i]);
n = HCLGE_RTN_DATA_NUM;
}
for (k = 0; k < n; k++) {
- *data++ += cpu_to_le64(*desc_data);
+ *data++ += le64_to_cpu(*desc_data);
desc_data++;
}
}
@@ -508,7 +514,7 @@ static int hclge_tqps_update_stats(struct hnae3_handle *handle)
HCLGE_OPC_QUERY_RX_STATUS,
true);
- desc[0].data[0] = (tqp->index & 0x1ff);
+ desc[0].data[0] = cpu_to_le32((tqp->index & 0x1ff));
ret = hclge_cmd_send(&hdev->hw, desc, 1);
if (ret) {
dev_err(&hdev->pdev->dev,
@@ -517,7 +523,7 @@ static int hclge_tqps_update_stats(struct hnae3_handle *handle)
return ret;
}
tqp->tqp_stats.rcb_rx_ring_pktnum_rcd +=
- cpu_to_le32(desc[0].data[4]);
+ le32_to_cpu(desc[0].data[4]);
}
for (i = 0; i < kinfo->num_tqps; i++) {
@@ -528,7 +534,7 @@ static int hclge_tqps_update_stats(struct hnae3_handle *handle)
HCLGE_OPC_QUERY_TX_STATUS,
true);
- desc[0].data[0] = (tqp->index & 0x1ff);
+ desc[0].data[0] = cpu_to_le32((tqp->index & 0x1ff));
ret = hclge_cmd_send(&hdev->hw, desc, 1);
if (ret) {
dev_err(&hdev->pdev->dev,
@@ -537,7 +543,7 @@ static int hclge_tqps_update_stats(struct hnae3_handle *handle)
return ret;
}
tqp->tqp_stats.rcb_tx_ring_pktnum_rcd +=
- cpu_to_le32(desc[0].data[4]);
+ le32_to_cpu(desc[0].data[4]);
}
return 0;
@@ -552,12 +558,12 @@ static u64 *hclge_tqps_get_stats(struct hnae3_handle *handle, u64 *data)
for (i = 0; i < kinfo->num_tqps; i++) {
tqp = container_of(kinfo->tqp[i], struct hclge_tqp, q);
- *buff++ = cpu_to_le64(tqp->tqp_stats.rcb_tx_ring_pktnum_rcd);
+ *buff++ = tqp->tqp_stats.rcb_tx_ring_pktnum_rcd;
}
for (i = 0; i < kinfo->num_tqps; i++) {
tqp = container_of(kinfo->tqp[i], struct hclge_tqp, q);
- *buff++ = cpu_to_le64(tqp->tqp_stats.rcb_rx_ring_pktnum_rcd);
+ *buff++ = tqp->tqp_stats.rcb_rx_ring_pktnum_rcd;
}
return buff;
@@ -993,16 +999,17 @@ static int hclge_get_cfg(struct hclge_dev *hdev, struct hclge_cfg *hcfg)
int i, ret;
for (i = 0; i < HCLGE_PF_CFG_DESC_NUM; i++) {
+ u32 offset = 0;
+
req = (struct hclge_cfg_param_cmd *)desc[i].data;
hclge_cmd_setup_basic_desc(&desc[i], HCLGE_OPC_GET_CFG_PARAM,
true);
- hnae_set_field(req->offset, HCLGE_CFG_OFFSET_M,
+ hnae_set_field(offset, HCLGE_CFG_OFFSET_M,
HCLGE_CFG_OFFSET_S, i * HCLGE_CFG_RD_LEN_BYTES);
/* Len should be united by 4 bytes when send to hardware */
- hnae_set_field(req->offset, HCLGE_CFG_RD_LEN_M,
- HCLGE_CFG_RD_LEN_S,
+ hnae_set_field(offset, HCLGE_CFG_RD_LEN_M, HCLGE_CFG_RD_LEN_S,
HCLGE_CFG_RD_LEN_BYTES / HCLGE_CFG_RD_LEN_UNIT);
- req->offset = cpu_to_le32(req->offset);
+ req->offset = cpu_to_le32(offset);
}
ret = hclge_cmd_send(&hdev->hw, desc, HCLGE_PF_CFG_DESC_NUM);
@@ -1101,14 +1108,21 @@ static int hclge_config_tso(struct hclge_dev *hdev, int tso_mss_min,
{
struct hclge_cfg_tso_status_cmd *req;
struct hclge_desc desc;
+ u16 tso_mss;
hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_TSO_GENERIC_CONFIG, false);
req = (struct hclge_cfg_tso_status_cmd *)desc.data;
- hnae_set_field(req->tso_mss_min, HCLGE_TSO_MSS_MIN_M,
+
+ tso_mss = 0;
+ hnae_set_field(tso_mss, HCLGE_TSO_MSS_MIN_M,
HCLGE_TSO_MSS_MIN_S, tso_mss_min);
- hnae_set_field(req->tso_mss_max, HCLGE_TSO_MSS_MIN_M,
+ req->tso_mss_min = cpu_to_le16(tso_mss);
+
+ tso_mss = 0;
+ hnae_set_field(tso_mss, HCLGE_TSO_MSS_MIN_M,
HCLGE_TSO_MSS_MIN_S, tso_mss_max);
+ req->tso_mss_max = cpu_to_le16(tso_mss);
return hclge_cmd_send(&hdev->hw, &desc, 1);
}
@@ -1152,7 +1166,7 @@ static int hclge_map_tqps_to_func(struct hclge_dev *hdev, u16 func_id,
req = (struct hclge_tqp_map_cmd *)desc.data;
req->tqp_id = cpu_to_le16(tqp_pid);
- req->tqp_vf = cpu_to_le16(func_id);
+ req->tqp_vf = func_id;
req->tqp_flag = !is_pf << HCLGE_TQP_MAP_TYPE_B |
1 << HCLGE_TQP_MAP_EN_B;
req->tqp_vid = cpu_to_le16(tqp_vid);
@@ -2131,12 +2145,14 @@ static int hclge_set_autoneg_en(struct hclge_dev *hdev, bool enable)
{
struct hclge_config_auto_neg_cmd *req;
struct hclge_desc desc;
+ u32 flag = 0;
int ret;
hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_CONFIG_AN_MODE, false);
req = (struct hclge_config_auto_neg_cmd *)desc.data;
- hnae_set_bit(req->cfg_an_cmd_flag, HCLGE_MAC_CFG_AN_EN_B, !!enable);
+ hnae_set_bit(flag, HCLGE_MAC_CFG_AN_EN_B, !!enable);
+ req->cfg_an_cmd_flag = cpu_to_le32(flag);
ret = hclge_cmd_send(&hdev->hw, &desc, 1);
if (ret) {
@@ -2525,8 +2541,9 @@ static int hclge_set_rss_indir_table(struct hclge_dev *hdev, const u32 *indir)
hclge_cmd_setup_basic_desc
(&desc, HCLGE_OPC_RSS_INDIR_TABLE, false);
- req->start_table_index = i * HCLGE_RSS_CFG_TBL_SIZE;
- req->rss_set_bitmap = HCLGE_RSS_SET_BITMAP_MSK;
+ req->start_table_index =
+ cpu_to_le16(i * HCLGE_RSS_CFG_TBL_SIZE);
+ req->rss_set_bitmap = cpu_to_le16(HCLGE_RSS_SET_BITMAP_MSK);
for (j = 0; j < HCLGE_RSS_CFG_TBL_SIZE; j++)
req->rss_result[j] =
@@ -2555,12 +2572,15 @@ static int hclge_set_rss_tc_mode(struct hclge_dev *hdev, u16 *tc_valid,
req = (struct hclge_rss_tc_mode_cmd *)desc.data;
for (i = 0; i < HCLGE_MAX_TC_NUM; i++) {
- hnae_set_bit(req->rss_tc_mode[i], HCLGE_RSS_TC_VALID_B,
- (tc_valid[i] & 0x1));
- hnae_set_field(req->rss_tc_mode[i], HCLGE_RSS_TC_SIZE_M,
+ u16 mode = 0;
+
+ hnae_set_bit(mode, HCLGE_RSS_TC_VALID_B, (tc_valid[i] & 0x1));
+ hnae_set_field(mode, HCLGE_RSS_TC_SIZE_M,
HCLGE_RSS_TC_SIZE_S, tc_size[i]);
- hnae_set_field(req->rss_tc_mode[i], HCLGE_RSS_TC_OFFSET_M,
+ hnae_set_field(mode, HCLGE_RSS_TC_OFFSET_M,
HCLGE_RSS_TC_OFFSET_S, tc_offset[i]);
+
+ req->rss_tc_mode[i] = cpu_to_le16(mode);
}
ret = hclge_cmd_send(&hdev->hw, &desc, 1);
@@ -2763,15 +2783,16 @@ int hclge_map_vport_ring_to_vector(struct hclge_vport *vport, int vector_id,
i = 0;
for (node = ring_chain; node; node = node->next) {
- hnae_set_field(req->tqp_type_and_id[i], HCLGE_INT_TYPE_M,
- HCLGE_INT_TYPE_S,
+ u16 type_and_id = 0;
+
+ hnae_set_field(type_and_id, HCLGE_INT_TYPE_M, HCLGE_INT_TYPE_S,
hnae_get_bit(node->flag, HNAE3_RING_TYPE_B));
- hnae_set_field(req->tqp_type_and_id[i], HCLGE_TQP_ID_M,
- HCLGE_TQP_ID_S, node->tqp_index);
- hnae_set_field(req->tqp_type_and_id[i], HCLGE_INT_GL_IDX_M,
+ hnae_set_field(type_and_id, HCLGE_TQP_ID_M, HCLGE_TQP_ID_S,
+ node->tqp_index);
+ hnae_set_field(type_and_id, HCLGE_INT_GL_IDX_M,
HCLGE_INT_GL_IDX_S,
hnae_get_bit(node->flag, HNAE3_RING_TYPE_B));
- req->tqp_type_and_id[i] = cpu_to_le16(req->tqp_type_and_id[i]);
+ req->tqp_type_and_id[i] = cpu_to_le16(type_and_id);
req->vfid = vport->vport_id;
if (++i >= HCLGE_VECTOR_ELEMENTS_PER_CMD) {
@@ -2851,16 +2872,17 @@ static int hclge_unmap_ring_from_vector(
i = 0;
for (node = ring_chain; node; node = node->next) {
- hnae_set_field(req->tqp_type_and_id[i], HCLGE_INT_TYPE_M,
- HCLGE_INT_TYPE_S,
+ u16 type_and_id = 0;
+
+ hnae_set_field(type_and_id, HCLGE_INT_TYPE_M, HCLGE_INT_TYPE_S,
hnae_get_bit(node->flag, HNAE3_RING_TYPE_B));
- hnae_set_field(req->tqp_type_and_id[i], HCLGE_TQP_ID_M,
- HCLGE_TQP_ID_S, node->tqp_index);
- hnae_set_field(req->tqp_type_and_id[i], HCLGE_INT_GL_IDX_M,
+ hnae_set_field(type_and_id, HCLGE_TQP_ID_M, HCLGE_TQP_ID_S,
+ node->tqp_index);
+ hnae_set_field(type_and_id, HCLGE_INT_GL_IDX_M,
HCLGE_INT_GL_IDX_S,
hnae_get_bit(node->flag, HNAE3_RING_TYPE_B));
- req->tqp_type_and_id[i] = cpu_to_le16(req->tqp_type_and_id[i]);
+ req->tqp_type_and_id[i] = cpu_to_le16(type_and_id);
req->vfid = vport->vport_id;
if (++i >= HCLGE_VECTOR_ELEMENTS_PER_CMD) {
@@ -2948,27 +2970,25 @@ static void hclge_cfg_mac_mode(struct hclge_dev *hdev, bool enable)
struct hclge_desc desc;
struct hclge_config_mac_mode_cmd *req =
(struct hclge_config_mac_mode_cmd *)desc.data;
+ u32 loop_en = 0;
int ret;
hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_CONFIG_MAC_MODE, false);
- hnae_set_bit(req->txrx_pad_fcs_loop_en, HCLGE_MAC_TX_EN_B, enable);
- hnae_set_bit(req->txrx_pad_fcs_loop_en, HCLGE_MAC_RX_EN_B, enable);
- hnae_set_bit(req->txrx_pad_fcs_loop_en, HCLGE_MAC_PAD_TX_B, enable);
- hnae_set_bit(req->txrx_pad_fcs_loop_en, HCLGE_MAC_PAD_RX_B, enable);
- hnae_set_bit(req->txrx_pad_fcs_loop_en, HCLGE_MAC_1588_TX_B, 0);
- hnae_set_bit(req->txrx_pad_fcs_loop_en, HCLGE_MAC_1588_RX_B, 0);
- hnae_set_bit(req->txrx_pad_fcs_loop_en, HCLGE_MAC_APP_LP_B, 0);
- hnae_set_bit(req->txrx_pad_fcs_loop_en, HCLGE_MAC_LINE_LP_B, 0);
- hnae_set_bit(req->txrx_pad_fcs_loop_en, HCLGE_MAC_FCS_TX_B, enable);
- hnae_set_bit(req->txrx_pad_fcs_loop_en, HCLGE_MAC_RX_FCS_B, enable);
- hnae_set_bit(req->txrx_pad_fcs_loop_en,
- HCLGE_MAC_RX_FCS_STRIP_B, enable);
- hnae_set_bit(req->txrx_pad_fcs_loop_en,
- HCLGE_MAC_TX_OVERSIZE_TRUNCATE_B, enable);
- hnae_set_bit(req->txrx_pad_fcs_loop_en,
- HCLGE_MAC_RX_OVERSIZE_TRUNCATE_B, enable);
- hnae_set_bit(req->txrx_pad_fcs_loop_en,
- HCLGE_MAC_TX_UNDER_MIN_ERR_B, enable);
+ hnae_set_bit(loop_en, HCLGE_MAC_TX_EN_B, enable);
+ hnae_set_bit(loop_en, HCLGE_MAC_RX_EN_B, enable);
+ hnae_set_bit(loop_en, HCLGE_MAC_PAD_TX_B, enable);
+ hnae_set_bit(loop_en, HCLGE_MAC_PAD_RX_B, enable);
+ hnae_set_bit(loop_en, HCLGE_MAC_1588_TX_B, 0);
+ hnae_set_bit(loop_en, HCLGE_MAC_1588_RX_B, 0);
+ hnae_set_bit(loop_en, HCLGE_MAC_APP_LP_B, 0);
+ hnae_set_bit(loop_en, HCLGE_MAC_LINE_LP_B, 0);
+ hnae_set_bit(loop_en, HCLGE_MAC_FCS_TX_B, enable);
+ hnae_set_bit(loop_en, HCLGE_MAC_RX_FCS_B, enable);
+ hnae_set_bit(loop_en, HCLGE_MAC_RX_FCS_STRIP_B, enable);
+ hnae_set_bit(loop_en, HCLGE_MAC_TX_OVERSIZE_TRUNCATE_B, enable);
+ hnae_set_bit(loop_en, HCLGE_MAC_RX_OVERSIZE_TRUNCATE_B, enable);
+ hnae_set_bit(loop_en, HCLGE_MAC_TX_UNDER_MIN_ERR_B, enable);
+ req->txrx_pad_fcs_loop_en = cpu_to_le32(loop_en);
ret = hclge_cmd_send(&hdev->hw, &desc, 1);
if (ret)
@@ -3145,16 +3165,16 @@ static int hclge_update_desc_vfid(struct hclge_desc *desc, int vfid, bool clr)
word_num = vfid / 32;
bit_num = vfid % 32;
if (clr)
- desc[1].data[word_num] &= ~(1 << bit_num);
+ desc[1].data[word_num] &= cpu_to_le32(~(1 << bit_num));
else
- desc[1].data[word_num] |= (1 << bit_num);
+ desc[1].data[word_num] |= cpu_to_le32(1 << bit_num);
} else {
word_num = (vfid - 192) / 32;
bit_num = vfid % 32;
if (clr)
- desc[2].data[word_num] &= ~(1 << bit_num);
+ desc[2].data[word_num] &= cpu_to_le32(~(1 << bit_num));
else
- desc[2].data[word_num] |= (1 << bit_num);
+ desc[2].data[word_num] |= cpu_to_le32(1 << bit_num);
}
return 0;
@@ -3257,15 +3277,16 @@ static int hclge_set_mta_table_item(struct hclge_vport *vport,
struct hclge_dev *hdev = vport->back;
struct hclge_cfg_func_mta_item_cmd *req;
struct hclge_desc desc;
+ u16 item_idx = 0;
int ret;
req = (struct hclge_cfg_func_mta_item_cmd *)desc.data;
hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_MTA_TBL_ITEM_CFG, false);
hnae_set_bit(req->accept, HCLGE_CFG_MTA_ITEM_ACCEPT_B, enable);
- hnae_set_field(req->item_idx, HCLGE_CFG_MTA_ITEM_IDX_M,
+ hnae_set_field(item_idx, HCLGE_CFG_MTA_ITEM_IDX_M,
HCLGE_CFG_MTA_ITEM_IDX_S, idx);
- req->item_idx = cpu_to_le16(req->item_idx);
+ req->item_idx = cpu_to_le16(item_idx);
ret = hclge_cmd_send(&hdev->hw, &desc, 1);
if (ret) {
@@ -3284,6 +3305,7 @@ static int hclge_remove_mac_vlan_tbl(struct hclge_vport *vport,
struct hclge_dev *hdev = vport->back;
struct hclge_desc desc;
u8 resp_code;
+ u16 retval;
int ret;
hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_MAC_VLAN_REMOVE, false);
@@ -3297,9 +3319,10 @@ static int hclge_remove_mac_vlan_tbl(struct hclge_vport *vport,
ret);
return ret;
}
- resp_code = (desc.data[0] >> 8) & 0xff;
+ resp_code = (le32_to_cpu(desc.data[0]) >> 8) & 0xff;
+ retval = le16_to_cpu(desc.retval);
- return hclge_get_mac_vlan_cmd_status(vport, desc.retval, resp_code,
+ return hclge_get_mac_vlan_cmd_status(vport, retval, resp_code,
HCLGE_MAC_VLAN_REMOVE);
}
@@ -3310,6 +3333,7 @@ static int hclge_lookup_mac_vlan_tbl(struct hclge_vport *vport,
{
struct hclge_dev *hdev = vport->back;
u8 resp_code;
+ u16 retval;
int ret;
hclge_cmd_setup_basic_desc(&desc[0], HCLGE_OPC_MAC_VLAN_ADD, true);
@@ -3338,9 +3362,10 @@ static int hclge_lookup_mac_vlan_tbl(struct hclge_vport *vport,
ret);
return ret;
}
- resp_code = (desc[0].data[0] >> 8) & 0xff;
+ resp_code = (le32_to_cpu(desc[0].data[0]) >> 8) & 0xff;
+ retval = le16_to_cpu(desc[0].retval);
- return hclge_get_mac_vlan_cmd_status(vport, desc[0].retval, resp_code,
+ return hclge_get_mac_vlan_cmd_status(vport, retval, resp_code,
HCLGE_MAC_VLAN_LKUP);
}
@@ -3351,6 +3376,7 @@ static int hclge_add_mac_vlan_tbl(struct hclge_vport *vport,
struct hclge_dev *hdev = vport->back;
int cfg_status;
u8 resp_code;
+ u16 retval;
int ret;
if (!mc_desc) {
@@ -3362,8 +3388,10 @@ static int hclge_add_mac_vlan_tbl(struct hclge_vport *vport,
memcpy(desc.data, req,
sizeof(struct hclge_mac_vlan_tbl_entry_cmd));
ret = hclge_cmd_send(&hdev->hw, &desc, 1);
- resp_code = (desc.data[0] >> 8) & 0xff;
- cfg_status = hclge_get_mac_vlan_cmd_status(vport, desc.retval,
+ resp_code = (le32_to_cpu(desc.data[0]) >> 8) & 0xff;
+ retval = le16_to_cpu(desc.retval);
+
+ cfg_status = hclge_get_mac_vlan_cmd_status(vport, retval,
resp_code,
HCLGE_MAC_VLAN_ADD);
} else {
@@ -3376,9 +3404,10 @@ static int hclge_add_mac_vlan_tbl(struct hclge_vport *vport,
memcpy(mc_desc[0].data, req,
sizeof(struct hclge_mac_vlan_tbl_entry_cmd));
ret = hclge_cmd_send(&hdev->hw, mc_desc, 3);
- resp_code = (mc_desc[0].data[0] >> 8) & 0xff;
- cfg_status = hclge_get_mac_vlan_cmd_status(vport,
- mc_desc[0].retval,
+ resp_code = (le32_to_cpu(mc_desc[0].data[0]) >> 8) & 0xff;
+ retval = le16_to_cpu(mc_desc[0].retval);
+
+ cfg_status = hclge_get_mac_vlan_cmd_status(vport, retval,
resp_code,
HCLGE_MAC_VLAN_ADD);
}
@@ -3407,6 +3436,7 @@ int hclge_add_uc_addr_common(struct hclge_vport *vport,
struct hclge_dev *hdev = vport->back;
struct hclge_mac_vlan_tbl_entry_cmd req;
enum hclge_cmd_status status;
+ u16 egress_port = 0;
/* mac addr check */
if (is_zero_ether_addr(addr) ||
@@ -3426,15 +3456,15 @@ int hclge_add_uc_addr_common(struct hclge_vport *vport,
hnae_set_bit(req.entry_type, HCLGE_MAC_VLAN_BIT0_EN_B, 0);
hnae_set_bit(req.entry_type, HCLGE_MAC_VLAN_BIT1_EN_B, 0);
hnae_set_bit(req.mc_mac_en, HCLGE_MAC_VLAN_BIT0_EN_B, 0);
- hnae_set_bit(req.egress_port,
- HCLGE_MAC_EPORT_SW_EN_B, 0);
- hnae_set_bit(req.egress_port,
- HCLGE_MAC_EPORT_TYPE_B, 0);
- hnae_set_field(req.egress_port, HCLGE_MAC_EPORT_VFID_M,
+
+ hnae_set_bit(egress_port, HCLGE_MAC_EPORT_SW_EN_B, 0);
+ hnae_set_bit(egress_port, HCLGE_MAC_EPORT_TYPE_B, 0);
+ hnae_set_field(egress_port, HCLGE_MAC_EPORT_VFID_M,
HCLGE_MAC_EPORT_VFID_S, vport->vport_id);
- hnae_set_field(req.egress_port, HCLGE_MAC_EPORT_PFID_M,
+ hnae_set_field(egress_port, HCLGE_MAC_EPORT_PFID_M,
HCLGE_MAC_EPORT_PFID_S, 0);
- req.egress_port = cpu_to_le16(req.egress_port);
+
+ req.egress_port = cpu_to_le16(egress_port);
hclge_prepare_mac_addr(&req, addr);
@@ -3667,7 +3697,7 @@ int hclge_set_vf_vlan_common(struct hclge_dev *hdev, int vfid,
req0 = (struct hclge_vlan_filter_vf_cfg_cmd *)desc[0].data;
req1 = (struct hclge_vlan_filter_vf_cfg_cmd *)desc[1].data;
- req0->vlan_id = vlan;
+ req0->vlan_id = cpu_to_le16(vlan);
req0->vlan_cfg = is_kill;
if (vf_byte_off < HCLGE_MAX_VF_BYTES)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c
index 359ee67..1ae6eae 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c
@@ -283,6 +283,7 @@ static int hclge_tm_pg_shapping_cfg(struct hclge_dev *hdev,
struct hclge_pg_shapping_cmd *shap_cfg_cmd;
enum hclge_opcode_type opcode;
struct hclge_desc desc;
+ u32 shapping_para = 0;
opcode = bucket ? HCLGE_OPC_TM_PG_P_SHAPPING :
HCLGE_OPC_TM_PG_C_SHAPPING;
@@ -292,11 +293,13 @@ static int hclge_tm_pg_shapping_cfg(struct hclge_dev *hdev,
shap_cfg_cmd->pg_id = pg_id;
- hclge_tm_set_field(shap_cfg_cmd->pg_shapping_para, IR_B, ir_b);
- hclge_tm_set_field(shap_cfg_cmd->pg_shapping_para, IR_U, ir_u);
- hclge_tm_set_field(shap_cfg_cmd->pg_shapping_para, IR_S, ir_s);
- hclge_tm_set_field(shap_cfg_cmd->pg_shapping_para, BS_B, bs_b);
- hclge_tm_set_field(shap_cfg_cmd->pg_shapping_para, BS_S, bs_s);
+ hclge_tm_set_field(shapping_para, IR_B, ir_b);
+ hclge_tm_set_field(shapping_para, IR_U, ir_u);
+ hclge_tm_set_field(shapping_para, IR_S, ir_s);
+ hclge_tm_set_field(shapping_para, BS_B, bs_b);
+ hclge_tm_set_field(shapping_para, BS_S, bs_s);
+
+ shap_cfg_cmd->pg_shapping_para = cpu_to_le32(shapping_para);
return hclge_cmd_send(&hdev->hw, &desc, 1);
}
@@ -337,6 +340,7 @@ static int hclge_tm_pri_shapping_cfg(struct hclge_dev *hdev,
struct hclge_pri_shapping_cmd *shap_cfg_cmd;
enum hclge_opcode_type opcode;
struct hclge_desc desc;
+ u32 shapping_para = 0;
opcode = bucket ? HCLGE_OPC_TM_PRI_P_SHAPPING :
HCLGE_OPC_TM_PRI_C_SHAPPING;
@@ -347,11 +351,13 @@ static int hclge_tm_pri_shapping_cfg(struct hclge_dev *hdev,
shap_cfg_cmd->pri_id = pri_id;
- hclge_tm_set_field(shap_cfg_cmd->pri_shapping_para, IR_B, ir_b);
- hclge_tm_set_field(shap_cfg_cmd->pri_shapping_para, IR_U, ir_u);
- hclge_tm_set_field(shap_cfg_cmd->pri_shapping_para, IR_S, ir_s);
- hclge_tm_set_field(shap_cfg_cmd->pri_shapping_para, BS_B, bs_b);
- hclge_tm_set_field(shap_cfg_cmd->pri_shapping_para, BS_S, bs_s);
+ hclge_tm_set_field(shapping_para, IR_B, ir_b);
+ hclge_tm_set_field(shapping_para, IR_U, ir_u);
+ hclge_tm_set_field(shapping_para, IR_S, ir_s);
+ hclge_tm_set_field(shapping_para, BS_B, bs_b);
+ hclge_tm_set_field(shapping_para, BS_S, bs_s);
+
+ shap_cfg_cmd->pri_shapping_para = cpu_to_le32(shapping_para);
return hclge_cmd_send(&hdev->hw, &desc, 1);
}
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hns3_enet.c
index c2a0537..aa73855 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hns3_enet.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hns3_enet.c
@@ -761,7 +761,7 @@ static int hns3_fill_desc(struct hns3_enet_ring *ring, void *priv,
if (type == DESC_TYPE_SKB) {
skb = (struct sk_buff *)priv;
- paylen = cpu_to_le16(skb->len);
+ paylen = skb->len;
if (skb->ip_summed == CHECKSUM_PARTIAL) {
skb_reset_mac_len(skb);
@@ -795,7 +795,7 @@ static int hns3_fill_desc(struct hns3_enet_ring *ring, void *priv,
cpu_to_le32(ol_type_vlan_len_msec);
desc->tx.type_cs_vlan_tso_len =
cpu_to_le32(type_cs_vlan_tso);
- desc->tx.paylen = cpu_to_le16(paylen);
+ desc->tx.paylen = cpu_to_le32(paylen);
desc->tx.mss = cpu_to_le16(mss);
}
--
1.9.1
^ permalink raw reply related
* Re: [PATCH net-next v11] openvswitch: enable NSH support
From: Yang, Yi @ 2017-10-09 8:05 UTC (permalink / raw)
To: Jiri Benc
Cc: dev-yBygre7rU0TnMu66kgdUjQ@public.gmane.org,
netdev-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, e@erig.me,
davem-fT/PcQaiUtIeIZ0/mPfg9Q@public.gmane.org
In-Reply-To: <20171002211308.03424ed6@griffin>
On Tue, Oct 03, 2017 at 03:13:08AM +0800, Jiri Benc wrote:
> On Fri, 29 Sep 2017 15:03:30 +0800, Yi Yang wrote:
> > --- a/include/net/nsh.h
> > +++ b/include/net/nsh.h
> > @@ -304,4 +304,7 @@ static inline void nsh_set_flags_ttl_len(struct nshhdr *nsh, u8 flags,
> > NSH_FLAGS_MASK | NSH_TTL_MASK | NSH_LEN_MASK);
> > }
> >
> > +int skb_push_nsh(struct sk_buff *skb, const struct nshhdr *nh);
>
> [...]
> > +int skb_push_nsh(struct sk_buff *skb, const struct nshhdr *src_nsh_hdr)
>
> This is minor but since this patch will need a respin anyway, please
> name the variables in the forward declaration and here the same.
Sorry for late reply, I was taking vacation from Oct. 1 to Oct. 8. I will
change "nh" and "src_nsh_hdr" to "pushed_nsh" because there is
another nh inside of skb_push_nsh.
>
> > +int skb_pop_nsh(struct sk_buff *skb)
> > +{
> > + int err;
> > + struct nshhdr *nsh_hdr = (struct nshhdr *)(skb->data);
>
> Bad name of the variable, clashes with the nsh_hdr function. I pointed
> that out already.
Sorry for missing this, I just did change in one .c file, forgot to do
the same thing in other .c files.
>
> > + size_t length;
> > + __be16 inner_proto;
> > +
> > + err = skb_ensure_writable(skb, skb_network_offset(skb) +
> > + sizeof(struct nshhdr));
>
> You assume that the skb starts at the NSH header, thus the
> skb_network_offset is completely unnecessary and introduces just
> another assumption on the caller. Also, the sizeof(struct nshhdr) is
> wrong: there's no guarantee that the header is not smaller or larger
> than that.
>
> More importantly though, why do you need skb_ensure_writable? You don't
> write into the header. pkskb_may_pull is enough.
>
> if (!pskb_may_pull(skb, NSH_BASE_HDR_LEN))
> return -ENOMEM;
> length = nsh_hdr_len(nsh_hdr);
> if (!pskb_may_pull(skb, length))
> return -ENOMEM;
>
Thank you for pointing out this, your version is the best one.
> > +static int set_nsh(struct sk_buff *skb, struct sw_flow_key *flow_key,
> > + const struct nlattr *a)
> > +{
> > + struct nshhdr *nh;
> > + int err;
> > + u8 flags;
> > + u8 ttl;
> > + int i;
> > +
> > + struct ovs_key_nsh key;
> > + struct ovs_key_nsh mask;
> > +
> > + err = nsh_key_from_nlattr(a, &key, &mask);
> > + if (err)
> > + return err;
> > +
> > + err = skb_ensure_writable(skb, skb_network_offset(skb) +
> > + sizeof(struct nshhdr));
>
> I missed this before: this is wrong, too. You need to use the real
> header size, not sizeof(struct nshhdr). It should be computable from
> the flow key.
It will be better to use code you provided above.
>
> > + case OVS_ACTION_ATTR_PUSH_NSH: {
> > + u8 buffer[NSH_HDR_MAX_LEN];
> > + struct nshhdr *nh = (struct nshhdr *)buffer;
> > +
> > + nsh_hdr_from_nlattr(nla_data(a), nh,
> > + NSH_HDR_MAX_LEN);
> > + err = push_nsh(skb, key, (const struct nshhdr *)nh);
>
> Is the cast to const really needed? It looks suspicious. If you added it
> because a compiler complained, it's even more suspicious.
You're right, it is ok after I remove "(const struct nshhdr *)".
>
> > +static int parse_nsh(struct sk_buff *skb, struct sw_flow_key *key)
> > +{
> > + struct nshhdr *nh;
> > + unsigned int nh_ofs = skb_network_offset(skb);
> > + u8 version, length;
> > + int err;
> > +
> > + err = check_header(skb, nh_ofs + NSH_BASE_HDR_LEN);
> > + if (unlikely(err))
> > + return err;
> > +
> > + nh = nsh_hdr(skb);
> > + version = nsh_get_ver(nh);
> > + length = nsh_hdr_len(nh);
> > +
> > + if (version != 0)
> > + return -EINVAL;
> > +
> > + err = check_header(skb, nh_ofs + length);
> > + if (unlikely(err))
> > + return err;
> > +
> > + nh = (struct nshhdr *)skb_network_header(skb);
>
> I really really really hate this. This is the third time I'm telling
> you to use the nsh_hdr function. Every time, you change only part of
> the places. And this one I even explicitly pointed out in the previous
> review.
>
> I'm not supposed to look at my previous review to verify that you
> addressed everything. That's your responsibility. Yet I need to do it
> because every time, some of my comments remain unaddressed.
Sorry, it is a missing change, accumulated comments overwhelmed this.
>
> > +int nsh_hdr_from_nlattr(const struct nlattr *attr,
> > + struct nshhdr *nh, size_t size)
> > +{
> > + struct nlattr *a;
> > + int rem;
> > + u8 flags = 0;
> > + u8 ttl = 0;
> > + int mdlen = 0;
> > +
> > + /* validate_nsh has check this, so we needn't do duplicate check here
> > + */
> > + nla_for_each_nested(a, attr, rem) {
> > + int type = nla_type(a);
> > +
> > + switch (type) {
> > + case OVS_NSH_KEY_ATTR_BASE: {
> > + const struct ovs_nsh_key_base *base = nla_data(a);
> > +
> > + flags = base->flags;
> > + ttl = base->ttl;
> > + nh->np = base->np;
> > + nh->mdtype = base->mdtype;
> > + nh->path_hdr = base->path_hdr;
> > + break;
> > + }
> > + case OVS_NSH_KEY_ATTR_MD1: {
> > + const struct ovs_nsh_key_md1 *md1 = nla_data(a);
> > +
> > + mdlen = nla_len(a);
> > + memcpy(&nh->md1, md1, mdlen);
> > + break;
>
> Looks better. Why not simplify it even more?
>
> case OVS_NSH_KEY_ATTR_MD1:
> mdlen = nla_len(a);
> memcpy(&nh->md1, nla_data(a), mdlen);
> break;
>
> It's still perfectly readable this way and there's no need for the
> braces.
>
> > + }
> > + case OVS_NSH_KEY_ATTR_MD2: {
> > + const struct u8 *md2 = nla_data(a);
> > +
> > + mdlen = nla_len(a);
> > + memcpy(&nh->md2, md2, mdlen);
>
> And here, too.
Yes, the code you provided is better.
>
> > +int nsh_key_from_nlattr(const struct nlattr *attr,
> > + struct ovs_key_nsh *nsh, struct ovs_key_nsh *nsh_mask)
> > +{
> > + struct nlattr *a;
> > + int rem;
> > +
> > + /* validate_nsh has check this, so we needn't do duplicate check here
> > + */
> > + nla_for_each_nested(a, attr, rem) {
> > + int type = nla_type(a);
> > +
> > + switch (type) {
> > + case OVS_NSH_KEY_ATTR_BASE: {
> > + const struct ovs_nsh_key_base *base = nla_data(a);
> > + const struct ovs_nsh_key_base *base_mask = base + 1;
> > +
> > + nsh->base = *base;
> > + nsh_mask->base = *base_mask;
> > + break;
> > + }
> > + case OVS_NSH_KEY_ATTR_MD1: {
> > + const struct ovs_nsh_key_md1 *md1 =
> > + (struct ovs_nsh_key_md1 *)nla_data(a);
>
> I'm speechless.
>
> Yes, I don't like the line above. For a reason that I already pointed
> out.
>
> I expected more of this version.
Sorry, these are also missing changes, I remember I did global change
about this comment, it is my bad.
Here is incremental patch against v11, I'll send out v12 if you haven't
more comments about this.
diff -u b/include/net/nsh.h b/include/net/nsh.h
--- b/include/net/nsh.h
+++ b/include/net/nsh.h
@@ -304,7 +304,7 @@
NSH_FLAGS_MASK | NSH_TTL_MASK | NSH_LEN_MASK);
}
-int skb_push_nsh(struct sk_buff *skb, const struct nshhdr *nh);
+int skb_push_nsh(struct sk_buff *skb, const struct nshhdr *pushed_nh);
int skb_pop_nsh(struct sk_buff *skb);
#endif /* __NET_NSH_H */
diff -u b/net/nsh/nsh.c b/net/nsh/nsh.c
--- b/net/nsh/nsh.c
+++ b/net/nsh/nsh.c
@@ -14,10 +14,10 @@
#include <net/nsh.h>
#include <net/tun_proto.h>
-int skb_push_nsh(struct sk_buff *skb, const struct nshhdr *src_nsh_hdr)
+int skb_push_nsh(struct sk_buff *skb, const struct nshhdr *pushed_nh)
{
- struct nshhdr *nsh_hdr;
- size_t length = nsh_hdr_len(src_nsh_hdr);
+ struct nshhdr *nh;
+ size_t length = nsh_hdr_len(pushed_nh);
u8 next_proto;
if (skb->mac_len) {
@@ -33,9 +33,9 @@
return -ENOMEM;
skb_push(skb, length);
- nsh_hdr = (struct nshhdr *)(skb->data);
- memcpy(nsh_hdr, src_nsh_hdr, length);
- nsh_hdr->np = next_proto;
+ nh = (struct nshhdr *)(skb->data);
+ memcpy(nh, pushed_nh, length);
+ nh->np = next_proto;
skb->protocol = htons(ETH_P_NSH);
skb_reset_mac_header(skb);
@@ -48,21 +48,23 @@
int skb_pop_nsh(struct sk_buff *skb)
{
- int err;
- struct nshhdr *nsh_hdr = (struct nshhdr *)(skb->data);
+ struct nshhdr *nh;
size_t length;
__be16 inner_proto;
- err = skb_ensure_writable(skb, skb_network_offset(skb) +
- sizeof(struct nshhdr));
- if (unlikely(err))
- return err;
+ if (!pskb_may_pull(skb, NSH_BASE_HDR_LEN))
+ return -ENOMEM;
+ nh = (struct nshhdr *)(skb->data);
+ length = nsh_hdr_len(nh);
+ if (!pskb_may_pull(skb, length))
+ return -ENOMEM;
- inner_proto = tun_p_to_eth_p(nsh_hdr->np);
+ nh = (struct nshhdr *)(skb->data);
+ inner_proto = tun_p_to_eth_p(nh->np);
if (!inner_proto)
return -EAFNOSUPPORT;
- length = nsh_hdr_len(nsh_hdr);
+ length = nsh_hdr_len(nh);
skb_pull(skb, length);
skb_reset_mac_header(skb);
skb_reset_network_header(skb);
diff -u b/net/openvswitch/actions.c b/net/openvswitch/actions.c
--- b/net/openvswitch/actions.c
+++ b/net/openvswitch/actions.c
@@ -644,6 +644,7 @@
const struct nlattr *a)
{
struct nshhdr *nh;
+ size_t length;
int err;
u8 flags;
u8 ttl;
@@ -656,13 +657,22 @@
if (err)
return err;
+ /* Make sure the NSH base header is there */
err = skb_ensure_writable(skb, skb_network_offset(skb) +
- sizeof(struct nshhdr));
+ NSH_BASE_HDR_LEN);
if (unlikely(err))
return err;
nh = nsh_hdr(skb);
+ length = nsh_hdr_len(nh);
+ /* Make sure the whole NSH header is there */
+ err = skb_ensure_writable(skb, skb_network_offset(skb) +
+ length);
+ if (unlikely(err))
+ return err;
+
+ nh = nsh_hdr(skb);
flags = nsh_get_flags(nh);
flags = OVS_MASKED(flags, key.base.flags, mask.base.flags);
flow_key->nsh.base.flags = flags;
@@ -1312,7 +1322,7 @@
nsh_hdr_from_nlattr(nla_data(a), nh,
NSH_HDR_MAX_LEN);
- err = push_nsh(skb, key, (const struct nshhdr *)nh);
+ err = push_nsh(skb, key, nh);
break;
}
diff -u b/net/openvswitch/flow.c b/net/openvswitch/flow.c
--- b/net/openvswitch/flow.c
+++ b/net/openvswitch/flow.c
@@ -513,7 +513,7 @@
if (unlikely(err))
return err;
- nh = (struct nshhdr *)skb_network_header(skb);
+ nh = nsh_hdr(skb);
key->nsh.base.flags = nsh_get_flags(nh);
key->nsh.base.ttl = nsh_get_ttl(nh);
key->nsh.base.mdtype = nh->mdtype;
diff -u b/net/openvswitch/flow_netlink.c b/net/openvswitch/flow_netlink.c
--- b/net/openvswitch/flow_netlink.c
+++ b/net/openvswitch/flow_netlink.c
@@ -1233,20 +1233,16 @@
nh->path_hdr = base->path_hdr;
break;
}
- case OVS_NSH_KEY_ATTR_MD1: {
- const struct ovs_nsh_key_md1 *md1 = nla_data(a);
-
+ case OVS_NSH_KEY_ATTR_MD1:
mdlen = nla_len(a);
- memcpy(&nh->md1, md1, mdlen);
+ memcpy(&nh->md1, nla_data(a), mdlen);
break;
- }
- case OVS_NSH_KEY_ATTR_MD2: {
- const struct u8 *md2 = nla_data(a);
+ case OVS_NSH_KEY_ATTR_MD2:
mdlen = nla_len(a);
- memcpy(&nh->md2, md2, mdlen);
+ memcpy(&nh->md2, nla_data(a), mdlen);
break;
- }
+
default:
return -EINVAL;
}
@@ -1280,8 +1276,7 @@
break;
}
case OVS_NSH_KEY_ATTR_MD1: {
- const struct ovs_nsh_key_md1 *md1 =
- (struct ovs_nsh_key_md1 *)nla_data(a);
+ const struct ovs_nsh_key_md1 *md1 = nla_data(a);
const struct ovs_nsh_key_md1 *md1_mask = md1 + 1;
memcpy(nsh->context, md1->context, sizeof(*md1));
@@ -1339,8 +1334,7 @@
switch (type) {
case OVS_NSH_KEY_ATTR_BASE: {
- const struct ovs_nsh_key_base *base =
- (struct ovs_nsh_key_base *)nla_data(a);
+ const struct ovs_nsh_key_base *base = nla_data(a);
has_base = true;
mdtype = base->mdtype;
@@ -1357,8 +1351,7 @@
break;
}
case OVS_NSH_KEY_ATTR_MD1: {
- const struct ovs_nsh_key_md1 *md1 =
- (struct ovs_nsh_key_md1 *)nla_data(a);
+ const struct ovs_nsh_key_md1 *md1 = nla_data(a);
has_md1 = true;
for (i = 0; i < NSH_MD1_CONTEXT_SIZE; i++)
^ permalink raw reply
* Re: [PATCH net-next 0/7] nfp: extend match and action for flower offload
From: Simon Horman @ 2017-10-09 8:05 UTC (permalink / raw)
To: Tom Herbert
Cc: David Miller, Jakub Kicinski, Linux Kernel Network Developers,
oss-drivers
In-Reply-To: <CALx6S36zb=V3Uv1xxjQi04TaPre7GRyYQ1Wcx_7zd96nSpu3pg@mail.gmail.com>
On Fri, Oct 06, 2017 at 08:34:59AM -0700, Tom Herbert wrote:
> Simon,
>
> Maybe a bit off topic, but I had the impression netronome would
> support BPF so that filters could be programmed for arbitrary
> protocols and fields. Is that true? If so, what is the relationship
> between that functionality and these patches?
Hi Tom,
you are correct in thinking that Netronome is supporting BPF offload
in its nfp driver. That support continues to be enhanced and supported.
This patch-set relates to a different set of functionality, offload of the
TC flower classifier. At this point there is no relationship between the
two sets of functionality and they cannot be used at the same time;
different firmware images are required and the driver initiates itself
according to the firmware loaded.
In future it may be possible to use both BPF and TC flower offloads at the
same time but that is not the case at this time.
Does that answer your question?
^ permalink raw reply
* Re: [PATCH v1 RFC 1/1] Add Microchip KSZ8795 DSA driver
From: Maxim Uvarov @ 2017-10-09 8:20 UTC (permalink / raw)
To: Tristram.Ha
Cc: Andrew Lunn, Florian Fainelli, Pavel Machek, Ruediger Schmitt,
Nathan Conrad, Vivien Didelot, UNGLinuxDriver, netdev,
linux-kernel
In-Reply-To: <1507322023-15182-2-git-send-email-Tristram.Ha@microchip.com>
Hello Tristram,
in previous version I see that transit traffic (ping) goes to cpu,
then from cpu back to destination port. I.e. it works but with cpu
involving. Is this version supposed to work like that?
Thank you,
Maxim.
2017-10-06 23:33 GMT+03:00 <Tristram.Ha@microchip.com>:
> From: Tristram Ha <Tristram.Ha@microchip.com>
>
> Add Microchip KSZ8795 DSA driver.
>
> Signed-off-by: Tristram Ha <Tristram.Ha@microchip.com>
> ---
> drivers/net/dsa/microchip/Kconfig | 17 +
> drivers/net/dsa/microchip/Makefile | 2 +
> drivers/net/dsa/microchip/ksz8795.c | 1372 +++++++++++++++++++++++++++++++
> drivers/net/dsa/microchip/ksz8795_reg.h | 1016 +++++++++++++++++++++++
> drivers/net/dsa/microchip/ksz8795_spi.c | 166 ++++
> drivers/net/dsa/microchip/ksz_priv.h | 1 +
> include/net/dsa.h | 1 +
> net/dsa/Kconfig | 4 +
> net/dsa/dsa.c | 3 +
> net/dsa/dsa_priv.h | 1 +
> net/dsa/tag_ksz.c | 37 +
> 11 files changed, 2620 insertions(+)
> create mode 100644 drivers/net/dsa/microchip/ksz8795.c
> create mode 100644 drivers/net/dsa/microchip/ksz8795_reg.h
> create mode 100644 drivers/net/dsa/microchip/ksz8795_spi.c
>
> diff --git a/drivers/net/dsa/microchip/Kconfig b/drivers/net/dsa/microchip/Kconfig
> index ab8f9f6..cb95d3d 100644
> --- a/drivers/net/dsa/microchip/Kconfig
> +++ b/drivers/net/dsa/microchip/Kconfig
> @@ -10,3 +10,20 @@ config MICROCHIP_KSZ9477_SPI_DRIVER
> depends on MICROCHIP_KSZ9477 && SPI
> help
> Select to enable support for registering switches configured through SPI.
> +
> +menuconfig MICROCHIP_KSZ8795
> + tristate "Microchip KSZ8795 series switch support"
> + depends on NET_DSA
> + select NET_DSA_TAG_KSZ8795
> + help
> + This driver adds support for Microchip KSZ8795 switch chips.
> +
> +config MICROCHIP_KSZ8795_SPI_DRIVER
> + tristate "KSZ8795 series SPI connected switch driver"
> + depends on MICROCHIP_KSZ8795 && SPI
> + default y
> + help
> + This driver accesses KSZ8795 chip through SPI.
> +
> + It is required to use the KSZ8795 switch driver as the only access
> + is through SPI.
> diff --git a/drivers/net/dsa/microchip/Makefile b/drivers/net/dsa/microchip/Makefile
> index 13dd8f0..99a283e 100644
> --- a/drivers/net/dsa/microchip/Makefile
> +++ b/drivers/net/dsa/microchip/Makefile
> @@ -1,2 +1,4 @@
> obj-$(CONFIG_MICROCHIP_KSZ9477) += ksz9477.o ksz_common.o
> obj-$(CONFIG_MICROCHIP_KSZ9477_SPI_DRIVER) += ksz9477_spi.o
> +obj-$(CONFIG_MICROCHIP_KSZ8795) += ksz8795.o ksz_common.o
> +obj-$(CONFIG_MICROCHIP_KSZ8795_SPI_DRIVER) += ksz8795_spi.o
> diff --git a/drivers/net/dsa/microchip/ksz8795.c b/drivers/net/dsa/microchip/ksz8795.c
> new file mode 100644
> index 0000000..7e727d3
> --- /dev/null
> +++ b/drivers/net/dsa/microchip/ksz8795.c
> @@ -0,0 +1,1372 @@
> +/*
> + * Microchip KSZ8795 switch driver
> + *
> + * Copyright (C) 2017 Microchip Technology Inc.
> + * Tristram Ha <Tristram.Ha@microchip.com>
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License
> + * as published by the Free Software Foundation; either version 2
> + * of the License, or (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include <linux/delay.h>
> +#include <linux/export.h>
> +#include <linux/gpio.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/platform_data/microchip-ksz.h>
> +#include <linux/phy.h>
> +#include <linux/etherdevice.h>
> +#include <linux/if_bridge.h>
> +#include <net/dsa.h>
> +#include <net/switchdev.h>
> +
> +#include "ksz_priv.h"
> +#include "ksz_common.h"
> +#include "ksz8795_reg.h"
> +
> +static const struct {
> + char string[ETH_GSTRING_LEN];
> +} mib_names[TOTAL_SWITCH_COUNTER_NUM] = {
> + { "rx_hi" },
> + { "rx_undersize" },
> + { "rx_fragments" },
> + { "rx_oversize" },
> + { "rx_jabbers" },
> + { "rx_symbol_err" },
> + { "rx_crc_err" },
> + { "rx_align_err" },
> + { "rx_mac_ctrl" },
> + { "rx_pause" },
> + { "rx_bcast" },
> + { "rx_mcast" },
> + { "rx_ucast" },
> + { "rx_64_or_less" },
> + { "rx_65_127" },
> + { "rx_128_255" },
> + { "rx_256_511" },
> + { "rx_512_1023" },
> + { "rx_1024_1522" },
> + { "rx_1523_2000" },
> + { "rx_2001" },
> + { "tx_hi" },
> + { "tx_late_col" },
> + { "tx_pause" },
> + { "tx_bcast" },
> + { "tx_mcast" },
> + { "tx_ucast" },
> + { "tx_deferred" },
> + { "tx_total_col" },
> + { "tx_exc_col" },
> + { "tx_single_col" },
> + { "tx_mult_col" },
> + { "rx_total" },
> + { "tx_total" },
> + { "rx_discards" },
> + { "tx_discards" },
> +};
> +
> +static int ksz8795_reset_switch(struct ksz_device *dev)
> +{
> + /* reset switch */
> + ksz_write8(dev, REG_POWER_MANAGEMENT_1,
> + SW_SOFTWARE_POWER_DOWN << SW_POWER_MANAGEMENT_MODE_S);
> + ksz_write8(dev, REG_POWER_MANAGEMENT_1, 0);
> +
> + return 0;
> +}
> +
> +static void ksz8795_set_prio_queue(struct ksz_device *dev, int port, int queue)
> +{
> + u8 hi;
> + u8 lo;
> +
> + /* Number of queues can only be 1, 2, or 4. */
> + switch (queue) {
> + case 4:
> + case 3:
> + queue = PORT_QUEUE_SPLIT_4;
> + break;
> + case 2:
> + queue = PORT_QUEUE_SPLIT_2;
> + break;
> + default:
> + queue = PORT_QUEUE_SPLIT_1;
> + }
> + ksz_pread8(dev, port, REG_PORT_CTRL_0, &lo);
> + ksz_pread8(dev, port, P_DROP_TAG_CTRL, &hi);
> + lo &= ~PORT_QUEUE_SPLIT_L;
> + if (queue & PORT_QUEUE_SPLIT_2)
> + lo |= PORT_QUEUE_SPLIT_L;
> + hi &= ~PORT_QUEUE_SPLIT_H;
> + if (queue & PORT_QUEUE_SPLIT_4)
> + hi |= PORT_QUEUE_SPLIT_H;
> + ksz_pwrite8(dev, port, REG_PORT_CTRL_0, lo);
> + ksz_pwrite8(dev, port, P_DROP_TAG_CTRL, hi);
> +
> + /* Default is port based for egress rate limit. */
> + if (queue != PORT_QUEUE_SPLIT_1)
> + ksz_cfg(dev, REG_SW_CTRL_19, SW_OUT_RATE_LIMIT_QUEUE_BASED,
> + true);
> +}
> +
> +static void ksz8795_r_mib_cnt(struct ksz_device *dev, int port, u16 addr,
> + u64 *cnt)
> +{
> + u32 data;
> + u16 ctrl_addr;
> + u8 check;
> + int loop;
> +
> + ctrl_addr = addr + SWITCH_COUNTER_NUM * port;
> + ctrl_addr |= IND_ACC_TABLE(TABLE_MIB | TABLE_READ);
> +
> + mutex_lock(&dev->alu_mutex);
> + ksz_write16(dev, REG_IND_CTRL_0, ctrl_addr);
> +
> + /* It is almost guaranteed to always read the valid bit because of
> + * slow SPI speed.
> + */
> + for (loop = 2; loop > 0; loop--) {
> + ksz_read8(dev, REG_IND_MIB_CHECK, &check);
> +
> + if (check & MIB_COUNTER_VALID) {
> + ksz_read32(dev, REG_IND_DATA_LO, &data);
> + if (check & MIB_COUNTER_OVERFLOW)
> + *cnt += MIB_COUNTER_VALUE + 1;
> + *cnt += data & MIB_COUNTER_VALUE;
> + break;
> + }
> + }
> + mutex_unlock(&dev->alu_mutex);
> +}
> +
> +static void ksz8795_r_mib_pkt(struct ksz_device *dev, int port, u16 addr,
> + u64 *dropped, u64 *cnt)
> +{
> + u32 data;
> + u16 ctrl_addr;
> + u8 check;
> + int loop;
> +
> + addr -= SWITCH_COUNTER_NUM;
> + ctrl_addr = (KS_MIB_TOTAL_RX_1 - KS_MIB_TOTAL_RX_0) * port;
> + ctrl_addr += addr + KS_MIB_TOTAL_RX_0;
> + ctrl_addr |= IND_ACC_TABLE(TABLE_MIB | TABLE_READ);
> +
> + mutex_lock(&dev->alu_mutex);
> + ksz_write16(dev, REG_IND_CTRL_0, ctrl_addr);
> +
> + /* It is almost guaranteed to always read the valid bit because of
> + * slow SPI speed.
> + */
> + for (loop = 2; loop > 0; loop--) {
> + ksz_read8(dev, REG_IND_MIB_CHECK, &check);
> +
> + if (check & MIB_COUNTER_VALID) {
> + ksz_read32(dev, REG_IND_DATA_LO, &data);
> + if (addr < 2) {
> + u64 total;
> +
> + total = check & MIB_TOTAL_BYTES_H;
> + total <<= 32;
> + *cnt += total;
> + *cnt += data;
> + if (check & MIB_COUNTER_OVERFLOW) {
> + total = MIB_TOTAL_BYTES_H + 1;
> + total <<= 32;
> + *cnt += total;
> + }
> + } else {
> + if (check & MIB_COUNTER_OVERFLOW)
> + *cnt += MIB_PACKET_DROPPED + 1;
> + *cnt += data & MIB_PACKET_DROPPED;
> + }
> + break;
> + }
> + }
> + mutex_unlock(&dev->alu_mutex);
> +}
> +
> +static void ksz8795_freeze_mib(struct ksz_device *dev, int port, bool freeze)
> +{
> + /* enable the port for flush/freeze function */
> + if (freeze)
> + ksz_cfg(dev, REG_SW_CTRL_6, 1 << port, true);
> + ksz_cfg(dev, REG_SW_CTRL_6, SW_MIB_COUNTER_FREEZE, freeze);
> +
> + /* disable the port after freeze is done */
> + if (!freeze)
> + ksz_cfg(dev, REG_SW_CTRL_6, 1 << port, false);
> +}
> +
> +static void ksz8795_port_init_cnt(struct ksz_device *dev, int port)
> +{
> + struct ksz_port_mib *mib = &dev->ports[port].mib;
> +
> + /* flush all enabled port MIB counters */
> + ksz_cfg(dev, REG_SW_CTRL_6, 1 << port, true);
> + ksz_cfg(dev, REG_SW_CTRL_6, SW_MIB_COUNTER_FLUSH, true);
> + ksz_cfg(dev, REG_SW_CTRL_6, 1 << port, false);
> +
> + mib->cnt_ptr = 0;
> +
> + /* Some ports may not have MIB counters before SWITCH_COUNTER_NUM. */
> + while (mib->cnt_ptr < dev->reg_mib_cnt) {
> + dev->dev_ops->r_mib_cnt(dev, port, mib->cnt_ptr,
> + &mib->counters[mib->cnt_ptr]);
> + ++mib->cnt_ptr;
> + }
> +
> + /* Some ports may not have MIB counters after SWITCH_COUNTER_NUM. */
> + while (mib->cnt_ptr < dev->mib_cnt) {
> + dev->dev_ops->r_mib_pkt(dev, port, mib->cnt_ptr,
> + NULL, &mib->counters[mib->cnt_ptr]);
> + ++mib->cnt_ptr;
> + }
> + mib->cnt_ptr = 0;
> + memset(mib->counters, 0, dev->mib_cnt * sizeof(u64));
> +}
> +
> +static void ksz8795_r_table(struct ksz_device *dev, int table, u16 addr,
> + u64 *data)
> +{
> + u16 ctrl_addr;
> +
> + ctrl_addr = IND_ACC_TABLE(table | TABLE_READ) | addr;
> +
> + mutex_lock(&dev->alu_mutex);
> + ksz_write16(dev, REG_IND_CTRL_0, ctrl_addr);
> + ksz_get(dev, REG_IND_DATA_HI, data, sizeof(u64));
> + mutex_unlock(&dev->alu_mutex);
> + *data = be64_to_cpu(*data);
> +}
> +
> +static void ksz8795_w_table(struct ksz_device *dev, int table, u16 addr,
> + u64 data)
> +{
> + u16 ctrl_addr;
> +
> + ctrl_addr = IND_ACC_TABLE(table) | addr;
> + data = cpu_to_be64(data);
> +
> + mutex_lock(&dev->alu_mutex);
> + ksz_set(dev, REG_IND_DATA_HI, &data, sizeof(u64));
> + ksz_write16(dev, REG_IND_CTRL_0, ctrl_addr);
> + mutex_unlock(&dev->alu_mutex);
> +}
> +
> +static int ksz8795_valid_dyn_entry(struct ksz_device *dev, u8 *data)
> +{
> + int timeout = 100;
> +
> + do {
> + ksz_read8(dev, REG_IND_DATA_CHECK, data);
> + timeout--;
> + } while ((*data & DYNAMIC_MAC_TABLE_NOT_READY) && timeout);
> +
> + /* Entry is not ready for accessing. */
> + if (*data & DYNAMIC_MAC_TABLE_NOT_READY) {
> + return -EAGAIN;
> + /* Entry is ready for accessing. */
> + } else {
> + ksz_read8(dev, REG_IND_DATA_8, data);
> +
> + /* There is no valid entry in the table. */
> + if (*data & DYNAMIC_MAC_TABLE_MAC_EMPTY)
> + return -ENXIO;
> + }
> + return 0;
> +}
> +
> +static int ksz8795_r_dyn_mac_table(struct ksz_device *dev, u16 addr,
> + u8 *mac_addr, u8 *fid, u8 *src_port,
> + u8 *timestamp, u16 *entries)
> +{
> + u32 data_hi;
> + u32 data_lo;
> + u16 ctrl_addr;
> + int rc;
> + u8 data;
> +
> + ctrl_addr = IND_ACC_TABLE(TABLE_DYNAMIC_MAC | TABLE_READ) | addr;
> +
> + mutex_lock(&dev->alu_mutex);
> + ksz_write16(dev, REG_IND_CTRL_0, ctrl_addr);
> +
> + rc = ksz8795_valid_dyn_entry(dev, &data);
> + if (rc == -EAGAIN) {
> + if (addr == 0)
> + *entries = 0;
> + } else if (rc == -ENXIO) {
> + *entries = 0;
> + /* At least one valid entry in the table. */
> + } else {
> + u64 buf;
> + int cnt;
> +
> + ksz_get(dev, REG_IND_DATA_HI, &buf, sizeof(buf));
> + buf = be64_to_cpu(buf);
> + data_hi = (u32)(buf >> 32);
> + data_lo = (u32)buf;
> +
> + /* Check out how many valid entry in the table. */
> + cnt = data & DYNAMIC_MAC_TABLE_ENTRIES_H;
> + cnt <<= DYNAMIC_MAC_ENTRIES_H_S;
> + cnt |= (data_hi & DYNAMIC_MAC_TABLE_ENTRIES) >>
> + DYNAMIC_MAC_ENTRIES_S;
> + *entries = cnt + 1;
> +
> + *fid = (data_hi & DYNAMIC_MAC_TABLE_FID) >>
> + DYNAMIC_MAC_FID_S;
> + *src_port = (data_hi & DYNAMIC_MAC_TABLE_SRC_PORT) >>
> + DYNAMIC_MAC_SRC_PORT_S;
> + *timestamp = (data_hi & DYNAMIC_MAC_TABLE_TIMESTAMP) >>
> + DYNAMIC_MAC_TIMESTAMP_S;
> +
> + mac_addr[5] = (u8)data_lo;
> + mac_addr[4] = (u8)(data_lo >> 8);
> + mac_addr[3] = (u8)(data_lo >> 16);
> + mac_addr[2] = (u8)(data_lo >> 24);
> +
> + mac_addr[1] = (u8)data_hi;
> + mac_addr[0] = (u8)(data_hi >> 8);
> + rc = 0;
> + }
> + mutex_unlock(&dev->alu_mutex);
> +
> + return rc;
> +}
> +
> +static int ksz8795_r_sta_mac_table(struct ksz_device *dev, u16 addr,
> + struct alu_struct *alu)
> +{
> + u64 data;
> + u32 data_hi;
> + u32 data_lo;
> +
> + ksz8795_r_table(dev, TABLE_STATIC_MAC, addr, &data);
> + data_hi = data >> 32;
> + data_lo = (u32)data;
> + if (data_hi & (STATIC_MAC_TABLE_VALID | STATIC_MAC_TABLE_OVERRIDE)) {
> + alu->mac[5] = (u8)data_lo;
> + alu->mac[4] = (u8)(data_lo >> 8);
> + alu->mac[3] = (u8)(data_lo >> 16);
> + alu->mac[2] = (u8)(data_lo >> 24);
> + alu->mac[1] = (u8)data_hi;
> + alu->mac[0] = (u8)(data_hi >> 8);
> + alu->port_forward = (data_hi & STATIC_MAC_TABLE_FWD_PORTS) >>
> + STATIC_MAC_FWD_PORTS_S;
> + alu->is_override =
> + (data_hi & STATIC_MAC_TABLE_OVERRIDE) ? 1 : 0;
> + data_hi >>= 1;
> + alu->is_use_fid = (data_hi & STATIC_MAC_TABLE_USE_FID) ? 1 : 0;
> + alu->fid = (data_hi & STATIC_MAC_TABLE_FID) >>
> + STATIC_MAC_FID_S;
> + return 0;
> + }
> + return -ENXIO;
> +}
> +
> +static void ksz8795_w_sta_mac_table(struct ksz_device *dev, u16 addr,
> + struct alu_struct *alu)
> +{
> + u64 data;
> + u32 data_hi;
> + u32 data_lo;
> +
> + data_lo = ((u32)alu->mac[2] << 24) |
> + ((u32)alu->mac[3] << 16) |
> + ((u32)alu->mac[4] << 8) | alu->mac[5];
> + data_hi = ((u32)alu->mac[0] << 8) | alu->mac[1];
> + data_hi |= (u32)alu->port_forward << STATIC_MAC_FWD_PORTS_S;
> +
> + if (alu->is_override)
> + data_hi |= STATIC_MAC_TABLE_OVERRIDE;
> + if (alu->is_use_fid) {
> + data_hi |= STATIC_MAC_TABLE_USE_FID;
> + data_hi |= (u32)alu->fid << STATIC_MAC_FID_S;
> + }
> + if (alu->is_static)
> + data_hi |= STATIC_MAC_TABLE_VALID;
> + else
> + data_hi &= ~STATIC_MAC_TABLE_OVERRIDE;
> +
> + data = (u64)data_hi << 32 | data_lo;
> + ksz8795_w_table(dev, TABLE_STATIC_MAC, addr, data);
> +}
> +
> +static inline void ksz8795_from_vlan(u16 vlan, u8 *fid, u8 *member, u8 *valid)
> +{
> + *fid = vlan & VLAN_TABLE_FID;
> + *member = (vlan & VLAN_TABLE_MEMBERSHIP) >> VLAN_TABLE_MEMBERSHIP_S;
> + *valid = !!(vlan & VLAN_TABLE_VALID);
> +}
> +
> +static inline void ksz8795_to_vlan(u8 fid, u8 member, u8 valid, u16 *vlan)
> +{
> + *vlan = fid;
> + *vlan |= (u16)member << VLAN_TABLE_MEMBERSHIP_S;
> + if (valid)
> + *vlan |= VLAN_TABLE_VALID;
> +}
> +
> +static void ksz8795_r_vlan_entries(struct ksz_device *dev, u16 addr)
> +{
> + u64 data;
> + int i;
> +
> + ksz8795_r_table(dev, TABLE_VLAN, addr, &data);
> + addr *= 4;
> + for (i = 0; i < 4; i++) {
> + dev->vlan_cache[addr + i].table[0] = (u16)data;
> + data >>= VLAN_TABLE_S;
> + }
> +}
> +
> +static void ksz8795_r_vlan_table(struct ksz_device *dev, u16 vid, u16 *vlan)
> +{
> + u64 buf;
> + u16 *data = (u16 *)&buf;
> + u16 addr;
> + int index;
> +
> + addr = vid / 4;
> + index = vid & 3;
> + ksz8795_r_table(dev, TABLE_VLAN, addr, &buf);
> + *vlan = data[index];
> +}
> +
> +static void ksz8795_w_vlan_table(struct ksz_device *dev, u16 vid, u16 vlan)
> +{
> + u64 buf;
> + u16 *data = (u16 *)&buf;
> + u16 addr;
> + int index;
> +
> + addr = vid / 4;
> + index = vid & 3;
> + ksz8795_r_table(dev, TABLE_VLAN, addr, &buf);
> + data[index] = vlan;
> + dev->vlan_cache[vid].table[0] = vlan;
> + ksz8795_w_table(dev, TABLE_VLAN, addr, buf);
> +}
> +
> +static void ksz8795_r_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 *val)
> +{
> + struct ksz_port *port;
> + u8 ctrl;
> + u8 restart;
> + u8 link;
> + u8 speed;
> + u8 p = phy;
> + u16 data = 0;
> + int processed = true;
> +
> + port = &dev->ports[p];
> + switch (reg) {
> + case PHY_REG_CTRL:
> + ksz_pread8(dev, p, P_NEG_RESTART_CTRL, &restart);
> + ksz_pread8(dev, p, P_SPEED_STATUS, &speed);
> + ksz_pread8(dev, p, P_FORCE_CTRL, &ctrl);
> + if (restart & PORT_PHY_LOOPBACK)
> + data |= PHY_LOOPBACK;
> + if (ctrl & PORT_FORCE_100_MBIT)
> + data |= PHY_SPEED_100MBIT;
> + if (!(ctrl & PORT_AUTO_NEG_DISABLE))
> + data |= PHY_AUTO_NEG_ENABLE;
> + if (restart & PORT_POWER_DOWN)
> + data |= PHY_POWER_DOWN;
> + if (restart & PORT_AUTO_NEG_RESTART)
> + data |= PHY_AUTO_NEG_RESTART;
> + if (ctrl & PORT_FORCE_FULL_DUPLEX)
> + data |= PHY_FULL_DUPLEX;
> + if (speed & PORT_HP_MDIX)
> + data |= PHY_HP_MDIX;
> + if (restart & PORT_FORCE_MDIX)
> + data |= PHY_FORCE_MDIX;
> + if (restart & PORT_AUTO_MDIX_DISABLE)
> + data |= PHY_AUTO_MDIX_DISABLE;
> + if (restart & PORT_TX_DISABLE)
> + data |= PHY_TRANSMIT_DISABLE;
> + if (restart & PORT_LED_OFF)
> + data |= PHY_LED_DISABLE;
> + break;
> + case PHY_REG_STATUS:
> + ksz_pread8(dev, p, P_LINK_STATUS, &link);
> + data = PHY_100BTX_FD_CAPABLE |
> + PHY_100BTX_CAPABLE |
> + PHY_10BT_FD_CAPABLE |
> + PHY_10BT_CAPABLE |
> + PHY_AUTO_NEG_CAPABLE;
> + if (link & PORT_AUTO_NEG_COMPLETE)
> + data |= PHY_AUTO_NEG_ACKNOWLEDGE;
> + if (link & PORT_STAT_LINK_GOOD)
> + data |= PHY_LINK_STATUS;
> + break;
> + case PHY_REG_ID_1:
> + data = KSZ8795_ID_HI;
> + break;
> + case PHY_REG_ID_2:
> + data = KSZ8795_ID_LO;
> + break;
> + case PHY_REG_AUTO_NEGOTIATION:
> + ksz_pread8(dev, p, P_LOCAL_CTRL, &ctrl);
> + data = PHY_AUTO_NEG_802_3;
> + if (ctrl & PORT_AUTO_NEG_SYM_PAUSE)
> + data |= PHY_AUTO_NEG_SYM_PAUSE;
> + if (ctrl & PORT_AUTO_NEG_100BTX_FD)
> + data |= PHY_AUTO_NEG_100BTX_FD;
> + if (ctrl & PORT_AUTO_NEG_100BTX)
> + data |= PHY_AUTO_NEG_100BTX;
> + if (ctrl & PORT_AUTO_NEG_10BT_FD)
> + data |= PHY_AUTO_NEG_10BT_FD;
> + if (ctrl & PORT_AUTO_NEG_10BT)
> + data |= PHY_AUTO_NEG_10BT;
> + break;
> + case PHY_REG_REMOTE_CAPABILITY:
> + ksz_pread8(dev, p, P_REMOTE_STATUS, &link);
> + data = PHY_AUTO_NEG_802_3;
> + if (link & PORT_REMOTE_SYM_PAUSE)
> + data |= PHY_AUTO_NEG_SYM_PAUSE;
> + if (link & PORT_REMOTE_100BTX_FD)
> + data |= PHY_AUTO_NEG_100BTX_FD;
> + if (link & PORT_REMOTE_100BTX)
> + data |= PHY_AUTO_NEG_100BTX;
> + if (link & PORT_REMOTE_10BT_FD)
> + data |= PHY_AUTO_NEG_10BT_FD;
> + if (link & PORT_REMOTE_10BT)
> + data |= PHY_AUTO_NEG_10BT;
> + if (data & ~PHY_AUTO_NEG_802_3)
> + data |= PHY_REMOTE_ACKNOWLEDGE_NOT;
> + break;
> + default:
> + processed = false;
> + break;
> + }
> + if (processed)
> + *val = data;
> +}
> +
> +static void ksz8795_w_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 val)
> +{
> + u8 ctrl;
> + u8 restart;
> + u8 speed;
> + u8 data;
> + u8 p = phy;
> +
> + switch (reg) {
> + case PHY_REG_CTRL:
> +
> + /* Do not support PHY reset function. */
> + if (val & PHY_RESET)
> + break;
> + ksz_pread8(dev, p, P_SPEED_STATUS, &speed);
> + data = speed;
> + if (val & PHY_HP_MDIX)
> + data |= PORT_HP_MDIX;
> + else
> + data &= ~PORT_HP_MDIX;
> + if (data != speed)
> + ksz_pwrite8(dev, p, P_SPEED_STATUS, data);
> + ksz_pread8(dev, p, P_FORCE_CTRL, &ctrl);
> + data = ctrl;
> + if (!(val & PHY_AUTO_NEG_ENABLE))
> + data |= PORT_AUTO_NEG_DISABLE;
> + else
> + data &= ~PORT_AUTO_NEG_DISABLE;
> +
> + /* Fiber port does not support auto-negotiation. */
> + if (dev->ports[p].fiber)
> + data |= PORT_AUTO_NEG_DISABLE;
> + if (val & PHY_SPEED_100MBIT)
> + data |= PORT_FORCE_100_MBIT;
> + else
> + data &= ~PORT_FORCE_100_MBIT;
> + if (val & PHY_FULL_DUPLEX)
> + data |= PORT_FORCE_FULL_DUPLEX;
> + else
> + data &= ~PORT_FORCE_FULL_DUPLEX;
> + if (data != ctrl)
> + ksz_pwrite8(dev, p, P_FORCE_CTRL, data);
> + ksz_pread8(dev, p, P_NEG_RESTART_CTRL, &restart);
> + data = restart;
> + if (val & PHY_LED_DISABLE)
> + data |= PORT_LED_OFF;
> + else
> + data &= ~PORT_LED_OFF;
> + if (val & PHY_TRANSMIT_DISABLE)
> + data |= PORT_TX_DISABLE;
> + else
> + data &= ~PORT_TX_DISABLE;
> + if (val & PHY_AUTO_NEG_RESTART)
> + data |= PORT_AUTO_NEG_RESTART;
> + else
> + data &= ~(PORT_AUTO_NEG_RESTART);
> + if (val & PHY_POWER_DOWN)
> + data |= PORT_POWER_DOWN;
> + else
> + data &= ~PORT_POWER_DOWN;
> + if (val & PHY_AUTO_MDIX_DISABLE)
> + data |= PORT_AUTO_MDIX_DISABLE;
> + else
> + data &= ~PORT_AUTO_MDIX_DISABLE;
> + if (val & PHY_FORCE_MDIX)
> + data |= PORT_FORCE_MDIX;
> + else
> + data &= ~PORT_FORCE_MDIX;
> + if (val & PHY_LOOPBACK)
> + data |= PORT_PHY_LOOPBACK;
> + else
> + data &= ~PORT_PHY_LOOPBACK;
> + if (data != restart)
> + ksz_pwrite8(dev, p, P_NEG_RESTART_CTRL, data);
> + break;
> + case PHY_REG_AUTO_NEGOTIATION:
> + ksz_pread8(dev, p, P_LOCAL_CTRL, &ctrl);
> + data = ctrl;
> + data &= ~(PORT_AUTO_NEG_SYM_PAUSE |
> + PORT_AUTO_NEG_100BTX_FD |
> + PORT_AUTO_NEG_100BTX |
> + PORT_AUTO_NEG_10BT_FD |
> + PORT_AUTO_NEG_10BT);
> + if (val & PHY_AUTO_NEG_SYM_PAUSE)
> + data |= PORT_AUTO_NEG_SYM_PAUSE;
> + if (val & PHY_AUTO_NEG_100BTX_FD)
> + data |= PORT_AUTO_NEG_100BTX_FD;
> + if (val & PHY_AUTO_NEG_100BTX)
> + data |= PORT_AUTO_NEG_100BTX;
> + if (val & PHY_AUTO_NEG_10BT_FD)
> + data |= PORT_AUTO_NEG_10BT_FD;
> + if (val & PHY_AUTO_NEG_10BT)
> + data |= PORT_AUTO_NEG_10BT;
> + if (data != ctrl)
> + ksz_pwrite8(dev, p, P_LOCAL_CTRL, data);
> + break;
> + default:
> + break;
> + }
> +}
> +
> +static enum dsa_tag_protocol ksz8795_get_tag_protocol(struct dsa_switch *ds)
> +{
> + return DSA_TAG_PROTO_KSZ8795;
> +}
> +
> +static void ksz8795_get_strings(struct dsa_switch *ds, int port, uint8_t *buf)
> +{
> + int i;
> +
> + for (i = 0; i < TOTAL_SWITCH_COUNTER_NUM; i++) {
> + memcpy(buf + i * ETH_GSTRING_LEN, mib_names[i].string,
> + ETH_GSTRING_LEN);
> + }
> +}
> +
> +static const u8 stp_multicast_addr[] = {
> + 0x01, 0x80, 0xC2, 0x00, 0x00, 0x00
> +};
> +
> +static void ksz8795_cfg_port_member(struct ksz_device *dev, int port,
> + u8 member)
> +{
> + u8 data;
> +
> + ksz_pread8(dev, port, P_MIRROR_CTRL, &data);
> + data &= ~PORT_VLAN_MEMBERSHIP;
> + data |= (member & dev->port_mask);
> + ksz_pwrite8(dev, port, P_MIRROR_CTRL, data);
> + dev->ports[port].member = member;
> +}
> +
> +static void ksz8795_port_stp_state_set(struct dsa_switch *ds, int port,
> + u8 state)
> +{
> + struct ksz_device *dev = ds->priv;
> + struct ksz_port *p = &dev->ports[port];
> + u8 data;
> + int member = -1;
> +
> + ksz_pread8(dev, port, P_STP_CTRL, &data);
> + data &= ~(PORT_TX_ENABLE | PORT_RX_ENABLE | PORT_LEARN_DISABLE);
> +
> + switch (state) {
> + case BR_STATE_DISABLED:
> + data |= PORT_LEARN_DISABLE;
> + if (port < SWITCH_PORT_NUM)
> + member = 0;
> + break;
> + case BR_STATE_LISTENING:
> + data |= (PORT_RX_ENABLE | PORT_LEARN_DISABLE);
> + if (port < SWITCH_PORT_NUM &&
> + p->stp_state == BR_STATE_DISABLED)
> + member = dev->host_mask | p->vid_member;
> + break;
> + case BR_STATE_LEARNING:
> + data |= PORT_RX_ENABLE;
> + break;
> + case BR_STATE_FORWARDING:
> + data |= (PORT_TX_ENABLE | PORT_RX_ENABLE);
> +
> + /* This function is also used internally. */
> + if (port == dev->cpu_port)
> + break;
> +
> + /* Port is a member of a bridge. */
> + if (dev->br_member & (1 << port)) {
> + dev->member |= (1 << port);
> + member = dev->member;
> + } else {
> + member = dev->host_mask | p->vid_member;
> + }
> + break;
> + case BR_STATE_BLOCKING:
> + data |= PORT_LEARN_DISABLE;
> + if (port < SWITCH_PORT_NUM &&
> + p->stp_state == BR_STATE_DISABLED)
> + member = dev->host_mask | p->vid_member;
> + break;
> + default:
> + dev_err(ds->dev, "invalid STP state: %d\n", state);
> + return;
> + }
> +
> + ksz_pwrite8(dev, port, P_STP_CTRL, data);
> + p->stp_state = state;
> + if (data & PORT_RX_ENABLE)
> + dev->rx_ports |= (1 << port);
> + else
> + dev->rx_ports &= ~(1 << port);
> + if (data & PORT_TX_ENABLE)
> + dev->tx_ports |= (1 << port);
> + else
> + dev->tx_ports &= ~(1 << port);
> +
> + /* Port membership may share register with STP state. */
> + if (member >= 0 && member != p->member)
> + ksz8795_cfg_port_member(dev, port, (u8)member);
> +
> + /* Check if forwarding needs to be updated. */
> + if (state != BR_STATE_FORWARDING) {
> + if (dev->br_member & (1 << port))
> + dev->member &= ~(1 << port);
> + }
> +
> + /* When topology has changed the function ksz_update_port_member
> + * should be called to modify port forwarding behavior. However
> + * as the offload_fwd_mark indication cannot be reported here
> + * the switch forwarding function is not enabled.
> + */
> +}
> +
> +static void ksz8795_flush_dyn_mac_table(struct ksz_device *dev, int port)
> +{
> + struct ksz_port *p;
> + int cnt;
> + int first;
> + int index;
> + u8 learn[TOTAL_PORT_NUM];
> +
> + if ((uint)port < TOTAL_PORT_NUM) {
> + first = port;
> + cnt = port + 1;
> + } else {
> + /* Flush all ports. */
> + first = 0;
> + cnt = dev->mib_port_cnt;
> + }
> + for (index = first; index < cnt; index++) {
> + p = &dev->ports[index];
> + if (!p->on)
> + continue;
> + ksz_pread8(dev, index, P_STP_CTRL, &learn[index]);
> + if (!(learn[index] & PORT_LEARN_DISABLE))
> + ksz_pwrite8(dev, index, P_STP_CTRL,
> + learn[index] | PORT_LEARN_DISABLE);
> + }
> + ksz_cfg(dev, S_FLUSH_TABLE_CTRL, SW_FLUSH_DYN_MAC_TABLE, true);
> + for (index = first; index < cnt; index++) {
> + p = &dev->ports[index];
> + if (!p->on)
> + continue;
> + if (!(learn[index] & PORT_LEARN_DISABLE))
> + ksz_pwrite8(dev, index, P_STP_CTRL, learn[index]);
> + }
> +}
> +
> +static int ksz8795_port_vlan_filtering(struct dsa_switch *ds, int port,
> + bool flag)
> +{
> + struct ksz_device *dev = ds->priv;
> +
> + ksz_cfg(dev, S_MIRROR_CTRL, SW_VLAN_ENABLE, flag);
> +
> + return 0;
> +}
> +
> +static void ksz8795_port_vlan_add(struct dsa_switch *ds, int port,
> + const struct switchdev_obj_port_vlan *vlan,
> + struct switchdev_trans *trans)
> +{
> + struct ksz_device *dev = ds->priv;
> + bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED;
> + u16 data;
> + u16 vid;
> + u8 fid;
> + u8 member;
> + u8 valid;
> + u16 new_pvid = 0;
> +
> + ksz_port_cfg(dev, port, P_TAG_CTRL, PORT_REMOVE_TAG, untagged);
> +
> + for (vid = vlan->vid_begin; vid <= vlan->vid_end; vid++) {
> + ksz8795_r_vlan_table(dev, vid, &data);
> + ksz8795_from_vlan(data, &fid, &member, &valid);
> +
> + /* First time to setup the VLAN entry. */
> + if (!valid) {
> + /* Need to find a way to map VID to FID. */
> + fid = 1;
> + valid = 1;
> + }
> + member |= BIT(port);
> +
> + ksz8795_to_vlan(fid, member, valid, &data);
> + ksz8795_w_vlan_table(dev, vid, data);
> +
> + /* change PVID */
> + if (vlan->flags & BRIDGE_VLAN_INFO_PVID)
> + new_pvid = vid;
> + }
> +
> + if (new_pvid) {
> + ksz_pread16(dev, port, REG_PORT_CTRL_VID, &vid);
> + vid &= 0xfff;
> + vid |= new_pvid;
> + ksz_pwrite16(dev, port, REG_PORT_CTRL_VID, vid);
> + }
> +}
> +
> +static int ksz8795_port_vlan_del(struct dsa_switch *ds, int port,
> + const struct switchdev_obj_port_vlan *vlan)
> +{
> + struct ksz_device *dev = ds->priv;
> + bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED;
> + u16 data;
> + u16 vid;
> + u16 pvid;
> + u8 fid;
> + u8 member;
> + u8 valid;
> + u16 new_pvid = 0;
> +
> + ksz_pread16(dev, port, REG_PORT_CTRL_VID, &pvid);
> + pvid = pvid & 0xFFF;
> +
> + ksz_port_cfg(dev, port, P_TAG_CTRL, PORT_REMOVE_TAG, untagged);
> +
> + for (vid = vlan->vid_begin; vid <= vlan->vid_end; vid++) {
> + ksz8795_r_vlan_table(dev, vid, &data);
> + ksz8795_from_vlan(data, &fid, &member, &valid);
> +
> + member &= ~BIT(port);
> +
> + /* Invalidate the entry if no more member. */
> + if (!member) {
> + fid = 0;
> + valid = 0;
> + }
> +
> + if (pvid == vid)
> + new_pvid = 1;
> +
> + ksz8795_to_vlan(fid, member, valid, &data);
> + ksz8795_w_vlan_table(dev, vid, data);
> + }
> +
> + if (new_pvid != pvid)
> + ksz_pwrite16(dev, port, REG_PORT_CTRL_VID, pvid);
> +
> + return 0;
> +}
> +
> +static int ksz8795_port_mirror_add(struct dsa_switch *ds, int port,
> + struct dsa_mall_mirror_tc_entry *mirror,
> + bool ingress)
> +{
> + struct ksz_device *dev = ds->priv;
> +
> + if (ingress) {
> + ksz_port_cfg(dev, port, P_MIRROR_CTRL, PORT_MIRROR_RX, true);
> + dev->mirror_rx |= (1 << port);
> + } else {
> + ksz_port_cfg(dev, port, P_MIRROR_CTRL, PORT_MIRROR_TX, true);
> + dev->mirror_tx |= (1 << port);
> + }
> +
> + ksz_port_cfg(dev, port, P_MIRROR_CTRL, PORT_MIRROR_SNIFFER, false);
> +
> + /* configure mirror port */
> + if (dev->mirror_rx || dev->mirror_tx)
> + ksz_port_cfg(dev, mirror->to_local_port, P_MIRROR_CTRL,
> + PORT_MIRROR_SNIFFER, true);
> +
> + return 0;
> +}
> +
> +static void ksz8795_port_mirror_del(struct dsa_switch *ds, int port,
> + struct dsa_mall_mirror_tc_entry *mirror)
> +{
> + struct ksz_device *dev = ds->priv;
> + u8 data;
> +
> + if (mirror->ingress) {
> + ksz_port_cfg(dev, port, P_MIRROR_CTRL, PORT_MIRROR_RX, false);
> + dev->mirror_rx &= ~(1 << port);
> + } else {
> + ksz_port_cfg(dev, port, P_MIRROR_CTRL, PORT_MIRROR_TX, false);
> + dev->mirror_tx &= ~(1 << port);
> + }
> +
> + ksz_pread8(dev, port, P_MIRROR_CTRL, &data);
> +
> + if (!dev->mirror_rx && !dev->mirror_tx)
> + ksz_port_cfg(dev, mirror->to_local_port, P_MIRROR_CTRL,
> + PORT_MIRROR_SNIFFER, false);
> +}
> +
> +static void ksz8795_phy_setup(struct ksz_device *dev, int port,
> + struct phy_device *phy)
> +{
> + /* SUPPORTED_Pause can be removed to disable flow control when
> + * rate limiting is used.
> + */
> + phy->supported &= ~SUPPORTED_Asym_Pause;
> + phy->advertising = phy->supported;
> +}
> +
> +static void ksz8795_port_setup(struct ksz_device *dev, int port, bool cpu_port)
> +{
> + u8 data8;
> + u8 member;
> + struct ksz_port *p = &dev->ports[port];
> +
> + /* enable broadcast storm limit */
> + ksz_port_cfg(dev, port, P_BCAST_STORM_CTRL, PORT_BROADCAST_STORM, true);
> +
> + ksz8795_set_prio_queue(dev, port, 4);
> +
> + /* disable DiffServ priority */
> + ksz_port_cfg(dev, port, P_PRIO_CTRL, PORT_DIFFSERV_ENABLE, false);
> +
> + /* replace priority */
> + ksz_port_cfg(dev, port, P_802_1P_CTRL, PORT_802_1P_REMAPPING, false);
> +
> + /* enable 802.1p priority */
> + ksz_port_cfg(dev, port, P_PRIO_CTRL, PORT_802_1P_ENABLE, true);
> +
> + if (cpu_port) {
> + /* Configure MII interface for proper network communication. */
> + ksz_read8(dev, REG_PORT_5_CTRL_6, &data8);
> + data8 &= ~PORT_INTERFACE_TYPE;
> + data8 &= ~PORT_GMII_1GPS_MODE;
> + switch (dev->interface) {
> + case PHY_INTERFACE_MODE_MII:
> + p->speed = SPEED_100;
> + break;
> + case PHY_INTERFACE_MODE_RMII:
> + data8 |= PORT_INTERFACE_RMII;
> + p->speed = SPEED_100;
> + break;
> + case PHY_INTERFACE_MODE_GMII:
> + data8 |= PORT_GMII_1GPS_MODE;
> + data8 |= PORT_INTERFACE_GMII;
> + p->speed = SPEED_1000;
> + break;
> + default:
> + data8 &= ~PORT_RGMII_ID_IN_ENABLE;
> + data8 &= ~PORT_RGMII_ID_OUT_ENABLE;
> + if (dev->interface == PHY_INTERFACE_MODE_RGMII_ID ||
> + dev->interface == PHY_INTERFACE_MODE_RGMII_RXID)
> + data8 |= PORT_RGMII_ID_IN_ENABLE;
> + if (dev->interface == PHY_INTERFACE_MODE_RGMII_ID ||
> + dev->interface == PHY_INTERFACE_MODE_RGMII_TXID)
> + data8 |= PORT_RGMII_ID_OUT_ENABLE;
> + data8 |= PORT_GMII_1GPS_MODE;
> + data8 |= PORT_INTERFACE_RGMII;
> + p->speed = SPEED_1000;
> + break;
> + }
> + ksz_write8(dev, REG_PORT_5_CTRL_6, data8);
> + p->duplex = 1;
> +
> + member = dev->port_mask;
> + dev->on_ports = dev->host_mask;
> + dev->live_ports = dev->host_mask;
> + } else {
> + member = dev->host_mask | p->vid_member;
> + dev->on_ports |= (1 << port);
> +
> + /* Link was detected before port is enabled. */
> + if (p->link_up)
> + dev->live_ports |= (1 << port);
> + }
> + ksz8795_cfg_port_member(dev, port, member);
> +}
> +
> +static void ksz8795_config_cpu_port(struct dsa_switch *ds)
> +{
> + struct ksz_device *dev = ds->priv;
> + struct ksz_port *p;
> + int i;
> + u8 remote;
> +
> + ds->num_ports = dev->port_cnt + 1;
> +
> + /* Switch marks the maximum frame with extra byte as oversize. */
> + ksz_cfg(dev, REG_SW_CTRL_2, SW_LEGAL_PACKET_DISABLE, true);
> + ksz_cfg(dev, S_TAIL_TAG_CTRL, SW_TAIL_TAG_ENABLE, true);
> +
> + p = &dev->ports[dev->cpu_port];
> + p->vid_member = dev->port_mask;
> + p->on = 1;
> +
> + ksz8795_port_setup(dev, dev->cpu_port, true);
> + dev->member = dev->host_mask;
> +
> + for (i = 0; i < SWITCH_PORT_NUM; i++) {
> + p = &dev->ports[i];
> +
> + /* Initialize to non-zero so that ksz_cfg_port_member() will
> + * be called.
> + */
> + p->vid_member = (1 << i);
> + p->member = dev->port_mask;
> + ksz8795_port_stp_state_set(ds, i, BR_STATE_DISABLED);
> +
> + /* Last port may be disabled. */
> + if (i == dev->port_cnt)
> + break;
> + p->on = 1;
> + p->phy = 1;
> + }
> + for (i = 0; i < dev->phy_port_cnt; i++) {
> + p = &dev->ports[i];
> + if (!p->on)
> + continue;
> + ksz_pread8(dev, i, P_REMOTE_STATUS, &remote);
> + if (remote & PORT_FIBER_MODE)
> + p->fiber = 1;
> + if (p->fiber)
> + ksz_port_cfg(dev, i, P_STP_CTRL, PORT_FORCE_FLOW_CTRL,
> + true);
> + else
> + ksz_port_cfg(dev, i, P_STP_CTRL, PORT_FORCE_FLOW_CTRL,
> + false);
> + }
> +}
> +
> +static int ksz8795_set_addr(struct dsa_switch *ds, u8 *addr)
> +{
> + /* Setting the switch MAC address is required for the self-address
> + * filtering feature. However, there is a flaw in the feature and
> + * so it cannot be used.
> + * The dynamic MAC table also does not learn the address so unicast
> + * forwarding is not operating correctly for the host.
> + */
> + return 0;
> +}
> +
> +static int ksz8795_setup(struct dsa_switch *ds)
> +{
> + u8 data8;
> + u16 data16;
> + u32 value;
> + int i;
> + struct alu_struct alu;
> + struct ksz_device *dev = ds->priv;
> + int ret = 0;
> +
> + dev->vlan_cache = devm_kcalloc(dev->dev, sizeof(struct vlan_table),
> + dev->num_vlans, GFP_KERNEL);
> + if (!dev->vlan_cache)
> + return -ENOMEM;
> +
> + ret = ksz8795_reset_switch(dev);
> + if (ret) {
> + dev_err(ds->dev, "failed to reset switch\n");
> + return ret;
> + }
> +
> + ksz_cfg(dev, S_REPLACE_VID_CTRL, SW_FLOW_CTRL, true);
> +
> + /* Enable automatic fast aging when link changed detected. */
> + ksz_cfg(dev, S_LINK_AGING_CTRL, SW_LINK_AUTO_AGING, true);
> +
> + ksz_read8(dev, REG_SW_CTRL_1, &data8);
> +
> + /* Enable aggressive back off algorithm in half duplex mode. */
> + data8 |= SW_AGGR_BACKOFF;
> + ksz_write8(dev, REG_SW_CTRL_1, data8);
> +
> + ksz_read8(dev, REG_SW_CTRL_2, &data8);
> +
> + /* Make sure unicast VLAN boundary is set as default. */
> + data8 |= UNICAST_VLAN_BOUNDARY;
> +
> + /* Enable no excessive collision drop. */
> + data8 |= NO_EXC_COLLISION_DROP;
> + ksz_write8(dev, REG_SW_CTRL_2, data8);
> +
> + ksz8795_config_cpu_port(ds);
> +
> + ksz_cfg(dev, REG_SW_CTRL_2, MULTICAST_STORM_DISABLE, true);
> +
> + ksz_cfg(dev, S_REPLACE_VID_CTRL, SW_REPLACE_VID, false);
> +
> + ksz_cfg(dev, S_MIRROR_CTRL, SW_MIRROR_RX_TX, false);
> +
> + /* set broadcast storm protection 10% rate */
> + data8 = BROADCAST_STORM_PROT_RATE;
> + value = ((u32)BROADCAST_STORM_VALUE * data8) / 100;
> + if (value > BROADCAST_STORM_RATE)
> + value = BROADCAST_STORM_RATE;
> + ksz_read16(dev, S_REPLACE_VID_CTRL, &data16);
> + data16 &= ~BROADCAST_STORM_RATE;
> + data16 |= value;
> + ksz_write16(dev, S_REPLACE_VID_CTRL, data16);
> +
> + for (i = 0; i < VLAN_TABLE_ENTRIES; i++)
> + ksz8795_r_vlan_entries(dev, i);
> +
> + /* Setup STP address for STP operation. */
> + memset(&alu, 0, sizeof(alu));
> + memcpy(alu.mac, stp_multicast_addr, ETH_ALEN);
> + alu.is_static = true;
> + alu.is_override = true;
> + alu.port_forward = dev->host_mask;
> +
> + ksz8795_w_sta_mac_table(dev, 0, &alu);
> +
> + ksz_init_mib_timer(dev);
> +
> + return 0;
> +}
> +
> +static const struct dsa_switch_ops ksz8795_switch_ops = {
> + .get_tag_protocol = ksz8795_get_tag_protocol,
> + .setup = ksz8795_setup,
> + .set_addr = ksz8795_set_addr,
> + .phy_read = ksz_phy_read16,
> + .phy_write = ksz_phy_write16,
> + .adjust_link = ksz_adjust_link,
> + .port_enable = ksz_enable_port,
> + .port_disable = ksz_disable_port,
> + .get_strings = ksz8795_get_strings,
> + .get_ethtool_stats = ksz_get_ethtool_stats,
> + .get_sset_count = ksz_sset_count,
> + .port_bridge_join = ksz_port_bridge_join,
> + .port_bridge_leave = ksz_port_bridge_leave,
> + .port_stp_state_set = ksz8795_port_stp_state_set,
> + .port_fast_age = ksz_port_fast_age,
> + .port_vlan_filtering = ksz8795_port_vlan_filtering,
> + .port_vlan_prepare = ksz_port_vlan_prepare,
> + .port_vlan_add = ksz8795_port_vlan_add,
> + .port_vlan_del = ksz8795_port_vlan_del,
> + .port_fdb_dump = ksz_port_fdb_dump,
> + .port_mdb_prepare = ksz_port_mdb_prepare,
> + .port_mdb_add = ksz_port_mdb_add,
> + .port_mdb_del = ksz_port_mdb_del,
> + .port_mirror_add = ksz8795_port_mirror_add,
> + .port_mirror_del = ksz8795_port_mirror_del,
> +};
> +
> +static u32 ksz8795_get_port_addr(int port, int offset)
> +{
> + return PORT_CTRL_ADDR(port, offset);
> +}
> +
> +static int ksz8795_switch_detect(struct ksz_device *dev)
> +{
> + u16 id16;
> + u8 id1;
> + u8 id2;
> + int ret;
> +
> + /* read chip id */
> + ret = ksz_read16(dev, REG_CHIP_ID0, &id16);
> + if (ret)
> + return ret;
> +
> + id1 = id16 >> 8;
> + id2 = id16 & SW_CHIP_ID_M;
> + if (id1 != FAMILY_ID ||
> + (id2 != CHIP_ID_94 && id2 != CHIP_ID_95))
> + return -ENODEV;
> +
> + dev->mib_port_cnt = TOTAL_PORT_NUM;
> + dev->phy_port_cnt = SWITCH_PORT_NUM;
> + dev->port_cnt = SWITCH_PORT_NUM;
> +
> + if (id2 == CHIP_ID_95) {
> + u8 val;
> +
> + id2 = 0x95;
> + ksz_read8(dev, REG_PORT_1_STATUS_0, &val);
> + if (val & PORT_FIBER_MODE)
> + id2 = 0x65;
> + } else if (id2 == CHIP_ID_94) {
> + dev->port_cnt--;
> + dev->last_port = dev->port_cnt;
> + id2 = 0x94;
> + }
> + id16 &= ~0xff;
> + id16 |= id2;
> + dev->chip_id = id16;
> +
> + dev->cpu_port = dev->mib_port_cnt - 1;
> + dev->host_mask = (1 << dev->cpu_port);
> +
> + return 0;
> +}
> +
> +struct ksz_chip_data {
> + u16 chip_id;
> + const char *dev_name;
> + int num_vlans;
> + int num_alus;
> + int num_statics;
> + int cpu_ports;
> + int port_cnt;
> +};
> +
> +static const struct ksz_chip_data ksz8795_switch_chips[] = {
> + {
> + .chip_id = 0x8795,
> + .dev_name = "KSZ8795",
> + .num_vlans = 4096,
> + .num_alus = 0,
> + .num_statics = 8,
> + .cpu_ports = 0x10, /* can be configured as cpu port */
> + .port_cnt = 4, /* total physical port count */
> + },
> + {
> + .chip_id = 0x8794,
> + .dev_name = "KSZ8794",
> + .num_vlans = 4096,
> + .num_alus = 0,
> + .num_statics = 8,
> + .cpu_ports = 0x10, /* can be configured as cpu port */
> + .port_cnt = 3, /* total physical port count */
> + },
> + {
> + .chip_id = 0x8765,
> + .dev_name = "KSZ8765",
> + .num_vlans = 4096,
> + .num_alus = 0,
> + .num_statics = 8,
> + .cpu_ports = 0x10, /* can be configured as cpu port */
> + .port_cnt = 4, /* total physical port count */
> + },
> +};
> +
> +static int ksz8795_switch_init(struct ksz_device *dev)
> +{
> + int i;
> +
> + mutex_init(&dev->reg_mutex);
> + mutex_init(&dev->stats_mutex);
> + mutex_init(&dev->alu_mutex);
> + mutex_init(&dev->vlan_mutex);
> +
> + dev->ds->ops = &ksz8795_switch_ops;
> +
> + for (i = 0; i < ARRAY_SIZE(ksz8795_switch_chips); i++) {
> + const struct ksz_chip_data *chip = &ksz8795_switch_chips[i];
> +
> + if (dev->chip_id == chip->chip_id) {
> + dev->name = chip->dev_name;
> + dev->num_vlans = chip->num_vlans;
> + dev->num_alus = chip->num_alus;
> + dev->num_statics = chip->num_statics;
> + dev->port_cnt = chip->port_cnt;
> + dev->cpu_ports = chip->cpu_ports;
> +
> + break;
> + }
> + }
> +
> + /* no switch found */
> + if (!dev->cpu_ports)
> + return -ENODEV;
> +
> + dev->port_mask = (1 << dev->port_cnt) - 1;
> + dev->port_mask |= dev->host_mask;
> +
> + dev->reg_mib_cnt = SWITCH_COUNTER_NUM;
> + dev->mib_cnt = TOTAL_SWITCH_COUNTER_NUM;
> +
> + i = dev->mib_port_cnt;
> + dev->ports = devm_kzalloc(dev->dev, sizeof(struct ksz_port) * i,
> + GFP_KERNEL);
> + if (!dev->ports)
> + return -ENOMEM;
> + for (i = 0; i < dev->mib_port_cnt; i++) {
> + mutex_init(&dev->ports[i].mib.cnt_mutex);
> + dev->ports[i].mib.counters =
> + devm_kzalloc(dev->dev,
> + sizeof(u64) *
> + (TOTAL_SWITCH_COUNTER_NUM + 1),
> + GFP_KERNEL);
> + if (!dev->ports[i].mib.counters)
> + return -ENOMEM;
> + }
> +
> + return 0;
> +}
> +
> +static void ksz8795_switch_exit(struct ksz_device *dev)
> +{
> + ksz8795_reset_switch(dev);
> +}
> +
> +static const struct ksz_dev_ops ksz8795_dev_ops = {
> + .get_port_addr = ksz8795_get_port_addr,
> + .cfg_port_member = ksz8795_cfg_port_member,
> + .flush_dyn_mac_table = ksz8795_flush_dyn_mac_table,
> + .phy_setup = ksz8795_phy_setup,
> + .port_setup = ksz8795_port_setup,
> + .r_phy = ksz8795_r_phy,
> + .w_phy = ksz8795_w_phy,
> + .r_dyn_mac_table = ksz8795_r_dyn_mac_table,
> + .r_sta_mac_table = ksz8795_r_sta_mac_table,
> + .w_sta_mac_table = ksz8795_w_sta_mac_table,
> + .r_mib_cnt = ksz8795_r_mib_cnt,
> + .r_mib_pkt = ksz8795_r_mib_pkt,
> + .freeze_mib = ksz8795_freeze_mib,
> + .port_init_cnt = ksz8795_port_init_cnt,
> + .shutdown = ksz8795_reset_switch,
> + .detect = ksz8795_switch_detect,
> + .init = ksz8795_switch_init,
> + .exit = ksz8795_switch_exit,
> +};
> +
> +int ksz8795_switch_register(struct ksz_device *dev)
> +{
> + return ksz_switch_register(dev, &ksz8795_dev_ops);
> +}
> +EXPORT_SYMBOL(ksz8795_switch_register);
> +
> +MODULE_AUTHOR("Tristram Ha <Tristram.Ha@microchip.com>");
> +MODULE_DESCRIPTION("Microchip KSZ8795 Series Switch DSA Driver");
> +MODULE_LICENSE("GPL");
> diff --git a/drivers/net/dsa/microchip/ksz8795_reg.h b/drivers/net/dsa/microchip/ksz8795_reg.h
> new file mode 100644
> index 0000000..fe2aa8d
> --- /dev/null
> +++ b/drivers/net/dsa/microchip/ksz8795_reg.h
> @@ -0,0 +1,1016 @@
> +/**
> + * Microchip KSZ8795 register definitions
> + *
> + * Copyright (c) 2017 Microchip Technology Inc.
> + * Tristram Ha <Tristram.Ha@microchip.com>
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License
> + * as published by the Free Software Foundation; either version 2
> + * of the License, or (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#ifndef __KSZ8795_REG_H
> +#define __KSZ8795_REG_H
> +
> +#define KS_PORT_M 0x1F
> +
> +#define KS_PRIO_M 0x3
> +#define KS_PRIO_S 2
> +
> +#define REG_CHIP_ID0 0x00
> +
> +#define FAMILY_ID 0x87
> +
> +#define REG_CHIP_ID1 0x01
> +
> +#define SW_CHIP_ID_M 0xF0
> +#define SW_CHIP_ID_S 4
> +#define SW_REVISION_M 0x0E
> +#define SW_REVISION_S 1
> +#define SW_START 0x01
> +
> +#define CHIP_ID_94 0x60
> +#define CHIP_ID_95 0x90
> +
> +#define REG_SW_CTRL_0 0x02
> +
> +#define SW_NEW_BACKOFF BIT(7)
> +#define SW_GLOBAL_RESET BIT(6)
> +#define SW_FLUSH_DYN_MAC_TABLE BIT(5)
> +#define SW_FLUSH_STA_MAC_TABLE BIT(4)
> +#define SW_LINK_AUTO_AGING BIT(0)
> +
> +#define REG_SW_CTRL_1 0x03
> +
> +#define SW_HUGE_PACKET BIT(6)
> +#define SW_TX_FLOW_CTRL_DISABLE BIT(5)
> +#define SW_RX_FLOW_CTRL_DISABLE BIT(4)
> +#define SW_CHECK_LENGTH BIT(3)
> +#define SW_AGING_ENABLE BIT(2)
> +#define SW_FAST_AGING BIT(1)
> +#define SW_AGGR_BACKOFF BIT(0)
> +
> +#define REG_SW_CTRL_2 0x04
> +
> +#define UNICAST_VLAN_BOUNDARY BIT(7)
> +#define MULTICAST_STORM_DISABLE BIT(6)
> +#define SW_BACK_PRESSURE BIT(5)
> +#define FAIR_FLOW_CTRL BIT(4)
> +#define NO_EXC_COLLISION_DROP BIT(3)
> +#define SW_LEGAL_PACKET_DISABLE BIT(1)
> +
> +#define REG_SW_CTRL_3 0x05
> + #define WEIGHTED_FAIR_QUEUE_ENABLE BIT(3)
> +
> +#define SW_VLAN_ENABLE BIT(7)
> +#define SW_IGMP_SNOOP BIT(6)
> +#define SW_MIRROR_RX_TX BIT(0)
> +
> +#define REG_SW_CTRL_4 0x06
> +
> +#define SW_HALF_DUPLEX_FLOW_CTRL BIT(7)
> +#define SW_HALF_DUPLEX BIT(6)
> +#define SW_FLOW_CTRL BIT(5)
> +#define SW_10_MBIT BIT(4)
> +#define SW_REPLACE_VID BIT(3)
> +#define BROADCAST_STORM_RATE_HI 0x07
> +
> +#define REG_SW_CTRL_5 0x07
> +
> +#define BROADCAST_STORM_RATE_LO 0xFF
> +#define BROADCAST_STORM_RATE 0x07FF
> +
> +#define REG_SW_CTRL_6 0x08
> +
> +#define SW_MIB_COUNTER_FLUSH BIT(7)
> +#define SW_MIB_COUNTER_FREEZE BIT(6)
> +#define SW_MIB_COUNTER_CTRL_ENABLE KS_PORT_M
> +
> +#define REG_SW_CTRL_9 0x0B
> +
> +#define SPI_CLK_125_MHZ 0x80
> +#define SPI_CLK_62_5_MHZ 0x40
> +#define SPI_CLK_31_25_MHZ 0x00
> +
> +#define SW_LED_MODE_M 0x3
> +#define SW_LED_MODE_S 4
> +#define SW_LED_LINK_ACT_SPEED 0
> +#define SW_LED_LINK_ACT 1
> +#define SW_LED_LINK_ACT_DUPLEX 2
> +#define SW_LED_LINK_DUPLEX 3
> +
> +#define REG_SW_CTRL_10 0x0C
> +
> +#define SW_TAIL_TAG_ENABLE BIT(1)
> +#define SW_PASS_PAUSE BIT(0)
> +
> +#define REG_SW_CTRL_11 0x0D
> +
> +#define REG_POWER_MANAGEMENT_1 0x0E
> +
> +#define SW_PLL_POWER_DOWN BIT(5)
> +#define SW_POWER_MANAGEMENT_MODE_M 0x3
> +#define SW_POWER_MANAGEMENT_MODE_S 3
> +#define SW_POWER_NORMAL 0
> +#define SW_ENERGY_DETECTION 1
> +#define SW_SOFTWARE_POWER_DOWN 2
> +
> +#define REG_POWER_MANAGEMENT_2 0x0F
> +
> +#define REG_PORT_1_CTRL_0 0x10
> +#define REG_PORT_2_CTRL_0 0x20
> +#define REG_PORT_3_CTRL_0 0x30
> +#define REG_PORT_4_CTRL_0 0x40
> +#define REG_PORT_5_CTRL_0 0x50
> +
> +#define PORT_BROADCAST_STORM BIT(7)
> +#define PORT_DIFFSERV_ENABLE BIT(6)
> +#define PORT_802_1P_ENABLE BIT(5)
> +#define PORT_BASED_PRIO_S 3
> +#define PORT_BASED_PRIO_M KS_PRIO_M
> +#define PORT_BASED_PRIO_0 0
> +#define PORT_BASED_PRIO_1 1
> +#define PORT_BASED_PRIO_2 2
> +#define PORT_BASED_PRIO_3 3
> +#define PORT_INSERT_TAG BIT(2)
> +#define PORT_REMOVE_TAG BIT(1)
> +#define PORT_QUEUE_SPLIT_L BIT(0)
> +
> +#define REG_PORT_1_CTRL_1 0x11
> +#define REG_PORT_2_CTRL_1 0x21
> +#define REG_PORT_3_CTRL_1 0x31
> +#define REG_PORT_4_CTRL_1 0x41
> +#define REG_PORT_5_CTRL_1 0x51
> +
> +#define PORT_MIRROR_SNIFFER BIT(7)
> +#define PORT_MIRROR_RX BIT(6)
> +#define PORT_MIRROR_TX BIT(5)
> +#define PORT_VLAN_MEMBERSHIP KS_PORT_M
> +
> +#define REG_PORT_1_CTRL_2 0x12
> +#define REG_PORT_2_CTRL_2 0x22
> +#define REG_PORT_3_CTRL_2 0x32
> +#define REG_PORT_4_CTRL_2 0x42
> +#define REG_PORT_5_CTRL_2 0x52
> +
> +#define PORT_802_1P_REMAPPING BIT(7)
> +#define PORT_INGRESS_FILTER BIT(6)
> +#define PORT_DISCARD_NON_VID BIT(5)
> +#define PORT_FORCE_FLOW_CTRL BIT(4)
> +#define PORT_BACK_PRESSURE BIT(3)
> +#define PORT_TX_ENABLE BIT(2)
> +#define PORT_RX_ENABLE BIT(1)
> +#define PORT_LEARN_DISABLE BIT(0)
> +
> +#define REG_PORT_1_CTRL_3 0x13
> +#define REG_PORT_2_CTRL_3 0x23
> +#define REG_PORT_3_CTRL_3 0x33
> +#define REG_PORT_4_CTRL_3 0x43
> +#define REG_PORT_5_CTRL_3 0x53
> +#define REG_PORT_1_CTRL_4 0x14
> +#define REG_PORT_2_CTRL_4 0x24
> +#define REG_PORT_3_CTRL_4 0x34
> +#define REG_PORT_4_CTRL_4 0x44
> +#define REG_PORT_5_CTRL_4 0x54
> +
> +#define PORT_DEFAULT_VID 0x0001
> +
> +#define REG_PORT_1_CTRL_5 0x15
> +#define REG_PORT_2_CTRL_5 0x25
> +#define REG_PORT_3_CTRL_5 0x35
> +#define REG_PORT_4_CTRL_5 0x45
> +#define REG_PORT_5_CTRL_5 0x55
> +
> +#define PORT_ACL_ENABLE BIT(2)
> +#define PORT_AUTHEN_MODE 0x3
> +#define PORT_AUTHEN_PASS 0
> +#define PORT_AUTHEN_BLOCK 1
> +#define PORT_AUTHEN_TRAP 2
> +
> +#define REG_PORT_5_CTRL_6 0x56
> +
> +#define PORT_MII_INTERNAL_CLOCK BIT(7)
> +#define PORT_GMII_1GPS_MODE BIT(6)
> +#define PORT_RGMII_ID_IN_ENABLE BIT(4)
> +#define PORT_RGMII_ID_OUT_ENABLE BIT(3)
> +#define PORT_GMII_MAC_MODE BIT(2)
> +#define PORT_INTERFACE_TYPE 0x3
> +#define PORT_INTERFACE_MII 0
> +#define PORT_INTERFACE_RMII 1
> +#define PORT_INTERFACE_GMII 2
> +#define PORT_INTERFACE_RGMII 3
> +
> +#define REG_PORT_1_CTRL_7 0x17
> +#define REG_PORT_2_CTRL_7 0x27
> +#define REG_PORT_3_CTRL_7 0x37
> +#define REG_PORT_4_CTRL_7 0x47
> +
> +#define PORT_AUTO_NEG_ASYM_PAUSE BIT(5)
> +#define PORT_AUTO_NEG_SYM_PAUSE BIT(4)
> +#define PORT_AUTO_NEG_100BTX_FD BIT(3)
> +#define PORT_AUTO_NEG_100BTX BIT(2)
> +#define PORT_AUTO_NEG_10BT_FD BIT(1)
> +#define PORT_AUTO_NEG_10BT BIT(0)
> +
> +#define REG_PORT_1_STATUS_0 0x18
> +#define REG_PORT_2_STATUS_0 0x28
> +#define REG_PORT_3_STATUS_0 0x38
> +#define REG_PORT_4_STATUS_0 0x48
> +
> +/* For KSZ8765. */
> +#define PORT_FIBER_MODE BIT(7)
> +
> +#define PORT_REMOTE_ASYM_PAUSE BIT(5)
> +#define PORT_REMOTE_SYM_PAUSE BIT(4)
> +#define PORT_REMOTE_100BTX_FD BIT(3)
> +#define PORT_REMOTE_100BTX BIT(2)
> +#define PORT_REMOTE_10BT_FD BIT(1)
> +#define PORT_REMOTE_10BT BIT(0)
> +
> +#define REG_PORT_1_STATUS_1 0x19
> +#define REG_PORT_2_STATUS_1 0x29
> +#define REG_PORT_3_STATUS_1 0x39
> +#define REG_PORT_4_STATUS_1 0x49
> +
> +#define PORT_HP_MDIX BIT(7)
> +#define PORT_REVERSED_POLARITY BIT(5)
> +#define PORT_TX_FLOW_CTRL BIT(4)
> +#define PORT_RX_FLOW_CTRL BIT(3)
> +#define PORT_STAT_SPEED_100MBIT BIT(2)
> +#define PORT_STAT_FULL_DUPLEX BIT(1)
> +
> +#define PORT_REMOTE_FAULT BIT(0)
> +
> +#define REG_PORT_1_LINK_MD_CTRL 0x1A
> +#define REG_PORT_2_LINK_MD_CTRL 0x2A
> +#define REG_PORT_3_LINK_MD_CTRL 0x3A
> +#define REG_PORT_4_LINK_MD_CTRL 0x4A
> +
> +#define PORT_CABLE_10M_SHORT BIT(7)
> +#define PORT_CABLE_DIAG_RESULT_M 0x3
> +#define PORT_CABLE_DIAG_RESULT_S 5
> +#define PORT_CABLE_STAT_NORMAL 0
> +#define PORT_CABLE_STAT_OPEN 1
> +#define PORT_CABLE_STAT_SHORT 2
> +#define PORT_CABLE_STAT_FAILED 3
> +#define PORT_START_CABLE_DIAG BIT(4)
> +#define PORT_FORCE_LINK BIT(3)
> +#define PORT_POWER_SAVING BIT(2)
> +#define PORT_PHY_REMOTE_LOOPBACK BIT(1)
> +#define PORT_CABLE_FAULT_COUNTER_H 0x01
> +
> +#define REG_PORT_1_LINK_MD_RESULT 0x1B
> +#define REG_PORT_2_LINK_MD_RESULT 0x2B
> +#define REG_PORT_3_LINK_MD_RESULT 0x3B
> +#define REG_PORT_4_LINK_MD_RESULT 0x4B
> +
> +#define PORT_CABLE_FAULT_COUNTER_L 0xFF
> +#define PORT_CABLE_FAULT_COUNTER 0x1FF
> +
> +#define REG_PORT_1_CTRL_9 0x1C
> +#define REG_PORT_2_CTRL_9 0x2C
> +#define REG_PORT_3_CTRL_9 0x3C
> +#define REG_PORT_4_CTRL_9 0x4C
> +
> +#define PORT_AUTO_NEG_DISABLE BIT(7)
> +#define PORT_FORCE_100_MBIT BIT(6)
> +#define PORT_FORCE_FULL_DUPLEX BIT(5)
> +
> +#define REG_PORT_1_CTRL_10 0x1D
> +#define REG_PORT_2_CTRL_10 0x2D
> +#define REG_PORT_3_CTRL_10 0x3D
> +#define REG_PORT_4_CTRL_10 0x4D
> +
> +#define PORT_LED_OFF BIT(7)
> +#define PORT_TX_DISABLE BIT(6)
> +#define PORT_AUTO_NEG_RESTART BIT(5)
> +#define PORT_POWER_DOWN BIT(3)
> +#define PORT_AUTO_MDIX_DISABLE BIT(2)
> +#define PORT_FORCE_MDIX BIT(1)
> +#define PORT_MAC_LOOPBACK BIT(0)
> +
> +#define REG_PORT_1_STATUS_2 0x1E
> +#define REG_PORT_2_STATUS_2 0x2E
> +#define REG_PORT_3_STATUS_2 0x3E
> +#define REG_PORT_4_STATUS_2 0x4E
> +
> +#define PORT_MDIX_STATUS BIT(7)
> +#define PORT_AUTO_NEG_COMPLETE BIT(6)
> +#define PORT_STAT_LINK_GOOD BIT(5)
> +
> +#define REG_PORT_1_STATUS_3 0x1F
> +#define REG_PORT_2_STATUS_3 0x2F
> +#define REG_PORT_3_STATUS_3 0x3F
> +#define REG_PORT_4_STATUS_3 0x4F
> +
> +#define PORT_PHY_LOOPBACK BIT(7)
> +#define PORT_PHY_ISOLATE BIT(5)
> +#define PORT_PHY_SOFT_RESET BIT(4)
> +#define PORT_PHY_FORCE_LINK BIT(3)
> +#define PORT_PHY_MODE_M 0x7
> +#define PHY_MODE_IN_AUTO_NEG 1
> +#define PHY_MODE_10BT_HALF 2
> +#define PHY_MODE_100BT_HALF 3
> +#define PHY_MODE_10BT_FULL 5
> +#define PHY_MODE_100BT_FULL 6
> +#define PHY_MODE_ISOLDATE 7
> +
> +#define REG_PORT_CTRL_0 0x00
> +#define REG_PORT_CTRL_1 0x01
> +#define REG_PORT_CTRL_2 0x02
> +#define REG_PORT_CTRL_VID 0x03
> +
> +#define REG_PORT_CTRL_5 0x05
> +
> +#define REG_PORT_CTRL_7 0x07
> +#define REG_PORT_STATUS_0 0x08
> +#define REG_PORT_STATUS_1 0x09
> +#define REG_PORT_LINK_MD_CTRL 0x0A
> +#define REG_PORT_LINK_MD_RESULT 0x0B
> +#define REG_PORT_CTRL_9 0x0C
> +#define REG_PORT_CTRL_10 0x0D
> +#define REG_PORT_STATUS_2 0x0E
> +#define REG_PORT_STATUS_3 0x0F
> +
> +#define REG_PORT_CTRL_12 0xA0
> +#define REG_PORT_CTRL_13 0xA1
> +#define REG_PORT_RATE_CTRL_3 0xA2
> +#define REG_PORT_RATE_CTRL_2 0xA3
> +#define REG_PORT_RATE_CTRL_1 0xA4
> +#define REG_PORT_RATE_CTRL_0 0xA5
> +#define REG_PORT_RATE_LIMIT 0xA6
> +#define REG_PORT_IN_RATE_0 0xA7
> +#define REG_PORT_IN_RATE_1 0xA8
> +#define REG_PORT_IN_RATE_2 0xA9
> +#define REG_PORT_IN_RATE_3 0xAA
> +#define REG_PORT_OUT_RATE_0 0xAB
> +#define REG_PORT_OUT_RATE_1 0xAC
> +#define REG_PORT_OUT_RATE_2 0xAD
> +#define REG_PORT_OUT_RATE_3 0xAE
> +
> +#define PORT_CTRL_ADDR(port, addr) \
> + ((addr) + REG_PORT_1_CTRL_0 + (port) * \
> + (REG_PORT_2_CTRL_0 - REG_PORT_1_CTRL_0))
> +
> +#define REG_SW_MAC_ADDR_0 0x68
> +#define REG_SW_MAC_ADDR_1 0x69
> +#define REG_SW_MAC_ADDR_2 0x6A
> +#define REG_SW_MAC_ADDR_3 0x6B
> +#define REG_SW_MAC_ADDR_4 0x6C
> +#define REG_SW_MAC_ADDR_5 0x6D
> +
> +#define REG_IND_CTRL_0 0x6E
> +
> +#define TABLE_EXT_SELECT_S 5
> +#define TABLE_EEE_V 1
> +#define TABLE_ACL_V 2
> +#define TABLE_PME_V 4
> +#define TABLE_LINK_MD_V 5
> +#define TABLE_EEE (TABLE_EEE_V << TABLE_EXT_SELECT_S)
> +#define TABLE_ACL (TABLE_ACL_V << TABLE_EXT_SELECT_S)
> +#define TABLE_PME (TABLE_PME_V << TABLE_EXT_SELECT_S)
> +#define TABLE_LINK_MD (TABLE_LINK_MD << TABLE_EXT_SELECT_S)
> +#define TABLE_READ BIT(4)
> +#define TABLE_SELECT_S 2
> +#define TABLE_STATIC_MAC_V 0
> +#define TABLE_VLAN_V 1
> +#define TABLE_DYNAMIC_MAC_V 2
> +#define TABLE_MIB_V 3
> +#define TABLE_STATIC_MAC (TABLE_STATIC_MAC_V << TABLE_SELECT_S)
> +#define TABLE_VLAN (TABLE_VLAN_V << TABLE_SELECT_S)
> +#define TABLE_DYNAMIC_MAC (TABLE_DYNAMIC_MAC_V << TABLE_SELECT_S)
> +#define TABLE_MIB (TABLE_MIB_V << TABLE_SELECT_S)
> +
> +#define REG_IND_CTRL_1 0x6F
> +
> +#define TABLE_ENTRY_MASK 0x03FF
> +#define TABLE_EXT_ENTRY_MASK 0x0FFF
> +
> +#define REG_IND_DATA_8 0x70
> +#define REG_IND_DATA_7 0x71
> +#define REG_IND_DATA_6 0x72
> +#define REG_IND_DATA_5 0x73
> +#define REG_IND_DATA_4 0x74
> +#define REG_IND_DATA_3 0x75
> +#define REG_IND_DATA_2 0x76
> +#define REG_IND_DATA_1 0x77
> +#define REG_IND_DATA_0 0x78
> +
> +#define REG_IND_DATA_PME_EEE_ACL 0xA0
> +
> +#define REG_IND_DATA_CHECK REG_IND_DATA_6
> +#define REG_IND_MIB_CHECK REG_IND_DATA_4
> +#define REG_IND_DATA_HI REG_IND_DATA_7
> +#define REG_IND_DATA_LO REG_IND_DATA_3
> +
> +#define REG_INT_STATUS 0x7C
> +#define REG_INT_ENABLE 0x7D
> +
> +#define INT_PME BIT(4)
> +
> +#define REG_ACL_INT_STATUS 0x7E
> +#define REG_ACL_INT_ENABLE 0x7F
> +
> +#define INT_PORT_5 BIT(4)
> +#define INT_PORT_4 BIT(3)
> +#define INT_PORT_3 BIT(2)
> +#define INT_PORT_2 BIT(1)
> +#define INT_PORT_1 BIT(0)
> +
> +#define INT_PORT_ALL \
> + (INT_PORT_5 | INT_PORT_4 | INT_PORT_3 | INT_PORT_2 | INT_PORT_1)
> +
> +#define REG_SW_CTRL_12 0x80
> +#define REG_SW_CTRL_13 0x81
> +
> +#define SWITCH_802_1P_MASK 3
> +#define SWITCH_802_1P_BASE 3
> +#define SWITCH_802_1P_SHIFT 2
> +
> +#define SW_802_1P_MAP_M KS_PRIO_M
> +#define SW_802_1P_MAP_S KS_PRIO_S
> +
> +#define REG_SWITCH_CTRL_14 0x82
> +
> +#define SW_PRIO_MAPPING_M KS_PRIO_M
> +#define SW_PRIO_MAPPING_S 6
> +#define SW_PRIO_MAP_3_HI 0
> +#define SW_PRIO_MAP_2_HI 2
> +#define SW_PRIO_MAP_0_LO 3
> +
> +#define REG_SW_CTRL_15 0x83
> +#define REG_SW_CTRL_16 0x84
> +#define REG_SW_CTRL_17 0x85
> +#define REG_SW_CTRL_18 0x86
> +
> +#define SW_SELF_ADDR_FILTER_ENABLE BIT(6)
> +
> +#define REG_SW_UNK_UCAST_CTRL 0x83
> +#define REG_SW_UNK_MCAST_CTRL 0x84
> +#define REG_SW_UNK_VID_CTRL 0x85
> +#define REG_SW_UNK_IP_MCAST_CTRL 0x86
> +
> +#define SW_UNK_FWD_ENABLE BIT(5)
> +#define SW_UNK_FWD_MAP KS_PORT_M
> +
> +#define REG_SW_CTRL_19 0x87
> +
> +#define SW_IN_RATE_LIMIT_PERIOD_M 0x3
> +#define SW_IN_RATE_LIMIT_PERIOD_S 4
> +#define SW_IN_RATE_LIMIT_16_MS 0
> +#define SW_IN_RATE_LIMIT_64_MS 1
> +#define SW_IN_RATE_LIMIT_256_MS 2
> +#define SW_OUT_RATE_LIMIT_QUEUE_BASED BIT(3)
> +#define SW_INS_TAG_ENABLE BIT(2)
> +
> +#define REG_TOS_PRIO_CTRL_0 0x90
> +#define REG_TOS_PRIO_CTRL_1 0x91
> +#define REG_TOS_PRIO_CTRL_2 0x92
> +#define REG_TOS_PRIO_CTRL_3 0x93
> +#define REG_TOS_PRIO_CTRL_4 0x94
> +#define REG_TOS_PRIO_CTRL_5 0x95
> +#define REG_TOS_PRIO_CTRL_6 0x96
> +#define REG_TOS_PRIO_CTRL_7 0x97
> +#define REG_TOS_PRIO_CTRL_8 0x98
> +#define REG_TOS_PRIO_CTRL_9 0x99
> +#define REG_TOS_PRIO_CTRL_10 0x9A
> +#define REG_TOS_PRIO_CTRL_11 0x9B
> +#define REG_TOS_PRIO_CTRL_12 0x9C
> +#define REG_TOS_PRIO_CTRL_13 0x9D
> +#define REG_TOS_PRIO_CTRL_14 0x9E
> +#define REG_TOS_PRIO_CTRL_15 0x9F
> +
> +#define TOS_PRIO_M KS_PRIO_M
> +#define TOS_PRIO_S KS_PRIO_S
> +
> +#define REG_SW_CTRL_20 0xA3
> +
> +#define SW_GMII_DRIVE_STRENGTH_S 4
> +#define SW_DRIVE_STRENGTH_M 0x7
> +#define SW_DRIVE_STRENGTH_2MA 0
> +#define SW_DRIVE_STRENGTH_4MA 1
> +#define SW_DRIVE_STRENGTH_8MA 2
> +#define SW_DRIVE_STRENGTH_12MA 3
> +#define SW_DRIVE_STRENGTH_16MA 4
> +#define SW_DRIVE_STRENGTH_20MA 5
> +#define SW_DRIVE_STRENGTH_24MA 6
> +#define SW_DRIVE_STRENGTH_28MA 7
> +#define SW_MII_DRIVE_STRENGTH_S 0
> +
> +#define REG_SW_CTRL_21 0xA4
> +
> +#define SW_IPV6_MLD_OPTION BIT(3)
> +#define SW_IPV6_MLD_SNOOP BIT(2)
> +
> +#define REG_PORT_1_CTRL_12 0xB0
> +#define REG_PORT_2_CTRL_12 0xC0
> +#define REG_PORT_3_CTRL_12 0xD0
> +#define REG_PORT_4_CTRL_12 0xE0
> +#define REG_PORT_5_CTRL_12 0xF0
> +
> +#define PORT_PASS_ALL BIT(6)
> +#define PORT_INS_TAG_FOR_PORT_5_S 3
> +#define PORT_INS_TAG_FOR_PORT_5 BIT(3)
> +#define PORT_INS_TAG_FOR_PORT_4 BIT(2)
> +#define PORT_INS_TAG_FOR_PORT_3 BIT(1)
> +#define PORT_INS_TAG_FOR_PORT_2 BIT(0)
> +
> +#define REG_PORT_1_CTRL_13 0xB1
> +#define REG_PORT_2_CTRL_13 0xC1
> +#define REG_PORT_3_CTRL_13 0xD1
> +#define REG_PORT_4_CTRL_13 0xE1
> +#define REG_PORT_5_CTRL_13 0xF1
> +
> +#define PORT_QUEUE_SPLIT_H BIT(1)
> +#define PORT_QUEUE_SPLIT_1 0
> +#define PORT_QUEUE_SPLIT_2 1
> +#define PORT_QUEUE_SPLIT_4 2
> +#define PORT_DROP_TAG BIT(0)
> +
> +#define REG_PORT_1_CTRL_14 0xB2
> +#define REG_PORT_2_CTRL_14 0xC2
> +#define REG_PORT_3_CTRL_14 0xD2
> +#define REG_PORT_4_CTRL_14 0xE2
> +#define REG_PORT_5_CTRL_14 0xF2
> +#define REG_PORT_1_CTRL_15 0xB3
> +#define REG_PORT_2_CTRL_15 0xC3
> +#define REG_PORT_3_CTRL_15 0xD3
> +#define REG_PORT_4_CTRL_15 0xE3
> +#define REG_PORT_5_CTRL_15 0xF3
> +#define REG_PORT_1_CTRL_16 0xB4
> +#define REG_PORT_2_CTRL_16 0xC4
> +#define REG_PORT_3_CTRL_16 0xD4
> +#define REG_PORT_4_CTRL_16 0xE4
> +#define REG_PORT_5_CTRL_16 0xF4
> +#define REG_PORT_1_CTRL_17 0xB5
> +#define REG_PORT_2_CTRL_17 0xC5
> +#define REG_PORT_3_CTRL_17 0xD5
> +#define REG_PORT_4_CTRL_17 0xE5
> +#define REG_PORT_5_CTRL_17 0xF5
> +
> +#define REG_PORT_1_RATE_CTRL_3 0xB2
> +#define REG_PORT_1_RATE_CTRL_2 0xB3
> +#define REG_PORT_1_RATE_CTRL_1 0xB4
> +#define REG_PORT_1_RATE_CTRL_0 0xB5
> +#define REG_PORT_2_RATE_CTRL_3 0xC2
> +#define REG_PORT_2_RATE_CTRL_2 0xC3
> +#define REG_PORT_2_RATE_CTRL_1 0xC4
> +#define REG_PORT_2_RATE_CTRL_0 0xC5
> +#define REG_PORT_3_RATE_CTRL_3 0xD2
> +#define REG_PORT_3_RATE_CTRL_2 0xD3
> +#define REG_PORT_3_RATE_CTRL_1 0xD4
> +#define REG_PORT_3_RATE_CTRL_0 0xD5
> +#define REG_PORT_4_RATE_CTRL_3 0xE2
> +#define REG_PORT_4_RATE_CTRL_2 0xE3
> +#define REG_PORT_4_RATE_CTRL_1 0xE4
> +#define REG_PORT_4_RATE_CTRL_0 0xE5
> +#define REG_PORT_5_RATE_CTRL_3 0xF2
> +#define REG_PORT_5_RATE_CTRL_2 0xF3
> +#define REG_PORT_5_RATE_CTRL_1 0xF4
> +#define REG_PORT_5_RATE_CTRL_0 0xF5
> +
> +#define RATE_CTRL_ENABLE BIT(7)
> +#define RATE_RATIO_M (BIT(7) - 1)
> +
> +#define PORT_OUT_RATE_ENABLE BIT(7)
> +
> +#define REG_PORT_1_RATE_LIMIT 0xB6
> +#define REG_PORT_2_RATE_LIMIT 0xC6
> +#define REG_PORT_3_RATE_LIMIT 0xD6
> +#define REG_PORT_4_RATE_LIMIT 0xE6
> +#define REG_PORT_5_RATE_LIMIT 0xF6
> +
> +#define PORT_IN_PORT_BASED_S 6
> +#define PORT_RATE_PACKET_BASED_S 5
> +#define PORT_IN_FLOW_CTRL_S 4
> +#define PORT_IN_LIMIT_MODE_M 0x3
> +#define PORT_IN_LIMIT_MODE_S 2
> +#define PORT_COUNT_IFG_S 1
> +#define PORT_COUNT_PREAMBLE_S 0
> +#define PORT_IN_PORT_BASED BIT(PORT_IN_PORT_BASED_S)
> +#define PORT_RATE_PACKET_BASED BIT(PORT_RATE_PACKET_BASED_S)
> +#define PORT_IN_FLOW_CTRL BIT(PORT_IN_FLOW_CTRL_S)
> +#define PORT_IN_ALL 0
> +#define PORT_IN_UNICAST 1
> +#define PORT_IN_MULTICAST 2
> +#define PORT_IN_BROADCAST 3
> +#define PORT_COUNT_IFG BIT(PORT_COUNT_IFG_S)
> +#define PORT_COUNT_PREAMBLE BIT(PORT_COUNT_PREAMBLE_S)
> +
> +#define REG_PORT_1_IN_RATE_0 0xB7
> +#define REG_PORT_2_IN_RATE_0 0xC7
> +#define REG_PORT_3_IN_RATE_0 0xD7
> +#define REG_PORT_4_IN_RATE_0 0xE7
> +#define REG_PORT_5_IN_RATE_0 0xF7
> +#define REG_PORT_1_IN_RATE_1 0xB8
> +#define REG_PORT_2_IN_RATE_1 0xC8
> +#define REG_PORT_3_IN_RATE_1 0xD8
> +#define REG_PORT_4_IN_RATE_1 0xE8
> +#define REG_PORT_5_IN_RATE_1 0xF8
> +#define REG_PORT_1_IN_RATE_2 0xB9
> +#define REG_PORT_2_IN_RATE_2 0xC9
> +#define REG_PORT_3_IN_RATE_2 0xD9
> +#define REG_PORT_4_IN_RATE_2 0xE9
> +#define REG_PORT_5_IN_RATE_2 0xF9
> +#define REG_PORT_1_IN_RATE_3 0xBA
> +#define REG_PORT_2_IN_RATE_3 0xCA
> +#define REG_PORT_3_IN_RATE_3 0xDA
> +#define REG_PORT_4_IN_RATE_3 0xEA
> +#define REG_PORT_5_IN_RATE_3 0xFA
> +
> +#define PORT_IN_RATE_ENABLE BIT(7)
> +#define PORT_RATE_LIMIT_M (BIT(7) - 1)
> +
> +#define REG_PORT_1_OUT_RATE_0 0xBB
> +#define REG_PORT_2_OUT_RATE_0 0xCB
> +#define REG_PORT_3_OUT_RATE_0 0xDB
> +#define REG_PORT_4_OUT_RATE_0 0xEB
> +#define REG_PORT_5_OUT_RATE_0 0xFB
> +#define REG_PORT_1_OUT_RATE_1 0xBC
> +#define REG_PORT_2_OUT_RATE_1 0xCC
> +#define REG_PORT_3_OUT_RATE_1 0xDC
> +#define REG_PORT_4_OUT_RATE_1 0xEC
> +#define REG_PORT_5_OUT_RATE_1 0xFC
> +#define REG_PORT_1_OUT_RATE_2 0xBD
> +#define REG_PORT_2_OUT_RATE_2 0xCD
> +#define REG_PORT_3_OUT_RATE_2 0xDD
> +#define REG_PORT_4_OUT_RATE_2 0xED
> +#define REG_PORT_5_OUT_RATE_2 0xFD
> +#define REG_PORT_1_OUT_RATE_3 0xBE
> +#define REG_PORT_2_OUT_RATE_3 0xCE
> +#define REG_PORT_3_OUT_RATE_3 0xDE
> +#define REG_PORT_4_OUT_RATE_3 0xEE
> +#define REG_PORT_5_OUT_RATE_3 0xFE
> +
> +/* PME */
> +
> +#define SW_PME_OUTPUT_ENABLE BIT(1)
> +#define SW_PME_ACTIVE_HIGH BIT(0)
> +
> +#define PORT_MAGIC_PACKET_DETECT BIT(2)
> +#define PORT_LINK_UP_DETECT BIT(1)
> +#define PORT_ENERGY_DETECT BIT(0)
> +
> +/* ACL */
> +
> +#define ACL_FIRST_RULE_M 0xF
> +
> +#define ACL_MODE_M 0x3
> +#define ACL_MODE_S 4
> +#define ACL_MODE_DISABLE 0
> +#define ACL_MODE_LAYER_2 1
> +#define ACL_MODE_LAYER_3 2
> +#define ACL_MODE_LAYER_4 3
> +#define ACL_ENABLE_M 0x3
> +#define ACL_ENABLE_S 2
> +#define ACL_ENABLE_2_COUNT 0
> +#define ACL_ENABLE_2_TYPE 1
> +#define ACL_ENABLE_2_MAC 2
> +#define ACL_ENABLE_2_BOTH 3
> +#define ACL_ENABLE_3_IP 1
> +#define ACL_ENABLE_3_SRC_DST_COMP 2
> +#define ACL_ENABLE_4_PROTOCOL 0
> +#define ACL_ENABLE_4_TCP_PORT_COMP 1
> +#define ACL_ENABLE_4_UDP_PORT_COMP 2
> +#define ACL_ENABLE_4_TCP_SEQN_COMP 3
> +#define ACL_SRC BIT(1)
> +#define ACL_EQUAL BIT(0)
> +
> +#define ACL_MAX_PORT 0xFFFF
> +
> +#define ACL_MIN_PORT 0xFFFF
> +#define ACL_IP_ADDR 0xFFFFFFFF
> +#define ACL_TCP_SEQNUM 0xFFFFFFFF
> +
> +#define ACL_RESERVED 0xF8
> +#define ACL_PORT_MODE_M 0x3
> +#define ACL_PORT_MODE_S 1
> +#define ACL_PORT_MODE_DISABLE 0
> +#define ACL_PORT_MODE_EITHER 1
> +#define ACL_PORT_MODE_IN_RANGE 2
> +#define ACL_PORT_MODE_OUT_OF_RANGE 3
> +
> +#define ACL_TCP_FLAG_ENABLE BIT(0)
> +
> +#define ACL_TCP_FLAG_M 0xFF
> +
> +#define ACL_TCP_FLAG 0xFF
> +#define ACL_ETH_TYPE 0xFFFF
> +#define ACL_IP_M 0xFFFFFFFF
> +
> +#define ACL_PRIO_MODE_M 0x3
> +#define ACL_PRIO_MODE_S 6
> +#define ACL_PRIO_MODE_DISABLE 0
> +#define ACL_PRIO_MODE_HIGHER 1
> +#define ACL_PRIO_MODE_LOWER 2
> +#define ACL_PRIO_MODE_REPLACE 3
> +#define ACL_PRIO_M 0x7
> +#define ACL_PRIO_S 3
> +#define ACL_VLAN_PRIO_REPLACE BIT(2)
> +#define ACL_VLAN_PRIO_M 0x7
> +#define ACL_VLAN_PRIO_HI_M 0x3
> +
> +#define ACL_VLAN_PRIO_LO_M 0x8
> +#define ACL_VLAN_PRIO_S 7
> +#define ACL_MAP_MODE_M 0x3
> +#define ACL_MAP_MODE_S 5
> +#define ACL_MAP_MODE_DISABLE 0
> +#define ACL_MAP_MODE_OR 1
> +#define ACL_MAP_MODE_AND 2
> +#define ACL_MAP_MODE_REPLACE 3
> +#define ACL_MAP_PORT_M 0x1F
> +
> +#define ACL_CNT_M (BIT(11) - 1)
> +#define ACL_CNT_S 5
> +#define ACL_MSEC_UNIT BIT(4)
> +#define ACL_INTR_MODE BIT(3)
> +
> +#define REG_PORT_ACL_BYTE_EN_MSB 0x10
> +
> +#define ACL_BYTE_EN_MSB_M 0x3F
> +
> +#define REG_PORT_ACL_BYTE_EN_LSB 0x11
> +
> +#define ACL_ACTION_START 0xA
> +#define ACL_ACTION_LEN 2
> +#define ACL_INTR_CNT_START 0xB
> +#define ACL_RULESET_START 0xC
> +#define ACL_RULESET_LEN 2
> +#define ACL_TABLE_LEN 14
> +
> +#define ACL_ACTION_ENABLE 0x000C
> +#define ACL_MATCH_ENABLE 0x1FF0
> +#define ACL_RULESET_ENABLE 0x2003
> +#define ACL_BYTE_ENABLE ((ACL_BYTE_EN_MSB_M << 8) | 0xFF)
> +#define ACL_MODE_ENABLE (0x10 << 8)
> +
> +#define REG_PORT_ACL_CTRL_0 0x12
> +
> +#define PORT_ACL_WRITE_DONE BIT(6)
> +#define PORT_ACL_READ_DONE BIT(5)
> +#define PORT_ACL_WRITE BIT(4)
> +#define PORT_ACL_INDEX_M 0xF
> +
> +#define REG_PORT_ACL_CTRL_1 0x13
> +
> +#define PORT_ACL_FORCE_DLR_MISS BIT(0)
> +
> +#ifndef PHY_REG_CTRL
> +#define PHY_REG_CTRL 0
> +
> +#define PHY_RESET BIT(15)
> +#define PHY_LOOPBACK BIT(14)
> +#define PHY_SPEED_100MBIT BIT(13)
> +#define PHY_AUTO_NEG_ENABLE BIT(12)
> +#define PHY_POWER_DOWN BIT(11)
> +#define PHY_MII_DISABLE BIT(10)
> +#define PHY_AUTO_NEG_RESTART BIT(9)
> +#define PHY_FULL_DUPLEX BIT(8)
> +#define PHY_COLLISION_TEST_NOT BIT(7)
> +#define PHY_HP_MDIX BIT(5)
> +#define PHY_FORCE_MDIX BIT(4)
> +#define PHY_AUTO_MDIX_DISABLE BIT(3)
> +#define PHY_REMOTE_FAULT_DISABLE BIT(2)
> +#define PHY_TRANSMIT_DISABLE BIT(1)
> +#define PHY_LED_DISABLE BIT(0)
> +
> +#define PHY_REG_STATUS 1
> +
> +#define PHY_100BT4_CAPABLE BIT(15)
> +#define PHY_100BTX_FD_CAPABLE BIT(14)
> +#define PHY_100BTX_CAPABLE BIT(13)
> +#define PHY_10BT_FD_CAPABLE BIT(12)
> +#define PHY_10BT_CAPABLE BIT(11)
> +#define PHY_MII_SUPPRESS_CAPABLE_NOT BIT(6)
> +#define PHY_AUTO_NEG_ACKNOWLEDGE BIT(5)
> +#define PHY_REMOTE_FAULT BIT(4)
> +#define PHY_AUTO_NEG_CAPABLE BIT(3)
> +#define PHY_LINK_STATUS BIT(2)
> +#define PHY_JABBER_DETECT_NOT BIT(1)
> +#define PHY_EXTENDED_CAPABILITY BIT(0)
> +
> +#define PHY_REG_ID_1 2
> +#define PHY_REG_ID_2 3
> +
> +#define PHY_REG_AUTO_NEGOTIATION 4
> +
> +#define PHY_AUTO_NEG_NEXT_PAGE_NOT BIT(15)
> +#define PHY_AUTO_NEG_REMOTE_FAULT_NOT BIT(13)
> +#define PHY_AUTO_NEG_SYM_PAUSE BIT(10)
> +#define PHY_AUTO_NEG_100BT4 BIT(9)
> +#define PHY_AUTO_NEG_100BTX_FD BIT(8)
> +#define PHY_AUTO_NEG_100BTX BIT(7)
> +#define PHY_AUTO_NEG_10BT_FD BIT(6)
> +#define PHY_AUTO_NEG_10BT BIT(5)
> +#define PHY_AUTO_NEG_SELECTOR 0x001F
> +#define PHY_AUTO_NEG_802_3 0x0001
> +
> +#define PHY_REG_REMOTE_CAPABILITY 5
> +
> +#define PHY_REMOTE_NEXT_PAGE_NOT BIT(15)
> +#define PHY_REMOTE_ACKNOWLEDGE_NOT BIT(14)
> +#define PHY_REMOTE_REMOTE_FAULT_NOT BIT(13)
> +#define PHY_REMOTE_SYM_PAUSE BIT(10)
> +#define PHY_REMOTE_100BTX_FD BIT(8)
> +#define PHY_REMOTE_100BTX BIT(7)
> +#define PHY_REMOTE_10BT_FD BIT(6)
> +#define PHY_REMOTE_10BT BIT(5)
> +#endif
> +
> +#define KSZ8795_ID_HI 0x0022
> +#define KSZ8795_ID_LO 0x1550
> +
> +#define KSZ8795_SW_ID 0x8795
> +
> +#define PHY_REG_LINK_MD 0x1D
> +
> +#define PHY_START_CABLE_DIAG BIT(15)
> +#define PHY_CABLE_DIAG_RESULT 0x6000
> +#define PHY_CABLE_STAT_NORMAL 0x0000
> +#define PHY_CABLE_STAT_OPEN 0x2000
> +#define PHY_CABLE_STAT_SHORT 0x4000
> +#define PHY_CABLE_STAT_FAILED 0x6000
> +#define PHY_CABLE_10M_SHORT BIT(12)
> +#define PHY_CABLE_FAULT_COUNTER 0x01FF
> +
> +#define PHY_REG_PHY_CTRL 0x1F
> +
> +#define PHY_MODE_M 0x7
> +#define PHY_MODE_S 8
> +#define PHY_STAT_REVERSED_POLARITY BIT(5)
> +#define PHY_STAT_MDIX BIT(4)
> +#define PHY_FORCE_LINK BIT(3)
> +#define PHY_POWER_SAVING_ENABLE BIT(2)
> +#define PHY_REMOTE_LOOPBACK BIT(1)
> +
> +/* Chip resource */
> +
> +#define PRIO_QUEUES 4
> +
> +#define KS_PRIO_IN_REG 4
> +
> +#define TOTAL_PORT_NUM 5
> +
> +/* Host port can only be last of them. */
> +#define SWITCH_PORT_NUM (TOTAL_PORT_NUM - 1)
> +
> +#define KSZ8795_COUNTER_NUM 0x20
> +#define TOTAL_KSZ8795_COUNTER_NUM (KSZ8795_COUNTER_NUM + 4)
> +
> +#define SWITCH_COUNTER_NUM KSZ8795_COUNTER_NUM
> +#define TOTAL_SWITCH_COUNTER_NUM TOTAL_KSZ8795_COUNTER_NUM
> +
> +/* Common names used by other drivers */
> +
> +#define P_BCAST_STORM_CTRL REG_PORT_CTRL_0
> +#define P_PRIO_CTRL REG_PORT_CTRL_0
> +#define P_TAG_CTRL REG_PORT_CTRL_0
> +#define P_MIRROR_CTRL REG_PORT_CTRL_1
> +#define P_802_1P_CTRL REG_PORT_CTRL_2
> +#define P_STP_CTRL REG_PORT_CTRL_2
> +#define P_LOCAL_CTRL REG_PORT_CTRL_7
> +#define P_REMOTE_STATUS REG_PORT_STATUS_0
> +#define P_FORCE_CTRL REG_PORT_CTRL_9
> +#define P_NEG_RESTART_CTRL REG_PORT_CTRL_10
> +#define P_SPEED_STATUS REG_PORT_STATUS_1
> +#define P_LINK_STATUS REG_PORT_STATUS_2
> +#define P_PASS_ALL_CTRL REG_PORT_CTRL_12
> +#define P_INS_SRC_PVID_CTRL REG_PORT_CTRL_12
> +#define P_DROP_TAG_CTRL REG_PORT_CTRL_13
> +#define P_RATE_LIMIT_CTRL REG_PORT_RATE_LIMIT
> +
> +#define S_UNKNOWN_DA_CTRL REG_SWITCH_CTRL_12
> +#define S_FORWARD_INVALID_VID_CTRL REG_FORWARD_INVALID_VID
> +
> +#define S_FLUSH_TABLE_CTRL REG_SW_CTRL_0
> +#define S_LINK_AGING_CTRL REG_SW_CTRL_0
> +#define S_HUGE_PACKET_CTRL REG_SW_CTRL_1
> +#define S_MIRROR_CTRL REG_SW_CTRL_3
> +#define S_REPLACE_VID_CTRL REG_SW_CTRL_4
> +#define S_PASS_PAUSE_CTRL REG_SW_CTRL_10
> +#define S_TAIL_TAG_CTRL REG_SW_CTRL_10
> +#define S_802_1P_PRIO_CTRL REG_SW_CTRL_12
> +#define S_TOS_PRIO_CTRL REG_TOS_PRIO_CTRL_0
> +#define S_IPV6_MLD_CTRL REG_SW_CTRL_21
> +
> +#define IND_ACC_TABLE(table) ((table) << 8)
> +
> +/* Driver set switch broadcast storm protection at 10% rate. */
> +#define BROADCAST_STORM_PROT_RATE 10
> +
> +/* 148,800 frames * 67 ms / 100 */
> +#define BROADCAST_STORM_VALUE 9969
> +
> +/**
> + * STATIC_MAC_TABLE_ADDR 00-0000FFFF-FFFFFFFF
> + * STATIC_MAC_TABLE_FWD_PORTS 00-001F0000-00000000
> + * STATIC_MAC_TABLE_VALID 00-00200000-00000000
> + * STATIC_MAC_TABLE_OVERRIDE 00-00400000-00000000
> + * STATIC_MAC_TABLE_USE_FID 00-00800000-00000000
> + * STATIC_MAC_TABLE_FID 00-7F000000-00000000
> + */
> +
> +#define STATIC_MAC_TABLE_ADDR 0x0000FFFF
> +#define STATIC_MAC_TABLE_FWD_PORTS 0x001F0000
> +#define STATIC_MAC_TABLE_VALID 0x00200000
> +#define STATIC_MAC_TABLE_OVERRIDE 0x00400000
> +#define STATIC_MAC_TABLE_USE_FID 0x00800000
> +#define STATIC_MAC_TABLE_FID 0x7F000000
> +
> +#define STATIC_MAC_FWD_PORTS_S 16
> +#define STATIC_MAC_FID_S 24
> +
> +/**
> + * VLAN_TABLE_FID 00-007F007F-007F007F
> + * VLAN_TABLE_MEMBERSHIP 00-0F800F80-0F800F80
> + * VLAN_TABLE_VALID 00-10001000-10001000
> + */
> +
> +#define VLAN_TABLE_FID 0x007F
> +#define VLAN_TABLE_MEMBERSHIP 0x0F80
> +#define VLAN_TABLE_VALID 0x1000
> +
> +#define VLAN_TABLE_MEMBERSHIP_S 7
> +#define VLAN_TABLE_S 16
> +
> +/**
> + * DYNAMIC_MAC_TABLE_ADDR 00-0000FFFF-FFFFFFFF
> + * DYNAMIC_MAC_TABLE_FID 00-007F0000-00000000
> + * DYNAMIC_MAC_TABLE_NOT_READY 00-00800000-00000000
> + * DYNAMIC_MAC_TABLE_SRC_PORT 00-07000000-00000000
> + * DYNAMIC_MAC_TABLE_TIMESTAMP 00-18000000-00000000
> + * DYNAMIC_MAC_TABLE_ENTRIES 7F-E0000000-00000000
> + * DYNAMIC_MAC_TABLE_MAC_EMPTY 80-00000000-00000000
> + */
> +
> +#define DYNAMIC_MAC_TABLE_ADDR 0x0000FFFF
> +#define DYNAMIC_MAC_TABLE_FID 0x007F0000
> +#define DYNAMIC_MAC_TABLE_SRC_PORT 0x07000000
> +#define DYNAMIC_MAC_TABLE_TIMESTAMP 0x18000000
> +#define DYNAMIC_MAC_TABLE_ENTRIES 0xE0000000
> +
> +#define DYNAMIC_MAC_TABLE_NOT_READY 0x80
> +
> +#define DYNAMIC_MAC_TABLE_ENTRIES_H 0x7F
> +#define DYNAMIC_MAC_TABLE_MAC_EMPTY 0x80
> +
> +#define DYNAMIC_MAC_FID_S 16
> +#define DYNAMIC_MAC_SRC_PORT_S 24
> +#define DYNAMIC_MAC_TIMESTAMP_S 27
> +#define DYNAMIC_MAC_ENTRIES_S 29
> +#define DYNAMIC_MAC_ENTRIES_H_S 3
> +
> +/**
> + * MIB_COUNTER_VALUE 00-00000000-3FFFFFFF
> + * MIB_TOTAL_BYTES 00-0000000F-FFFFFFFF
> + * MIB_PACKET_DROPPED 00-00000000-0000FFFF
> + * MIB_COUNTER_VALID 00-00000020-00000000
> + * MIB_COUNTER_OVERFLOW 00-00000040-00000000
> + */
> +
> +#define MIB_COUNTER_OVERFLOW BIT(6)
> +#define MIB_COUNTER_VALID BIT(5)
> +
> +#define MIB_COUNTER_VALUE 0x3FFFFFFF
> +
> +#define KS_MIB_TOTAL_RX_0 0x100
> +#define KS_MIB_TOTAL_TX_0 0x101
> +#define KS_MIB_PACKET_DROPPED_RX_0 0x102
> +#define KS_MIB_PACKET_DROPPED_TX_0 0x103
> +#define KS_MIB_TOTAL_RX_1 0x104
> +#define KS_MIB_TOTAL_TX_1 0x105
> +#define KS_MIB_PACKET_DROPPED_TX_1 0x106
> +#define KS_MIB_PACKET_DROPPED_RX_1 0x107
> +#define KS_MIB_TOTAL_RX_2 0x108
> +#define KS_MIB_TOTAL_TX_2 0x109
> +#define KS_MIB_PACKET_DROPPED_TX_2 0x10A
> +#define KS_MIB_PACKET_DROPPED_RX_2 0x10B
> +#define KS_MIB_TOTAL_RX_3 0x10C
> +#define KS_MIB_TOTAL_TX_3 0x10D
> +#define KS_MIB_PACKET_DROPPED_TX_3 0x10E
> +#define KS_MIB_PACKET_DROPPED_RX_3 0x10F
> +#define KS_MIB_TOTAL_RX_4 0x110
> +#define KS_MIB_TOTAL_TX_4 0x111
> +#define KS_MIB_PACKET_DROPPED_TX_4 0x112
> +#define KS_MIB_PACKET_DROPPED_RX_4 0x113
> +
> +#define MIB_PACKET_DROPPED 0x0000FFFF
> +
> +#define MIB_TOTAL_BYTES_H 0x0000000F
> +
> +#define TAIL_TAG_OVERRIDE BIT(6)
> +#define TAIL_TAG_LOOKUP BIT(7)
> +
> +#define VLAN_TABLE_ENTRIES (4096 / 4)
> +#define FID_ENTRIES 128
> +
> +#endif
> diff --git a/drivers/net/dsa/microchip/ksz8795_spi.c b/drivers/net/dsa/microchip/ksz8795_spi.c
> new file mode 100644
> index 0000000..48d0a2c
> --- /dev/null
> +++ b/drivers/net/dsa/microchip/ksz8795_spi.c
> @@ -0,0 +1,166 @@
> +/*
> + * Microchip KSZ8795 series register access through SPI
> + *
> + * Copyright (C) 2017 Microchip Technology Inc.
> + * Tristram Ha <Tristram.Ha@microchip.com>
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License
> + * as published by the Free Software Foundation; either version 2
> + * of the License, or (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include <asm/unaligned.h>
> +
> +#include <linux/delay.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/spi/spi.h>
> +
> +#include "ksz_priv.h"
> +#include "ksz_spi.h"
> +
> +/* SPI frame opcodes */
> +#define KS_SPIOP_RD 3
> +#define KS_SPIOP_WR 2
> +
> +#define SPI_ADDR_S 12
> +#define SPI_ADDR_M (BIT(SPI_ADDR_S) - 1)
> +#define SPI_TURNAROUND_S 1
> +
> +/* Enough to read all switch registers. */
> +#define SPI_TX_BUF_LEN 0x100
> +
> +static int ksz8795_spi_read_reg(struct spi_device *spi, u32 reg, u8 *val,
> + unsigned int len)
> +{
> + u16 txbuf;
> + int ret;
> +
> + txbuf = reg & SPI_ADDR_M;
> + txbuf |= KS_SPIOP_RD << SPI_ADDR_S;
> + txbuf <<= SPI_TURNAROUND_S;
> + txbuf = cpu_to_be16(txbuf);
> +
> + ret = spi_write_then_read(spi, &txbuf, 2, val, len);
> + return ret;
> +}
> +
> +static int ksz8795_spi_write_reg(struct spi_device *spi, u32 reg, u8 *val,
> + unsigned int len)
> +{
> + u16 *txbuf = (u16 *)val;
> +
> + *txbuf = reg & SPI_ADDR_M;
> + *txbuf |= (KS_SPIOP_WR << SPI_ADDR_S);
> + *txbuf <<= SPI_TURNAROUND_S;
> + *txbuf = cpu_to_be16(*txbuf);
> +
> + return spi_write(spi, txbuf, 2 + len);
> +}
> +
> +static int ksz_spi_read(struct ksz_device *dev, u32 reg, u8 *data,
> + unsigned int len)
> +{
> + struct spi_device *spi = dev->priv;
> +
> + return ksz8795_spi_read_reg(spi, reg, data, len);
> +}
> +
> +static int ksz_spi_write(struct ksz_device *dev, u32 reg, void *data,
> + unsigned int len)
> +{
> + struct spi_device *spi = dev->priv;
> +
> + if (len > SPI_TX_BUF_LEN)
> + len = SPI_TX_BUF_LEN;
> + memcpy(&dev->txbuf[2], data, len);
> + return ksz8795_spi_write_reg(spi, reg, dev->txbuf, len);
> +}
> +
> +static const struct ksz_io_ops ksz8795_spi_ops = {
> + .read8 = ksz_spi_read8,
> + .read16 = ksz_spi_read16,
> + .read32 = ksz_spi_read32,
> + .write8 = ksz_spi_write8,
> + .write16 = ksz_spi_write16,
> + .write32 = ksz_spi_write32,
> + .get = ksz_spi_get,
> + .set = ksz_spi_set,
> +};
> +
> +static int ksz8795_spi_probe(struct spi_device *spi)
> +{
> + struct ksz_device *dev;
> + int ret;
> +
> + dev = ksz_switch_alloc(&spi->dev, &ksz8795_spi_ops, spi);
> + if (!dev)
> + return -ENOMEM;
> +
> + if (spi->dev.platform_data)
> + dev->pdata = spi->dev.platform_data;
> +
> + dev->txbuf = devm_kzalloc(dev->dev, 2 + SPI_TX_BUF_LEN, GFP_KERNEL);
> +
> + ret = ksz8795_switch_register(dev);
> +
> + /* Main DSA driver may not be started yet. */
> + if (ret)
> + return ret;
> +
> + spi_set_drvdata(spi, dev);
> +
> + return 0;
> +}
> +
> +static int ksz8795_spi_remove(struct spi_device *spi)
> +{
> + struct ksz_device *dev = spi_get_drvdata(spi);
> +
> + if (dev)
> + ksz_switch_remove(dev);
> +
> + return 0;
> +}
> +
> +static void ksz8795_spi_shutdown(struct spi_device *spi)
> +{
> + struct ksz_device *dev = spi_get_drvdata(spi);
> +
> + if (dev && dev->dev_ops->shutdown)
> + dev->dev_ops->shutdown(dev);
> +}
> +
> +static const struct of_device_id ksz8795_dt_ids[] = {
> + { .compatible = "microchip,ksz8795" },
> + { .compatible = "microchip,ksz8794" },
> + { .compatible = "microchip,ksz8765" },
> + {},
> +};
> +MODULE_DEVICE_TABLE(of, ksz8795_dt_ids);
> +
> +static struct spi_driver ksz8795_spi_driver = {
> + .driver = {
> + .name = "ksz8795-switch",
> + .owner = THIS_MODULE,
> + .of_match_table = of_match_ptr(ksz8795_dt_ids),
> + },
> + .probe = ksz8795_spi_probe,
> + .remove = ksz8795_spi_remove,
> + .shutdown = ksz8795_spi_shutdown,
> +};
> +
> +module_spi_driver(ksz8795_spi_driver);
> +
> +MODULE_AUTHOR("Tristram Ha <Tristram.Ha@microchip.com>");
> +MODULE_DESCRIPTION("Microchip KSZ8795 Series Switch SPI Driver");
> +MODULE_LICENSE("GPL");
> diff --git a/drivers/net/dsa/microchip/ksz_priv.h b/drivers/net/dsa/microchip/ksz_priv.h
> index 0e1ccd3..6cc92ea 100644
> --- a/drivers/net/dsa/microchip/ksz_priv.h
> +++ b/drivers/net/dsa/microchip/ksz_priv.h
> @@ -177,6 +177,7 @@ int ksz_switch_register(struct ksz_device *dev,
> const struct ksz_dev_ops *ops);
> void ksz_switch_remove(struct ksz_device *dev);
>
> +int ksz8795_switch_register(struct ksz_device *dev);
> int ksz9477_switch_register(struct ksz_device *dev);
>
> #endif
> diff --git a/include/net/dsa.h b/include/net/dsa.h
> index 28cdc5e..6261550 100644
> --- a/include/net/dsa.h
> +++ b/include/net/dsa.h
> @@ -31,6 +31,7 @@ enum dsa_tag_protocol {
> DSA_TAG_PROTO_BRCM,
> DSA_TAG_PROTO_DSA,
> DSA_TAG_PROTO_EDSA,
> + DSA_TAG_PROTO_KSZ8795,
> DSA_TAG_PROTO_KSZ9477,
> DSA_TAG_PROTO_LAN9303,
> DSA_TAG_PROTO_MTK,
> diff --git a/net/dsa/Kconfig b/net/dsa/Kconfig
> index d2bbd21..51769ba 100644
> --- a/net/dsa/Kconfig
> +++ b/net/dsa/Kconfig
> @@ -28,6 +28,10 @@ config NET_DSA_TAG_EDSA
> config NET_DSA_TAG_KSZ
> bool
>
> +config NET_DSA_TAG_KSZ8795
> + bool
> + select NET_DSA_TAG_KSZ
> +
> config NET_DSA_TAG_KSZ9477
> bool
> select NET_DSA_TAG_KSZ
> diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c
> index cc03a09..bb6afb8 100644
> --- a/net/dsa/dsa.c
> +++ b/net/dsa/dsa.c
> @@ -49,6 +49,9 @@ static struct sk_buff *dsa_slave_notag_xmit(struct sk_buff *skb,
> #ifdef CONFIG_NET_DSA_TAG_EDSA
> [DSA_TAG_PROTO_EDSA] = &edsa_netdev_ops,
> #endif
> +#ifdef CONFIG_NET_DSA_TAG_KSZ8795
> + [DSA_TAG_PROTO_KSZ8795] = &ksz8795_netdev_ops,
> +#endif
> #ifdef CONFIG_NET_DSA_TAG_KSZ9477
> [DSA_TAG_PROTO_KSZ9477] = &ksz9477_netdev_ops,
> #endif
> diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h
> index e0dc2d4..542660f 100644
> --- a/net/dsa/dsa_priv.h
> +++ b/net/dsa/dsa_priv.h
> @@ -183,6 +183,7 @@ int dsa_port_vlan_del(struct dsa_port *dp,
> extern const struct dsa_device_ops edsa_netdev_ops;
>
> /* tag_ksz.c */
> +extern const struct dsa_device_ops ksz8795_netdev_ops;
> extern const struct dsa_device_ops ksz9477_netdev_ops;
>
> /* tag_lan9303.c */
> diff --git a/net/dsa/tag_ksz.c b/net/dsa/tag_ksz.c
> index 1bb5b7d..bf3a19a 100644
> --- a/net/dsa/tag_ksz.c
> +++ b/net/dsa/tag_ksz.c
> @@ -18,6 +18,9 @@
> #define KSZ_EGRESS_TAG_LEN 1
> #define KSZ_INGRESS_TAG_LEN 1
>
> +#define KSZ_TAIL_TAG_OVERRIDE BIT(6)
> +#define KSZ_TAIL_TAG_LOOKUP BIT(7)
> +
> /* Frames with following addresse may need to be sent even when the port is
> * closed.
> */
> @@ -90,6 +93,40 @@ static struct sk_buff *ksz_rcv(struct sk_buff *skb, struct net_device *dev,
> return skb;
> }
>
> +static int ksz_get_tag(u8 *tag, int *port)
> +{
> + int len = KSZ_EGRESS_TAG_LEN;
> +
> + *port = tag[0] & 7;
> + return len;
> +}
> +
> +static void ksz8795_set_tag(void *ptr, u8 *addr, int p)
> +{
> + u8 *tag = (u8 *)ptr;
> +
> + *tag = 1 << p;
> + if (!memcmp(addr, special_mult_addr, ETH_ALEN))
> + *tag |= KSZ_TAIL_TAG_OVERRIDE;
> +}
> +
> +static struct sk_buff *ksz8795_xmit(struct sk_buff *skb,
> + struct net_device *dev)
> +{
> + return ksz_xmit(skb, dev, KSZ_INGRESS_TAG_LEN, ksz8795_set_tag);
> +}
> +
> +static struct sk_buff *ksz_sw_rcv(struct sk_buff *skb, struct net_device *dev,
> + struct packet_type *pt)
> +{
> + return ksz_rcv(skb, dev, pt, ksz_get_tag);
> +}
> +
> +const struct dsa_device_ops ksz8795_netdev_ops = {
> + .xmit = ksz8795_xmit,
> + .rcv = ksz_sw_rcv,
> +};
> +
> /* For Ingress (Host -> KSZ9477), 2 bytes are added before FCS.
> * ---------------------------------------------------------------------------
> * DA(6bytes)|SA(6bytes)|....|Data(nbytes)|tag0(1byte)|tag1(1byte)|FCS(4bytes)
> --
> 1.9.1
>
--
Best regards,
Maxim Uvarov
^ permalink raw reply
* Re: [PATCH net] net: enable interface alias removal via rtnl
From: Nicolas Dichtel @ 2017-10-09 8:23 UTC (permalink / raw)
To: Oliver Hartkopp, David Ahern, davem
Cc: netdev, Oliver Hartkopp, Stephen Hemminger
In-Reply-To: <f6bd73fe-9b60-6741-8a6d-c93f6ee64a40@hartkopp.net>
Le 06/10/2017 à 22:10, Oliver Hartkopp a écrit :
>
>
> On 10/06/2017 08:18 PM, David Ahern wrote:
>> On 10/5/17 4:19 AM, Nicolas Dichtel wrote:
>>> IFLA_IFALIAS is defined as NLA_STRING. It means that the minimal length of
>>> the attribute is 1 ("\0"). However, to remove an alias, the attribute
>>> length must be 0 (see dev_set_alias()).
>>
>> why not add a check in dev_set_alias that if len is 1 and the 1
>> character is '\0' it means remove the alias?
Because it requires an iproute2 patch. iproute2 doesn't send the '\0'. With the
command 'ip link set dummy0 alias ""', the attribute length is 0.
A kernel patch is probably enough for this problem. Updating iproute2 on old
distributions is not always easy.
>
> Yes. That looks indeed better than changing NLA_STRING to NLA_BINARY which does
> not really hit the point.
>
> Nicolas, can you send an updated patch picking up David's suggestion?
>
> Tnx & best regards,
> Oliver
>
>>
>>>
>>> Let's define the type to NLA_BINARY, so that the alias can be removed.
>>
>> that changes the uapi
>>
I don't understand what will be broken.
^ permalink raw reply
* RE: [net-next 14/15] i40e: ignore skb->xmit_more when deciding to set RS bit
From: David Laight @ 2017-10-09 9:07 UTC (permalink / raw)
To: 'Jeff Kirsher', davem@davemloft.net
Cc: Jacob Keller, netdev@vger.kernel.org, nhorman@redhat.com,
sassmann@redhat.com, jogreene@redhat.com
In-Reply-To: <20171006175727.868-15-jeffrey.t.kirsher@intel.com>
From: Jeff Kirsher
> Sent: 06 October 2017 18:57
> From: Jacob Keller <jacob.e.keller@intel.com>
>
> Since commit 6a7fded776a7 ("i40e: Fix RS bit update in Tx path and
> disable force WB workaround") we've tried to "optimize" setting the
> RS bit based around skb->xmit_more. This same logic was refactored
> in commit 1dc8b538795f ("i40e: Reorder logic for coalescing RS bits"),
> but ultimately was not functionally changed.
I've tried to understand the above, but without definitions of WB
and RS and the '4-ness' of something it is quite difficult.
I THINK this is all about telling the hardware there is a packet
in the ring to transmit?
I don't understand the 4-ness. Linux requires that the hardware
be notified of a single packet transmit, and that the 'transmit
complete' also be notified in 'a timely manner' for a single packet.
skb->xmit_more ought to be usable to optimise both of these
(assuming it isn't a lie).
The driver would need to ensure a ring full of messages isn't
generated without either wakeup - but that might be 128 frames.
FWIW on the systems I have PCIe writes are relatively cheap
(reads are slow). So different counts would be appropriate
for delaying doorbell writes and requesting completion interrupts.
David
^ permalink raw reply
* RE: [PATCH v2] isdn/gigaset: Convert timers to use timer_setup()
From: David Laight @ 2017-10-09 9:15 UTC (permalink / raw)
To: 'Kees Cook', Paul Bolle
Cc: Karsten Keil, David S. Miller, Johan Hovold, LKML,
gigaset307x-common@lists.sourceforge.net, Network Development
In-Reply-To: <CAGXu5jJaMODs0NNasPY97wiXeQJ-Y5G+qLrFbwquhGJj=o3rxA@mail.gmail.com>
From: Kees Cook
> Sent: 06 October 2017 20:40
...
> I'm in no rush for any specific change. There are about 900 call sites
> I'm making my way through, about 2/3rd are pretty trivial, and the
> less obvious is what I've started sending out now, since I expect some
> will need some more careful review.
Is it worth adding a structure that contains a timer and an extra 'long'
than can be used to maintain the existing API logic for the 'difficult'
cases?
David
^ permalink raw reply
* [patch net-next v2 0/5] mlxsw: Offload bridge device mrouter
From: Jiri Pirko @ 2017-10-09 9:15 UTC (permalink / raw)
To: netdev
Cc: davem, yotamg, idosch, nogahf, mlxsw, ivecera, nikolay, andrew,
stephen, nbd, roopa
From: Jiri Pirko <jiri@mellanox.com>
Yotam says:
Similarly to a bridged port, the bridge device itself can be configured by
the user to be an mrouter port. In this case, all multicast traffic should
be forwarded to it. Make the mlxsw Spectrum driver offload these directives
to the Spectrum hardware.
Patches 1 and 2 add a new switchdev notification for bridge device mrouter
port status and make the bridge module notify about it.
Patches 3-5 change the mlxsw Spectrum driver to handle these notifications
by adding the Spectrum router port to the bridge MDB entries.
---
v1->v2:
- patch1:
- Don't add the MDB_RTR_TYPE_TEMP state and use the timer_pending to
distinguish between learning-on and learning-off states
Yotam Gigi (5):
net: bridge: Notify on bridge device mrouter state changes
net: bridge: Export bridge multicast router state
mlxsw: spectrum: router: Export the mlxsw_sp_router_port function
mlxsw: spectrum_switchdev: Add support for router port in SMID entries
mlxsw: spectrum_switchdev: Support bridge mrouter notifications
.../net/ethernet/mellanox/mlxsw/spectrum_router.c | 2 +-
.../net/ethernet/mellanox/mlxsw/spectrum_router.h | 1 +
.../ethernet/mellanox/mlxsw/spectrum_switchdev.c | 76 +++++++++++++++++++++-
include/linux/if_bridge.h | 5 ++
include/net/switchdev.h | 1 +
net/bridge/br_multicast.c | 50 +++++++++++++-
6 files changed, 128 insertions(+), 7 deletions(-)
--
2.9.5
^ permalink raw reply
* [patch net-next v2 1/5] net: bridge: Notify on bridge device mrouter state changes
From: Jiri Pirko @ 2017-10-09 9:15 UTC (permalink / raw)
To: netdev
Cc: davem, yotamg, idosch, nogahf, mlxsw, ivecera, nikolay, andrew,
stephen, nbd, roopa
In-Reply-To: <20171009091535.1315-1-jiri@resnulli.us>
From: Yotam Gigi <yotamg@mellanox.com>
Add the SWITCHDEV_ATTR_ID_BRIDGE_MROUTER switchdev notification type, used
to indicate whether the bridge is or isn't mrouter. Notify when the bridge
changes its state, similarly to the already existing bridged port mrouter
notifications.
The notification uses the switchdev_attr.u.mrouter boolean flag to indicate
the current bridge mrouter status. Thus, it only indicates whether the
bridge is currently used as an mrouter or not, and does not indicate the
exact mrouter state of the bridge (learning, permanent, etc.).
Signed-off-by: Yotam Gigi <yotamg@mellanox.com>
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
v1->v2:
- use the timer_pending to distinguish between learning-on and
learning-off states
---
include/net/switchdev.h | 1 +
net/bridge/br_multicast.c | 38 +++++++++++++++++++++++++++++++++++---
2 files changed, 36 insertions(+), 3 deletions(-)
diff --git a/include/net/switchdev.h b/include/net/switchdev.h
index d767b79..d756fbe 100644
--- a/include/net/switchdev.h
+++ b/include/net/switchdev.h
@@ -51,6 +51,7 @@ enum switchdev_attr_id {
SWITCHDEV_ATTR_ID_BRIDGE_AGEING_TIME,
SWITCHDEV_ATTR_ID_BRIDGE_VLAN_FILTERING,
SWITCHDEV_ATTR_ID_BRIDGE_MC_DISABLED,
+ SWITCHDEV_ATTR_ID_BRIDGE_MROUTER,
};
struct switchdev_attr {
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c
index 8dc5c8d..bd50550 100644
--- a/net/bridge/br_multicast.c
+++ b/net/bridge/br_multicast.c
@@ -859,8 +859,32 @@ static void br_multicast_router_expired(unsigned long data)
spin_unlock(&br->multicast_lock);
}
+static void br_mc_router_state_change(struct net_bridge *p,
+ bool is_mc_router)
+{
+ struct switchdev_attr attr = {
+ .orig_dev = p->dev,
+ .id = SWITCHDEV_ATTR_ID_BRIDGE_MROUTER,
+ .flags = SWITCHDEV_F_DEFER,
+ .u.mrouter = is_mc_router,
+ };
+
+ switchdev_port_attr_set(p->dev, &attr);
+}
+
static void br_multicast_local_router_expired(unsigned long data)
{
+ struct net_bridge *br = (struct net_bridge *)data;
+
+ spin_lock(&br->multicast_lock);
+ if (br->multicast_router == MDB_RTR_TYPE_DISABLED ||
+ br->multicast_router == MDB_RTR_TYPE_PERM ||
+ timer_pending(&br->multicast_router_timer))
+ goto out;
+
+ br_mc_router_state_change(br, false);
+out:
+ spin_unlock(&br->multicast_lock);
}
static void br_multicast_querier_expired(struct net_bridge *br,
@@ -1364,9 +1388,12 @@ static void br_multicast_mark_router(struct net_bridge *br,
unsigned long now = jiffies;
if (!port) {
- if (br->multicast_router == MDB_RTR_TYPE_TEMP_QUERY)
+ if (br->multicast_router == MDB_RTR_TYPE_TEMP_QUERY) {
+ if (!timer_pending(&br->multicast_router_timer))
+ br_mc_router_state_change(br, true);
mod_timer(&br->multicast_router_timer,
now + br->multicast_querier_interval);
+ }
return;
}
@@ -1952,7 +1979,7 @@ void br_multicast_init(struct net_bridge *br)
spin_lock_init(&br->multicast_lock);
setup_timer(&br->multicast_router_timer,
- br_multicast_local_router_expired, 0);
+ br_multicast_local_router_expired, (unsigned long)br);
setup_timer(&br->ip4_other_query.timer,
br_ip4_multicast_querier_expired, (unsigned long)br);
setup_timer(&br->ip4_own_query.timer, br_ip4_multicast_query_expired,
@@ -2042,9 +2069,14 @@ int br_multicast_set_router(struct net_bridge *br, unsigned long val)
switch (val) {
case MDB_RTR_TYPE_DISABLED:
case MDB_RTR_TYPE_PERM:
+ br_mc_router_state_change(br, val == MDB_RTR_TYPE_PERM);
del_timer(&br->multicast_router_timer);
- /* fall through */
+ br->multicast_router = val;
+ err = 0;
+ break;
case MDB_RTR_TYPE_TEMP_QUERY:
+ if (br->multicast_router != MDB_RTR_TYPE_TEMP_QUERY)
+ br_mc_router_state_change(br, false);
br->multicast_router = val;
err = 0;
break;
--
2.9.5
^ permalink raw reply related
* [patch net-next v2 2/5] net: bridge: Export bridge multicast router state
From: Jiri Pirko @ 2017-10-09 9:15 UTC (permalink / raw)
To: netdev
Cc: davem, yotamg, idosch, nogahf, mlxsw, ivecera, nikolay, andrew,
stephen, nbd, roopa
In-Reply-To: <20171009091535.1315-1-jiri@resnulli.us>
From: Yotam Gigi <yotamg@mellanox.com>
Add an access function that, given a bridge netdevice, returns whether the
bridge device is currently an mrouter or not. The function uses the already
existing br_multicast_is_router function to check that.
This function is needed in order to allow ports that join an already
existing bridge to know the current mrouter state of the bridge device.
Together with the bridge device mrouter ports switchdev notifications, it
is possible to have full offloading of the semantics of the bridge device
mcast router state.
Due to the fact that the bridge multicast router status can change in
packet RX path, take the multicast_router bridge spinlock to protect the
read.
Signed-off-by: Yotam Gigi <yotamg@mellanox.com>
Reviewed-by: Nogah Frankel <nogahf@mellanox.com>
Reviewed-by: Nikolay Aleksandrov <nikolay@cumulusnetworks.com>
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
include/linux/if_bridge.h | 5 +++++
net/bridge/br_multicast.c | 12 ++++++++++++
2 files changed, 17 insertions(+)
diff --git a/include/linux/if_bridge.h b/include/linux/if_bridge.h
index 316ee11..02639eb 100644
--- a/include/linux/if_bridge.h
+++ b/include/linux/if_bridge.h
@@ -64,6 +64,7 @@ int br_multicast_list_adjacent(struct net_device *dev,
bool br_multicast_has_querier_anywhere(struct net_device *dev, int proto);
bool br_multicast_has_querier_adjacent(struct net_device *dev, int proto);
bool br_multicast_enabled(const struct net_device *dev);
+bool br_multicast_router(const struct net_device *dev);
#else
static inline int br_multicast_list_adjacent(struct net_device *dev,
struct list_head *br_ip_list)
@@ -84,6 +85,10 @@ static inline bool br_multicast_enabled(const struct net_device *dev)
{
return false;
}
+static inline bool br_multicast_router(const struct net_device *dev)
+{
+ return false;
+}
#endif
#if IS_ENABLED(CONFIG_BRIDGE) && IS_ENABLED(CONFIG_BRIDGE_VLAN_FILTERING)
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c
index bd50550..7947e04 100644
--- a/net/bridge/br_multicast.c
+++ b/net/bridge/br_multicast.c
@@ -2216,6 +2216,18 @@ bool br_multicast_enabled(const struct net_device *dev)
}
EXPORT_SYMBOL_GPL(br_multicast_enabled);
+bool br_multicast_router(const struct net_device *dev)
+{
+ struct net_bridge *br = netdev_priv(dev);
+ bool is_router;
+
+ spin_lock_bh(&br->multicast_lock);
+ is_router = br_multicast_is_router(br);
+ spin_unlock_bh(&br->multicast_lock);
+ return is_router;
+}
+EXPORT_SYMBOL_GPL(br_multicast_router);
+
int br_multicast_set_querier(struct net_bridge *br, unsigned long val)
{
unsigned long max_delay;
--
2.9.5
^ permalink raw reply related
* [patch net-next v2 3/5] mlxsw: spectrum: router: Export the mlxsw_sp_router_port function
From: Jiri Pirko @ 2017-10-09 9:15 UTC (permalink / raw)
To: netdev
Cc: davem, yotamg, idosch, nogahf, mlxsw, ivecera, nikolay, andrew,
stephen, nbd, roopa
In-Reply-To: <20171009091535.1315-1-jiri@resnulli.us>
From: Yotam Gigi <yotamg@mellanox.com>
In Spectrum hardware, the router port is a virtual port that is the gateway
to the routing mechanism. Hence, in order for a packet to be L3 forwarded,
it must first be L2 forwarded to the router port inside the hardware.
Further patches in this patchset are going to introduce support in bridge
device used as an mrouter port. In this case, the router port index will be
needed in order to update the MDB entries to include the router port. Thus,
export the mlxsw_sp_router_port function, which returns the index of the
Spectrum router port.
Signed-off-by: Yotam Gigi <yotamg@mellanox.com>
Reviewed-by: Nogah Frankel <nogahf@mellanox.com>
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c | 2 +-
drivers/net/ethernet/mellanox/mlxsw/spectrum_router.h | 1 +
2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
index e0f8ea4..a072903 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
@@ -5957,7 +5957,7 @@ static int mlxsw_sp_rif_vlan_fid_op(struct mlxsw_sp_rif *rif,
return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ritr), ritr_pl);
}
-static u8 mlxsw_sp_router_port(const struct mlxsw_sp *mlxsw_sp)
+u8 mlxsw_sp_router_port(const struct mlxsw_sp *mlxsw_sp)
{
return mlxsw_core_max_ports(mlxsw_sp->core) + 1;
}
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.h
index 3d44918..3f2d840 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.h
@@ -70,6 +70,7 @@ u16 mlxsw_sp_rif_index(const struct mlxsw_sp_rif *rif);
u16 mlxsw_sp_ipip_lb_rif_index(const struct mlxsw_sp_rif_ipip_lb *rif);
u16 mlxsw_sp_ipip_lb_ul_vr_id(const struct mlxsw_sp_rif_ipip_lb *rif);
int mlxsw_sp_rif_dev_ifindex(const struct mlxsw_sp_rif *rif);
+u8 mlxsw_sp_router_port(const struct mlxsw_sp *mlxsw_sp);
const struct net_device *mlxsw_sp_rif_dev(const struct mlxsw_sp_rif *rif);
int mlxsw_sp_rif_counter_value_get(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_rif *rif,
--
2.9.5
^ permalink raw reply related
* [patch net-next v2 4/5] mlxsw: spectrum_switchdev: Add support for router port in SMID entries
From: Jiri Pirko @ 2017-10-09 9:15 UTC (permalink / raw)
To: netdev
Cc: davem, yotamg, idosch, nogahf, mlxsw, ivecera, nikolay, andrew,
stephen, nbd, roopa
In-Reply-To: <20171009091535.1315-1-jiri@resnulli.us>
From: Yotam Gigi <yotamg@mellanox.com>
In Spectrum, MDB entries point to MID entries, that indicate which ports a
packet should be forwarded to. Add the support in creating MID entries that
forward the packet to the Spectrum router port.
This will be later used to handle the bridge mrouter port switchdev
notifications.
Signed-off-by: Yotam Gigi <yotamg@mellanox.com>
Reviewed-by: Nogah Frankel <nogahf@mellanox.com>
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c | 13 +++++++++++--
1 file changed, 11 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
index 2cfdf22..4b4584f 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
@@ -49,6 +49,7 @@
#include <linux/netlink.h>
#include <net/switchdev.h>
+#include "spectrum_router.h"
#include "spectrum.h"
#include "core.h"
#include "reg.h"
@@ -1243,7 +1244,8 @@ static int mlxsw_sp_port_mdb_op(struct mlxsw_sp *mlxsw_sp, const char *addr,
}
static int mlxsw_sp_port_smid_full_entry(struct mlxsw_sp *mlxsw_sp, u16 mid_idx,
- long *ports_bitmap)
+ long *ports_bitmap,
+ bool set_router_port)
{
char *smid_pl;
int err, i;
@@ -1258,9 +1260,15 @@ static int mlxsw_sp_port_smid_full_entry(struct mlxsw_sp *mlxsw_sp, u16 mid_idx,
mlxsw_reg_smid_port_mask_set(smid_pl, i, 1);
}
+ mlxsw_reg_smid_port_mask_set(smid_pl,
+ mlxsw_sp_router_port(mlxsw_sp), 1);
+
for_each_set_bit(i, ports_bitmap, mlxsw_core_max_ports(mlxsw_sp->core))
mlxsw_reg_smid_port_set(smid_pl, i, 1);
+ mlxsw_reg_smid_port_set(smid_pl, mlxsw_sp_router_port(mlxsw_sp),
+ set_router_port);
+
err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(smid), smid_pl);
kfree(smid_pl);
return err;
@@ -1364,7 +1372,8 @@ mlxsw_sp_mc_write_mdb_entry(struct mlxsw_sp *mlxsw_sp,
mlxsw_sp_mc_get_mrouters_bitmap(flood_bitmap, bridge_device, mlxsw_sp);
mid->mid = mid_idx;
- err = mlxsw_sp_port_smid_full_entry(mlxsw_sp, mid_idx, flood_bitmap);
+ err = mlxsw_sp_port_smid_full_entry(mlxsw_sp, mid_idx, flood_bitmap,
+ false);
kfree(flood_bitmap);
if (err)
return false;
--
2.9.5
^ permalink raw reply related
* [patch net-next v2 5/5] mlxsw: spectrum_switchdev: Support bridge mrouter notifications
From: Jiri Pirko @ 2017-10-09 9:15 UTC (permalink / raw)
To: netdev
Cc: davem, yotamg, idosch, nogahf, mlxsw, ivecera, nikolay, andrew,
stephen, nbd, roopa
In-Reply-To: <20171009091535.1315-1-jiri@resnulli.us>
From: Yotam Gigi <yotamg@mellanox.com>
Support the SWITCHDEV_ATTR_ID_BRIDGE_MROUTER port attribute switchdev
notification.
To do that, add the mrouter flag to struct mlxsw_sp_bridge_device, which
indicates whether the bridge device was set to be mrouter port. This field
is set when:
- A new bridge is created, where the value is taken from the kernel
bridge value.
- A switchdev SWITCHDEV_ATTR_ID_BRIDGE_MROUTER notification is sent.
In addition, change the bridge MID entries to include the router port when
the bridge device is configured to be mrouter port. The MID entries are
updated in the following cases:
- When a new MID entry is created, update the router port according to the
bridge mrouter state.
- When a SWITCHDEV_ATTR_ID_BRIDGE_MROUTER notification is sent, update all
the bridge's MID entries.
This is aligned with the case where a bridge slave is configured to be
mrouter port.
Signed-off-by: Yotam Gigi <yotamg@mellanox.com>
Reviewed-by: Nogah Frankel <nogahf@mellanox.com>
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
.../ethernet/mellanox/mlxsw/spectrum_switchdev.c | 65 +++++++++++++++++++++-
1 file changed, 63 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
index 4b4584f..7b8548e 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
@@ -80,7 +80,8 @@ struct mlxsw_sp_bridge_device {
struct list_head ports_list;
struct list_head mids_list;
u8 vlan_enabled:1,
- multicast_enabled:1;
+ multicast_enabled:1,
+ mrouter:1;
const struct mlxsw_sp_bridge_ops *ops;
};
@@ -171,6 +172,7 @@ mlxsw_sp_bridge_device_create(struct mlxsw_sp_bridge *bridge,
bridge_device->dev = br_dev;
bridge_device->vlan_enabled = vlan_enabled;
bridge_device->multicast_enabled = br_multicast_enabled(br_dev);
+ bridge_device->mrouter = br_multicast_router(br_dev);
INIT_LIST_HEAD(&bridge_device->ports_list);
if (vlan_enabled) {
bridge->vlan_enabled_exists = true;
@@ -813,6 +815,60 @@ static int mlxsw_sp_port_mc_disabled_set(struct mlxsw_sp_port *mlxsw_sp_port,
return 0;
}
+static int mlxsw_sp_smid_router_port_set(struct mlxsw_sp *mlxsw_sp,
+ u16 mid_idx, bool add)
+{
+ char *smid_pl;
+ int err;
+
+ smid_pl = kmalloc(MLXSW_REG_SMID_LEN, GFP_KERNEL);
+ if (!smid_pl)
+ return -ENOMEM;
+
+ mlxsw_reg_smid_pack(smid_pl, mid_idx,
+ mlxsw_sp_router_port(mlxsw_sp), add);
+ err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(smid), smid_pl);
+ kfree(smid_pl);
+ return err;
+}
+
+static void
+mlxsw_sp_bridge_mrouter_update_mdb(struct mlxsw_sp *mlxsw_sp,
+ struct mlxsw_sp_bridge_device *bridge_device,
+ bool add)
+{
+ struct mlxsw_sp_mid *mid;
+
+ list_for_each_entry(mid, &bridge_device->mids_list, list)
+ mlxsw_sp_smid_router_port_set(mlxsw_sp, mid->mid, add);
+}
+
+static int
+mlxsw_sp_port_attr_br_mrouter_set(struct mlxsw_sp_port *mlxsw_sp_port,
+ struct switchdev_trans *trans,
+ struct net_device *orig_dev,
+ bool is_mrouter)
+{
+ struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
+ struct mlxsw_sp_bridge_device *bridge_device;
+
+ if (switchdev_trans_ph_prepare(trans))
+ return 0;
+
+ /* It's possible we failed to enslave the port, yet this
+ * operation is executed due to it being deferred.
+ */
+ bridge_device = mlxsw_sp_bridge_device_find(mlxsw_sp->bridge, orig_dev);
+ if (!bridge_device)
+ return 0;
+
+ if (bridge_device->mrouter != is_mrouter)
+ mlxsw_sp_bridge_mrouter_update_mdb(mlxsw_sp, bridge_device,
+ is_mrouter);
+ bridge_device->mrouter = is_mrouter;
+ return 0;
+}
+
static int mlxsw_sp_port_attr_set(struct net_device *dev,
const struct switchdev_attr *attr,
struct switchdev_trans *trans)
@@ -850,6 +906,11 @@ static int mlxsw_sp_port_attr_set(struct net_device *dev,
attr->orig_dev,
attr->u.mc_disabled);
break;
+ case SWITCHDEV_ATTR_ID_BRIDGE_MROUTER:
+ err = mlxsw_sp_port_attr_br_mrouter_set(mlxsw_sp_port, trans,
+ attr->orig_dev,
+ attr->u.mrouter);
+ break;
default:
err = -EOPNOTSUPP;
break;
@@ -1373,7 +1434,7 @@ mlxsw_sp_mc_write_mdb_entry(struct mlxsw_sp *mlxsw_sp,
mid->mid = mid_idx;
err = mlxsw_sp_port_smid_full_entry(mlxsw_sp, mid_idx, flood_bitmap,
- false);
+ bridge_device->mrouter);
kfree(flood_bitmap);
if (err)
return false;
--
2.9.5
^ permalink raw reply related
* RE: [PATCH v1 RFC 1/7] Replace license with GPL
From: David Laight @ 2017-10-09 9:18 UTC (permalink / raw)
To: 'Tristram.Ha@microchip.com', Andrew Lunn,
Florian Fainelli, Pavel Machek, Ruediger Schmitt
Cc: muvarov@gmail.com, nathan.leigh.conrad@gmail.com,
vivien.didelot@savoirfairelinux.com, UNGLinuxDriver@microchip.com,
netdev@vger.kernel.org, linux-kernel@vger.kernel.org
In-Reply-To: <1507321985-15097-2-git-send-email-Tristram.Ha@microchip.com>
From: Tristram.Ha@microchip.com
> Sent: 06 October 2017 21:33
> Replace license with GPL.
Don't you need permission from all the people who have updated
the files in order to make this change?
David
^ permalink raw reply
* Re: RIF/VRF overflow in spectrum and reporting errors back to user
From: Ido Schimmel @ 2017-10-09 9:31 UTC (permalink / raw)
To: David Ahern; +Cc: Ido Schimmel, Jiri Pirko, netdev@vger.kernel.org
In-Reply-To: <8d0df382-35d1-7991-1c39-9a2b5d5334e2@gmail.com>
Hi David,
On Sun, Oct 08, 2017 at 02:10:33PM -0600, David Ahern wrote:
> Jiri / Ido:
>
> I am looking at adding user messages for spectrum failures related to
> RIF and VRF overflow coming from the inetaddr and inet6addr notifier
> paths. The key is that if the notifiers fail the address add needs to
> fail and an error reported to the user as to what happened.
Thanks for working on this. Very nice idea!
> Earlier this year 3ad7d2468f79f added in_validator_info and
> in6_validator_info as a way for the notifiers to fail adding an address.
> Adding support to spectrum for that notifier is complicated by the fact
> that the validator notifier and address notifiers will come in back to
> back for the NETDEV_UP case. Ignoring NETDEV_UP in
> mlxsw_sp_inetaddr_event seems ok for IPv6 but not clear for IPv4 since
> the NETDEV_UP case is emitted on an address delete that involves a
> promotion. Handling the back to back NETDEV_UP is complicated since
> functions invoked by __mlxsw_sp_inetaddr_event can take multiple
> references. Specifically, in mlxsw_sp_port_vlan_router_join():
> fid = rif->ops->fid_get(rif);
>
> Can NETDEV_UP be ignored for the inetaddr notifier if it is handled by
> the validator notitifer?
Yes. The case where we get a NETDEV_DOWN for an address delete and then
a NETDEV_UP for a promotion is basically a NOP from the driver's
perspective. When the NETDEV_DOWN is received, the RIF isn't destroyed
because the address list isn't empty (there's an address to be
promoted). When the NETDEV_UP is received, it's ignored because we
already have a RIF.
Regarding IPv6, it's a bit more complicated actually, since we do the
actual work in a workqueue, as the notification chain is atomic. I
believe this is because the notifier can be called from softirq in
response to RA packets.
However, this case isn't interesting for mlxsw, as the fact that you
process an RA packet suggests you already have a link-local address and
thus a RIF. Plus, the kernel won't even process such packets in our case
as you most likely have forwarding enabled (unless you tweaked accept_ra
for some reason).
Looking at ipvlan (the only user of inet6addr_validator_chain), I see
that it ignores this specific case and returns NOTIFY_DONE. Maybe we can
move this notification chain to be blocking and not call it in response
to RA packets seeing that all its users ignore it?
Please let me know if you need my help in any way.
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox