* re: amd-xgbe: Add support for MDIO attached PHYs
From: Colin Ian King @ 2016-11-15 13:07 UTC (permalink / raw)
To: Tom Lendacky; +Cc: netdev@vger.kernel.org, David S. Miller
Hi,
Commit:
amd-xgbe: Add support for MDIO attached PHYs
Use the phylib support in the kernel to communicate with and control an
MDIO attached PHY. Use the hardware's MDIO communication mechanism to
communicate with the PHY.
+static int xgbe_clr_gpio(struct xgbe_prv_data *pdata, unsigned int gpio)
+{
+ unsigned int reg;
+
+ if (gpio > 16)
+ return -EINVAL;
is gpio in the range 0..15?
if (gpio > 15)
return -EINVAL;
+
+ reg = XGMAC_IOREAD(pdata, MAC_GPIOSR);
+
+ reg &= ~(1 << (gpio + 16));
if gpio is 16, we get 1 << 32 which I believe is undefined behaviour.
+ XGMAC_IOWRITE(pdata, MAC_GPIOSR, reg);
+
+ return 0;
+}
Same applies for function xgbe_clr_gpio().
Colin
^ permalink raw reply
* Re: [PATCH] vhost/vsock: Remove unused but set variable
From: Stefan Hajnoczi @ 2016-11-15 13:00 UTC (permalink / raw)
To: Tobias Klauser
Cc: Michael S. Tsirkin, Jason Wang, kvm, virtualization, netdev
In-Reply-To: <20161111132631.25708-1-tklauser@distanz.ch>
[-- Attachment #1: Type: text/plain, Size: 470 bytes --]
On Fri, Nov 11, 2016 at 02:26:31PM +0100, Tobias Klauser wrote:
> Remove the unused but set variable vq in vhost_transport_send_pkt() to
> fix the following GCC warning when building with 'W=1':
>
> drivers/vhost/vsock.c:198:26: warning: variable ‘vq’ set but not used
>
> Signed-off-by: Tobias Klauser <tklauser@distanz.ch>
> ---
> drivers/vhost/vsock.c | 3 ---
> 1 file changed, 3 deletions(-)
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 455 bytes --]
^ permalink raw reply
* [PATCH] net: ioctl SIOCSIFADDR minor cleanup
From: yuan linyu @ 2016-11-15 12:44 UTC (permalink / raw)
To: netdev; +Cc: davem, yuan linyu
From: yuan linyu <Linyu.Yuan@alcatel-sbell.com.cn>
1. set interface address label to ioctl request device name is enough
2. when address pass inet_abc_len check, prefixlen < 31 is always true
Signed-off-by: yuan linyu <Linyu.Yuan@alcatel-sbell.com.cn>
---
net/ipv4/devinet.c | 8 ++------
1 file changed, 2 insertions(+), 6 deletions(-)
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index 062a67c..d491a7a 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -1063,10 +1063,7 @@ int devinet_ioctl(struct net *net, unsigned int cmd, void __user *arg)
if (!ifa)
break;
INIT_HLIST_NODE(&ifa->hash);
- if (colon)
- memcpy(ifa->ifa_label, ifr.ifr_name, IFNAMSIZ);
- else
- memcpy(ifa->ifa_label, dev->name, IFNAMSIZ);
+ memcpy(ifa->ifa_label, ifr.ifr_name, IFNAMSIZ);
} else {
ret = 0;
if (ifa->ifa_local == sin->sin_addr.s_addr)
@@ -1081,8 +1078,7 @@ int devinet_ioctl(struct net *net, unsigned int cmd, void __user *arg)
if (!(dev->flags & IFF_POINTOPOINT)) {
ifa->ifa_prefixlen = inet_abc_len(ifa->ifa_address);
ifa->ifa_mask = inet_make_mask(ifa->ifa_prefixlen);
- if ((dev->flags & IFF_BROADCAST) &&
- ifa->ifa_prefixlen < 31)
+ if (dev->flags & IFF_BROADCAST)
ifa->ifa_broadcast = ifa->ifa_address |
~ifa->ifa_mask;
} else {
--
2.7.4
^ permalink raw reply related
* [PATCH] amd-xgbe: fix unsigned comparison against less than zero
From: Colin King @ 2016-11-15 12:18 UTC (permalink / raw)
To: Tom Lendacky, netdev; +Cc: linux-kernel
From: Colin Ian King <colin.king@canonical.com>
Comparing unsigned int ret to less than zero for an error status
check is never true. Fix this by making ret a signed int. Reduce
scope of ret too.
Found with static analysis by CoverityScan, CID 1377750
Signed-off-by: Colin Ian King <colin.king@canonical.com>
---
drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
index 4ba4332..168507e 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
@@ -2346,7 +2346,7 @@ static bool xgbe_phy_valid_speed(struct xgbe_prv_data *pdata, int speed)
static int xgbe_phy_link_status(struct xgbe_prv_data *pdata, int *an_restart)
{
struct xgbe_phy_data *phy_data = pdata->phy_data;
- unsigned int ret, reg;
+ unsigned int reg;
*an_restart = 0;
@@ -2365,7 +2365,8 @@ static int xgbe_phy_link_status(struct xgbe_prv_data *pdata, int *an_restart)
if (phy_data->phydev) {
/* Check external PHY */
- ret = phy_read_status(phy_data->phydev);
+ int ret = phy_read_status(phy_data->phydev);
+
if (ret < 0)
return 0;
--
2.10.2
^ permalink raw reply related
* [PATCH v2 5/5] net: thunderx: Fix memory leak and other issues upon interface toggle
From: sunil.kovvuri @ 2016-11-15 12:08 UTC (permalink / raw)
To: netdev; +Cc: linux-kernel, linux-arm-kernel, Sunil Goutham
From: Sunil Goutham <sgoutham@cavium.com>
This patch fixes the following
1. When interface is being teardown and queues are being cleaned up,
free pending SKBs that are in SQ which are either not transmitted
or freed as NAPI is disabled by that time.
2. While interface initialization, delay CFG_DONE notification till
the end to avoid corner cases where TXQs are enabled but CQ
interrupts are not which results blocking transmission and kicking
off watchdog.
3. Check for IFF_UP while re-enabling RBDR interrupts from tasklet.
Signed-off-by: Sunil Goutham <sgoutham@cavium.com>
---
drivers/net/ethernet/cavium/thunder/nicvf_main.c | 11 +++++------
drivers/net/ethernet/cavium/thunder/nicvf_queues.c | 14 +++++++++++++-
2 files changed, 18 insertions(+), 7 deletions(-)
diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_main.c b/drivers/net/ethernet/cavium/thunder/nicvf_main.c
index 9dc79c05..8a37012 100644
--- a/drivers/net/ethernet/cavium/thunder/nicvf_main.c
+++ b/drivers/net/ethernet/cavium/thunder/nicvf_main.c
@@ -473,9 +473,6 @@ int nicvf_set_real_num_queues(struct net_device *netdev,
static int nicvf_init_resources(struct nicvf *nic)
{
int err;
- union nic_mbx mbx = {};
-
- mbx.msg.msg = NIC_MBOX_MSG_CFG_DONE;
/* Enable Qset */
nicvf_qset_config(nic, true);
@@ -488,9 +485,6 @@ static int nicvf_init_resources(struct nicvf *nic)
return err;
}
- /* Send VF config done msg to PF */
- nicvf_write_to_mbx(nic, &mbx);
-
return 0;
}
@@ -1184,6 +1178,7 @@ int nicvf_open(struct net_device *netdev)
struct nicvf *nic = netdev_priv(netdev);
struct queue_set *qs = nic->qs;
struct nicvf_cq_poll *cq_poll = NULL;
+ union nic_mbx mbx = {};
netif_carrier_off(netdev);
@@ -1271,6 +1266,10 @@ int nicvf_open(struct net_device *netdev)
for (qidx = 0; qidx < qs->rbdr_cnt; qidx++)
nicvf_enable_intr(nic, NICVF_INTR_RBDR, qidx);
+ /* Send VF config done msg to PF */
+ mbx.msg.msg = NIC_MBOX_MSG_CFG_DONE;
+ nicvf_write_to_mbx(nic, &mbx);
+
return 0;
cleanup:
nicvf_disable_intr(nic, NICVF_INTR_MBOX, 0);
diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_queues.c b/drivers/net/ethernet/cavium/thunder/nicvf_queues.c
index bdce591..747ef08 100644
--- a/drivers/net/ethernet/cavium/thunder/nicvf_queues.c
+++ b/drivers/net/ethernet/cavium/thunder/nicvf_queues.c
@@ -271,7 +271,8 @@ static void nicvf_refill_rbdr(struct nicvf *nic, gfp_t gfp)
rbdr_idx, new_rb);
next_rbdr:
/* Re-enable RBDR interrupts only if buffer allocation is success */
- if (!nic->rb_alloc_fail && rbdr->enable)
+ if (!nic->rb_alloc_fail && rbdr->enable &&
+ netif_running(nic->pnicvf->netdev))
nicvf_enable_intr(nic, NICVF_INTR_RBDR, rbdr_idx);
if (rbdr_idx)
@@ -362,6 +363,8 @@ static int nicvf_init_snd_queue(struct nicvf *nic,
static void nicvf_free_snd_queue(struct nicvf *nic, struct snd_queue *sq)
{
+ struct sk_buff *skb;
+
if (!sq)
return;
if (!sq->dmem.base)
@@ -372,6 +375,15 @@ static void nicvf_free_snd_queue(struct nicvf *nic, struct snd_queue *sq)
sq->dmem.q_len * TSO_HEADER_SIZE,
sq->tso_hdrs, sq->tso_hdrs_phys);
+ /* Free pending skbs in the queue */
+ smp_rmb();
+ while (sq->head != sq->tail) {
+ skb = (struct sk_buff *)sq->skbuff[sq->head];
+ if (skb)
+ dev_kfree_skb_any(skb);
+ sq->head++;
+ sq->head &= (sq->dmem.q_len - 1);
+ }
kfree(sq->skbuff);
nicvf_free_q_desc_mem(nic, &sq->dmem);
}
--
2.7.4
^ permalink raw reply related
* [PATCH v2 4/5] net: thunderx: Fix VF driver's interface statistics
From: sunil.kovvuri @ 2016-11-15 12:08 UTC (permalink / raw)
To: netdev; +Cc: linux-kernel, linux-arm-kernel, Sunil Goutham
From: Sunil Goutham <sgoutham@cavium.com>
This patch fixes multiple issues
1. Convert all driver statistics to percpu counters for accuracy.
2. To avoid multiple CQEs posted by a TSO packet appended to HW,
TSO pkt's SQE has 'post_cqe' not set but a dummy SQE is added
for getting HW transmit completion notification. This dummy
SQE has 'dont_send' set and HW drops the pkt pointed to in this
thus Tx drop counter increases. This patch fixes this by subtracting
SW tx tso counter from HW Tx drop counter for actual packet drop counter.
3. Reset all individual queue's and VNIC HW stats when interface is going down.
4. Getrid off unnecessary counters in hot path.
5. Bringout all CQE error stats i.e both Rx and Tx.
Signed-off-by: Sunil Goutham <sgoutham@cavium.com>
---
drivers/net/ethernet/cavium/thunder/nic.h | 61 +++++++-----
drivers/net/ethernet/cavium/thunder/nic_main.c | 1 +
.../net/ethernet/cavium/thunder/nicvf_ethtool.c | 105 +++++++++++---------
drivers/net/ethernet/cavium/thunder/nicvf_main.c | 106 +++++++++++----------
drivers/net/ethernet/cavium/thunder/nicvf_queues.c | 96 +++++++++----------
drivers/net/ethernet/cavium/thunder/nicvf_queues.h | 24 +----
6 files changed, 197 insertions(+), 196 deletions(-)
diff --git a/drivers/net/ethernet/cavium/thunder/nic.h b/drivers/net/ethernet/cavium/thunder/nic.h
index cd2d379..86bd93c 100644
--- a/drivers/net/ethernet/cavium/thunder/nic.h
+++ b/drivers/net/ethernet/cavium/thunder/nic.h
@@ -178,11 +178,11 @@ enum tx_stats_reg_offset {
struct nicvf_hw_stats {
u64 rx_bytes;
+ u64 rx_frames;
u64 rx_ucast_frames;
u64 rx_bcast_frames;
u64 rx_mcast_frames;
- u64 rx_fcs_errors;
- u64 rx_l2_errors;
+ u64 rx_drops;
u64 rx_drop_red;
u64 rx_drop_red_bytes;
u64 rx_drop_overrun;
@@ -191,6 +191,19 @@ struct nicvf_hw_stats {
u64 rx_drop_mcast;
u64 rx_drop_l3_bcast;
u64 rx_drop_l3_mcast;
+ u64 rx_fcs_errors;
+ u64 rx_l2_errors;
+
+ u64 tx_bytes;
+ u64 tx_frames;
+ u64 tx_ucast_frames;
+ u64 tx_bcast_frames;
+ u64 tx_mcast_frames;
+ u64 tx_drops;
+};
+
+struct nicvf_drv_stats {
+ /* CQE Rx errs */
u64 rx_bgx_truncated_pkts;
u64 rx_jabber_errs;
u64 rx_fcs_errs;
@@ -216,34 +229,30 @@ struct nicvf_hw_stats {
u64 rx_l4_pclp;
u64 rx_truncated_pkts;
- u64 tx_bytes_ok;
- u64 tx_ucast_frames_ok;
- u64 tx_bcast_frames_ok;
- u64 tx_mcast_frames_ok;
- u64 tx_drops;
-};
-
-struct nicvf_drv_stats {
- /* Rx */
- u64 rx_frames_ok;
- u64 rx_frames_64;
- u64 rx_frames_127;
- u64 rx_frames_255;
- u64 rx_frames_511;
- u64 rx_frames_1023;
- u64 rx_frames_1518;
- u64 rx_frames_jumbo;
- u64 rx_drops;
-
+ /* CQE Tx errs */
+ u64 tx_desc_fault;
+ u64 tx_hdr_cons_err;
+ u64 tx_subdesc_err;
+ u64 tx_max_size_exceeded;
+ u64 tx_imm_size_oflow;
+ u64 tx_data_seq_err;
+ u64 tx_mem_seq_err;
+ u64 tx_lock_viol;
+ u64 tx_data_fault;
+ u64 tx_tstmp_conflict;
+ u64 tx_tstmp_timeout;
+ u64 tx_mem_fault;
+ u64 tx_csum_overlap;
+ u64 tx_csum_overflow;
+
+ /* driver debug stats */
u64 rcv_buffer_alloc_failures;
-
- /* Tx */
- u64 tx_frames_ok;
- u64 tx_drops;
u64 tx_tso;
u64 tx_timeout;
u64 txq_stop;
u64 txq_wake;
+
+ struct u64_stats_sync syncp;
};
struct nicvf {
@@ -297,7 +306,7 @@ struct nicvf {
/* Stats */
struct nicvf_hw_stats hw_stats;
- struct nicvf_drv_stats drv_stats;
+ struct nicvf_drv_stats __percpu *drv_stats;
struct bgx_stats bgx_stats;
/* MSI-X */
diff --git a/drivers/net/ethernet/cavium/thunder/nic_main.c b/drivers/net/ethernet/cavium/thunder/nic_main.c
index 85c9e62..6677b96 100644
--- a/drivers/net/ethernet/cavium/thunder/nic_main.c
+++ b/drivers/net/ethernet/cavium/thunder/nic_main.c
@@ -851,6 +851,7 @@ static int nic_reset_stat_counters(struct nicpf *nic,
nic_reg_write(nic, reg_addr, 0);
}
}
+
return 0;
}
diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_ethtool.c b/drivers/net/ethernet/cavium/thunder/nicvf_ethtool.c
index ad4fddb..432bf6b 100644
--- a/drivers/net/ethernet/cavium/thunder/nicvf_ethtool.c
+++ b/drivers/net/ethernet/cavium/thunder/nicvf_ethtool.c
@@ -36,11 +36,11 @@ struct nicvf_stat {
static const struct nicvf_stat nicvf_hw_stats[] = {
NICVF_HW_STAT(rx_bytes),
+ NICVF_HW_STAT(rx_frames),
NICVF_HW_STAT(rx_ucast_frames),
NICVF_HW_STAT(rx_bcast_frames),
NICVF_HW_STAT(rx_mcast_frames),
- NICVF_HW_STAT(rx_fcs_errors),
- NICVF_HW_STAT(rx_l2_errors),
+ NICVF_HW_STAT(rx_drops),
NICVF_HW_STAT(rx_drop_red),
NICVF_HW_STAT(rx_drop_red_bytes),
NICVF_HW_STAT(rx_drop_overrun),
@@ -49,50 +49,59 @@ static const struct nicvf_stat nicvf_hw_stats[] = {
NICVF_HW_STAT(rx_drop_mcast),
NICVF_HW_STAT(rx_drop_l3_bcast),
NICVF_HW_STAT(rx_drop_l3_mcast),
- NICVF_HW_STAT(rx_bgx_truncated_pkts),
- NICVF_HW_STAT(rx_jabber_errs),
- NICVF_HW_STAT(rx_fcs_errs),
- NICVF_HW_STAT(rx_bgx_errs),
- NICVF_HW_STAT(rx_prel2_errs),
- NICVF_HW_STAT(rx_l2_hdr_malformed),
- NICVF_HW_STAT(rx_oversize),
- NICVF_HW_STAT(rx_undersize),
- NICVF_HW_STAT(rx_l2_len_mismatch),
- NICVF_HW_STAT(rx_l2_pclp),
- NICVF_HW_STAT(rx_ip_ver_errs),
- NICVF_HW_STAT(rx_ip_csum_errs),
- NICVF_HW_STAT(rx_ip_hdr_malformed),
- NICVF_HW_STAT(rx_ip_payload_malformed),
- NICVF_HW_STAT(rx_ip_ttl_errs),
- NICVF_HW_STAT(rx_l3_pclp),
- NICVF_HW_STAT(rx_l4_malformed),
- NICVF_HW_STAT(rx_l4_csum_errs),
- NICVF_HW_STAT(rx_udp_len_errs),
- NICVF_HW_STAT(rx_l4_port_errs),
- NICVF_HW_STAT(rx_tcp_flag_errs),
- NICVF_HW_STAT(rx_tcp_offset_errs),
- NICVF_HW_STAT(rx_l4_pclp),
- NICVF_HW_STAT(rx_truncated_pkts),
- NICVF_HW_STAT(tx_bytes_ok),
- NICVF_HW_STAT(tx_ucast_frames_ok),
- NICVF_HW_STAT(tx_bcast_frames_ok),
- NICVF_HW_STAT(tx_mcast_frames_ok),
+ NICVF_HW_STAT(rx_fcs_errors),
+ NICVF_HW_STAT(rx_l2_errors),
+ NICVF_HW_STAT(tx_bytes),
+ NICVF_HW_STAT(tx_frames),
+ NICVF_HW_STAT(tx_ucast_frames),
+ NICVF_HW_STAT(tx_bcast_frames),
+ NICVF_HW_STAT(tx_mcast_frames),
+ NICVF_HW_STAT(tx_drops),
};
static const struct nicvf_stat nicvf_drv_stats[] = {
- NICVF_DRV_STAT(rx_frames_ok),
- NICVF_DRV_STAT(rx_frames_64),
- NICVF_DRV_STAT(rx_frames_127),
- NICVF_DRV_STAT(rx_frames_255),
- NICVF_DRV_STAT(rx_frames_511),
- NICVF_DRV_STAT(rx_frames_1023),
- NICVF_DRV_STAT(rx_frames_1518),
- NICVF_DRV_STAT(rx_frames_jumbo),
- NICVF_DRV_STAT(rx_drops),
+ NICVF_DRV_STAT(rx_bgx_truncated_pkts),
+ NICVF_DRV_STAT(rx_jabber_errs),
+ NICVF_DRV_STAT(rx_fcs_errs),
+ NICVF_DRV_STAT(rx_bgx_errs),
+ NICVF_DRV_STAT(rx_prel2_errs),
+ NICVF_DRV_STAT(rx_l2_hdr_malformed),
+ NICVF_DRV_STAT(rx_oversize),
+ NICVF_DRV_STAT(rx_undersize),
+ NICVF_DRV_STAT(rx_l2_len_mismatch),
+ NICVF_DRV_STAT(rx_l2_pclp),
+ NICVF_DRV_STAT(rx_ip_ver_errs),
+ NICVF_DRV_STAT(rx_ip_csum_errs),
+ NICVF_DRV_STAT(rx_ip_hdr_malformed),
+ NICVF_DRV_STAT(rx_ip_payload_malformed),
+ NICVF_DRV_STAT(rx_ip_ttl_errs),
+ NICVF_DRV_STAT(rx_l3_pclp),
+ NICVF_DRV_STAT(rx_l4_malformed),
+ NICVF_DRV_STAT(rx_l4_csum_errs),
+ NICVF_DRV_STAT(rx_udp_len_errs),
+ NICVF_DRV_STAT(rx_l4_port_errs),
+ NICVF_DRV_STAT(rx_tcp_flag_errs),
+ NICVF_DRV_STAT(rx_tcp_offset_errs),
+ NICVF_DRV_STAT(rx_l4_pclp),
+ NICVF_DRV_STAT(rx_truncated_pkts),
+
+ NICVF_DRV_STAT(tx_desc_fault),
+ NICVF_DRV_STAT(tx_hdr_cons_err),
+ NICVF_DRV_STAT(tx_subdesc_err),
+ NICVF_DRV_STAT(tx_max_size_exceeded),
+ NICVF_DRV_STAT(tx_imm_size_oflow),
+ NICVF_DRV_STAT(tx_data_seq_err),
+ NICVF_DRV_STAT(tx_mem_seq_err),
+ NICVF_DRV_STAT(tx_lock_viol),
+ NICVF_DRV_STAT(tx_data_fault),
+ NICVF_DRV_STAT(tx_tstmp_conflict),
+ NICVF_DRV_STAT(tx_tstmp_timeout),
+ NICVF_DRV_STAT(tx_mem_fault),
+ NICVF_DRV_STAT(tx_csum_overlap),
+ NICVF_DRV_STAT(tx_csum_overflow),
+
NICVF_DRV_STAT(rcv_buffer_alloc_failures),
- NICVF_DRV_STAT(tx_frames_ok),
NICVF_DRV_STAT(tx_tso),
- NICVF_DRV_STAT(tx_drops),
NICVF_DRV_STAT(tx_timeout),
NICVF_DRV_STAT(txq_stop),
NICVF_DRV_STAT(txq_wake),
@@ -278,8 +287,8 @@ static void nicvf_get_ethtool_stats(struct net_device *netdev,
struct ethtool_stats *stats, u64 *data)
{
struct nicvf *nic = netdev_priv(netdev);
- int stat;
- int sqs;
+ int stat, tmp_stats;
+ int sqs, cpu;
nicvf_update_stats(nic);
@@ -289,9 +298,13 @@ static void nicvf_get_ethtool_stats(struct net_device *netdev,
for (stat = 0; stat < nicvf_n_hw_stats; stat++)
*(data++) = ((u64 *)&nic->hw_stats)
[nicvf_hw_stats[stat].index];
- for (stat = 0; stat < nicvf_n_drv_stats; stat++)
- *(data++) = ((u64 *)&nic->drv_stats)
- [nicvf_drv_stats[stat].index];
+ for (stat = 0; stat < nicvf_n_drv_stats; stat++) {
+ tmp_stats = 0;
+ for_each_possible_cpu(cpu)
+ tmp_stats += ((u64 *)per_cpu_ptr(nic->drv_stats, cpu))
+ [nicvf_drv_stats[stat].index];
+ *(data++) = tmp_stats;
+ }
nicvf_get_qset_stats(nic, stats, &data);
diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_main.c b/drivers/net/ethernet/cavium/thunder/nicvf_main.c
index 8f83361..9dc79c05 100644
--- a/drivers/net/ethernet/cavium/thunder/nicvf_main.c
+++ b/drivers/net/ethernet/cavium/thunder/nicvf_main.c
@@ -69,25 +69,6 @@ static inline u8 nicvf_netdev_qidx(struct nicvf *nic, u8 qidx)
return qidx;
}
-static inline void nicvf_set_rx_frame_cnt(struct nicvf *nic,
- struct sk_buff *skb)
-{
- if (skb->len <= 64)
- nic->drv_stats.rx_frames_64++;
- else if (skb->len <= 127)
- nic->drv_stats.rx_frames_127++;
- else if (skb->len <= 255)
- nic->drv_stats.rx_frames_255++;
- else if (skb->len <= 511)
- nic->drv_stats.rx_frames_511++;
- else if (skb->len <= 1023)
- nic->drv_stats.rx_frames_1023++;
- else if (skb->len <= 1518)
- nic->drv_stats.rx_frames_1518++;
- else
- nic->drv_stats.rx_frames_jumbo++;
-}
-
/* The Cavium ThunderX network controller can *only* be found in SoCs
* containing the ThunderX ARM64 CPU implementation. All accesses to the device
* registers on this platform are implicitly strongly ordered with respect
@@ -514,7 +495,6 @@ static int nicvf_init_resources(struct nicvf *nic)
}
static void nicvf_snd_pkt_handler(struct net_device *netdev,
- struct cmp_queue *cq,
struct cqe_send_t *cqe_tx,
int cqe_type, int budget,
unsigned int *tx_pkts, unsigned int *tx_bytes)
@@ -536,7 +516,7 @@ static void nicvf_snd_pkt_handler(struct net_device *netdev,
__func__, cqe_tx->sq_qs, cqe_tx->sq_idx,
cqe_tx->sqe_ptr, hdr->subdesc_cnt);
- nicvf_check_cqe_tx_errs(nic, cq, cqe_tx);
+ nicvf_check_cqe_tx_errs(nic, cqe_tx);
skb = (struct sk_buff *)sq->skbuff[cqe_tx->sqe_ptr];
if (skb) {
/* Check for dummy descriptor used for HW TSO offload on 88xx */
@@ -630,8 +610,6 @@ static void nicvf_rcv_pkt_handler(struct net_device *netdev,
return;
}
- nicvf_set_rx_frame_cnt(nic, skb);
-
nicvf_set_rxhash(netdev, cqe_rx, skb);
skb_record_rx_queue(skb, rq_idx);
@@ -703,7 +681,7 @@ static int nicvf_cq_intr_handler(struct net_device *netdev, u8 cq_idx,
work_done++;
break;
case CQE_TYPE_SEND:
- nicvf_snd_pkt_handler(netdev, cq,
+ nicvf_snd_pkt_handler(netdev,
(void *)cq_desc, CQE_TYPE_SEND,
budget, &tx_pkts, &tx_bytes);
tx_done++;
@@ -740,7 +718,7 @@ static int nicvf_cq_intr_handler(struct net_device *netdev, u8 cq_idx,
nic = nic->pnicvf;
if (netif_tx_queue_stopped(txq) && netif_carrier_ok(netdev)) {
netif_tx_start_queue(txq);
- nic->drv_stats.txq_wake++;
+ this_cpu_inc(nic->drv_stats->txq_wake);
if (netif_msg_tx_err(nic))
netdev_warn(netdev,
"%s: Transmit queue wakeup SQ%d\n",
@@ -1084,7 +1062,7 @@ static netdev_tx_t nicvf_xmit(struct sk_buff *skb, struct net_device *netdev)
if (!netif_tx_queue_stopped(txq) && !nicvf_sq_append_skb(nic, skb)) {
netif_tx_stop_queue(txq);
- nic->drv_stats.txq_stop++;
+ this_cpu_inc(nic->drv_stats->txq_stop);
if (netif_msg_tx_err(nic))
netdev_warn(netdev,
"%s: Transmit ring full, stopping SQ%d\n",
@@ -1202,7 +1180,7 @@ static int nicvf_update_hw_max_frs(struct nicvf *nic, int mtu)
int nicvf_open(struct net_device *netdev)
{
- int err, qidx;
+ int cpu, err, qidx;
struct nicvf *nic = netdev_priv(netdev);
struct queue_set *qs = nic->qs;
struct nicvf_cq_poll *cq_poll = NULL;
@@ -1262,6 +1240,11 @@ int nicvf_open(struct net_device *netdev)
nicvf_rss_init(nic);
if (nicvf_update_hw_max_frs(nic, netdev->mtu))
goto cleanup;
+
+ /* Clear percpu stats */
+ for_each_possible_cpu(cpu)
+ memset(per_cpu_ptr(nic->drv_stats, cpu), 0,
+ sizeof(struct nicvf_drv_stats));
}
err = nicvf_register_interrupts(nic);
@@ -1288,9 +1271,6 @@ int nicvf_open(struct net_device *netdev)
for (qidx = 0; qidx < qs->rbdr_cnt; qidx++)
nicvf_enable_intr(nic, NICVF_INTR_RBDR, qidx);
- nic->drv_stats.txq_stop = 0;
- nic->drv_stats.txq_wake = 0;
-
return 0;
cleanup:
nicvf_disable_intr(nic, NICVF_INTR_MBOX, 0);
@@ -1383,9 +1363,10 @@ void nicvf_update_lmac_stats(struct nicvf *nic)
void nicvf_update_stats(struct nicvf *nic)
{
- int qidx;
+ int qidx, cpu;
+ u64 tmp_stats = 0;
struct nicvf_hw_stats *stats = &nic->hw_stats;
- struct nicvf_drv_stats *drv_stats = &nic->drv_stats;
+ struct nicvf_drv_stats *drv_stats;
struct queue_set *qs = nic->qs;
#define GET_RX_STATS(reg) \
@@ -1408,21 +1389,33 @@ void nicvf_update_stats(struct nicvf *nic)
stats->rx_drop_l3_bcast = GET_RX_STATS(RX_DRP_L3BCAST);
stats->rx_drop_l3_mcast = GET_RX_STATS(RX_DRP_L3MCAST);
- stats->tx_bytes_ok = GET_TX_STATS(TX_OCTS);
- stats->tx_ucast_frames_ok = GET_TX_STATS(TX_UCAST);
- stats->tx_bcast_frames_ok = GET_TX_STATS(TX_BCAST);
- stats->tx_mcast_frames_ok = GET_TX_STATS(TX_MCAST);
+ stats->tx_bytes = GET_TX_STATS(TX_OCTS);
+ stats->tx_ucast_frames = GET_TX_STATS(TX_UCAST);
+ stats->tx_bcast_frames = GET_TX_STATS(TX_BCAST);
+ stats->tx_mcast_frames = GET_TX_STATS(TX_MCAST);
stats->tx_drops = GET_TX_STATS(TX_DROP);
- drv_stats->tx_frames_ok = stats->tx_ucast_frames_ok +
- stats->tx_bcast_frames_ok +
- stats->tx_mcast_frames_ok;
- drv_stats->rx_frames_ok = stats->rx_ucast_frames +
- stats->rx_bcast_frames +
- stats->rx_mcast_frames;
- drv_stats->rx_drops = stats->rx_drop_red +
- stats->rx_drop_overrun;
- drv_stats->tx_drops = stats->tx_drops;
+ /* On T88 pass 2.0, the dummy SQE added for TSO notification
+ * via CQE has 'dont_send' set. Hence HW drops the pkt pointed
+ * pointed by dummy SQE and results in tx_drops counter being
+ * incremented. Subtracting it from tx_tso counter will give
+ * exact tx_drops counter.
+ */
+ if (nic->t88 && nic->hw_tso) {
+ for_each_possible_cpu(cpu) {
+ drv_stats = per_cpu_ptr(nic->drv_stats, cpu);
+ tmp_stats += drv_stats->tx_tso;
+ }
+ stats->tx_drops = tmp_stats - stats->tx_drops;
+ }
+ stats->tx_frames = stats->tx_ucast_frames +
+ stats->tx_bcast_frames +
+ stats->tx_mcast_frames;
+ stats->rx_frames = stats->rx_ucast_frames +
+ stats->rx_bcast_frames +
+ stats->rx_mcast_frames;
+ stats->rx_drops = stats->rx_drop_red +
+ stats->rx_drop_overrun;
/* Update RQ and SQ stats */
for (qidx = 0; qidx < qs->rq_cnt; qidx++)
@@ -1436,18 +1429,17 @@ static struct rtnl_link_stats64 *nicvf_get_stats64(struct net_device *netdev,
{
struct nicvf *nic = netdev_priv(netdev);
struct nicvf_hw_stats *hw_stats = &nic->hw_stats;
- struct nicvf_drv_stats *drv_stats = &nic->drv_stats;
nicvf_update_stats(nic);
stats->rx_bytes = hw_stats->rx_bytes;
- stats->rx_packets = drv_stats->rx_frames_ok;
- stats->rx_dropped = drv_stats->rx_drops;
+ stats->rx_packets = hw_stats->rx_frames;
+ stats->rx_dropped = hw_stats->rx_drops;
stats->multicast = hw_stats->rx_mcast_frames;
- stats->tx_bytes = hw_stats->tx_bytes_ok;
- stats->tx_packets = drv_stats->tx_frames_ok;
- stats->tx_dropped = drv_stats->tx_drops;
+ stats->tx_bytes = hw_stats->tx_bytes;
+ stats->tx_packets = hw_stats->tx_frames;
+ stats->tx_dropped = hw_stats->tx_drops;
return stats;
}
@@ -1460,7 +1452,7 @@ static void nicvf_tx_timeout(struct net_device *dev)
netdev_warn(dev, "%s: Transmit timed out, resetting\n",
dev->name);
- nic->drv_stats.tx_timeout++;
+ this_cpu_inc(nic->drv_stats->tx_timeout);
schedule_work(&nic->reset_task);
}
@@ -1594,6 +1586,12 @@ static int nicvf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
goto err_free_netdev;
}
+ nic->drv_stats = netdev_alloc_pcpu_stats(struct nicvf_drv_stats);
+ if (!nic->drv_stats) {
+ err = -ENOMEM;
+ goto err_free_netdev;
+ }
+
err = nicvf_set_qset_resources(nic);
if (err)
goto err_free_netdev;
@@ -1652,6 +1650,8 @@ static int nicvf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
nicvf_unregister_interrupts(nic);
err_free_netdev:
pci_set_drvdata(pdev, NULL);
+ if (nic->drv_stats)
+ free_percpu(nic->drv_stats);
free_netdev(netdev);
err_release_regions:
pci_release_regions(pdev);
@@ -1679,6 +1679,8 @@ static void nicvf_remove(struct pci_dev *pdev)
unregister_netdev(pnetdev);
nicvf_unregister_interrupts(nic);
pci_set_drvdata(pdev, NULL);
+ if (nic->drv_stats)
+ free_percpu(nic->drv_stats);
free_netdev(netdev);
pci_release_regions(pdev);
pci_disable_device(pdev);
diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_queues.c b/drivers/net/ethernet/cavium/thunder/nicvf_queues.c
index f914eef..bdce591 100644
--- a/drivers/net/ethernet/cavium/thunder/nicvf_queues.c
+++ b/drivers/net/ethernet/cavium/thunder/nicvf_queues.c
@@ -104,7 +104,8 @@ static inline int nicvf_alloc_rcv_buffer(struct nicvf *nic, gfp_t gfp,
nic->rb_page = alloc_pages(gfp | __GFP_COMP | __GFP_NOWARN,
order);
if (!nic->rb_page) {
- nic->drv_stats.rcv_buffer_alloc_failures++;
+ this_cpu_inc(nic->pnicvf->drv_stats->
+ rcv_buffer_alloc_failures);
return -ENOMEM;
}
nic->rb_page_offset = 0;
@@ -483,9 +484,12 @@ static void nicvf_reset_rcv_queue_stats(struct nicvf *nic)
{
union nic_mbx mbx = {};
- /* Reset all RXQ's stats */
+ /* Reset all RQ/SQ and VF stats */
mbx.reset_stat.msg = NIC_MBOX_MSG_RESET_STAT_COUNTER;
+ mbx.reset_stat.rx_stat_mask = 0x3FFF;
+ mbx.reset_stat.tx_stat_mask = 0x1F;
mbx.reset_stat.rq_stat_mask = 0xFFFF;
+ mbx.reset_stat.sq_stat_mask = 0xFFFF;
nicvf_send_msg_to_pf(nic, &mbx);
}
@@ -1032,7 +1036,7 @@ nicvf_sq_add_hdr_subdesc(struct nicvf *nic, struct snd_queue *sq, int qentry,
hdr->tso_max_paysize = skb_shinfo(skb)->gso_size;
/* For non-tunneled pkts, point this to L2 ethertype */
hdr->inner_l3_offset = skb_network_offset(skb) - 2;
- nic->drv_stats.tx_tso++;
+ this_cpu_inc(nic->pnicvf->drv_stats->tx_tso);
}
}
@@ -1164,7 +1168,7 @@ static int nicvf_sq_append_tso(struct nicvf *nic, struct snd_queue *sq,
nicvf_sq_doorbell(nic, skb, sq_num, desc_cnt);
- nic->drv_stats.tx_tso++;
+ this_cpu_inc(nic->pnicvf->drv_stats->tx_tso);
return 1;
}
@@ -1425,8 +1429,6 @@ void nicvf_update_sq_stats(struct nicvf *nic, int sq_idx)
/* Check for errors in the receive cmp.queue entry */
int nicvf_check_cqe_rx_errs(struct nicvf *nic, struct cqe_rx_t *cqe_rx)
{
- struct nicvf_hw_stats *stats = &nic->hw_stats;
-
if (!cqe_rx->err_level && !cqe_rx->err_opcode)
return 0;
@@ -1438,76 +1440,76 @@ int nicvf_check_cqe_rx_errs(struct nicvf *nic, struct cqe_rx_t *cqe_rx)
switch (cqe_rx->err_opcode) {
case CQ_RX_ERROP_RE_PARTIAL:
- stats->rx_bgx_truncated_pkts++;
+ this_cpu_inc(nic->drv_stats->rx_bgx_truncated_pkts);
break;
case CQ_RX_ERROP_RE_JABBER:
- stats->rx_jabber_errs++;
+ this_cpu_inc(nic->drv_stats->rx_jabber_errs);
break;
case CQ_RX_ERROP_RE_FCS:
- stats->rx_fcs_errs++;
+ this_cpu_inc(nic->drv_stats->rx_fcs_errs);
break;
case CQ_RX_ERROP_RE_RX_CTL:
- stats->rx_bgx_errs++;
+ this_cpu_inc(nic->drv_stats->rx_bgx_errs);
break;
case CQ_RX_ERROP_PREL2_ERR:
- stats->rx_prel2_errs++;
+ this_cpu_inc(nic->drv_stats->rx_prel2_errs);
break;
case CQ_RX_ERROP_L2_MAL:
- stats->rx_l2_hdr_malformed++;
+ this_cpu_inc(nic->drv_stats->rx_l2_hdr_malformed);
break;
case CQ_RX_ERROP_L2_OVERSIZE:
- stats->rx_oversize++;
+ this_cpu_inc(nic->drv_stats->rx_oversize);
break;
case CQ_RX_ERROP_L2_UNDERSIZE:
- stats->rx_undersize++;
+ this_cpu_inc(nic->drv_stats->rx_undersize);
break;
case CQ_RX_ERROP_L2_LENMISM:
- stats->rx_l2_len_mismatch++;
+ this_cpu_inc(nic->drv_stats->rx_l2_len_mismatch);
break;
case CQ_RX_ERROP_L2_PCLP:
- stats->rx_l2_pclp++;
+ this_cpu_inc(nic->drv_stats->rx_l2_pclp);
break;
case CQ_RX_ERROP_IP_NOT:
- stats->rx_ip_ver_errs++;
+ this_cpu_inc(nic->drv_stats->rx_ip_ver_errs);
break;
case CQ_RX_ERROP_IP_CSUM_ERR:
- stats->rx_ip_csum_errs++;
+ this_cpu_inc(nic->drv_stats->rx_ip_csum_errs);
break;
case CQ_RX_ERROP_IP_MAL:
- stats->rx_ip_hdr_malformed++;
+ this_cpu_inc(nic->drv_stats->rx_ip_hdr_malformed);
break;
case CQ_RX_ERROP_IP_MALD:
- stats->rx_ip_payload_malformed++;
+ this_cpu_inc(nic->drv_stats->rx_ip_payload_malformed);
break;
case CQ_RX_ERROP_IP_HOP:
- stats->rx_ip_ttl_errs++;
+ this_cpu_inc(nic->drv_stats->rx_ip_ttl_errs);
break;
case CQ_RX_ERROP_L3_PCLP:
- stats->rx_l3_pclp++;
+ this_cpu_inc(nic->drv_stats->rx_l3_pclp);
break;
case CQ_RX_ERROP_L4_MAL:
- stats->rx_l4_malformed++;
+ this_cpu_inc(nic->drv_stats->rx_l4_malformed);
break;
case CQ_RX_ERROP_L4_CHK:
- stats->rx_l4_csum_errs++;
+ this_cpu_inc(nic->drv_stats->rx_l4_csum_errs);
break;
case CQ_RX_ERROP_UDP_LEN:
- stats->rx_udp_len_errs++;
+ this_cpu_inc(nic->drv_stats->rx_udp_len_errs);
break;
case CQ_RX_ERROP_L4_PORT:
- stats->rx_l4_port_errs++;
+ this_cpu_inc(nic->drv_stats->rx_l4_port_errs);
break;
case CQ_RX_ERROP_TCP_FLAG:
- stats->rx_tcp_flag_errs++;
+ this_cpu_inc(nic->drv_stats->rx_tcp_flag_errs);
break;
case CQ_RX_ERROP_TCP_OFFSET:
- stats->rx_tcp_offset_errs++;
+ this_cpu_inc(nic->drv_stats->rx_tcp_offset_errs);
break;
case CQ_RX_ERROP_L4_PCLP:
- stats->rx_l4_pclp++;
+ this_cpu_inc(nic->drv_stats->rx_l4_pclp);
break;
case CQ_RX_ERROP_RBDR_TRUNC:
- stats->rx_truncated_pkts++;
+ this_cpu_inc(nic->drv_stats->rx_truncated_pkts);
break;
}
@@ -1515,56 +1517,52 @@ int nicvf_check_cqe_rx_errs(struct nicvf *nic, struct cqe_rx_t *cqe_rx)
}
/* Check for errors in the send cmp.queue entry */
-int nicvf_check_cqe_tx_errs(struct nicvf *nic,
- struct cmp_queue *cq, struct cqe_send_t *cqe_tx)
+int nicvf_check_cqe_tx_errs(struct nicvf *nic, struct cqe_send_t *cqe_tx)
{
- struct cmp_queue_stats *stats = &cq->stats;
-
switch (cqe_tx->send_status) {
case CQ_TX_ERROP_GOOD:
- stats->tx.good++;
return 0;
case CQ_TX_ERROP_DESC_FAULT:
- stats->tx.desc_fault++;
+ this_cpu_inc(nic->drv_stats->tx_desc_fault);
break;
case CQ_TX_ERROP_HDR_CONS_ERR:
- stats->tx.hdr_cons_err++;
+ this_cpu_inc(nic->drv_stats->tx_hdr_cons_err);
break;
case CQ_TX_ERROP_SUBDC_ERR:
- stats->tx.subdesc_err++;
+ this_cpu_inc(nic->drv_stats->tx_subdesc_err);
break;
case CQ_TX_ERROP_MAX_SIZE_VIOL:
- stats->tx.max_size_exceeded++;
+ this_cpu_inc(nic->drv_stats->tx_max_size_exceeded);
break;
case CQ_TX_ERROP_IMM_SIZE_OFLOW:
- stats->tx.imm_size_oflow++;
+ this_cpu_inc(nic->drv_stats->tx_imm_size_oflow);
break;
case CQ_TX_ERROP_DATA_SEQUENCE_ERR:
- stats->tx.data_seq_err++;
+ this_cpu_inc(nic->drv_stats->tx_data_seq_err);
break;
case CQ_TX_ERROP_MEM_SEQUENCE_ERR:
- stats->tx.mem_seq_err++;
+ this_cpu_inc(nic->drv_stats->tx_mem_seq_err);
break;
case CQ_TX_ERROP_LOCK_VIOL:
- stats->tx.lock_viol++;
+ this_cpu_inc(nic->drv_stats->tx_lock_viol);
break;
case CQ_TX_ERROP_DATA_FAULT:
- stats->tx.data_fault++;
+ this_cpu_inc(nic->drv_stats->tx_data_fault);
break;
case CQ_TX_ERROP_TSTMP_CONFLICT:
- stats->tx.tstmp_conflict++;
+ this_cpu_inc(nic->drv_stats->tx_tstmp_conflict);
break;
case CQ_TX_ERROP_TSTMP_TIMEOUT:
- stats->tx.tstmp_timeout++;
+ this_cpu_inc(nic->drv_stats->tx_tstmp_timeout);
break;
case CQ_TX_ERROP_MEM_FAULT:
- stats->tx.mem_fault++;
+ this_cpu_inc(nic->drv_stats->tx_mem_fault);
break;
case CQ_TX_ERROP_CK_OVERLAP:
- stats->tx.csum_overlap++;
+ this_cpu_inc(nic->drv_stats->tx_csum_overlap);
break;
case CQ_TX_ERROP_CK_OFLOW:
- stats->tx.csum_overflow++;
+ this_cpu_inc(nic->drv_stats->tx_csum_overflow);
break;
}
diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_queues.h b/drivers/net/ethernet/cavium/thunder/nicvf_queues.h
index 8f4718e..2e3c940 100644
--- a/drivers/net/ethernet/cavium/thunder/nicvf_queues.h
+++ b/drivers/net/ethernet/cavium/thunder/nicvf_queues.h
@@ -172,26 +172,6 @@ enum CQ_TX_ERROP_E {
CQ_TX_ERROP_ENUM_LAST = 0x8a,
};
-struct cmp_queue_stats {
- struct tx_stats {
- u64 good;
- u64 desc_fault;
- u64 hdr_cons_err;
- u64 subdesc_err;
- u64 max_size_exceeded;
- u64 imm_size_oflow;
- u64 data_seq_err;
- u64 mem_seq_err;
- u64 lock_viol;
- u64 data_fault;
- u64 tstmp_conflict;
- u64 tstmp_timeout;
- u64 mem_fault;
- u64 csum_overlap;
- u64 csum_overflow;
- } tx;
-} ____cacheline_aligned_in_smp;
-
enum RQ_SQ_STATS {
RQ_SQ_STATS_OCTS,
RQ_SQ_STATS_PKTS,
@@ -243,7 +223,6 @@ struct cmp_queue {
spinlock_t lock; /* lock to serialize processing CQEs */
void *desc;
struct q_desc_mem dmem;
- struct cmp_queue_stats stats;
int irq;
} ____cacheline_aligned_in_smp;
@@ -338,6 +317,5 @@ u64 nicvf_queue_reg_read(struct nicvf *nic,
void nicvf_update_rq_stats(struct nicvf *nic, int rq_idx);
void nicvf_update_sq_stats(struct nicvf *nic, int sq_idx);
int nicvf_check_cqe_rx_errs(struct nicvf *nic, struct cqe_rx_t *cqe_rx);
-int nicvf_check_cqe_tx_errs(struct nicvf *nic,
- struct cmp_queue *cq, struct cqe_send_t *cqe_tx);
+int nicvf_check_cqe_tx_errs(struct nicvf *nic, struct cqe_send_t *cqe_tx);
#endif /* NICVF_QUEUES_H */
--
2.7.4
^ permalink raw reply related
* Re: [CRIU] [PATCH net-next] tcp: allow to enable the repair mode for non-listening sockets
From: Pavel Emelyanov @ 2016-11-15 12:08 UTC (permalink / raw)
To: Andrei Vagin, David S. Miller
Cc: Hideaki YOSHIFUJI, netdev, James Morris, linux-kernel, criu,
Alexey Kuznetsov, Patrick McHardy
In-Reply-To: <1479176114-12658-1-git-send-email-avagin@openvz.org>
On 11/15/2016 05:15 AM, Andrei Vagin wrote:
> The repair mode is used to get and restore sequence numbers and
> data from queues. It used to checkpoint/restore connections.
>
> Currently the repair mode can be enabled for sockets in the established
> and closed states, but for other states we have to dump the same socket
> properties, so lets allow to enable repair mode for these sockets.
>
> The repair mode reveals nothing more for sockets in other states.
>
> Signed-off-by: Andrei Vagin <avagin@openvz.org>
Acked-by: Pavel Emelyanov <xemul@openvz.org>
> ---
> net/ipv4/tcp.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
> index 3251fe7..a2a3a8c 100644
> --- a/net/ipv4/tcp.c
> +++ b/net/ipv4/tcp.c
> @@ -2302,7 +2302,7 @@ EXPORT_SYMBOL(tcp_disconnect);
> static inline bool tcp_can_repair_sock(const struct sock *sk)
> {
> return ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN) &&
> - ((1 << sk->sk_state) & (TCPF_CLOSE | TCPF_ESTABLISHED));
> + (sk->sk_state != TCP_LISTEN);
> }
>
> static int tcp_repair_set_window(struct tcp_sock *tp, char __user *optbuf, int len)
>
^ permalink raw reply
* [PATCH v2 3/5] net: thunderx: Fix configuration of L3/L4 length checking
From: sunil.kovvuri @ 2016-11-15 12:07 UTC (permalink / raw)
To: netdev; +Cc: linux-kernel, linux-arm-kernel, Sunil Goutham
From: Sunil Goutham <sgoutham@cavium.com>
This patch fixes enabling of HW verification of L3/L4 length and
TCP/UDP checksum which is currently being cleared. Also fixed VLAN
stripping config which is being cleared when multiqset is enabled.
Signed-off-by: Sunil Goutham <sgoutham@cavium.com>
---
drivers/net/ethernet/cavium/thunder/nicvf_queues.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_queues.c b/drivers/net/ethernet/cavium/thunder/nicvf_queues.c
index f0e0ca6..f914eef 100644
--- a/drivers/net/ethernet/cavium/thunder/nicvf_queues.c
+++ b/drivers/net/ethernet/cavium/thunder/nicvf_queues.c
@@ -538,9 +538,12 @@ static void nicvf_rcv_queue_config(struct nicvf *nic, struct queue_set *qs,
mbx.rq.cfg = (1ULL << 62) | (RQ_CQ_DROP << 8);
nicvf_send_msg_to_pf(nic, &mbx);
- nicvf_queue_reg_write(nic, NIC_QSET_RQ_GEN_CFG, 0, 0x00);
- if (!nic->sqs_mode)
+ if (!nic->sqs_mode && (qidx == 0)) {
+ /* Enable checking L3/L4 length and TCP/UDP checksums */
+ nicvf_queue_reg_write(nic, NIC_QSET_RQ_GEN_CFG, 0,
+ (BIT(24) | BIT(23) | BIT(21)));
nicvf_config_vlan_stripping(nic, nic->netdev->features);
+ }
/* Enable Receive queue */
memset(&rq_cfg, 0, sizeof(struct rq_cfg));
--
2.7.4
^ permalink raw reply related
* [PATCH v2 2/5] net: thunderx: Program LMAC credits based on MTU
From: sunil.kovvuri @ 2016-11-15 12:07 UTC (permalink / raw)
To: netdev; +Cc: linux-kernel, linux-arm-kernel, Sunil Goutham
From: Sunil Goutham <sgoutham@cavium.com>
Programming LMAC credits taking 9K frame size by default is incorrect
as for an interface which is one of the many on the same BGX/QLM
no of credits available will be less as Tx FIFO will be divided
across all interfaces. So let's say a BGX with 40G interface and another
BGX with multiple 10G, bandwidth of 10G interfaces will be effected when
traffic is running on both 40G and 10G interfaces simultaneously.
This patch fixes this issue by programming credits based on netdev's MTU.
Also fixed configuring MTU to HW and added CQE counter for pkts which
exceed this value.
Signed-off-by: Sunil Goutham <sgoutham@cavium.com>
---
drivers/net/ethernet/cavium/thunder/nic.h | 3 +-
drivers/net/ethernet/cavium/thunder/nic_main.c | 36 +++++++++++++-------
drivers/net/ethernet/cavium/thunder/nic_reg.h | 1 +
drivers/net/ethernet/cavium/thunder/nicvf_main.c | 38 ++++++++++++----------
drivers/net/ethernet/cavium/thunder/nicvf_queues.c | 3 ++
drivers/net/ethernet/cavium/thunder/nicvf_queues.h | 2 ++
6 files changed, 53 insertions(+), 30 deletions(-)
diff --git a/drivers/net/ethernet/cavium/thunder/nic.h b/drivers/net/ethernet/cavium/thunder/nic.h
index 3042610..cd2d379 100644
--- a/drivers/net/ethernet/cavium/thunder/nic.h
+++ b/drivers/net/ethernet/cavium/thunder/nic.h
@@ -47,7 +47,7 @@
/* Min/Max packet size */
#define NIC_HW_MIN_FRS 64
-#define NIC_HW_MAX_FRS 9200 /* 9216 max packet including FCS */
+#define NIC_HW_MAX_FRS 9190 /* Excluding L2 header and FCS */
/* Max pkinds */
#define NIC_MAX_PKIND 16
@@ -282,7 +282,6 @@ struct nicvf {
u8 node;
u8 cpi_alg;
- u16 mtu;
bool link_up;
u8 duplex;
u32 speed;
diff --git a/drivers/net/ethernet/cavium/thunder/nic_main.c b/drivers/net/ethernet/cavium/thunder/nic_main.c
index 2bbf4cb..85c9e62 100644
--- a/drivers/net/ethernet/cavium/thunder/nic_main.c
+++ b/drivers/net/ethernet/cavium/thunder/nic_main.c
@@ -11,6 +11,7 @@
#include <linux/pci.h>
#include <linux/etherdevice.h>
#include <linux/of.h>
+#include <linux/if_vlan.h>
#include "nic_reg.h"
#include "nic.h"
@@ -260,18 +261,31 @@ static void nic_get_bgx_stats(struct nicpf *nic, struct bgx_stats_msg *bgx)
/* Update hardware min/max frame size */
static int nic_update_hw_frs(struct nicpf *nic, int new_frs, int vf)
{
- if ((new_frs > NIC_HW_MAX_FRS) || (new_frs < NIC_HW_MIN_FRS)) {
- dev_err(&nic->pdev->dev,
- "Invalid MTU setting from VF%d rejected, should be between %d and %d\n",
- vf, NIC_HW_MIN_FRS, NIC_HW_MAX_FRS);
+ int bgx, lmac, lmac_cnt;
+ u64 lmac_credits;
+
+ if ((new_frs > NIC_HW_MAX_FRS) || (new_frs < NIC_HW_MIN_FRS))
return 1;
- }
- new_frs += ETH_HLEN;
- if (new_frs <= nic->pkind.maxlen)
- return 0;
- nic->pkind.maxlen = new_frs;
- nic_reg_write(nic, NIC_PF_PKIND_0_15_CFG, *(u64 *)&nic->pkind);
+ bgx = NIC_GET_BGX_FROM_VF_LMAC_MAP(nic->vf_lmac_map[vf]);
+ lmac = NIC_GET_LMAC_FROM_VF_LMAC_MAP(nic->vf_lmac_map[vf]);
+ lmac += bgx * MAX_LMAC_PER_BGX;
+
+ new_frs += VLAN_ETH_HLEN + ETH_FCS_LEN + 4;
+
+ /* Update corresponding LMAC credits */
+ lmac_cnt = bgx_get_lmac_count(nic->node, bgx);
+ lmac_credits = nic_reg_read(nic, NIC_PF_LMAC_0_7_CREDIT + (lmac * 8));
+ lmac_credits &= ~(0xFFFFFULL << 12);
+ lmac_credits |= (((((48 * 1024) / lmac_cnt) - new_frs) / 16) << 12);
+ nic_reg_write(nic, NIC_PF_LMAC_0_7_CREDIT + (lmac * 8), lmac_credits);
+
+ /* Enforce MTU in HW
+ * This config is supported only from 88xx pass 2.0 onwards.
+ */
+ if (!pass1_silicon(nic->pdev))
+ nic_reg_write(nic,
+ NIC_PF_LMAC_0_7_CFG2 + (lmac * 8), new_frs);
return 0;
}
@@ -464,7 +478,7 @@ static int nic_init_hw(struct nicpf *nic)
/* PKIND configuration */
nic->pkind.minlen = 0;
- nic->pkind.maxlen = NIC_HW_MAX_FRS + ETH_HLEN;
+ nic->pkind.maxlen = NIC_HW_MAX_FRS + VLAN_ETH_HLEN + ETH_FCS_LEN + 4;
nic->pkind.lenerr_en = 1;
nic->pkind.rx_hdr = 0;
nic->pkind.hdr_sl = 0;
diff --git a/drivers/net/ethernet/cavium/thunder/nic_reg.h b/drivers/net/ethernet/cavium/thunder/nic_reg.h
index edf779f..80d4633 100644
--- a/drivers/net/ethernet/cavium/thunder/nic_reg.h
+++ b/drivers/net/ethernet/cavium/thunder/nic_reg.h
@@ -106,6 +106,7 @@
#define NIC_PF_MPI_0_2047_CFG (0x210000)
#define NIC_PF_RSSI_0_4097_RQ (0x220000)
#define NIC_PF_LMAC_0_7_CFG (0x240000)
+#define NIC_PF_LMAC_0_7_CFG2 (0x240100)
#define NIC_PF_LMAC_0_7_SW_XOFF (0x242000)
#define NIC_PF_LMAC_0_7_CREDIT (0x244000)
#define NIC_PF_CHAN_0_255_TX_CFG (0x400000)
diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_main.c b/drivers/net/ethernet/cavium/thunder/nicvf_main.c
index 45a13f7..8f83361 100644
--- a/drivers/net/ethernet/cavium/thunder/nicvf_main.c
+++ b/drivers/net/ethernet/cavium/thunder/nicvf_main.c
@@ -1189,6 +1189,17 @@ int nicvf_stop(struct net_device *netdev)
return 0;
}
+static int nicvf_update_hw_max_frs(struct nicvf *nic, int mtu)
+{
+ union nic_mbx mbx = {};
+
+ mbx.frs.msg = NIC_MBOX_MSG_SET_MAX_FRS;
+ mbx.frs.max_frs = mtu;
+ mbx.frs.vf_id = nic->vf_id;
+
+ return nicvf_send_msg_to_pf(nic, &mbx);
+}
+
int nicvf_open(struct net_device *netdev)
{
int err, qidx;
@@ -1196,8 +1207,6 @@ int nicvf_open(struct net_device *netdev)
struct queue_set *qs = nic->qs;
struct nicvf_cq_poll *cq_poll = NULL;
- nic->mtu = netdev->mtu;
-
netif_carrier_off(netdev);
err = nicvf_register_misc_interrupt(nic);
@@ -1248,9 +1257,12 @@ int nicvf_open(struct net_device *netdev)
if (nic->sqs_mode)
nicvf_get_primary_vf_struct(nic);
- /* Configure receive side scaling */
- if (!nic->sqs_mode)
+ /* Configure receive side scaling and MTU */
+ if (!nic->sqs_mode) {
nicvf_rss_init(nic);
+ if (nicvf_update_hw_max_frs(nic, netdev->mtu))
+ goto cleanup;
+ }
err = nicvf_register_interrupts(nic);
if (err)
@@ -1297,17 +1309,6 @@ int nicvf_open(struct net_device *netdev)
return err;
}
-static int nicvf_update_hw_max_frs(struct nicvf *nic, int mtu)
-{
- union nic_mbx mbx = {};
-
- mbx.frs.msg = NIC_MBOX_MSG_SET_MAX_FRS;
- mbx.frs.max_frs = mtu;
- mbx.frs.vf_id = nic->vf_id;
-
- return nicvf_send_msg_to_pf(nic, &mbx);
-}
-
static int nicvf_change_mtu(struct net_device *netdev, int new_mtu)
{
struct nicvf *nic = netdev_priv(netdev);
@@ -1318,10 +1319,13 @@ static int nicvf_change_mtu(struct net_device *netdev, int new_mtu)
if (new_mtu < NIC_HW_MIN_FRS)
return -EINVAL;
+ netdev->mtu = new_mtu;
+
+ if (!netif_running(netdev))
+ return 0;
+
if (nicvf_update_hw_max_frs(nic, new_mtu))
return -EINVAL;
- netdev->mtu = new_mtu;
- nic->mtu = new_mtu;
return 0;
}
diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_queues.c b/drivers/net/ethernet/cavium/thunder/nicvf_queues.c
index a4fc501..f0e0ca6 100644
--- a/drivers/net/ethernet/cavium/thunder/nicvf_queues.c
+++ b/drivers/net/ethernet/cavium/thunder/nicvf_queues.c
@@ -1530,6 +1530,9 @@ int nicvf_check_cqe_tx_errs(struct nicvf *nic,
case CQ_TX_ERROP_SUBDC_ERR:
stats->tx.subdesc_err++;
break;
+ case CQ_TX_ERROP_MAX_SIZE_VIOL:
+ stats->tx.max_size_exceeded++;
+ break;
case CQ_TX_ERROP_IMM_SIZE_OFLOW:
stats->tx.imm_size_oflow++;
break;
diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_queues.h b/drivers/net/ethernet/cavium/thunder/nicvf_queues.h
index 869f338..8f4718e 100644
--- a/drivers/net/ethernet/cavium/thunder/nicvf_queues.h
+++ b/drivers/net/ethernet/cavium/thunder/nicvf_queues.h
@@ -158,6 +158,7 @@ enum CQ_TX_ERROP_E {
CQ_TX_ERROP_DESC_FAULT = 0x10,
CQ_TX_ERROP_HDR_CONS_ERR = 0x11,
CQ_TX_ERROP_SUBDC_ERR = 0x12,
+ CQ_TX_ERROP_MAX_SIZE_VIOL = 0x13,
CQ_TX_ERROP_IMM_SIZE_OFLOW = 0x80,
CQ_TX_ERROP_DATA_SEQUENCE_ERR = 0x81,
CQ_TX_ERROP_MEM_SEQUENCE_ERR = 0x82,
@@ -177,6 +178,7 @@ struct cmp_queue_stats {
u64 desc_fault;
u64 hdr_cons_err;
u64 subdesc_err;
+ u64 max_size_exceeded;
u64 imm_size_oflow;
u64 data_seq_err;
u64 mem_seq_err;
--
2.7.4
^ permalink raw reply related
* [PATCH v2 1/5] net: thunderx: Introduce BGX_ID_MASK macro to extract bgx_id
From: sunil.kovvuri @ 2016-11-15 12:07 UTC (permalink / raw)
To: netdev
Cc: linux-kernel, linux-arm-kernel, Radha Mohan Chintakuntla,
Sunil Goutham
From: Radha Mohan Chintakuntla <rchintakuntla@cavium.com>
This patch fixes the 'bgx_id' determination on 83xx where there are
4 BGX blocks instead of 2 on other platforms.
Signed-off-by: Radha Mohan Chintakuntla <rchintakuntla@cavium.com>
Signed-off-by: Sunil Goutham <sgoutham@cavium.com>
---
drivers/net/ethernet/cavium/thunder/thunder_bgx.c | 4 ++--
drivers/net/ethernet/cavium/thunder/thunder_bgx.h | 2 ++
2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/cavium/thunder/thunder_bgx.c b/drivers/net/ethernet/cavium/thunder/thunder_bgx.c
index 8bbaedb..050e21f 100644
--- a/drivers/net/ethernet/cavium/thunder/thunder_bgx.c
+++ b/drivers/net/ethernet/cavium/thunder/thunder_bgx.c
@@ -1242,8 +1242,8 @@ static int bgx_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
pci_read_config_word(pdev, PCI_DEVICE_ID, &sdevid);
if (sdevid != PCI_DEVICE_ID_THUNDER_RGX) {
- bgx->bgx_id =
- (pci_resource_start(pdev, PCI_CFG_REG_BAR_NUM) >> 24) & 1;
+ bgx->bgx_id = (pci_resource_start(pdev,
+ PCI_CFG_REG_BAR_NUM) >> 24) & BGX_ID_MASK;
bgx->bgx_id += nic_get_node_id(pdev) * MAX_BGX_PER_NODE;
bgx->max_lmac = MAX_LMAC_PER_BGX;
bgx_vnic[bgx->bgx_id] = bgx;
diff --git a/drivers/net/ethernet/cavium/thunder/thunder_bgx.h b/drivers/net/ethernet/cavium/thunder/thunder_bgx.h
index d59c71e..01cc7c8 100644
--- a/drivers/net/ethernet/cavium/thunder/thunder_bgx.h
+++ b/drivers/net/ethernet/cavium/thunder/thunder_bgx.h
@@ -28,6 +28,8 @@
#define MAX_DMAC_PER_LMAC 8
#define MAX_FRAME_SIZE 9216
+#define BGX_ID_MASK 0x3
+
#define MAX_DMAC_PER_LMAC_TNS_BYPASS_MODE 2
/* Registers */
--
2.7.4
^ permalink raw reply related
* [PATCH v2 0/5] net: thunderx: Miscellaneous fixes
From: sunil.kovvuri @ 2016-11-15 12:05 UTC (permalink / raw)
To: netdev; +Cc: linux-kernel, linux-arm-kernel, Sunil Goutham
From: Sunil Goutham <sgoutham@cavium.com>
This patchset includes fixes for incorrect LMAC credits,
unreliable driver statistics, memory leak upon interface
down e.t.c
Changes from v1:
- As suggested replaced bit shifting with BIT() macro
in the patch 'Fix configuration of L3/L4 length checking'.
Radha Mohan Chintakuntla (1):
net: thunderx: Introduce BGX_ID_MASK macro to extract bgx_id
Sunil Goutham (4):
net: thunderx: Program LMAC credits based on MTU
net: thunderx: Fix configuration of L3/L4 length checking
net: thunderx: Fix VF driver's interface statistics
net: thunderx: Fix memory leak and other issues upon interface toggle
drivers/net/ethernet/cavium/thunder/nic.h | 64 +++++----
drivers/net/ethernet/cavium/thunder/nic_main.c | 37 +++--
drivers/net/ethernet/cavium/thunder/nic_reg.h | 1 +
.../net/ethernet/cavium/thunder/nicvf_ethtool.c | 105 +++++++-------
drivers/net/ethernet/cavium/thunder/nicvf_main.c | 153 +++++++++++----------
drivers/net/ethernet/cavium/thunder/nicvf_queues.c | 118 +++++++++-------
drivers/net/ethernet/cavium/thunder/nicvf_queues.h | 24 +---
drivers/net/ethernet/cavium/thunder/thunder_bgx.c | 4 +-
drivers/net/ethernet/cavium/thunder/thunder_bgx.h | 2 +
9 files changed, 274 insertions(+), 234 deletions(-)
--
2.7.4
^ permalink raw reply
* 18163 netdev
From: gestu @ 2016-11-15 11:44 UTC (permalink / raw)
To: netdev
[-- Attachment #1: EMAIL_06652941_netdev.zip --]
[-- Type: application/zip, Size: 5845 bytes --]
^ permalink raw reply
* [PATCH net-next V2 9/9] alx: enable multiple tx queues
From: Tobias Regnery @ 2016-11-15 11:43 UTC (permalink / raw)
To: netdev, jcliburn, chris.snook; +Cc: davem, Tobias Regnery
In-Reply-To: <cover.1479208627.git.tobias.regnery@gmail.com>
Enable multiple tx queues by default based on the number of online cpus. The
hardware supports up to four tx queues.
Based on the downstream driver at github.com/qca/alx
Signed-off-by: Tobias Regnery <tobias.regnery@gmail.com>
---
drivers/net/ethernet/atheros/alx/main.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/atheros/alx/main.c b/drivers/net/ethernet/atheros/alx/main.c
index 91c9149ab3f2..c8f525574d68 100644
--- a/drivers/net/ethernet/atheros/alx/main.c
+++ b/drivers/net/ethernet/atheros/alx/main.c
@@ -834,7 +834,7 @@ static bool alx_enable_msix(struct alx_priv *alx)
{
int i, err, num_vec, num_txq, num_rxq;
- num_txq = 1;
+ num_txq = min_t(int, num_online_cpus(), ALX_MAX_TX_QUEUES);
num_rxq = 1;
num_vec = max_t(int, num_txq, num_rxq) + 1;
@@ -1241,6 +1241,9 @@ static int __alx_open(struct alx_priv *alx, bool resume)
if (err)
goto out_free_rings;
+ netif_set_real_num_tx_queues(alx->dev, alx->num_txq);
+ netif_set_real_num_rx_queues(alx->dev, alx->num_rxq);
+
/* clear old interrupts */
alx_write_mem32(&alx->hw, ALX_ISR, ~(u32)ALX_ISR_DIS);
@@ -1749,7 +1752,8 @@ static int alx_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
goto out_pci_release;
}
- netdev = alloc_etherdev(sizeof(*alx));
+ netdev = alloc_etherdev_mqs(sizeof(*alx),
+ ALX_MAX_TX_QUEUES, 1);
if (!netdev) {
err = -ENOMEM;
goto out_pci_release;
--
2.7.4
^ permalink raw reply related
* [PATCH net-next V2 8/9] alx: enable msi-x interrupts by default
From: Tobias Regnery @ 2016-11-15 11:43 UTC (permalink / raw)
To: netdev, jcliburn, chris.snook; +Cc: davem, Tobias Regnery
In-Reply-To: <cover.1479208627.git.tobias.regnery@gmail.com>
Remove the module parameter to enable msi-x support and enable msi-x
interrupts unconditionally by default. This is a preparatory step to enable
multi queue support by default, because this is only working with msi-x
interrupts.
Signed-off-by: Tobias Regnery <tobias.regnery@gmail.com>
---
drivers/net/ethernet/atheros/alx/main.c | 6 +-----
1 file changed, 1 insertion(+), 5 deletions(-)
diff --git a/drivers/net/ethernet/atheros/alx/main.c b/drivers/net/ethernet/atheros/alx/main.c
index 0e773a2ca6a0..91c9149ab3f2 100644
--- a/drivers/net/ethernet/atheros/alx/main.c
+++ b/drivers/net/ethernet/atheros/alx/main.c
@@ -51,10 +51,6 @@
const char alx_drv_name[] = "alx";
-static bool msix = false;
-module_param(msix, bool, 0);
-MODULE_PARM_DESC(msix, "Enable msi-x interrupt support");
-
static void alx_free_txbuf(struct alx_tx_queue *txq, int entry)
{
struct alx_buffer *txb = &txq->bufs[entry];
@@ -1226,7 +1222,7 @@ static int __alx_open(struct alx_priv *alx, bool resume)
{
int err;
- alx_init_intr(alx, msix);
+ alx_init_intr(alx, true);
if (!resume)
netif_carrier_off(alx->dev);
--
2.7.4
^ permalink raw reply related
* [PATCH net-next V2 7/9] alx: prepare tx path for multi queue support
From: Tobias Regnery @ 2016-11-15 11:43 UTC (permalink / raw)
To: netdev, jcliburn, chris.snook; +Cc: davem, Tobias Regnery
In-Reply-To: <cover.1479208627.git.tobias.regnery@gmail.com>
This patch prepares the tx path to send data on multiple tx queues. It
introduces per queue register adresses and uses them in the alx_tx_queue
structs.
There are new helper functions for the queue mapping in the tx path.
Based on the downstream driver at github.com/qca/alx
Signed-off-by: Tobias Regnery <tobias.regnery@gmail.com>
---
drivers/net/ethernet/atheros/alx/main.c | 58 +++++++++++++++++++++++++--------
1 file changed, 45 insertions(+), 13 deletions(-)
diff --git a/drivers/net/ethernet/atheros/alx/main.c b/drivers/net/ethernet/atheros/alx/main.c
index c5f09d2616a4..0e773a2ca6a0 100644
--- a/drivers/net/ethernet/atheros/alx/main.c
+++ b/drivers/net/ethernet/atheros/alx/main.c
@@ -143,6 +143,22 @@ static int alx_refill_rx_ring(struct alx_priv *alx, gfp_t gfp)
return count;
}
+static struct alx_tx_queue *alx_tx_queue_mapping(struct alx_priv *alx,
+ struct sk_buff *skb)
+{
+ unsigned int r_idx = skb->queue_mapping;
+
+ if (r_idx >= alx->num_txq)
+ r_idx = r_idx % alx->num_txq;
+
+ return alx->qnapi[r_idx]->txq;
+}
+
+static struct netdev_queue *alx_get_tx_queue(const struct alx_tx_queue *txq)
+{
+ return netdev_get_tx_queue(txq->netdev, txq->queue_idx);
+}
+
static inline int alx_tpd_avail(struct alx_tx_queue *txq)
{
if (txq->write_idx >= txq->read_idx)
@@ -153,14 +169,16 @@ static inline int alx_tpd_avail(struct alx_tx_queue *txq)
static bool alx_clean_tx_irq(struct alx_tx_queue *txq)
{
struct alx_priv *alx;
+ struct netdev_queue *tx_queue;
u16 hw_read_idx, sw_read_idx;
unsigned int total_bytes = 0, total_packets = 0;
int budget = ALX_DEFAULT_TX_WORK;
alx = netdev_priv(txq->netdev);
+ tx_queue = alx_get_tx_queue(txq);
sw_read_idx = txq->read_idx;
- hw_read_idx = alx_read_mem16(&alx->hw, ALX_TPD_PRI0_CIDX);
+ hw_read_idx = alx_read_mem16(&alx->hw, txq->c_reg);
if (sw_read_idx != hw_read_idx) {
while (sw_read_idx != hw_read_idx && budget > 0) {
@@ -180,12 +198,12 @@ static bool alx_clean_tx_irq(struct alx_tx_queue *txq)
}
txq->read_idx = sw_read_idx;
- netdev_completed_queue(txq->netdev, total_packets, total_bytes);
+ netdev_tx_completed_queue(tx_queue, total_packets, total_bytes);
}
- if (netif_queue_stopped(txq->netdev) && netif_carrier_ok(txq->netdev) &&
+ if (netif_tx_queue_stopped(tx_queue) && netif_carrier_ok(alx->dev) &&
alx_tpd_avail(txq) > txq->count / 4)
- netif_wake_queue(txq->netdev);
+ netif_tx_wake_queue(tx_queue);
return sw_read_idx == hw_read_idx;
}
@@ -487,7 +505,7 @@ static void alx_free_txring_buf(struct alx_tx_queue *txq)
txq->write_idx = 0;
txq->read_idx = 0;
- netdev_reset_queue(txq->netdev);
+ netdev_tx_reset_queue(alx_get_tx_queue(txq));
}
static void alx_free_rxring_buf(struct alx_rx_queue *rxq)
@@ -714,6 +732,10 @@ static void alx_free_napis(struct alx_priv *alx)
}
}
+static const u16 tx_pidx_reg[] = {ALX_TPD_PRI0_PIDX, ALX_TPD_PRI1_PIDX,
+ ALX_TPD_PRI2_PIDX, ALX_TPD_PRI3_PIDX};
+static const u16 tx_cidx_reg[] = {ALX_TPD_PRI0_CIDX, ALX_TPD_PRI1_CIDX,
+ ALX_TPD_PRI2_CIDX, ALX_TPD_PRI3_CIDX};
static const u32 tx_vect_mask[] = {ALX_ISR_TX_Q0, ALX_ISR_TX_Q1,
ALX_ISR_TX_Q2, ALX_ISR_TX_Q3};
static const u32 rx_vect_mask[] = {ALX_ISR_RX_Q0, ALX_ISR_RX_Q1,
@@ -749,6 +771,8 @@ static int alx_alloc_napis(struct alx_priv *alx)
goto err_out;
np->txq = txq;
+ txq->p_reg = tx_pidx_reg[i];
+ txq->c_reg = tx_cidx_reg[i];
txq->queue_idx = i;
txq->count = alx->tx_ringsz;
txq->netdev = alx->dev;
@@ -1501,16 +1525,17 @@ static int alx_map_tx_skb(struct alx_tx_queue *txq, struct sk_buff *skb)
return -ENOMEM;
}
-static netdev_tx_t alx_start_xmit(struct sk_buff *skb,
- struct net_device *netdev)
+static netdev_tx_t alx_start_xmit_ring(struct sk_buff *skb,
+ struct alx_tx_queue *txq)
{
- struct alx_priv *alx = netdev_priv(netdev);
- struct alx_tx_queue *txq = alx->qnapi[0]->txq;
+ struct alx_priv *alx;
struct alx_txd *first;
int tso;
+ alx = netdev_priv(txq->netdev);
+
if (alx_tpd_avail(txq) < alx_tpd_req(skb)) {
- netif_stop_queue(txq->netdev);
+ netif_tx_stop_queue(alx_get_tx_queue(txq));
goto drop;
}
@@ -1526,14 +1551,14 @@ static netdev_tx_t alx_start_xmit(struct sk_buff *skb,
if (alx_map_tx_skb(txq, skb) < 0)
goto drop;
- netdev_sent_queue(txq->netdev, skb->len);
+ netdev_tx_sent_queue(alx_get_tx_queue(txq), skb->len);
/* flush updates before updating hardware */
wmb();
- alx_write_mem16(&alx->hw, ALX_TPD_PRI0_PIDX, txq->write_idx);
+ alx_write_mem16(&alx->hw, txq->p_reg, txq->write_idx);
if (alx_tpd_avail(txq) < txq->count / 8)
- netif_stop_queue(txq->netdev);
+ netif_tx_stop_queue(alx_get_tx_queue(txq));
return NETDEV_TX_OK;
@@ -1542,6 +1567,13 @@ static netdev_tx_t alx_start_xmit(struct sk_buff *skb,
return NETDEV_TX_OK;
}
+static netdev_tx_t alx_start_xmit(struct sk_buff *skb,
+ struct net_device *netdev)
+{
+ struct alx_priv *alx = netdev_priv(netdev);
+ return alx_start_xmit_ring(skb, alx_tx_queue_mapping(alx, skb));
+}
+
static void alx_tx_timeout(struct net_device *dev)
{
struct alx_priv *alx = netdev_priv(dev);
--
2.7.4
^ permalink raw reply related
* [PATCH net-next V2 6/9] alx: prepare resource allocation for multi queue support
From: Tobias Regnery @ 2016-11-15 11:43 UTC (permalink / raw)
To: netdev, jcliburn, chris.snook; +Cc: davem, Tobias Regnery
In-Reply-To: <cover.1479208627.git.tobias.regnery@gmail.com>
Allocate, initialise and free alx_tx_queue structs based on the number of
alx_napi structures. Also increase the size of the descriptor memory based
on the number of tx queues in use.
Based on the downstream driver at github.com/qca/alx
Signed-off-by: Tobias Regnery <tobias.regnery@gmail.com>
---
drivers/net/ethernet/atheros/alx/main.c | 149 +++++++++++++++++++++-----------
1 file changed, 97 insertions(+), 52 deletions(-)
diff --git a/drivers/net/ethernet/atheros/alx/main.c b/drivers/net/ethernet/atheros/alx/main.c
index aeb42120910d..c5f09d2616a4 100644
--- a/drivers/net/ethernet/atheros/alx/main.c
+++ b/drivers/net/ethernet/atheros/alx/main.c
@@ -429,28 +429,45 @@ static irqreturn_t alx_intr_legacy(int irq, void *data)
return alx_intr_handle(alx, intr);
}
+static const u16 txring_header_reg[] = {ALX_TPD_PRI0_ADDR_LO,
+ ALX_TPD_PRI1_ADDR_LO,
+ ALX_TPD_PRI2_ADDR_LO,
+ ALX_TPD_PRI3_ADDR_LO};
+
static void alx_init_ring_ptrs(struct alx_priv *alx)
{
struct alx_hw *hw = &alx->hw;
u32 addr_hi = ((u64)alx->descmem.dma) >> 32;
- struct alx_napi *np = alx->qnapi[0];
+ struct alx_napi *np;
+ int i;
+
+ for (i = 0; i < alx->num_napi; i++) {
+ np = alx->qnapi[i];
+ if (np->txq) {
+ np->txq->read_idx = 0;
+ np->txq->write_idx = 0;
+ alx_write_mem32(hw,
+ txring_header_reg[np->txq->queue_idx],
+ np->txq->tpd_dma);
+ }
+
+ if (np->rxq) {
+ np->rxq->read_idx = 0;
+ np->rxq->write_idx = 0;
+ np->rxq->rrd_read_idx = 0;
+ alx_write_mem32(hw, ALX_RRD_ADDR_LO, np->rxq->rrd_dma);
+ alx_write_mem32(hw, ALX_RFD_ADDR_LO, np->rxq->rfd_dma);
+ }
+ }
+
+ alx_write_mem32(hw, ALX_TX_BASE_ADDR_HI, addr_hi);
+ alx_write_mem32(hw, ALX_TPD_RING_SZ, alx->tx_ringsz);
- np->rxq->read_idx = 0;
- np->rxq->write_idx = 0;
- np->rxq->rrd_read_idx = 0;
alx_write_mem32(hw, ALX_RX_BASE_ADDR_HI, addr_hi);
- alx_write_mem32(hw, ALX_RRD_ADDR_LO, np->rxq->rrd_dma);
alx_write_mem32(hw, ALX_RRD_RING_SZ, alx->rx_ringsz);
- alx_write_mem32(hw, ALX_RFD_ADDR_LO, np->rxq->rfd_dma);
alx_write_mem32(hw, ALX_RFD_RING_SZ, alx->rx_ringsz);
alx_write_mem32(hw, ALX_RFD_BUF_SZ, alx->rxbuf_size);
- np->txq->read_idx = 0;
- np->txq->write_idx = 0;
- alx_write_mem32(hw, ALX_TX_BASE_ADDR_HI, addr_hi);
- alx_write_mem32(hw, ALX_TPD_PRI0_ADDR_LO, np->txq->tpd_dma);
- alx_write_mem32(hw, ALX_TPD_RING_SZ, alx->tx_ringsz);
-
/* load these pointers into the chip */
alx_write_mem32(hw, ALX_SRAM9, ALX_SRAM_LOAD_PTR);
}
@@ -478,7 +495,7 @@ static void alx_free_rxring_buf(struct alx_rx_queue *rxq)
struct alx_buffer *cur_buf;
u16 i;
- if (rxq == NULL)
+ if (!rxq->bufs)
return;
for (i = 0; i < rxq->count; i++) {
@@ -502,8 +519,14 @@ static void alx_free_rxring_buf(struct alx_rx_queue *rxq)
static void alx_free_buffers(struct alx_priv *alx)
{
- alx_free_txring_buf(alx->qnapi[0]->txq);
- alx_free_rxring_buf(alx->qnapi[0]->rxq);
+ int i;
+
+ for (i = 0; i < alx->num_txq; i++)
+ if (alx->qnapi[i] && alx->qnapi[i]->txq)
+ alx_free_txring_buf(alx->qnapi[i]->txq);
+
+ if (alx->qnapi[0] && alx->qnapi[0]->rxq)
+ alx_free_rxring_buf(alx->qnapi[0]->rxq);
}
static int alx_reinit_rings(struct alx_priv *alx)
@@ -611,7 +634,7 @@ static int alx_alloc_rx_ring(struct alx_priv *alx, struct alx_rx_queue *rxq,
static int alx_alloc_rings(struct alx_priv *alx)
{
- int offset = 0;
+ int i, offset = 0;
/* physical tx/rx ring descriptors
*
@@ -619,7 +642,8 @@ static int alx_alloc_rings(struct alx_priv *alx)
* 4G boundary (hardware has a single register for high 32 bits
* of addresses only)
*/
- alx->descmem.size = sizeof(struct alx_txd) * alx->tx_ringsz +
+ alx->descmem.size = sizeof(struct alx_txd) * alx->tx_ringsz *
+ alx->num_txq +
sizeof(struct alx_rrd) * alx->rx_ringsz +
sizeof(struct alx_rfd) * alx->rx_ringsz;
alx->descmem.virt = dma_zalloc_coherent(&alx->hw.pdev->dev,
@@ -633,10 +657,12 @@ static int alx_alloc_rings(struct alx_priv *alx)
BUILD_BUG_ON(sizeof(struct alx_txd) % 8);
BUILD_BUG_ON(sizeof(struct alx_rrd) % 8);
- offset = alx_alloc_tx_ring(alx, alx->qnapi[0]->txq, offset);
- if (offset < 0) {
- netdev_err(alx->dev, "Allocation of tx buffer failed!\n");
- return -ENOMEM;
+ for (i = 0; i < alx->num_txq; i++) {
+ offset = alx_alloc_tx_ring(alx, alx->qnapi[i]->txq, offset);
+ if (offset < 0) {
+ netdev_err(alx->dev, "Allocation of tx buffer failed!\n");
+ return -ENOMEM;
+ }
}
offset = alx_alloc_rx_ring(alx, alx->qnapi[0]->rxq, offset);
@@ -652,11 +678,16 @@ static int alx_alloc_rings(struct alx_priv *alx)
static void alx_free_rings(struct alx_priv *alx)
{
+ int i;
alx_free_buffers(alx);
- kfree(alx->qnapi[0]->txq->bufs);
- kfree(alx->qnapi[0]->rxq->bufs);
+ for (i = 0; i < alx->num_txq; i++)
+ if (alx->qnapi[i] && alx->qnapi[i]->txq)
+ kfree(alx->qnapi[i]->txq->bufs);
+
+ if (alx->qnapi[0] && alx->qnapi[0]->rxq)
+ kfree(alx->qnapi[0]->rxq->bufs);
if (!alx->descmem.virt)
dma_free_coherent(&alx->hw.pdev->dev,
@@ -668,16 +699,19 @@ static void alx_free_rings(struct alx_priv *alx)
static void alx_free_napis(struct alx_priv *alx)
{
struct alx_napi *np;
+ int i;
- np = alx->qnapi[0];
- if (!np)
- return;
-
- netif_napi_del(&np->napi);
- kfree(np->txq);
- kfree(np->rxq);
- kfree(np);
- alx->qnapi[0] = NULL;
+ for (i = 0; i < alx->num_napi; i++) {
+ np = alx->qnapi[i];
+ if (!np)
+ continue;
+
+ netif_napi_del(&np->napi);
+ kfree(np->txq);
+ kfree(np->rxq);
+ kfree(np);
+ alx->qnapi[i] = NULL;
+ }
}
static const u32 tx_vect_mask[] = {ALX_ISR_TX_Q0, ALX_ISR_TX_Q1,
@@ -692,31 +726,36 @@ static int alx_alloc_napis(struct alx_priv *alx)
struct alx_napi *np;
struct alx_rx_queue *rxq;
struct alx_tx_queue *txq;
+ int i;
alx->int_mask &= ~ALX_ISR_ALL_QUEUES;
/* allocate alx_napi structures */
- np = kzalloc(sizeof(struct alx_napi), GFP_KERNEL);
- if (!np)
- goto err_out;
+ for (i = 0; i < alx->num_napi; i++) {
+ np = kzalloc(sizeof(struct alx_napi), GFP_KERNEL);
+ if (!np)
+ goto err_out;
- np->alx = alx;
- netif_napi_add(alx->dev, &np->napi, alx_poll, 64);
- alx->qnapi[0] = np;
+ np->alx = alx;
+ netif_napi_add(alx->dev, &np->napi, alx_poll, 64);
+ alx->qnapi[i] = np;
+ }
/* allocate tx queues */
- np = alx->qnapi[0];
- txq = kzalloc(sizeof(*txq), GFP_KERNEL);
- if (!txq)
- goto err_out;
-
- np->txq = txq;
- txq->queue_idx = 0;
- txq->count = alx->tx_ringsz;
- txq->netdev = alx->dev;
- txq->dev = &alx->hw.pdev->dev;
- np->vec_mask |= tx_vect_mask[0];
- alx->int_mask |= tx_vect_mask[0];
+ for (i = 0; i < alx->num_txq; i++) {
+ np = alx->qnapi[i];
+ txq = kzalloc(sizeof(*txq), GFP_KERNEL);
+ if (!txq)
+ goto err_out;
+
+ np->txq = txq;
+ txq->queue_idx = i;
+ txq->count = alx->tx_ringsz;
+ txq->netdev = alx->dev;
+ txq->dev = &alx->hw.pdev->dev;
+ np->vec_mask |= tx_vect_mask[i];
+ alx->int_mask |= tx_vect_mask[i];
+ }
/* allocate rx queues */
np = alx->qnapi[0];
@@ -1075,11 +1114,14 @@ static netdev_features_t alx_fix_features(struct net_device *netdev,
static void alx_netif_stop(struct alx_priv *alx)
{
+ int i;
+
netif_trans_update(alx->dev);
if (netif_carrier_ok(alx->dev)) {
netif_carrier_off(alx->dev);
netif_tx_disable(alx->dev);
- napi_disable(&alx->qnapi[0]->napi);
+ for (i = 0; i < alx->num_napi; i++)
+ napi_disable(&alx->qnapi[i]->napi);
}
}
@@ -1148,8 +1190,11 @@ static int alx_change_mtu(struct net_device *netdev, int mtu)
static void alx_netif_start(struct alx_priv *alx)
{
+ int i;
+
netif_tx_wake_all_queues(alx->dev);
- napi_enable(&alx->qnapi[0]->napi);
+ for (i = 0; i < alx->num_napi; i++)
+ napi_enable(&alx->qnapi[i]->napi);
netif_carrier_on(alx->dev);
}
--
2.7.4
^ permalink raw reply related
* [PATCH net-next V2 5/9] alx: prepare interrupt functions for multiple queues
From: Tobias Regnery @ 2016-11-15 11:43 UTC (permalink / raw)
To: netdev, jcliburn, chris.snook; +Cc: davem, Tobias Regnery
In-Reply-To: <cover.1479208627.git.tobias.regnery@gmail.com>
Extend the interrupt bringup code and the interrupt handler for msi-x
interrupts in order to handle multiple queues.
We must change the poll function because with multiple queues it is possible
that an alx_napi structure has only a tx or only a rx queue pointer.
Based on the downstream driver at github.com/qca/alx
Signed-off-by: Tobias Regnery <tobias.regnery@gmail.com>
---
drivers/net/ethernet/atheros/alx/main.c | 132 +++++++++++++++++++++++++-------
1 file changed, 105 insertions(+), 27 deletions(-)
diff --git a/drivers/net/ethernet/atheros/alx/main.c b/drivers/net/ethernet/atheros/alx/main.c
index a9fc44611b8a..aeb42120910d 100644
--- a/drivers/net/ethernet/atheros/alx/main.c
+++ b/drivers/net/ethernet/atheros/alx/main.c
@@ -286,11 +286,13 @@ static int alx_poll(struct napi_struct *napi, int budget)
struct alx_priv *alx = np->alx;
struct alx_hw *hw = &alx->hw;
unsigned long flags;
- bool tx_complete;
- int work;
+ bool tx_complete = true;
+ int work = 0;
- tx_complete = alx_clean_tx_irq(np->txq);
- work = alx_clean_rx_irq(np->rxq, budget);
+ if (np->txq)
+ tx_complete = alx_clean_tx_irq(np->txq);
+ if (np->rxq)
+ work = alx_clean_rx_irq(np->rxq, budget);
if (!tx_complete || work == budget)
return budget;
@@ -299,7 +301,7 @@ static int alx_poll(struct napi_struct *napi, int budget)
/* enable interrupt */
if (alx->flags & ALX_FLAG_USING_MSIX) {
- alx_mask_msix(hw, 1, false);
+ alx_mask_msix(hw, np->vec_idx, false);
} else {
spin_lock_irqsave(&alx->irq_lock, flags);
alx->int_mask |= ALX_ISR_TX_Q0 | ALX_ISR_RX_Q0;
@@ -372,9 +374,9 @@ static irqreturn_t alx_intr_msix_ring(int irq, void *data)
struct alx_hw *hw = &np->alx->hw;
/* mask interrupt to ACK chip */
- alx_mask_msix(hw, 1, true);
+ alx_mask_msix(hw, np->vec_idx, true);
/* clear interrupt status */
- alx_write_mem32(hw, ALX_ISR, (ALX_ISR_TX_Q0 | ALX_ISR_RX_Q0));
+ alx_write_mem32(hw, ALX_ISR, np->vec_mask);
napi_schedule(&np->napi);
@@ -678,6 +680,13 @@ static void alx_free_napis(struct alx_priv *alx)
alx->qnapi[0] = NULL;
}
+static const u32 tx_vect_mask[] = {ALX_ISR_TX_Q0, ALX_ISR_TX_Q1,
+ ALX_ISR_TX_Q2, ALX_ISR_TX_Q3};
+static const u32 rx_vect_mask[] = {ALX_ISR_RX_Q0, ALX_ISR_RX_Q1,
+ ALX_ISR_RX_Q2, ALX_ISR_RX_Q3,
+ ALX_ISR_RX_Q4, ALX_ISR_RX_Q5,
+ ALX_ISR_RX_Q6, ALX_ISR_RX_Q7};
+
static int alx_alloc_napis(struct alx_priv *alx)
{
struct alx_napi *np;
@@ -685,7 +694,6 @@ static int alx_alloc_napis(struct alx_priv *alx)
struct alx_tx_queue *txq;
alx->int_mask &= ~ALX_ISR_ALL_QUEUES;
- alx->int_mask |= ALX_ISR_TX_Q0 | ALX_ISR_RX_Q0;
/* allocate alx_napi structures */
np = kzalloc(sizeof(struct alx_napi), GFP_KERNEL);
@@ -703,9 +711,12 @@ static int alx_alloc_napis(struct alx_priv *alx)
goto err_out;
np->txq = txq;
+ txq->queue_idx = 0;
txq->count = alx->tx_ringsz;
txq->netdev = alx->dev;
txq->dev = &alx->hw.pdev->dev;
+ np->vec_mask |= tx_vect_mask[0];
+ alx->int_mask |= tx_vect_mask[0];
/* allocate rx queues */
np = alx->qnapi[0];
@@ -715,9 +726,12 @@ static int alx_alloc_napis(struct alx_priv *alx)
np->rxq = rxq;
rxq->np = alx->qnapi[0];
+ rxq->queue_idx = 0;
rxq->count = alx->rx_ringsz;
rxq->netdev = alx->dev;
rxq->dev = &alx->hw.pdev->dev;
+ np->vec_mask |= rx_vect_mask[0];
+ alx->int_mask |= rx_vect_mask[0];
return 0;
@@ -727,24 +741,43 @@ static int alx_alloc_napis(struct alx_priv *alx)
return -ENOMEM;
}
+static const int txq_vec_mapping_shift[] = {
+ 0, ALX_MSI_MAP_TBL1_TXQ0_SHIFT,
+ 0, ALX_MSI_MAP_TBL1_TXQ1_SHIFT,
+ 1, ALX_MSI_MAP_TBL2_TXQ2_SHIFT,
+ 1, ALX_MSI_MAP_TBL2_TXQ3_SHIFT,
+};
+
static void alx_config_vector_mapping(struct alx_priv *alx)
{
struct alx_hw *hw = &alx->hw;
- u32 tbl = 0;
+ u32 tbl[2] = {0, 0};
+ int i, vector, idx, shift;
if (alx->flags & ALX_FLAG_USING_MSIX) {
- tbl |= 1 << ALX_MSI_MAP_TBL1_TXQ0_SHIFT;
- tbl |= 1 << ALX_MSI_MAP_TBL1_RXQ0_SHIFT;
+ /* tx mappings */
+ for (i = 0, vector = 1; i < alx->num_txq; i++, vector++) {
+ idx = txq_vec_mapping_shift[i * 2];
+ shift = txq_vec_mapping_shift[i * 2 + 1];
+ tbl[idx] |= vector << shift;
+ }
+
+ /* rx mapping */
+ tbl[0] |= 1 << ALX_MSI_MAP_TBL1_RXQ0_SHIFT;
}
- alx_write_mem32(hw, ALX_MSI_MAP_TBL1, tbl);
- alx_write_mem32(hw, ALX_MSI_MAP_TBL2, 0);
+ alx_write_mem32(hw, ALX_MSI_MAP_TBL1, tbl[0]);
+ alx_write_mem32(hw, ALX_MSI_MAP_TBL2, tbl[1]);
alx_write_mem32(hw, ALX_MSI_ID_MAP, 0);
}
static bool alx_enable_msix(struct alx_priv *alx)
{
- int i, err, num_vec = 2;
+ int i, err, num_vec, num_txq, num_rxq;
+
+ num_txq = 1;
+ num_rxq = 1;
+ num_vec = max_t(int, num_txq, num_rxq) + 1;
alx->msix_entries = kcalloc(num_vec, sizeof(struct msix_entry),
GFP_KERNEL);
@@ -764,6 +797,10 @@ static bool alx_enable_msix(struct alx_priv *alx)
}
alx->num_vec = num_vec;
+ alx->num_napi = num_vec - 1;
+ alx->num_txq = num_txq;
+ alx->num_rxq = num_rxq;
+
return true;
}
@@ -771,21 +808,35 @@ static int alx_request_msix(struct alx_priv *alx)
{
struct net_device *netdev = alx->dev;
int i, err, vector = 0, free_vector = 0;
- struct alx_napi *np = alx->qnapi[0];
err = request_irq(alx->msix_entries[0].vector, alx_intr_msix_misc,
0, netdev->name, alx);
if (err)
goto out_err;
- vector++;
- sprintf(np->irq_lbl, "%s-TxRx-0", netdev->name);
-
- err = request_irq(alx->msix_entries[vector].vector,
- alx_intr_msix_ring, 0, np->irq_lbl, np);
+ for (i = 0; i < alx->num_napi; i++) {
+ struct alx_napi *np = alx->qnapi[i];
+
+ vector++;
+
+ if (np->txq && np->rxq)
+ sprintf(np->irq_lbl, "%s-TxRx-%u", netdev->name,
+ np->txq->queue_idx);
+ else if (np->txq)
+ sprintf(np->irq_lbl, "%s-tx-%u", netdev->name,
+ np->txq->queue_idx);
+ else if (np->rxq)
+ sprintf(np->irq_lbl, "%s-rx-%u", netdev->name,
+ np->rxq->queue_idx);
+ else
+ sprintf(np->irq_lbl, "%s-unused", netdev->name);
+
+ np->vec_idx = vector;
+ err = request_irq(alx->msix_entries[vector].vector,
+ alx_intr_msix_ring, 0, np->irq_lbl, np);
if (err)
goto out_free;
-
+ }
return 0;
out_free:
@@ -793,7 +844,8 @@ static int alx_request_msix(struct alx_priv *alx)
vector--;
for (i = 0; i < vector; i++)
- free_irq(alx->msix_entries[free_vector++].vector, alx->qnapi[0]);
+ free_irq(alx->msix_entries[free_vector++].vector,
+ alx->qnapi[i]);
out_err:
return err;
@@ -808,6 +860,9 @@ static void alx_init_intr(struct alx_priv *alx, bool msix)
if (!(alx->flags & ALX_FLAG_USING_MSIX)) {
alx->num_vec = 1;
+ alx->num_napi = 1;
+ alx->num_txq = 1;
+ alx->num_rxq = 1;
if (!pci_enable_msi(alx->hw.pdev))
alx->flags |= ALX_FLAG_USING_MSI;
@@ -863,6 +918,25 @@ static void alx_irq_disable(struct alx_priv *alx)
}
}
+static int alx_realloc_resources(struct alx_priv *alx)
+{
+ int err;
+
+ alx_free_rings(alx);
+ alx_free_napis(alx);
+ alx_disable_advanced_intr(alx);
+
+ err = alx_alloc_napis(alx);
+ if (err)
+ return err;
+
+ err = alx_alloc_rings(alx);
+ if (err)
+ return err;
+
+ return 0;
+}
+
static int alx_request_irq(struct alx_priv *alx)
{
struct pci_dev *pdev = alx->hw.pdev;
@@ -879,8 +953,9 @@ static int alx_request_irq(struct alx_priv *alx)
goto out;
/* msix request failed, realloc resources */
- alx_disable_advanced_intr(alx);
- alx_init_intr(alx, false);
+ err = alx_realloc_resources(alx);
+ if (err)
+ goto out;
}
if (alx->flags & ALX_FLAG_USING_MSI) {
@@ -912,9 +987,10 @@ static void alx_free_irq(struct alx_priv *alx)
int i, vector = 0;
if (alx->flags & ALX_FLAG_USING_MSIX) {
- /* we have only 2 vectors without multi queue support */
free_irq(alx->msix_entries[vector++].vector, alx);
- free_irq(alx->msix_entries[vector++].vector, alx->qnapi[0]);
+ for (i = 0; i < alx->num_napi; i++)
+ free_irq(alx->msix_entries[vector++].vector,
+ alx->qnapi[i]);
} else {
free_irq(pdev->irq, alx);
}
@@ -1478,10 +1554,12 @@ static int alx_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
static void alx_poll_controller(struct net_device *netdev)
{
struct alx_priv *alx = netdev_priv(netdev);
+ int i;
if (alx->flags & ALX_FLAG_USING_MSIX) {
alx_intr_msix_misc(0, alx);
- alx_intr_msix_ring(0, alx->qnapi[0]);
+ for (i = 0; i < alx->num_txq; i++)
+ alx_intr_msix_ring(0, alx->qnapi[i]);
} else if (alx->flags & ALX_FLAG_USING_MSI)
alx_intr_msi(0, alx);
else
--
2.7.4
^ permalink raw reply related
* [PATCH net-next V2 4/9] alx: switch to per queue data structures
From: Tobias Regnery @ 2016-11-15 11:43 UTC (permalink / raw)
To: netdev, jcliburn, chris.snook; +Cc: davem, Tobias Regnery
In-Reply-To: <cover.1479208627.git.tobias.regnery@gmail.com>
Remove the tx and rx queue structures from the alx_priv structure and switch
everything over to the queue pointers in the alx_napi structure.
Based on the downstream driver at github.com/qca/alx
Signed-off-by: Tobias Regnery <tobias.regnery@gmail.com>
---
drivers/net/ethernet/atheros/alx/alx.h | 5 -
drivers/net/ethernet/atheros/alx/main.c | 183 ++++++++++++++++----------------
2 files changed, 93 insertions(+), 95 deletions(-)
diff --git a/drivers/net/ethernet/atheros/alx/alx.h b/drivers/net/ethernet/atheros/alx/alx.h
index 0859053525de..d4a409139ea2 100644
--- a/drivers/net/ethernet/atheros/alx/alx.h
+++ b/drivers/net/ethernet/atheros/alx/alx.h
@@ -113,7 +113,6 @@ struct alx_priv {
/* msi-x vectors */
int num_vec;
struct msix_entry *msix_entries;
- char irq_lbl[IFNAMSIZ + 8];
/* all descriptor memory */
struct {
@@ -135,10 +134,6 @@ struct alx_priv {
unsigned int rx_ringsz;
unsigned int rxbuf_size;
- struct napi_struct napi;
- struct alx_tx_queue txq;
- struct alx_rx_queue rxq;
-
struct work_struct link_check_wk;
struct work_struct reset_wk;
diff --git a/drivers/net/ethernet/atheros/alx/main.c b/drivers/net/ethernet/atheros/alx/main.c
index 193da6799979..a9fc44611b8a 100644
--- a/drivers/net/ethernet/atheros/alx/main.c
+++ b/drivers/net/ethernet/atheros/alx/main.c
@@ -55,12 +55,12 @@ static bool msix = false;
module_param(msix, bool, 0);
MODULE_PARM_DESC(msix, "Enable msi-x interrupt support");
-static void alx_free_txbuf(struct alx_priv *alx, int entry)
+static void alx_free_txbuf(struct alx_tx_queue *txq, int entry)
{
- struct alx_buffer *txb = &alx->txq.bufs[entry];
+ struct alx_buffer *txb = &txq->bufs[entry];
if (dma_unmap_len(txb, size)) {
- dma_unmap_single(&alx->hw.pdev->dev,
+ dma_unmap_single(txq->dev,
dma_unmap_addr(txb, dma),
dma_unmap_len(txb, size),
DMA_TO_DEVICE);
@@ -75,7 +75,7 @@ static void alx_free_txbuf(struct alx_priv *alx, int entry)
static int alx_refill_rx_ring(struct alx_priv *alx, gfp_t gfp)
{
- struct alx_rx_queue *rxq = &alx->rxq;
+ struct alx_rx_queue *rxq = alx->qnapi[0]->rxq;
struct sk_buff *skb;
struct alx_buffer *cur_buf;
dma_addr_t dma;
@@ -143,22 +143,22 @@ static int alx_refill_rx_ring(struct alx_priv *alx, gfp_t gfp)
return count;
}
-static inline int alx_tpd_avail(struct alx_priv *alx)
+static inline int alx_tpd_avail(struct alx_tx_queue *txq)
{
- struct alx_tx_queue *txq = &alx->txq;
-
if (txq->write_idx >= txq->read_idx)
- return alx->tx_ringsz + txq->read_idx - txq->write_idx - 1;
+ return txq->count + txq->read_idx - txq->write_idx - 1;
return txq->read_idx - txq->write_idx - 1;
}
-static bool alx_clean_tx_irq(struct alx_priv *alx)
+static bool alx_clean_tx_irq(struct alx_tx_queue *txq)
{
- struct alx_tx_queue *txq = &alx->txq;
+ struct alx_priv *alx;
u16 hw_read_idx, sw_read_idx;
unsigned int total_bytes = 0, total_packets = 0;
int budget = ALX_DEFAULT_TX_WORK;
+ alx = netdev_priv(txq->netdev);
+
sw_read_idx = txq->read_idx;
hw_read_idx = alx_read_mem16(&alx->hw, ALX_TPD_PRI0_CIDX);
@@ -173,19 +173,19 @@ static bool alx_clean_tx_irq(struct alx_priv *alx)
budget--;
}
- alx_free_txbuf(alx, sw_read_idx);
+ alx_free_txbuf(txq, sw_read_idx);
- if (++sw_read_idx == alx->tx_ringsz)
+ if (++sw_read_idx == txq->count)
sw_read_idx = 0;
}
txq->read_idx = sw_read_idx;
- netdev_completed_queue(alx->dev, total_packets, total_bytes);
+ netdev_completed_queue(txq->netdev, total_packets, total_bytes);
}
- if (netif_queue_stopped(alx->dev) && netif_carrier_ok(alx->dev) &&
- alx_tpd_avail(alx) > alx->tx_ringsz/4)
- netif_wake_queue(alx->dev);
+ if (netif_queue_stopped(txq->netdev) && netif_carrier_ok(txq->netdev) &&
+ alx_tpd_avail(txq) > txq->count / 4)
+ netif_wake_queue(txq->netdev);
return sw_read_idx == hw_read_idx;
}
@@ -200,15 +200,17 @@ static void alx_schedule_reset(struct alx_priv *alx)
schedule_work(&alx->reset_wk);
}
-static int alx_clean_rx_irq(struct alx_priv *alx, int budget)
+static int alx_clean_rx_irq(struct alx_rx_queue *rxq, int budget)
{
- struct alx_rx_queue *rxq = &alx->rxq;
+ struct alx_priv *alx;
struct alx_rrd *rrd;
struct alx_buffer *rxb;
struct sk_buff *skb;
u16 length, rfd_cleaned = 0;
int work = 0;
+ alx = netdev_priv(rxq->netdev);
+
while (work < budget) {
rrd = &rxq->rrd[rxq->rrd_read_idx];
if (!(rrd->word3 & cpu_to_le32(1 << RRD_UPDATED_SHIFT)))
@@ -224,7 +226,7 @@ static int alx_clean_rx_irq(struct alx_priv *alx, int budget)
}
rxb = &rxq->bufs[rxq->read_idx];
- dma_unmap_single(&alx->hw.pdev->dev,
+ dma_unmap_single(rxq->dev,
dma_unmap_addr(rxb, dma),
dma_unmap_len(rxb, size),
DMA_FROM_DEVICE);
@@ -242,7 +244,7 @@ static int alx_clean_rx_irq(struct alx_priv *alx, int budget)
length = ALX_GET_FIELD(le32_to_cpu(rrd->word3),
RRD_PKTLEN) - ETH_FCS_LEN;
skb_put(skb, length);
- skb->protocol = eth_type_trans(skb, alx->dev);
+ skb->protocol = eth_type_trans(skb, rxq->netdev);
skb_checksum_none_assert(skb);
if (alx->dev->features & NETIF_F_RXCSUM &&
@@ -259,13 +261,13 @@ static int alx_clean_rx_irq(struct alx_priv *alx, int budget)
}
}
- napi_gro_receive(&alx->napi, skb);
+ napi_gro_receive(&rxq->np->napi, skb);
work++;
next_pkt:
- if (++rxq->read_idx == alx->rx_ringsz)
+ if (++rxq->read_idx == rxq->count)
rxq->read_idx = 0;
- if (++rxq->rrd_read_idx == alx->rx_ringsz)
+ if (++rxq->rrd_read_idx == rxq->count)
rxq->rrd_read_idx = 0;
if (++rfd_cleaned > ALX_RX_ALLOC_THRESH)
@@ -280,19 +282,20 @@ static int alx_clean_rx_irq(struct alx_priv *alx, int budget)
static int alx_poll(struct napi_struct *napi, int budget)
{
- struct alx_priv *alx = container_of(napi, struct alx_priv, napi);
+ struct alx_napi *np = container_of(napi, struct alx_napi, napi);
+ struct alx_priv *alx = np->alx;
struct alx_hw *hw = &alx->hw;
unsigned long flags;
bool tx_complete;
int work;
- tx_complete = alx_clean_tx_irq(alx);
- work = alx_clean_rx_irq(alx, budget);
+ tx_complete = alx_clean_tx_irq(np->txq);
+ work = alx_clean_rx_irq(np->rxq, budget);
if (!tx_complete || work == budget)
return budget;
- napi_complete(&alx->napi);
+ napi_complete(&np->napi);
/* enable interrupt */
if (alx->flags & ALX_FLAG_USING_MSIX) {
@@ -350,7 +353,7 @@ static irqreturn_t alx_intr_handle(struct alx_priv *alx, u32 intr)
goto out;
if (intr & (ALX_ISR_TX_Q0 | ALX_ISR_RX_Q0)) {
- napi_schedule(&alx->napi);
+ napi_schedule(&alx->qnapi[0]->napi);
/* mask rx/tx interrupt, enable them when napi complete */
alx->int_mask &= ~ALX_ISR_ALL_QUEUES;
alx_write_mem32(hw, ALX_IMR, alx->int_mask);
@@ -365,15 +368,15 @@ static irqreturn_t alx_intr_handle(struct alx_priv *alx, u32 intr)
static irqreturn_t alx_intr_msix_ring(int irq, void *data)
{
- struct alx_priv *alx = data;
- struct alx_hw *hw = &alx->hw;
+ struct alx_napi *np = data;
+ struct alx_hw *hw = &np->alx->hw;
/* mask interrupt to ACK chip */
alx_mask_msix(hw, 1, true);
/* clear interrupt status */
alx_write_mem32(hw, ALX_ISR, (ALX_ISR_TX_Q0 | ALX_ISR_RX_Q0));
- napi_schedule(&alx->napi);
+ napi_schedule(&np->napi);
return IRQ_HANDLED;
}
@@ -428,59 +431,58 @@ static void alx_init_ring_ptrs(struct alx_priv *alx)
{
struct alx_hw *hw = &alx->hw;
u32 addr_hi = ((u64)alx->descmem.dma) >> 32;
+ struct alx_napi *np = alx->qnapi[0];
- alx->rxq.read_idx = 0;
- alx->rxq.write_idx = 0;
- alx->rxq.rrd_read_idx = 0;
+ np->rxq->read_idx = 0;
+ np->rxq->write_idx = 0;
+ np->rxq->rrd_read_idx = 0;
alx_write_mem32(hw, ALX_RX_BASE_ADDR_HI, addr_hi);
- alx_write_mem32(hw, ALX_RRD_ADDR_LO, alx->rxq.rrd_dma);
+ alx_write_mem32(hw, ALX_RRD_ADDR_LO, np->rxq->rrd_dma);
alx_write_mem32(hw, ALX_RRD_RING_SZ, alx->rx_ringsz);
- alx_write_mem32(hw, ALX_RFD_ADDR_LO, alx->rxq.rfd_dma);
+ alx_write_mem32(hw, ALX_RFD_ADDR_LO, np->rxq->rfd_dma);
alx_write_mem32(hw, ALX_RFD_RING_SZ, alx->rx_ringsz);
alx_write_mem32(hw, ALX_RFD_BUF_SZ, alx->rxbuf_size);
- alx->txq.read_idx = 0;
- alx->txq.write_idx = 0;
+ np->txq->read_idx = 0;
+ np->txq->write_idx = 0;
alx_write_mem32(hw, ALX_TX_BASE_ADDR_HI, addr_hi);
- alx_write_mem32(hw, ALX_TPD_PRI0_ADDR_LO, alx->txq.tpd_dma);
+ alx_write_mem32(hw, ALX_TPD_PRI0_ADDR_LO, np->txq->tpd_dma);
alx_write_mem32(hw, ALX_TPD_RING_SZ, alx->tx_ringsz);
/* load these pointers into the chip */
alx_write_mem32(hw, ALX_SRAM9, ALX_SRAM_LOAD_PTR);
}
-static void alx_free_txring_buf(struct alx_priv *alx)
+static void alx_free_txring_buf(struct alx_tx_queue *txq)
{
- struct alx_tx_queue *txq = &alx->txq;
int i;
if (!txq->bufs)
return;
- for (i = 0; i < alx->tx_ringsz; i++)
- alx_free_txbuf(alx, i);
+ for (i = 0; i < txq->count; i++)
+ alx_free_txbuf(txq, i);
- memset(txq->bufs, 0, alx->tx_ringsz * sizeof(struct alx_buffer));
- memset(txq->tpd, 0, alx->tx_ringsz * sizeof(struct alx_txd));
+ memset(txq->bufs, 0, txq->count * sizeof(struct alx_buffer));
+ memset(txq->tpd, 0, txq->count * sizeof(struct alx_txd));
txq->write_idx = 0;
txq->read_idx = 0;
- netdev_reset_queue(alx->dev);
+ netdev_reset_queue(txq->netdev);
}
-static void alx_free_rxring_buf(struct alx_priv *alx)
+static void alx_free_rxring_buf(struct alx_rx_queue *rxq)
{
- struct alx_rx_queue *rxq = &alx->rxq;
struct alx_buffer *cur_buf;
u16 i;
if (rxq == NULL)
return;
- for (i = 0; i < alx->rx_ringsz; i++) {
+ for (i = 0; i < rxq->count; i++) {
cur_buf = rxq->bufs + i;
if (cur_buf->skb) {
- dma_unmap_single(&alx->hw.pdev->dev,
+ dma_unmap_single(rxq->dev,
dma_unmap_addr(cur_buf, dma),
dma_unmap_len(cur_buf, size),
DMA_FROM_DEVICE);
@@ -498,8 +500,8 @@ static void alx_free_rxring_buf(struct alx_priv *alx)
static void alx_free_buffers(struct alx_priv *alx)
{
- alx_free_txring_buf(alx);
- alx_free_rxring_buf(alx);
+ alx_free_txring_buf(alx->qnapi[0]->txq);
+ alx_free_rxring_buf(alx->qnapi[0]->rxq);
}
static int alx_reinit_rings(struct alx_priv *alx)
@@ -576,13 +578,13 @@ static int alx_set_mac_address(struct net_device *netdev, void *data)
static int alx_alloc_tx_ring(struct alx_priv *alx, struct alx_tx_queue *txq,
int offset)
{
- txq->bufs = kcalloc(alx->tx_ringsz, sizeof(struct alx_buffer), GFP_KERNEL);
+ txq->bufs = kcalloc(txq->count, sizeof(struct alx_buffer), GFP_KERNEL);
if (!txq->bufs)
return -ENOMEM;
txq->tpd = alx->descmem.virt + offset;
txq->tpd_dma = alx->descmem.dma + offset;
- offset += sizeof(struct alx_txd) * alx->tx_ringsz;
+ offset += sizeof(struct alx_txd) * txq->count;
return offset;
}
@@ -590,17 +592,17 @@ static int alx_alloc_tx_ring(struct alx_priv *alx, struct alx_tx_queue *txq,
static int alx_alloc_rx_ring(struct alx_priv *alx, struct alx_rx_queue *rxq,
int offset)
{
- rxq->bufs = kcalloc(alx->rx_ringsz, sizeof(struct alx_buffer), GFP_KERNEL);
+ rxq->bufs = kcalloc(rxq->count, sizeof(struct alx_buffer), GFP_KERNEL);
if (!rxq->bufs)
return -ENOMEM;
rxq->rrd = alx->descmem.virt + offset;
rxq->rrd_dma = alx->descmem.dma + offset;
- offset += sizeof(struct alx_rrd) * alx->rx_ringsz;
+ offset += sizeof(struct alx_rrd) * rxq->count;
rxq->rfd = alx->descmem.virt + offset;
rxq->rfd_dma = alx->descmem.dma + offset;
- offset += sizeof(struct alx_rfd) * alx->rx_ringsz;
+ offset += sizeof(struct alx_rfd) * rxq->count;
return offset;
}
@@ -629,13 +631,13 @@ static int alx_alloc_rings(struct alx_priv *alx)
BUILD_BUG_ON(sizeof(struct alx_txd) % 8);
BUILD_BUG_ON(sizeof(struct alx_rrd) % 8);
- offset = alx_alloc_tx_ring(alx, &alx->txq, offset);
+ offset = alx_alloc_tx_ring(alx, alx->qnapi[0]->txq, offset);
if (offset < 0) {
netdev_err(alx->dev, "Allocation of tx buffer failed!\n");
return -ENOMEM;
}
- offset = alx_alloc_rx_ring(alx, &alx->rxq, offset);
+ offset = alx_alloc_rx_ring(alx, alx->qnapi[0]->rxq, offset);
if (offset < 0) {
netdev_err(alx->dev, "Allocation of rx buffer failed!\n");
return -ENOMEM;
@@ -648,10 +650,11 @@ static int alx_alloc_rings(struct alx_priv *alx)
static void alx_free_rings(struct alx_priv *alx)
{
+
alx_free_buffers(alx);
- kfree(alx->txq.bufs);
- kfree(alx->rxq.bufs);
+ kfree(alx->qnapi[0]->txq->bufs);
+ kfree(alx->qnapi[0]->rxq->bufs);
if (!alx->descmem.virt)
dma_free_coherent(&alx->hw.pdev->dev,
@@ -668,7 +671,7 @@ static void alx_free_napis(struct alx_priv *alx)
if (!np)
return;
- netif_napi_del(&alx->napi);
+ netif_napi_del(&np->napi);
kfree(np->txq);
kfree(np->rxq);
kfree(np);
@@ -690,7 +693,7 @@ static int alx_alloc_napis(struct alx_priv *alx)
goto err_out;
np->alx = alx;
- netif_napi_add(alx->dev, &alx->napi, alx_poll, 64);
+ netif_napi_add(alx->dev, &np->napi, alx_poll, 64);
alx->qnapi[0] = np;
/* allocate tx queues */
@@ -768,6 +771,7 @@ static int alx_request_msix(struct alx_priv *alx)
{
struct net_device *netdev = alx->dev;
int i, err, vector = 0, free_vector = 0;
+ struct alx_napi *np = alx->qnapi[0];
err = request_irq(alx->msix_entries[0].vector, alx_intr_msix_misc,
0, netdev->name, alx);
@@ -775,10 +779,10 @@ static int alx_request_msix(struct alx_priv *alx)
goto out_err;
vector++;
- sprintf(alx->irq_lbl, "%s-TxRx-0", netdev->name);
+ sprintf(np->irq_lbl, "%s-TxRx-0", netdev->name);
err = request_irq(alx->msix_entries[vector].vector,
- alx_intr_msix_ring, 0, alx->irq_lbl, alx);
+ alx_intr_msix_ring, 0, np->irq_lbl, np);
if (err)
goto out_free;
@@ -789,7 +793,7 @@ static int alx_request_msix(struct alx_priv *alx)
vector--;
for (i = 0; i < vector; i++)
- free_irq(alx->msix_entries[free_vector++].vector, alx);
+ free_irq(alx->msix_entries[free_vector++].vector, alx->qnapi[0]);
out_err:
return err;
@@ -905,12 +909,12 @@ static int alx_request_irq(struct alx_priv *alx)
static void alx_free_irq(struct alx_priv *alx)
{
struct pci_dev *pdev = alx->hw.pdev;
- int i;
+ int i, vector = 0;
if (alx->flags & ALX_FLAG_USING_MSIX) {
/* we have only 2 vectors without multi queue support */
- for (i = 0; i < 2; i++)
- free_irq(alx->msix_entries[i].vector, alx);
+ free_irq(alx->msix_entries[vector++].vector, alx);
+ free_irq(alx->msix_entries[vector++].vector, alx->qnapi[0]);
} else {
free_irq(pdev->irq, alx);
}
@@ -999,7 +1003,7 @@ static void alx_netif_stop(struct alx_priv *alx)
if (netif_carrier_ok(alx->dev)) {
netif_carrier_off(alx->dev);
netif_tx_disable(alx->dev);
- napi_disable(&alx->napi);
+ napi_disable(&alx->qnapi[0]->napi);
}
}
@@ -1069,7 +1073,7 @@ static int alx_change_mtu(struct net_device *netdev, int mtu)
static void alx_netif_start(struct alx_priv *alx)
{
netif_tx_wake_all_queues(alx->dev);
- napi_enable(&alx->napi);
+ napi_enable(&alx->qnapi[0]->napi);
netif_carrier_on(alx->dev);
}
@@ -1303,9 +1307,8 @@ static int alx_tso(struct sk_buff *skb, struct alx_txd *first)
return 1;
}
-static int alx_map_tx_skb(struct alx_priv *alx, struct sk_buff *skb)
+static int alx_map_tx_skb(struct alx_tx_queue *txq, struct sk_buff *skb)
{
- struct alx_tx_queue *txq = &alx->txq;
struct alx_txd *tpd, *first_tpd;
dma_addr_t dma;
int maplen, f, first_idx = txq->write_idx;
@@ -1314,7 +1317,7 @@ static int alx_map_tx_skb(struct alx_priv *alx, struct sk_buff *skb)
tpd = first_tpd;
if (tpd->word1 & (1 << TPD_LSO_V2_SHIFT)) {
- if (++txq->write_idx == alx->tx_ringsz)
+ if (++txq->write_idx == txq->count)
txq->write_idx = 0;
tpd = &txq->tpd[txq->write_idx];
@@ -1324,9 +1327,9 @@ static int alx_map_tx_skb(struct alx_priv *alx, struct sk_buff *skb)
}
maplen = skb_headlen(skb);
- dma = dma_map_single(&alx->hw.pdev->dev, skb->data, maplen,
+ dma = dma_map_single(txq->dev, skb->data, maplen,
DMA_TO_DEVICE);
- if (dma_mapping_error(&alx->hw.pdev->dev, dma))
+ if (dma_mapping_error(txq->dev, dma))
goto err_dma;
dma_unmap_len_set(&txq->bufs[txq->write_idx], size, maplen);
@@ -1340,16 +1343,16 @@ static int alx_map_tx_skb(struct alx_priv *alx, struct sk_buff *skb)
frag = &skb_shinfo(skb)->frags[f];
- if (++txq->write_idx == alx->tx_ringsz)
+ if (++txq->write_idx == txq->count)
txq->write_idx = 0;
tpd = &txq->tpd[txq->write_idx];
tpd->word1 = first_tpd->word1;
maplen = skb_frag_size(frag);
- dma = skb_frag_dma_map(&alx->hw.pdev->dev, frag, 0,
+ dma = skb_frag_dma_map(txq->dev, frag, 0,
maplen, DMA_TO_DEVICE);
- if (dma_mapping_error(&alx->hw.pdev->dev, dma))
+ if (dma_mapping_error(txq->dev, dma))
goto err_dma;
dma_unmap_len_set(&txq->bufs[txq->write_idx], size, maplen);
dma_unmap_addr_set(&txq->bufs[txq->write_idx], dma, dma);
@@ -1362,7 +1365,7 @@ static int alx_map_tx_skb(struct alx_priv *alx, struct sk_buff *skb)
tpd->word1 |= cpu_to_le32(1 << TPD_EOP_SHIFT);
txq->bufs[txq->write_idx].skb = skb;
- if (++txq->write_idx == alx->tx_ringsz)
+ if (++txq->write_idx == txq->count)
txq->write_idx = 0;
return 0;
@@ -1370,8 +1373,8 @@ static int alx_map_tx_skb(struct alx_priv *alx, struct sk_buff *skb)
err_dma:
f = first_idx;
while (f != txq->write_idx) {
- alx_free_txbuf(alx, f);
- if (++f == alx->tx_ringsz)
+ alx_free_txbuf(txq, f);
+ if (++f == txq->count)
f = 0;
}
return -ENOMEM;
@@ -1381,12 +1384,12 @@ static netdev_tx_t alx_start_xmit(struct sk_buff *skb,
struct net_device *netdev)
{
struct alx_priv *alx = netdev_priv(netdev);
- struct alx_tx_queue *txq = &alx->txq;
+ struct alx_tx_queue *txq = alx->qnapi[0]->txq;
struct alx_txd *first;
int tso;
- if (alx_tpd_avail(alx) < alx_tpd_req(skb)) {
- netif_stop_queue(alx->dev);
+ if (alx_tpd_avail(txq) < alx_tpd_req(skb)) {
+ netif_stop_queue(txq->netdev);
goto drop;
}
@@ -1399,17 +1402,17 @@ static netdev_tx_t alx_start_xmit(struct sk_buff *skb,
else if (!tso && alx_tx_csum(skb, first))
goto drop;
- if (alx_map_tx_skb(alx, skb) < 0)
+ if (alx_map_tx_skb(txq, skb) < 0)
goto drop;
- netdev_sent_queue(alx->dev, skb->len);
+ netdev_sent_queue(txq->netdev, skb->len);
/* flush updates before updating hardware */
wmb();
alx_write_mem16(&alx->hw, ALX_TPD_PRI0_PIDX, txq->write_idx);
- if (alx_tpd_avail(alx) < alx->tx_ringsz/8)
- netif_stop_queue(alx->dev);
+ if (alx_tpd_avail(txq) < txq->count / 8)
+ netif_stop_queue(txq->netdev);
return NETDEV_TX_OK;
@@ -1478,7 +1481,7 @@ static void alx_poll_controller(struct net_device *netdev)
if (alx->flags & ALX_FLAG_USING_MSIX) {
alx_intr_msix_misc(0, alx);
- alx_intr_msix_ring(0, alx);
+ alx_intr_msix_ring(0, alx->qnapi[0]);
} else if (alx->flags & ALX_FLAG_USING_MSI)
alx_intr_msi(0, alx);
else
--
2.7.4
^ permalink raw reply related
* [PATCH net-next V2 3/9] alx: add ability to allocate and free alx_napi structures
From: Tobias Regnery @ 2016-11-15 11:43 UTC (permalink / raw)
To: netdev, jcliburn, chris.snook; +Cc: davem, Tobias Regnery
In-Reply-To: <cover.1479208627.git.tobias.regnery@gmail.com>
Add new functions to allocate and free the alx_napi structures and use them
in __alx_open and __alx_stop. We only allocate one of these structures for
now, as the rest of the driver is not yet ready for multiple queues.
We switch over the setup of the interrupt mask and the call to netif_napi_add
to the new function because we must adjust these later on a per queue basis.
Based on the downstream driver at github.com/qca/alx
Signed-off-by: Tobias Regnery <tobias.regnery@gmail.com>
---
drivers/net/ethernet/atheros/alx/main.c | 99 ++++++++++++++++++++++++++-------
1 file changed, 78 insertions(+), 21 deletions(-)
diff --git a/drivers/net/ethernet/atheros/alx/main.c b/drivers/net/ethernet/atheros/alx/main.c
index 8935766829b1..193da6799979 100644
--- a/drivers/net/ethernet/atheros/alx/main.c
+++ b/drivers/net/ethernet/atheros/alx/main.c
@@ -632,45 +632,96 @@ static int alx_alloc_rings(struct alx_priv *alx)
offset = alx_alloc_tx_ring(alx, &alx->txq, offset);
if (offset < 0) {
netdev_err(alx->dev, "Allocation of tx buffer failed!\n");
- goto out_free;
+ return -ENOMEM;
}
offset = alx_alloc_rx_ring(alx, &alx->rxq, offset);
if (offset < 0) {
netdev_err(alx->dev, "Allocation of rx buffer failed!\n");
- goto out_free;
+ return -ENOMEM;
}
- alx->int_mask &= ~ALX_ISR_ALL_QUEUES;
- alx->int_mask |= ALX_ISR_TX_Q0 | ALX_ISR_RX_Q0;
-
- netif_napi_add(alx->dev, &alx->napi, alx_poll, 64);
-
alx_reinit_rings(alx);
return 0;
-out_free:
- kfree(alx->txq.bufs);
- kfree(alx->rxq.bufs);
- dma_free_coherent(&alx->hw.pdev->dev,
- alx->descmem.size,
- alx->descmem.virt,
- alx->descmem.dma);
- return -ENOMEM;
}
static void alx_free_rings(struct alx_priv *alx)
{
- netif_napi_del(&alx->napi);
alx_free_buffers(alx);
kfree(alx->txq.bufs);
kfree(alx->rxq.bufs);
- dma_free_coherent(&alx->hw.pdev->dev,
- alx->descmem.size,
- alx->descmem.virt,
- alx->descmem.dma);
+ if (!alx->descmem.virt)
+ dma_free_coherent(&alx->hw.pdev->dev,
+ alx->descmem.size,
+ alx->descmem.virt,
+ alx->descmem.dma);
+}
+
+static void alx_free_napis(struct alx_priv *alx)
+{
+ struct alx_napi *np;
+
+ np = alx->qnapi[0];
+ if (!np)
+ return;
+
+ netif_napi_del(&alx->napi);
+ kfree(np->txq);
+ kfree(np->rxq);
+ kfree(np);
+ alx->qnapi[0] = NULL;
+}
+
+static int alx_alloc_napis(struct alx_priv *alx)
+{
+ struct alx_napi *np;
+ struct alx_rx_queue *rxq;
+ struct alx_tx_queue *txq;
+
+ alx->int_mask &= ~ALX_ISR_ALL_QUEUES;
+ alx->int_mask |= ALX_ISR_TX_Q0 | ALX_ISR_RX_Q0;
+
+ /* allocate alx_napi structures */
+ np = kzalloc(sizeof(struct alx_napi), GFP_KERNEL);
+ if (!np)
+ goto err_out;
+
+ np->alx = alx;
+ netif_napi_add(alx->dev, &alx->napi, alx_poll, 64);
+ alx->qnapi[0] = np;
+
+ /* allocate tx queues */
+ np = alx->qnapi[0];
+ txq = kzalloc(sizeof(*txq), GFP_KERNEL);
+ if (!txq)
+ goto err_out;
+
+ np->txq = txq;
+ txq->count = alx->tx_ringsz;
+ txq->netdev = alx->dev;
+ txq->dev = &alx->hw.pdev->dev;
+
+ /* allocate rx queues */
+ np = alx->qnapi[0];
+ rxq = kzalloc(sizeof(*rxq), GFP_KERNEL);
+ if (!rxq)
+ goto err_out;
+
+ np->rxq = rxq;
+ rxq->np = alx->qnapi[0];
+ rxq->count = alx->rx_ringsz;
+ rxq->netdev = alx->dev;
+ rxq->dev = &alx->hw.pdev->dev;
+
+ return 0;
+
+err_out:
+ netdev_err(alx->dev, "error allocating internal structures\n");
+ alx_free_napis(alx);
+ return -ENOMEM;
}
static void alx_config_vector_mapping(struct alx_priv *alx)
@@ -1031,10 +1082,14 @@ static int __alx_open(struct alx_priv *alx, bool resume)
if (!resume)
netif_carrier_off(alx->dev);
- err = alx_alloc_rings(alx);
+ err = alx_alloc_napis(alx);
if (err)
goto out_disable_adv_intr;
+ err = alx_alloc_rings(alx);
+ if (err)
+ goto out_free_rings;
+
alx_configure(alx);
err = alx_request_irq(alx);
@@ -1054,6 +1109,7 @@ static int __alx_open(struct alx_priv *alx, bool resume)
out_free_rings:
alx_free_rings(alx);
+ alx_free_napis(alx);
out_disable_adv_intr:
alx_disable_advanced_intr(alx);
return err;
@@ -1064,6 +1120,7 @@ static void __alx_stop(struct alx_priv *alx)
alx_halt(alx);
alx_free_irq(alx);
alx_free_rings(alx);
+ alx_free_napis(alx);
}
static const char *alx_speed_desc(struct alx_hw *hw)
--
2.7.4
^ permalink raw reply related
* [PATCH net-next V2 2/9] alx: extend data structures for multi queue support
From: Tobias Regnery @ 2016-11-15 11:43 UTC (permalink / raw)
To: netdev, jcliburn, chris.snook; +Cc: davem, Tobias Regnery
In-Reply-To: <cover.1479208627.git.tobias.regnery@gmail.com>
Extend the driver data structures to be able to handle multiple queues.
Based on the downstream driver at github.com/qca/alx
Signed-off-by: Tobias Regnery <tobias.regnery@gmail.com>
---
drivers/net/ethernet/atheros/alx/alx.h | 31 +++++++++++++++++++++++++++++++
1 file changed, 31 insertions(+)
diff --git a/drivers/net/ethernet/atheros/alx/alx.h b/drivers/net/ethernet/atheros/alx/alx.h
index 6cac919272ea..0859053525de 100644
--- a/drivers/net/ethernet/atheros/alx/alx.h
+++ b/drivers/net/ethernet/atheros/alx/alx.h
@@ -50,6 +50,10 @@ struct alx_buffer {
};
struct alx_rx_queue {
+ struct net_device *netdev;
+ struct device *dev;
+ struct alx_napi *np;
+
struct alx_rrd *rrd;
dma_addr_t rrd_dma;
@@ -58,16 +62,26 @@ struct alx_rx_queue {
struct alx_buffer *bufs;
+ u16 count;
u16 write_idx, read_idx;
u16 rrd_read_idx;
+ u16 queue_idx;
};
#define ALX_RX_ALLOC_THRESH 32
struct alx_tx_queue {
+ struct net_device *netdev;
+ struct device *dev;
+
struct alx_txd *tpd;
dma_addr_t tpd_dma;
+
struct alx_buffer *bufs;
+
+ u16 count;
u16 write_idx, read_idx;
+ u16 queue_idx;
+ u16 p_reg, c_reg;
};
#define ALX_DEFAULT_TX_WORK 128
@@ -76,6 +90,18 @@ enum alx_device_quirks {
ALX_DEV_QUIRK_MSI_INTX_DISABLE_BUG = BIT(0),
};
+struct alx_napi {
+ struct napi_struct napi;
+ struct alx_priv *alx;
+ struct alx_rx_queue *rxq;
+ struct alx_tx_queue *txq;
+ int vec_idx;
+ u32 vec_mask;
+ char irq_lbl[IFNAMSIZ + 8];
+};
+
+#define ALX_MAX_NAPIS 8
+
#define ALX_FLAG_USING_MSIX BIT(0)
#define ALX_FLAG_USING_MSI BIT(1)
@@ -96,6 +122,11 @@ struct alx_priv {
unsigned int size;
} descmem;
+ struct alx_napi *qnapi[ALX_MAX_NAPIS];
+ int num_txq;
+ int num_rxq;
+ int num_napi;
+
/* protect int_mask updates */
spinlock_t irq_lock;
u32 int_mask;
--
2.7.4
^ permalink raw reply related
* [PATCH net-next V2 1/9] alx: refactor descriptor allocation
From: Tobias Regnery @ 2016-11-15 11:43 UTC (permalink / raw)
To: netdev, jcliburn, chris.snook; +Cc: davem, Tobias Regnery
In-Reply-To: <cover.1479208627.git.tobias.regnery@gmail.com>
Split the allocation of descriptor memory and the buffer allocation into a
tx and rx function. This is in preparation for multiple queues where we
need to iterate over the new functions.
While at it drop the unneeded casting on the rx side.
Signed-off-by: Tobias Regnery <tobias.regnery@gmail.com>
---
drivers/net/ethernet/atheros/alx/main.c | 97 ++++++++++++++++++---------------
1 file changed, 53 insertions(+), 44 deletions(-)
diff --git a/drivers/net/ethernet/atheros/alx/main.c b/drivers/net/ethernet/atheros/alx/main.c
index eccbacd96201..8935766829b1 100644
--- a/drivers/net/ethernet/atheros/alx/main.c
+++ b/drivers/net/ethernet/atheros/alx/main.c
@@ -573,19 +573,41 @@ static int alx_set_mac_address(struct net_device *netdev, void *data)
return 0;
}
-static int alx_alloc_descriptors(struct alx_priv *alx)
+static int alx_alloc_tx_ring(struct alx_priv *alx, struct alx_tx_queue *txq,
+ int offset)
{
- alx->txq.bufs = kcalloc(alx->tx_ringsz,
- sizeof(struct alx_buffer),
- GFP_KERNEL);
- if (!alx->txq.bufs)
+ txq->bufs = kcalloc(alx->tx_ringsz, sizeof(struct alx_buffer), GFP_KERNEL);
+ if (!txq->bufs)
return -ENOMEM;
- alx->rxq.bufs = kcalloc(alx->rx_ringsz,
- sizeof(struct alx_buffer),
- GFP_KERNEL);
- if (!alx->rxq.bufs)
- goto out_free;
+ txq->tpd = alx->descmem.virt + offset;
+ txq->tpd_dma = alx->descmem.dma + offset;
+ offset += sizeof(struct alx_txd) * alx->tx_ringsz;
+
+ return offset;
+}
+
+static int alx_alloc_rx_ring(struct alx_priv *alx, struct alx_rx_queue *rxq,
+ int offset)
+{
+ rxq->bufs = kcalloc(alx->rx_ringsz, sizeof(struct alx_buffer), GFP_KERNEL);
+ if (!rxq->bufs)
+ return -ENOMEM;
+
+ rxq->rrd = alx->descmem.virt + offset;
+ rxq->rrd_dma = alx->descmem.dma + offset;
+ offset += sizeof(struct alx_rrd) * alx->rx_ringsz;
+
+ rxq->rfd = alx->descmem.virt + offset;
+ rxq->rfd_dma = alx->descmem.dma + offset;
+ offset += sizeof(struct alx_rfd) * alx->rx_ringsz;
+
+ return offset;
+}
+
+static int alx_alloc_rings(struct alx_priv *alx)
+{
+ int offset = 0;
/* physical tx/rx ring descriptors
*
@@ -601,45 +623,23 @@ static int alx_alloc_descriptors(struct alx_priv *alx)
&alx->descmem.dma,
GFP_KERNEL);
if (!alx->descmem.virt)
- goto out_free;
-
- alx->txq.tpd = alx->descmem.virt;
- alx->txq.tpd_dma = alx->descmem.dma;
+ return -ENOMEM;
- /* alignment requirement for next block */
+ /* alignment requirements */
BUILD_BUG_ON(sizeof(struct alx_txd) % 8);
-
- alx->rxq.rrd =
- (void *)((u8 *)alx->descmem.virt +
- sizeof(struct alx_txd) * alx->tx_ringsz);
- alx->rxq.rrd_dma = alx->descmem.dma +
- sizeof(struct alx_txd) * alx->tx_ringsz;
-
- /* alignment requirement for next block */
BUILD_BUG_ON(sizeof(struct alx_rrd) % 8);
- alx->rxq.rfd =
- (void *)((u8 *)alx->descmem.virt +
- sizeof(struct alx_txd) * alx->tx_ringsz +
- sizeof(struct alx_rrd) * alx->rx_ringsz);
- alx->rxq.rfd_dma = alx->descmem.dma +
- sizeof(struct alx_txd) * alx->tx_ringsz +
- sizeof(struct alx_rrd) * alx->rx_ringsz;
-
- return 0;
-out_free:
- kfree(alx->txq.bufs);
- kfree(alx->rxq.bufs);
- return -ENOMEM;
-}
-
-static int alx_alloc_rings(struct alx_priv *alx)
-{
- int err;
+ offset = alx_alloc_tx_ring(alx, &alx->txq, offset);
+ if (offset < 0) {
+ netdev_err(alx->dev, "Allocation of tx buffer failed!\n");
+ goto out_free;
+ }
- err = alx_alloc_descriptors(alx);
- if (err)
- return err;
+ offset = alx_alloc_rx_ring(alx, &alx->rxq, offset);
+ if (offset < 0) {
+ netdev_err(alx->dev, "Allocation of rx buffer failed!\n");
+ goto out_free;
+ }
alx->int_mask &= ~ALX_ISR_ALL_QUEUES;
alx->int_mask |= ALX_ISR_TX_Q0 | ALX_ISR_RX_Q0;
@@ -647,7 +647,16 @@ static int alx_alloc_rings(struct alx_priv *alx)
netif_napi_add(alx->dev, &alx->napi, alx_poll, 64);
alx_reinit_rings(alx);
+
return 0;
+out_free:
+ kfree(alx->txq.bufs);
+ kfree(alx->rxq.bufs);
+ dma_free_coherent(&alx->hw.pdev->dev,
+ alx->descmem.size,
+ alx->descmem.virt,
+ alx->descmem.dma);
+ return -ENOMEM;
}
static void alx_free_rings(struct alx_priv *alx)
--
2.7.4
^ permalink raw reply related
* [PATCH net-next V2 0/9] alx: add multi queue support
From: Tobias Regnery @ 2016-11-15 11:43 UTC (permalink / raw)
To: netdev, jcliburn, chris.snook; +Cc: davem, Tobias Regnery
This patchset lays the groundwork for multi queue support in the alx driver
and enables multi queue support for the tx path by default. The hardware
supports up to 4 tx queues.
Benefits are better utilization of multi core cpus and the usage of the
msi-x support by default which splits the handling of rx / tx and misc
other interrupts.
The rx path is a little bit harder because apparently (based on the limited
information from the downstream driver) the hardware supports up to 8 rss
queues but only has one hardware descriptor ring on the rx side. So the rx
path will be part of another patchset.
Tested on my AR8161 ethernet adapter with different tests:
- there are no regressions observed during my daily usage
- iperf tcp and udp tests shows no performance regressions
- netperf TCP_RR and UDP_RR shows a slight performance increase of about
1-2% with this patchset applied
This work is based on the downstream driver at github.com/qca/alx
Changes in V2:
- drop unneeded casts in alx_alloc_rx_ring (Patch 1)
- add additional information about testing and benefit to the
changelog
Tobias Regnery (9):
alx: refactor descriptor allocation
alx: extend data structures for multi queue support
alx: add ability to allocate and free alx_napi structures
alx: switch to per queue data structures
alx: prepare interrupt functions for multiple queues
alx: prepare resource allocation for multi queue support
alx: prepare tx path for multi queue support
alx: enable msi-x interrupts by default
alx: enable multiple tx queues
drivers/net/ethernet/atheros/alx/alx.h | 36 ++-
drivers/net/ethernet/atheros/alx/main.c | 554 ++++++++++++++++++++++----------
2 files changed, 420 insertions(+), 170 deletions(-)
--
2.7.4
^ permalink raw reply
* Re: stmmac/RTL8211F/Meson GXBB: TX throughput problems
From: Jerome Brunet @ 2016-11-15 11:27 UTC (permalink / raw)
To: Andreas Färber, Martin Blumenstingl
Cc: Giuseppe CAVALLARO, Alexandre Torgue, netdev, André Roth,
Johnson Leung, linux-amlogic
In-Reply-To: <24b4d9b3-0a9d-5f6c-7dc2-5fcbb1012481@suse.de>
On Mon, 2016-11-14 at 16:00 +0100, Andreas Färber wrote:
> Hi,
>
> Am 07.11.2016 um 18:37 schrieb Martin Blumenstingl:
> >
> > The same problem still appears on my Tronsmart Vega S95 Meta even
> > with
> > the patched PHY driver.
> >
> > Unfortunately I don't have a second device to rule out that my
> > Tronsmart Vega S95 Meta could be broken (not unlikely, I get DDR
> > errors from time to time in u-boot). Maybe Andreas Faerber can test
> > ethernet with and without Jerome's patch on one of his Tronsmart
> > devices.
>
> So far I only ran into the stall issue on my Odroid-C2, not on my
> Vega
> S95 Telos, both on v4.10/integ branch with a rebased MMC patch of
> yours
> on top.
The status of vega/mxq boards seems a bit confused.
This is the status I have so far:
These designs are not affected by the EEE issue. The patch mentioned
has no effect on these boards.
Some boards run fine at GBit speed (like yours) , some have terrible Tx
throughput (like mine and Martin's one). However, unlike on the
odroidc2, the link is not broken after the test, it is not necessary to
ifdown/ifup the interface to do another test.
I'm wondering if the vega/mxq designs all use the rtl8211f phy ?
>
> I'm assuming you mean realtek8211f-disable-eee-1000.patch from Nov 3.
>
Indeed. I won't submit anything for the vega since it has no effect.
> Regards,
> Andreas
>
^ permalink raw reply
* Re: [PATCH v9 0/8] thunderbolt: Introducing Thunderbolt(TM) Networking
From: Simon Guinot @ 2016-11-15 10:59 UTC (permalink / raw)
To: Levy, Amir (Jer)
Cc: gregkh@linuxfoundation.org, andreas.noever@gmail.com,
bhelgaas@google.com, corbet@lwn.net, linux-kernel@vger.kernel.org,
linux-pci@vger.kernel.org, netdev@vger.kernel.org,
linux-doc@vger.kernel.org, mario_limonciello@dell.com,
thunderbolt-linux, Westerberg, Mika, Winkler, Tomas,
Zhang, Xiong Y, Jamet, Michael, remi.rerolle
In-Reply-To: <E607265CB020454880711A6F96C05A03B677E4C9@hasmsx107.ger.corp.intel.com>
[-- Attachment #1: Type: text/plain, Size: 4442 bytes --]
On Wed, Nov 09, 2016 at 03:42:53PM +0000, Levy, Amir (Jer) wrote:
> On Wed, Nov 9 2016, 04:36 PM, Simon Guinot wrote:
> > On Wed, Nov 09, 2016 at 04:20:00PM +0200, Amir Levy wrote:
> > > This driver enables Thunderbolt Networking on non-Apple platforms
> > > running Linux.
> > >
> > > Thunderbolt Networking provides peer-to-peer connections to transfer
> > > files between computers, perform PC migrations, and/or set up small
> > > workgroups with shared storage.
> > >
> > > This is a virtual connection that emulates an Ethernet adapter that
> > > enables Ethernet networking with the benefit of Thunderbolt
> > > superfast medium capability.
> > >
> > > Thunderbolt Networking enables two hosts and several devices that
> > > have a Thunderbolt controller to be connected together in a linear
> > > (Daisy
> > > chain) series from a single port.
> > >
> > > Thunderbolt Networking for Linux is compatible with Thunderbolt
> > > Networking on systems running macOS or Windows and also supports
> > > Thunderbolt generation 2 and 3 controllers.
> > >
> > > Note that all pre-existing Thunderbolt generation 3 features, such
> > > as USB, Display and other Thunderbolt device connectivity will
> > > continue to function exactly as they did prior to enabling Thunderbolt Networking.
> > >
> > > Code and Software Specifications:
> > > This kernel code creates a virtual ethernet device for computer to
> > > computer communication over a Thunderbolt cable.
> > > The new driver is a separate driver to the existing Thunderbolt driver.
> > > It is designed to work on systems running Linux that interface with
> > > Intel Connection Manager (ICM) firmware based Thunderbolt
> > > controllers that support Thunderbolt Networking.
> > > The kernel code operates in coordination with the Thunderbolt user-
> > > space daemon to implement full Thunderbolt networking functionality.
> > >
> > > Hardware Specifications:
> > > Thunderbolt Hardware specs have not yet been published but are used
> > > where necessary for register definitions.
> >
> > Hi Amir,
> >
> > I have an ASUS "All Series/Z87-DELUXE/QUAD" motherboard with a
> > Thunderbolt 2 "Falcon Ridge" chipset (device ID 156d).
> >
> > Is the thunderbolt-icm driver supposed to work with this chipset ?
> >
>
> Yes, the thunderbolt-icm supports Falcon Ridge, device ID 156c.
> 156d is the bridge - http://lxr.free-electrons.com/source/include/linux/pci_ids.h#L2619
>
> > I have installed both a 4.8.6 Linux kernel (patched with your v9
> > series) and the thunderbolt-software-daemon (27 october release)
> > inside a Debian system (Jessie).
> >
> > If I connect the ASUS motherboard with a MacBook Pro (Thunderbolt 2,
> > device ID 156c), I can see that the thunderbolt-icm driver is loaded
> > and that the thunderbolt-software-daemon is well started. But the
> > Ethernet interface is not created.
> >
> > I have attached to this email the syslog file. There is the logs from
> > both the kernel and the daemon inside. Note that the daemon logs are
> > everything but clear about what could be the issue. Maybe I missed
> > some kind of configuration ? But I failed to find any valuable
> > information about configuring the driver and/or the daemon in the various documentation files.
> >
> > Please, can you provide some guidance ? I'd really like to test your
> > patch series.
>
> First, thank you very much for willing to test it.
> Thunderbolt Networking support was added during Falcon Ridge, in the latest FR images.
> Do you know which Thunderbolt image version you have on your system?
> Currently I submitted only Thunderbolt Networking feature in Linux, and we plan to add
> more features like reading the image version and updating the image.
> If you don't know the image version, the only thing I can suggest is to load windows, install thunderbolt SW
> and check in the Thunderbolt application the image version.
> To know if image update is needed, you can check - https://thunderbolttechnology.net/updates
Hi Amir,
From the Windows Thunderbolt software, I can read 13.00 for the firmware
version. And from https://thunderbolttechnology.net/updates, I can see
that there is no update available for my ASUS motherboard.
Am I good to go ?
BTW, it is quite a shame that the Thunderbolt firmware version can't be
read from Linux.
Simon
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 181 bytes --]
^ permalink raw reply
* RE: [PATCH 20/39] netfilter: ipset: Use kmalloc() in comment extension helper
From: David Laight @ 2016-11-15 10:48 UTC (permalink / raw)
To: 'Pablo Neira Ayuso', netfilter-devel@vger.kernel.org
Cc: davem@davemloft.net, netdev@vger.kernel.org
In-Reply-To: <1479075933-4491-21-git-send-email-pablo@netfilter.org>
From: Pablo Neira Ayuso
> Sent: 13 November 2016 22:25
> Allocate memory with kmalloc() rather than kzalloc(): the string
> is immediately initialized so it is unnecessary to zero out
> the allocated memory area.
>
> Ported from a patch proposed by Sergey Popovich <popovich_sergei@mail.ua>.
>
> Suggested-by: Sergey Popovich <popovich_sergei@mail.ua>
> Signed-off-by: Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
> ---
> include/linux/netfilter/ipset/ip_set_comment.h | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/include/linux/netfilter/ipset/ip_set_comment.h
> b/include/linux/netfilter/ipset/ip_set_comment.h
> index bae5c7609be2..5444b1bbe656 100644
> --- a/include/linux/netfilter/ipset/ip_set_comment.h
> +++ b/include/linux/netfilter/ipset/ip_set_comment.h
> @@ -34,7 +34,7 @@ ip_set_init_comment(struct ip_set_comment *comment,
> return;
> if (unlikely(len > IPSET_MAX_COMMENT_SIZE))
> len = IPSET_MAX_COMMENT_SIZE;
> - c = kzalloc(sizeof(*c) + len + 1, GFP_ATOMIC);
> + c = kmalloc(sizeof(*c) + len + 1, GFP_ATOMIC);
> if (unlikely(!c))
> return;
> strlcpy(c->str, ext->comment, len + 1);
I think I'd do a memcpy() and zero the last byte.
Note that any other parts of 'c->' are no longer zeroed by this code fragment.
David
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox