Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
d5df7c41
Commit
d5df7c41
authored
Feb 16, 2012
by
David S. Miller
Browse files
Options
Browse Files
Download
Plain Diff
Merge
git://git.kernel.org/pub/scm/linux/kernel/git/bwh/sfc-next
parents
80703d26
cd2d5b52
Changes
21
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
21 changed files
with
3170 additions
and
604 deletions
+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
No files found.
drivers/net/ethernet/sfc/Kconfig
View file @
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
View file @
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
View file @
d5df7c41
This diff is collapsed.
Click to expand it.
drivers/net/ethernet/sfc/efx.h
View file @
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
View file @
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
View file @
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
View file @
d5df7c41
This diff is collapsed.
Click to expand it.
drivers/net/ethernet/sfc/filter.h
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
d5df7c41
This diff is collapsed.
Click to expand it.
drivers/net/ethernet/sfc/nic.c
View file @
d5df7c41
This diff is collapsed.
Click to expand it.
drivers/net/ethernet/sfc/nic.h
View file @
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
View file @
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
View file @
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
View file @
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
View file @
d5df7c41
This diff is collapsed.
Click to expand it.
drivers/net/ethernet/sfc/tx.c
View file @
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
View file @
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
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment