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
cf78f8ee
Commit
cf78f8ee
authored
Dec 10, 2010
by
David S. Miller
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'for-davem' of
git://git.kernel.org/pub/scm/linux/kernel/git/bwh/sfc-next-2.6
parents
1e13f863
c39d35eb
Changes
8
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
468 additions
and
306 deletions
+468
-306
drivers/net/sfc/efx.h
drivers/net/sfc/efx.h
+2
-3
drivers/net/sfc/ethtool.c
drivers/net/sfc/ethtool.c
+44
-55
drivers/net/sfc/filter.c
drivers/net/sfc/filter.c
+205
-47
drivers/net/sfc/filter.h
drivers/net/sfc/filter.h
+36
-113
drivers/net/sfc/io.h
drivers/net/sfc/io.h
+88
-65
drivers/net/sfc/net_driver.h
drivers/net/sfc/net_driver.h
+39
-18
drivers/net/sfc/nic.c
drivers/net/sfc/nic.c
+40
-2
drivers/net/sfc/tx.c
drivers/net/sfc/tx.c
+14
-3
No files found.
drivers/net/sfc/efx.h
View file @
cf78f8ee
...
...
@@ -74,9 +74,8 @@ extern int efx_filter_insert_filter(struct efx_nic *efx,
bool
replace
);
extern
int
efx_filter_remove_filter
(
struct
efx_nic
*
efx
,
struct
efx_filter_spec
*
spec
);
extern
void
efx_filter_table_clear
(
struct
efx_nic
*
efx
,
enum
efx_filter_table_id
table_id
,
enum
efx_filter_priority
priority
);
extern
void
efx_filter_clear_rx
(
struct
efx_nic
*
efx
,
enum
efx_filter_priority
priority
);
/* Channels */
extern
void
efx_process_channel_now
(
struct
efx_channel
*
channel
);
...
...
drivers/net/sfc/ethtool.c
View file @
cf78f8ee
...
...
@@ -11,6 +11,7 @@
#include <linux/netdevice.h>
#include <linux/ethtool.h>
#include <linux/rtnetlink.h>
#include <linux/in.h>
#include "net_driver.h"
#include "workarounds.h"
#include "selftest.h"
...
...
@@ -558,12 +559,8 @@ static int efx_ethtool_set_flags(struct net_device *net_dev, u32 data)
if
(
rc
)
return
rc
;
if
(
!
(
data
&
ETH_FLAG_NTUPLE
))
{
efx_filter_table_clear
(
efx
,
EFX_FILTER_TABLE_RX_IP
,
EFX_FILTER_PRI_MANUAL
);
efx_filter_table_clear
(
efx
,
EFX_FILTER_TABLE_RX_MAC
,
EFX_FILTER_PRI_MANUAL
);
}
if
(
!
(
data
&
ETH_FLAG_NTUPLE
))
efx_filter_clear_rx
(
efx
,
EFX_FILTER_PRI_MANUAL
);
return
0
;
}
...
...
@@ -582,6 +579,9 @@ static void efx_ethtool_self_test(struct net_device *net_dev,
goto
fail1
;
}
netif_info
(
efx
,
drv
,
efx
->
net_dev
,
"starting %sline testing
\n
"
,
(
test
->
flags
&
ETH_TEST_FL_OFFLINE
)
?
"off"
:
"on"
);
/* We need rx buffers and interrupts. */
already_up
=
(
efx
->
net_dev
->
flags
&
IFF_UP
);
if
(
!
already_up
)
{
...
...
@@ -600,9 +600,9 @@ static void efx_ethtool_self_test(struct net_device *net_dev,
if
(
!
already_up
)
dev_close
(
efx
->
net_dev
);
netif_
dbg
(
efx
,
drv
,
efx
->
net_dev
,
"%s %sline self-tests
\n
"
,
rc
==
0
?
"passed"
:
"failed"
,
(
test
->
flags
&
ETH_TEST_FL_OFFLINE
)
?
"off"
:
"on"
);
netif_
info
(
efx
,
drv
,
efx
->
net_dev
,
"%s %sline self-tests
\n
"
,
rc
==
0
?
"passed"
:
"failed"
,
(
test
->
flags
&
ETH_TEST_FL_OFFLINE
)
?
"off"
:
"on"
);
fail2:
fail1:
...
...
@@ -921,6 +921,7 @@ static int efx_ethtool_set_rx_ntuple(struct net_device *net_dev,
struct
ethhdr
*
mac_entry
=
&
ntuple
->
fs
.
h_u
.
ether_spec
;
struct
ethhdr
*
mac_mask
=
&
ntuple
->
fs
.
m_u
.
ether_spec
;
struct
efx_filter_spec
filter
;
int
rc
;
/* Range-check action */
if
(
ntuple
->
fs
.
action
<
ETHTOOL_RXNTUPLE_ACTION_CLEAR
||
...
...
@@ -930,9 +931,16 @@ static int efx_ethtool_set_rx_ntuple(struct net_device *net_dev,
if
(
~
ntuple
->
fs
.
data_mask
)
return
-
EINVAL
;
efx_filter_init_rx
(
&
filter
,
EFX_FILTER_PRI_MANUAL
,
0
,
(
ntuple
->
fs
.
action
==
ETHTOOL_RXNTUPLE_ACTION_DROP
)
?
0xfff
:
ntuple
->
fs
.
action
);
switch
(
ntuple
->
fs
.
flow_type
)
{
case
TCP_V4_FLOW
:
case
UDP_V4_FLOW
:
case
UDP_V4_FLOW
:
{
u8
proto
=
(
ntuple
->
fs
.
flow_type
==
TCP_V4_FLOW
?
IPPROTO_TCP
:
IPPROTO_UDP
);
/* Must match all of destination, */
if
(
ip_mask
->
ip4dst
|
ip_mask
->
pdst
)
return
-
EINVAL
;
...
...
@@ -944,7 +952,22 @@ static int efx_ethtool_set_rx_ntuple(struct net_device *net_dev,
/* and nothing else */
if
((
u8
)
~
ip_mask
->
tos
|
(
u16
)
~
ntuple
->
fs
.
vlan_tag_mask
)
return
-
EINVAL
;
if
(
!
ip_mask
->
ip4src
)
rc
=
efx_filter_set_ipv4_full
(
&
filter
,
proto
,
ip_entry
->
ip4dst
,
ip_entry
->
pdst
,
ip_entry
->
ip4src
,
ip_entry
->
psrc
);
else
rc
=
efx_filter_set_ipv4_local
(
&
filter
,
proto
,
ip_entry
->
ip4dst
,
ip_entry
->
pdst
);
if
(
rc
)
return
rc
;
break
;
}
case
ETHER_FLOW
:
/* Must match all of destination, */
if
(
!
is_zero_ether_addr
(
mac_mask
->
h_dest
))
...
...
@@ -957,58 +980,24 @@ static int efx_ethtool_set_rx_ntuple(struct net_device *net_dev,
if
(
!
is_broadcast_ether_addr
(
mac_mask
->
h_source
)
||
mac_mask
->
h_proto
!=
htons
(
0xffff
))
return
-
EINVAL
;
rc
=
efx_filter_set_eth_local
(
&
filter
,
(
ntuple
->
fs
.
vlan_tag_mask
==
0xf000
)
?
ntuple
->
fs
.
vlan_tag
:
EFX_FILTER_VID_UNSPEC
,
mac_entry
->
h_dest
);
if
(
rc
)
return
rc
;
break
;
default:
return
-
EINVAL
;
}
filter
.
priority
=
EFX_FILTER_PRI_MANUAL
;
filter
.
flags
=
0
;
switch
(
ntuple
->
fs
.
flow_type
)
{
case
TCP_V4_FLOW
:
if
(
!
ip_mask
->
ip4src
)
efx_filter_set_rx_tcp_full
(
&
filter
,
htonl
(
ip_entry
->
ip4src
),
htons
(
ip_entry
->
psrc
),
htonl
(
ip_entry
->
ip4dst
),
htons
(
ip_entry
->
pdst
));
else
efx_filter_set_rx_tcp_wild
(
&
filter
,
htonl
(
ip_entry
->
ip4dst
),
htons
(
ip_entry
->
pdst
));
break
;
case
UDP_V4_FLOW
:
if
(
!
ip_mask
->
ip4src
)
efx_filter_set_rx_udp_full
(
&
filter
,
htonl
(
ip_entry
->
ip4src
),
htons
(
ip_entry
->
psrc
),
htonl
(
ip_entry
->
ip4dst
),
htons
(
ip_entry
->
pdst
));
else
efx_filter_set_rx_udp_wild
(
&
filter
,
htonl
(
ip_entry
->
ip4dst
),
htons
(
ip_entry
->
pdst
));
break
;
case
ETHER_FLOW
:
if
(
ntuple
->
fs
.
vlan_tag_mask
==
0xf000
)
efx_filter_set_rx_mac_full
(
&
filter
,
ntuple
->
fs
.
vlan_tag
&
0xfff
,
mac_entry
->
h_dest
);
else
efx_filter_set_rx_mac_wild
(
&
filter
,
mac_entry
->
h_dest
);
break
;
}
if
(
ntuple
->
fs
.
action
==
ETHTOOL_RXNTUPLE_ACTION_CLEAR
)
{
if
(
ntuple
->
fs
.
action
==
ETHTOOL_RXNTUPLE_ACTION_CLEAR
)
return
efx_filter_remove_filter
(
efx
,
&
filter
);
}
else
{
if
(
ntuple
->
fs
.
action
==
ETHTOOL_RXNTUPLE_ACTION_DROP
)
filter
.
dmaq_id
=
0xfff
;
else
filter
.
dmaq_id
=
ntuple
->
fs
.
action
;
else
return
efx_filter_insert_filter
(
efx
,
&
filter
,
true
);
}
}
static
int
efx_ethtool_get_rxfh_indir
(
struct
net_device
*
net_dev
,
...
...
drivers/net/sfc/filter.c
View file @
cf78f8ee
This diff is collapsed.
Click to expand it.
drivers/net/sfc/filter.h
View file @
cf78f8ee
...
...
@@ -12,31 +12,27 @@
#include <linux/types.h>
enum
efx_filter_table_id
{
EFX_FILTER_TABLE_RX_IP
=
0
,
EFX_FILTER_TABLE_RX_MAC
,
EFX_FILTER_TABLE_COUNT
,
};
/**
* enum efx_filter_type - type of hardware filter
* @EFX_FILTER_RX_TCP_FULL: RX, matching TCP/IPv4 4-tuple
* @EFX_FILTER_RX_TCP_WILD: RX, matching TCP/IPv4 destination (host, port)
* @EFX_FILTER_RX_UDP_FULL: RX, matching UDP/IPv4 4-tuple
* @EFX_FILTER_RX_UDP_WILD: RX, matching UDP/IPv4 destination (host, port)
* @EFX_FILTER_RX_MAC_FULL: RX, matching Ethernet destination MAC address, VID
* @EFX_FILTER_RX_MAC_WILD: RX, matching Ethernet destination MAC address
* @EFX_FILTER_TCP_FULL: Matching TCP/IPv4 4-tuple
* @EFX_FILTER_TCP_WILD: Matching TCP/IPv4 destination (host, port)
* @EFX_FILTER_UDP_FULL: Matching UDP/IPv4 4-tuple
* @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_UNSPEC: Match type is unspecified
*
* Falcon NICs only support the
RX
TCP/IPv4 and UDP/IPv4 filter types.
* Falcon NICs only support the TCP/IPv4 and UDP/IPv4 filter types.
*/
enum
efx_filter_type
{
EFX_FILTER_RX_TCP_FULL
=
0
,
EFX_FILTER_RX_TCP_WILD
,
EFX_FILTER_RX_UDP_FULL
,
EFX_FILTER_RX_UDP_WILD
,
EFX_FILTER_RX_MAC_FULL
=
4
,
EFX_FILTER_RX_MAC_WILD
,
EFX_FILTER_TYPE_COUNT
,
EFX_FILTER_TCP_FULL
=
0
,
EFX_FILTER_TCP_WILD
,
EFX_FILTER_UDP_FULL
,
EFX_FILTER_UDP_WILD
,
EFX_FILTER_MAC_FULL
=
4
,
EFX_FILTER_MAC_WILD
,
EFX_FILTER_TYPE_COUNT
,
/* number of specific types */
EFX_FILTER_UNSPEC
=
0xf
,
};
/**
...
...
@@ -63,13 +59,13 @@ enum efx_filter_priority {
* @EFX_FILTER_FLAG_RX_OVERRIDE_IP: Enables a MAC filter to override
* any IP filter that matches the same packet. By default, IP
* filters take precedence.
*
* Currently, no flags are defined for TX filters.
* @EFX_FILTER_FLAG_RX: Filter is for RX
*/
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
,
};
/**
...
...
@@ -91,99 +87,26 @@ struct efx_filter_spec {
u32
data
[
3
];
};
/**
* efx_filter_set_rx_tcp_full - specify RX filter with TCP/IPv4 full match
* @spec: Specification to initialise
* @shost: Source host address (host byte order)
* @sport: Source port (host byte order)
* @dhost: Destination host address (host byte order)
* @dport: Destination port (host byte order)
*/
static
inline
void
efx_filter_set_rx_tcp_full
(
struct
efx_filter_spec
*
spec
,
u32
shost
,
u16
sport
,
u32
dhost
,
u16
dport
)
{
spec
->
type
=
EFX_FILTER_RX_TCP_FULL
;
spec
->
data
[
0
]
=
sport
|
shost
<<
16
;
spec
->
data
[
1
]
=
dport
<<
16
|
shost
>>
16
;
spec
->
data
[
2
]
=
dhost
;
}
/**
* efx_filter_set_rx_tcp_wild - specify RX filter with TCP/IPv4 wildcard match
* @spec: Specification to initialise
* @dhost: Destination host address (host byte order)
* @dport: Destination port (host byte order)
*/
static
inline
void
efx_filter_set_rx_tcp_wild
(
struct
efx_filter_spec
*
spec
,
u32
dhost
,
u16
dport
)
{
spec
->
type
=
EFX_FILTER_RX_TCP_WILD
;
spec
->
data
[
0
]
=
0
;
spec
->
data
[
1
]
=
dport
<<
16
;
spec
->
data
[
2
]
=
dhost
;
}
/**
* efx_filter_set_rx_udp_full - specify RX filter with UDP/IPv4 full match
* @spec: Specification to initialise
* @shost: Source host address (host byte order)
* @sport: Source port (host byte order)
* @dhost: Destination host address (host byte order)
* @dport: Destination port (host byte order)
*/
static
inline
void
efx_filter_set_rx_udp_full
(
struct
efx_filter_spec
*
spec
,
u32
shost
,
u16
sport
,
u32
dhost
,
u16
dport
)
{
spec
->
type
=
EFX_FILTER_RX_UDP_FULL
;
spec
->
data
[
0
]
=
sport
|
shost
<<
16
;
spec
->
data
[
1
]
=
dport
<<
16
|
shost
>>
16
;
spec
->
data
[
2
]
=
dhost
;
}
/**
* efx_filter_set_rx_udp_wild - specify RX filter with UDP/IPv4 wildcard match
* @spec: Specification to initialise
* @dhost: Destination host address (host byte order)
* @dport: Destination port (host byte order)
*/
static
inline
void
efx_filter_set_rx_udp_wild
(
struct
efx_filter_spec
*
spec
,
u32
dhost
,
u16
dport
)
static
inline
void
efx_filter_init_rx
(
struct
efx_filter_spec
*
spec
,
enum
efx_filter_priority
priority
,
enum
efx_filter_flags
flags
,
unsigned
rxq_id
)
{
spec
->
type
=
EFX_FILTER_
RX_UDP_WILD
;
spec
->
data
[
0
]
=
dport
;
spec
->
data
[
1
]
=
0
;
spec
->
d
ata
[
2
]
=
dhost
;
spec
->
type
=
EFX_FILTER_
UNSPEC
;
spec
->
priority
=
priority
;
spec
->
flags
=
EFX_FILTER_FLAG_RX
|
flags
;
spec
->
d
maq_id
=
rxq_id
;
}
/**
* efx_filter_set_rx_mac_full - specify RX filter with MAC full match
* @spec: Specification to initialise
* @vid: VLAN ID
* @addr: Destination MAC address
*/
static
inline
void
efx_filter_set_rx_mac_full
(
struct
efx_filter_spec
*
spec
,
u16
vid
,
const
u8
*
addr
)
{
spec
->
type
=
EFX_FILTER_RX_MAC_FULL
;
spec
->
data
[
0
]
=
vid
;
spec
->
data
[
1
]
=
addr
[
2
]
<<
24
|
addr
[
3
]
<<
16
|
addr
[
4
]
<<
8
|
addr
[
5
];
spec
->
data
[
2
]
=
addr
[
0
]
<<
8
|
addr
[
1
];
}
/**
* efx_filter_set_rx_mac_full - specify RX filter with MAC wildcard match
* @spec: Specification to initialise
* @addr: Destination MAC address
*/
static
inline
void
efx_filter_set_rx_mac_wild
(
struct
efx_filter_spec
*
spec
,
const
u8
*
addr
)
{
spec
->
type
=
EFX_FILTER_RX_MAC_WILD
;
spec
->
data
[
0
]
=
0
;
spec
->
data
[
1
]
=
addr
[
2
]
<<
24
|
addr
[
3
]
<<
16
|
addr
[
4
]
<<
8
|
addr
[
5
];
spec
->
data
[
2
]
=
addr
[
0
]
<<
8
|
addr
[
1
];
}
extern
int
efx_filter_set_ipv4_local
(
struct
efx_filter_spec
*
spec
,
u8
proto
,
__be32
host
,
__be16
port
);
extern
int
efx_filter_set_ipv4_full
(
struct
efx_filter_spec
*
spec
,
u8
proto
,
__be32
host
,
__be16
port
,
__be32
rhost
,
__be16
rport
);
extern
int
efx_filter_set_eth_local
(
struct
efx_filter_spec
*
spec
,
u16
vid
,
const
u8
*
addr
);
enum
{
EFX_FILTER_VID_UNSPEC
=
0xffff
,
};
#endif
/* EFX_FILTER_H */
drivers/net/sfc/io.h
View file @
cf78f8ee
This diff is collapsed.
Click to expand it.
drivers/net/sfc/net_driver.h
View file @
cf78f8ee
...
...
@@ -142,6 +142,12 @@ struct efx_tx_buffer {
* @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.
* This is here for performance reasons. The xmit path will
* only get the up-to-date value of @write_count if this
* variable indicates that the queue is empty. This is to
* avoid cache-line ping-pong between the xmit path and the
* completion path.
* @stopped: Stopped count.
* Set if this TX queue is currently stopping its port.
* @insert_count: Current insert pointer
...
...
@@ -163,6 +169,10 @@ struct efx_tx_buffer {
* @tso_long_headers: Number of packets with headers too long for standard
* blocks
* @tso_packets: Number of packets via the TSO xmit path
* @pushes: Number of times the TX push feature has been used
* @empty_read_count: If the completion path has seen the queue as empty
* and the transmission path has not yet checked this, the value of
* @read_count bitwise-added to %EFX_EMPTY_COUNT_VALID; otherwise 0.
*/
struct
efx_tx_queue
{
/* Members which don't change on the fast path */
...
...
@@ -177,6 +187,7 @@ struct efx_tx_queue {
/* Members used mainly on the completion path */
unsigned
int
read_count
____cacheline_aligned_in_smp
;
unsigned
int
old_write_count
;
int
stopped
;
/* Members used only on the xmit path */
...
...
@@ -187,6 +198,11 @@ struct efx_tx_queue {
unsigned
int
tso_bursts
;
unsigned
int
tso_long_headers
;
unsigned
int
tso_packets
;
unsigned
int
pushes
;
/* Members shared between paths and sometimes updated */
unsigned
int
empty_read_count
____cacheline_aligned_in_smp
;
#define EFX_EMPTY_COUNT_VALID 0x80000000
};
/**
...
...
@@ -626,10 +642,8 @@ struct efx_filter_state;
* Work items do not hold and must not acquire RTNL.
* @workqueue_name: Name of workqueue
* @reset_work: Scheduled reset workitem
* @monitor_work: Hardware monitor workitem
* @membase_phys: Memory BAR value as physical address
* @membase: Memory BAR value
* @biu_lock: BIU (bus interface unit) lock
* @interrupt_mode: Interrupt mode
* @irq_rx_adaptive: Adaptive IRQ moderation enabled for RX event queues
* @irq_rx_moderation: IRQ moderation time for RX event queues
...
...
@@ -653,14 +667,9 @@ struct efx_filter_state;
* @int_error_count: Number of internal errors seen recently
* @int_error_expire: Time at which error count will be expired
* @irq_status: Interrupt status buffer
* @last_irq_cpu: Last CPU to handle interrupt.
* This register is written with the SMP processor ID whenever an
* interrupt is handled. It is used by efx_nic_test_interrupt()
* to verify that an interrupt has occurred.
* @irq_zero_count: Number of legacy IRQs seen with queue flags == 0
* @fatal_irq_level: IRQ level (bit number) used for serious errors
* @mtd_list: List of MTDs attached to the NIC
* @n_rx_nodesc_drop_cnt: RX no descriptor drop count
* @nic_data: Hardware dependant state
* @mac_lock: MAC access lock. Protects @port_enabled, @phy_mode,
* @port_inhibited, efx_monitor() and efx_reconfigure_port()
...
...
@@ -673,11 +682,7 @@ struct efx_filter_state;
* @port_initialized: Port initialized?
* @net_dev: Operating system network device. Consider holding the rtnl lock
* @rx_checksum_enabled: RX checksumming enabled
* @mac_stats: MAC statistics. These include all statistics the MACs
* can provide. Generic code converts these into a standard
* &struct net_device_stats.
* @stats_buffer: DMA buffer for statistics
* @stats_lock: Statistics update lock. Serialises statistics fetches
* @mac_op: MAC interface
* @phy_type: PHY type
* @phy_op: PHY interface
...
...
@@ -695,10 +700,23 @@ struct efx_filter_state;
* @loopback_mode: Loopback status
* @loopback_modes: Supported loopback mode bitmask
* @loopback_selftest: Offline self-test private state
* @monitor_work: Hardware monitor workitem
* @biu_lock: BIU (bus interface unit) lock
* @last_irq_cpu: Last CPU to handle interrupt.
* This register is written with the SMP processor ID whenever an
* interrupt is handled. It is used by efx_nic_test_interrupt()
* to verify that an interrupt has occurred.
* @n_rx_nodesc_drop_cnt: RX no descriptor drop count
* @mac_stats: MAC statistics. These include all statistics the MACs
* can provide. Generic code converts these into a standard
* &struct net_device_stats.
* @stats_lock: Statistics update lock. Serialises statistics fetches
*
* This is stored in the private area of the &struct net_device.
*/
struct
efx_nic
{
/* The following fields should be written very rarely */
char
name
[
IFNAMSIZ
];
struct
pci_dev
*
pci_dev
;
const
struct
efx_nic_type
*
type
;
...
...
@@ -707,10 +725,9 @@ struct efx_nic {
struct
workqueue_struct
*
workqueue
;
char
workqueue_name
[
16
];
struct
work_struct
reset_work
;
struct
delayed_work
monitor_work
;
resource_size_t
membase_phys
;
void
__iomem
*
membase
;
spinlock_t
biu_lock
;
enum
efx_int_mode
interrupt_mode
;
bool
irq_rx_adaptive
;
unsigned
int
irq_rx_moderation
;
...
...
@@ -737,7 +754,6 @@ struct efx_nic {
unsigned
long
int_error_expire
;
struct
efx_buffer
irq_status
;
volatile
signed
int
last_irq_cpu
;
unsigned
irq_zero_count
;
unsigned
fatal_irq_level
;
...
...
@@ -745,8 +761,6 @@ struct efx_nic {
struct
list_head
mtd_list
;
#endif
unsigned
n_rx_nodesc_drop_cnt
;
void
*
nic_data
;
struct
mutex
mac_lock
;
...
...
@@ -758,9 +772,7 @@ struct efx_nic {
struct
net_device
*
net_dev
;
bool
rx_checksum_enabled
;
struct
efx_mac_stats
mac_stats
;
struct
efx_buffer
stats_buffer
;
spinlock_t
stats_lock
;
struct
efx_mac_operations
*
mac_op
;
...
...
@@ -786,6 +798,15 @@ struct efx_nic {
void
*
loopback_selftest
;
struct
efx_filter_state
*
filter_state
;
/* The following fields may be written more often */
struct
delayed_work
monitor_work
____cacheline_aligned_in_smp
;
spinlock_t
biu_lock
;
volatile
signed
int
last_irq_cpu
;
unsigned
n_rx_nodesc_drop_cnt
;
struct
efx_mac_stats
mac_stats
;
spinlock_t
stats_lock
;
};
static
inline
int
efx_dev_registered
(
struct
efx_nic
*
efx
)
...
...
drivers/net/sfc/nic.c
View file @
cf78f8ee
...
...
@@ -362,6 +362,35 @@ static inline void efx_notify_tx_desc(struct efx_tx_queue *tx_queue)
FR_AZ_TX_DESC_UPD_DWORD_P0
,
tx_queue
->
queue
);
}
/* Write pointer and first descriptor for TX descriptor ring */
static
inline
void
efx_push_tx_desc
(
struct
efx_tx_queue
*
tx_queue
,
const
efx_qword_t
*
txd
)
{
unsigned
write_ptr
;
efx_oword_t
reg
;
BUILD_BUG_ON
(
FRF_AZ_TX_DESC_LBN
!=
0
);
BUILD_BUG_ON
(
FR_AA_TX_DESC_UPD_KER
!=
FR_BZ_TX_DESC_UPD_P0
);
write_ptr
=
tx_queue
->
write_count
&
tx_queue
->
ptr_mask
;
EFX_POPULATE_OWORD_2
(
reg
,
FRF_AZ_TX_DESC_PUSH_CMD
,
true
,
FRF_AZ_TX_DESC_WPTR
,
write_ptr
);
reg
.
qword
[
0
]
=
*
txd
;
efx_writeo_page
(
tx_queue
->
efx
,
&
reg
,
FR_BZ_TX_DESC_UPD_P0
,
tx_queue
->
queue
);
}
static
inline
bool
efx_may_push_tx_desc
(
struct
efx_tx_queue
*
tx_queue
,
unsigned
int
write_count
)
{
unsigned
empty_read_count
=
ACCESS_ONCE
(
tx_queue
->
empty_read_count
);
if
(
empty_read_count
==
0
)
return
false
;
tx_queue
->
empty_read_count
=
0
;
return
((
empty_read_count
^
write_count
)
&
~
EFX_EMPTY_COUNT_VALID
)
==
0
;
}
/* For each entry inserted into the software descriptor ring, create a
* descriptor in the hardware TX descriptor ring (in host memory), and
...
...
@@ -373,6 +402,7 @@ void efx_nic_push_buffers(struct efx_tx_queue *tx_queue)
struct
efx_tx_buffer
*
buffer
;
efx_qword_t
*
txd
;
unsigned
write_ptr
;
unsigned
old_write_count
=
tx_queue
->
write_count
;
BUG_ON
(
tx_queue
->
write_count
==
tx_queue
->
insert_count
);
...
...
@@ -391,7 +421,15 @@ void efx_nic_push_buffers(struct efx_tx_queue *tx_queue)
}
while
(
tx_queue
->
write_count
!=
tx_queue
->
insert_count
);
wmb
();
/* Ensure descriptors are written before they are fetched */
efx_notify_tx_desc
(
tx_queue
);
if
(
efx_may_push_tx_desc
(
tx_queue
,
old_write_count
))
{
txd
=
efx_tx_desc
(
tx_queue
,
old_write_count
&
tx_queue
->
ptr_mask
);
efx_push_tx_desc
(
tx_queue
,
txd
);
++
tx_queue
->
pushes
;
}
else
{
efx_notify_tx_desc
(
tx_queue
);
}
}
/* Allocate hardware resources for a TX queue */
...
...
@@ -1632,7 +1670,7 @@ void efx_nic_init_common(struct efx_nic *efx)
EFX_SET_OWORD_FIELD
(
temp
,
FRF_AZ_TX_RX_SPACER
,
0xfe
);
EFX_SET_OWORD_FIELD
(
temp
,
FRF_AZ_TX_RX_SPACER_EN
,
1
);
EFX_SET_OWORD_FIELD
(
temp
,
FRF_AZ_TX_ONE_PKT_PER_Q
,
1
);
EFX_SET_OWORD_FIELD
(
temp
,
FRF_AZ_TX_PUSH_EN
,
0
);
EFX_SET_OWORD_FIELD
(
temp
,
FRF_AZ_TX_PUSH_EN
,
1
);
EFX_SET_OWORD_FIELD
(
temp
,
FRF_AZ_TX_DIS_NON_IP_EV
,
1
);
/* Enable SW_EV to inherit in char driver - assume harmless here */
EFX_SET_OWORD_FIELD
(
temp
,
FRF_AZ_TX_SOFT_EVT_EN
,
1
);
...
...
drivers/net/sfc/tx.c
View file @
cf78f8ee
...
...
@@ -240,8 +240,7 @@ netdev_tx_t efx_enqueue_skb(struct efx_tx_queue *tx_queue, struct sk_buff *skb)
* of read_count. */
smp_mb
();
tx_queue
->
old_read_count
=
*
(
volatile
unsigned
*
)
&
tx_queue
->
read_count
;
ACCESS_ONCE
(
tx_queue
->
read_count
);
fill_level
=
(
tx_queue
->
insert_count
-
tx_queue
->
old_read_count
);
q_space
=
efx
->
txq_entries
-
1
-
fill_level
;
...
...
@@ -429,6 +428,16 @@ void efx_xmit_done(struct efx_tx_queue *tx_queue, unsigned int index)
__netif_tx_unlock
(
queue
);
}
}
/* Check whether the hardware queue is now empty */
if
((
int
)(
tx_queue
->
read_count
-
tx_queue
->
old_write_count
)
>=
0
)
{
tx_queue
->
old_write_count
=
ACCESS_ONCE
(
tx_queue
->
write_count
);
if
(
tx_queue
->
read_count
==
tx_queue
->
old_write_count
)
{
smp_mb
();
tx_queue
->
empty_read_count
=
tx_queue
->
read_count
|
EFX_EMPTY_COUNT_VALID
;
}
}
}
int
efx_probe_tx_queue
(
struct
efx_tx_queue
*
tx_queue
)
...
...
@@ -474,8 +483,10 @@ void efx_init_tx_queue(struct efx_tx_queue *tx_queue)
tx_queue
->
insert_count
=
0
;
tx_queue
->
write_count
=
0
;
tx_queue
->
old_write_count
=
0
;
tx_queue
->
read_count
=
0
;
tx_queue
->
old_read_count
=
0
;
tx_queue
->
empty_read_count
=
0
|
EFX_EMPTY_COUNT_VALID
;
BUG_ON
(
tx_queue
->
stopped
);
/* Set up TX descriptor ring */
...
...
@@ -764,7 +775,7 @@ static int efx_tx_queue_insert(struct efx_tx_queue *tx_queue,
* stopped from the access of read_count. */
smp_mb
();
tx_queue
->
old_read_count
=
*
(
volatile
unsigned
*
)
&
tx_queue
->
read_count
;
ACCESS_ONCE
(
tx_queue
->
read_count
)
;
fill_level
=
(
tx_queue
->
insert_count
-
tx_queue
->
old_read_count
);
q_space
=
efx
->
txq_entries
-
1
-
fill_level
;
...
...
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