* Re: [PATCH net-next] tcp: Remove some spurious dropped packet profile hits from the passive connection accept path
From: Eric Dumazet @ 2014-11-20 20:47 UTC (permalink / raw)
To: Rick Jones; +Cc: netdev, davem
In-Reply-To: <20141120185829.986CB290095D@tardy>
On Thu, 2014-11-20 at 10:58 -0800, Rick Jones wrote:
> From: Rick Jones <rick.jones2@hp.com>
>
> When a system is the passive accepter of many connections, for example
> when the target of a netperf TCP_CC or TCP_CRR test, or as say a web
> server, the discard of the skb containing the TCP SYN being processed
> for the LISTEN endpoint should be a consume_skb() rather than a kfree_skb()
> to avoid cluttering a dropped packet profile.
>
> Signed-off-by: Rick Jones <rick.jones2@hp.com>
>
> ---
So what happens if we really drop the packet ?
TCP stack at this point owns the packet, it is possible to mark a bit in
it to either call consume_skb() or kfree_skb()
I attempted this once but gave up because it was a quite intrusive
patch...
^ permalink raw reply
* Re: [PATCH] bonding: clear header_ops when last slave detached (v2)
From: Eric Dumazet @ 2014-11-20 20:41 UTC (permalink / raw)
To: Cong Wang; +Cc: Wengang, netdev
In-Reply-To: <CAHA+R7PKRbBNwfUWRAsVHQreKsGXBc8CHorZRuyCfvwL4O=y+g@mail.gmail.com>
On Thu, 2014-11-20 at 09:34 -0800, Cong Wang wrote:
> I didn't look into ipoib_header_ops, thought it might have some dependency
> on symbols.
I did look before answering and suggesting this, you really should do
the same instead of giving advices of over engineering the stack.
Best is the enemy of the good.
Its hard to find some networking function trivial than this one.
static int ipoib_hard_header(struct sk_buff *skb,
struct net_device *dev,
unsigned short type,
const void *daddr, const void *saddr, unsigned len)
{
struct ipoib_header *header;
struct ipoib_cb *cb = ipoib_skb_cb(skb);
header = (struct ipoib_header *) skb_push(skb, sizeof *header);
header->proto = htons(type);
header->reserved = 0;
/*
* we don't rely on dst_entry structure, always stuff the
* destination address into skb->cb so we can figure out where
* to send the packet later.
*/
memcpy(cb->hwaddr, daddr, INFINIBAND_ALEN);
return sizeof *header;
}
^ permalink raw reply
* Re: [PATCH net-next] tcp: Remove some spurious dropped packet profile hits from the passive connection accept path
From: Vijay Subramanian @ 2014-11-20 20:15 UTC (permalink / raw)
To: Rick Jones; +Cc: netdev, David Miller
In-Reply-To: <20141120185829.986CB290095D@tardy>
> + * 99 times out of 10, there won't actually be any
Minor typo here.. s/10/100.
Vijay
^ permalink raw reply
* Re: [PATCH net 2/5] i40e: Implement ndo_gso_check()
From: Jesse Gross @ 2014-11-20 20:14 UTC (permalink / raw)
To: Joe Stringer
Cc: netdev, Jeff Kirsher, linux.nics, Tom Herbert,
Linux Kernel Mailing List, Shannon Nelson, Brandeburg, Jesse
In-Reply-To: <201411201116.04406.joestringer@nicira.com>
On Thu, Nov 20, 2014 at 11:16 AM, Joe Stringer <joestringer@nicira.com> wrote:
> On Tuesday, November 04, 2014 15:45:22 Jesse Gross wrote:
>> On Tue, Nov 4, 2014 at 1:56 PM, Joe Stringer <joestringer@nicira.com> wrote:
>> > diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c
>> > b/drivers/net/ethernet/intel/i40e/i40e_main.c index c3a7f4a..21829b5
>> > 100644
>> > --- a/drivers/net/ethernet/intel/i40e/i40e_main.c
>> > +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
>> > +static bool i40e_gso_check(struct sk_buff *skb, struct net_device *dev)
>> > +{
>> > + if ((skb_shinfo(skb)->gso_type & SKB_GSO_UDP_TUNNEL) &&
>> > + (skb->inner_protocol_type != ENCAP_TYPE_ETHER ||
>> > + skb->inner_protocol != htons(ETH_P_TEB) ||
>> > + skb_inner_mac_header(skb) - skb_transport_header(skb) > 64))
>> > + return false;
>>
>> I think it may be possible to even support a few more things here.
>> According to the datasheet here:
>> http://www.intel.com/content/dam/www/public/us/en/documents/datasheets/xl71
>> 0-10-40-controller-datasheet.pdf
>>
>> This can actually support 64 bytes beyond the tunnel header, which
>> would make for a total of 80 bytes. It looks like it can also support
>> IPv4 or IPv6 beyond just Ethernet as the encapsulated protocol.
>>
>> Intel guys, can you confirm that this is correct?
>
> I'm just respinning this for v4/6 beyond GRE/UDP tunnel and IPIP, and I found
> the description of max protocol parsing size of 480B (with individual header
> limit of 255B). I couldn't find where you get this 64/80 number or which
> headers it maps to. Could you (or one of the intel guys) expand on this?
The number that I gave was from the section on Geneve support (on page
708), which says that it can support up to 64 bytes of options (this
was also my understanding from previous conversations with Intel
guys). I searched for 480 byte limit and it seems like it for receive
instead of transmit, which could conceivably be different.
^ permalink raw reply
* [PATCH net-next] filter: add bpf_optimize_div()
From: Denis Kirjanov @ 2014-11-20 19:42 UTC (permalink / raw)
To: netdev; +Cc: Denis Kirjanov, Alexei Starovoitov
optimize_div() found in mips bpf jit is really usefull
for other arches. So let's put it in filter.h
CC: Alexei Starovoitov <ast@plumgrid.com>
Signed-off-by: Denis Kirjanov <kda@linux-powerpc.org>
---
include/linux/filter.h | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/include/linux/filter.h b/include/linux/filter.h
index ca95abd..b385637 100644
--- a/include/linux/filter.h
+++ b/include/linux/filter.h
@@ -414,6 +414,17 @@ static inline void bpf_jit_dump(unsigned int flen, unsigned int proglen,
print_hex_dump(KERN_ERR, "JIT code: ", DUMP_PREFIX_OFFSET,
16, 1, image, proglen, false);
}
+
+static inline int bpf_optimize_div(u32 *k)
+{
+ /* power of 2 divides can be implemented with right shift */
+ if (!(*k & (*k-1))) {
+ *k = ilog2(*k);
+ return 1;
+ }
+
+ return 0;
+}
#else
static inline void bpf_jit_compile(struct bpf_prog *fp)
{
--
2.1.0
^ permalink raw reply related
* i40e/i40e_ethtool.c weirdness?
From: Valdis Kletnieks @ 2014-11-20 19:21 UTC (permalink / raw)
To: Mitch Williams, Jeff Kirsher
Cc: Catherine Sullivan, Shannon Nelson, netdev, linux-kernel
[-- Attachment #1: Type: text/plain, Size: 1861 bytes --]
(spotted while looking at a 'git bisect visualize' for something else)
After this commit:
Author: Mitch Williams <mitch.a.williams@intel.com> 2014-09-13 03:40:47
Committer: Jeff Kirsher <jeffrey.t.kirsher@intel.com> 2014-10-23 23:38:04
i40e: Add 10GBaseT support
Add driver support for 10GBaseT device.
we have the following chunk of code in i40e_ethtool.c:
case I40E_PHY_TYPE_10GBASE_SFPP_CU:
ecmd->supported = SUPPORTED_10000baseT_Full;
break;
case I40E_PHY_TYPE_1000BASE_KX:
case I40E_PHY_TYPE_1000BASE_T:
ecmd->supported = SUPPORTED_Autoneg |
SUPPORTED_10000baseT_Full |
SUPPORTED_1000baseT_Full |
SUPPORTED_100baseT_Full;
ecmd->advertising = ADVERTISED_Autoneg |
ADVERTISED_10000baseT_Full |
ADVERTISED_1000baseT_Full |
ADVERTISED_100baseT_Full;
break;
case I40E_PHY_TYPE_100BASE_TX:
ecmd->supported = SUPPORTED_Autoneg |
SUPPORTED_10000baseT_Full |
SUPPORTED_1000baseT_Full |
SUPPORTED_100baseT_Full;
ecmd->advertising = ADVERTISED_Autoneg |
ADVERTISED_10000baseT_Full |
ADVERTISED_1000baseT_Full |
ADVERTISED_100baseT_Full;
break;
case I40E_PHY_TYPE_SGMII:
ecmd->supported = SUPPORTED_Autoneg |
I'm confused by the fact that 2 cases that by name are 100M and 1G parts
got bits saying that 10G is "supported" - was that intentional?
[-- Attachment #2: Type: application/pgp-signature, Size: 848 bytes --]
^ permalink raw reply
* Re: [PATCH net 2/5] i40e: Implement ndo_gso_check()
From: Joe Stringer @ 2014-11-20 19:16 UTC (permalink / raw)
To: Jesse Gross
Cc: netdev, Jeff Kirsher, linux.nics, Tom Herbert,
Linux Kernel Mailing List, Shannon Nelson, jesse.brandeburg
In-Reply-To: <CAEP_g=8rbJF5z92LV_c14KooU=i3x=9WpikocctcEUOdw5-oLA@mail.gmail.com>
On Tuesday, November 04, 2014 15:45:22 Jesse Gross wrote:
> On Tue, Nov 4, 2014 at 1:56 PM, Joe Stringer <joestringer@nicira.com> wrote:
> > diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c
> > b/drivers/net/ethernet/intel/i40e/i40e_main.c index c3a7f4a..21829b5
> > 100644
> > --- a/drivers/net/ethernet/intel/i40e/i40e_main.c
> > +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
> > +static bool i40e_gso_check(struct sk_buff *skb, struct net_device *dev)
> > +{
> > + if ((skb_shinfo(skb)->gso_type & SKB_GSO_UDP_TUNNEL) &&
> > + (skb->inner_protocol_type != ENCAP_TYPE_ETHER ||
> > + skb->inner_protocol != htons(ETH_P_TEB) ||
> > + skb_inner_mac_header(skb) - skb_transport_header(skb) > 64))
> > + return false;
>
> I think it may be possible to even support a few more things here.
> According to the datasheet here:
> http://www.intel.com/content/dam/www/public/us/en/documents/datasheets/xl71
> 0-10-40-controller-datasheet.pdf
>
> This can actually support 64 bytes beyond the tunnel header, which
> would make for a total of 80 bytes. It looks like it can also support
> IPv4 or IPv6 beyond just Ethernet as the encapsulated protocol.
>
> Intel guys, can you confirm that this is correct?
I'm just respinning this for v4/6 beyond GRE/UDP tunnel and IPIP, and I found
the description of max protocol parsing size of 480B (with individual header
limit of 255B). I couldn't find where you get this 64/80 number or which
headers it maps to. Could you (or one of the intel guys) expand on this?
^ permalink raw reply
* Re: [PATCHv10 ovs 12/15] datapath: Add support for unique flow identifiers.
From: Joe Stringer @ 2014-11-20 18:57 UTC (permalink / raw)
To: Pravin Shelar; +Cc: dev@openvswitch.org, netdev
In-Reply-To: <CALnjE+qwnKa-s1GoZRvh-RgjRO5eKvrf+XnvD_meGES1L=fe0w@mail.gmail.com>
On Wednesday, November 19, 2014 16:39:20 Pravin Shelar wrote:
> On Wed, Nov 19, 2014 at 4:20 PM, Joe Stringer <joestringer@nicira.com>
wrote:
> > On Wednesday, November 19, 2014 15:34:24 Pravin Shelar wrote:
> >> On Thu, Nov 13, 2014 at 11:17 AM, Joe Stringer <joestringer@nicira.com>
> >
> > wrote:
> >> > @@ -684,33 +691,43 @@ static size_t ovs_flow_cmd_msg_size(const struct
> >> > sw_flow_actions *acts)
> >> >
> >> > /* Called with ovs_mutex or RCU read lock. */
> >> > static int ovs_flow_cmd_fill_match(const struct sw_flow *flow,
> >> >
> >> > - struct sk_buff *skb)
> >> > + struct sk_buff *skb, u32
> >> > ufid_flags)
> >> >
> >> > {
> >> >
> >> > struct nlattr *nla;
> >> > int err;
> >> >
> >> > - /* Fill flow key. */
> >> > - nla = nla_nest_start(skb, OVS_FLOW_ATTR_KEY);
> >> > - if (!nla)
> >> > - return -EMSGSIZE;
> >> > -
> >> > - err = ovs_nla_put_flow(&flow->unmasked_key,
> >> > &flow->unmasked_key, skb, - false);
> >> > - if (err)
> >> > - return err;
> >> > -
> >> > - nla_nest_end(skb, nla);
> >> > + /* Fill flow key. If userspace didn't specify a UFID, then
> >> > ignore the + * OMIT_KEY flag. */
> >> > + if (!(ufid_flags & OVS_UFID_F_OMIT_KEY) ||
> >> > + !flow->index_by_ufid) {
> >>
> >> I am not sure about this check, userspace needs to send atleast ufid
> >> or the unmasked key as id for flow. otherwise we shld flag error. Here
> >> we can serialize flow->key.
> >> There could be another function which takes care of flow-id
> >> serialization where we serialize use ufid or unmasked key as flow id.
> >> Lets group ufid and unmasked key together rather than masked key and
> >> unmasked key which are not related.
> >
> > Right, at flow setup time the flow key is always required, but the UFID
> > is optional. For most other cases, one of the two most be specified. For
> > flow dump, neither is required from userspace, but OMIT_KEY flag may be
> > raised. That's the particular case that this logic is trying to catch
> > (dump all flows, including those that were set up without UFID - in
> > which case the OMIT_KEY flag doesn't make sense, so treat the flag like
> > a request rather than a command).
>
> How do you handle overlapping flows without the flow id in dump operation?
In userspace? revalidators will dump flows, then if the flow-key is exactly the
same as another flow then they will be hashed to the same udpif_key and the
second flow will be ignored each dump. So, stats may get messed up. If they
differ but overlap, they will hash to different udpif_keys and stats tracked
separately. Revalidator won't check the validity of overlapping flows until the
next change to ofproto-dpif.
^ permalink raw reply
* RE: [PATCH 1/1] net: Hyper-V: Deletion of an unnecessary check before the function call "vfree"
From: Haiyang Zhang @ 2014-11-20 18:58 UTC (permalink / raw)
To: SF Markus Elfring, KY Srinivasan, devel@linuxdriverproject.org,
netdev@vger.kernel.org
Cc: LKML, kernel-janitors@vger.kernel.org, Julia Lawall
In-Reply-To: <546DF9D7.6080801@users.sourceforge.net>
> -----Original Message-----
> From: SF Markus Elfring [mailto:elfring@users.sourceforge.net]
> Sent: Thursday, November 20, 2014 9:25 AM
> To: Haiyang Zhang; KY Srinivasan; devel@linuxdriverproject.org;
> netdev@vger.kernel.org
> Cc: LKML; kernel-janitors@vger.kernel.org; Julia Lawall
> Subject: [PATCH 1/1] net: Hyper-V: Deletion of an unnecessary check
> before the function call "vfree"
>
> From: Markus Elfring <elfring@users.sourceforge.net>
> Date: Thu, 20 Nov 2014 15:15:21 +0100
>
> The vfree() function performs also input parameter validation. Thus the
> test
> around the call is not needed.
>
> This issue was detected by using the Coccinelle software.
>
> Signed-off-by: Markus Elfring <elfring@users.sourceforge.net>
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Thanks!
^ permalink raw reply
* [PATCH net-next] tcp: Remove some spurious dropped packet profile hits from the passive connection accept path
From: Rick Jones @ 2014-11-20 18:58 UTC (permalink / raw)
To: netdev; +Cc: davem
From: Rick Jones <rick.jones2@hp.com>
When a system is the passive accepter of many connections, for example
when the target of a netperf TCP_CC or TCP_CRR test, or as say a web
server, the discard of the skb containing the TCP SYN being processed
for the LISTEN endpoint should be a consume_skb() rather than a kfree_skb()
to avoid cluttering a dropped packet profile.
Signed-off-by: Rick Jones <rick.jones2@hp.com>
---
perf top -a -g -e skb:kfree_sk output from a system which is the target
of a netperf TCP_CC test
before:
- 100.00% 100.00% [kernel] [k] kfree_skb
- kfree_skb
+ 68.68% sk_stream_kill_queues
+ 31.32% tcp_rcv_state_process
after:
- 100.00% 100.00% [kernel] [k] kfree_skb
- kfree_skb
99.89% sk_stream_kill_queues
Presumably, the consume_skb() versus kfree_skb() could be made conditional
on there actually being data in the TCP SYN segment, but the odds of there
actually being data seemed low enough to not warrant it.
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index d91436b..999b0a4 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -5624,8 +5624,12 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
* against this problem. So, we drop the data
* in the interest of security over speed unless
* it's still in use.
+ *
+ * 99 times out of 10, there won't actually be any
+ * data and so we aren't really dropping anything.
+ * So, we consume_skb() rather than kfree_skb().
*/
- kfree_skb(skb);
+ consume_skb(skb);
return 0;
}
goto discard;
^ permalink raw reply related
* Re: mlx5: don't duplicate kvfree()
From: Al Viro @ 2014-11-20 18:51 UTC (permalink / raw)
To: Or Gerlitz
Cc: Eli Cohen, linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-rdma-u79uwXL29TY76Z2rM5mHXA, netdev-u79uwXL29TY76Z2rM5mHXA,
David S. Miller
In-Reply-To: <546E204B.5080106-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
On Thu, Nov 20, 2014 at 07:09:31PM +0200, Or Gerlitz wrote:
> On 11/20/2014 10:17 AM, Al Viro wrote:
> >On Thu, Nov 20, 2014 at 08:13:57AM +0000, Al Viro wrote:
> >>> 9 files changed, 21 insertions(+), 35 deletions(-)
> >grr... 8 files changed, actually - that was from the diff that included mlx4
> >bits. Patch split correctly and sent in two pieces, summary left as is ;-/
> >Sorry about the confusion it might cause...
> Al,
>
> I think the best way to proceed here is to come up with mlx4 and
> mlx5 patches and get both of them in through netdev / net-nexttree,
> don't worry about each of these drivers have a part which is also
> under drivers/infiniband/hw -- it doesn't justify splitting in this
> case
Both had been sent to netdev today (and ACKed by respective drivers'
maintainers). I'd certainly prefer not to put them through vfs.git,
but beyond that I really don't care which tree do those go into...
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH 1/1] net: brcm80211: Deletion of unnecessary checks before two function calls
From: Arend van Spriel @ 2014-11-20 18:04 UTC (permalink / raw)
To: SF Markus Elfring
Cc: Brett Rudley, Franky (Zhenhui) Lin, Hante Meuleman,
John W. Linville, linux-wireless, brcm80211-dev-list, netdev,
LKML, kernel-janitors, Julia Lawall
In-Reply-To: <546E0DC8.3050906@users.sourceforge.net>
On 11/20/14 16:50, SF Markus Elfring wrote:
> From: Markus Elfring<elfring@users.sourceforge.net>
> Date: Thu, 20 Nov 2014 16:42:51 +0100
>
> The functions brcmu_pkt_buf_free_skb() and release_firmware() test whether
> their argument is NULL and then return immediately. Thus the test around
> the call is not needed.
>
> This issue was detected by using the Coccinelle software.
Goodo for coccinelle and you for running it.
Acked-by: Arend van Spriel <arend@broadcom.com>
> Signed-off-by: Markus Elfring<elfring@users.sourceforge.net>
> ---
> drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c | 3 +--
> drivers/net/wireless/brcm80211/brcmfmac/firmware.c | 3 +--
> drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c | 3 +--
> drivers/net/wireless/brcm80211/brcmsmac/main.c | 3 +--
> 4 files changed, 4 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
> index f55f625..8ff7037 100644
> --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
> +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
> @@ -2539,8 +2539,7 @@ static void brcmf_sdio_bus_stop(struct device *dev)
> brcmu_pktq_flush(&bus->txq, true, NULL, NULL);
>
> /* Clear any held glomming stuff */
> - if (bus->glomd)
> - brcmu_pkt_buf_free_skb(bus->glomd);
> + brcmu_pkt_buf_free_skb(bus->glomd);
> brcmf_sdio_free_glom(bus);
>
> /* Clear rx control and wake any waiters */
> diff --git a/drivers/net/wireless/brcm80211/brcmfmac/firmware.c b/drivers/net/wireless/brcm80211/brcmfmac/firmware.c
> index 8ea9f28..3a2d014 100644
> --- a/drivers/net/wireless/brcm80211/brcmfmac/firmware.c
> +++ b/drivers/net/wireless/brcm80211/brcmfmac/firmware.c
> @@ -262,8 +262,7 @@ static void brcmf_fw_request_nvram_done(const struct firmware *fw, void *ctx)
>
> fail:
> brcmf_dbg(TRACE, "failed: dev=%s\n", dev_name(fwctx->dev));
> - if (fwctx->code)
> - release_firmware(fwctx->code);
> + release_firmware(fwctx->code);
> device_release_driver(fwctx->dev);
> kfree(fwctx);
> }
> diff --git a/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c b/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c
> index 8f8b937..0cb00dc 100644
> --- a/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c
> +++ b/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c
> @@ -506,8 +506,7 @@ static int brcmf_msgbuf_query_dcmd(struct brcmf_pub *drvr, int ifidx,
> memcpy(buf, skb->data, (len< msgbuf->ioctl_resp_ret_len) ?
> len : msgbuf->ioctl_resp_ret_len);
> }
> - if (skb)
> - brcmu_pkt_buf_free_skb(skb);
> + brcmu_pkt_buf_free_skb(skb);
>
> return msgbuf->ioctl_resp_status;
> }
> diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.c b/drivers/net/wireless/brcm80211/brcmsmac/main.c
> index 1b47482..ce538a1 100644
> --- a/drivers/net/wireless/brcm80211/brcmsmac/main.c
> +++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c
> @@ -1009,8 +1009,7 @@ brcms_c_dotxstatus(struct brcms_c_info *wlc, struct tx_status *txs)
> if (txh)
> trace_brcms_txdesc(&wlc->hw->d11core->dev, txh,
> sizeof(*txh));
> - if (p)
> - brcmu_pkt_buf_free_skb(p);
> + brcmu_pkt_buf_free_skb(p);
> }
>
> if (dma&& queue< NFIFO) {
^ permalink raw reply
* Re: [patch net-next] i40e: remove dead fdb code
From: Jesse Brandeburg @ 2014-11-20 17:39 UTC (permalink / raw)
To: Jiri Pirko
Cc: linux.nics, e1000-devel, netdev, bruce.w.allan, john.ronciak,
davem
In-Reply-To: <1416489029-1929-1-git-send-email-jiri@resnulli.us>
On Thu, 20 Nov 2014 14:10:29 +0100
Jiri Pirko <jiri@resnulli.us> wrote:
> This code is not used now and also it contains some weird ifdefs. So
> remove it for now. It can be added when needed.
>
First, thanks for looking at our code.
but, NAK, the code just needs to have the #ifdefs removed.
In addition the fdb_del and fdb_dump functions are un-necessary and
were submitted by mistake.
I will draft up a patch today and send it (and Jeff can take it through
Jeff Kirsher's i40e tree, if thats okay with DaveM)
Thanks,
Jesse
------------------------------------------------------------------------------
Download BIRT iHub F-Type - The Free Enterprise-Grade BIRT Server
from Actuate! Instantly Supercharge Your Business Reports and Dashboards
with Interactivity, Sharing, Native Excel Exports, App Integration & more
Get technology previously reserved for billion-dollar corporations, FREE
http://pubads.g.doubleclick.net/gampad/clk?id=157005751&iu=/4140/ostg.clktrk
_______________________________________________
E1000-devel mailing list
E1000-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/e1000-devel
To learn more about Intel® Ethernet, visit http://communities.intel.com/community/wired
^ permalink raw reply
* Re: [PATCH] bonding: clear header_ops when last slave detached (v2)
From: Cong Wang @ 2014-11-20 17:34 UTC (permalink / raw)
To: Eric Dumazet; +Cc: Wengang, netdev
In-Reply-To: <1416465685.8629.15.camel@edumazet-glaptop2.roam.corp.google.com>
On Wed, Nov 19, 2014 at 10:41 PM, Eric Dumazet <eric.dumazet@gmail.com> wrote:
> On Wed, 2014-11-19 at 14:26 -0800, Cong Wang wrote:
>> On Tue, Nov 18, 2014 at 11:00 PM, Wengang <wen.gang.wang@oracle.com> wrote:
>> >
>> > Yes, that's true. So the simplest way is move ipoib_header_ops to vmlinux.
>> >
>>
>> That is not an option. Perhaps you need RCU to protect the dev->header_ops
>> pointer.
>
> This _is_ a reasonable option, especially for stable kernels
>
> ipoib_hard_header() is 100 bytes or less. Adding infrastructure all over
> the kernel to be able to use RCU or module refcounting will cost much
> more.
I didn't look into ipoib_header_ops, thought it might have some dependency
on symbols. So _generally_ speaking, we can't do that, the dependency
chain could be very long. It could be an exception and good luck
to play with module symbols.
>
> Tell me why it is ok for eth_header_ops() being static (while its _much_
> bigger), and not for ipoib_header_ops. This looks pretty arbitrary to
> me.
>
Simple, eth_* is kinda of a builtin library now, too many drivers use them.
^ permalink raw reply
* Re: [PATCH 1/1] net: Xilinx: Deletion of unnecessary checks before two function calls
From: Sören Brinkmann @ 2014-11-20 17:29 UTC (permalink / raw)
To: SF Markus Elfring
Cc: Michal Simek, netdev, linux-arm-kernel, LKML, kernel-janitors,
Julia Lawall
In-Reply-To: <546DF1A2.8090208@users.sourceforge.net>
On Thu, 2014-11-20 at 02:50PM +0100, SF Markus Elfring wrote:
> From: Markus Elfring <elfring@users.sourceforge.net>
> Date: Thu, 20 Nov 2014 14:47:12 +0100
>
> The functions kfree() and of_node_put() test whether their argument is NULL
> and then return immediately. Thus the test around the call is not needed.
>
> This issue was detected by using the Coccinelle software.
>
> Signed-off-by: Markus Elfring <elfring@users.sourceforge.net>
Reviewed-by: Soren Brinkmann <soren.brinkmann@xilinx.com>
Sören
^ permalink raw reply
* Re: mlx5: don't duplicate kvfree()
From: Or Gerlitz @ 2014-11-20 17:09 UTC (permalink / raw)
To: Al Viro, Eli Cohen
Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-rdma-u79uwXL29TY76Z2rM5mHXA, netdev-u79uwXL29TY76Z2rM5mHXA,
David S. Miller
In-Reply-To: <20141120081726.GK7996-3bDd1+5oDREiFSDQTTA3OLVCufUGDwFn@public.gmane.org>
On 11/20/2014 10:17 AM, Al Viro wrote:
> On Thu, Nov 20, 2014 at 08:13:57AM +0000, Al Viro wrote:
>> > 9 files changed, 21 insertions(+), 35 deletions(-)
> grr... 8 files changed, actually - that was from the diff that included mlx4
> bits. Patch split correctly and sent in two pieces, summary left as is ;-/
> Sorry about the confusion it might cause...
Al,
I think the best way to proceed here is to come up with mlx4 and mlx5
patches and get both of them in through netdev / net-nexttree, don't
worry about each of these drivers have a part which is also under
drivers/infiniband/hw -- it doesn't justify splitting in this case
Or.
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* [PATCH net-next v1 8/8] amd-xgbe: Add support for the skb->xmit_more flag
From: Tom Lendacky @ 2014-11-20 17:04 UTC (permalink / raw)
To: netdev; +Cc: David Miller
In-Reply-To: <20141120170320.15397.10583.stgit@tlendack-t1.amdoffice.net>
Add support to delay telling the hardware about data that is ready to
be transmitted if the skb->xmit_more flag is set.
Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
drivers/net/ethernet/amd/xgbe/xgbe-desc.c | 5 +--
drivers/net/ethernet/amd/xgbe/xgbe-dev.c | 43 ++++++++++++++++++++---------
drivers/net/ethernet/amd/xgbe/xgbe-drv.c | 37 +++++++++++++++++++++----
drivers/net/ethernet/amd/xgbe/xgbe.h | 15 ++++++++++
4 files changed, 78 insertions(+), 22 deletions(-)
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-desc.c b/drivers/net/ethernet/amd/xgbe/xgbe-desc.c
index 62cb4d3..51b68d1 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-desc.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-desc.c
@@ -378,7 +378,7 @@ static void xgbe_wrapper_tx_descriptor_init(struct xgbe_prv_data *pdata)
ring->cur = 0;
ring->dirty = 0;
- ring->tx.queue_stopped = 0;
+ memset(&ring->tx, 0, sizeof(ring->tx));
hw_if->tx_desc_init(channel);
}
@@ -422,8 +422,7 @@ static void xgbe_wrapper_rx_descriptor_init(struct xgbe_prv_data *pdata)
ring->cur = 0;
ring->dirty = 0;
- ring->rx.realloc_index = 0;
- ring->rx.realloc_threshold = 0;
+ memset(&ring->rx, 0, sizeof(ring->rx));
hw_if->rx_desc_init(channel);
}
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
index b3d2433..53f5f66 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
@@ -1325,6 +1325,29 @@ static void xgbe_config_dcb_pfc(struct xgbe_prv_data *pdata)
xgbe_config_flow_control(pdata);
}
+static void xgbe_tx_start_xmit(struct xgbe_channel *channel,
+ struct xgbe_ring *ring)
+{
+ struct xgbe_prv_data *pdata = channel->pdata;
+ struct xgbe_ring_data *rdata;
+
+ /* Issue a poll command to Tx DMA by writing address
+ * of next immediate free descriptor */
+ rdata = XGBE_GET_DESC_DATA(ring, ring->cur);
+ XGMAC_DMA_IOWRITE(channel, DMA_CH_TDTR_LO,
+ lower_32_bits(rdata->rdesc_dma));
+
+ /* Start the Tx coalescing timer */
+ if (pdata->tx_usecs && !channel->tx_timer_active) {
+ channel->tx_timer_active = 1;
+ hrtimer_start(&channel->tx_timer,
+ ktime_set(0, pdata->tx_usecs * NSEC_PER_USEC),
+ HRTIMER_MODE_REL);
+ }
+
+ ring->tx.xmit_more = 0;
+}
+
static void xgbe_dev_xmit(struct xgbe_channel *channel)
{
struct xgbe_prv_data *pdata = channel->pdata;
@@ -1528,20 +1551,13 @@ static void xgbe_dev_xmit(struct xgbe_channel *channel)
/* Make sure ownership is written to the descriptor */
wmb();
- /* Issue a poll command to Tx DMA by writing address
- * of next immediate free descriptor */
ring->cur++;
- rdata = XGBE_GET_DESC_DATA(ring, ring->cur);
- XGMAC_DMA_IOWRITE(channel, DMA_CH_TDTR_LO,
- lower_32_bits(rdata->rdesc_dma));
-
- /* Start the Tx coalescing timer */
- if (pdata->tx_usecs && !channel->tx_timer_active) {
- channel->tx_timer_active = 1;
- hrtimer_start(&channel->tx_timer,
- ktime_set(0, pdata->tx_usecs * NSEC_PER_USEC),
- HRTIMER_MODE_REL);
- }
+ if (!packet->skb->xmit_more ||
+ netif_xmit_stopped(netdev_get_tx_queue(pdata->netdev,
+ channel->queue_index)))
+ xgbe_tx_start_xmit(channel, ring);
+ else
+ ring->tx.xmit_more = 1;
DBGPR(" %s: descriptors %u to %u written\n",
channel->name, start_index & (ring->rdesc_count - 1),
@@ -2802,6 +2818,7 @@ void xgbe_init_function_ptrs_dev(struct xgbe_hw_if *hw_if)
hw_if->rx_desc_reset = xgbe_rx_desc_reset;
hw_if->is_last_desc = xgbe_is_last_desc;
hw_if->is_context_desc = xgbe_is_context_desc;
+ hw_if->tx_start_xmit = xgbe_tx_start_xmit;
/* For FLOW ctrl */
hw_if->config_tx_flow_control = xgbe_config_tx_flow_control;
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
index f963528..02c104d 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
@@ -225,6 +225,28 @@ static inline unsigned int xgbe_tx_avail_desc(struct xgbe_ring *ring)
return (ring->rdesc_count - (ring->cur - ring->dirty));
}
+static int xgbe_maybe_stop_tx_queue(struct xgbe_channel *channel,
+ struct xgbe_ring *ring, unsigned int count)
+{
+ struct xgbe_prv_data *pdata = channel->pdata;
+
+ if (count > xgbe_tx_avail_desc(ring)) {
+ DBGPR(" Tx queue stopped, not enough descriptors available\n");
+ netif_stop_subqueue(pdata->netdev, channel->queue_index);
+ ring->tx.queue_stopped = 1;
+
+ /* If we haven't notified the hardware because of xmit_more
+ * support, tell it now
+ */
+ if (ring->tx.xmit_more)
+ pdata->hw_if.tx_start_xmit(channel, ring);
+
+ return NETDEV_TX_BUSY;
+ }
+
+ return 0;
+}
+
static int xgbe_calc_rx_buf_size(struct net_device *netdev, unsigned int mtu)
{
unsigned int rx_buf_size;
@@ -1199,6 +1221,8 @@ static void xgbe_packet_info(struct xgbe_prv_data *pdata,
unsigned int len;
unsigned int i;
+ packet->skb = skb;
+
context_desc = 0;
packet->rdesc_count = 0;
@@ -1447,13 +1471,9 @@ static int xgbe_xmit(struct sk_buff *skb, struct net_device *netdev)
xgbe_packet_info(pdata, ring, skb, packet);
/* Check that there are enough descriptors available */
- if (packet->rdesc_count > xgbe_tx_avail_desc(ring)) {
- DBGPR(" Tx queue stopped, not enough descriptors available\n");
- netif_stop_subqueue(netdev, channel->queue_index);
- ring->tx.queue_stopped = 1;
- ret = NETDEV_TX_BUSY;
+ ret = xgbe_maybe_stop_tx_queue(channel, ring, packet->rdesc_count);
+ if (ret)
goto tx_netdev_return;
- }
ret = xgbe_prep_tso(skb, packet);
if (ret) {
@@ -1480,6 +1500,11 @@ static int xgbe_xmit(struct sk_buff *skb, struct net_device *netdev)
xgbe_print_pkt(netdev, skb, true);
#endif
+ /* Stop the queue in advance if there may not be enough descriptors */
+ xgbe_maybe_stop_tx_queue(channel, ring, XGBE_TX_MAX_DESCS);
+
+ ret = NETDEV_TX_OK;
+
tx_netdev_return:
spin_unlock_irqrestore(&ring->lock, flags);
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe.h b/drivers/net/ethernet/amd/xgbe/xgbe.h
index ec0d37a..eb33873 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe.h
+++ b/drivers/net/ethernet/amd/xgbe/xgbe.h
@@ -140,6 +140,17 @@
#define XGBE_TX_MAX_BUF_SIZE (0x3fff & ~(64 - 1))
+/* Descriptors required for maximum contigous TSO/GSO packet */
+#define XGBE_TX_MAX_SPLIT ((GSO_MAX_SIZE / XGBE_TX_MAX_BUF_SIZE) + 1)
+
+/* Maximum possible descriptors needed for an SKB:
+ * - Maximum number of SKB frags
+ * - Maximum descriptors for contiguous TSO/GSO packet
+ * - Possible context descriptor
+ * - Possible TSO header descriptor
+ */
+#define XGBE_TX_MAX_DESCS (MAX_SKB_FRAGS + XGBE_TX_MAX_SPLIT + 2)
+
#define XGBE_RX_MIN_BUF_SIZE (ETH_FRAME_LEN + ETH_FCS_LEN + VLAN_HLEN)
#define XGBE_RX_BUF_ALIGN 64
#define XGBE_SKB_ALLOC_SIZE 256
@@ -225,6 +236,8 @@
struct xgbe_prv_data;
struct xgbe_packet_data {
+ struct sk_buff *skb;
+
unsigned int attributes;
unsigned int errors;
@@ -360,6 +373,7 @@ struct xgbe_ring {
union {
struct {
unsigned int queue_stopped;
+ unsigned int xmit_more;
unsigned short cur_mss;
unsigned short cur_vlan_ctag;
} tx;
@@ -523,6 +537,7 @@ struct xgbe_hw_if {
void (*tx_desc_reset)(struct xgbe_ring_data *);
int (*is_last_desc)(struct xgbe_ring_desc *);
int (*is_context_desc)(struct xgbe_ring_desc *);
+ void (*tx_start_xmit)(struct xgbe_channel *, struct xgbe_ring *);
/* For FLOW ctrl */
int (*config_tx_flow_control)(struct xgbe_prv_data *);
^ permalink raw reply related
* [PATCH net-next v1 7/8] amd-xgbe: Perform Tx coalescing on a packet basis
From: Tom Lendacky @ 2014-11-20 17:04 UTC (permalink / raw)
To: netdev; +Cc: David Miller
In-Reply-To: <20141120170320.15397.10583.stgit@tlendack-t1.amdoffice.net>
The current form of Tx coalescing works on a descriptor basis instead
of on a packet basis and doesn't take into account TSO packets. Update
the Tx coalescing support to work on a packet basis, taking into
account the number of packets associated with a TSO transmit. Also,
only activate the Tx timer if a timer value is set.
Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
drivers/net/ethernet/amd/xgbe/xgbe-dev.c | 46 +++++++++++++++++-------------
1 file changed, 26 insertions(+), 20 deletions(-)
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
index 78db5a6..b3d2433 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
@@ -1334,7 +1334,7 @@ static void xgbe_dev_xmit(struct xgbe_channel *channel)
struct xgbe_packet_data *packet = &ring->packet_data;
unsigned int csum, tso, vlan;
unsigned int tso_context, vlan_context;
- unsigned int tx_coalesce, tx_frames;
+ unsigned int tx_set_ic;
int start_index = ring->cur;
int i;
@@ -1357,10 +1357,26 @@ static void xgbe_dev_xmit(struct xgbe_channel *channel)
else
vlan_context = 0;
- tx_coalesce = (pdata->tx_usecs || pdata->tx_frames) ? 1 : 0;
- tx_frames = pdata->tx_frames;
- if (tx_coalesce && !channel->tx_timer_active)
- ring->coalesce_count = 0;
+ /* Determine if an interrupt should be generated for this Tx:
+ * Interrupt:
+ * - Tx frame count exceeds the frame count setting
+ * - Addition of Tx frame count to the frame count since the
+ * last interrupt was set exceeds the frame count setting
+ * No interrupt:
+ * - No frame count setting specified (ethtool -C ethX tx-frames 0)
+ * - Addition of Tx frame count to the frame count since the
+ * last interrupt was set does not exceed the frame count setting
+ */
+ ring->coalesce_count += packet->tx_packets;
+ if (!pdata->tx_frames)
+ tx_set_ic = 0;
+ else if (packet->tx_packets > pdata->tx_frames)
+ tx_set_ic = 1;
+ else if ((ring->coalesce_count % pdata->tx_frames) <
+ packet->tx_packets)
+ tx_set_ic = 1;
+ else
+ tx_set_ic = 0;
rdata = XGBE_GET_DESC_DATA(ring, ring->cur);
rdesc = rdata->rdesc;
@@ -1427,13 +1443,6 @@ static void xgbe_dev_xmit(struct xgbe_channel *channel)
if (XGMAC_GET_BITS(packet->attributes, TX_PACKET_ATTRIBUTES, PTP))
XGMAC_SET_BITS_LE(rdesc->desc2, TX_NORMAL_DESC2, TTSE, 1);
- /* Set IC bit based on Tx coalescing settings */
- XGMAC_SET_BITS_LE(rdesc->desc2, TX_NORMAL_DESC2, IC, 1);
- if (tx_coalesce && (!tx_frames ||
- (++ring->coalesce_count % tx_frames)))
- /* Clear IC bit */
- XGMAC_SET_BITS_LE(rdesc->desc2, TX_NORMAL_DESC2, IC, 0);
-
/* Mark it as First Descriptor */
XGMAC_SET_BITS_LE(rdesc->desc3, TX_NORMAL_DESC3, FD, 1);
@@ -1478,13 +1487,6 @@ static void xgbe_dev_xmit(struct xgbe_channel *channel)
XGMAC_SET_BITS_LE(rdesc->desc2, TX_NORMAL_DESC2, HL_B1L,
rdata->skb_dma_len);
- /* Set IC bit based on Tx coalescing settings */
- XGMAC_SET_BITS_LE(rdesc->desc2, TX_NORMAL_DESC2, IC, 1);
- if (tx_coalesce && (!tx_frames ||
- (++ring->coalesce_count % tx_frames)))
- /* Clear IC bit */
- XGMAC_SET_BITS_LE(rdesc->desc2, TX_NORMAL_DESC2, IC, 0);
-
/* Set OWN bit */
XGMAC_SET_BITS_LE(rdesc->desc3, TX_NORMAL_DESC3, OWN, 1);
@@ -1500,6 +1502,10 @@ static void xgbe_dev_xmit(struct xgbe_channel *channel)
/* Set LAST bit for the last descriptor */
XGMAC_SET_BITS_LE(rdesc->desc3, TX_NORMAL_DESC3, LD, 1);
+ /* Set IC bit based on Tx coalescing settings */
+ if (tx_set_ic)
+ XGMAC_SET_BITS_LE(rdesc->desc2, TX_NORMAL_DESC2, IC, 1);
+
/* Save the Tx info to report back during cleanup */
rdata->tx.packets = packet->tx_packets;
rdata->tx.bytes = packet->tx_bytes;
@@ -1530,7 +1536,7 @@ static void xgbe_dev_xmit(struct xgbe_channel *channel)
lower_32_bits(rdata->rdesc_dma));
/* Start the Tx coalescing timer */
- if (tx_coalesce && !channel->tx_timer_active) {
+ if (pdata->tx_usecs && !channel->tx_timer_active) {
channel->tx_timer_active = 1;
hrtimer_start(&channel->tx_timer,
ktime_set(0, pdata->tx_usecs * NSEC_PER_USEC),
^ permalink raw reply related
* [PATCH net-next v1 6/8] amd-xgbe: Remove unused variable
From: Tom Lendacky @ 2014-11-20 17:03 UTC (permalink / raw)
To: netdev; +Cc: David Miller
In-Reply-To: <20141120170320.15397.10583.stgit@tlendack-t1.amdoffice.net>
The tso_header variable in the xgbe_tx_ring_data structure is not used,
remove it.
Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
drivers/net/ethernet/amd/xgbe/xgbe-desc.c | 1 -
drivers/net/ethernet/amd/xgbe/xgbe.h | 1 -
2 files changed, 2 deletions(-)
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-desc.c b/drivers/net/ethernet/amd/xgbe/xgbe-desc.c
index 3c7c386..62cb4d3 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-desc.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-desc.c
@@ -532,7 +532,6 @@ static int xgbe_map_tx_skb(struct xgbe_channel *channel, struct sk_buff *skb)
}
rdata->skb_dma = skb_dma;
rdata->skb_dma_len = packet->header_len;
- rdata->tx.tso_header = 1;
offset = packet->header_len;
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe.h b/drivers/net/ethernet/amd/xgbe/xgbe.h
index 98504f1..ec0d37a 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe.h
+++ b/drivers/net/ethernet/amd/xgbe/xgbe.h
@@ -276,7 +276,6 @@ struct xgbe_buffer_data {
/* Tx-related ring data */
struct xgbe_tx_ring_data {
- unsigned int tso_header; /* TSO header indicator */
unsigned int packets; /* BQL packet count */
unsigned int bytes; /* BQL byte count */
};
^ permalink raw reply related
* [PATCH net-next v1 5/8] amd-xgbe: Add BQL support
From: Tom Lendacky @ 2014-11-20 17:03 UTC (permalink / raw)
To: netdev; +Cc: David Miller
In-Reply-To: <20141120170320.15397.10583.stgit@tlendack-t1.amdoffice.net>
Call the appropriate BQL functions to track the number of bytes queued
during Tx processing and to track the number of packets and bytes
that have been transmitted during Tx complete processing.
Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
drivers/net/ethernet/amd/xgbe/xgbe-dev.c | 4 +++
drivers/net/ethernet/amd/xgbe/xgbe-drv.c | 43 +++++++++++++++++++++++++++++-
drivers/net/ethernet/amd/xgbe/xgbe.h | 5 +++
3 files changed, 51 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
index 2908ad1..78db5a6 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
@@ -1500,6 +1500,10 @@ static void xgbe_dev_xmit(struct xgbe_channel *channel)
/* Set LAST bit for the last descriptor */
XGMAC_SET_BITS_LE(rdesc->desc3, TX_NORMAL_DESC3, LD, 1);
+ /* Save the Tx info to report back during cleanup */
+ rdata->tx.packets = packet->tx_packets;
+ rdata->tx.bytes = packet->tx_bytes;
+
/* In case the Tx DMA engine is running, make sure everything
* is written to the descriptor(s) before setting the OWN bit
* for the first descriptor
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
index 46ea423..f963528 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
@@ -876,7 +876,10 @@ static int xgbe_start(struct xgbe_prv_data *pdata)
static void xgbe_stop(struct xgbe_prv_data *pdata)
{
struct xgbe_hw_if *hw_if = &pdata->hw_if;
+ struct xgbe_channel *channel;
struct net_device *netdev = pdata->netdev;
+ struct netdev_queue *txq;
+ unsigned int i;
DBGPR("-->xgbe_stop\n");
@@ -890,6 +893,15 @@ static void xgbe_stop(struct xgbe_prv_data *pdata)
hw_if->disable_tx(pdata);
hw_if->disable_rx(pdata);
+ channel = pdata->channel;
+ for (i = 0; i < pdata->channel_count; i++, channel++) {
+ if (!channel->tx_ring)
+ continue;
+
+ txq = netdev_get_tx_queue(netdev, channel->queue_index);
+ netdev_tx_reset_queue(txq);
+ }
+
DBGPR("<--xgbe_stop\n");
}
@@ -1156,6 +1168,12 @@ static int xgbe_prep_tso(struct sk_buff *skb, struct xgbe_packet_data *packet)
packet->tcp_header_len, packet->tcp_payload_len);
DBGPR(" packet->mss=%u\n", packet->mss);
+ /* Update the number of packets that will ultimately be transmitted
+ * along with the extra bytes for each extra packet
+ */
+ packet->tx_packets = skb_shinfo(skb)->gso_segs;
+ packet->tx_bytes += (packet->tx_packets - 1) * packet->header_len;
+
return 0;
}
@@ -1184,6 +1202,9 @@ static void xgbe_packet_info(struct xgbe_prv_data *pdata,
context_desc = 0;
packet->rdesc_count = 0;
+ packet->tx_packets = 1;
+ packet->tx_bytes = skb->len;
+
if (xgbe_is_tso(skb)) {
/* TSO requires an extra descriptor if mss is different */
if (skb_shinfo(skb)->gso_size != ring->tx.cur_mss) {
@@ -1400,12 +1421,14 @@ static int xgbe_xmit(struct sk_buff *skb, struct net_device *netdev)
struct xgbe_channel *channel;
struct xgbe_ring *ring;
struct xgbe_packet_data *packet;
+ struct netdev_queue *txq;
unsigned long flags;
int ret;
DBGPR("-->xgbe_xmit: skb->len = %d\n", skb->len);
channel = pdata->channel + skb->queue_mapping;
+ txq = netdev_get_tx_queue(netdev, channel->queue_index);
ring = channel->tx_ring;
packet = &ring->packet_data;
@@ -1447,6 +1470,9 @@ static int xgbe_xmit(struct sk_buff *skb, struct net_device *netdev)
xgbe_prep_tx_tstamp(pdata, skb, packet);
+ /* Report on the actual number of bytes (to be) sent */
+ netdev_tx_sent_queue(txq, packet->tx_bytes);
+
/* Configure required descriptor fields for transmission */
hw_if->dev_xmit(channel);
@@ -1772,8 +1798,10 @@ static int xgbe_tx_poll(struct xgbe_channel *channel)
struct xgbe_ring_data *rdata;
struct xgbe_ring_desc *rdesc;
struct net_device *netdev = pdata->netdev;
+ struct netdev_queue *txq;
unsigned long flags;
int processed = 0;
+ unsigned int tx_packets = 0, tx_bytes = 0;
DBGPR("-->xgbe_tx_poll\n");
@@ -1781,6 +1809,8 @@ static int xgbe_tx_poll(struct xgbe_channel *channel)
if (!ring)
return 0;
+ txq = netdev_get_tx_queue(netdev, channel->queue_index);
+
spin_lock_irqsave(&ring->lock, flags);
while ((processed < XGBE_TX_DESC_MAX_PROC) &&
@@ -1799,6 +1829,11 @@ static int xgbe_tx_poll(struct xgbe_channel *channel)
xgbe_dump_tx_desc(ring, ring->dirty, 1, 0);
#endif
+ if (hw_if->is_last_desc(rdesc)) {
+ tx_packets += rdata->tx.packets;
+ tx_bytes += rdata->tx.bytes;
+ }
+
/* Free the SKB and reset the descriptor for re-use */
desc_if->unmap_rdata(pdata, rdata);
hw_if->tx_desc_reset(rdata);
@@ -1807,14 +1842,20 @@ static int xgbe_tx_poll(struct xgbe_channel *channel)
ring->dirty++;
}
+ if (!processed)
+ goto unlock;
+
+ netdev_tx_completed_queue(txq, tx_packets, tx_bytes);
+
if ((ring->tx.queue_stopped == 1) &&
(xgbe_tx_avail_desc(ring) > XGBE_TX_DESC_MIN_FREE)) {
ring->tx.queue_stopped = 0;
- netif_wake_subqueue(netdev, channel->queue_index);
+ netif_tx_wake_queue(txq);
}
DBGPR("<--xgbe_tx_poll: processed=%d\n", processed);
+unlock:
spin_unlock_irqrestore(&ring->lock, flags);
return processed;
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe.h b/drivers/net/ethernet/amd/xgbe/xgbe.h
index 41ce6e3..98504f1 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe.h
+++ b/drivers/net/ethernet/amd/xgbe/xgbe.h
@@ -243,6 +243,9 @@ struct xgbe_packet_data {
u32 rss_hash;
enum pkt_hash_types rss_hash_type;
+
+ unsigned int tx_packets;
+ unsigned int tx_bytes;
};
/* Common Rx and Tx descriptor mapping */
@@ -274,6 +277,8 @@ struct xgbe_buffer_data {
/* Tx-related ring data */
struct xgbe_tx_ring_data {
unsigned int tso_header; /* TSO header indicator */
+ unsigned int packets; /* BQL packet count */
+ unsigned int bytes; /* BQL byte count */
};
/* Rx-related ring data */
^ permalink raw reply related
* [PATCH net-next v1 4/8] amd-xgbe: Separate Tx/Rx ring data fields into new structs
From: Tom Lendacky @ 2014-11-20 17:03 UTC (permalink / raw)
To: netdev; +Cc: David Miller
In-Reply-To: <20141120170320.15397.10583.stgit@tlendack-t1.amdoffice.net>
Move the Tx and Rx related fields within the xgbe_ring_data struct into
their own structs in order to more easily see what fields are used for
each operation.
Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
drivers/net/ethernet/amd/xgbe/xgbe-desc.c | 36 ++++++++++++++---------------
drivers/net/ethernet/amd/xgbe/xgbe-dev.c | 14 ++++++-----
drivers/net/ethernet/amd/xgbe/xgbe-drv.c | 28 +++++++++++------------
drivers/net/ethernet/amd/xgbe/xgbe.h | 22 +++++++++++++-----
4 files changed, 54 insertions(+), 46 deletions(-)
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-desc.c b/drivers/net/ethernet/amd/xgbe/xgbe-desc.c
index e6b9f54..3c7c386 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-desc.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-desc.c
@@ -335,11 +335,11 @@ static int xgbe_map_rx_buffer(struct xgbe_prv_data *pdata,
}
/* Set up the header page info */
- xgbe_set_buffer_data(&rdata->rx_hdr, &ring->rx_hdr_pa,
+ xgbe_set_buffer_data(&rdata->rx.hdr, &ring->rx_hdr_pa,
XGBE_SKB_ALLOC_SIZE);
/* Set up the buffer page info */
- xgbe_set_buffer_data(&rdata->rx_buf, &ring->rx_buf_pa,
+ xgbe_set_buffer_data(&rdata->rx.buf, &ring->rx_buf_pa,
pdata->rx_buf_size);
return 0;
@@ -451,31 +451,29 @@ static void xgbe_unmap_rdata(struct xgbe_prv_data *pdata,
rdata->skb = NULL;
}
- if (rdata->rx_hdr.pa.pages)
- put_page(rdata->rx_hdr.pa.pages);
+ if (rdata->rx.hdr.pa.pages)
+ put_page(rdata->rx.hdr.pa.pages);
- if (rdata->rx_hdr.pa_unmap.pages) {
- dma_unmap_page(pdata->dev, rdata->rx_hdr.pa_unmap.pages_dma,
- rdata->rx_hdr.pa_unmap.pages_len,
+ if (rdata->rx.hdr.pa_unmap.pages) {
+ dma_unmap_page(pdata->dev, rdata->rx.hdr.pa_unmap.pages_dma,
+ rdata->rx.hdr.pa_unmap.pages_len,
DMA_FROM_DEVICE);
- put_page(rdata->rx_hdr.pa_unmap.pages);
+ put_page(rdata->rx.hdr.pa_unmap.pages);
}
- if (rdata->rx_buf.pa.pages)
- put_page(rdata->rx_buf.pa.pages);
+ if (rdata->rx.buf.pa.pages)
+ put_page(rdata->rx.buf.pa.pages);
- if (rdata->rx_buf.pa_unmap.pages) {
- dma_unmap_page(pdata->dev, rdata->rx_buf.pa_unmap.pages_dma,
- rdata->rx_buf.pa_unmap.pages_len,
+ if (rdata->rx.buf.pa_unmap.pages) {
+ dma_unmap_page(pdata->dev, rdata->rx.buf.pa_unmap.pages_dma,
+ rdata->rx.buf.pa_unmap.pages_len,
DMA_FROM_DEVICE);
- put_page(rdata->rx_buf.pa_unmap.pages);
+ put_page(rdata->rx.buf.pa_unmap.pages);
}
- memset(&rdata->rx_hdr, 0, sizeof(rdata->rx_hdr));
- memset(&rdata->rx_buf, 0, sizeof(rdata->rx_buf));
+ memset(&rdata->tx, 0, sizeof(rdata->tx));
+ memset(&rdata->rx, 0, sizeof(rdata->rx));
- rdata->tso_header = 0;
- rdata->len = 0;
rdata->interrupt = 0;
rdata->mapped_as_page = 0;
@@ -534,7 +532,7 @@ static int xgbe_map_tx_skb(struct xgbe_channel *channel, struct sk_buff *skb)
}
rdata->skb_dma = skb_dma;
rdata->skb_dma_len = packet->header_len;
- rdata->tso_header = 1;
+ rdata->tx.tso_header = 1;
offset = packet->header_len;
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
index 72425ff..2908ad1 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
@@ -1085,10 +1085,10 @@ static void xgbe_rx_desc_reset(struct xgbe_ring_data *rdata)
* Set buffer 2 (hi) address to buffer dma address (hi) and
* set control bits OWN and INTE
*/
- rdesc->desc0 = cpu_to_le32(lower_32_bits(rdata->rx_hdr.dma));
- rdesc->desc1 = cpu_to_le32(upper_32_bits(rdata->rx_hdr.dma));
- rdesc->desc2 = cpu_to_le32(lower_32_bits(rdata->rx_buf.dma));
- rdesc->desc3 = cpu_to_le32(upper_32_bits(rdata->rx_buf.dma));
+ rdesc->desc0 = cpu_to_le32(lower_32_bits(rdata->rx.hdr.dma));
+ rdesc->desc1 = cpu_to_le32(upper_32_bits(rdata->rx.hdr.dma));
+ rdesc->desc2 = cpu_to_le32(lower_32_bits(rdata->rx.buf.dma));
+ rdesc->desc3 = cpu_to_le32(upper_32_bits(rdata->rx.buf.dma));
XGMAC_SET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, INTE,
rdata->interrupt ? 1 : 0);
@@ -1586,8 +1586,8 @@ static int xgbe_dev_read(struct xgbe_channel *channel)
/* Get the header length */
if (XGMAC_GET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, FD))
- rdata->hdr_len = XGMAC_GET_BITS_LE(rdesc->desc2,
- RX_NORMAL_DESC2, HL);
+ rdata->rx.hdr_len = XGMAC_GET_BITS_LE(rdesc->desc2,
+ RX_NORMAL_DESC2, HL);
/* Get the RSS hash */
if (XGMAC_GET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, RSV)) {
@@ -1610,7 +1610,7 @@ static int xgbe_dev_read(struct xgbe_channel *channel)
}
/* Get the packet length */
- rdata->len = XGMAC_GET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, PL);
+ rdata->rx.len = XGMAC_GET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, PL);
if (!XGMAC_GET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, LD)) {
/* Not all the data has been transferred for this packet */
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
index eebb787..46ea423 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
@@ -1747,14 +1747,14 @@ static struct sk_buff *xgbe_create_skb(struct xgbe_prv_data *pdata,
u8 *packet;
unsigned int copy_len;
- skb = netdev_alloc_skb_ip_align(netdev, rdata->rx_hdr.dma_len);
+ skb = netdev_alloc_skb_ip_align(netdev, rdata->rx.hdr.dma_len);
if (!skb)
return NULL;
- packet = page_address(rdata->rx_hdr.pa.pages) +
- rdata->rx_hdr.pa.pages_offset;
- copy_len = (rdata->hdr_len) ? rdata->hdr_len : *len;
- copy_len = min(rdata->rx_hdr.dma_len, copy_len);
+ packet = page_address(rdata->rx.hdr.pa.pages) +
+ rdata->rx.hdr.pa.pages_offset;
+ copy_len = (rdata->rx.hdr_len) ? rdata->rx.hdr_len : *len;
+ copy_len = min(rdata->rx.hdr.dma_len, copy_len);
skb_copy_to_linear_data(skb, packet, copy_len);
skb_put(skb, copy_len);
@@ -1900,13 +1900,13 @@ read_again:
}
if (!context) {
- put_len = rdata->len - len;
+ put_len = rdata->rx.len - len;
len += put_len;
if (!skb) {
dma_sync_single_for_cpu(pdata->dev,
- rdata->rx_hdr.dma,
- rdata->rx_hdr.dma_len,
+ rdata->rx.hdr.dma,
+ rdata->rx.hdr.dma_len,
DMA_FROM_DEVICE);
skb = xgbe_create_skb(pdata, rdata, &put_len);
@@ -1918,15 +1918,15 @@ read_again:
if (put_len) {
dma_sync_single_for_cpu(pdata->dev,
- rdata->rx_buf.dma,
- rdata->rx_buf.dma_len,
+ rdata->rx.buf.dma,
+ rdata->rx.buf.dma_len,
DMA_FROM_DEVICE);
skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags,
- rdata->rx_buf.pa.pages,
- rdata->rx_buf.pa.pages_offset,
- put_len, rdata->rx_buf.dma_len);
- rdata->rx_buf.pa.pages = NULL;
+ rdata->rx.buf.pa.pages,
+ rdata->rx.buf.pa.pages_offset,
+ put_len, rdata->rx.buf.dma_len);
+ rdata->rx.buf.pa.pages = NULL;
}
}
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe.h b/drivers/net/ethernet/amd/xgbe/xgbe.h
index 46ce544..41ce6e3 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe.h
+++ b/drivers/net/ethernet/amd/xgbe/xgbe.h
@@ -271,6 +271,20 @@ struct xgbe_buffer_data {
unsigned int dma_len;
};
+/* Tx-related ring data */
+struct xgbe_tx_ring_data {
+ unsigned int tso_header; /* TSO header indicator */
+};
+
+/* Rx-related ring data */
+struct xgbe_rx_ring_data {
+ struct xgbe_buffer_data hdr; /* Header locations */
+ struct xgbe_buffer_data buf; /* Payload locations */
+
+ unsigned short hdr_len; /* Length of received header */
+ unsigned short len; /* Length of received packet */
+};
+
/* Structure used to hold information related to the descriptor
* and the packet associated with the descriptor (always use
* use the XGBE_GET_DESC_DATA macro to access this data from the ring)
@@ -282,13 +296,9 @@ struct xgbe_ring_data {
struct sk_buff *skb; /* Virtual address of SKB */
dma_addr_t skb_dma; /* DMA address of SKB data */
unsigned int skb_dma_len; /* Length of SKB DMA area */
- unsigned int tso_header; /* TSO header indicator */
- struct xgbe_buffer_data rx_hdr; /* Header locations */
- struct xgbe_buffer_data rx_buf; /* Payload locations */
-
- unsigned short hdr_len; /* Length of received header */
- unsigned short len; /* Length of received Rx packet */
+ struct xgbe_tx_ring_data tx; /* Tx-related data */
+ struct xgbe_rx_ring_data rx; /* Rx-related data */
unsigned int interrupt; /* Interrupt indicator */
^ permalink raw reply related
* [PATCH net-next v1 3/8] amd-xgbe: Incorporate Smatch coding suggestion
From: Tom Lendacky @ 2014-11-20 17:03 UTC (permalink / raw)
To: netdev; +Cc: David Miller, Dan Carpenter
In-Reply-To: <20141120170320.15397.10583.stgit@tlendack-t1.amdoffice.net>
The Smatch tool indicated that one of the if statements in xgbe-dev.c
could be rewritten to remove a redundant check for the 'err' variable
in an if statement.
Change the statement as suggested and add a comment to help clarify.
Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
---
drivers/net/ethernet/amd/xgbe/xgbe-dev.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
index dcd0347..72425ff 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
@@ -1633,7 +1633,8 @@ static int xgbe_dev_read(struct xgbe_channel *channel)
etlt = XGMAC_GET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, ETLT);
DBGPR(" err=%u, etlt=%#x\n", err, etlt);
- if (!err || (err && !etlt)) {
+ if (!err || !etlt) {
+ /* No error if err is 0 or etlt is 0 */
if ((etlt == 0x09) &&
(netdev->features & NETIF_F_HW_VLAN_CTAG_RX)) {
XGMAC_SET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES,
^ permalink raw reply related
* [PATCH net-next v1 2/8] amd-xgbe: Tx engine must not be active before stopping it
From: Tom Lendacky @ 2014-11-20 17:03 UTC (permalink / raw)
To: netdev; +Cc: David Miller
In-Reply-To: <20141120170320.15397.10583.stgit@tlendack-t1.amdoffice.net>
If the Tx engine is told to stop while it is actively processing Tx
descriptors it is possible that the Tx descriptor(s) will not be closed
out properly. When the Tx engine is restarted this could result in the
driver being stuck on the improperly closed descriptor.
Update the driver to wait for the Tx engine to be in a stopped or
suspended state before issuing the stop command.
This has not been an issue to date, but it's a good safe-guard to have.
Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
drivers/net/ethernet/amd/xgbe/xgbe-common.h | 21 ++++++----
drivers/net/ethernet/amd/xgbe/xgbe-dev.c | 59 +++++++++++++++++++++++++++
drivers/net/ethernet/amd/xgbe/xgbe.h | 1
3 files changed, 74 insertions(+), 7 deletions(-)
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-common.h b/drivers/net/ethernet/amd/xgbe/xgbe-common.h
index 2fe8fc7..75b08c6 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-common.h
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-common.h
@@ -125,9 +125,6 @@
#define DMA_AXIAWCR 0x3018
#define DMA_DSR0 0x3020
#define DMA_DSR1 0x3024
-#define DMA_DSR2 0x3028
-#define DMA_DSR3 0x302c
-#define DMA_DSR4 0x3030
/* DMA register entry bit positions and sizes */
#define DMA_AXIARCR_DRC_INDEX 0
@@ -158,10 +155,6 @@
#define DMA_AXIAWCR_TDC_WIDTH 4
#define DMA_AXIAWCR_TDD_INDEX 28
#define DMA_AXIAWCR_TDD_WIDTH 2
-#define DMA_DSR0_RPS_INDEX 8
-#define DMA_DSR0_RPS_WIDTH 4
-#define DMA_DSR0_TPS_INDEX 12
-#define DMA_DSR0_TPS_WIDTH 4
#define DMA_ISR_MACIS_INDEX 17
#define DMA_ISR_MACIS_WIDTH 1
#define DMA_ISR_MTLIS_INDEX 16
@@ -175,6 +168,20 @@
#define DMA_SBMR_UNDEF_INDEX 0
#define DMA_SBMR_UNDEF_WIDTH 1
+/* DMA register values */
+#define DMA_DSR_RPS_WIDTH 4
+#define DMA_DSR_TPS_WIDTH 4
+#define DMA_DSR_Q_WIDTH (DMA_DSR_RPS_WIDTH + DMA_DSR_TPS_WIDTH)
+#define DMA_DSR0_RPS_START 8
+#define DMA_DSR0_TPS_START 12
+#define DMA_DSRX_FIRST_QUEUE 3
+#define DMA_DSRX_INC 4
+#define DMA_DSRX_QPR 4
+#define DMA_DSRX_RPS_START 0
+#define DMA_DSRX_TPS_START 4
+#define DMA_TPS_STOPPED 0x00
+#define DMA_TPS_SUSPENDED 0x06
+
/* DMA channel register offsets
* Multiple channels can be active. The first channel has registers
* that begin at 0x3100. Each subsequent channel has registers that
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
index 9b1d9fa..dcd0347 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
@@ -2453,6 +2453,47 @@ static void xgbe_config_mmc(struct xgbe_prv_data *pdata)
XGMAC_IOWRITE_BITS(pdata, MMC_CR, CR, 1);
}
+static void xgbe_prepare_tx_stop(struct xgbe_prv_data *pdata,
+ struct xgbe_channel *channel)
+{
+ unsigned int tx_dsr, tx_pos, tx_qidx;
+ unsigned int tx_status;
+ unsigned long tx_timeout;
+
+ /* Calculate the status register to read and the position within */
+ if (channel->queue_index < DMA_DSRX_FIRST_QUEUE) {
+ tx_dsr = DMA_DSR0;
+ tx_pos = (channel->queue_index * DMA_DSR_Q_WIDTH) +
+ DMA_DSR0_TPS_START;
+ } else {
+ tx_qidx = channel->queue_index - DMA_DSRX_FIRST_QUEUE;
+
+ tx_dsr = DMA_DSR1 + ((tx_qidx / DMA_DSRX_QPR) * DMA_DSRX_INC);
+ tx_pos = ((tx_qidx % DMA_DSRX_QPR) * DMA_DSR_Q_WIDTH) +
+ DMA_DSRX_TPS_START;
+ }
+
+ /* The Tx engine cannot be stopped if it is actively processing
+ * descriptors. Wait for the Tx engine to enter the stopped or
+ * suspended state. Don't wait forever though...
+ */
+ tx_timeout = jiffies + (XGBE_DMA_STOP_TIMEOUT * HZ);
+ while (time_before(jiffies, tx_timeout)) {
+ tx_status = XGMAC_IOREAD(pdata, tx_dsr);
+ tx_status = GET_BITS(tx_status, tx_pos, DMA_DSR_TPS_WIDTH);
+ if ((tx_status == DMA_TPS_STOPPED) ||
+ (tx_status == DMA_TPS_SUSPENDED))
+ break;
+
+ usleep_range(500, 1000);
+ }
+
+ if (!time_before(jiffies, tx_timeout))
+ netdev_info(pdata->netdev,
+ "timed out waiting for Tx DMA channel %u to stop\n",
+ channel->queue_index);
+}
+
static void xgbe_enable_tx(struct xgbe_prv_data *pdata)
{
struct xgbe_channel *channel;
@@ -2481,6 +2522,15 @@ static void xgbe_disable_tx(struct xgbe_prv_data *pdata)
struct xgbe_channel *channel;
unsigned int i;
+ /* Prepare for Tx DMA channel stop */
+ channel = pdata->channel;
+ for (i = 0; i < pdata->channel_count; i++, channel++) {
+ if (!channel->tx_ring)
+ break;
+
+ xgbe_prepare_tx_stop(pdata, channel);
+ }
+
/* Disable MAC Tx */
XGMAC_IOWRITE_BITS(pdata, MAC_TCR, TE, 0);
@@ -2572,6 +2622,15 @@ static void xgbe_powerdown_tx(struct xgbe_prv_data *pdata)
struct xgbe_channel *channel;
unsigned int i;
+ /* Prepare for Tx DMA channel stop */
+ channel = pdata->channel;
+ for (i = 0; i < pdata->channel_count; i++, channel++) {
+ if (!channel->tx_ring)
+ break;
+
+ xgbe_prepare_tx_stop(pdata, channel);
+ }
+
/* Disable MAC Tx */
XGMAC_IOWRITE_BITS(pdata, MAC_TCR, TE, 0);
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe.h b/drivers/net/ethernet/amd/xgbe/xgbe.h
index 901fb1f..46ce544 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe.h
+++ b/drivers/net/ethernet/amd/xgbe/xgbe.h
@@ -147,6 +147,7 @@
#define XGBE_MAX_DMA_CHANNELS 16
#define XGBE_MAX_QUEUES 16
+#define XGBE_DMA_STOP_TIMEOUT 5
/* DMA cache settings - Outer sharable, write-back, write-allocate */
#define XGBE_DMA_OS_AXDOMAIN 0x2
^ permalink raw reply related
* [PATCH net-next v1 1/8] amd-xgbe: Add a read memory barrier to Tx/Rx path
From: Tom Lendacky @ 2014-11-20 17:03 UTC (permalink / raw)
To: netdev; +Cc: David Miller
In-Reply-To: <20141120170320.15397.10583.stgit@tlendack-t1.amdoffice.net>
Add a read memory barrier to the Tx and Rx paths where the ownership
bit is checked to be sure that all descriptor fields are read after
having read the ownership bit for the descriptor.
This has not been an issue to date, but it's a good safe-guard to have.
Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
drivers/net/ethernet/amd/xgbe/xgbe-dev.c | 3 +++
drivers/net/ethernet/amd/xgbe/xgbe-drv.c | 4 ++++
2 files changed, 7 insertions(+)
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
index f6014d3..9b1d9fa 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
@@ -1558,6 +1558,9 @@ static int xgbe_dev_read(struct xgbe_channel *channel)
if (XGMAC_GET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, OWN))
return 1;
+ /* Make sure descriptor fields are read after reading the OWN bit */
+ rmb();
+
#ifdef XGMAC_ENABLE_RX_DESC_DUMP
xgbe_dump_rx_desc(ring, rdesc, ring->cur);
#endif
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
index 0544931..eebb787 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
@@ -1791,6 +1791,10 @@ static int xgbe_tx_poll(struct xgbe_channel *channel)
if (!hw_if->tx_complete(rdesc))
break;
+ /* Make sure descriptor fields are read after reading the OWN
+ * bit */
+ rmb();
+
#ifdef XGMAC_ENABLE_TX_DESC_DUMP
xgbe_dump_tx_desc(ring, ring->dirty, 1, 0);
#endif
^ permalink raw reply related
* [PATCH net-next v1 0/8] amd-xgbe: AMD XGBE driver updates 2014-11-20
From: Tom Lendacky @ 2014-11-20 17:03 UTC (permalink / raw)
To: netdev; +Cc: David Miller
The following series of patches includes functional updates to the
driver as well as some trivial changes.
- Add a read memory barrier in the Tx and Rx path after checking the
descriptor ownership bit
- Wait for the Tx engine to stop/suspend before issuing a stop command
- Implement a smatch tool suggestion to simplify an if statement
- Separate out Tx and Rx ring data fields into their own structures
- Add BQL support
- Remove an unused variable
- Change Tx coalescing support to operate on packet basis instead of
a descriptor basis
- Add support for the skb->xmit_more flag
This patch series is based on net-next.
---
Tom Lendacky (8):
amd-xgbe: Add a read memory barrier to Tx/Rx path
amd-xgbe: Tx engine must not be active before stopping it
amd-xgbe: Incorporate Smatch coding suggestion
amd-xgbe: Separate Tx/Rx ring data fields into new structs
amd-xgbe: Add BQL support
amd-xgbe: Remove unused variable
amd-xgbe: Perform Tx coalescing on a packet basis
amd-xgbe: Add support for the skb->xmit_more flag
drivers/net/ethernet/amd/xgbe/xgbe-common.h | 21 ++-
drivers/net/ethernet/amd/xgbe/xgbe-desc.c | 40 +++---
drivers/net/ethernet/amd/xgbe/xgbe-dev.c | 170 +++++++++++++++++++++------
drivers/net/ethernet/amd/xgbe/xgbe-drv.c | 112 ++++++++++++++----
drivers/net/ethernet/amd/xgbe/xgbe.h | 42 ++++++-
5 files changed, 289 insertions(+), 96 deletions(-)
--
Tom Lendacky
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox