Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
cloud-kernel
提交
d5df7c41
cloud-kernel
项目概览
openanolis
/
cloud-kernel
1 年多 前同步成功
通知
161
Star
36
Fork
7
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
10
列表
看板
标记
里程碑
合并请求
2
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
cloud-kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
10
Issue
10
列表
看板
标记
里程碑
合并请求
2
合并请求
2
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
d5df7c41
编写于
2月 16, 2012
作者:
D
David S. Miller
浏览文件
操作
浏览文件
下载
差异文件
Merge
git://git.kernel.org/pub/scm/linux/kernel/git/bwh/sfc-next
上级
80703d26
cd2d5b52
变更
21
展开全部
隐藏空白更改
内联
并排
Showing
21 changed file
with
3170 addition
and
604 deletion
+3170
-604
drivers/net/ethernet/sfc/Kconfig
drivers/net/ethernet/sfc/Kconfig
+8
-0
drivers/net/ethernet/sfc/Makefile
drivers/net/ethernet/sfc/Makefile
+1
-0
drivers/net/ethernet/sfc/efx.c
drivers/net/ethernet/sfc/efx.c
+397
-288
drivers/net/ethernet/sfc/efx.h
drivers/net/ethernet/sfc/efx.h
+1
-0
drivers/net/ethernet/sfc/ethtool.c
drivers/net/ethernet/sfc/ethtool.c
+44
-18
drivers/net/ethernet/sfc/falcon.c
drivers/net/ethernet/sfc/falcon.c
+8
-4
drivers/net/ethernet/sfc/filter.c
drivers/net/ethernet/sfc/filter.c
+223
-32
drivers/net/ethernet/sfc/filter.h
drivers/net/ethernet/sfc/filter.h
+19
-1
drivers/net/ethernet/sfc/mcdi.c
drivers/net/ethernet/sfc/mcdi.c
+34
-0
drivers/net/ethernet/sfc/mcdi.h
drivers/net/ethernet/sfc/mcdi.h
+2
-0
drivers/net/ethernet/sfc/mcdi_mac.c
drivers/net/ethernet/sfc/mcdi_mac.c
+3
-1
drivers/net/ethernet/sfc/mtd.c
drivers/net/ethernet/sfc/mtd.c
+1
-1
drivers/net/ethernet/sfc/net_driver.h
drivers/net/ethernet/sfc/net_driver.h
+97
-26
drivers/net/ethernet/sfc/nic.c
drivers/net/ethernet/sfc/nic.c
+309
-215
drivers/net/ethernet/sfc/nic.h
drivers/net/ethernet/sfc/nic.h
+99
-3
drivers/net/ethernet/sfc/regs.h
drivers/net/ethernet/sfc/regs.h
+10
-10
drivers/net/ethernet/sfc/rx.c
drivers/net/ethernet/sfc/rx.c
+5
-2
drivers/net/ethernet/sfc/siena.c
drivers/net/ethernet/sfc/siena.c
+12
-2
drivers/net/ethernet/sfc/siena_sriov.c
drivers/net/ethernet/sfc/siena_sriov.c
+1642
-0
drivers/net/ethernet/sfc/tx.c
drivers/net/ethernet/sfc/tx.c
+1
-1
drivers/net/ethernet/sfc/vfdi.h
drivers/net/ethernet/sfc/vfdi.h
+254
-0
未找到文件。
drivers/net/ethernet/sfc/Kconfig
浏览文件 @
d5df7c41
...
...
@@ -26,3 +26,11 @@ config SFC_MCDI_MON
----help---
This exposes the on-board firmware-managed sensors as a
hardware monitor device.
config SFC_SRIOV
bool "Solarflare SFC9000-family SR-IOV support"
depends on SFC && PCI_IOV
default y
---help---
This enables support for the SFC9000 I/O Virtualization
features, allowing accelerated network performance in
virtualized environments.
drivers/net/ethernet/sfc/Makefile
浏览文件 @
d5df7c41
...
...
@@ -4,5 +4,6 @@ sfc-y += efx.o nic.o falcon.o siena.o tx.o rx.o filter.o \
tenxpress.o txc43128_phy.o falcon_boards.o
\
mcdi.o mcdi_phy.o mcdi_mon.o
sfc-$(CONFIG_SFC_MTD)
+=
mtd.o
sfc-$(CONFIG_SFC_SRIOV)
+=
siena_sriov.o
obj-$(CONFIG_SFC)
+=
sfc.o
drivers/net/ethernet/sfc/efx.c
浏览文件 @
d5df7c41
此差异已折叠。
点击以展开。
drivers/net/ethernet/sfc/efx.h
浏览文件 @
d5df7c41
...
...
@@ -95,6 +95,7 @@ static inline void efx_filter_rfs_expire(struct efx_channel *channel) {}
#endif
/* Channels */
extern
int
efx_channel_dummy_op_int
(
struct
efx_channel
*
channel
);
extern
void
efx_process_channel_now
(
struct
efx_channel
*
channel
);
extern
int
efx_realloc_channels
(
struct
efx_nic
*
efx
,
u32
rxq_entries
,
u32
txq_entries
);
...
...
drivers/net/ethernet/sfc/ethtool.c
浏览文件 @
d5df7c41
...
...
@@ -808,11 +808,16 @@ static int efx_ethtool_reset(struct net_device *net_dev, u32 *flags)
return
efx_reset
(
efx
,
rc
);
}
/* MAC address mask including only MC flag */
static
const
u8
mac_addr_mc_mask
[
ETH_ALEN
]
=
{
0x01
,
0
,
0
,
0
,
0
,
0
};
static
int
efx_ethtool_get_class_rule
(
struct
efx_nic
*
efx
,
struct
ethtool_rx_flow_spec
*
rule
)
{
struct
ethtool_tcpip4_spec
*
ip_entry
=
&
rule
->
h_u
.
tcp_ip4_spec
;
struct
ethtool_tcpip4_spec
*
ip_mask
=
&
rule
->
m_u
.
tcp_ip4_spec
;
struct
ethhdr
*
mac_entry
=
&
rule
->
h_u
.
ether_spec
;
struct
ethhdr
*
mac_mask
=
&
rule
->
m_u
.
ether_spec
;
struct
efx_filter_spec
spec
;
u16
vid
;
u8
proto
;
...
...
@@ -828,11 +833,18 @@ static int efx_ethtool_get_class_rule(struct efx_nic *efx,
else
rule
->
ring_cookie
=
spec
.
dmaq_id
;
rc
=
efx_filter_get_eth_local
(
&
spec
,
&
vid
,
rule
->
h_u
.
ether_spec
.
h_dest
);
if
(
spec
.
type
==
EFX_FILTER_MC_DEF
||
spec
.
type
==
EFX_FILTER_UC_DEF
)
{
rule
->
flow_type
=
ETHER_FLOW
;
memcpy
(
mac_mask
->
h_dest
,
mac_addr_mc_mask
,
ETH_ALEN
);
if
(
spec
.
type
==
EFX_FILTER_MC_DEF
)
memcpy
(
mac_entry
->
h_dest
,
mac_addr_mc_mask
,
ETH_ALEN
);
return
0
;
}
rc
=
efx_filter_get_eth_local
(
&
spec
,
&
vid
,
mac_entry
->
h_dest
);
if
(
rc
==
0
)
{
rule
->
flow_type
=
ETHER_FLOW
;
memset
(
rule
->
m_u
.
ether_spec
.
h_dest
,
~
0
,
ETH_ALEN
);
memset
(
mac_mask
->
h_dest
,
~
0
,
ETH_ALEN
);
if
(
vid
!=
EFX_FILTER_VID_UNSPEC
)
{
rule
->
flow_type
|=
FLOW_EXT
;
rule
->
h_ext
.
vlan_tci
=
htons
(
vid
);
...
...
@@ -1001,27 +1013,40 @@ static int efx_ethtool_set_class_rule(struct efx_nic *efx,
}
case
ETHER_FLOW
|
FLOW_EXT
:
/* Must match all or none of VID */
if
(
rule
->
m_ext
.
vlan_tci
!=
htons
(
0xfff
)
&&
rule
->
m_ext
.
vlan_tci
!=
0
)
return
-
EINVAL
;
case
ETHER_FLOW
:
/* Must match all of destination */
if
(
!
is_broadcast_ether_addr
(
mac_mask
->
h_dest
))
return
-
EINVAL
;
/* and nothing else */
case
ETHER_FLOW
:
{
u16
vlan_tag_mask
=
(
rule
->
flow_type
&
FLOW_EXT
?
ntohs
(
rule
->
m_ext
.
vlan_tci
)
:
0
);
/* Must not match on source address or Ethertype */
if
(
!
is_zero_ether_addr
(
mac_mask
->
h_source
)
||
mac_mask
->
h_proto
)
return
-
EINVAL
;
rc
=
efx_filter_set_eth_local
(
&
spec
,
(
rule
->
flow_type
&
FLOW_EXT
&&
rule
->
m_ext
.
vlan_tci
)
?
ntohs
(
rule
->
h_ext
.
vlan_tci
)
:
EFX_FILTER_VID_UNSPEC
,
mac_entry
->
h_dest
);
/* Is it a default UC or MC filter? */
if
(
!
compare_ether_addr
(
mac_mask
->
h_dest
,
mac_addr_mc_mask
)
&&
vlan_tag_mask
==
0
)
{
if
(
is_multicast_ether_addr
(
mac_entry
->
h_dest
))
rc
=
efx_filter_set_mc_def
(
&
spec
);
else
rc
=
efx_filter_set_uc_def
(
&
spec
);
}
/* Otherwise, it must match all of destination and all
* or none of VID.
*/
else
if
(
is_broadcast_ether_addr
(
mac_mask
->
h_dest
)
&&
(
vlan_tag_mask
==
0xfff
||
vlan_tag_mask
==
0
))
{
rc
=
efx_filter_set_eth_local
(
&
spec
,
vlan_tag_mask
?
ntohs
(
rule
->
h_ext
.
vlan_tci
)
:
EFX_FILTER_VID_UNSPEC
,
mac_entry
->
h_dest
);
}
else
{
rc
=
-
EINVAL
;
}
if
(
rc
)
return
rc
;
break
;
}
default:
return
-
EINVAL
;
...
...
@@ -1060,7 +1085,8 @@ static u32 efx_ethtool_get_rxfh_indir_size(struct net_device *net_dev)
{
struct
efx_nic
*
efx
=
netdev_priv
(
net_dev
);
return
(
efx_nic_rev
(
efx
)
<
EFX_REV_FALCON_B0
?
return
((
efx_nic_rev
(
efx
)
<
EFX_REV_FALCON_B0
||
efx
->
n_rx_channels
==
1
)
?
0
:
ARRAY_SIZE
(
efx
->
rx_indir_table
));
}
...
...
drivers/net/ethernet/sfc/falcon.c
浏览文件 @
d5df7c41
...
...
@@ -1333,6 +1333,12 @@ static int falcon_probe_nvconfig(struct efx_nic *efx)
return
rc
;
}
static
void
falcon_dimension_resources
(
struct
efx_nic
*
efx
)
{
efx
->
rx_dc_base
=
0x20000
;
efx
->
tx_dc_base
=
0x26000
;
}
/* Probe all SPI devices on the NIC */
static
void
falcon_probe_spi_devices
(
struct
efx_nic
*
efx
)
{
...
...
@@ -1749,6 +1755,7 @@ const struct efx_nic_type falcon_a1_nic_type = {
.
probe
=
falcon_probe_nic
,
.
remove
=
falcon_remove_nic
,
.
init
=
falcon_init_nic
,
.
dimension_resources
=
falcon_dimension_resources
,
.
fini
=
efx_port_dummy_op_void
,
.
monitor
=
falcon_monitor
,
.
map_reset_reason
=
falcon_map_reset_reason
,
...
...
@@ -1783,8 +1790,6 @@ const struct efx_nic_type falcon_a1_nic_type = {
.
max_interrupt_mode
=
EFX_INT_MODE_MSI
,
.
phys_addr_channels
=
4
,
.
timer_period_max
=
1
<<
FRF_AB_TC_TIMER_VAL_WIDTH
,
.
tx_dc_base
=
0x130000
,
.
rx_dc_base
=
0x100000
,
.
offload_features
=
NETIF_F_IP_CSUM
,
};
...
...
@@ -1792,6 +1797,7 @@ const struct efx_nic_type falcon_b0_nic_type = {
.
probe
=
falcon_probe_nic
,
.
remove
=
falcon_remove_nic
,
.
init
=
falcon_init_nic
,
.
dimension_resources
=
falcon_dimension_resources
,
.
fini
=
efx_port_dummy_op_void
,
.
monitor
=
falcon_monitor
,
.
map_reset_reason
=
falcon_map_reset_reason
,
...
...
@@ -1835,8 +1841,6 @@ const struct efx_nic_type falcon_b0_nic_type = {
* interrupt handler only supports 32
* channels */
.
timer_period_max
=
1
<<
FRF_AB_TC_TIMER_VAL_WIDTH
,
.
tx_dc_base
=
0x130000
,
.
rx_dc_base
=
0x100000
,
.
offload_features
=
NETIF_F_IP_CSUM
|
NETIF_F_RXHASH
|
NETIF_F_NTUPLE
,
};
drivers/net/ethernet/sfc/filter.c
浏览文件 @
d5df7c41
...
...
@@ -35,9 +35,17 @@
enum
efx_filter_table_id
{
EFX_FILTER_TABLE_RX_IP
=
0
,
EFX_FILTER_TABLE_RX_MAC
,
EFX_FILTER_TABLE_RX_DEF
,
EFX_FILTER_TABLE_TX_MAC
,
EFX_FILTER_TABLE_COUNT
,
};
enum
efx_filter_index
{
EFX_FILTER_INDEX_UC_DEF
,
EFX_FILTER_INDEX_MC_DEF
,
EFX_FILTER_SIZE_RX_DEF
,
};
struct
efx_filter_table
{
enum
efx_filter_table_id
id
;
u32
offset
;
/* address of table relative to BAR */
...
...
@@ -90,8 +98,9 @@ efx_filter_spec_table_id(const struct efx_filter_spec *spec)
BUILD_BUG_ON
(
EFX_FILTER_TABLE_RX_IP
!=
(
EFX_FILTER_UDP_WILD
>>
2
));
BUILD_BUG_ON
(
EFX_FILTER_TABLE_RX_MAC
!=
(
EFX_FILTER_MAC_FULL
>>
2
));
BUILD_BUG_ON
(
EFX_FILTER_TABLE_RX_MAC
!=
(
EFX_FILTER_MAC_WILD
>>
2
));
BUILD_BUG_ON
(
EFX_FILTER_TABLE_TX_MAC
!=
EFX_FILTER_TABLE_RX_MAC
+
2
);
EFX_BUG_ON_PARANOID
(
spec
->
type
==
EFX_FILTER_UNSPEC
);
return
spec
->
type
>>
2
;
return
(
spec
->
type
>>
2
)
+
((
spec
->
flags
&
EFX_FILTER_FLAG_TX
)
?
2
:
0
)
;
}
static
struct
efx_filter_table
*
...
...
@@ -109,7 +118,7 @@ static void efx_filter_table_reset_search_depth(struct efx_filter_table *table)
memset
(
table
->
search_depth
,
0
,
sizeof
(
table
->
search_depth
));
}
static
void
efx_filter_push_rx_
limits
(
struct
efx_nic
*
efx
)
static
void
efx_filter_push_rx_
config
(
struct
efx_nic
*
efx
)
{
struct
efx_filter_state
*
state
=
efx
->
filter_state
;
struct
efx_filter_table
*
table
;
...
...
@@ -143,9 +152,58 @@ static void efx_filter_push_rx_limits(struct efx_nic *efx)
FILTER_CTL_SRCH_FUDGE_WILD
);
}
table
=
&
state
->
table
[
EFX_FILTER_TABLE_RX_DEF
];
if
(
table
->
size
)
{
EFX_SET_OWORD_FIELD
(
filter_ctl
,
FRF_CZ_UNICAST_NOMATCH_Q_ID
,
table
->
spec
[
EFX_FILTER_INDEX_UC_DEF
].
dmaq_id
);
EFX_SET_OWORD_FIELD
(
filter_ctl
,
FRF_CZ_UNICAST_NOMATCH_RSS_ENABLED
,
!!
(
table
->
spec
[
EFX_FILTER_INDEX_UC_DEF
].
flags
&
EFX_FILTER_FLAG_RX_RSS
));
EFX_SET_OWORD_FIELD
(
filter_ctl
,
FRF_CZ_UNICAST_NOMATCH_IP_OVERRIDE
,
!!
(
table
->
spec
[
EFX_FILTER_INDEX_UC_DEF
].
flags
&
EFX_FILTER_FLAG_RX_OVERRIDE_IP
));
EFX_SET_OWORD_FIELD
(
filter_ctl
,
FRF_CZ_MULTICAST_NOMATCH_Q_ID
,
table
->
spec
[
EFX_FILTER_INDEX_MC_DEF
].
dmaq_id
);
EFX_SET_OWORD_FIELD
(
filter_ctl
,
FRF_CZ_MULTICAST_NOMATCH_RSS_ENABLED
,
!!
(
table
->
spec
[
EFX_FILTER_INDEX_MC_DEF
].
flags
&
EFX_FILTER_FLAG_RX_RSS
));
EFX_SET_OWORD_FIELD
(
filter_ctl
,
FRF_CZ_MULTICAST_NOMATCH_IP_OVERRIDE
,
!!
(
table
->
spec
[
EFX_FILTER_INDEX_MC_DEF
].
flags
&
EFX_FILTER_FLAG_RX_OVERRIDE_IP
));
}
efx_writeo
(
efx
,
&
filter_ctl
,
FR_BZ_RX_FILTER_CTL
);
}
static
void
efx_filter_push_tx_limits
(
struct
efx_nic
*
efx
)
{
struct
efx_filter_state
*
state
=
efx
->
filter_state
;
struct
efx_filter_table
*
table
;
efx_oword_t
tx_cfg
;
efx_reado
(
efx
,
&
tx_cfg
,
FR_AZ_TX_CFG
);
table
=
&
state
->
table
[
EFX_FILTER_TABLE_TX_MAC
];
if
(
table
->
size
)
{
EFX_SET_OWORD_FIELD
(
tx_cfg
,
FRF_CZ_TX_ETH_FILTER_FULL_SEARCH_RANGE
,
table
->
search_depth
[
EFX_FILTER_MAC_FULL
]
+
FILTER_CTL_SRCH_FUDGE_FULL
);
EFX_SET_OWORD_FIELD
(
tx_cfg
,
FRF_CZ_TX_ETH_FILTER_WILD_SEARCH_RANGE
,
table
->
search_depth
[
EFX_FILTER_MAC_WILD
]
+
FILTER_CTL_SRCH_FUDGE_WILD
);
}
efx_writeo
(
efx
,
&
tx_cfg
,
FR_AZ_TX_CFG
);
}
static
inline
void
__efx_filter_set_ipv4
(
struct
efx_filter_spec
*
spec
,
__be32
host1
,
__be16
port1
,
__be32
host2
,
__be16
port2
)
...
...
@@ -300,7 +358,8 @@ int efx_filter_get_ipv4_full(const struct efx_filter_spec *spec,
int
efx_filter_set_eth_local
(
struct
efx_filter_spec
*
spec
,
u16
vid
,
const
u8
*
addr
)
{
EFX_BUG_ON_PARANOID
(
!
(
spec
->
flags
&
EFX_FILTER_FLAG_RX
));
EFX_BUG_ON_PARANOID
(
!
(
spec
->
flags
&
(
EFX_FILTER_FLAG_RX
|
EFX_FILTER_FLAG_TX
)));
/* This cannot currently be combined with other filtering */
if
(
spec
->
type
!=
EFX_FILTER_UNSPEC
)
...
...
@@ -319,6 +378,52 @@ int efx_filter_set_eth_local(struct efx_filter_spec *spec,
return
0
;
}
/**
* efx_filter_set_uc_def - specify matching otherwise-unmatched unicast
* @spec: Specification to initialise
*/
int
efx_filter_set_uc_def
(
struct
efx_filter_spec
*
spec
)
{
EFX_BUG_ON_PARANOID
(
!
(
spec
->
flags
&
(
EFX_FILTER_FLAG_RX
|
EFX_FILTER_FLAG_TX
)));
if
(
spec
->
type
!=
EFX_FILTER_UNSPEC
)
return
-
EINVAL
;
spec
->
type
=
EFX_FILTER_UC_DEF
;
memset
(
spec
->
data
,
0
,
sizeof
(
spec
->
data
));
/* ensure equality */
return
0
;
}
/**
* efx_filter_set_mc_def - specify matching otherwise-unmatched multicast
* @spec: Specification to initialise
*/
int
efx_filter_set_mc_def
(
struct
efx_filter_spec
*
spec
)
{
EFX_BUG_ON_PARANOID
(
!
(
spec
->
flags
&
(
EFX_FILTER_FLAG_RX
|
EFX_FILTER_FLAG_TX
)));
if
(
spec
->
type
!=
EFX_FILTER_UNSPEC
)
return
-
EINVAL
;
spec
->
type
=
EFX_FILTER_MC_DEF
;
memset
(
spec
->
data
,
0
,
sizeof
(
spec
->
data
));
/* ensure equality */
return
0
;
}
static
void
efx_filter_reset_rx_def
(
struct
efx_nic
*
efx
,
unsigned
filter_idx
)
{
struct
efx_filter_state
*
state
=
efx
->
filter_state
;
struct
efx_filter_table
*
table
=
&
state
->
table
[
EFX_FILTER_TABLE_RX_DEF
];
struct
efx_filter_spec
*
spec
=
&
table
->
spec
[
filter_idx
];
efx_filter_init_rx
(
spec
,
EFX_FILTER_PRI_MANUAL
,
EFX_FILTER_FLAG_RX_RSS
,
0
);
spec
->
type
=
EFX_FILTER_UC_DEF
+
filter_idx
;
table
->
used_bitmap
[
0
]
|=
1
<<
filter_idx
;
}
int
efx_filter_get_eth_local
(
const
struct
efx_filter_spec
*
spec
,
u16
*
vid
,
u8
*
addr
)
{
...
...
@@ -366,6 +471,13 @@ static u32 efx_filter_build(efx_oword_t *filter, struct efx_filter_spec *spec)
break
;
}
case
EFX_FILTER_TABLE_RX_DEF
:
/* One filter spec per type */
BUILD_BUG_ON
(
EFX_FILTER_INDEX_UC_DEF
!=
0
);
BUILD_BUG_ON
(
EFX_FILTER_INDEX_MC_DEF
!=
EFX_FILTER_MC_DEF
-
EFX_FILTER_UC_DEF
);
return
spec
->
type
-
EFX_FILTER_UC_DEF
;
case
EFX_FILTER_TABLE_RX_MAC
:
{
bool
is_wild
=
spec
->
type
==
EFX_FILTER_MAC_WILD
;
EFX_POPULATE_OWORD_8
(
...
...
@@ -385,6 +497,18 @@ static u32 efx_filter_build(efx_oword_t *filter, struct efx_filter_spec *spec)
break
;
}
case
EFX_FILTER_TABLE_TX_MAC
:
{
bool
is_wild
=
spec
->
type
==
EFX_FILTER_MAC_WILD
;
EFX_POPULATE_OWORD_5
(
*
filter
,
FRF_CZ_TMFT_TXQ_ID
,
spec
->
dmaq_id
,
FRF_CZ_TMFT_WILDCARD_MATCH
,
is_wild
,
FRF_CZ_TMFT_SRC_MAC_HI
,
spec
->
data
[
2
],
FRF_CZ_TMFT_SRC_MAC_LO
,
spec
->
data
[
1
],
FRF_CZ_TMFT_VLAN_ID
,
spec
->
data
[
0
]);
data3
=
is_wild
|
spec
->
dmaq_id
<<
1
;
break
;
}
default:
BUG
();
}
...
...
@@ -399,6 +523,10 @@ static bool efx_filter_equal(const struct efx_filter_spec *left,
memcmp
(
left
->
data
,
right
->
data
,
sizeof
(
left
->
data
)))
return
false
;
if
(
left
->
flags
&
EFX_FILTER_FLAG_TX
&&
left
->
dmaq_id
!=
right
->
dmaq_id
)
return
false
;
return
true
;
}
...
...
@@ -448,23 +576,40 @@ static int efx_filter_search(struct efx_filter_table *table,
* MAC filters without overriding behaviour.
*/
#define EFX_FILTER_MATCH_PRI_RX_MAC_OVERRIDE_IP 0
#define EFX_FILTER_MATCH_PRI_RX_DEF_OVERRIDE_IP 1
#define EFX_FILTER_MATCH_PRI_NORMAL_BASE 2
#define EFX_FILTER_INDEX_WIDTH 13
#define EFX_FILTER_INDEX_MASK ((1 << EFX_FILTER_INDEX_WIDTH) - 1)
static
inline
u32
efx_filter_make_id
(
enum
efx_filter_table_id
table_id
,
unsigned
int
index
,
u8
flags
)
{
return
(
table_id
==
EFX_FILTER_TABLE_RX_MAC
&&
flags
&
EFX_FILTER_FLAG_RX_OVERRIDE_IP
)
?
index
:
(
table_id
+
1
)
<<
EFX_FILTER_INDEX_WIDTH
|
index
;
unsigned
int
match_pri
=
EFX_FILTER_MATCH_PRI_NORMAL_BASE
+
table_id
;
if
(
flags
&
EFX_FILTER_FLAG_RX_OVERRIDE_IP
)
{
if
(
table_id
==
EFX_FILTER_TABLE_RX_MAC
)
match_pri
=
EFX_FILTER_MATCH_PRI_RX_MAC_OVERRIDE_IP
;
else
if
(
table_id
==
EFX_FILTER_TABLE_RX_DEF
)
match_pri
=
EFX_FILTER_MATCH_PRI_RX_DEF_OVERRIDE_IP
;
}
return
match_pri
<<
EFX_FILTER_INDEX_WIDTH
|
index
;
}
static
inline
enum
efx_filter_table_id
efx_filter_id_table_id
(
u32
id
)
{
return
(
id
<=
EFX_FILTER_INDEX_MASK
)
?
EFX_FILTER_TABLE_RX_MAC
:
(
id
>>
EFX_FILTER_INDEX_WIDTH
)
-
1
;
unsigned
int
match_pri
=
id
>>
EFX_FILTER_INDEX_WIDTH
;
switch
(
match_pri
)
{
case
EFX_FILTER_MATCH_PRI_RX_MAC_OVERRIDE_IP
:
return
EFX_FILTER_TABLE_RX_MAC
;
case
EFX_FILTER_MATCH_PRI_RX_DEF_OVERRIDE_IP
:
return
EFX_FILTER_TABLE_RX_DEF
;
default:
return
match_pri
-
EFX_FILTER_MATCH_PRI_NORMAL_BASE
;
}
}
static
inline
unsigned
int
efx_filter_id_index
(
u32
id
)
...
...
@@ -474,23 +619,30 @@ static inline unsigned int efx_filter_id_index(u32 id)
static
inline
u8
efx_filter_id_flags
(
u32
id
)
{
return
(
id
<=
EFX_FILTER_INDEX_MASK
)
?
EFX_FILTER_FLAG_RX
|
EFX_FILTER_FLAG_RX_OVERRIDE_IP
:
EFX_FILTER_FLAG_RX
;
unsigned
int
match_pri
=
id
>>
EFX_FILTER_INDEX_WIDTH
;
if
(
match_pri
<
EFX_FILTER_MATCH_PRI_NORMAL_BASE
)
return
EFX_FILTER_FLAG_RX
|
EFX_FILTER_FLAG_RX_OVERRIDE_IP
;
else
if
(
match_pri
<=
EFX_FILTER_MATCH_PRI_NORMAL_BASE
+
EFX_FILTER_TABLE_RX_DEF
)
return
EFX_FILTER_FLAG_RX
;
else
return
EFX_FILTER_FLAG_TX
;
}
u32
efx_filter_get_rx_id_limit
(
struct
efx_nic
*
efx
)
{
struct
efx_filter_state
*
state
=
efx
->
filter_state
;
unsigned
int
table_id
=
EFX_FILTER_TABLE_RX_DEF
;
if
(
state
->
table
[
EFX_FILTER_TABLE_RX_MAC
].
size
!=
0
)
return
((
EFX_FILTER_TABLE_RX_MAC
+
1
)
<<
EFX_FILTER_INDEX_WIDTH
)
+
state
->
table
[
EFX_FILTER_TABLE_RX_MAC
].
size
;
else
if
(
state
->
table
[
EFX_FILTER_TABLE_RX_IP
].
size
!=
0
)
return
((
EFX_FILTER_TABLE_RX_IP
+
1
)
<<
EFX_FILTER_INDEX_WIDTH
)
+
state
->
table
[
EFX_FILTER_TABLE_RX_IP
].
size
;
else
return
0
;
do
{
if
(
state
->
table
[
table_id
].
size
!=
0
)
return
((
EFX_FILTER_MATCH_PRI_NORMAL_BASE
+
table_id
)
<<
EFX_FILTER_INDEX_WIDTH
)
+
state
->
table
[
table_id
].
size
;
}
while
(
table_id
--
)
;
return
0
;
}
/**
...
...
@@ -548,12 +700,20 @@ s32 efx_filter_insert_filter(struct efx_nic *efx, struct efx_filter_spec *spec,
}
*
saved_spec
=
*
spec
;
if
(
table
->
search_depth
[
spec
->
type
]
<
depth
)
{
table
->
search_depth
[
spec
->
type
]
=
depth
;
efx_filter_push_rx_limits
(
efx
);
}
if
(
table
->
id
==
EFX_FILTER_TABLE_RX_DEF
)
{
efx_filter_push_rx_config
(
efx
);
}
else
{
if
(
table
->
search_depth
[
spec
->
type
]
<
depth
)
{
table
->
search_depth
[
spec
->
type
]
=
depth
;
if
(
spec
->
flags
&
EFX_FILTER_FLAG_TX
)
efx_filter_push_tx_limits
(
efx
);
else
efx_filter_push_rx_config
(
efx
);
}
efx_writeo
(
efx
,
&
filter
,
table
->
offset
+
table
->
step
*
filter_idx
);
efx_writeo
(
efx
,
&
filter
,
table
->
offset
+
table
->
step
*
filter_idx
);
}
netif_vdbg
(
efx
,
hw
,
efx
->
net_dev
,
"%s: filter type %d index %d rxq %u set"
,
...
...
@@ -571,7 +731,11 @@ static void efx_filter_table_clear_entry(struct efx_nic *efx,
{
static
efx_oword_t
filter
;
if
(
test_bit
(
filter_idx
,
table
->
used_bitmap
))
{
if
(
table
->
id
==
EFX_FILTER_TABLE_RX_DEF
)
{
/* RX default filters must always exist */
efx_filter_reset_rx_def
(
efx
,
filter_idx
);
efx_filter_push_rx_config
(
efx
);
}
else
if
(
test_bit
(
filter_idx
,
table
->
used_bitmap
))
{
__clear_bit
(
filter_idx
,
table
->
used_bitmap
);
--
table
->
used
;
memset
(
&
table
->
spec
[
filter_idx
],
0
,
sizeof
(
table
->
spec
[
0
]));
...
...
@@ -617,7 +781,8 @@ int efx_filter_remove_id_safe(struct efx_nic *efx,
spin_lock_bh
(
&
state
->
lock
);
if
(
test_bit
(
filter_idx
,
table
->
used_bitmap
)
&&
spec
->
priority
==
priority
&&
spec
->
flags
==
filter_flags
)
{
spec
->
priority
==
priority
&&
!
((
spec
->
flags
^
filter_flags
)
&
EFX_FILTER_FLAG_RX_OVERRIDE_IP
))
{
efx_filter_table_clear_entry
(
efx
,
table
,
filter_idx
);
if
(
table
->
used
==
0
)
efx_filter_table_reset_search_depth
(
table
);
...
...
@@ -668,7 +833,8 @@ int efx_filter_get_filter_safe(struct efx_nic *efx,
spin_lock_bh
(
&
state
->
lock
);
if
(
test_bit
(
filter_idx
,
table
->
used_bitmap
)
&&
spec
->
priority
==
priority
&&
spec
->
flags
==
filter_flags
)
{
spec
->
priority
==
priority
&&
!
((
spec
->
flags
^
filter_flags
)
&
EFX_FILTER_FLAG_RX_OVERRIDE_IP
))
{
*
spec_buf
=
*
spec
;
rc
=
0
;
}
else
{
...
...
@@ -722,7 +888,7 @@ u32 efx_filter_count_rx_used(struct efx_nic *efx,
spin_lock_bh
(
&
state
->
lock
);
for
(
table_id
=
EFX_FILTER_TABLE_RX_IP
;
table_id
<=
EFX_FILTER_TABLE_RX_
MAC
;
table_id
<=
EFX_FILTER_TABLE_RX_
DEF
;
table_id
++
)
{
table
=
&
state
->
table
[
table_id
];
for
(
filter_idx
=
0
;
filter_idx
<
table
->
size
;
filter_idx
++
)
{
...
...
@@ -750,7 +916,7 @@ s32 efx_filter_get_rx_ids(struct efx_nic *efx,
spin_lock_bh
(
&
state
->
lock
);
for
(
table_id
=
EFX_FILTER_TABLE_RX_IP
;
table_id
<=
EFX_FILTER_TABLE_RX_
MAC
;
table_id
<=
EFX_FILTER_TABLE_RX_
DEF
;
table_id
++
)
{
table
=
&
state
->
table
[
table_id
];
for
(
filter_idx
=
0
;
filter_idx
<
table
->
size
;
filter_idx
++
)
{
...
...
@@ -785,6 +951,11 @@ void efx_restore_filters(struct efx_nic *efx)
for
(
table_id
=
0
;
table_id
<
EFX_FILTER_TABLE_COUNT
;
table_id
++
)
{
table
=
&
state
->
table
[
table_id
];
/* Check whether this is a regular register table */
if
(
table
->
step
==
0
)
continue
;
for
(
filter_idx
=
0
;
filter_idx
<
table
->
size
;
filter_idx
++
)
{
if
(
!
test_bit
(
filter_idx
,
table
->
used_bitmap
))
continue
;
...
...
@@ -794,7 +965,8 @@ void efx_restore_filters(struct efx_nic *efx)
}
}
efx_filter_push_rx_limits
(
efx
);
efx_filter_push_rx_config
(
efx
);
efx_filter_push_tx_limits
(
efx
);
spin_unlock_bh
(
&
state
->
lock
);
}
...
...
@@ -833,6 +1005,16 @@ int efx_probe_filters(struct efx_nic *efx)
table
->
offset
=
FR_CZ_RX_MAC_FILTER_TBL0
;
table
->
size
=
FR_CZ_RX_MAC_FILTER_TBL0_ROWS
;
table
->
step
=
FR_CZ_RX_MAC_FILTER_TBL0_STEP
;
table
=
&
state
->
table
[
EFX_FILTER_TABLE_RX_DEF
];
table
->
id
=
EFX_FILTER_TABLE_RX_DEF
;
table
->
size
=
EFX_FILTER_SIZE_RX_DEF
;
table
=
&
state
->
table
[
EFX_FILTER_TABLE_TX_MAC
];
table
->
id
=
EFX_FILTER_TABLE_TX_MAC
;
table
->
offset
=
FR_CZ_TX_MAC_FILTER_TBL0
;
table
->
size
=
FR_CZ_TX_MAC_FILTER_TBL0_ROWS
;
table
->
step
=
FR_CZ_TX_MAC_FILTER_TBL0_STEP
;
}
for
(
table_id
=
0
;
table_id
<
EFX_FILTER_TABLE_COUNT
;
table_id
++
)
{
...
...
@@ -849,6 +1031,15 @@ int efx_probe_filters(struct efx_nic *efx)
goto
fail
;
}
if
(
state
->
table
[
EFX_FILTER_TABLE_RX_DEF
].
size
)
{
/* RX default filters must always exist */
unsigned
i
;
for
(
i
=
0
;
i
<
EFX_FILTER_SIZE_RX_DEF
;
i
++
)
efx_filter_reset_rx_def
(
efx
,
i
);
}
efx_filter_push_rx_config
(
efx
);
return
0
;
fail:
...
...
drivers/net/ethernet/sfc/filter.h
浏览文件 @
d5df7c41
...
...
@@ -20,6 +20,8 @@
* @EFX_FILTER_UDP_WILD: Matching UDP/IPv4 destination (host, port)
* @EFX_FILTER_MAC_FULL: Matching Ethernet destination MAC address, VID
* @EFX_FILTER_MAC_WILD: Matching Ethernet destination MAC address
* @EFX_FILTER_UC_DEF: Matching all otherwise unmatched unicast
* @EFX_FILTER_MC_DEF: Matching all otherwise unmatched multicast
* @EFX_FILTER_UNSPEC: Match type is unspecified
*
* Falcon NICs only support the TCP/IPv4 and UDP/IPv4 filter types.
...
...
@@ -31,6 +33,8 @@ enum efx_filter_type {
EFX_FILTER_UDP_WILD
,
EFX_FILTER_MAC_FULL
=
4
,
EFX_FILTER_MAC_WILD
,
EFX_FILTER_UC_DEF
=
8
,
EFX_FILTER_MC_DEF
,
EFX_FILTER_TYPE_COUNT
,
/* number of specific types */
EFX_FILTER_UNSPEC
=
0xf
,
};
...
...
@@ -39,7 +43,8 @@ enum efx_filter_type {
* enum efx_filter_priority - priority of a hardware filter specification
* @EFX_FILTER_PRI_HINT: Performance hint
* @EFX_FILTER_PRI_MANUAL: Manually configured filter
* @EFX_FILTER_PRI_REQUIRED: Required for correct behaviour
* @EFX_FILTER_PRI_REQUIRED: Required for correct behaviour (user-level
* networking and SR-IOV)
*/
enum
efx_filter_priority
{
EFX_FILTER_PRI_HINT
=
0
,
...
...
@@ -60,12 +65,14 @@ enum efx_filter_priority {
* any IP filter that matches the same packet. By default, IP
* filters take precedence.
* @EFX_FILTER_FLAG_RX: Filter is for RX
* @EFX_FILTER_FLAG_TX: Filter is for TX
*/
enum
efx_filter_flags
{
EFX_FILTER_FLAG_RX_RSS
=
0x01
,
EFX_FILTER_FLAG_RX_SCATTER
=
0x02
,
EFX_FILTER_FLAG_RX_OVERRIDE_IP
=
0x04
,
EFX_FILTER_FLAG_RX
=
0x08
,
EFX_FILTER_FLAG_TX
=
0x10
,
};
/**
...
...
@@ -103,6 +110,15 @@ static inline void efx_filter_init_rx(struct efx_filter_spec *spec,
spec
->
dmaq_id
=
rxq_id
;
}
static
inline
void
efx_filter_init_tx
(
struct
efx_filter_spec
*
spec
,
unsigned
txq_id
)
{
spec
->
type
=
EFX_FILTER_UNSPEC
;
spec
->
priority
=
EFX_FILTER_PRI_REQUIRED
;
spec
->
flags
=
EFX_FILTER_FLAG_TX
;
spec
->
dmaq_id
=
txq_id
;
}
extern
int
efx_filter_set_ipv4_local
(
struct
efx_filter_spec
*
spec
,
u8
proto
,
__be32
host
,
__be16
port
);
extern
int
efx_filter_get_ipv4_local
(
const
struct
efx_filter_spec
*
spec
,
...
...
@@ -117,6 +133,8 @@ extern int efx_filter_set_eth_local(struct efx_filter_spec *spec,
u16
vid
,
const
u8
*
addr
);
extern
int
efx_filter_get_eth_local
(
const
struct
efx_filter_spec
*
spec
,
u16
*
vid
,
u8
*
addr
);
extern
int
efx_filter_set_uc_def
(
struct
efx_filter_spec
*
spec
);
extern
int
efx_filter_set_mc_def
(
struct
efx_filter_spec
*
spec
);
enum
{
EFX_FILTER_VID_UNSPEC
=
0xffff
,
};
...
...
drivers/net/ethernet/sfc/mcdi.c
浏览文件 @
d5df7c41
...
...
@@ -560,6 +560,9 @@ void efx_mcdi_process_event(struct efx_channel *channel,
case
MCDI_EVENT_CODE_MAC_STATS_DMA
:
/* MAC stats are gather lazily. We can ignore this. */
break
;
case
MCDI_EVENT_CODE_FLR
:
efx_sriov_flr
(
efx
,
MCDI_EVENT_FIELD
(
*
event
,
FLR_VF
));
break
;
default:
netif_err
(
efx
,
hw
,
efx
->
net_dev
,
"Unknown MCDI event 0x%x
\n
"
,
...
...
@@ -1154,6 +1157,37 @@ int efx_mcdi_wol_filter_remove(struct efx_nic *efx, int id)
return
rc
;
}
int
efx_mcdi_flush_rxqs
(
struct
efx_nic
*
efx
)
{
struct
efx_channel
*
channel
;
struct
efx_rx_queue
*
rx_queue
;
__le32
*
qid
;
int
rc
,
count
;
qid
=
kmalloc
(
EFX_MAX_CHANNELS
*
sizeof
(
*
qid
),
GFP_KERNEL
);
if
(
qid
==
NULL
)
return
-
ENOMEM
;
count
=
0
;
efx_for_each_channel
(
channel
,
efx
)
{
efx_for_each_channel_rx_queue
(
rx_queue
,
channel
)
{
if
(
rx_queue
->
flush_pending
)
{
rx_queue
->
flush_pending
=
false
;
atomic_dec
(
&
efx
->
rxq_flush_pending
);
qid
[
count
++
]
=
cpu_to_le32
(
efx_rx_queue_index
(
rx_queue
));
}
}
}
rc
=
efx_mcdi_rpc
(
efx
,
MC_CMD_FLUSH_RX_QUEUES
,
(
u8
*
)
qid
,
count
*
sizeof
(
*
qid
),
NULL
,
0
,
NULL
);
WARN_ON
(
rc
>
0
);
kfree
(
qid
);
return
rc
;
}
int
efx_mcdi_wol_filter_reset
(
struct
efx_nic
*
efx
)
{
...
...
drivers/net/ethernet/sfc/mcdi.h
浏览文件 @
d5df7c41
...
...
@@ -146,6 +146,8 @@ extern int efx_mcdi_wol_filter_set_magic(struct efx_nic *efx,
extern
int
efx_mcdi_wol_filter_get_magic
(
struct
efx_nic
*
efx
,
int
*
id_out
);
extern
int
efx_mcdi_wol_filter_remove
(
struct
efx_nic
*
efx
,
int
id
);
extern
int
efx_mcdi_wol_filter_reset
(
struct
efx_nic
*
efx
);
extern
int
efx_mcdi_flush_rxqs
(
struct
efx_nic
*
efx
);
extern
int
efx_mcdi_set_mac
(
struct
efx_nic
*
efx
);
extern
int
efx_mcdi_mac_stats
(
struct
efx_nic
*
efx
,
dma_addr_t
dma_addr
,
u32
dma_len
,
int
enable
,
int
clear
);
extern
int
efx_mcdi_mac_reconfigure
(
struct
efx_nic
*
efx
);
...
...
drivers/net/ethernet/sfc/mcdi_mac.c
浏览文件 @
d5df7c41
...
...
@@ -12,7 +12,7 @@
#include "mcdi.h"
#include "mcdi_pcol.h"
static
int
efx_mcdi_set_mac
(
struct
efx_nic
*
efx
)
int
efx_mcdi_set_mac
(
struct
efx_nic
*
efx
)
{
u32
reject
,
fcntl
;
u8
cmdbytes
[
MC_CMD_SET_MAC_IN_LEN
];
...
...
@@ -44,6 +44,8 @@ static int efx_mcdi_set_mac(struct efx_nic *efx)
}
if
(
efx
->
wanted_fc
&
EFX_FC_AUTO
)
fcntl
=
MC_CMD_FCNTL_AUTO
;
if
(
efx
->
fc_disable
)
fcntl
=
MC_CMD_FCNTL_OFF
;
MCDI_SET_DWORD
(
cmdbytes
,
SET_MAC_IN_FCNTL
,
fcntl
);
...
...
drivers/net/ethernet/sfc/mtd.c
浏览文件 @
d5df7c41
...
...
@@ -280,7 +280,7 @@ static int efx_mtd_probe_device(struct efx_nic *efx, struct efx_mtd *efx_mtd)
--
part
;
efx_mtd_remove_partition
(
part
);
}
/*
mtd_device_register() returns 1 if the MTD table is full
*/
/*
Failure is unlikely here, but probably means we're out of memory
*/
return
-
ENOMEM
;
}
...
...
drivers/net/ethernet/sfc/net_driver.h
浏览文件 @
d5df7c41
...
...
@@ -24,6 +24,7 @@
#include <linux/device.h>
#include <linux/highmem.h>
#include <linux/workqueue.h>
#include <linux/mutex.h>
#include <linux/vmalloc.h>
#include <linux/i2c.h>
...
...
@@ -52,8 +53,10 @@
*
**************************************************************************/
#define EFX_MAX_CHANNELS 32
#define EFX_MAX_CHANNELS 32
U
#define EFX_MAX_RX_QUEUES EFX_MAX_CHANNELS
#define EFX_EXTRA_CHANNEL_IOV 0
#define EFX_MAX_EXTRA_CHANNELS 1U
/* Checksum generation is a per-queue option in hardware, so each
* queue visible to the networking core is backed by two hardware TX
...
...
@@ -81,15 +84,8 @@ struct efx_special_buffer {
void
*
addr
;
dma_addr_t
dma_addr
;
unsigned
int
len
;
int
index
;
int
entries
;
};
enum
efx_flush_state
{
FLUSH_NONE
,
FLUSH_PENDING
,
FLUSH_FAILED
,
FLUSH_DONE
,
unsigned
int
index
;
unsigned
int
entries
;
};
/**
...
...
@@ -138,7 +134,6 @@ struct efx_tx_buffer {
* @txd: The hardware descriptor ring
* @ptr_mask: The size of the ring minus 1.
* @initialised: Has hardware queue been initialised?
* @flushed: Used when handling queue flushing
* @read_count: Current read pointer.
* This is the number of buffers that have been removed from both rings.
* @old_write_count: The value of @write_count when last checked.
...
...
@@ -181,7 +176,6 @@ struct efx_tx_queue {
struct
efx_special_buffer
txd
;
unsigned
int
ptr_mask
;
bool
initialised
;
enum
efx_flush_state
flushed
;
/* Members used mainly on the completion path */
unsigned
int
read_count
____cacheline_aligned_in_smp
;
...
...
@@ -249,6 +243,9 @@ struct efx_rx_page_state {
* @buffer: The software buffer ring
* @rxd: The hardware descriptor ring
* @ptr_mask: The size of the ring minus 1.
* @enabled: Receive queue enabled indicator.
* @flush_pending: Set when a RX flush is pending. Has the same lifetime as
* @rxq_flush_pending.
* @added_count: Number of buffers added to the receive queue.
* @notified_count: Number of buffers given to NIC (<= @added_count).
* @removed_count: Number of buffers removed from the receive queue.
...
...
@@ -263,13 +260,14 @@ struct efx_rx_page_state {
* @alloc_page_count: RX allocation strategy counter.
* @alloc_skb_count: RX allocation strategy counter.
* @slow_fill: Timer used to defer efx_nic_generate_fill_event().
* @flushed: Use when handling queue flushing
*/
struct
efx_rx_queue
{
struct
efx_nic
*
efx
;
struct
efx_rx_buffer
*
buffer
;
struct
efx_special_buffer
rxd
;
unsigned
int
ptr_mask
;
bool
enabled
;
bool
flush_pending
;
int
added_count
;
int
notified_count
;
...
...
@@ -283,8 +281,6 @@ struct efx_rx_queue {
unsigned
int
alloc_skb_count
;
struct
timer_list
slow_fill
;
unsigned
int
slow_fill_count
;
enum
efx_flush_state
flushed
;
};
/**
...
...
@@ -318,6 +314,7 @@ enum efx_rx_alloc_method {
*
* @efx: Associated Efx NIC
* @channel: Channel instance number
* @type: Channel type definition
* @enabled: Channel enabled indicator
* @irq: IRQ number (MSI and MSI-X only)
* @irq_moderation: IRQ moderation value (in hardware ticks)
...
...
@@ -348,6 +345,7 @@ enum efx_rx_alloc_method {
struct
efx_channel
{
struct
efx_nic
*
efx
;
int
channel
;
const
struct
efx_channel_type
*
type
;
bool
enabled
;
int
irq
;
unsigned
int
irq_moderation
;
...
...
@@ -386,6 +384,26 @@ struct efx_channel {
struct
efx_tx_queue
tx_queue
[
EFX_TXQ_TYPES
];
};
/**
* struct efx_channel_type - distinguishes traffic and extra channels
* @handle_no_channel: Handle failure to allocate an extra channel
* @pre_probe: Set up extra state prior to initialisation
* @post_remove: Tear down extra state after finalisation, if allocated.
* May be called on channels that have not been probed.
* @get_name: Generate the channel's name (used for its IRQ handler)
* @copy: Copy the channel state prior to reallocation. May be %NULL if
* reallocation is not supported.
* @keep_eventq: Flag for whether event queue should be kept initialised
* while the device is stopped
*/
struct
efx_channel_type
{
void
(
*
handle_no_channel
)(
struct
efx_nic
*
);
int
(
*
pre_probe
)(
struct
efx_channel
*
);
void
(
*
get_name
)(
struct
efx_channel
*
,
char
*
buf
,
size_t
len
);
struct
efx_channel
*
(
*
copy
)(
const
struct
efx_channel
*
);
bool
keep_eventq
;
};
enum
efx_led_mode
{
EFX_LED_OFF
=
0
,
EFX_LED_ON
=
1
,
...
...
@@ -613,6 +631,8 @@ union efx_multicast_hash {
};
struct
efx_filter_state
;
struct
efx_vf
;
struct
vfdi_status
;
/**
* struct efx_nic - an Efx NIC
...
...
@@ -638,8 +658,13 @@ struct efx_filter_state;
* @rx_queue: RX DMA queues
* @channel: Channels
* @channel_name: Names for channels and their IRQs
* @extra_channel_types: Types of extra (non-traffic) channels that
* should be allocated for this NIC
* @rxq_entries: Size of receive queues requested by user.
* @txq_entries: Size of transmit queues requested by user.
* @tx_dc_base: Base qword address in SRAM of TX queue descriptor caches
* @rx_dc_base: Base qword address in SRAM of RX queue descriptor caches
* @sram_lim_qw: Qword address limit of SRAM
* @next_buffer_table: First available buffer table id
* @n_channels: Number of channels in use
* @n_rx_channels: Number of channels used for RX (= number of RX queues)
...
...
@@ -677,10 +702,31 @@ struct efx_filter_state;
* @promiscuous: Promiscuous flag. Protected by netif_tx_lock.
* @multicast_hash: Multicast hash table
* @wanted_fc: Wanted flow control flags
* @fc_disable: When non-zero flow control is disabled. Typically used to
* ensure that network back pressure doesn't delay dma queue flushes.
* Serialised by the rtnl lock.
* @mac_work: Work item for changing MAC promiscuity and multicast hash
* @loopback_mode: Loopback status
* @loopback_modes: Supported loopback mode bitmask
* @loopback_selftest: Offline self-test private state
* @drain_pending: Count of RX and TX queues that haven't been flushed and drained.
* @rxq_flush_pending: Count of number of receive queues that need to be flushed.
* Decremented when the efx_flush_rx_queue() is called.
* @rxq_flush_outstanding: Count of number of RX flushes started but not yet
* completed (either success or failure). Not used when MCDI is used to
* flush receive queues.
* @flush_wq: wait queue used by efx_nic_flush_queues() to wait for flush completions.
* @vf: Array of &struct efx_vf objects.
* @vf_count: Number of VFs intended to be enabled.
* @vf_init_count: Number of VFs that have been fully initialised.
* @vi_scale: log2 number of vnics per VF.
* @vf_buftbl_base: The zeroth buffer table index used to back VF queues.
* @vfdi_status: Common VFDI status page to be dmad to VF address space.
* @local_addr_list: List of local addresses. Protected by %local_lock.
* @local_page_list: List of DMA addressable pages used to broadcast
* %local_addr_list. Protected by %local_lock.
* @local_lock: Mutex protecting %local_addr_list and %local_page_list.
* @peer_work: Work item to broadcast peer addresses to VMs.
* @monitor_work: Hardware monitor workitem
* @biu_lock: BIU (bus interface unit) lock
* @last_irq_cpu: Last CPU to handle a possible test interrupt. This
...
...
@@ -720,12 +766,18 @@ struct efx_nic {
struct
efx_channel
*
channel
[
EFX_MAX_CHANNELS
];
char
channel_name
[
EFX_MAX_CHANNELS
][
IFNAMSIZ
+
6
];
const
struct
efx_channel_type
*
extra_channel_type
[
EFX_MAX_EXTRA_CHANNELS
];
unsigned
rxq_entries
;
unsigned
txq_entries
;
unsigned
tx_dc_base
;
unsigned
rx_dc_base
;
unsigned
sram_lim_qw
;
unsigned
next_buffer_table
;
unsigned
n_channels
;
unsigned
n_rx_channels
;
unsigned
rss_spread
;
unsigned
tx_channel_offset
;
unsigned
n_tx_channels
;
unsigned
int
rx_buffer_len
;
...
...
@@ -769,6 +821,7 @@ struct efx_nic {
bool
promiscuous
;
union
efx_multicast_hash
multicast_hash
;
u8
wanted_fc
;
unsigned
fc_disable
;
atomic_t
rx_reset
;
enum
efx_loopback_mode
loopback_mode
;
...
...
@@ -778,6 +831,25 @@ struct efx_nic {
struct
efx_filter_state
*
filter_state
;
atomic_t
drain_pending
;
atomic_t
rxq_flush_pending
;
atomic_t
rxq_flush_outstanding
;
wait_queue_head_t
flush_wq
;
#ifdef CONFIG_SFC_SRIOV
struct
efx_channel
*
vfdi_channel
;
struct
efx_vf
*
vf
;
unsigned
vf_count
;
unsigned
vf_init_count
;
unsigned
vi_scale
;
unsigned
vf_buftbl_base
;
struct
efx_buffer
vfdi_status
;
struct
list_head
local_addr_list
;
struct
list_head
local_page_list
;
struct
mutex
local_lock
;
struct
work_struct
peer_work
;
#endif
/* The following fields may be written more often */
struct
delayed_work
monitor_work
____cacheline_aligned_in_smp
;
...
...
@@ -803,6 +875,8 @@ static inline unsigned int efx_port_num(struct efx_nic *efx)
* @probe: Probe the controller
* @remove: Free resources allocated by probe()
* @init: Initialise the controller
* @dimension_resources: Dimension controller resources (buffer table,
* and VIs once the available interrupt resources are clear)
* @fini: Shut down the controller
* @monitor: Periodic function for polling link state and hardware monitor
* @map_reset_reason: Map ethtool reset reason to a reset method
...
...
@@ -842,8 +916,6 @@ static inline unsigned int efx_port_num(struct efx_nic *efx)
* @phys_addr_channels: Number of channels with physically addressed
* descriptors
* @timer_period_max: Maximum period of interrupt timer (in ticks)
* @tx_dc_base: Base address in SRAM of TX queue descriptor caches
* @rx_dc_base: Base address in SRAM of RX queue descriptor caches
* @offload_features: net_device feature flags for protocol offload
* features implemented in hardware
*/
...
...
@@ -851,6 +923,7 @@ struct efx_nic_type {
int
(
*
probe
)(
struct
efx_nic
*
efx
);
void
(
*
remove
)(
struct
efx_nic
*
efx
);
int
(
*
init
)(
struct
efx_nic
*
efx
);
void
(
*
dimension_resources
)(
struct
efx_nic
*
efx
);
void
(
*
fini
)(
struct
efx_nic
*
efx
);
void
(
*
monitor
)(
struct
efx_nic
*
efx
);
enum
reset_type
(
*
map_reset_reason
)(
enum
reset_type
reason
);
...
...
@@ -887,8 +960,6 @@ struct efx_nic_type {
unsigned
int
max_interrupt_mode
;
unsigned
int
phys_addr_channels
;
unsigned
int
timer_period_max
;
unsigned
int
tx_dc_base
;
unsigned
int
rx_dc_base
;
netdev_features_t
offload_features
;
};
...
...
@@ -912,6 +983,13 @@ efx_get_channel(struct efx_nic *efx, unsigned index)
_channel = (_channel->channel + 1 < (_efx)->n_channels) ? \
(_efx)->channel[_channel->channel + 1] : NULL)
/* Iterate over all used channels in reverse */
#define efx_for_each_channel_rev(_channel, _efx) \
for (_channel = (_efx)->channel[(_efx)->n_channels - 1]; \
_channel; \
_channel = _channel->channel ? \
(_efx)->channel[_channel->channel - 1] : NULL)
static
inline
struct
efx_tx_queue
*
efx_get_tx_queue
(
struct
efx_nic
*
efx
,
unsigned
index
,
unsigned
type
)
{
...
...
@@ -956,13 +1034,6 @@ static inline bool efx_tx_queue_used(struct efx_tx_queue *tx_queue)
_tx_queue < (_channel)->tx_queue + EFX_TXQ_TYPES; \
_tx_queue++)
static
inline
struct
efx_rx_queue
*
efx_get_rx_queue
(
struct
efx_nic
*
efx
,
unsigned
index
)
{
EFX_BUG_ON_PARANOID
(
index
>=
efx
->
n_rx_channels
);
return
&
efx
->
channel
[
index
]
->
rx_queue
;
}
static
inline
bool
efx_channel_has_rx_queue
(
struct
efx_channel
*
channel
)
{
return
channel
->
channel
<
channel
->
efx
->
n_rx_channels
;
...
...
drivers/net/ethernet/sfc/nic.c
浏览文件 @
d5df7c41
此差异已折叠。
点击以展开。
drivers/net/ethernet/sfc/nic.h
浏览文件 @
d5df7c41
...
...
@@ -65,6 +65,11 @@ enum {
#define FALCON_GMAC_LOOPBACKS \
(1 << LOOPBACK_GMAC)
/* Alignment of PCIe DMA boundaries (4KB) */
#define EFX_PAGE_SIZE 4096
/* Size and alignment of buffer table entries (same) */
#define EFX_BUF_SIZE EFX_PAGE_SIZE
/**
* struct falcon_board_type - board operations and type information
* @id: Board type id, as found in NVRAM
...
...
@@ -164,6 +169,95 @@ static inline struct efx_mcdi_mon *efx_mcdi_mon(struct efx_nic *efx)
}
#endif
/*
* On the SFC9000 family each port is associated with 1 PCI physical
* function (PF) handled by sfc and a configurable number of virtual
* functions (VFs) that may be handled by some other driver, often in
* a VM guest. The queue pointer registers are mapped in both PF and
* VF BARs such that an 8K region provides access to a single RX, TX
* and event queue (collectively a Virtual Interface, VI or VNIC).
*
* The PF has access to all 1024 VIs while VFs are mapped to VIs
* according to VI_BASE and VI_SCALE: VF i has access to VIs numbered
* in range [VI_BASE + i << VI_SCALE, VI_BASE + i + 1 << VI_SCALE).
* The number of VIs and the VI_SCALE value are configurable but must
* be established at boot time by firmware.
*/
/* Maximum VI_SCALE parameter supported by Siena */
#define EFX_VI_SCALE_MAX 6
/* Base VI to use for SR-IOV. Must be aligned to (1 << EFX_VI_SCALE_MAX),
* so this is the smallest allowed value. */
#define EFX_VI_BASE 128U
/* Maximum number of VFs allowed */
#define EFX_VF_COUNT_MAX 127
/* Limit EVQs on VFs to be only 8k to reduce buffer table reservation */
#define EFX_MAX_VF_EVQ_SIZE 8192UL
/* The number of buffer table entries reserved for each VI on a VF */
#define EFX_VF_BUFTBL_PER_VI \
((EFX_MAX_VF_EVQ_SIZE + 2 * EFX_MAX_DMAQ_SIZE) * \
sizeof(efx_qword_t) / EFX_BUF_SIZE)
#ifdef CONFIG_SFC_SRIOV
static
inline
bool
efx_sriov_wanted
(
struct
efx_nic
*
efx
)
{
return
efx
->
vf_count
!=
0
;
}
static
inline
bool
efx_sriov_enabled
(
struct
efx_nic
*
efx
)
{
return
efx
->
vf_init_count
!=
0
;
}
static
inline
unsigned
int
efx_vf_size
(
struct
efx_nic
*
efx
)
{
return
1
<<
efx
->
vi_scale
;
}
extern
int
efx_init_sriov
(
void
);
extern
void
efx_sriov_probe
(
struct
efx_nic
*
efx
);
extern
int
efx_sriov_init
(
struct
efx_nic
*
efx
);
extern
void
efx_sriov_mac_address_changed
(
struct
efx_nic
*
efx
);
extern
void
efx_sriov_tx_flush_done
(
struct
efx_nic
*
efx
,
efx_qword_t
*
event
);
extern
void
efx_sriov_rx_flush_done
(
struct
efx_nic
*
efx
,
efx_qword_t
*
event
);
extern
void
efx_sriov_event
(
struct
efx_channel
*
channel
,
efx_qword_t
*
event
);
extern
void
efx_sriov_desc_fetch_err
(
struct
efx_nic
*
efx
,
unsigned
dmaq
);
extern
void
efx_sriov_flr
(
struct
efx_nic
*
efx
,
unsigned
flr
);
extern
void
efx_sriov_reset
(
struct
efx_nic
*
efx
);
extern
void
efx_sriov_fini
(
struct
efx_nic
*
efx
);
extern
void
efx_fini_sriov
(
void
);
#else
static
inline
bool
efx_sriov_wanted
(
struct
efx_nic
*
efx
)
{
return
false
;
}
static
inline
bool
efx_sriov_enabled
(
struct
efx_nic
*
efx
)
{
return
false
;
}
static
inline
unsigned
int
efx_vf_size
(
struct
efx_nic
*
efx
)
{
return
0
;
}
static
inline
int
efx_init_sriov
(
void
)
{
return
0
;
}
static
inline
void
efx_sriov_probe
(
struct
efx_nic
*
efx
)
{}
static
inline
int
efx_sriov_init
(
struct
efx_nic
*
efx
)
{
return
-
EOPNOTSUPP
;
}
static
inline
void
efx_sriov_mac_address_changed
(
struct
efx_nic
*
efx
)
{}
static
inline
void
efx_sriov_tx_flush_done
(
struct
efx_nic
*
efx
,
efx_qword_t
*
event
)
{}
static
inline
void
efx_sriov_rx_flush_done
(
struct
efx_nic
*
efx
,
efx_qword_t
*
event
)
{}
static
inline
void
efx_sriov_event
(
struct
efx_channel
*
channel
,
efx_qword_t
*
event
)
{}
static
inline
void
efx_sriov_desc_fetch_err
(
struct
efx_nic
*
efx
,
unsigned
dmaq
)
{}
static
inline
void
efx_sriov_flr
(
struct
efx_nic
*
efx
,
unsigned
flr
)
{}
static
inline
void
efx_sriov_reset
(
struct
efx_nic
*
efx
)
{}
static
inline
void
efx_sriov_fini
(
struct
efx_nic
*
efx
)
{}
static
inline
void
efx_fini_sriov
(
void
)
{}
#endif
extern
int
efx_sriov_set_vf_mac
(
struct
net_device
*
dev
,
int
vf
,
u8
*
mac
);
extern
int
efx_sriov_set_vf_vlan
(
struct
net_device
*
dev
,
int
vf
,
u16
vlan
,
u8
qos
);
extern
int
efx_sriov_get_vf_config
(
struct
net_device
*
dev
,
int
vf
,
struct
ifla_vf_info
*
ivf
);
extern
int
efx_sriov_set_vf_spoofchk
(
struct
net_device
*
net_dev
,
int
vf
,
bool
spoofchk
);
extern
const
struct
efx_nic_type
falcon_a1_nic_type
;
extern
const
struct
efx_nic_type
falcon_b0_nic_type
;
extern
const
struct
efx_nic_type
siena_a0_nic_type
;
...
...
@@ -190,6 +284,7 @@ extern void efx_nic_init_rx(struct efx_rx_queue *rx_queue);
extern
void
efx_nic_fini_rx
(
struct
efx_rx_queue
*
rx_queue
);
extern
void
efx_nic_remove_rx
(
struct
efx_rx_queue
*
rx_queue
);
extern
void
efx_nic_notify_rx_desc
(
struct
efx_rx_queue
*
rx_queue
);
extern
void
efx_nic_generate_fill_event
(
struct
efx_rx_queue
*
rx_queue
);
/* Event data path */
extern
int
efx_nic_probe_eventq
(
struct
efx_channel
*
channel
);
...
...
@@ -211,7 +306,6 @@ extern void falcon_update_stats_xmac(struct efx_nic *efx);
extern
int
efx_nic_init_interrupt
(
struct
efx_nic
*
efx
);
extern
void
efx_nic_enable_interrupts
(
struct
efx_nic
*
efx
);
extern
void
efx_nic_generate_test_event
(
struct
efx_channel
*
channel
);
extern
void
efx_nic_generate_fill_event
(
struct
efx_channel
*
channel
);
extern
void
efx_nic_generate_interrupt
(
struct
efx_nic
*
efx
);
extern
void
efx_nic_disable_interrupts
(
struct
efx_nic
*
efx
);
extern
void
efx_nic_fini_interrupt
(
struct
efx_nic
*
efx
);
...
...
@@ -225,6 +319,8 @@ extern void falcon_start_nic_stats(struct efx_nic *efx);
extern
void
falcon_stop_nic_stats
(
struct
efx_nic
*
efx
);
extern
void
falcon_setup_xaui
(
struct
efx_nic
*
efx
);
extern
int
falcon_reset_xaui
(
struct
efx_nic
*
efx
);
extern
void
efx_nic_dimension_resources
(
struct
efx_nic
*
efx
,
unsigned
sram_lim_qw
);
extern
void
efx_nic_init_common
(
struct
efx_nic
*
efx
);
extern
void
efx_nic_push_rx_indir_table
(
struct
efx_nic
*
efx
);
...
...
@@ -278,8 +374,8 @@ extern void efx_nic_get_regs(struct efx_nic *efx, void *buf);
#define MAC_DATA_LBN 0
#define MAC_DATA_WIDTH 32
extern
void
efx_
nic_generate_event
(
struct
efx_channel
*
channel
,
efx_qword_t
*
event
);
extern
void
efx_
generate_event
(
struct
efx_nic
*
efx
,
unsigned
int
evq
,
efx_qword_t
*
event
);
extern
void
falcon_poll_xmac
(
struct
efx_nic
*
efx
);
...
...
drivers/net/ethernet/sfc/regs.h
浏览文件 @
d5df7c41
...
...
@@ -2446,8 +2446,8 @@
#define FRF_CZ_RMFT_RXQ_ID_WIDTH 12
#define FRF_CZ_RMFT_WILDCARD_MATCH_LBN 60
#define FRF_CZ_RMFT_WILDCARD_MATCH_WIDTH 1
#define FRF_CZ_RMFT_DEST_MAC_LBN 1
6
#define FRF_CZ_RMFT_DEST_MAC_WIDTH 4
4
#define FRF_CZ_RMFT_DEST_MAC_LBN 1
2
#define FRF_CZ_RMFT_DEST_MAC_WIDTH 4
8
#define FRF_CZ_RMFT_VLAN_ID_LBN 0
#define FRF_CZ_RMFT_VLAN_ID_WIDTH 12
...
...
@@ -2523,8 +2523,8 @@
#define FRF_CZ_TMFT_TXQ_ID_WIDTH 12
#define FRF_CZ_TMFT_WILDCARD_MATCH_LBN 60
#define FRF_CZ_TMFT_WILDCARD_MATCH_WIDTH 1
#define FRF_CZ_TMFT_SRC_MAC_LBN 1
6
#define FRF_CZ_TMFT_SRC_MAC_WIDTH 4
4
#define FRF_CZ_TMFT_SRC_MAC_LBN 1
2
#define FRF_CZ_TMFT_SRC_MAC_WIDTH 4
8
#define FRF_CZ_TMFT_VLAN_ID_LBN 0
#define FRF_CZ_TMFT_VLAN_ID_WIDTH 12
...
...
@@ -2895,17 +2895,17 @@
/* RX_MAC_FILTER_TBL0 */
/* RMFT_DEST_MAC is wider than 32 bits */
#define FRF_CZ_RMFT_DEST_MAC_LO_LBN
12
#define FRF_CZ_RMFT_DEST_MAC_LO_LBN
FRF_CZ_RMFT_DEST_MAC_LBN
#define FRF_CZ_RMFT_DEST_MAC_LO_WIDTH 32
#define FRF_CZ_RMFT_DEST_MAC_HI_LBN
44
#define FRF_CZ_RMFT_DEST_MAC_HI_WIDTH
16
#define FRF_CZ_RMFT_DEST_MAC_HI_LBN
(FRF_CZ_RMFT_DEST_MAC_LBN + 32)
#define FRF_CZ_RMFT_DEST_MAC_HI_WIDTH
(FRF_CZ_RMFT_DEST_MAC_WIDTH - 32)
/* TX_MAC_FILTER_TBL0 */
/* TMFT_SRC_MAC is wider than 32 bits */
#define FRF_CZ_TMFT_SRC_MAC_LO_LBN
12
#define FRF_CZ_TMFT_SRC_MAC_LO_LBN
FRF_CZ_TMFT_SRC_MAC_LBN
#define FRF_CZ_TMFT_SRC_MAC_LO_WIDTH 32
#define FRF_CZ_TMFT_SRC_MAC_HI_LBN
44
#define FRF_CZ_TMFT_SRC_MAC_HI_WIDTH
16
#define FRF_CZ_TMFT_SRC_MAC_HI_LBN
(FRF_CZ_TMFT_SRC_MAC_LBN + 32)
#define FRF_CZ_TMFT_SRC_MAC_HI_WIDTH
(FRF_CZ_TMFT_SRC_MAC_WIDTH - 32)
/* TX_PACE_TBL */
/* Values >20 are documented as reserved, but will result in a queue going
...
...
drivers/net/ethernet/sfc/rx.c
浏览文件 @
d5df7c41
...
...
@@ -405,10 +405,9 @@ void efx_fast_push_rx_descriptors(struct efx_rx_queue *rx_queue)
void
efx_rx_slow_fill
(
unsigned
long
context
)
{
struct
efx_rx_queue
*
rx_queue
=
(
struct
efx_rx_queue
*
)
context
;
struct
efx_channel
*
channel
=
efx_rx_queue_channel
(
rx_queue
);
/* Post an event to cause NAPI to run and refill the queue */
efx_nic_generate_fill_event
(
channel
);
efx_nic_generate_fill_event
(
rx_queue
);
++
rx_queue
->
slow_fill_count
;
}
...
...
@@ -706,6 +705,7 @@ void efx_init_rx_queue(struct efx_rx_queue *rx_queue)
rx_queue
->
fast_fill_limit
=
limit
;
/* Set up RX descriptor ring */
rx_queue
->
enabled
=
true
;
efx_nic_init_rx
(
rx_queue
);
}
...
...
@@ -717,6 +717,9 @@ void efx_fini_rx_queue(struct efx_rx_queue *rx_queue)
netif_dbg
(
rx_queue
->
efx
,
drv
,
rx_queue
->
efx
->
net_dev
,
"shutting down RX queue %d
\n
"
,
efx_rx_queue_index
(
rx_queue
));
/* A flush failure might have left rx_queue->enabled */
rx_queue
->
enabled
=
false
;
del_timer_sync
(
&
rx_queue
->
slow_fill
);
efx_nic_fini_rx
(
rx_queue
);
...
...
drivers/net/ethernet/sfc/siena.c
浏览文件 @
d5df7c41
...
...
@@ -225,6 +225,15 @@ static int siena_probe_nvconfig(struct efx_nic *efx)
return
rc
;
}
static
void
siena_dimension_resources
(
struct
efx_nic
*
efx
)
{
/* Each port has a small block of internal SRAM dedicated to
* the buffer table and descriptor caches. In theory we can
* map both blocks to one port, but we don't.
*/
efx_nic_dimension_resources
(
efx
,
FR_CZ_BUF_FULL_TBL_ROWS
/
2
);
}
static
int
siena_probe_nic
(
struct
efx_nic
*
efx
)
{
struct
siena_nic_data
*
nic_data
;
...
...
@@ -304,6 +313,8 @@ static int siena_probe_nic(struct efx_nic *efx)
if
(
rc
)
goto
fail5
;
efx_sriov_probe
(
efx
);
return
0
;
fail5:
...
...
@@ -619,6 +630,7 @@ const struct efx_nic_type siena_a0_nic_type = {
.
probe
=
siena_probe_nic
,
.
remove
=
siena_remove_nic
,
.
init
=
siena_init_nic
,
.
dimension_resources
=
siena_dimension_resources
,
.
fini
=
efx_port_dummy_op_void
,
.
monitor
=
NULL
,
.
map_reset_reason
=
siena_map_reset_reason
,
...
...
@@ -657,8 +669,6 @@ const struct efx_nic_type siena_a0_nic_type = {
* interrupt handler only supports 32
* channels */
.
timer_period_max
=
1
<<
FRF_CZ_TC_TIMER_VAL_WIDTH
,
.
tx_dc_base
=
0x88000
,
.
rx_dc_base
=
0x68000
,
.
offload_features
=
(
NETIF_F_IP_CSUM
|
NETIF_F_IPV6_CSUM
|
NETIF_F_RXHASH
|
NETIF_F_NTUPLE
),
};
drivers/net/ethernet/sfc/siena_sriov.c
0 → 100644
浏览文件 @
d5df7c41
此差异已折叠。
点击以展开。
drivers/net/ethernet/sfc/tx.c
浏览文件 @
d5df7c41
...
...
@@ -110,7 +110,7 @@ efx_max_tx_len(struct efx_nic *efx, dma_addr_t dma_addr)
* little benefit from using descriptors that cross those
* boundaries and we keep things simple by not doing so.
*/
unsigned
len
=
(
~
dma_addr
&
0xfff
)
+
1
;
unsigned
len
=
(
~
dma_addr
&
(
EFX_PAGE_SIZE
-
1
)
)
+
1
;
/* Work around hardware bug for unaligned buffers. */
if
(
EFX_WORKAROUND_5391
(
efx
)
&&
(
dma_addr
&
0xf
))
...
...
drivers/net/ethernet/sfc/vfdi.h
0 → 100644
浏览文件 @
d5df7c41
/****************************************************************************
* Driver for Solarflare Solarstorm network controllers and boards
* Copyright 2010-2012 Solarflare Communications Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published
* by the Free Software Foundation, incorporated herein by reference.
*/
#ifndef _VFDI_H
#define _VFDI_H
/**
* DOC: Virtual Function Driver Interface
*
* This file contains software structures used to form a two way
* communication channel between the VF driver and the PF driver,
* named Virtual Function Driver Interface (VFDI).
*
* For the purposes of VFDI, a page is a memory region with size and
* alignment of 4K. All addresses are DMA addresses to be used within
* the domain of the relevant VF.
*
* The only hardware-defined channels for a VF driver to communicate
* with the PF driver are the event mailboxes (%FR_CZ_USR_EV
* registers). Writing to these registers generates an event with
* EV_CODE = EV_CODE_USR_EV, USER_QID set to the index of the mailbox
* and USER_EV_REG_VALUE set to the value written. The PF driver may
* direct or disable delivery of these events by setting
* %FR_CZ_USR_EV_CFG.
*
* The PF driver can send arbitrary events to arbitrary event queues.
* However, for consistency, VFDI events from the PF are defined to
* follow the same form and be sent to the first event queue assigned
* to the VF while that queue is enabled by the VF driver.
*
* The general form of the variable bits of VFDI events is:
*
* 0 16 24 31
* | DATA | TYPE | SEQ |
*
* SEQ is a sequence number which should be incremented by 1 (modulo
* 256) for each event. The sequence numbers used in each direction
* are independent.
*
* The VF submits requests of type &struct vfdi_req by sending the
* address of the request (ADDR) in a series of 4 events:
*
* 0 16 24 31
* | ADDR[0:15] | VFDI_EV_TYPE_REQ_WORD0 | SEQ |
* | ADDR[16:31] | VFDI_EV_TYPE_REQ_WORD1 | SEQ+1 |
* | ADDR[32:47] | VFDI_EV_TYPE_REQ_WORD2 | SEQ+2 |
* | ADDR[48:63] | VFDI_EV_TYPE_REQ_WORD3 | SEQ+3 |
*
* The address must be page-aligned. After receiving such a valid
* series of events, the PF driver will attempt to read the request
* and write a response to the same address. In case of an invalid
* sequence of events or a DMA error, there will be no response.
*
* The VF driver may request that the PF driver writes status
* information into its domain asynchronously. After writing the
* status, the PF driver will send an event of the form:
*
* 0 16 24 31
* | reserved | VFDI_EV_TYPE_STATUS | SEQ |
*
* In case the VF must be reset for any reason, the PF driver will
* send an event of the form:
*
* 0 16 24 31
* | reserved | VFDI_EV_TYPE_RESET | SEQ |
*
* It is then the responsibility of the VF driver to request
* reinitialisation of its queues.
*/
#define VFDI_EV_SEQ_LBN 24
#define VFDI_EV_SEQ_WIDTH 8
#define VFDI_EV_TYPE_LBN 16
#define VFDI_EV_TYPE_WIDTH 8
#define VFDI_EV_TYPE_REQ_WORD0 0
#define VFDI_EV_TYPE_REQ_WORD1 1
#define VFDI_EV_TYPE_REQ_WORD2 2
#define VFDI_EV_TYPE_REQ_WORD3 3
#define VFDI_EV_TYPE_STATUS 4
#define VFDI_EV_TYPE_RESET 5
#define VFDI_EV_DATA_LBN 0
#define VFDI_EV_DATA_WIDTH 16
struct
vfdi_endpoint
{
u8
mac_addr
[
ETH_ALEN
];
__be16
tci
;
};
/**
* enum vfdi_op - VFDI operation enumeration
* @VFDI_OP_RESPONSE: Indicates a response to the request.
* @VFDI_OP_INIT_EVQ: Initialize SRAM entries and initialize an EVQ.
* @VFDI_OP_INIT_RXQ: Initialize SRAM entries and initialize an RXQ.
* @VFDI_OP_INIT_TXQ: Initialize SRAM entries and initialize a TXQ.
* @VFDI_OP_FINI_ALL_QUEUES: Flush all queues, finalize all queues, then
* finalize the SRAM entries.
* @VFDI_OP_INSERT_FILTER: Insert a MAC filter targetting the given RXQ.
* @VFDI_OP_REMOVE_ALL_FILTERS: Remove all filters.
* @VFDI_OP_SET_STATUS_PAGE: Set the DMA page(s) used for status updates
* from PF and write the initial status.
* @VFDI_OP_CLEAR_STATUS_PAGE: Clear the DMA page(s) used for status
* updates from PF.
*/
enum
vfdi_op
{
VFDI_OP_RESPONSE
=
0
,
VFDI_OP_INIT_EVQ
=
1
,
VFDI_OP_INIT_RXQ
=
2
,
VFDI_OP_INIT_TXQ
=
3
,
VFDI_OP_FINI_ALL_QUEUES
=
4
,
VFDI_OP_INSERT_FILTER
=
5
,
VFDI_OP_REMOVE_ALL_FILTERS
=
6
,
VFDI_OP_SET_STATUS_PAGE
=
7
,
VFDI_OP_CLEAR_STATUS_PAGE
=
8
,
VFDI_OP_LIMIT
,
};
/* Response codes for VFDI operations. Other values may be used in future. */
#define VFDI_RC_SUCCESS 0
#define VFDI_RC_ENOMEM (-12)
#define VFDI_RC_EINVAL (-22)
#define VFDI_RC_EOPNOTSUPP (-95)
#define VFDI_RC_ETIMEDOUT (-110)
/**
* struct vfdi_req - Request from VF driver to PF driver
* @op: Operation code or response indicator, taken from &enum vfdi_op.
* @rc: Response code. Set to 0 on success or a negative error code on failure.
* @u.init_evq.index: Index of event queue to create.
* @u.init_evq.buf_count: Number of 4k buffers backing event queue.
* @u.init_evq.addr: Array of length %u.init_evq.buf_count containing DMA
* address of each page backing the event queue.
* @u.init_rxq.index: Index of receive queue to create.
* @u.init_rxq.buf_count: Number of 4k buffers backing receive queue.
* @u.init_rxq.evq: Instance of event queue to target receive events at.
* @u.init_rxq.label: Label used in receive events.
* @u.init_rxq.flags: Unused.
* @u.init_rxq.addr: Array of length %u.init_rxq.buf_count containing DMA
* address of each page backing the receive queue.
* @u.init_txq.index: Index of transmit queue to create.
* @u.init_txq.buf_count: Number of 4k buffers backing transmit queue.
* @u.init_txq.evq: Instance of event queue to target transmit completion
* events at.
* @u.init_txq.label: Label used in transmit completion events.
* @u.init_txq.flags: Checksum offload flags.
* @u.init_txq.addr: Array of length %u.init_txq.buf_count containing DMA
* address of each page backing the transmit queue.
* @u.mac_filter.rxq: Insert MAC filter at VF local address/VLAN targetting
* all traffic at this receive queue.
* @u.mac_filter.flags: MAC filter flags.
* @u.set_status_page.dma_addr: Base address for the &struct vfdi_status.
* This address must be such that the structure fits within a page.
* @u.set_status_page.peer_page_count: Number of additional pages the VF
* has provided into which peer addresses may be DMAd.
* @u.set_status_page.peer_page_addr: Array of DMA addresses of pages.
* If the number of peers exceeds 256, then the VF must provide
* additional pages in this array. The PF will then DMA up to
* 512 vfdi_endpoint structures into each page. These addresses
* must be page-aligned.
*/
struct
vfdi_req
{
u32
op
;
u32
reserved1
;
s32
rc
;
u32
reserved2
;
union
{
struct
{
u32
index
;
u32
buf_count
;
u64
addr
[];
}
init_evq
;
struct
{
u32
index
;
u32
buf_count
;
u32
evq
;
u32
label
;
u32
flags
;
#define VFDI_RXQ_FLAG_SCATTER_EN 1
u32
reserved
;
u64
addr
[];
}
init_rxq
;
struct
{
u32
index
;
u32
buf_count
;
u32
evq
;
u32
label
;
u32
flags
;
#define VFDI_TXQ_FLAG_IP_CSUM_DIS 1
#define VFDI_TXQ_FLAG_TCPUDP_CSUM_DIS 2
u32
reserved
;
u64
addr
[];
}
init_txq
;
struct
{
u32
rxq
;
u32
flags
;
#define VFDI_MAC_FILTER_FLAG_RSS 1
#define VFDI_MAC_FILTER_FLAG_SCATTER 2
}
mac_filter
;
struct
{
u64
dma_addr
;
u64
peer_page_count
;
u64
peer_page_addr
[];
}
set_status_page
;
}
u
;
};
/**
* struct vfdi_status - Status provided by PF driver to VF driver
* @generation_start: A generation count DMA'd to VF *before* the
* rest of the structure.
* @generation_end: A generation count DMA'd to VF *after* the
* rest of the structure.
* @version: Version of this structure; currently set to 1. Later
* versions must either be layout-compatible or only be sent to VFs
* that specifically request them.
* @length: Total length of this structure including embedded tables
* @vi_scale: log2 the number of VIs available on this VF. This quantity
* is used by the hardware for register decoding.
* @max_tx_channels: The maximum number of transmit queues the VF can use.
* @rss_rxq_count: The number of receive queues present in the shared RSS
* indirection table.
* @peer_count: Total number of peers in the complete peer list. If larger
* than ARRAY_SIZE(%peers), then the VF must provide sufficient
* additional pages each of which is filled with vfdi_endpoint structures.
* @local: The MAC address and outer VLAN tag of *this* VF
* @peers: Table of peer addresses. The @tci fields in these structures
* are currently unused and must be ignored. Additional peers are
* written into any additional pages provided by the VF.
* @timer_quantum_ns: Timer quantum (nominal period between timer ticks)
* for interrupt moderation timers, in nanoseconds. This member is only
* present if @length is sufficiently large.
*/
struct
vfdi_status
{
u32
generation_start
;
u32
generation_end
;
u32
version
;
u32
length
;
u8
vi_scale
;
u8
max_tx_channels
;
u8
rss_rxq_count
;
u8
reserved1
;
u16
peer_count
;
u16
reserved2
;
struct
vfdi_endpoint
local
;
struct
vfdi_endpoint
peers
[
256
];
/* Members below here extend version 1 of this structure */
u32
timer_quantum_ns
;
};
#endif
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录