* RE: [PATCH] net: stmmac: synchronize stmmac_open and stmmac_dvr_probe
From: Kweh, Hock Leong @ 2016-12-27 5:25 UTC (permalink / raw)
To: Florian Fainelli, David S. Miller, Joao Pinto, Giuseppe CAVALLARO,
seraphin.bonnaffe@st.com
Cc: Alexandre TORGUE, Joachim Eastwood, Niklas Cassel, Johan Hovold,
pavel@ucw.cz, Ong, Boon Leong, netdev, LKML, Voon, Weifeng,
Lars Persson
In-Reply-To: <6df6425b-bb0c-1e74-b5e1-a221447b761f@gmail.com>
> -----Original Message-----
> From: Florian Fainelli [mailto:f.fainelli@gmail.com]
> Sent: Tuesday, December 27, 2016 1:14 PM
> To: Kweh, Hock Leong <hock.leong.kweh@intel.com>; David S. Miller
> <davem@davemloft.net>; Joao Pinto <Joao.Pinto@synopsys.com>; Giuseppe
> CAVALLARO <peppe.cavallaro@st.com>; seraphin.bonnaffe@st.com
> Cc: Alexandre TORGUE <alexandre.torgue@gmail.com>; Joachim Eastwood
> <manabian@gmail.com>; Niklas Cassel <niklas.cassel@axis.com>; Johan Hovold
> <johan@kernel.org>; pavel@ucw.cz; Ong, Boon Leong
> <boon.leong.ong@intel.com>; netdev <netdev@vger.kernel.org>; LKML <linux-
> kernel@vger.kernel.org>; Voon, Weifeng <weifeng.voon@intel.com>; Lars
> Persson <lars.persson@axis.com>
> Subject: Re: [PATCH] net: stmmac: synchronize stmmac_open and
> stmmac_dvr_probe
>
>
>
> On 12/26/2016 09:10 PM, Florian Fainelli wrote:
> >
> >
> > On 12/27/2016 03:44 AM, Kweh, Hock Leong wrote:
> >> From: "Kweh, Hock Leong" <hock.leong.kweh@intel.com>
> >>
> >> If kernel module stmmac driver being loaded after OS booted, there is a
> >> race condition between stmmac_open() and stmmac_mdio_register(), which
> is
> >> invoked inside stmmac_dvr_probe(), and the error is showed in dmesg log as
> >> PHY not found and stmmac_open() failed:
> >> [ 473.919358] stmmaceth 0000:01:00.0 (unnamed net_device) (uninitialized):
> >> stmmac_dvr_probe: warning: cannot get CSR clock
> >> [ 473.919382] stmmaceth 0000:01:00.0: no reset control found
> >> [ 473.919412] stmmac - user ID: 0x10, Synopsys ID: 0x42
> >> [ 473.919429] stmmaceth 0000:01:00.0: DMA HW capability register
> supported
> >> [ 473.919436] stmmaceth 0000:01:00.0: RX Checksum Offload Engine
> supported
> >> [ 473.919443] stmmaceth 0000:01:00.0: TX Checksum insertion supported
> >> [ 473.919451] stmmaceth 0000:01:00.0 (unnamed net_device) (uninitialized):
> >> Enable RX Mitigation via HW Watchdog Timer
> >> [ 473.921395] libphy: PHY stmmac-1:00 not found
> >> [ 473.921417] stmmaceth 0000:01:00.0 eth0: Could not attach to PHY
> >> [ 473.921427] stmmaceth 0000:01:00.0 eth0: stmmac_open: Cannot attach
> to
> >> PHY (error: -19)
> >> [ 473.959710] libphy: stmmac: probed
> >> [ 473.959724] stmmaceth 0000:01:00.0 eth0: PHY ID 01410cc2 at 0 IRQ POLL
> >> (stmmac-1:00) active
> >> [ 473.959728] stmmaceth 0000:01:00.0 eth0: PHY ID 01410cc2 at 1 IRQ POLL
> >> (stmmac-1:01)
> >> [ 473.959731] stmmaceth 0000:01:00.0 eth0: PHY ID 01410cc2 at 2 IRQ POLL
> >> (stmmac-1:02)
> >> [ 473.959734] stmmaceth 0000:01:00.0 eth0: PHY ID 01410cc2 at 3 IRQ POLL
> >> (stmmac-1:03)
> >>
> >> The resolution used wait_for_completion_interruptible() to synchronize
> >> stmmac_open() and stmmac_dvr_probe() to prevent the race condition
> >> happening.
> >
> > The proper fix for this would be to have register_netdev() be the last
> > thing done in stmmac_drv_probe(), whereas right now, the last thing done
> > is stmmac_mdio_register(), leading the window you are seeing here, where
> > the network interface can be open prior to all resources being set up,
> > including, but not limited to MDIO devices.
>
> Something like the following untested patch should plug this race:
>
> diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> index bb40382e205d..5910ea51f8f6 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> @@ -3339,13 +3339,6 @@ int stmmac_dvr_probe(struct device *device,
>
> spin_lock_init(&priv->lock);
>
> - ret = register_netdev(ndev);
> - if (ret) {
> - netdev_err(priv->dev, "%s: ERROR %i registering the
> device\n",
> - __func__, ret);
> - goto error_netdev_register;
> - }
> -
> /* If a specific clk_csr value is passed from the platform
> * this means that the CSR Clock Range selection cannot be
> * changed at run-time and it is fixed. Viceversa the driver'll
> try to
> @@ -3372,11 +3365,14 @@ int stmmac_dvr_probe(struct device *device,
> }
> }
>
> - return 0;
> + ret = register_netdev(ndev);
> + if (ret)
> + netdev_err(priv->dev, "%s: ERROR %i registering the
> device\n",
> + __func__, ret);
> +
> + return ret;
>
> error_mdio_register:
> - unregister_netdev(ndev);
> -error_netdev_register:
> netif_napi_del(&priv->napi);
> error_hw_init:
> clk_disable_unprepare(priv->pclk);
>
> --
> Florian
Thanks. Will try out to confirm.
Regards,
Wilson
^ permalink raw reply
* RE: [PATCH] net: stmmac: synchronize stmmac_open and stmmac_dvr_probe
From: Kweh, Hock Leong @ 2016-12-27 5:26 UTC (permalink / raw)
To: David Miller
Cc: Joao.Pinto@synopsys.com, peppe.cavallaro@st.com,
seraphin.bonnaffe@st.com, alexandre.torgue@gmail.com,
manabian@gmail.com, niklas.cassel@axis.com, johan@kernel.org,
pavel@ucw.cz, Ong, Boon Leong, netdev@vger.kernel.org,
linux-kernel@vger.kernel.org, Voon, Weifeng,
lars.persson@axis.com
In-Reply-To: <20161226.235436.131087168899382517.davem@davemloft.net>
> -----Original Message-----
> From: David Miller [mailto:davem@davemloft.net]
> Sent: Tuesday, December 27, 2016 12:55 PM
> To: Kweh, Hock Leong <hock.leong.kweh@intel.com>
> Cc: Joao.Pinto@synopsys.com; peppe.cavallaro@st.com;
> seraphin.bonnaffe@st.com; alexandre.torgue@gmail.com;
> manabian@gmail.com; niklas.cassel@axis.com; johan@kernel.org;
> pavel@ucw.cz; Ong, Boon Leong <boon.leong.ong@intel.com>;
> netdev@vger.kernel.org; linux-kernel@vger.kernel.org; Voon, Weifeng
> <weifeng.voon@intel.com>; lars.persson@axis.com
> Subject: Re: [PATCH] net: stmmac: synchronize stmmac_open and
> stmmac_dvr_probe
>
> From: "Kweh, Hock Leong" <hock.leong.kweh@intel.com>
> Date: Tue, 27 Dec 2016 19:44:59 +0800
>
> > From: "Kweh, Hock Leong" <hock.leong.kweh@intel.com>
> >
> > If kernel module stmmac driver being loaded after OS booted, there is a
> > race condition between stmmac_open() and stmmac_mdio_register(), which is
> > invoked inside stmmac_dvr_probe(), and the error is showed in dmesg log as
> > PHY not found and stmmac_open() failed:
> ...
> > The resolution used wait_for_completion_interruptible() to synchronize
> > stmmac_open() and stmmac_dvr_probe() to prevent the race condition
> > happening.
> >
> > Signed-off-by: Kweh, Hock Leong <hock.leong.kweh@intel.com>
>
> The proper thing to do is to make sure register_netdevice() is not
> invoked until it is %100 safe to call stmmac_open().
Noted & thanks. Will look into it.
Regards,
Wilson
^ permalink raw reply
* Re: driver r8169 suddenly failed
From: Robert Grasso @ 2016-12-27 7:33 UTC (permalink / raw)
To: Francois Romieu; +Cc: Realtek linux nic maintainers, netdev
In-Reply-To: <20161227001248.GA20172@electric-eye.fr.zoreil.com>
Thank you for your quick answer ! Allow me some days for this test :
1 - I am at work these days
2 - it has been a while since I have dealt with custom kernels, I am a
bit rusty, it will be good to review this topic
--
Robert Grasso
@home
---
UNIX was not designed to stop you from doing stupid things, because
that would also stop you from doing clever things. -- Doug Gwyn
On 27/12/2016 01:12, Francois Romieu wrote:
> Robert Grasso <robert.grasso@modulonet.fr> :
> [dhcp snafu]
>> First of all, can you confirm that I am doing right in posting to you
>> (addresses found in README.Debian) ?
> It isn't completely wrong.
>
>> If I do, can you help ? I am not very proficient with Ethernet, and I am not
>> able to figure out what my provider changed : their hotline is
>> underqualified, they are just able to tell that "the signal on the line is
>> ok".
> You're spoiled. It is more than decent for a company whose core business
> used to sell cable TV.
>
>> But if you want me to run various tests, try new versions, I would be
>> glad to do so : I would appreciate if I could salvage this Shuttle.
> Please try a recent stable vanilla kernel and send a complete dmesg
> from boot. I need to identify the specific 816x chipset.
>
> Then record some traffic:
>
> # touch gonzo.pcap && tshark -w gonzo.pcap -i eth1
>
> It should only exhibit small outgoing packets but, well, one never knows.
>
> Check the leds activity to be sure that the network interfaces have not
> been renumbered.
>
> Use ethtool to check that tso is disabled. If it isn't, disable it.
>
^ permalink raw reply
* [PATCH] net: fix incorrect original ingress device index in PKTINFO
From: Wei Zhang @ 2016-12-27 7:52 UTC (permalink / raw)
To: davem, kuznet, jmorris, yoshfuji, kaber; +Cc: netdev, linux-kernel
When we send a packet for our own local address on a non-loopback interface
(e.g. eth0), due to the change had been introduced from commit 0b922b7a829c
("net: original ingress device index in PKTINFO"), the original ingress
device index would be set as the loopback interface. However, the packet
should be considered as if it is being arrived via the sending interface
(eth0), otherwise it would break the expectation of the userspace
application (e.g. the DHCPRELEASE message from dhcp_release binary would
be ignored by the dnsmasq daemon)
Signed-off-by: Wei Zhang <asuka.com@163.com>
---
net/ipv4/ip_sockglue.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c
index b8a2d63..b6a6d35 100644
--- a/net/ipv4/ip_sockglue.c
+++ b/net/ipv4/ip_sockglue.c
@@ -1202,8 +1202,13 @@ void ipv4_pktinfo_prepare(const struct sock *sk, struct sk_buff *skb)
* which has interface index (iif) as the first member of the
* underlying inet{6}_skb_parm struct. This code then overlays
* PKTINFO_SKB_CB and in_pktinfo also has iif as the first
- * element so the iif is picked up from the prior IPCB
+ * element so the iif is picked up from the prior IPCB except
+ * iif is loopback interface which the packet should be
+ * considered as if it is being arrived via the sending interface
*/
+ if (pktinfo->ipi_ifindex == LOOPBACK_IFINDEX) {
+ pktinfo->ipi_ifindex = inet_iif(skb);
+ }
pktinfo->ipi_spec_dst.s_addr = fib_compute_spec_dst(skb);
} else {
pktinfo->ipi_ifindex = 0;
--
1.8.3.1
^ permalink raw reply related
* [PATCH] net: dev_weight: TX/RX orthogonality
From: Matthias Tafelmeier @ 2016-12-27 8:25 UTC (permalink / raw)
To: netdev; +Cc: hagen, fw, edumazet, daniel
In-Reply-To: <20161226.115818.1691666598003246082.davem@davemloft.net>
Oftenly, introducing side effects on packet processing on the other half
of the stack by adjusting one of TX/RX via sysctl is not desirable.
There are cases of demand for asymmetric, orthogonal configurability.
This holds true especially for nodes where RPS for RFS usage on top is
configured and therefore use the 'old dev_weight'. This is quite a
common base configuration setup nowadays, even with NICs of superior processing
support (e.g. aRFS).
A good example use case are nodes acting as noSQL data bases with a
large number of tiny requests and rather fewer but large packets as responses.
It's affordable to have large budget and rx dev_weights for the
requests. But as a side effect having this large a number on TX
processed in one run can overwhelm drivers.
This patch therefore introduces an independent configurability via sysctl to
userland.
---
include/linux/netdevice.h | 2 ++
net/core/dev.c | 4 +++-
net/core/sysctl_net_core.c | 14 ++++++++++++++
net/sched/sch_generic.c | 2 +-
4 files changed, 20 insertions(+), 2 deletions(-)
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 994f742..bb331e0 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -3795,6 +3795,8 @@ void netdev_stats_to_stats64(struct rtnl_link_stats64 *stats64,
extern int netdev_max_backlog;
extern int netdev_tstamp_prequeue;
extern int weight_p;
+extern int dev_w_rx_bias;
+extern int dev_w_tx_bias;
bool netdev_has_upper_dev(struct net_device *dev, struct net_device *upper_dev);
struct net_device *netdev_upper_get_next_dev_rcu(struct net_device *dev,
diff --git a/net/core/dev.c b/net/core/dev.c
index 8db5a0b..0dcbd28 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -3428,6 +3428,8 @@ EXPORT_SYMBOL(netdev_max_backlog);
int netdev_tstamp_prequeue __read_mostly = 1;
int netdev_budget __read_mostly = 300;
int weight_p __read_mostly = 64; /* old backlog weight */
+int dev_w_rx_bias __read_mostly = 1; /* bias for backlog weight */
+int dev_w_tx_bias __read_mostly = 1; /* bias for output_queue quota */
/* Called with irq disabled */
static inline void ____napi_schedule(struct softnet_data *sd,
@@ -4833,7 +4835,7 @@ static int process_backlog(struct napi_struct *napi, int quota)
net_rps_action_and_irq_enable(sd);
}
- napi->weight = weight_p;
+ napi->weight = weight_p * dev_w_rx_bias;
while (again) {
struct sk_buff *skb;
diff --git a/net/core/sysctl_net_core.c b/net/core/sysctl_net_core.c
index 2a46e40..a2ab149 100644
--- a/net/core/sysctl_net_core.c
+++ b/net/core/sysctl_net_core.c
@@ -276,6 +276,20 @@ static struct ctl_table net_core_table[] = {
.proc_handler = proc_dointvec
},
{
+ .procname = "dev_w_rx_bias",
+ .data = &dev_w_rx_bias,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = proc_dointvec
+ },
+ {
+ .procname = "dev_w_tx_bias",
+ .data = &dev_w_tx_bias,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = proc_dointvec
+ },
+ {
.procname = "netdev_max_backlog",
.data = &netdev_max_backlog,
.maxlen = sizeof(int),
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c
index 6eb9c8e..4c07780 100644
--- a/net/sched/sch_generic.c
+++ b/net/sched/sch_generic.c
@@ -247,7 +247,7 @@ static inline int qdisc_restart(struct Qdisc *q, int *packets)
void __qdisc_run(struct Qdisc *q)
{
- int quota = weight_p;
+ int quota = weight_p * dev_w_tx_bias;
int packets;
while (qdisc_restart(q, &packets)) {
--
2.7.4
^ permalink raw reply related
* Re:[PATCH] net: fix incorrect original ingress device index in PKTINFO
From: wei zhang @ 2016-12-27 8:29 UTC (permalink / raw)
To: kuznet, davem, jmorris, yoshfuji, kaber; +Cc: netdev, linux-kernel
In-Reply-To: <1482825138-2125-1-git-send-email-asuka.com@163.com>
At 2016-12-27 15:52:18, "Wei Zhang" <asuka.com@163.com> wrote:
>When we send a packet for our own local address on a non-loopback interface
>(e.g. eth0), due to the change had been introduced from commit 0b922b7a829c
>("net: original ingress device index in PKTINFO"), the original ingress
>device index would be set as the loopback interface. However, the packet
>should be considered as if it is being arrived via the sending interface
>(eth0), otherwise it would break the expectation of the userspace
>application (e.g. the DHCPRELEASE message from dhcp_release binary would
>be ignored by the dnsmasq daemon)
>
>Signed-off-by: Wei Zhang <asuka.com@163.com>
>---
> net/ipv4/ip_sockglue.c | 7 ++++++-
> 1 file changed, 6 insertions(+), 1 deletion(-)
>
>diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c
>index b8a2d63..b6a6d35 100644
>--- a/net/ipv4/ip_sockglue.c
>+++ b/net/ipv4/ip_sockglue.c
>@@ -1202,8 +1202,13 @@ void ipv4_pktinfo_prepare(const struct sock *sk, struct sk_buff *skb)
> * which has interface index (iif) as the first member of the
> * underlying inet{6}_skb_parm struct. This code then overlays
> * PKTINFO_SKB_CB and in_pktinfo also has iif as the first
>- * element so the iif is picked up from the prior IPCB
>+ * element so the iif is picked up from the prior IPCB except
>+ * iif is loopback interface which the packet should be
>+ * considered as if it is being arrived via the sending interface
> */
>+ if (pktinfo->ipi_ifindex == LOOPBACK_IFINDEX) {
>+ pktinfo->ipi_ifindex = inet_iif(skb);
>+ }
> pktinfo->ipi_spec_dst.s_addr = fib_compute_spec_dst(skb);
> } else {
> pktinfo->ipi_ifindex = 0;
>--
>1.8.3.1
>
When I upgrade to the 4.9, the dhcp_release could not release the dhcp
lease, the dnsmasq ignored all the DHCPRELEASE message which it think come
from lo. I think this is due to the commit 0b922b7a829c, which set the
IPCB(skb)->iif = skb->skb_iif in the ip_rcv()!
And I'm very sorry about forgetting checkpatch, I will resend the patch,
hope I'm not bothering you!
Thanks,
Wei Zhang
^ permalink raw reply
* [PATCH net-next] r8169: add support for RTL8168 series add-on card.
From: Chun-Hao Lin @ 2016-12-27 8:29 UTC (permalink / raw)
To: netdev; +Cc: nic_swsd, linux-kernel, Chun-Hao Lin
This chip is the same as RTL8168, but its device id is 0x8161.
Signed-off-by: Chun-Hao Lin <hau@realtek.com>
---
drivers/net/ethernet/realtek/r8169.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c
index f9b97f5..44389c9 100644
--- a/drivers/net/ethernet/realtek/r8169.c
+++ b/drivers/net/ethernet/realtek/r8169.c
@@ -326,6 +326,7 @@ enum cfg_version {
static const struct pci_device_id rtl8169_pci_tbl[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8129), 0, 0, RTL_CFG_0 },
{ PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8136), 0, 0, RTL_CFG_2 },
+ { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8161), 0, 0, RTL_CFG_1 },
{ PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8167), 0, 0, RTL_CFG_0 },
{ PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8168), 0, 0, RTL_CFG_1 },
{ PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8169), 0, 0, RTL_CFG_0 },
--
2.7.4
^ permalink raw reply related
* Re: [PATCH net] net: xdp: remove unused bfp_warn_invalid_xdp_buffer()
From: Daniel Borkmann @ 2016-12-27 9:29 UTC (permalink / raw)
To: Jason Wang, davem, linux-kernel, netdev; +Cc: John Fastabend
In-Reply-To: <1482806994-14649-1-git-send-email-jasowang@redhat.com>
On 12/27/2016 03:49 AM, Jason Wang wrote:
> After commit 73b62bd085f4737679ea9afc7867fa5f99ba7d1b ("virtio-net:
> remove the warning before XDP linearizing"), there's no users for
> bpf_warn_invalid_xdp_buffer(), so remove it. This is a revert for
> commit f23bc46c30ca5ef58b8549434899fcbac41b2cfc.
>
> Cc: Daniel Borkmann <daniel@iogearbox.net>
> Cc: John Fastabend <john.r.fastabend@intel.com>
> Signed-off-by: Jason Wang <jasowang@redhat.com>
Thanks for following up.
Acked-by: Daniel Borkmann <daniel@iogearbox.net>
^ permalink raw reply
* [PATCH] net: fix incorrect original ingress device index in PKTINFO
From: Wei Zhang @ 2016-12-27 9:52 UTC (permalink / raw)
To: davem, kuznet, jmorris, yoshfuji, kaber; +Cc: netdev, linux-kernel
When we send a packet for our own local address on a non-loopback
interface (e.g. eth0), due to the change had been introduced from
commit 0b922b7a829c ("net: original ingress device index in PKTINFO"), the
original ingress device index would be set as the loopback interface.
However, the packet should be considered as if it is being arrived via the
sending interface (eth0), otherwise it would break the expectation of the
userspace application (e.g. the DHCPRELEASE message from dhcp_release
binary would be ignored by the dnsmasq daemon, since it come from lo which
is not the interface dnsmasq bind to)
Signed-off-by: Wei Zhang <asuka.com@163.com>
---
net/ipv4/ip_sockglue.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c
index b8a2d63..76d78a7 100644
--- a/net/ipv4/ip_sockglue.c
+++ b/net/ipv4/ip_sockglue.c
@@ -1202,8 +1202,14 @@ void ipv4_pktinfo_prepare(const struct sock *sk, struct sk_buff *skb)
* which has interface index (iif) as the first member of the
* underlying inet{6}_skb_parm struct. This code then overlays
* PKTINFO_SKB_CB and in_pktinfo also has iif as the first
- * element so the iif is picked up from the prior IPCB
+ * element so the iif is picked up from the prior IPCB except
+ * iif is loopback interface which the packet should be
+ * considered as if it is being arrived via the sending
+ * interface
*/
+ if (pktinfo->ipi_ifindex == LOOPBACK_IFINDEX)
+ pktinfo->ipi_ifindex = inet_iif(skb);
+
pktinfo->ipi_spec_dst.s_addr = fib_compute_spec_dst(skb);
} else {
pktinfo->ipi_ifindex = 0;
--
1.8.3.1
^ permalink raw reply related
* Greetings From Mr. Hamidou Kader.
From: Mr. Hamidou Kader @ 2016-12-27 9:50 UTC (permalink / raw)
In-Reply-To: <1424159083.2117965.1482832245161.ref@mail.yahoo.com>
Greetings From Mr. Hamidou Kader.
I have a Mutual/Beneficial Business Project that would be beneficial to you. I only have two questions to ask of you,if you are interested.
1. Can you handle this project?
2. Can I give you this trust ?
Please note that the deal requires high level of maturity, honesty and secrecy. This will involve moving some money from my office, on trust to your hands or bank account. Also note that i will do everything to make sure that the money is moved as a purely legitimate fund, so you will not be exposed to any risk.
I request for your full co-operation. I will give you details and procedure when I receive your reply, To commence this transaction, I require you to immediately indicate your interest by a return reply.
I will be waiting for your response in a timely manner.
please contact me through my private email address: hamidoukader@barid.com
Best Regard,
Mr. Hamidou Kader
^ permalink raw reply
* Re: [RFC PATCH 4.10 1/6] crypto/sha256: Refactor the API so it can be used without shash
From: Herbert Xu @ 2016-12-27 9:58 UTC (permalink / raw)
To: Andy Lutomirski
Cc: Ard Biesheuvel, Andy Lutomirski, Daniel Borkmann, Netdev, LKML,
Linux Crypto Mailing List, Jason A. Donenfeld,
Hannes Frederic Sowa, Alexei Starovoitov, Eric Dumazet,
Eric Biggers, Tom Herbert, David S. Miller
In-Reply-To: <CALCETrXFTQ2AXgbQzPnRcDRHK81=FS1R0zqfoTqGjUsqZy2PvQ@mail.gmail.com>
On Mon, Dec 26, 2016 at 10:08:48AM -0800, Andy Lutomirski wrote:
>
> According to Daniel, the networking folks want to let embedded systems
> include BPF without requiring the crypto core.
Last I checked the IPv4 stack depended on the crypto API so this
sounds bogus.
Cheers,
--
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
^ permalink raw reply
* Re: [PATCH] net: fix incorrect original ingress device index in PKTINFO
From: Sergei Shtylyov @ 2016-12-27 10:01 UTC (permalink / raw)
To: Wei Zhang, davem, kuznet, jmorris, yoshfuji, kaber; +Cc: netdev, linux-kernel
In-Reply-To: <1482825138-2125-1-git-send-email-asuka.com@163.com>
Hello!
On 12/27/2016 10:52 AM, Wei Zhang wrote:
> When we send a packet for our own local address on a non-loopback interface
> (e.g. eth0), due to the change had been introduced from commit 0b922b7a829c
> ("net: original ingress device index in PKTINFO"), the original ingress
> device index would be set as the loopback interface. However, the packet
> should be considered as if it is being arrived via the sending interface
> (eth0), otherwise it would break the expectation of the userspace
> application (e.g. the DHCPRELEASE message from dhcp_release binary would
> be ignored by the dnsmasq daemon)
>
> Signed-off-by: Wei Zhang <asuka.com@163.com>
> ---
> net/ipv4/ip_sockglue.c | 7 ++++++-
> 1 file changed, 6 insertions(+), 1 deletion(-)
>
> diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c
> index b8a2d63..b6a6d35 100644
> --- a/net/ipv4/ip_sockglue.c
> +++ b/net/ipv4/ip_sockglue.c
> @@ -1202,8 +1202,13 @@ void ipv4_pktinfo_prepare(const struct sock *sk, struct sk_buff *skb)
> * which has interface index (iif) as the first member of the
> * underlying inet{6}_skb_parm struct. This code then overlays
> * PKTINFO_SKB_CB and in_pktinfo also has iif as the first
> - * element so the iif is picked up from the prior IPCB
> + * element so the iif is picked up from the prior IPCB except
> + * iif is loopback interface which the packet should be
Tail space.
> + * considered as if it is being arrived via the sending interface
> */
> + if (pktinfo->ipi_ifindex == LOOPBACK_IFINDEX) {
> + pktinfo->ipi_ifindex = inet_iif(skb);
> + }
{} not needed here.
> pktinfo->ipi_spec_dst.s_addr = fib_compute_spec_dst(skb);
> } else {
> pktinfo->ipi_ifindex = 0;
MBR, Sergei
^ permalink raw reply
* Re: [PATCH v2] net: stmmac: bug fix to synchronize stmmac_open and stmmac_dvr_probe
From: Pavel Machek @ 2016-12-27 10:48 UTC (permalink / raw)
To: Kweh, Hock Leong
Cc: David S. Miller, Joao Pinto, Giuseppe CAVALLARO,
seraphin.bonnaffe, f.fainelli, Alexandre TORGUE, Joachim Eastwood,
Niklas Cassel, Johan Hovold, Ong Boon Leong, weifeng.voon,
lars.persson, Netdev list, LKML
In-Reply-To: <1482849756-21817-1-git-send-email-hock.leong.kweh@intel.com>
[-- Attachment #1: Type: text/plain, Size: 2190 bytes --]
On Tue 2016-12-27 22:42:36, Kweh, Hock Leong wrote:
> From: "Kweh, Hock Leong" <hock.leong.kweh@intel.com>
>
> If kernel module stmmac driver being loaded after OS booted, there is a
> race condition between stmmac_open() and stmmac_mdio_register(), which is
> invoked inside stmmac_dvr_probe(), and the error is showed in dmesg log as
> PHY not found and stmmac_open() failed:
> [ 473.919358] stmmaceth 0000:01:00.0 (unnamed net_device) (uninitialized):
> stmmac_dvr_probe: warning: cannot get CSR clock
> [ 473.919382] stmmaceth 0000:01:00.0: no reset control found
> [ 473.919412] stmmac - user ID: 0x10, Synopsys ID: 0x42
> [ 473.919429] stmmaceth 0000:01:00.0: DMA HW capability register supported
> [ 473.919436] stmmaceth 0000:01:00.0: RX Checksum Offload Engine supported
> [ 473.919443] stmmaceth 0000:01:00.0: TX Checksum insertion supported
> [ 473.919451] stmmaceth 0000:01:00.0 (unnamed net_device) (uninitialized):
> Enable RX Mitigation via HW Watchdog Timer
> [ 473.921395] libphy: PHY stmmac-1:00 not found
> [ 473.921417] stmmaceth 0000:01:00.0 eth0: Could not attach to PHY
> [ 473.921427] stmmaceth 0000:01:00.0 eth0: stmmac_open: Cannot attach to
> PHY (error: -19)
> [ 473.959710] libphy: stmmac: probed
> [ 473.959724] stmmaceth 0000:01:00.0 eth0: PHY ID 01410cc2 at 0 IRQ POLL
> (stmmac-1:00) active
> [ 473.959728] stmmaceth 0000:01:00.0 eth0: PHY ID 01410cc2 at 1 IRQ POLL
> (stmmac-1:01)
> [ 473.959731] stmmaceth 0000:01:00.0 eth0: PHY ID 01410cc2 at 2 IRQ POLL
> (stmmac-1:02)
> [ 473.959734] stmmaceth 0000:01:00.0 eth0: PHY ID 01410cc2 at 3 IRQ POLL
> (stmmac-1:03)
>
> The resolution moved the register_netdev() function call to the end of
> stmmac_dvr_probe() after stmmac_mdio_register().
>
> Suggested-by: Florian Fainelli <f.fainelli@gmail.com>
> Signed-off-by: Kweh, Hock Leong <hock.leong.kweh@intel.com>
Acked-by: Pavel Machek <pavel@ucw.cz>
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 181 bytes --]
^ permalink raw reply
* [PATCH] net: stmmac: synchronize stmmac_open and stmmac_dvr_probe
From: Kweh, Hock Leong @ 2016-12-27 11:44 UTC (permalink / raw)
To: David S. Miller, Joao Pinto, Giuseppe CAVALLARO,
seraphin.bonnaffe
Cc: Alexandre TORGUE, Joachim Eastwood, Niklas Cassel, Johan Hovold,
pavel, Kweh, Hock Leong, Ong Boon Leong, netdev, LKML,
weifeng.voon, Lars Persson
From: "Kweh, Hock Leong" <hock.leong.kweh@intel.com>
If kernel module stmmac driver being loaded after OS booted, there is a
race condition between stmmac_open() and stmmac_mdio_register(), which is
invoked inside stmmac_dvr_probe(), and the error is showed in dmesg log as
PHY not found and stmmac_open() failed:
[ 473.919358] stmmaceth 0000:01:00.0 (unnamed net_device) (uninitialized):
stmmac_dvr_probe: warning: cannot get CSR clock
[ 473.919382] stmmaceth 0000:01:00.0: no reset control found
[ 473.919412] stmmac - user ID: 0x10, Synopsys ID: 0x42
[ 473.919429] stmmaceth 0000:01:00.0: DMA HW capability register supported
[ 473.919436] stmmaceth 0000:01:00.0: RX Checksum Offload Engine supported
[ 473.919443] stmmaceth 0000:01:00.0: TX Checksum insertion supported
[ 473.919451] stmmaceth 0000:01:00.0 (unnamed net_device) (uninitialized):
Enable RX Mitigation via HW Watchdog Timer
[ 473.921395] libphy: PHY stmmac-1:00 not found
[ 473.921417] stmmaceth 0000:01:00.0 eth0: Could not attach to PHY
[ 473.921427] stmmaceth 0000:01:00.0 eth0: stmmac_open: Cannot attach to
PHY (error: -19)
[ 473.959710] libphy: stmmac: probed
[ 473.959724] stmmaceth 0000:01:00.0 eth0: PHY ID 01410cc2 at 0 IRQ POLL
(stmmac-1:00) active
[ 473.959728] stmmaceth 0000:01:00.0 eth0: PHY ID 01410cc2 at 1 IRQ POLL
(stmmac-1:01)
[ 473.959731] stmmaceth 0000:01:00.0 eth0: PHY ID 01410cc2 at 2 IRQ POLL
(stmmac-1:02)
[ 473.959734] stmmaceth 0000:01:00.0 eth0: PHY ID 01410cc2 at 3 IRQ POLL
(stmmac-1:03)
The resolution used wait_for_completion_interruptible() to synchronize
stmmac_open() and stmmac_dvr_probe() to prevent the race condition
happening.
Signed-off-by: Kweh, Hock Leong <hock.leong.kweh@intel.com>
---
drivers/net/ethernet/stmicro/stmmac/stmmac.h | 1 +
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 10 ++++++++++
2 files changed, 11 insertions(+)
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
index eab04ae..5daf8a5 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
@@ -131,6 +131,7 @@ struct stmmac_priv {
u32 rx_tail_addr;
u32 tx_tail_addr;
u32 mss;
+ struct completion probe_done;
#ifdef CONFIG_DEBUG_FS
struct dentry *dbgfs_dir;
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index bb40382..28e85f6 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -1770,6 +1770,14 @@ static int stmmac_open(struct net_device *dev)
struct stmmac_priv *priv = netdev_priv(dev);
int ret;
+ ret = wait_for_completion_interruptible(&priv->probe_done);
+ if (ret) {
+ netdev_err(priv->dev,
+ "%s: Interrupted while waiting probe completion\n",
+ __func__);
+ return ret;
+ }
+
stmmac_check_ether_addr(priv);
if (priv->hw->pcs != STMMAC_PCS_RGMII &&
@@ -3226,6 +3234,7 @@ int stmmac_dvr_probe(struct device *device,
priv = netdev_priv(ndev);
priv->device = device;
priv->dev = ndev;
+ init_completion(&priv->probe_done);
stmmac_set_ethtool_ops(ndev);
priv->pause = pause;
@@ -3372,6 +3381,7 @@ int stmmac_dvr_probe(struct device *device,
}
}
+ complete_all(&priv->probe_done);
return 0;
error_mdio_register:
--
1.7.9.5
^ permalink raw reply related
* Platform init code in stmmac_main
From: Joao Pinto @ 2016-12-27 11:47 UTC (permalink / raw)
To: pavel@ucw.cz, Niklas Cassel, Giuseppe CAVALLARO, Florian Fainelli,
netdev
Hello,
I spotted in stmmac_main.c, *_dvr_probe() function, some clocks initializations
that are related with platform based setups:
priv->pclk = devm_clk_get(priv->device, "pclk");
if (IS_ERR(priv->pclk)) {
if (PTR_ERR(priv->pclk) == -EPROBE_DEFER) {
ret = -EPROBE_DEFER;
goto error_pclk_get;
}
priv->pclk = NULL;
}
clk_prepare_enable(priv->pclk);
priv->stmmac_rst = devm_reset_control_get(priv->device,
STMMAC_RESOURCE_NAME);
if (IS_ERR(priv->stmmac_rst)) {
if (PTR_ERR(priv->stmmac_rst) == -EPROBE_DEFER) {
ret = -EPROBE_DEFER;
goto error_hw_init;
}
dev_info(priv->device, "no reset control found\n");
priv->stmmac_rst = NULL;
}
if (priv->stmmac_rst)
reset_control_deassert(priv->stmmac_rst);
I am using PCI based setup, so these initializations are executed since they are
in common space in stmmac_main.c. Wouldn't be better to map these clocks in
stmmac_platform? This hasn't any problem for me, but I think it would improve
code readbility.
I would like to have your opinion about the subject!
Thanks,
Joao
^ permalink raw reply
* [PATCH] net: stmmac: fix incorrect bit set in gmac4 mdio addr register
From: Kweh, Hock Leong @ 2016-12-27 20:07 UTC (permalink / raw)
To: David S. Miller, Joao Pinto, Giuseppe CAVALLARO,
seraphin.bonnaffe, f.fainelli
Cc: Alexandre TORGUE, Joachim Eastwood, Niklas Cassel, Johan Hovold,
pavel, Ong Boon Leong, Kweh, Hock Leong, weifeng.voon,
lars.persson, netdev, LKML
From: "Kweh, Hock Leong" <hock.leong.kweh@intel.com>
Fixing the gmac4 mdio write access to use MII_GMAC4_WRITE only instead of
OR together with MII_WRITE.
Signed-off-by: Kweh, Hock Leong <hock.leong.kweh@intel.com>
---
drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
index fda01f7..b0344c2 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
@@ -116,7 +116,7 @@ static int stmmac_mdio_write(struct mii_bus *bus, int phyaddr, int phyreg,
unsigned int mii_address = priv->hw->mii.addr;
unsigned int mii_data = priv->hw->mii.data;
- u32 value = MII_WRITE | MII_BUSY;
+ u32 value = MII_BUSY;
value |= (phyaddr << priv->hw->mii.addr_shift)
& priv->hw->mii.addr_mask;
@@ -126,6 +126,8 @@ static int stmmac_mdio_write(struct mii_bus *bus, int phyaddr, int phyreg,
& priv->hw->mii.clk_csr_mask;
if (priv->plat->has_gmac4)
value |= MII_GMAC4_WRITE;
+ else
+ value |= MII_WRITE;
/* Wait until any existing MII operation is complete */
if (stmmac_mdio_busy_wait(priv->ioaddr, mii_address))
--
1.7.9.5
^ permalink raw reply related
* Re: [PATCH] net: stmmac: fix incorrect bit set in gmac4 mdio addr register
From: Joao Pinto @ 2016-12-27 12:11 UTC (permalink / raw)
To: Kweh, Hock Leong, David S. Miller, Joao Pinto, Giuseppe CAVALLARO,
seraphin.bonnaffe, f.fainelli
Cc: Alexandre TORGUE, Joachim Eastwood, Niklas Cassel, Johan Hovold,
pavel, Ong Boon Leong, weifeng.voon, lars.persson, netdev, LKML
In-Reply-To: <1482869261-23803-1-git-send-email-hock.leong.kweh@intel.com>
Às 8:07 PM de 12/27/2016, Kweh, Hock Leong escreveu:
> From: "Kweh, Hock Leong" <hock.leong.kweh@intel.com>
>
> Fixing the gmac4 mdio write access to use MII_GMAC4_WRITE only instead of
> OR together with MII_WRITE.
>
> Signed-off-by: Kweh, Hock Leong <hock.leong.kweh@intel.com>
> ---
> drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c | 4 +++-
> 1 file changed, 3 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
> index fda01f7..b0344c2 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
> @@ -116,7 +116,7 @@ static int stmmac_mdio_write(struct mii_bus *bus, int phyaddr, int phyreg,
> unsigned int mii_address = priv->hw->mii.addr;
> unsigned int mii_data = priv->hw->mii.data;
>
> - u32 value = MII_WRITE | MII_BUSY;
> + u32 value = MII_BUSY;
>
> value |= (phyaddr << priv->hw->mii.addr_shift)
> & priv->hw->mii.addr_mask;
> @@ -126,6 +126,8 @@ static int stmmac_mdio_write(struct mii_bus *bus, int phyaddr, int phyreg,
> & priv->hw->mii.clk_csr_mask;
> if (priv->plat->has_gmac4)
> value |= MII_GMAC4_WRITE;
> + else
> + value |= MII_WRITE;
>
> /* Wait until any existing MII operation is complete */
> if (stmmac_mdio_busy_wait(priv->ioaddr, mii_address))
>
Acked-By: Joao Pinto <jpinto@synopsys.com>
^ permalink raw reply
* [PATCH 01/12] Make and configuration files.
From: David VomLehn @ 2016-12-27 13:17 UTC (permalink / raw)
To: netdev
Cc: Simon Edelhaus, David VomLehn, Dmitrii Tarakanov,
Alexander Loktionov
Patches to create the make and configuration files.
Signed-off-by: Dmitrii Tarakanov <Dmitrii.Tarakanov@aquantia.com>
Signed-off-by: Alexander Loktionov <Alexander.Loktionov@aquantia.com>
Signed-off-by: David M. VomLehn <vomlehn@texas.net>
---
drivers/net/ethernet/aquantia/atlantic/Kconfig | 9 ++++++
drivers/net/ethernet/aquantia/atlantic/Makefile | 40 +++++++++++++++++++++++++
drivers/net/ethernet/aquantia/atlantic/ver.h | 18 +++++++++++
3 files changed, 67 insertions(+)
create mode 100644 drivers/net/ethernet/aquantia/atlantic/Kconfig
create mode 100644 drivers/net/ethernet/aquantia/atlantic/Makefile
create mode 100644 drivers/net/ethernet/aquantia/atlantic/ver.h
diff --git a/drivers/net/ethernet/aquantia/atlantic/Kconfig b/drivers/net/ethernet/aquantia/atlantic/Kconfig
new file mode 100644
index 0000000..33f1eb6
--- /dev/null
+++ b/drivers/net/ethernet/aquantia/atlantic/Kconfig
@@ -0,0 +1,9 @@
+#
+# Aquantia device configuration
+#
+
+config AQTION
+ tristate "Aquantia AQtion Support"
+ depends on PCI
+ ---help---
+ This enables the support for the Aquantia AQtion Ethernet card.
\ No newline at end of file
diff --git a/drivers/net/ethernet/aquantia/atlantic/Makefile b/drivers/net/ethernet/aquantia/atlantic/Makefile
new file mode 100644
index 0000000..f0d961f
--- /dev/null
+++ b/drivers/net/ethernet/aquantia/atlantic/Makefile
@@ -0,0 +1,40 @@
+TARGET:=atlantic
+
+CC = gcc
+
+ifeq "$(CC)" "gcc"
+ ccflags-y := -Wall
+endif
+
+ifneq ($(KERNELRELEASE),)
+ $(TARGET)-objs:=aq_main.o aq_nic.o aq_pci_func.o aq_nic.o aq_vec.o \
+ aq_ring.o aq_hw_utils.o aq_ethtool.o hw_atl/hw_atl_a0.o \
+ hw_atl/hw_atl_utils.o hw_atl/hw_atl_llh.o
+
+ obj-m:=$(TARGET).o
+else
+ ifndef KDIR
+ BUILD_DIR:=/lib/modules/$(shell uname -r)/build
+ else
+ BUILD_DIR:=$(KDIR)
+ endif
+
+ PWD:=$(shell pwd)
+
+all:
+ $(MAKE) -j4 CC=$(CC) -C $(BUILD_DIR) M=$(PWD) modules
+
+dox: .doxygen
+ @doxygen $<
+
+clean:
+ $(MAKE) -j4 -C $(BUILD_DIR) M=$(PWD) clean
+ @-rm -rdf doc/html 2 > /dev/null
+
+load:
+ insmod ./$(TARGET).ko
+
+unload:
+ rmmod ./$(TARGET).ko
+
+endif
diff --git a/drivers/net/ethernet/aquantia/atlantic/ver.h b/drivers/net/ethernet/aquantia/atlantic/ver.h
new file mode 100644
index 0000000..225f561
--- /dev/null
+++ b/drivers/net/ethernet/aquantia/atlantic/ver.h
@@ -0,0 +1,18 @@
+/*
+ * Aquantia Corporation Network Driver
+ * Copyright (C) 2014-2016 Aquantia Corporation. All rights reserved
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ */
+
+#ifndef VER_H
+#define VER_H
+
+#define NIC_MAJOR_DRIVER_VERSION 1
+#define NIC_MINOR_DRIVER_VERSION 4
+#define NIC_BUILD_DRIVER_VERSION 1671
+#define NIC_REVISION_DRIVER_VERSION 0
+
+#endif /* VER_H */
--
2.7.4
^ permalink raw reply related
* [PATCH 07/12] Vector operations
From: David VomLehn @ 2016-12-27 13:17 UTC (permalink / raw)
To: netdev
Cc: Simon Edelhaus, David VomLehn, Dmitrii Tarakanov,
Alexander Loktionov
In-Reply-To: <726fb213b0f282fc4a6b997721c3022551783fe6.1482844668.git.vomlehn@texas.net>
Add functions to manululate the vector of receive and transmit rings.
Signed-off-by: Dmitrii Tarakanov <Dmitrii.Tarakanov@aquantia.com>
Signed-off-by: Alexander Loktionov <Alexander.Loktionov@aquantia.com>
Signed-off-by: David M. VomLehn <vomlehn@texas.net>
---
drivers/net/ethernet/aquantia/atlantic/aq_vec.c | 375 ++++++++++++++++++++++++
drivers/net/ethernet/aquantia/atlantic/aq_vec.h | 40 +++
2 files changed, 415 insertions(+)
create mode 100644 drivers/net/ethernet/aquantia/atlantic/aq_vec.c
create mode 100644 drivers/net/ethernet/aquantia/atlantic/aq_vec.h
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_vec.c b/drivers/net/ethernet/aquantia/atlantic/aq_vec.c
new file mode 100644
index 0000000..c8340d7
--- /dev/null
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_vec.c
@@ -0,0 +1,375 @@
+//err_exit:
+//err_exit:
+/*
+ * Aquantia Corporation Network Driver
+ * Copyright (C) 2014-2016 Aquantia Corporation. All rights reserved
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ */
+
+/*
+ * File aq_vec.c: Definition of common structure for vector of Rx and Tx rings.
+ * Definition of functions for Rx and Tx rings. Friendly module for aq_nic.
+ */
+
+#include "aq_vec.h"
+#include "aq_nic.h"
+#include "aq_ring.h"
+#include "aq_hw.h"
+
+#include <linux/netdevice.h>
+
+struct aq_vec_s {
+ AQ_OBJ_HEADER;
+ struct aq_hw_ops *aq_hw_ops;
+ struct aq_hw_s *aq_hw;
+ struct aq_nic_s *aq_nic;
+ unsigned int tx_rings;
+ unsigned int rx_rings;
+ struct aq_ring_param_s aq_ring_param;
+ struct napi_struct napi;
+ struct aq_ring_s ring[AQ_CFG_TCS_MAX][2];
+};
+
+#define AQ_VEC_TX_ID 0
+#define AQ_VEC_RX_ID 1
+
+struct aq_vec_s *aq_vec_alloc(struct aq_nic_s *aq_nic, unsigned int idx,
+ struct aq_nic_cfg_s *aq_nic_cfg)
+{
+ struct aq_vec_s *self = NULL;
+ struct aq_ring_s *ring = NULL;
+ unsigned int i = 0U;
+ int err = 0;
+
+ self = kzalloc(sizeof(*self), GFP_KERNEL);
+ if (!self) {
+ err = -ENOMEM;
+ goto err_exit;
+ }
+
+ self->aq_nic = aq_nic;
+ self->aq_ring_param.vec_idx = idx;
+ self->aq_ring_param.cpu =
+ idx + aq_nic_cfg->aq_rss.base_cpu_number;
+
+ cpumask_set_cpu(self->aq_ring_param.cpu,
+ &self->aq_ring_param.affinity_mask);
+
+ self->tx_rings = 0;
+ self->rx_rings = 0;
+
+ netif_napi_add(aq_nic_get_ndev(aq_nic), &self->napi,
+ aq_vec_poll, AQ_CFG_NAPI_WEIGHT);
+
+ for (i = 0; i < aq_nic_cfg->tcs; ++i) {
+ unsigned int idx_ring = AQ_NIC_TCVEC2RING(self->nic,
+ self->tx_rings,
+ self->aq_ring_param.vec_idx);
+
+ ring = aq_ring_tx_alloc(&self->ring[i][AQ_VEC_TX_ID], aq_nic,
+ idx_ring, aq_nic_cfg);
+ if (!ring) {
+ err = -ENOMEM;
+ goto err_exit;
+ }
+
+ ++self->tx_rings;
+
+ aq_nic_set_tx_ring(aq_nic, idx_ring, ring);
+
+ ring = aq_ring_rx_alloc(&self->ring[i][AQ_VEC_RX_ID], aq_nic,
+ idx_ring, aq_nic_cfg);
+ if (!ring) {
+ err = -ENOMEM;
+ goto err_exit;
+ }
+
+ ++self->rx_rings;
+ }
+
+err_exit:
+ if (err < 0) {
+ aq_vec_free(self);
+ self = NULL;
+ }
+ return self;
+}
+
+int aq_vec_init(struct aq_vec_s *self, struct aq_hw_ops *aq_hw_ops,
+ struct aq_hw_s *aq_hw)
+{
+ struct aq_ring_s *ring = NULL;
+ unsigned int i = 0U;
+ int err = 0;
+
+ self->aq_hw_ops = aq_hw_ops;
+ self->aq_hw = aq_hw;
+
+ spin_lock_init(&self->lock);
+
+ for (i = 0U, ring = self->ring[0];
+ self->tx_rings > i; ++i, ring = self->ring[i]) {
+ err = aq_ring_init(&ring[AQ_VEC_TX_ID]);
+ if (err < 0)
+ goto err_exit;
+
+ err = self->aq_hw_ops->hw_ring_tx_init(self->aq_hw,
+ &ring[AQ_VEC_TX_ID],
+ &self->aq_ring_param);
+ if (err < 0)
+ goto err_exit;
+
+ err = aq_ring_init(&ring[AQ_VEC_RX_ID]);
+ if (err < 0)
+ goto err_exit;
+
+ err = self->aq_hw_ops->hw_ring_rx_init(self->aq_hw,
+ &ring[AQ_VEC_RX_ID],
+ &self->aq_ring_param);
+ if (err < 0)
+ goto err_exit;
+
+ err = aq_ring_rx_fill(&ring[AQ_VEC_RX_ID]);
+ if (err < 0)
+ goto err_exit;
+
+ err = self->aq_hw_ops->hw_ring_rx_fill(self->aq_hw,
+ &ring[AQ_VEC_RX_ID], 0U);
+ if (err < 0)
+ goto err_exit;
+ }
+
+err_exit:
+ return err;
+}
+
+int aq_vec_start(struct aq_vec_s *self)
+{
+ struct aq_ring_s *ring = NULL;
+ unsigned int i = 0U;
+ int err = 0;
+
+ for (i = 0U, ring = self->ring[0];
+ self->tx_rings > i; ++i, ring = self->ring[i]) {
+ err = self->aq_hw_ops->hw_ring_tx_start(self->aq_hw,
+ &ring[AQ_VEC_TX_ID]);
+ if (err < 0)
+ goto err_exit;
+
+ err = self->aq_hw_ops->hw_ring_rx_start(self->aq_hw,
+ &ring[AQ_VEC_RX_ID]);
+ if (err < 0)
+ goto err_exit;
+ }
+
+ napi_enable(&self->napi);
+
+err_exit:
+ return err;
+}
+
+int aq_vec_stop(struct aq_vec_s *self)
+{
+ struct aq_ring_s *ring = NULL;
+ unsigned int i = 0U;
+ int err = 0;
+
+ for (i = 0U, ring = self->ring[0];
+ self->tx_rings > i; ++i, ring = self->ring[i]) {
+ err = self->aq_hw_ops->hw_ring_tx_stop(self->aq_hw,
+ &ring[AQ_VEC_TX_ID]);
+
+ err = self->aq_hw_ops->hw_ring_rx_stop(self->aq_hw,
+ &ring[AQ_VEC_RX_ID]);
+ }
+
+ napi_disable(&self->napi);
+ return err;
+}
+
+int aq_vec_deinit(struct aq_vec_s *self)
+{
+ struct aq_ring_s *ring = NULL;
+ unsigned int i = 0U;
+ int err = 0;
+
+ for (i = 0U, ring = self->ring[0];
+ self->tx_rings > i; ++i, ring = self->ring[i]) {
+ err = aq_ring_tx_drop(&ring[AQ_VEC_TX_ID]);
+
+ err = aq_ring_deinit(&ring[AQ_VEC_TX_ID]);
+
+ err = aq_ring_rx_drop(&ring[AQ_VEC_RX_ID]);
+
+ err = aq_ring_deinit(&ring[AQ_VEC_RX_ID]);
+ }
+ return err;
+}
+
+void aq_vec_free(struct aq_vec_s *self)
+{
+ struct aq_ring_s *ring = NULL;
+ unsigned int i = 0U;
+
+ if (!self)
+ goto err_exit;
+
+ for (i = 0U, ring = self->ring[0];
+ self->tx_rings > i; ++i, ring = self->ring[i]) {
+ aq_ring_free(&ring[AQ_VEC_TX_ID]);
+ aq_ring_free(&ring[AQ_VEC_RX_ID]);
+ }
+
+ netif_napi_del(&self->napi);
+
+ kfree(self);
+
+err_exit:;
+}
+
+int aq_vec_poll(struct napi_struct *napi, int budget)
+{
+ struct aq_vec_s *self = container_of(napi, struct aq_vec_s, napi);
+ struct aq_ring_s *ring = NULL;
+ int work_done = 0;
+ int err = 0;
+ unsigned int i = 0U;
+ unsigned int sw_tail_old = 0U;
+ bool was_tx_cleaned = false;
+ bool is_locked = false;
+
+ if (!self) {
+ err = -EINVAL;
+ goto err_exit;
+ }
+ is_locked = spin_trylock(&self->lock);
+ if (!(is_locked)) {
+ err = -EBUSY;
+ goto err_exit;
+ }
+
+ for (i = 0U, ring = self->ring[0];
+ self->tx_rings > i; ++i, ring = self->ring[i]) {
+ if (self->aq_hw_ops->hw_ring_tx_head_update) {
+ err = self->aq_hw_ops->hw_ring_tx_head_update(self->aq_hw,
+ &ring[AQ_VEC_TX_ID]);
+ if (err < 0)
+ goto err_exit;
+ }
+
+ if (ring[AQ_VEC_TX_ID].sw_head != ring[AQ_VEC_TX_ID].hw_head) {
+ err = aq_ring_tx_clean(&ring[AQ_VEC_TX_ID]);
+ if (err < 0)
+ goto err_exit;
+ was_tx_cleaned = true;
+ }
+
+ err = self->aq_hw_ops->hw_ring_rx_receive(self->aq_hw,
+ &ring[AQ_VEC_RX_ID]);
+ if (err < 0)
+ goto err_exit;
+
+ if (ring[AQ_VEC_RX_ID].sw_head != ring[AQ_VEC_RX_ID].hw_head) {
+ err = aq_ring_rx_clean(&ring[AQ_VEC_RX_ID], &work_done,
+ budget - work_done);
+ if (err < 0)
+ goto err_exit;
+
+ sw_tail_old = ring[AQ_VEC_RX_ID].sw_tail;
+
+ err = aq_ring_rx_fill(&ring[AQ_VEC_RX_ID]);
+ if (err < 0)
+ goto err_exit;
+
+ err = self->aq_hw_ops->hw_ring_rx_fill(self->aq_hw,
+ &ring[AQ_VEC_RX_ID], sw_tail_old);
+ if (err < 0)
+ goto err_exit;
+ }
+ }
+
+ spin_unlock(&self->lock);
+
+ if (was_tx_cleaned)
+ work_done = budget;
+
+ if (work_done < budget) {
+ napi_complete_done(napi, work_done);
+ self->aq_hw_ops->hw_irq_enable(self->aq_hw,
+ 1U << self->aq_ring_param.vec_idx);
+ }
+
+err_exit:
+ if (is_locked)
+ spin_unlock(&self->lock);
+ return work_done;
+}
+
+irqreturn_t aq_vec_isr(int irq, void *private)
+{
+ struct aq_vec_s *self = (struct aq_vec_s *)private;
+ int err = 0;
+
+ if (!self) {
+ err = -EINVAL;
+ goto err_exit;
+ }
+ napi_schedule(&self->napi);
+
+err_exit:
+ return err >= 0 ? IRQ_HANDLED : IRQ_NONE;
+}
+
+irqreturn_t aq_vec_isr_legacy(int irq, void *private)
+{
+ struct aq_vec_s *self = (struct aq_vec_s *)private;
+ u64 irq_mask = 0U;
+ irqreturn_t err = 0;
+
+ if (!self) {
+ err = -EINVAL;
+ goto err_exit;
+ }
+ err = self->aq_hw_ops->hw_irq_read(self->aq_hw, &irq_mask);
+
+ if (irq_mask) {
+ self->aq_hw_ops->hw_irq_disable(self->aq_hw,
+ 1U << self->aq_ring_param.vec_idx);
+ napi_schedule(&self->napi);
+ } else {
+ self->aq_hw_ops->hw_irq_enable(self->aq_hw, 1U);
+ err = IRQ_NONE;
+ }
+
+err_exit:
+ return err >= 0 ? IRQ_HANDLED : IRQ_NONE;
+}
+
+cpumask_t *aq_vec_get_affinity_mask(struct aq_vec_s *self)
+{
+ return &self->aq_ring_param.affinity_mask;
+}
+
+int aq_vec_get_sw_stats(struct aq_vec_s *self, u64 *data, unsigned int *p_count)
+{
+ struct aq_ring_s *ring = NULL;
+ unsigned int count = 0U;
+ unsigned int r = 0U;
+
+ for (r = 0U, ring = self->ring[0];
+ self->tx_rings > r; ++r, ring = self->ring[r]) {
+ data[count] += ring[AQ_VEC_RX_ID].stats.rx_packets;
+ data[++count] += ring[AQ_VEC_TX_ID].stats.tx_packets;
+ data[++count] += ring[AQ_VEC_RX_ID].stats.jumbo_packets;
+ data[++count] += ring[AQ_VEC_RX_ID].stats.lro_packets;
+ data[++count] += ring[AQ_VEC_RX_ID].stats.rx_errors;
+ }
+
+ if (p_count)
+ *p_count = ++count;
+
+ return 0;
+}
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_vec.h b/drivers/net/ethernet/aquantia/atlantic/aq_vec.h
new file mode 100644
index 0000000..a37ce8c
--- /dev/null
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_vec.h
@@ -0,0 +1,40 @@
+/*
+ * Aquantia Corporation Network Driver
+ * Copyright (C) 2014-2016 Aquantia Corporation. All rights reserved
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ */
+
+/*
+ * File aq_vec.c: Definition of common structures for vector of Rx and Tx rings.
+ * Declaration of functions for Rx and Tx rings.
+ */
+
+#ifndef AQ_VEC_H
+#define AQ_VEC_H
+
+#include "aq_common.h"
+
+#include <linux/irqreturn.h>
+
+struct aq_hw_s;
+struct aq_hw_ops;
+
+int aq_vec_poll(struct napi_struct *napi, int budget);
+irqreturn_t aq_vec_isr(int irq, void *private);
+irqreturn_t aq_vec_isr_legacy(int irq, void *private);
+struct aq_vec_s *aq_vec_alloc(struct aq_nic_s *aq_nic, unsigned int idx,
+ struct aq_nic_cfg_s *aq_nic_cfg);
+int aq_vec_init(struct aq_vec_s *self, struct aq_hw_ops *aq_hw_ops,
+ struct aq_hw_s *aq_hw);
+int aq_vec_deinit(struct aq_vec_s *self);
+void aq_vec_free(struct aq_vec_s *self);
+int aq_vec_start(struct aq_vec_s *self);
+int aq_vec_stop(struct aq_vec_s *self);
+cpumask_t *aq_vec_get_affinity_mask(struct aq_vec_s *self);
+int aq_vec_get_sw_stats(struct aq_vec_s *self, u64 *data,
+ unsigned int *p_count);
+
+#endif /* AQ_VEC_H */
--
2.7.4
^ permalink raw reply related
* [PATCH 12/12] Receive side scaling
From: David VomLehn @ 2016-12-27 13:17 UTC (permalink / raw)
To: netdev
Cc: Simon Edelhaus, David VomLehn, Dmitrii Tarakanov,
Alexander Loktionov
In-Reply-To: <37565094793e5df8b63a1c025d0057382ae70221.1482844668.git.vomlehn@texas.net>
Add definitions that support receive side scaling.
Signed-off-by: Dmitrii Tarakanov <Dmitrii.Tarakanov@aquantia.com>
Signed-off-by: Alexander Loktionov <Alexander.Loktionov@aquantia.com>
Signed-off-by: David M. VomLehn <vomlehn@texas.net>
---
| 35 +++++++++++++++++++++++++
1 file changed, 35 insertions(+)
create mode 100644 drivers/net/ethernet/aquantia/atlantic/aq_rss.h
--git a/drivers/net/ethernet/aquantia/atlantic/aq_rss.h b/drivers/net/ethernet/aquantia/atlantic/aq_rss.h
new file mode 100644
index 0000000..181d373
--- /dev/null
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_rss.h
@@ -0,0 +1,35 @@
+/*
+ * Aquantia Corporation Network Driver
+ * Copyright (C) 2014-2016 Aquantia Corporation. All rights reserved
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ */
+
+/*
+ * File aq_rss.h: Receive Side Scaling definitions.
+ */
+
+#ifndef AQ_RSS_H
+#define AQ_RSS_H
+
+#include "aq_common.h"
+#include "aq_cfg.h"
+
+#define HASH_TYPE_IPV4 0x00000100U
+#define HASH_TYPE_TCP_IPV4 0x00000200U
+#define HASH_TYPE_IPV6 0x00000400U
+#define HASH_TYPE_IPV6_EX 0x00000800U
+#define HASH_TYPE_TCP_IPV6 0x00001000U
+#define HASH_TYPE_TCP_IPV6_EX 0x00002000U
+
+struct aq_receive_scale_parameters {
+ u16 base_cpu_number;
+ u16 indirection_table_size;
+ u16 hash_secret_key_size;
+ u32 hash_secret_key[AQ_CFG_RSS_HASHKEY_SIZE / sizeof(u32)];
+ u8 indirection_table[AQ_CFG_RSS_INDIRECTION_TABLE_MAX];
+};
+
+#endif /* AQ_RSS_H */
--
2.7.4
^ permalink raw reply related
* [PATCH 03/12] Add ring spport code
From: David VomLehn @ 2016-12-27 13:17 UTC (permalink / raw)
To: netdev
Cc: Simon Edelhaus, David VomLehn, Dmitrii Tarakanov,
Alexander Loktionov
In-Reply-To: <67f8be9c3f6a4fede2eefaa4a3c45f9dbaf9b411.1482844668.git.vomlehn@texas.net>
Add code to support the firmware transmit and receive ring buffers.
Signed-off-by: Dmitrii Tarakanov <Dmitrii.Tarakanov@aquantia.com>
Signed-off-by: Alexander Loktionov <Alexander.Loktionov@aquantia.com>
Signed-off-by: David M. VomLehn <vomlehn@texas.net>
---
drivers/net/ethernet/aquantia/atlantic/aq_ring.c | 383 +++++++++++++++++++++++
drivers/net/ethernet/aquantia/atlantic/aq_ring.h | 150 +++++++++
2 files changed, 533 insertions(+)
create mode 100644 drivers/net/ethernet/aquantia/atlantic/aq_ring.c
create mode 100644 drivers/net/ethernet/aquantia/atlantic/aq_ring.h
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ring.c b/drivers/net/ethernet/aquantia/atlantic/aq_ring.c
new file mode 100644
index 0000000..bec5fcc
--- /dev/null
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_ring.c
@@ -0,0 +1,383 @@
+/*
+ * Aquantia Corporation Network Driver
+ * Copyright (C) 2014-2016 Aquantia Corporation. All rights reserved
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ */
+
+/*
+ * File aq_pci_ring.c: Definition of functions for Rx/Tx rings.
+ */
+
+#include "aq_ring.h"
+#include "aq_nic.h"
+#include "aq_hw.h"
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+
+static struct aq_ring_s *aq_ring_alloc(struct aq_ring_s *self,
+ struct aq_nic_s *aq_nic,
+ struct aq_nic_cfg_s *aq_nic_cfg)
+{
+ int err = 0;
+
+ if (!self) {
+ err = -ENOMEM;
+ goto err_exit;
+ }
+ self->buff_ring = (struct aq_ring_buff_s *)
+ kzalloc(sizeof(struct aq_ring_buff_s) * self->size, GFP_KERNEL);
+
+ if (!self->buff_ring) {
+ err = -ENOMEM;
+ goto err_exit;
+ }
+ self->dx_ring = dma_alloc_coherent(aq_nic_get_dev(aq_nic),
+ self->size * self->dx_size,
+ &self->dx_ring_pa, GFP_KERNEL);
+ if (!self->dx_ring) {
+ err = -ENOMEM;
+ goto err_exit;
+ }
+
+err_exit:
+ if (err < 0) {
+ aq_ring_free(self);
+ self = NULL;
+ }
+ return self;
+}
+
+struct aq_ring_s *aq_ring_tx_alloc(struct aq_ring_s *self,
+ struct aq_nic_s *aq_nic,
+ unsigned int idx,
+ struct aq_nic_cfg_s *aq_nic_cfg)
+{
+ int err = 0;
+
+ if (!self) {
+ err = -ENOMEM;
+ goto err_exit;
+ }
+ self->aq_nic = aq_nic;
+ self->idx = idx;
+ self->size = aq_nic_cfg->txds;
+ self->dx_size = aq_nic_cfg->aq_hw_caps->txd_size;
+
+ self = aq_ring_alloc(self, aq_nic, aq_nic_cfg);
+ if (!self) {
+ err = -ENOMEM;
+ goto err_exit;
+ }
+
+err_exit:
+ if (err < 0) {
+ aq_ring_free(self);
+ self = NULL;
+ }
+ return self;
+}
+
+struct aq_ring_s *aq_ring_rx_alloc(struct aq_ring_s *self,
+ struct aq_nic_s *aq_nic,
+ unsigned int idx,
+ struct aq_nic_cfg_s *aq_nic_cfg)
+{
+ int err = 0;
+
+ if (!self) {
+ err = -ENOMEM;
+ goto err_exit;
+ }
+ self->aq_nic = aq_nic;
+ self->idx = idx;
+ self->size = aq_nic_cfg->rxds;
+ self->dx_size = aq_nic_cfg->aq_hw_caps->rxd_size;
+
+ self = aq_ring_alloc(self, aq_nic, aq_nic_cfg);
+ if (!self) {
+ err = -ENOMEM;
+ goto err_exit;
+ }
+
+err_exit:
+ if (err < 0) {
+ aq_ring_free(self);
+ self = NULL;
+ }
+ return self;
+}
+
+int aq_ring_init(struct aq_ring_s *self)
+{
+ self->hw_head = 0;
+ self->sw_head = 0;
+ self->sw_tail = 0;
+ return 0;
+}
+
+int aq_ring_deinit(struct aq_ring_s *self)
+{
+ return 0;
+}
+
+void aq_ring_free(struct aq_ring_s *self)
+{
+ if (!self)
+ goto err_exit;
+
+ kfree(self->buff_ring);
+
+ if (self->dx_ring)
+ dma_free_coherent(aq_nic_get_dev(self->aq_nic),
+ self->size * self->dx_size, self->dx_ring,
+ self->dx_ring_pa);
+
+err_exit:;
+}
+
+void aq_ring_tx_append_buffs(struct aq_ring_s *self,
+ struct aq_ring_buff_s *buffer,
+ unsigned int buffers)
+{
+ if (likely(self->sw_tail + buffers < self->size))
+ memcpy(&self->buff_ring[self->sw_tail], buffer,
+ sizeof(buffer[0]) * buffers);
+ else {
+ unsigned int first_part = self->size - self->sw_tail;
+ unsigned int second_part = buffers - first_part;
+
+ memcpy(&self->buff_ring[self->sw_tail], buffer,
+ sizeof(buffer[0]) * first_part);
+
+ memcpy(&self->buff_ring[0], &buffer[first_part],
+ sizeof(buffer[0]) * second_part);
+ }
+}
+
+int aq_ring_tx_clean(struct aq_ring_s *self)
+{
+ struct device *dev = aq_nic_get_dev(self->aq_nic);
+ struct net_device *ndev = aq_nic_get_ndev(self->aq_nic);
+
+ for (; self->sw_head != self->hw_head;
+ self->sw_head = aq_ring_next_dx(self, self->sw_head)) {
+ struct aq_ring_buff_s *buff = &self->buff_ring[self->sw_head];
+
+ ++self->stats.tx_packets;
+ ++ndev->stats.tx_packets;
+ ndev->stats.tx_bytes += buff->len;
+
+ if (likely(buff->is_mapped)) {
+ if (unlikely(buff->is_sop))
+ dma_unmap_single(dev, buff->pa, buff->len,
+ DMA_TO_DEVICE);
+ else
+ dma_unmap_page(dev, buff->pa, buff->len,
+ DMA_TO_DEVICE);
+ }
+
+ if (unlikely(buff->is_eop))
+ dev_kfree_skb_any(buff->skb);
+ }
+
+ if (aq_ring_avail_dx(self) > AQ_CFG_SKB_FRAGS_MAX)
+ aq_nic_ndev_queue_start(self->aq_nic, self->idx);
+
+ return 0;
+}
+
+static inline unsigned int aq_ring_dx_in_range(unsigned int h, unsigned int i,
+ unsigned int t)
+{
+ return (h < t) ? ((h < i) && (i < t)) : ((h < i) || (i < t));
+}
+
+int aq_ring_rx_clean(struct aq_ring_s *self, int *work_done, int budget)
+{
+ struct net_device *ndev = aq_nic_get_ndev(self->aq_nic);
+ int err = 0;
+ bool is_rsc_completed = true;
+
+ for (; (self->sw_head != self->hw_head) && budget;
+ self->sw_head = aq_ring_next_dx(self, self->sw_head),
+ --budget, ++(*work_done)) {
+ struct aq_ring_buff_s *buff = &self->buff_ring[self->sw_head];
+ struct sk_buff *skb = NULL;
+ unsigned int next_ = 0U;
+ unsigned int i = 0U;
+ struct aq_ring_buff_s *buff_ = NULL;
+
+ if (buff->is_error) {
+ __free_pages(buff->page, 0);
+ continue;
+ }
+
+ if (buff->is_cleaned)
+ continue;
+
+ ++self->stats.rx_packets;
+ ++ndev->stats.rx_packets;
+ ndev->stats.rx_bytes += buff->len;
+
+ if (!buff->is_eop) {
+ for (next_ = buff->next,
+ buff_ = &self->buff_ring[next_]; true;
+ next_ = buff_->next,
+ buff_ = &self->buff_ring[next_]) {
+ if (unlikely(!aq_ring_dx_in_range(self->sw_head,
+ next_,
+ self->hw_head))) {
+ is_rsc_completed = false;
+ break;
+ }
+
+ if (buff_->is_eop)
+ break;
+ }
+
+ if (!(is_rsc_completed)) {
+ err = 0;
+ goto err_exit;
+ }
+ }
+
+ skb = netdev_alloc_skb(ndev, ETH_HLEN + AQ_CFG_IP_ALIGN);
+
+ skb_reserve(skb, AQ_CFG_IP_ALIGN);
+ skb_put(skb, ETH_HLEN);
+ memcpy(skb->data, page_address(buff->page), ETH_HLEN);
+
+ skb_add_rx_frag(skb, 0, buff->page, ETH_HLEN,
+ buff->len - ETH_HLEN,
+ SKB_TRUESIZE(buff->len - ETH_HLEN));
+
+ if (!buff->is_eop) {
+ for (i = 1U, next_ = buff->next,
+ buff_ = &self->buff_ring[next_]; true;
+ next_ = buff_->next,
+ buff_ = &self->buff_ring[next_], ++i) {
+ skb_add_rx_frag(skb, i, buff_->page, 0,
+ buff_->len,
+ SKB_TRUESIZE(buff_->len));
+
+ buff_->is_cleaned = 1;
+
+ if (buff_->is_eop)
+ break;
+ }
+ }
+
+ skb->dev = ndev;
+
+ skb->protocol = eth_type_trans(skb, ndev);
+
+ if (unlikely(buff->is_cso_err)) {
+ __skb_mark_checksum_bad(skb);
+ ++self->stats.rx_errors;
+ } else {
+ if (buff->is_ip_cso) {
+ __skb_incr_checksum_unnecessary(skb);
+ if (buff->is_udp_cso || buff->is_tcp_cso)
+ __skb_incr_checksum_unnecessary(skb);
+ } else {
+ skb->ip_summed = CHECKSUM_NONE;
+ }
+ }
+
+ skb->hash = buff->rss_hash;
+ skb->l4_hash = buff->is_hash_l4;
+
+ skb_set_hash(skb, buff->rss_hash,
+ buff->is_hash_l4 ? PKT_HASH_TYPE_L4 :
+ PKT_HASH_TYPE_NONE);
+ skb_record_rx_queue(skb, self->idx);
+
+ netif_receive_skb(skb);
+ }
+
+err_exit:
+ return err;
+}
+
+int aq_ring_tx_drop(struct aq_ring_s *self)
+{
+ for (; self->sw_head != self->sw_tail;
+ self->sw_head = aq_ring_next_dx(self, self->sw_head)) {
+ struct aq_ring_buff_s *buff = &self->buff_ring[self->sw_head];
+ struct device *ndev = aq_nic_get_dev(self->aq_nic);
+
+ if (likely(buff->is_mapped)) {
+ if (unlikely(buff->is_sop))
+ dma_unmap_single(ndev, buff->pa, buff->len,
+ DMA_TO_DEVICE);
+ else
+ dma_unmap_page(ndev, buff->pa, buff->len,
+ DMA_TO_DEVICE);
+ }
+
+ if (unlikely(buff->is_eop))
+ dev_kfree_skb_any(buff->skb);
+ }
+
+ return 0;
+}
+
+int aq_ring_rx_drop(struct aq_ring_s *self)
+{
+ for (; self->sw_head != self->sw_tail;
+ self->sw_head = aq_ring_next_dx(self, self->sw_head)) {
+ struct aq_ring_buff_s *buff = &self->buff_ring[self->sw_head];
+
+ dma_unmap_page(aq_nic_get_dev(self->aq_nic), buff->pa,
+ AQ_CFG_RX_FRAME_MAX, DMA_FROM_DEVICE);
+
+ __free_pages(buff->page, 0);
+ }
+
+ return 0;
+}
+
+int aq_ring_rx_fill(struct aq_ring_s *self)
+{
+ struct aq_ring_buff_s *buff = NULL;
+ int err = 0;
+ int i = 0;
+
+ for (i = aq_ring_avail_dx(self); i--;
+ self->sw_tail = aq_ring_next_dx(self, self->sw_tail)) {
+ buff = &self->buff_ring[self->sw_tail];
+
+ buff->flags = 0U;
+ buff->len = AQ_CFG_RX_FRAME_MAX;
+
+ buff->page = alloc_pages(GFP_ATOMIC | __GFP_COLD |
+ __GFP_COMP, 0);
+ if (!buff->page) {
+ err = -ENOMEM;
+ goto err_exit;
+ }
+
+ buff->pa = dma_map_page(aq_nic_get_dev(self->aq_nic),
+ buff->page, 0,
+ AQ_CFG_RX_FRAME_MAX, DMA_FROM_DEVICE);
+
+ err = dma_mapping_error(aq_nic_get_dev(self->aq_nic), buff->pa);
+ if (err < 0)
+ goto err_exit;
+
+ buff = NULL;
+ }
+ if (err < 0)
+ goto err_exit;
+
+err_exit:
+ if (err < 0)
+ if (buff && buff->page)
+ __free_pages(buff->page, 0);
+
+ return err;
+}
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ring.h b/drivers/net/ethernet/aquantia/atlantic/aq_ring.h
new file mode 100644
index 0000000..6a97f21
--- /dev/null
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_ring.h
@@ -0,0 +1,150 @@
+/*
+ * Aquantia Corporation Network Driver
+ * Copyright (C) 2014-2016 Aquantia Corporation. All rights reserved
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ */
+
+/*
+ * File aq_pci_ring.h: Declaration of functions for Rx/Tx rings.
+ */
+
+#ifndef AQ_RING_H
+#define AQ_RING_H
+
+#include "aq_common.h"
+
+struct page;
+
+/*
+ * TxC SOP DX EOP
+ * +----------+----------+----------+-----------
+ * 8bytes|len l3,l4 | pa | pa | pa
+ * +----------+----------+----------+-----------
+ * 4/8bytes|len pkt |len pkt | | skb
+ * +----------+----------+----------+-----------
+ * 4/8bytes|is_txc |len,flags |len |len,is_eop
+ * +----------+----------+----------+-----------
+ *
+ * This aq_ring_buff_s doesn't have endianness dependency.
+ * It is __packed for chache line optimisations.
+ */
+struct __packed aq_ring_buff_s {
+ union {
+ /* RX */
+ struct {
+ u32 rss_hash;
+ u16 next;
+ u8 is_hash_l4;
+ u8 rsvd1;
+ struct page *page;
+ };
+ /* EOP */
+ struct {
+ dma_addr_t pa_eop;
+ struct sk_buff *skb;
+ };
+ /* DX */
+ struct {
+ dma_addr_t pa;
+ };
+ /* SOP */
+ struct {
+ dma_addr_t pa_sop;
+ u32 len_pkt_sop;
+ };
+ /* TxC */
+ struct {
+ u32 mss;
+ u8 len_l2;
+ u8 len_l3;
+ u8 len_l4;
+ u8 rsvd2;
+ u32 len_pkt;
+ };
+ };
+ union {
+ struct {
+ u32 len:16;
+ u32 is_ip_cso:1;
+ u32 is_udp_cso:1;
+ u32 is_tcp_cso:1;
+ u32 is_cso_err:1;
+ u32 is_sop:1;
+ u32 is_eop:1;
+ u32 is_txc:1;
+ u32 is_mapped:1;
+ u32 is_cleaned:1;
+ u32 is_error:1;
+ u32 rsvd3:6;
+ };
+ u32 flags;
+ };
+};
+
+struct aq_ring_stats_s {
+ u64 rx_packets;
+ u64 tx_packets;
+ u64 lro_packets;
+ u64 jumbo_packets;
+ u64 rx_errors;
+};
+
+struct aq_ring_s {
+ AQ_OBJ_HEADER;
+ struct aq_ring_buff_s *buff_ring;
+ u8 *dx_ring; /* descriptors ring, dma shared mem */
+ struct aq_nic_s *aq_nic;
+ unsigned int idx; /* for HW layer registers operations */
+ unsigned int hw_head;
+ unsigned int sw_head;
+ unsigned int sw_tail;
+ unsigned int size; /* descriptors number */
+ unsigned int dx_size; /* TX or RX descriptor size, */
+ /* stored here for fater math */
+ struct aq_ring_stats_s stats;
+ dma_addr_t dx_ring_pa;
+};
+
+struct aq_ring_param_s {
+ unsigned int vec_idx;
+ unsigned int cpu;
+ cpumask_t affinity_mask;
+};
+
+static inline unsigned int aq_ring_next_dx(struct aq_ring_s *self,
+ unsigned int dx)
+{
+ return (++dx >= self->size) ? 0U : dx;
+}
+
+static inline unsigned int aq_ring_avail_dx(struct aq_ring_s *self)
+{
+ return (((self->sw_tail >= self->sw_head)) ?
+ (self->size - 1) - self->sw_tail + self->sw_head :
+ self->sw_head - self->sw_tail - 1);
+}
+
+struct aq_ring_s *aq_ring_tx_alloc(struct aq_ring_s *self,
+ struct aq_nic_s *aq_nic,
+ unsigned int idx,
+ struct aq_nic_cfg_s *aq_nic_cfg);
+struct aq_ring_s *aq_ring_rx_alloc(struct aq_ring_s *self,
+ struct aq_nic_s *aq_nic,
+ unsigned int idx,
+ struct aq_nic_cfg_s *aq_nic_cfg);
+int aq_ring_init(struct aq_ring_s *self);
+int aq_ring_deinit(struct aq_ring_s *self);
+void aq_ring_free(struct aq_ring_s *self);
+void aq_ring_tx_append_buffs(struct aq_ring_s *ring,
+ struct aq_ring_buff_s *buffer,
+ unsigned int buffers);
+int aq_ring_tx_clean(struct aq_ring_s *self);
+int aq_ring_rx_clean(struct aq_ring_s *self, int *work_done, int budget);
+int aq_ring_tx_drop(struct aq_ring_s *self);
+int aq_ring_rx_drop(struct aq_ring_s *self);
+int aq_ring_rx_fill(struct aq_ring_s *self);
+
+#endif /* AQ_RING_H */
--
2.7.4
^ permalink raw reply related
* [PATCH 10/12] Hardware interface and utility functions
From: David VomLehn @ 2016-12-27 13:17 UTC (permalink / raw)
To: netdev
Cc: Simon Edelhaus, David VomLehn, Dmitrii Tarakanov,
Alexander Loktionov
In-Reply-To: <9936fa643d5f6a8f29b069847d052fcf5dc23513.1482844668.git.vomlehn@texas.net>
Add functions to interface with the hardware and some utility functions.
Signed-off-by: Dmitrii Tarakanov <Dmitrii.Tarakanov@aquantia.com>
Signed-off-by: Alexander Loktionov <Alexander.Loktionov@aquantia.com>
Signed-off-by: David M. VomLehn <vomlehn@texas.net>
---
drivers/net/ethernet/aquantia/atlantic/aq_hw.h | 170 +++++++++++++++++++++
.../net/ethernet/aquantia/atlantic/aq_hw_utils.c | 70 +++++++++
.../net/ethernet/aquantia/atlantic/aq_hw_utils.h | 54 +++++++
3 files changed, 294 insertions(+)
create mode 100644 drivers/net/ethernet/aquantia/atlantic/aq_hw.h
create mode 100644 drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.c
create mode 100644 drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.h
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_hw.h b/drivers/net/ethernet/aquantia/atlantic/aq_hw.h
new file mode 100644
index 0000000..15e35b1
--- /dev/null
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_hw.h
@@ -0,0 +1,170 @@
+/*
+ * Aquantia Corporation Network Driver
+ * Copyright (C) 2014-2016 Aquantia Corporation. All rights reserved
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ */
+
+/*
+ * File aq_hw.h: Declaraion of abstract interface for NIC hardware specific
+ * functions.
+ */
+
+#ifndef AQ_HW_H
+#define AQ_HW_H
+
+#include "aq_common.h"
+
+/* NIC H/W capabilities */
+struct aq_hw_caps_s {
+ u64 hw_features;
+ u64 link_speed_msk;
+ unsigned int hw_priv_flags;
+ u32 rxds;
+ u32 txds;
+ u32 txhwb_alignment;
+ u32 irq_mask;
+ u32 vecs;
+ u32 mtu;
+ u32 mac_regs_count;
+ u8 ports;
+ u8 msix_irqs;
+ u8 tcs;
+ u8 rxd_alignment;
+ u8 rxd_size;
+ u8 txd_alignment;
+ u8 txd_size;
+ u8 tx_rings;
+ u8 rx_rings;
+ bool flow_control;
+ bool is_64_dma;
+};
+
+struct aq_hw_link_status_s {
+ u64 bps;
+};
+
+#define AQ_HW_POWER_STATE_D0 0U
+#define AQ_HW_POWER_STATE_D3 3U
+
+#define AQ_HW_FLAG_STARTED 0x00000004U
+#define AQ_HW_FLAG_STOPPING 0x00000008U
+#define AQ_HW_FLAG_RESETTING 0x00000010U
+#define AQ_HW_FLAG_CLOSING 0x00000020U
+#define AQ_HW_LINK_DOWN 0x04000000U
+#define AQ_HW_FLAG_ERR_UNPLUG 0x40000000U
+#define AQ_HW_FLAG_ERR_HW 0x80000000U
+
+#define AQ_HW_FLAG_ERRORS (AQ_HW_FLAG_ERR_HW | AQ_HW_FLAG_ERR_UNPLUG)
+
+struct aq_hw_s {
+ AQ_OBJ_HEADER;
+ struct aq_nic_cfg_s *aq_nic_cfg;
+ struct aq_pci_func_s *aq_pci_func;
+ void __iomem *mmio;
+ unsigned int not_ff_addr;
+ struct aq_hw_link_status_s aq_link_status;
+};
+
+struct aq_ring_s;
+struct aq_ring_param_s;
+struct aq_nic_cfg_s;
+struct sk_buff;
+
+struct aq_hw_ops {
+ struct aq_hw_s *(*create)(struct aq_pci_func_s *aq_pci_func,
+ unsigned int port, struct aq_hw_ops *ops);
+
+ void (*destroy)(struct aq_hw_s *self);
+
+ int (*get_hw_caps)(struct aq_hw_s *self,
+ struct aq_hw_caps_s *aq_hw_caps);
+
+ int (*hw_ring_tx_xmit)(struct aq_hw_s *self, struct aq_ring_s *aq_ring,
+ unsigned int frags);
+
+ int (*hw_ring_rx_receive)(struct aq_hw_s *self,
+ struct aq_ring_s *aq_ring);
+
+ int (*hw_ring_rx_fill)(struct aq_hw_s *self, struct aq_ring_s *aq_ring,
+ unsigned int sw_tail_old);
+
+ int (*hw_ring_tx_head_update)(struct aq_hw_s *self,
+ struct aq_ring_s *aq_ring);
+
+ int (*hw_get_mac_permanent)(struct aq_hw_s *self, u8 *mac);
+
+ int (*hw_set_mac_address)(struct aq_hw_s *self, u8 *mac_addr);
+
+ int (*hw_get_link_status)(struct aq_hw_s *self,
+ struct aq_hw_link_status_s *link_status);
+
+ int (*hw_set_link_speed)(struct aq_hw_s *self, u32 speed);
+
+ int (*hw_reset)(struct aq_hw_s *self);
+
+ int (*hw_init)(struct aq_hw_s *self, struct aq_nic_cfg_s *aq_nic_cfg,
+ u8 *mac_addr);
+
+ int (*hw_start)(struct aq_hw_s *self);
+
+ int (*hw_stop)(struct aq_hw_s *self);
+
+ int (*hw_ring_tx_init)(struct aq_hw_s *self, struct aq_ring_s *aq_ring,
+ struct aq_ring_param_s *aq_ring_param);
+
+ int (*hw_ring_tx_start)(struct aq_hw_s *self,
+ struct aq_ring_s *aq_ring);
+
+ int (*hw_ring_tx_stop)(struct aq_hw_s *self,
+ struct aq_ring_s *aq_ring);
+
+ int (*hw_ring_rx_init)(struct aq_hw_s *self,
+ struct aq_ring_s *aq_ring,
+ struct aq_ring_param_s *aq_ring_param);
+
+ int (*hw_ring_rx_start)(struct aq_hw_s *self,
+ struct aq_ring_s *aq_ring);
+
+ int (*hw_ring_rx_stop)(struct aq_hw_s *self,
+ struct aq_ring_s *aq_ring);
+
+ int (*hw_irq_enable)(struct aq_hw_s *self, u64 mask);
+
+ int (*hw_irq_disable)(struct aq_hw_s *self, u64 mask);
+
+ int (*hw_irq_read)(struct aq_hw_s *self, u64 *mask);
+
+ int (*hw_packet_filter_set)(struct aq_hw_s *self,
+ unsigned int packet_filter);
+
+ int (*hw_multicast_list_set)(struct aq_hw_s *self,
+ u8 ar_mac[AQ_CFG_MULTICAST_ADDRESS_MAX]
+ [ETH_ALEN],
+ u32 count);
+
+ int (*hw_interrupt_moderation_set)(struct aq_hw_s *self,
+ bool itr_enabled);
+
+ int (*hw_rss_set)(struct aq_hw_s *self,
+ struct aq_receive_scale_parameters *rss_params);
+
+ int (*hw_rss_hash_set)(struct aq_hw_s *self,
+ struct aq_receive_scale_parameters *rss_params);
+
+ int (*hw_get_regs)(struct aq_hw_s *self,
+ struct aq_hw_caps_s *aq_hw_caps, u32 *regs_buff);
+
+ int (*hw_get_hw_stats)(struct aq_hw_s *self, u64 *data,
+ unsigned int *p_count);
+
+ int (*hw_get_fw_version)(struct aq_hw_s *self, u32 *fw_version);
+
+ int (*hw_deinit)(struct aq_hw_s *self);
+
+ int (*hw_set_power)(struct aq_hw_s *self, unsigned int power_state);
+};
+
+#endif /* AQ_HW_H */
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.c b/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.c
new file mode 100644
index 0000000..d340f95
--- /dev/null
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.c
@@ -0,0 +1,70 @@
+/*
+ * Aquantia Corporation Network Driver
+ * Copyright (C) 2014-2016 Aquantia Corporation. All rights reserved
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ */
+
+/*
+ * File aq_hw_utils.c: Definitions of helper functions used across
+ * hardware layer.
+ */
+
+#include "aq_hw_utils.h"
+#include "aq_hw.h"
+
+void aq_hw_utils_write_reg_bit(struct aq_hw_s *aq_hw, u32 addr, u32 msk,
+ u32 shft, u32 val)
+{
+ if (msk ^ ~0) {
+ u32 reg_old, reg_new;
+
+ reg_old = aq_hw_read_reg(aq_hw, addr);
+ reg_new = (reg_old & (~msk)) | (val << shft);
+
+ if (reg_old != reg_new)
+ aq_hw_write_reg(aq_hw, addr, reg_new);
+ } else {
+ aq_hw_write_reg(aq_hw, addr, val);
+ }
+}
+
+u32 aq_hw_utils_read_reg_bit(struct aq_hw_s *aq_hw, u32 addr, u32 msk,
+ u32 shift)
+{
+ return ((aq_hw_read_reg(aq_hw, addr) & msk) >> shift);
+}
+
+u32 aq_hw_read_reg(struct aq_hw_s *hw, u32 reg)
+{
+ u32 value = readl(hw->mmio + reg);
+
+ if ((~0U) == value && (~0U) == readl(hw->mmio + hw->not_ff_addr))
+ AQ_OBJ_SET(hw, AQ_HW_FLAG_ERR_UNPLUG);
+
+ return value;
+}
+
+inline void aq_hw_write_reg(struct aq_hw_s *hw, u32 reg, u32 value)
+{
+ writel(value, hw->mmio + reg);
+}
+
+int aq_hw_err_from_flags(struct aq_hw_s *hw)
+{
+ int err = 0;
+
+ if (AQ_OBJ_TST(hw, AQ_HW_FLAG_ERR_UNPLUG)) {
+ err = -ENXIO;
+ goto err_exit;
+ }
+ if (AQ_OBJ_TST(hw, AQ_HW_FLAG_ERR_HW)) {
+ err = -EIO;
+ goto err_exit;
+ }
+
+err_exit:
+ return err;
+}
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.h b/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.h
new file mode 100644
index 0000000..7a0eaff
--- /dev/null
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.h
@@ -0,0 +1,54 @@
+/*
+ * Aquantia Corporation Network Driver
+ * Copyright (C) 2014-2016 Aquantia Corporation. All rights reserved
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ */
+
+/*
+ * File aq_hw_utils.h: Declaration of helper functions used across hardware
+ * layer.
+ */
+
+#ifndef AQ_HW_UTILS_H
+#define AQ_HW_UTILS_H
+
+#include "aq_common.h"
+
+#ifndef MBIT
+#define MBIT ((u64)1000000U)
+#define GBIT ((u64)1000000000U)
+#endif
+
+#ifndef HIDWORD
+#define LODWORD(_qw) ((u32)(_qw))
+#define HIDWORD(_qw) ((u32)(((_qw) >> 32) & 0xffffffff))
+#endif
+
+#define AQ_HW_SLEEP(_US_) mdelay(_US_)
+
+#define AQ_HW_WAIT_FOR(_B_, _US_, _N_) \
+do { \
+ unsigned int AQ_HW_WAIT_FOR_i; \
+ for (AQ_HW_WAIT_FOR_i = _N_; (!(_B_)) && (AQ_HW_WAIT_FOR_i);\
+ --AQ_HW_WAIT_FOR_i) {\
+ udelay(_US_); \
+ } \
+ if (!AQ_HW_WAIT_FOR_i) {\
+ err = ETIME; \
+ } \
+} while (0)
+
+struct aq_hw_s;
+
+void aq_hw_utils_write_reg_bit(struct aq_hw_s *aq_hw, u32 addr, u32 msk,
+ u32 shft, u32 val);
+u32 aq_hw_utils_read_reg_bit(struct aq_hw_s *aq_hw, u32 addr, u32 msk,
+ u32 shift);
+u32 aq_hw_read_reg(struct aq_hw_s *hw, u32 reg);
+inline void aq_hw_write_reg(struct aq_hw_s *hw, u32 reg, u32 value);
+int aq_hw_err_from_flags(struct aq_hw_s *hw);
+
+#endif /* AQ_HW_UTILS_H */
--
2.7.4
^ permalink raw reply related
* [PATCH 11/12] Ethtool support
From: David VomLehn @ 2016-12-27 13:17 UTC (permalink / raw)
To: netdev
Cc: Simon Edelhaus, David VomLehn, Dmitrii Tarakanov,
Alexander Loktionov
In-Reply-To: <7ef8eca5f4c5cc3d28992d820a7a1d9e92590bb2.1482844668.git.vomlehn@texas.net>
Add the driver interfaces required for support by the ethtool utility.
Signed-off-by: Dmitrii Tarakanov <Dmitrii.Tarakanov@aquantia.com>
Signed-off-by: Alexander Loktionov <Alexander.Loktionov@aquantia.com>
Signed-off-by: David M. VomLehn <vomlehn@texas.net>
---
.../net/ethernet/aquantia/atlantic/aq_ethtool.c | 254 +++++++++++++++++++++
.../net/ethernet/aquantia/atlantic/aq_ethtool.h | 21 ++
2 files changed, 275 insertions(+)
create mode 100644 drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c
create mode 100644 drivers/net/ethernet/aquantia/atlantic/aq_ethtool.h
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c b/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c
new file mode 100644
index 0000000..ab50aa1
--- /dev/null
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c
@@ -0,0 +1,254 @@
+/*
+ * Aquantia Corporation Network Driver
+ * Copyright (C) 2014-2016 Aquantia Corporation. All rights reserved
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ */
+
+/*
+ * File aq_ethtool.c: Definition of ethertool related functions.
+ */
+
+#include "aq_ethtool.h"
+#include "aq_nic.h"
+
+static void aq_ethtool_get_regs(struct net_device *ndev,
+ struct ethtool_regs *regs, void *p)
+{
+ struct aq_nic_s *aq_nic = (struct aq_nic_s *)netdev_priv(ndev);
+ u32 regs_count = aq_nic_get_regs_count(aq_nic);
+
+ memset(p, 0, regs_count * sizeof(u32));
+ aq_nic_get_regs(aq_nic, regs, p);
+}
+
+static int aq_ethtool_get_regs_len(struct net_device *ndev)
+{
+ struct aq_nic_s *aq_nic = (struct aq_nic_s *)netdev_priv(ndev);
+ u32 regs_count = aq_nic_get_regs_count(aq_nic);
+
+ return regs_count * sizeof(u32);
+}
+
+static u32 aq_ethtool_get_link(struct net_device *ndev)
+{
+ struct aq_nic_s *aq_nic = (struct aq_nic_s *)netdev_priv(ndev);
+ u32 ret = 0U;
+
+ ret = aq_nic_get_link_speed(aq_nic) ? 1U : 0U;
+ return ret;
+}
+
+static int aq_ethtool_get_settings(struct net_device *ndev,
+ struct ethtool_cmd *cmd)
+{
+ struct aq_nic_s *aq_nic = (struct aq_nic_s *)netdev_priv(ndev);
+
+ cmd->port = PORT_TP;
+ cmd->transceiver = XCVR_EXTERNAL;
+
+ ethtool_cmd_speed_set(cmd, netif_carrier_ok(ndev) ?
+ aq_nic_get_link_speed(aq_nic) : 0U);
+
+ cmd->duplex = DUPLEX_FULL;
+ aq_nic_get_link_settings(aq_nic, cmd);
+ return 0;
+}
+
+static int aq_ethtool_set_settings(struct net_device *ndev,
+ struct ethtool_cmd *cmd)
+{
+ struct aq_nic_s *aq_nic = (struct aq_nic_s *)netdev_priv(ndev);
+
+ return aq_nic_set_link_settings(aq_nic, cmd);
+}
+
+static const char aq_ethtool_stat_names[][ETH_GSTRING_LEN] = {
+ "InPackets",
+ "InUCast",
+ "InMCast",
+ "InBCast",
+ "InErrors",
+ "OutPackets",
+ "OutUCast",
+ "OutMCast",
+ "OutBCast",
+ "InUCastOctects",
+ "OutUCastOctects",
+ "InMCastOctects",
+ "OutMCastOctects",
+ "InBCastOctects",
+ "OutBCastOctects",
+ "InOctects",
+ "OutOctects",
+ "InPacketsDma",
+ "OutPacketsDma",
+ "InOctetsDma",
+ "OutOctetsDma",
+ "InDroppedDma",
+ "Queue[0] InPackets",
+ "Queue[0] OutPackets",
+ "Queue[0] InJumboPackets",
+ "Queue[0] InLroPackets",
+ "Queue[0] InErrors",
+#if 1 < AQ_CFG_VECS_DEF
+ "Queue[1] InPackets",
+ "Queue[1] OutPackets",
+ "Queue[1] InJumboPackets",
+ "Queue[1] InLroPackets",
+ "Queue[1] InErrors",
+#endif
+#if 2 < AQ_CFG_VECS_DEF
+ "Queue[2] InPackets",
+ "Queue[2] OutPackets",
+ "Queue[2] InJumboPackets",
+ "Queue[2] InLroPackets",
+ "Queue[2] InErrors",
+#endif
+#if 3 < AQ_CFG_VECS_DEF
+ "Queue[3] InPackets",
+ "Queue[3] OutPackets",
+ "Queue[3] InJumboPackets",
+ "Queue[3] InLroPackets",
+ "Queue[3] InErrors",
+#endif
+#if 4 < AQ_CFG_VECS_DEF
+ "Queue[4] InPackets",
+ "Queue[4] OutPackets",
+ "Queue[4] InJumboPackets",
+ "Queue[4] InLroPackets",
+ "Queue[4] InErrors",
+#endif
+#if 5 < AQ_CFG_VECS_DEF
+ "Queue[5] InPackets",
+ "Queue[5] OutPackets",
+ "Queue[5] InJumboPackets",
+ "Queue[5] InLroPackets",
+ "Queue[5] InErrors",
+#endif
+#if 6 < AQ_CFG_VECS_DEF
+ "Queue[6] InPackets",
+ "Queue[6] OutPackets",
+ "Queue[6] InJumboPackets",
+ "Queue[6] InLroPackets",
+ "Queue[6] InErrors",
+#endif
+#if 7 < AQ_CFG_VECS_DEF
+ "Queue[7] InPackets",
+ "Queue[7] OutPackets",
+ "Queue[7] InJumboPackets",
+ "Queue[7] InLroPackets",
+ "Queue[7] InErrors",
+#endif
+};
+
+static void aq_ethtool_stats(struct net_device *ndev,
+ struct ethtool_stats *stats, u64 *data)
+{
+ struct aq_nic_s *aq_nic = (struct aq_nic_s *)netdev_priv(ndev);
+
+ memset(data, 0, ARRAY_SIZE(aq_ethtool_stat_names) * sizeof(u64));
+ aq_nic_get_stats(aq_nic, data);
+}
+
+static void aq_ethtool_get_drvinfo(struct net_device *ndev,
+ struct ethtool_drvinfo *drvinfo)
+{
+ struct aq_nic_s *aq_nic = (struct aq_nic_s *)netdev_priv(ndev);
+ u32 firmware_version = aq_nic_get_fw_version(aq_nic);
+ u32 regs_count = aq_nic_get_regs_count(aq_nic);
+
+ strlcat(drvinfo->driver, AQ_CFG_DRV_NAME, sizeof(drvinfo->driver));
+ strlcat(drvinfo->version, AQ_CFG_DRV_VERSION, sizeof(drvinfo->version));
+
+ snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version),
+ "%u.%u.%u", firmware_version >> 24,
+ (firmware_version >> 16) & 0xFFU, firmware_version & 0xFFFFU);
+
+ drvinfo->n_stats = ARRAY_SIZE(aq_ethtool_stat_names);
+ drvinfo->testinfo_len = 0;
+ drvinfo->regdump_len = regs_count;
+ drvinfo->eedump_len = 0;
+}
+
+static void aq_ethtool_get_strings(struct net_device *ndev,
+ u32 stringset, u8 *data)
+{
+ memcpy(data, *aq_ethtool_stat_names, sizeof(aq_ethtool_stat_names));
+}
+
+static int aq_ethtool_get_sset_count(struct net_device *ndev, int stringset)
+{
+ return ARRAY_SIZE(aq_ethtool_stat_names);
+}
+
+static u32 aq_ethtool_get_rss_indir_size(struct net_device *ndev)
+{
+ return AQ_CFG_RSS_INDIRECTION_TABLE_MAX;
+}
+
+static u32 aq_ethtool_get_rss_key_size(struct net_device *ndev)
+{
+ struct aq_nic_s *aq_nic = (struct aq_nic_s *)netdev_priv(ndev);
+ struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(aq_nic);
+
+ return sizeof(cfg->aq_rss.hash_secret_key);
+}
+
+static int aq_ethtool_get_rss(struct net_device *ndev, u32 *indir, u8 *key,
+ u8 *hfunc)
+{
+ struct aq_nic_s *aq_nic = (struct aq_nic_s *)netdev_priv(ndev);
+ struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(aq_nic);
+ unsigned int i = 0U;
+
+ if (hfunc)
+ *hfunc = ETH_RSS_HASH_TOP; /* Toeplitz */
+ if (indir) {
+ for (i = 0; i < AQ_CFG_RSS_INDIRECTION_TABLE_MAX; i++)
+ indir[i] = cfg->aq_rss.indirection_table[i];
+ }
+ if (key)
+ memcpy(key, cfg->aq_rss.hash_secret_key,
+ sizeof(cfg->aq_rss.hash_secret_key));
+ return 0;
+}
+
+static int aq_ethtool_get_rxnfc(struct net_device *ndev,
+ struct ethtool_rxnfc *cmd, u32 *rule_locs)
+
+{
+ struct aq_nic_s *aq_nic = (struct aq_nic_s *)netdev_priv(ndev);
+ struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(aq_nic);
+ int err = -EOPNOTSUPP;
+
+ switch (cmd->cmd) {
+ case ETHTOOL_GRXRINGS:
+ cmd->data = cfg->vecs;
+ err = 0;
+ break;
+
+ default:
+ break;
+ }
+
+ return err;
+}
+
+const struct ethtool_ops aq_ethtool_ops = {
+ .get_link = aq_ethtool_get_link,
+ .get_regs_len = aq_ethtool_get_regs_len,
+ .get_regs = aq_ethtool_get_regs,
+ .get_settings = aq_ethtool_get_settings,
+ .set_settings = aq_ethtool_set_settings,
+ .get_drvinfo = aq_ethtool_get_drvinfo,
+ .get_strings = aq_ethtool_get_strings,
+ .get_rxfh_indir_size = aq_ethtool_get_rss_indir_size,
+ .get_rxfh_key_size = aq_ethtool_get_rss_key_size,
+ .get_rxfh = aq_ethtool_get_rss,
+ .get_rxnfc = aq_ethtool_get_rxnfc,
+ .get_sset_count = aq_ethtool_get_sset_count,
+ .get_ethtool_stats = aq_ethtool_stats
+};
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.h b/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.h
new file mode 100644
index 0000000..e125390
--- /dev/null
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.h
@@ -0,0 +1,21 @@
+/*
+ * Aquantia Corporation Network Driver
+ * Copyright (C) 2014-2016 Aquantia Corporation. All rights reserved
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ */
+
+/*
+ * File aq_ethtool.h: Declaration of ethertool related functions.
+ */
+
+#ifndef AQ_ETHTOOL_H
+#define AQ_ETHTOOL_H
+
+#include "aq_common.h"
+
+extern const struct ethtool_ops aq_ethtool_ops;
+
+#endif /* AQ_ETHTOOL_H */
--
2.7.4
^ permalink raw reply related
* [PATCH 08/12] PCI operations
From: David VomLehn @ 2016-12-27 13:17 UTC (permalink / raw)
To: netdev
Cc: Simon Edelhaus, David VomLehn, Dmitrii Tarakanov,
Alexander Loktionov
In-Reply-To: <61665299e584052d30bd1d623ebd4b138dd90694.1482844668.git.vomlehn@texas.net>
Add functions that handle the PCI bus interface.
Signed-off-by: Dmitrii Tarakanov <Dmitrii.Tarakanov@aquantia.com>
Signed-off-by: Alexander Loktionov <Alexander.Loktionov@aquantia.com>
Signed-off-by: David M. VomLehn <vomlehn@texas.net>
---
.../net/ethernet/aquantia/atlantic/aq_pci_func.c | 356 +++++++++++++++++++++
.../net/ethernet/aquantia/atlantic/aq_pci_func.h | 36 +++
2 files changed, 392 insertions(+)
create mode 100644 drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c
create mode 100644 drivers/net/ethernet/aquantia/atlantic/aq_pci_func.h
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c b/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c
new file mode 100644
index 0000000..bdd15c8
--- /dev/null
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c
@@ -0,0 +1,356 @@
+/*
+ * Aquantia Corporation Network Driver
+ * Copyright (C) 2014-2016 Aquantia Corporation. All rights reserved
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ */
+
+/*
+ * File aq_pci_func.c: Definition of PCI functions.
+ */
+
+#include "aq_pci_func.h"
+#include "aq_nic.h"
+#include "aq_vec.h"
+#include "aq_hw.h"
+
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+
+struct aq_pci_func_s {
+ struct pci_dev *pdev;
+ struct aq_nic_s *port[AQ_CFG_PCI_FUNC_PORTS];
+ void __iomem *mmio;
+ void *aq_vec[AQ_CFG_PCI_FUNC_MSIX_IRQS];
+ resource_size_t mmio_pa;
+ unsigned int msix_entry_mask;
+ unsigned int irq_type;
+ unsigned int ports;
+ bool is_pci_enabled;
+ bool is_regions;
+ bool is_pci_using_dac;
+ struct aq_hw_caps_s aq_hw_caps;
+ struct msix_entry msix_entry[AQ_CFG_PCI_FUNC_MSIX_IRQS];
+};
+
+struct aq_pci_func_s *aq_pci_func_alloc(struct aq_hw_ops *aq_hw_ops,
+ struct pci_dev *pdev,
+ const struct net_device_ops *ndev_ops,
+ const struct ethtool_ops *eth_ops)
+{
+ struct aq_pci_func_s *self = NULL;
+ int err = 0;
+ unsigned int port = 0U;
+
+ if (!aq_hw_ops) {
+ err = -EFAULT;
+ goto err_exit;
+ }
+ self = kzalloc(sizeof(*self), GFP_KERNEL);
+ if (!self) {
+ err = -ENOMEM;
+ goto err_exit;
+ }
+
+ pci_set_drvdata(pdev, self);
+ self->pdev = pdev;
+
+ err = aq_hw_ops->get_hw_caps(NULL, &self->aq_hw_caps);
+ if (err < 0)
+ goto err_exit;
+
+ self->ports = self->aq_hw_caps.ports;
+
+ for (port = 0; port < self->ports; ++port) {
+ struct aq_nic_s *aq_nic = aq_nic_alloc_cold(ndev_ops, eth_ops,
+ &pdev->dev, self,
+ port, aq_hw_ops);
+
+ if (!aq_nic) {
+ err = -ENOMEM;
+ goto err_exit;
+ }
+ self->port[port] = aq_nic;
+ }
+
+err_exit:
+ if (err < 0) {
+ if (self)
+ aq_pci_func_free(self);
+ self = NULL;
+ }
+
+ (void)err;
+ return self;
+}
+
+int aq_pci_func_init(struct aq_pci_func_s *self)
+{
+ int err = 0;
+ unsigned int bar = 0U;
+ unsigned int port = 0U;
+ unsigned int i = 0U;
+
+ err = pci_enable_device(self->pdev);
+ if (err < 0)
+ goto err_exit;
+
+ self->is_pci_enabled = true;
+
+ err = pci_set_dma_mask(self->pdev, DMA_BIT_MASK(64));
+ if (!err) {
+ err = pci_set_consistent_dma_mask(self->pdev, DMA_BIT_MASK(64));
+ self->is_pci_using_dac = 1;
+ }
+ if (err) {
+ err = pci_set_dma_mask(self->pdev, DMA_BIT_MASK(32));
+ if (!err)
+ err = pci_set_consistent_dma_mask(self->pdev,
+ DMA_BIT_MASK(32));
+ self->is_pci_using_dac = 0;
+ }
+ if (err != 0) {
+ err = -ENOSR;
+ goto err_exit;
+ }
+
+ err = pci_request_regions(self->pdev, AQ_CFG_DRV_NAME "_mmio");
+ if (err < 0)
+ goto err_exit;
+
+ self->is_regions = true;
+
+ pci_set_master(self->pdev);
+
+ for (bar = 0; bar < 4; ++bar) {
+ if (IORESOURCE_MEM & pci_resource_flags(self->pdev, bar)) {
+ resource_size_t reg_sz;
+
+ self->mmio_pa = pci_resource_start(self->pdev, bar);
+ if (self->mmio_pa == 0U) {
+ err = -EIO;
+ goto err_exit;
+ }
+
+ reg_sz = pci_resource_len(self->pdev, bar);
+ if ((reg_sz <= 24 /*ATL_REGS_SIZE*/)) {
+ err = -EIO;
+ goto err_exit;
+ }
+
+ self->mmio = ioremap_nocache(self->mmio_pa, reg_sz);
+ if (!self->mmio) {
+ err = -EIO;
+ goto err_exit;
+ }
+ break;
+ }
+ }
+
+ if (err < 0)
+ goto err_exit;
+ for (i = 0; i < self->aq_hw_caps.msix_irqs; i++)
+ self->msix_entry[i].entry = i;
+
+ /*enable interrupts */
+#if AQ_CFG_FORCE_LEGACY_INT
+ self->irq_type = AQ_IRQ_LEGACY;
+#else
+ err = pci_enable_msix(self->pdev, self->msix_entry,
+ self->aq_hw_caps.msix_irqs);
+
+ if (err >= 0) {
+ self->irq_type = AQ_IRQ_MSIX;
+ } else {
+ err = pci_enable_msi(self->pdev);
+
+ if (err >= 0) {
+ self->irq_type = AQ_IRQ_MSI;
+ } else {
+ self->irq_type = AQ_IRQ_LEGACY;
+ err = 0;
+ }
+ }
+#endif
+
+ /* net device init */
+ for (port = 0; port < self->ports; ++port) {
+ if (!self->port[port])
+ continue;
+
+ err = aq_nic_cfg_start(self->port[port]);
+ if (err < 0)
+ goto err_exit;
+
+ err = aq_nic_ndev_init(self->port[port]);
+ if (err < 0)
+ goto err_exit;
+
+ err = aq_nic_ndev_register(self->port[port]);
+ if (err < 0)
+ goto err_exit;
+ }
+
+err_exit:
+ if (err < 0)
+ err = aq_pci_func_deinit(self);
+ return err;
+}
+
+int aq_pci_func_alloc_irq(struct aq_pci_func_s *self, unsigned int i,
+ char *name, void *aq_vec, cpumask_t *affinity_mask)
+{
+ int err = 0;
+
+ switch (self->irq_type) {
+ case AQ_IRQ_MSIX:
+ err = request_irq(self->msix_entry[i].vector, aq_vec_isr, 0,
+ name, aq_vec);
+ break;
+
+ case AQ_IRQ_MSI:
+ err = request_irq(self->pdev->irq, aq_vec_isr, 0, name, aq_vec);
+ break;
+
+ case AQ_IRQ_LEGACY:
+ err = request_irq(self->pdev->irq, aq_vec_isr_legacy,
+ IRQF_SHARED, name, aq_vec);
+ break;
+
+ default:
+ err = -EFAULT;
+ break;
+ }
+
+ if (err >= 0) {
+ self->msix_entry_mask |= (1 << i);
+ self->aq_vec[i] = aq_vec;
+
+ if (self->irq_type == AQ_IRQ_MSIX)
+ irq_set_affinity_hint(self->msix_entry[i].vector,
+ affinity_mask);
+ }
+
+ return err;
+}
+
+void aq_pci_func_free_irqs(struct aq_pci_func_s *self)
+{
+ unsigned int i = 0U;
+
+ for (i = 32U; i--;) {
+ if (!((1U << i) & self->msix_entry_mask))
+ continue;
+
+ switch (self->irq_type) {
+ case AQ_IRQ_MSIX:
+ irq_set_affinity_hint(self->msix_entry[i].vector, NULL);
+ free_irq(self->msix_entry[i].vector, self->aq_vec[i]);
+ break;
+
+ case AQ_IRQ_MSI:
+ free_irq(self->pdev->irq, self->aq_vec[i]);
+ break;
+
+ case AQ_IRQ_LEGACY:
+ free_irq(self->pdev->irq, self->aq_vec[i]);
+ break;
+
+ default:
+ break;
+ }
+
+ self->msix_entry_mask &= ~(1U << i);
+ }
+}
+
+void __iomem *aq_pci_func_get_mmio(struct aq_pci_func_s *self)
+{
+ return self->mmio;
+}
+
+unsigned int aq_pci_func_get_irq_type(struct aq_pci_func_s *self)
+{
+ return self->irq_type;
+}
+
+int aq_pci_func_deinit(struct aq_pci_func_s *self)
+{
+ int err = 0;
+
+ if (!self) {
+ err = -EFAULT;
+ goto err_exit;
+ }
+ aq_pci_func_free_irqs(self);
+
+ switch (self->irq_type) {
+ case AQ_IRQ_MSI:
+ pci_disable_msi(self->pdev);
+ break;
+
+ case AQ_IRQ_MSIX:
+ pci_disable_msix(self->pdev);
+ break;
+
+ case AQ_IRQ_LEGACY:
+ break;
+
+ default:
+ break;
+ }
+
+ if (self->is_regions)
+ pci_release_regions(self->pdev);
+
+ if (self->is_pci_enabled)
+ pci_disable_device(self->pdev);
+
+err_exit:
+ return err;
+}
+
+void aq_pci_func_free(struct aq_pci_func_s *self)
+{
+ int err = 0;
+ unsigned int port = 0U;
+
+ if (!self) {
+ err = -EFAULT;
+ goto err_exit;
+ }
+ for (port = 0; port < self->ports; ++port) {
+ if (!self->port[port])
+ continue;
+
+ aq_nic_ndev_free(self->port[port]);
+ }
+
+ kfree(self);
+
+err_exit:
+ (void)err;
+}
+
+int aq_pci_func_change_pm_state(struct aq_pci_func_s *self,
+ pm_message_t *pm_msg)
+{
+ int err = 0;
+ unsigned int port = 0U;
+
+ if (!self) {
+ err = -EFAULT;
+ goto err_exit;
+ }
+ for (port = 0; port < self->ports; ++port) {
+ if (!self->port[port])
+ continue;
+
+ err = aq_nic_change_pm_state(self->port[port], pm_msg);
+ }
+
+err_exit:
+ return err;
+}
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.h b/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.h
new file mode 100644
index 0000000..7b77fac
--- /dev/null
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.h
@@ -0,0 +1,36 @@
+/*
+ * Aquantia Corporation Network Driver
+ * Copyright (C) 2014-2016 Aquantia Corporation. All rights reserved
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ */
+
+/*
+ * File aq_pci_func.h: Declaration of PCI functions.
+ */
+
+#ifndef AQ_PCI_FUNC_H
+#define AQ_PCI_FUNC_H
+
+#include "aq_common.h"
+
+struct aq_pci_func_s *aq_pci_func_alloc(struct aq_hw_ops *hw_ops,
+ struct pci_dev *pdev,
+ const struct net_device_ops *ndev_ops,
+ const struct ethtool_ops *eth_ops);
+int aq_pci_func_init(struct aq_pci_func_s *self);
+int aq_pci_func_alloc_irq(struct aq_pci_func_s *self, unsigned int i,
+ char *name, void *aq_vec,
+ cpumask_t *affinity_mask);
+void aq_pci_func_free_irqs(struct aq_pci_func_s *self);
+int aq_pci_func_start(struct aq_pci_func_s *self);
+void __iomem *aq_pci_func_get_mmio(struct aq_pci_func_s *self);
+unsigned int aq_pci_func_get_irq_type(struct aq_pci_func_s *self);
+int aq_pci_func_deinit(struct aq_pci_func_s *self);
+void aq_pci_func_free(struct aq_pci_func_s *self);
+int aq_pci_func_change_pm_state(struct aq_pci_func_s *self,
+ pm_message_t *pm_msg);
+
+#endif /* AQ_PCI_FUNC_H */
--
2.7.4
^ permalink raw reply related
* [PATCH 01/12] Make and configuration files.
From: David VomLehn @ 2016-12-27 13:15 UTC (permalink / raw)
To: netdev
Cc: Simon Edelhaus, David VomLehn, Dmitrii Tarakanov,
Alexander Loktionov
Patches to create the make and configuration files.
Signed-off-by: Dmitrii Tarakanov <Dmitrii.Tarakanov@aquantia.com>
Signed-off-by: Alexander Loktionov <Alexander.Loktionov@aquantia.com>
Signed-off-by: David M. VomLehn <vomlehn@texas.net>
---
drivers/net/ethernet/aquantia/atlantic/Kconfig | 9 ++++++
drivers/net/ethernet/aquantia/atlantic/Makefile | 40 +++++++++++++++++++++++++
drivers/net/ethernet/aquantia/atlantic/ver.h | 18 +++++++++++
3 files changed, 67 insertions(+)
create mode 100644 drivers/net/ethernet/aquantia/atlantic/Kconfig
create mode 100644 drivers/net/ethernet/aquantia/atlantic/Makefile
create mode 100644 drivers/net/ethernet/aquantia/atlantic/ver.h
diff --git a/drivers/net/ethernet/aquantia/atlantic/Kconfig b/drivers/net/ethernet/aquantia/atlantic/Kconfig
new file mode 100644
index 0000000..33f1eb6
--- /dev/null
+++ b/drivers/net/ethernet/aquantia/atlantic/Kconfig
@@ -0,0 +1,9 @@
+#
+# Aquantia device configuration
+#
+
+config AQTION
+ tristate "Aquantia AQtion Support"
+ depends on PCI
+ ---help---
+ This enables the support for the Aquantia AQtion Ethernet card.
\ No newline at end of file
diff --git a/drivers/net/ethernet/aquantia/atlantic/Makefile b/drivers/net/ethernet/aquantia/atlantic/Makefile
new file mode 100644
index 0000000..f0d961f
--- /dev/null
+++ b/drivers/net/ethernet/aquantia/atlantic/Makefile
@@ -0,0 +1,40 @@
+TARGET:=atlantic
+
+CC = gcc
+
+ifeq "$(CC)" "gcc"
+ ccflags-y := -Wall
+endif
+
+ifneq ($(KERNELRELEASE),)
+ $(TARGET)-objs:=aq_main.o aq_nic.o aq_pci_func.o aq_nic.o aq_vec.o \
+ aq_ring.o aq_hw_utils.o aq_ethtool.o hw_atl/hw_atl_a0.o \
+ hw_atl/hw_atl_utils.o hw_atl/hw_atl_llh.o
+
+ obj-m:=$(TARGET).o
+else
+ ifndef KDIR
+ BUILD_DIR:=/lib/modules/$(shell uname -r)/build
+ else
+ BUILD_DIR:=$(KDIR)
+ endif
+
+ PWD:=$(shell pwd)
+
+all:
+ $(MAKE) -j4 CC=$(CC) -C $(BUILD_DIR) M=$(PWD) modules
+
+dox: .doxygen
+ @doxygen $<
+
+clean:
+ $(MAKE) -j4 -C $(BUILD_DIR) M=$(PWD) clean
+ @-rm -rdf doc/html 2 > /dev/null
+
+load:
+ insmod ./$(TARGET).ko
+
+unload:
+ rmmod ./$(TARGET).ko
+
+endif
diff --git a/drivers/net/ethernet/aquantia/atlantic/ver.h b/drivers/net/ethernet/aquantia/atlantic/ver.h
new file mode 100644
index 0000000..225f561
--- /dev/null
+++ b/drivers/net/ethernet/aquantia/atlantic/ver.h
@@ -0,0 +1,18 @@
+/*
+ * Aquantia Corporation Network Driver
+ * Copyright (C) 2014-2016 Aquantia Corporation. All rights reserved
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ */
+
+#ifndef VER_H
+#define VER_H
+
+#define NIC_MAJOR_DRIVER_VERSION 1
+#define NIC_MINOR_DRIVER_VERSION 4
+#define NIC_BUILD_DRIVER_VERSION 1671
+#define NIC_REVISION_DRIVER_VERSION 0
+
+#endif /* VER_H */
--
2.7.4
^ permalink raw reply related
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