* [PATCH] net: dsa: slave: use new api ethtool_{get|set}_link_ksettings
From: Philippe Reynes @ 2016-10-09 15:00 UTC (permalink / raw)
To: andrew, vivien.didelot, f.fainelli, davem
Cc: netdev, linux-kernel, Philippe Reynes
The ethtool api {get|set}_settings is deprecated.
We move this driver to new api {get|set}_link_ksettings.
Signed-off-by: Philippe Reynes <tremyfr@gmail.com>
---
net/dsa/slave.c | 14 ++++++++------
1 files changed, 8 insertions(+), 6 deletions(-)
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index 6b1282c..68714a5 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -641,7 +641,8 @@ static netdev_tx_t dsa_slave_xmit(struct sk_buff *skb, struct net_device *dev)
/* ethtool operations *******************************************************/
static int
-dsa_slave_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+dsa_slave_get_link_ksettings(struct net_device *dev,
+ struct ethtool_link_ksettings *cmd)
{
struct dsa_slave_priv *p = netdev_priv(dev);
int err;
@@ -650,19 +651,20 @@ dsa_slave_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
if (p->phy != NULL) {
err = phy_read_status(p->phy);
if (err == 0)
- err = phy_ethtool_gset(p->phy, cmd);
+ err = phy_ethtool_ksettings_get(p->phy, cmd);
}
return err;
}
static int
-dsa_slave_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+dsa_slave_set_link_ksettings(struct net_device *dev,
+ const struct ethtool_link_ksettings *cmd)
{
struct dsa_slave_priv *p = netdev_priv(dev);
if (p->phy != NULL)
- return phy_ethtool_sset(p->phy, cmd);
+ return phy_ethtool_ksettings_set(p->phy, cmd);
return -EOPNOTSUPP;
}
@@ -990,8 +992,6 @@ void dsa_cpu_port_ethtool_init(struct ethtool_ops *ops)
}
static const struct ethtool_ops dsa_slave_ethtool_ops = {
- .get_settings = dsa_slave_get_settings,
- .set_settings = dsa_slave_set_settings,
.get_drvinfo = dsa_slave_get_drvinfo,
.get_regs_len = dsa_slave_get_regs_len,
.get_regs = dsa_slave_get_regs,
@@ -1007,6 +1007,8 @@ static const struct ethtool_ops dsa_slave_ethtool_ops = {
.get_wol = dsa_slave_get_wol,
.set_eee = dsa_slave_set_eee,
.get_eee = dsa_slave_get_eee,
+ .get_link_ksettings = dsa_slave_get_link_ksettings,
+ .set_link_ksettings = dsa_slave_set_link_ksettings,
};
static const struct net_device_ops dsa_slave_netdev_ops = {
--
1.7.4.4
^ permalink raw reply related
* [PATCH net-next 4/6] qed*: Allow unicast filtering
From: Yuval Mintz @ 2016-10-09 15:25 UTC (permalink / raw)
To: davem, netdev; +Cc: Yuval Mintz
In-Reply-To: <1476026738-26069-1-git-send-email-Yuval.Mintz@qlogic.com>
From: Yuval Mintz <Yuval.Mintz@caviumnetworks.com>
Apparently qede fails to set IFF_UNICAST_FLT, and as a result is not
actually performing unicast MAC filtering.
While we're at it - relax a hard-coded limitation that limits each
interface into using at most 15 unicast MAC addresses before turning
promiscuous. Instead utilize the HW resources to their limit.
Signed-off-by: Yuval Mintz <Yuval.Mintz@caviumnetworks.com>
---
drivers/net/ethernet/qlogic/qed/qed_l2.c | 12 ++++++++++--
drivers/net/ethernet/qlogic/qede/qede_main.c | 4 +++-
include/linux/qed/qed_eth_if.h | 1 +
3 files changed, 14 insertions(+), 3 deletions(-)
diff --git a/drivers/net/ethernet/qlogic/qed/qed_l2.c b/drivers/net/ethernet/qlogic/qed/qed_l2.c
index ddd410a..572ed04 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_l2.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_l2.c
@@ -1652,6 +1652,7 @@ static int qed_fill_eth_dev_info(struct qed_dev *cdev,
if (IS_PF(cdev)) {
int max_vf_vlan_filters = 0;
+ int max_vf_mac_filters = 0;
if (cdev->int_params.out.int_mode == QED_INT_MODE_MSIX) {
for_each_hwfn(cdev, i)
@@ -1665,11 +1666,18 @@ static int qed_fill_eth_dev_info(struct qed_dev *cdev,
info->num_queues = cdev->num_hwfns;
}
- if (IS_QED_SRIOV(cdev))
+ if (IS_QED_SRIOV(cdev)) {
max_vf_vlan_filters = cdev->p_iov_info->total_vfs *
QED_ETH_VF_NUM_VLAN_FILTERS;
- info->num_vlan_filters = RESC_NUM(&cdev->hwfns[0], QED_VLAN) -
+ max_vf_mac_filters = cdev->p_iov_info->total_vfs *
+ QED_ETH_VF_NUM_MAC_FILTERS;
+ }
+ info->num_vlan_filters = RESC_NUM(QED_LEADING_HWFN(cdev),
+ QED_VLAN) -
max_vf_vlan_filters;
+ info->num_mac_filters = RESC_NUM(QED_LEADING_HWFN(cdev),
+ QED_MAC) -
+ max_vf_mac_filters;
ether_addr_copy(info->port_mac,
cdev->hwfns[0].hw_info.hw_mac_addr);
diff --git a/drivers/net/ethernet/qlogic/qede/qede_main.c b/drivers/net/ethernet/qlogic/qede/qede_main.c
index 6c2b09c..0e483af 100644
--- a/drivers/net/ethernet/qlogic/qede/qede_main.c
+++ b/drivers/net/ethernet/qlogic/qede/qede_main.c
@@ -2365,6 +2365,8 @@ static void qede_init_ndev(struct qede_dev *edev)
qede_set_ethtool_ops(ndev);
+ ndev->priv_flags = IFF_UNICAST_FLT;
+
/* user-changeble features */
hw_features = NETIF_F_GRO | NETIF_F_SG |
NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
@@ -3937,7 +3939,7 @@ static void qede_config_rx_mode(struct net_device *ndev)
/* Check for promiscuous */
if ((ndev->flags & IFF_PROMISC) ||
- (uc_count > 15)) { /* @@@TBD resource allocation - 1 */
+ (uc_count > edev->dev_info.num_mac_filters - 1)) {
accept_flags = QED_FILTER_RX_MODE_TYPE_PROMISC;
} else {
/* Add MAC filters according to the unicast secondary macs */
diff --git a/include/linux/qed/qed_eth_if.h b/include/linux/qed/qed_eth_if.h
index 1c77948..1513080 100644
--- a/include/linux/qed/qed_eth_if.h
+++ b/include/linux/qed/qed_eth_if.h
@@ -23,6 +23,7 @@ struct qed_dev_eth_info {
u8 port_mac[ETH_ALEN];
u8 num_vlan_filters;
+ u16 num_mac_filters;
/* Legacy VF - this affects the datapath, so qede has to know */
bool is_legacy;
--
1.9.3
^ permalink raw reply related
* [PATCH net-next 6/6] qed: Handle malicious VFs events
From: Yuval Mintz @ 2016-10-09 15:25 UTC (permalink / raw)
To: davem, netdev; +Cc: Yuval Mintz
In-Reply-To: <1476026738-26069-1-git-send-email-Yuval.Mintz@qlogic.com>
From: Yuval Mintz <Yuval.Mintz@caviumnetworks.com>
Malicious VFs might be caught in several different methods:
- Misusing their bar permission and being blocked by hardware.
- Misusing their fastpath logic and being blocked by firmware.
- Misusing their interaction with their PF via hw-channel,
and being blocked by PF driver.
On the first two items, firmware would indicate to driver that
the VF is to be considered malicious, but would sometime still
allow the VF to communicate with the PF [depending on the exact
nature of the malicious activity done by the VF].
The current existing logic on the PF side lacks handling of such events,
and might allow the PF to perform some incorrect configuration on behalf
of a VF that was previously indicated as malicious.
The new scheme is simple -
Once the PF determines a VF is malicious it would:
a. Ignore any further requests on behalf of the VF-driver.
b. Prevent any configurations initiated by the hyperuser for
the malicious VF, as firmware isn't willing to serve such.
The malicious indication would be cleared upon the VF flr,
after which it would become usable once again.
Signed-off-by: Yuval Mintz <Yuval.Mintz@caviumnetworks.com>
---
drivers/net/ethernet/qlogic/qed/qed_sriov.c | 114 +++++++++++++++++++++++-----
drivers/net/ethernet/qlogic/qed/qed_sriov.h | 1 +
drivers/net/ethernet/qlogic/qed/qed_vf.h | 1 +
3 files changed, 96 insertions(+), 20 deletions(-)
diff --git a/drivers/net/ethernet/qlogic/qed/qed_sriov.c b/drivers/net/ethernet/qlogic/qed/qed_sriov.c
index d2d6621..6f029f9 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_sriov.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_sriov.c
@@ -109,7 +109,8 @@ static int qed_sp_vf_stop(struct qed_hwfn *p_hwfn,
}
static bool qed_iov_is_valid_vfid(struct qed_hwfn *p_hwfn,
- int rel_vf_id, bool b_enabled_only)
+ int rel_vf_id,
+ bool b_enabled_only, bool b_non_malicious)
{
if (!p_hwfn->pf_iov_info) {
DP_NOTICE(p_hwfn->cdev, "No iov info\n");
@@ -124,6 +125,10 @@ static bool qed_iov_is_valid_vfid(struct qed_hwfn *p_hwfn,
b_enabled_only)
return false;
+ if ((p_hwfn->pf_iov_info->vfs_array[rel_vf_id].b_malicious) &&
+ b_non_malicious)
+ return false;
+
return true;
}
@@ -138,7 +143,8 @@ static struct qed_vf_info *qed_iov_get_vf_info(struct qed_hwfn *p_hwfn,
return NULL;
}
- if (qed_iov_is_valid_vfid(p_hwfn, relative_vf_id, b_enabled_only))
+ if (qed_iov_is_valid_vfid(p_hwfn, relative_vf_id,
+ b_enabled_only, false))
vf = &p_hwfn->pf_iov_info->vfs_array[relative_vf_id];
else
DP_ERR(p_hwfn, "qed_iov_get_vf_info: VF[%d] is not enabled\n",
@@ -542,7 +548,8 @@ int qed_iov_hw_info(struct qed_hwfn *p_hwfn)
return 0;
}
-static bool qed_iov_pf_sanity_check(struct qed_hwfn *p_hwfn, int vfid)
+bool _qed_iov_pf_sanity_check(struct qed_hwfn *p_hwfn,
+ int vfid, bool b_fail_malicious)
{
/* Check PF supports sriov */
if (IS_VF(p_hwfn->cdev) || !IS_QED_SRIOV(p_hwfn->cdev) ||
@@ -550,12 +557,17 @@ static bool qed_iov_pf_sanity_check(struct qed_hwfn *p_hwfn, int vfid)
return false;
/* Check VF validity */
- if (!qed_iov_is_valid_vfid(p_hwfn, vfid, true))
+ if (!qed_iov_is_valid_vfid(p_hwfn, vfid, true, b_fail_malicious))
return false;
return true;
}
+bool qed_iov_pf_sanity_check(struct qed_hwfn *p_hwfn, int vfid)
+{
+ return _qed_iov_pf_sanity_check(p_hwfn, vfid, true);
+}
+
static void qed_iov_set_vf_to_disable(struct qed_dev *cdev,
u16 rel_vf_id, u8 to_disable)
{
@@ -652,6 +664,9 @@ static int qed_iov_enable_vf_access(struct qed_hwfn *p_hwfn,
qed_iov_vf_igu_reset(p_hwfn, p_ptt, vf);
+ /* It's possible VF was previously considered malicious */
+ vf->b_malicious = false;
+
rc = qed_mcp_config_vf_msix(p_hwfn, p_ptt, vf->abs_vf_id, vf->num_sbs);
if (rc)
return rc;
@@ -2804,6 +2819,13 @@ qed_iov_execute_vf_flr_cleanup(struct qed_hwfn *p_hwfn,
return rc;
}
+ /* Workaround to make VF-PF channel ready, as FW
+ * doesn't do that as a part of FLR.
+ */
+ REG_WR(p_hwfn,
+ GTT_BAR0_MAP_REG_USDM_RAM +
+ USTORM_VF_PF_CHANNEL_READY_OFFSET(vfid), 1);
+
/* VF_STOPPED has to be set only after final cleanup
* but prior to re-enabling the VF.
*/
@@ -2942,7 +2964,8 @@ static void qed_iov_process_mbx_req(struct qed_hwfn *p_hwfn,
mbx->first_tlv = mbx->req_virt->first_tlv;
/* check if tlv type is known */
- if (qed_iov_tlv_supported(mbx->first_tlv.tl.type)) {
+ if (qed_iov_tlv_supported(mbx->first_tlv.tl.type) &&
+ !p_vf->b_malicious) {
switch (mbx->first_tlv.tl.type) {
case CHANNEL_TLV_ACQUIRE:
qed_iov_vf_mbx_acquire(p_hwfn, p_ptt, p_vf);
@@ -2984,6 +3007,15 @@ static void qed_iov_process_mbx_req(struct qed_hwfn *p_hwfn,
qed_iov_vf_mbx_release(p_hwfn, p_ptt, p_vf);
break;
}
+ } else if (qed_iov_tlv_supported(mbx->first_tlv.tl.type)) {
+ DP_VERBOSE(p_hwfn, QED_MSG_IOV,
+ "VF [%02x] - considered malicious; Ignoring TLV [%04x]\n",
+ p_vf->abs_vf_id, mbx->first_tlv.tl.type);
+
+ qed_iov_prepare_resp(p_hwfn, p_ptt, p_vf,
+ mbx->first_tlv.tl.type,
+ sizeof(struct pfvf_def_resp_tlv),
+ PFVF_STATUS_MALICIOUS);
} else {
/* unknown TLV - this may belong to a VF driver from the future
* - a version written after this PF driver was written, which
@@ -3033,20 +3065,30 @@ static void qed_iov_pf_get_and_clear_pending_events(struct qed_hwfn *p_hwfn,
memset(p_pending_events, 0, sizeof(u64) * QED_VF_ARRAY_LENGTH);
}
-static int qed_sriov_vfpf_msg(struct qed_hwfn *p_hwfn,
- u16 abs_vfid, struct regpair *vf_msg)
+static struct qed_vf_info *qed_sriov_get_vf_from_absid(struct qed_hwfn *p_hwfn,
+ u16 abs_vfid)
{
- u8 min = (u8)p_hwfn->cdev->p_iov_info->first_vf_in_pf;
- struct qed_vf_info *p_vf;
+ u8 min = (u8) p_hwfn->cdev->p_iov_info->first_vf_in_pf;
- if (!qed_iov_pf_sanity_check(p_hwfn, (int)abs_vfid - min)) {
+ if (!_qed_iov_pf_sanity_check(p_hwfn, (int)abs_vfid - min, false)) {
DP_VERBOSE(p_hwfn,
QED_MSG_IOV,
- "Got a message from VF [abs 0x%08x] that cannot be handled by PF\n",
+ "Got indication for VF [abs 0x%08x] that cannot be handled by PF\n",
abs_vfid);
- return 0;
+ return NULL;
}
- p_vf = &p_hwfn->pf_iov_info->vfs_array[(u8)abs_vfid - min];
+
+ return &p_hwfn->pf_iov_info->vfs_array[(u8) abs_vfid - min];
+}
+
+static int qed_sriov_vfpf_msg(struct qed_hwfn *p_hwfn,
+ u16 abs_vfid, struct regpair *vf_msg)
+{
+ struct qed_vf_info *p_vf = qed_sriov_get_vf_from_absid(p_hwfn,
+ abs_vfid);
+
+ if (!p_vf)
+ return 0;
/* List the physical address of the request so that handler
* could later on copy the message from it.
@@ -3060,6 +3102,23 @@ static int qed_sriov_vfpf_msg(struct qed_hwfn *p_hwfn,
return 0;
}
+static void qed_sriov_vfpf_malicious(struct qed_hwfn *p_hwfn,
+ struct malicious_vf_eqe_data *p_data)
+{
+ struct qed_vf_info *p_vf;
+
+ p_vf = qed_sriov_get_vf_from_absid(p_hwfn, p_data->vf_id);
+
+ if (!p_vf)
+ return;
+
+ DP_INFO(p_hwfn,
+ "VF [%d] - Malicious behavior [%02x]\n",
+ p_vf->abs_vf_id, p_data->err_id);
+
+ p_vf->b_malicious = true;
+}
+
int qed_sriov_eqe_event(struct qed_hwfn *p_hwfn,
u8 opcode, __le16 echo, union event_ring_data *data)
{
@@ -3067,6 +3126,9 @@ int qed_sriov_eqe_event(struct qed_hwfn *p_hwfn,
case COMMON_EVENT_VF_PF_CHANNEL:
return qed_sriov_vfpf_msg(p_hwfn, le16_to_cpu(echo),
&data->vf_pf_channel.msg_addr);
+ case COMMON_EVENT_MALICIOUS_VF:
+ qed_sriov_vfpf_malicious(p_hwfn, &data->malicious_vf);
+ return 0;
default:
DP_INFO(p_hwfn->cdev, "Unknown sriov eqe event 0x%02x\n",
opcode);
@@ -3083,7 +3145,7 @@ u16 qed_iov_get_next_active_vf(struct qed_hwfn *p_hwfn, u16 rel_vf_id)
goto out;
for (i = rel_vf_id; i < p_iov->total_vfs; i++)
- if (qed_iov_is_valid_vfid(p_hwfn, rel_vf_id, true))
+ if (qed_iov_is_valid_vfid(p_hwfn, rel_vf_id, true, false))
return i;
out:
@@ -3130,6 +3192,12 @@ static void qed_iov_bulletin_set_forced_mac(struct qed_hwfn *p_hwfn,
return;
}
+ if (vf_info->b_malicious) {
+ DP_NOTICE(p_hwfn->cdev,
+ "Can't set forced MAC to malicious VF [%d]\n", vfid);
+ return;
+ }
+
feature = 1 << MAC_ADDR_FORCED;
memcpy(vf_info->bulletin.p_virt->mac, mac, ETH_ALEN);
@@ -3153,6 +3221,12 @@ static void qed_iov_bulletin_set_forced_vlan(struct qed_hwfn *p_hwfn,
return;
}
+ if (vf_info->b_malicious) {
+ DP_NOTICE(p_hwfn->cdev,
+ "Can't set forced vlan to malicious VF [%d]\n", vfid);
+ return;
+ }
+
feature = 1 << VLAN_ADDR_FORCED;
vf_info->bulletin.p_virt->pvid = pvid;
if (pvid)
@@ -3367,7 +3441,7 @@ int qed_sriov_disable(struct qed_dev *cdev, bool pci_enabled)
qed_for_each_vf(hwfn, j) {
int k;
- if (!qed_iov_is_valid_vfid(hwfn, j, true))
+ if (!qed_iov_is_valid_vfid(hwfn, j, true, false))
continue;
/* Wait until VF is disabled before releasing */
@@ -3425,7 +3499,7 @@ static int qed_sriov_enable(struct qed_dev *cdev, int num)
num_sbs = min_t(int, sb_cnt_info.sb_free_blk, limit);
for (i = 0; i < num; i++) {
- if (!qed_iov_is_valid_vfid(hwfn, i, false))
+ if (!qed_iov_is_valid_vfid(hwfn, i, false, true))
continue;
rc = qed_iov_init_hw_for_vf(hwfn,
@@ -3477,7 +3551,7 @@ static int qed_sriov_pf_set_mac(struct qed_dev *cdev, u8 *mac, int vfid)
return -EINVAL;
}
- if (!qed_iov_is_valid_vfid(&cdev->hwfns[0], vfid, true)) {
+ if (!qed_iov_is_valid_vfid(&cdev->hwfns[0], vfid, true, true)) {
DP_VERBOSE(cdev, QED_MSG_IOV,
"Cannot set VF[%d] MAC (VF is not active)\n", vfid);
return -EINVAL;
@@ -3509,7 +3583,7 @@ static int qed_sriov_pf_set_vlan(struct qed_dev *cdev, u16 vid, int vfid)
return -EINVAL;
}
- if (!qed_iov_is_valid_vfid(&cdev->hwfns[0], vfid, true)) {
+ if (!qed_iov_is_valid_vfid(&cdev->hwfns[0], vfid, true, true)) {
DP_VERBOSE(cdev, QED_MSG_IOV,
"Cannot set VF[%d] MAC (VF is not active)\n", vfid);
return -EINVAL;
@@ -3543,7 +3617,7 @@ static int qed_get_vf_config(struct qed_dev *cdev,
if (IS_VF(cdev))
return -EINVAL;
- if (!qed_iov_is_valid_vfid(&cdev->hwfns[0], vf_id, true)) {
+ if (!qed_iov_is_valid_vfid(&cdev->hwfns[0], vf_id, true, false)) {
DP_VERBOSE(cdev, QED_MSG_IOV,
"VF index [%d] isn't active\n", vf_id);
return -EINVAL;
@@ -3647,7 +3721,7 @@ static int qed_set_vf_link_state(struct qed_dev *cdev,
if (IS_VF(cdev))
return -EINVAL;
- if (!qed_iov_is_valid_vfid(&cdev->hwfns[0], vf_id, true)) {
+ if (!qed_iov_is_valid_vfid(&cdev->hwfns[0], vf_id, true, true)) {
DP_VERBOSE(cdev, QED_MSG_IOV,
"VF index [%d] isn't active\n", vf_id);
return -EINVAL;
diff --git a/drivers/net/ethernet/qlogic/qed/qed_sriov.h b/drivers/net/ethernet/qlogic/qed/qed_sriov.h
index 0dd23e4..3cf515b 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_sriov.h
+++ b/drivers/net/ethernet/qlogic/qed/qed_sriov.h
@@ -132,6 +132,7 @@ struct qed_vf_info {
struct qed_iov_vf_mbx vf_mbx;
enum vf_state state;
bool b_init;
+ bool b_malicious;
u8 to_disable;
struct qed_bulletin bulletin;
diff --git a/drivers/net/ethernet/qlogic/qed/qed_vf.h b/drivers/net/ethernet/qlogic/qed/qed_vf.h
index 35db7a28..944745b 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_vf.h
+++ b/drivers/net/ethernet/qlogic/qed/qed_vf.h
@@ -40,6 +40,7 @@ enum {
PFVF_STATUS_NOT_SUPPORTED,
PFVF_STATUS_NO_RESOURCE,
PFVF_STATUS_FORCED,
+ PFVF_STATUS_MALICIOUS,
};
/* vf pf channel tlvs */
--
1.9.3
^ permalink raw reply related
* [PATCH net-next 0/6] qed*: driver updates
From: Yuval Mintz @ 2016-10-09 15:25 UTC (permalink / raw)
To: davem, netdev; +Cc: Yuval Mintz
From: Yuval Mintz <Yuval.Mintz@caviumnetworks.com>
There are several new additions in this series;
Most are connected to either Tx offloading or Rx classifications
[either fastpath changes or supporting configuration].
In addition, there's a single IOV enhancement.
Dave,
Please consider applying this series to `net-next'.
Thanks,
Yuval
Manish Chopra (2):
qede: GSO support for tunnels with outer csum
qede: Prevent GSO on long Geneve headers
Yuval Mintz (4):
qed: Pass MAC hints to VFs
qed*: Allow unicast filtering
qed: Allow chance for fast ramrod completions
qed: Handle malicious VFs events
drivers/net/ethernet/qlogic/qed/qed_l2.c | 12 ++-
drivers/net/ethernet/qlogic/qed/qed_spq.c | 85 ++++++++++++++------
drivers/net/ethernet/qlogic/qed/qed_sriov.c | 114 ++++++++++++++++++++++-----
drivers/net/ethernet/qlogic/qed/qed_sriov.h | 1 +
drivers/net/ethernet/qlogic/qed/qed_vf.c | 4 +-
drivers/net/ethernet/qlogic/qed/qed_vf.h | 1 +
drivers/net/ethernet/qlogic/qede/qede.h | 1 +
drivers/net/ethernet/qlogic/qede/qede_main.c | 71 +++++++++++++++--
include/linux/qed/qed_eth_if.h | 3 +-
9 files changed, 236 insertions(+), 56 deletions(-)
--
1.9.3
^ permalink raw reply
* [PATCH net-next 2/6] qede: GSO support for tunnels with outer csum
From: Yuval Mintz @ 2016-10-09 15:25 UTC (permalink / raw)
To: davem, netdev; +Cc: Manish Chopra, Yuval Mintz
In-Reply-To: <1476026738-26069-1-git-send-email-Yuval.Mintz@qlogic.com>
From: Manish Chopra <manish.chopra@caviumnetworks.com>
This patch adds GSO support for GRE and UDP tunnels
where outer checksums are enabled.
Signed-off-by: Manish Chopra <manish.chopra@caviumnetworks.com>
Signed-off-by: Yuval Mintz <Yuval.Mintz@caviumnetworks.com>
---
drivers/net/ethernet/qlogic/qede/qede.h | 1 +
drivers/net/ethernet/qlogic/qede/qede_main.c | 26 +++++++++++++++++++++++---
2 files changed, 24 insertions(+), 3 deletions(-)
diff --git a/drivers/net/ethernet/qlogic/qede/qede.h b/drivers/net/ethernet/qlogic/qede/qede.h
index 28c0e9f..f50e527 100644
--- a/drivers/net/ethernet/qlogic/qede/qede.h
+++ b/drivers/net/ethernet/qlogic/qede/qede.h
@@ -320,6 +320,7 @@ struct qede_fastpath {
#define XMIT_L4_CSUM BIT(0)
#define XMIT_LSO BIT(1)
#define XMIT_ENC BIT(2)
+#define XMIT_ENC_GSO_L4_CSUM BIT(3)
#define QEDE_CSUM_ERROR BIT(0)
#define QEDE_CSUM_UNNECESSARY BIT(1)
diff --git a/drivers/net/ethernet/qlogic/qede/qede_main.c b/drivers/net/ethernet/qlogic/qede/qede_main.c
index 9866d95..7d5dc1e 100644
--- a/drivers/net/ethernet/qlogic/qede/qede_main.c
+++ b/drivers/net/ethernet/qlogic/qede/qede_main.c
@@ -400,8 +400,19 @@ static u32 qede_xmit_type(struct qede_dev *edev,
(ipv6_hdr(skb)->nexthdr == NEXTHDR_IPV6))
*ipv6_ext = 1;
- if (skb->encapsulation)
+ if (skb->encapsulation) {
rc |= XMIT_ENC;
+ if (skb_is_gso(skb)) {
+ unsigned short gso_type = skb_shinfo(skb)->gso_type;
+
+ if ((gso_type & SKB_GSO_UDP_TUNNEL_CSUM) ||
+ (gso_type & SKB_GSO_GRE_CSUM))
+ rc |= XMIT_ENC_GSO_L4_CSUM;
+
+ rc |= XMIT_LSO;
+ return rc;
+ }
+ }
if (skb_is_gso(skb))
rc |= XMIT_LSO;
@@ -637,6 +648,12 @@ static netdev_tx_t qede_start_xmit(struct sk_buff *skb,
if (unlikely(xmit_type & XMIT_ENC)) {
first_bd->data.bd_flags.bitfields |=
1 << ETH_TX_1ST_BD_FLAGS_TUNN_IP_CSUM_SHIFT;
+
+ if (xmit_type & XMIT_ENC_GSO_L4_CSUM) {
+ u8 tmp = ETH_TX_1ST_BD_FLAGS_TUNN_L4_CSUM_SHIFT;
+
+ first_bd->data.bd_flags.bitfields |= 1 << tmp;
+ }
hlen = qede_get_skb_hlen(skb, true);
} else {
first_bd->data.bd_flags.bitfields |=
@@ -2320,11 +2337,14 @@ static void qede_init_ndev(struct qede_dev *edev)
/* Encap features*/
hw_features |= NETIF_F_GSO_GRE | NETIF_F_GSO_UDP_TUNNEL |
- NETIF_F_TSO_ECN;
+ NETIF_F_TSO_ECN | NETIF_F_GSO_UDP_TUNNEL_CSUM |
+ NETIF_F_GSO_GRE_CSUM;
ndev->hw_enc_features = NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
NETIF_F_SG | NETIF_F_TSO | NETIF_F_TSO_ECN |
NETIF_F_TSO6 | NETIF_F_GSO_GRE |
- NETIF_F_GSO_UDP_TUNNEL | NETIF_F_RXCSUM;
+ NETIF_F_GSO_UDP_TUNNEL | NETIF_F_RXCSUM |
+ NETIF_F_GSO_UDP_TUNNEL_CSUM |
+ NETIF_F_GSO_GRE_CSUM;
ndev->vlan_features = hw_features | NETIF_F_RXHASH | NETIF_F_RXCSUM |
NETIF_F_HIGHDMA;
--
1.9.3
^ permalink raw reply related
* [PATCH net-next 1/6] qed: Pass MAC hints to VFs
From: Yuval Mintz @ 2016-10-09 15:25 UTC (permalink / raw)
To: davem, netdev; +Cc: Yuval Mintz
In-Reply-To: <1476026738-26069-1-git-send-email-Yuval.Mintz@qlogic.com>
From: Yuval Mintz <Yuval.Mintz@caviumnetworks.com>
Some hypervisors can support MAC hints to their VFs.
Even though we don't have such a hypervisor API in linux, we add
sufficient logic for the VF to be able to receive such hints and
set the mac accordingly - as long as the VF has not been set with
a MAC already.
Signed-off-by: Yuval Mintz <Yuval.Mintz@caviumnetworks.com>
---
drivers/net/ethernet/qlogic/qed/qed_vf.c | 4 ++--
drivers/net/ethernet/qlogic/qede/qede_main.c | 6 +++++-
include/linux/qed/qed_eth_if.h | 2 +-
3 files changed, 8 insertions(+), 4 deletions(-)
diff --git a/drivers/net/ethernet/qlogic/qed/qed_vf.c b/drivers/net/ethernet/qlogic/qed/qed_vf.c
index abf5bf1..f580bf4 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_vf.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_vf.c
@@ -1230,8 +1230,8 @@ static void qed_handle_bulletin_change(struct qed_hwfn *hwfn)
is_mac_exist = qed_vf_bulletin_get_forced_mac(hwfn, mac,
&is_mac_forced);
- if (is_mac_exist && is_mac_forced && cookie)
- ops->force_mac(cookie, mac);
+ if (is_mac_exist && cookie)
+ ops->force_mac(cookie, mac, !!is_mac_forced);
/* Always update link configuration according to bulletin */
qed_link_update(hwfn);
diff --git a/drivers/net/ethernet/qlogic/qede/qede_main.c b/drivers/net/ethernet/qlogic/qede/qede_main.c
index 343038c..9866d95 100644
--- a/drivers/net/ethernet/qlogic/qede/qede_main.c
+++ b/drivers/net/ethernet/qlogic/qede/qede_main.c
@@ -171,10 +171,14 @@ static struct pci_driver qede_pci_driver = {
#endif
};
-static void qede_force_mac(void *dev, u8 *mac)
+static void qede_force_mac(void *dev, u8 *mac, bool forced)
{
struct qede_dev *edev = dev;
+ /* MAC hints take effect only if we haven't set one already */
+ if (is_valid_ether_addr(edev->ndev->dev_addr) && !forced)
+ return;
+
ether_addr_copy(edev->ndev->dev_addr, mac);
ether_addr_copy(edev->primary_mac, mac);
}
diff --git a/include/linux/qed/qed_eth_if.h b/include/linux/qed/qed_eth_if.h
index 33c24eb..1c77948 100644
--- a/include/linux/qed/qed_eth_if.h
+++ b/include/linux/qed/qed_eth_if.h
@@ -129,7 +129,7 @@ struct qed_tunn_params {
struct qed_eth_cb_ops {
struct qed_common_cb_ops common;
- void (*force_mac) (void *dev, u8 *mac);
+ void (*force_mac) (void *dev, u8 *mac, bool forced);
};
#ifdef CONFIG_DCB
--
1.9.3
^ permalink raw reply related
* [PATCH net-next 5/6] qed: Allow chance for fast ramrod completions
From: Yuval Mintz @ 2016-10-09 15:25 UTC (permalink / raw)
To: davem, netdev; +Cc: Yuval Mintz
In-Reply-To: <1476026738-26069-1-git-send-email-Yuval.Mintz@qlogic.com>
From: Yuval Mintz <Yuval.Mintz@caviumnetworks.com>
Whenever a ramrod is being sent for some device configuration,
the driver is going to sleep at least 5ms between each iteration
of polling on the completion of the ramrod.
However, in almost every configuration scenario the firmware
would be able to comply and complete the ramrod in a manner of
several usecs. This is especially important in cases where there
might be a lot of sequential configurations applying to the hardware
[e.g., RoCE], in which case the existing scheme might cause some
visible user delays.
This patch changes the completion scheme - instead of immediately
starting to sleep for a 'long' period, allow the device to quickly
poll on the first iteration after a couple of usecs.
Signed-off-by: Yuval Mintz <Yuval.Mintz@caviumnetworks.com>
---
drivers/net/ethernet/qlogic/qed/qed_spq.c | 85 +++++++++++++++++++++----------
1 file changed, 59 insertions(+), 26 deletions(-)
diff --git a/drivers/net/ethernet/qlogic/qed/qed_spq.c b/drivers/net/ethernet/qlogic/qed/qed_spq.c
index caff415..259a615 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_spq.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_spq.c
@@ -37,7 +37,11 @@
***************************************************************************/
#define SPQ_HIGH_PRI_RESERVE_DEFAULT (1)
-#define SPQ_BLOCK_SLEEP_LENGTH (1000)
+
+#define SPQ_BLOCK_DELAY_MAX_ITER (10)
+#define SPQ_BLOCK_DELAY_US (10)
+#define SPQ_BLOCK_SLEEP_MAX_ITER (1000)
+#define SPQ_BLOCK_SLEEP_MS (5)
/***************************************************************************
* Blocking Imp. (BLOCK/EBLOCK mode)
@@ -57,53 +61,81 @@ static void qed_spq_blocking_cb(struct qed_hwfn *p_hwfn,
smp_wmb();
}
-static int qed_spq_block(struct qed_hwfn *p_hwfn,
- struct qed_spq_entry *p_ent,
- u8 *p_fw_ret)
+static int __qed_spq_block(struct qed_hwfn *p_hwfn,
+ struct qed_spq_entry *p_ent,
+ u8 *p_fw_ret, bool sleep_between_iter)
{
- int sleep_count = SPQ_BLOCK_SLEEP_LENGTH;
struct qed_spq_comp_done *comp_done;
- int rc;
+ u32 iter_cnt;
comp_done = (struct qed_spq_comp_done *)p_ent->comp_cb.cookie;
- while (sleep_count) {
- /* validate we receive completion update */
+ iter_cnt = sleep_between_iter ? SPQ_BLOCK_SLEEP_MAX_ITER
+ : SPQ_BLOCK_DELAY_MAX_ITER;
+
+ while (iter_cnt--) {
+ /* Validate we receive completion update */
smp_rmb();
if (comp_done->done == 1) {
if (p_fw_ret)
*p_fw_ret = comp_done->fw_return_code;
return 0;
}
- usleep_range(5000, 10000);
- sleep_count--;
+
+ if (sleep_between_iter)
+ msleep(SPQ_BLOCK_SLEEP_MS);
+ else
+ udelay(SPQ_BLOCK_DELAY_US);
}
+ return -EBUSY;
+}
+
+static int qed_spq_block(struct qed_hwfn *p_hwfn,
+ struct qed_spq_entry *p_ent,
+ u8 *p_fw_ret, bool skip_quick_poll)
+{
+ struct qed_spq_comp_done *comp_done;
+ int rc;
+
+ /* A relatively short polling period w/o sleeping, to allow the FW to
+ * complete the ramrod and thus possibly to avoid the following sleeps.
+ */
+ if (!skip_quick_poll) {
+ rc = __qed_spq_block(p_hwfn, p_ent, p_fw_ret, false);
+ if (!rc)
+ return 0;
+ }
+
+ /* Move to polling with a sleeping period between iterations */
+ rc = __qed_spq_block(p_hwfn, p_ent, p_fw_ret, true);
+ if (!rc)
+ return 0;
+
DP_INFO(p_hwfn, "Ramrod is stuck, requesting MCP drain\n");
rc = qed_mcp_drain(p_hwfn, p_hwfn->p_main_ptt);
- if (rc != 0)
+ if (rc) {
DP_NOTICE(p_hwfn, "MCP drain failed\n");
+ goto err;
+ }
/* Retry after drain */
- sleep_count = SPQ_BLOCK_SLEEP_LENGTH;
- while (sleep_count) {
- /* validate we receive completion update */
- smp_rmb();
- if (comp_done->done == 1) {
- if (p_fw_ret)
- *p_fw_ret = comp_done->fw_return_code;
- return 0;
- }
- usleep_range(5000, 10000);
- sleep_count--;
- }
+ rc = __qed_spq_block(p_hwfn, p_ent, p_fw_ret, true);
+ if (!rc)
+ return 0;
+ comp_done = (struct qed_spq_comp_done *)p_ent->comp_cb.cookie;
if (comp_done->done == 1) {
if (p_fw_ret)
*p_fw_ret = comp_done->fw_return_code;
return 0;
}
-
- DP_NOTICE(p_hwfn, "Ramrod is stuck, MCP drain failed\n");
+err:
+ DP_NOTICE(p_hwfn,
+ "Ramrod is stuck [CID %08x cmd %02x protocol %02x echo %04x]\n",
+ le32_to_cpu(p_ent->elem.hdr.cid),
+ p_ent->elem.hdr.cmd_id,
+ p_ent->elem.hdr.protocol_id,
+ le16_to_cpu(p_ent->elem.hdr.echo));
return -EBUSY;
}
@@ -729,7 +761,8 @@ int qed_spq_post(struct qed_hwfn *p_hwfn,
* access p_ent here to see whether it's successful or not.
* Thus, after gaining the answer perform the cleanup here.
*/
- rc = qed_spq_block(p_hwfn, p_ent, fw_return_code);
+ rc = qed_spq_block(p_hwfn, p_ent, fw_return_code,
+ p_ent->queue == &p_spq->unlimited_pending);
if (p_ent->queue == &p_spq->unlimited_pending) {
/* This is an allocated p_ent which does not need to
--
1.9.3
^ permalink raw reply related
* [PATCH net-next 3/6] qede: Prevent GSO on long Geneve headers
From: Yuval Mintz @ 2016-10-09 15:25 UTC (permalink / raw)
To: davem, netdev; +Cc: Manish Chopra, Yuval Mintz
In-Reply-To: <1476026738-26069-1-git-send-email-Yuval.Mintz@qlogic.com>
From: Manish Chopra <manish.chopra@caviumnetworks.com>
Due to hardware limitation, when transmitting a geneve-encapsulated
packet with more than 32 bytes worth of geneve options the hardware
would not be able to crack the packet and consider it a regular UDP
packet.
This implements the ndo_features_check() in qede in order to prevent
GSO on said transmitted packets.
Signed-off-by: Manish Chopra <manish.chopra@caviumnetworks.com>
Signed-off-by: Yuval Mintz <Yuval.Mintz@caviumnetworks.com>
---
drivers/net/ethernet/qlogic/qede/qede_main.c | 35 ++++++++++++++++++++++++++++
1 file changed, 35 insertions(+)
diff --git a/drivers/net/ethernet/qlogic/qede/qede_main.c b/drivers/net/ethernet/qlogic/qede/qede_main.c
index 7d5dc1e..6c2b09c 100644
--- a/drivers/net/ethernet/qlogic/qede/qede_main.c
+++ b/drivers/net/ethernet/qlogic/qede/qede_main.c
@@ -2240,6 +2240,40 @@ static void qede_udp_tunnel_del(struct net_device *dev,
schedule_delayed_work(&edev->sp_task, 0);
}
+/* 8B udp header + 8B base tunnel header + 32B option length */
+#define QEDE_MAX_TUN_HDR_LEN 48
+
+static netdev_features_t qede_features_check(struct sk_buff *skb,
+ struct net_device *dev,
+ netdev_features_t features)
+{
+ if (skb->encapsulation) {
+ u8 l4_proto = 0;
+
+ switch (vlan_get_protocol(skb)) {
+ case htons(ETH_P_IP):
+ l4_proto = ip_hdr(skb)->protocol;
+ break;
+ case htons(ETH_P_IPV6):
+ l4_proto = ipv6_hdr(skb)->nexthdr;
+ break;
+ default:
+ return features;
+ }
+
+ /* Disable offloads for geneve tunnels, as HW can't parse
+ * the geneve header which has option length greater than 32B.
+ */
+ if ((l4_proto == IPPROTO_UDP) &&
+ ((skb_inner_mac_header(skb) -
+ skb_transport_header(skb)) > QEDE_MAX_TUN_HDR_LEN))
+ return features & ~(NETIF_F_CSUM_MASK |
+ NETIF_F_GSO_MASK);
+ }
+
+ return features;
+}
+
static const struct net_device_ops qede_netdev_ops = {
.ndo_open = qede_open,
.ndo_stop = qede_close,
@@ -2264,6 +2298,7 @@ static const struct net_device_ops qede_netdev_ops = {
#endif
.ndo_udp_tunnel_add = qede_udp_tunnel_add,
.ndo_udp_tunnel_del = qede_udp_tunnel_del,
+ .ndo_features_check = qede_features_check,
};
/* -------------------------------------------------------------------------
--
1.9.3
^ permalink raw reply related
* Re: Accelerated receive flow steering (aRFS) for UDP
From: Eric Dumazet @ 2016-10-09 17:14 UTC (permalink / raw)
To: Chopra, Manish
Cc: netdev@vger.kernel.org, maorg@mellanox.com, tom@herbertland.com
In-Reply-To: <SN1PR07MB2447ED02140770F0B46967D589D90@SN1PR07MB2447.namprd07.prod.outlook.com>
On Sat, 2016-10-08 at 12:25 +0000, Chopra, Manish wrote:
> > -----Original Message-----
> > From: Eric Dumazet [mailto:eric.dumazet@gmail.com]
> > Sent: Saturday, October 08, 2016 5:08 AM
> > To: Chopra, Manish <Manish.Chopra@cavium.com>
> > Cc: netdev@vger.kernel.org; maorg@mellanox.com; tom@herbertland.com
> > Subject: Re: Accelerated receive flow steering (aRFS) for UDP
> >
> > On Fri, 2016-10-07 at 22:55 +0000, Chopra, Manish wrote:
> > > Hello Folks,
> > >
> > > I am experimenting aRFS with our NIC devices, and for that I have
> > > kernel 4.8.x installed with below config.
> > >
> > > CONFIG_RPS=y
> > > CONFIG_RFS_ACCEL=y
> > >
> > > # cat /proc/cpuinfo | grep processor
> > > processor : 0
> > > processor : 1
> > > processor : 2
> > > processor : 3
> > > processor : 4
> > > processor : 5
> > > processor : 6
> > > processor : 7
> > > processor : 8
> > > processor : 9
> > > processor : 10
> > > processor : 11
> > > processor : 12
> > > processor : 13
> > > processor : 14
> > > processor : 15
> > >
> > > I configured rps_sock_flow_entries and our NIC rx queues with below
> > > values
> > >
> > > echo 32768 > /proc/sys/net/core/rps_sock_flow_entries
> > > echo 4096 > /sys/class/net/p4p1/queues/rx-0/rps_flow_cnt
> > > echo 4096 > /sys/class/net/p4p1/queues/rx-1/rps_flow_cnt
> > > echo 4096 > /sys/class/net/p4p1/queues/rx-2/rps_flow_cnt
> > > echo 4096 > /sys/class/net/p4p1/queues/rx-3/rps_flow_cnt
> > > echo 4096 > /sys/class/net/p4p1/queues/rx-4/rps_flow_cnt
> > > echo 4096 > /sys/class/net/p4p1/queues/rx-5/rps_flow_cnt
> > > echo 4096 > /sys/class/net/p4p1/queues/rx-6/rps_flow_cnt
> > > echo 4096 > /sys/class/net/p4p1/queues/rx-7/rps_flow_cnt
> > >
> > > echo ffff > /sys/class/net/p4p1/queues/rx-0/rps_cpus
> > > echo ffff > /sys/class/net/p4p1/queues/rx-1/rps_cpus
> > > echo ffff > /sys/class/net/p4p1/queues/rx-2/rps_cpus
> > > echo ffff > /sys/class/net/p4p1/queues/rx-3/rps_cpus
> > > echo ffff > /sys/class/net/p4p1/queues/rx-4/rps_cpus
> > > echo ffff > /sys/class/net/p4p1/queues/rx-5/rps_cpus
> > > echo ffff > /sys/class/net/p4p1/queues/rx-6/rps_cpus
> > > echo ffff > /sys/class/net/p4p1/queues/rx-7/rps_cpus
> > >
> > > Below is IRQ affinity configuration for NIC irqs used.
> > >
> > > # cat /proc/irq/67/smp_affinity_list
> > > 8
> > > # cat /proc/irq/68/smp_affinity_list
> > > 9
> > > # cat /proc/irq/69/smp_affinity_list
> > > 10
> > > # cat /proc/irq/70/smp_affinity_list
> > > 11
> > > # cat /proc/irq/71/smp_affinity_list
> > > 12
> > > # cat /proc/irq/72/smp_affinity_list
> > > 13
> > > # cat /proc/irq/73/smp_affinity_list
> > > 14
> > > # cat /proc/irq/74/smp_affinity_list
> > > 15
> > >
> > > Driver has required feature NETIF_F_NTUPLE set, ndo_rx_flow_steer()
> > > registered and I am running UDP multiple connections stream using
> > > netperf to the host where I am experimenting aRFS.
> > >
> > > # netperf -V
> > > Netperf version 2.7.0
> > >
> > > netperf -H 192.168.200.40 -t UDP_STREAM -l 150 -T 8,8 -- -m 1470 -P
> > > 5001,48512 &
> > > netperf -H 192.168.200.40 -t UDP_STREAM -l 150 -T 9,9 -- -m 1470 -P
> > > 5001,37990 &
> > > netperf -H 192.168.200.40 -t UDP_STREAM -l 150 -T 10,10 -- -m 1470 -P
> > > 5001,40302 &
> > > netperf -H 192.168.200.40 -t UDP_STREAM -l 150 -T 11,11 -- -m 1470 -P
> > > 5001,39071 &
> > > netperf -H 192.168.200.40 -t UDP_STREAM -l 150 -T 12,12 -- -m 1470 -P
> > > 5001,58994 &
> > > netperf -H 192.168.200.40 -t UDP_STREAM -l 150 -T 13,13 -- -m 1470 -P
> > > 5001,59884 &
> > > netperf -H 192.168.200.40 -t UDP_STREAM -l 150 -T 14,14 -- -m 1470 -P
> > > 5001,40282 &
> > > netperf -H 192.168.200.40 -t UDP_STREAM -l 150 -T 15,15 -- -m 1470 -P
> > > 5001,56042 &
> > >
> > > I see that our registered callback for ndo_rx_flow_steer() "NEVER"
> > > gets invoked for UDP packets, with TCP_STREAM I do see it gets
> > > invoked.
> > > But while running UDP_STREAM I see it gets invoked for some of TCP
> > > packets as netperf also uses TCP managed connections while running
> > > UDP_STREAM.
> > >
> > > My initial investigation suspects that while running UDP_STREAM with
> > > netperf, rps_sock_flow_table doesn't get updated, as packets never
> > > reach to the flow of inet_recvmsg()
> > > where it gets updated using sock_rps_record_flow(). Which might be the
> > > reason it never invokes NIC's flow steering handler ?
> > >
> > > Please note that when I run UDP stream using "iperf" - I do see that
> > > our registered callback function for flow steering gets invoked for
> > > "UDP" packets.
> > > I am not sure if I am missing something in configuration or something
> > > else which is I am unware of ?
> > >
> > > I appreciate any help for this.
> >
> > Make sure you use connected UDP flows
> >
> >
> > netperf -t UDP_STREAM ... -- -N -n
> >
> > Otherwise, one UDP socket can be involved in millions of 4-tuples (aka
> > flows)
> >
> >
>
> Hi Eric, I tried with it but it doesn't help with the said issue. I still don't see that our registered handler for flow steering (ndo_rx_flow_steer()) is getting
> invoked for UDP packets [ip->protocol = IPPROTO_UDP] .All it gets invoked for TCP packets only [ip->protocol = IPPROTO_TCP]
>
> netperf -H $1 -t UDP_STREAM -l 150 -T 8,8 -- -N -m 1470 -P 5001,48512 &
> netperf -H $1 -t UDP_STREAM -l 150 -T 9,9 -- -N -m 1470 -P 5001,37990 &
> netperf -H $1 -t UDP_STREAM -l 150 -T 10,10 -- -N -m 1470 -P 5001,40302 &
> netperf -H $1 -t UDP_STREAM -l 150 -T 11,11 -- -N -m 1470 -P 5001,39071 &
> netperf -H $1 -t UDP_STREAM -l 150 -T 12,12 -- -N -m 1470 -P 5001,58994 &
> netperf -H $1 -t UDP_STREAM -l 150 -T 13,13 -- -N -m 1470 -P 5001,59884 &
> netperf -H $1 -t UDP_STREAM -l 150 -T 14,14 -- -N -m 1470 -P 5001,40282 &
> netperf -H $1 -t UDP_STREAM -l 150 -T 15,15 -- -N -m 1470 -P 5001,56042 &
>
> Thanks !!
Please carefully read what I wrote, and carefully read netperf
documentation.
When you add -n option to netperf, it _will_ use connected UDP sockets
and your problem will vanish.
You added '-N' only, which is useless for UDP_STREAM.
It might help for UDP_RR, but not UDP_STREAM.
^ permalink raw reply
* RE: Accelerated receive flow steering (aRFS) for UDP
From: Chopra, Manish @ 2016-10-09 19:48 UTC (permalink / raw)
To: Eric Dumazet
Cc: netdev@vger.kernel.org, maorg@mellanox.com, tom@herbertland.com
In-Reply-To: <1476033293.28155.273.camel@edumazet-glaptop3.roam.corp.google.com>
> -----Original Message-----
> From: Eric Dumazet [mailto:eric.dumazet@gmail.com]
> Sent: Sunday, October 09, 2016 10:45 PM
> To: Chopra, Manish <Manish.Chopra@cavium.com>
> Cc: netdev@vger.kernel.org; maorg@mellanox.com; tom@herbertland.com
> Subject: Re: Accelerated receive flow steering (aRFS) for UDP
>
> On Sat, 2016-10-08 at 12:25 +0000, Chopra, Manish wrote:
> > > -----Original Message-----
> > > From: Eric Dumazet [mailto:eric.dumazet@gmail.com]
> > > Sent: Saturday, October 08, 2016 5:08 AM
> > > To: Chopra, Manish <Manish.Chopra@cavium.com>
> > > Cc: netdev@vger.kernel.org; maorg@mellanox.com; tom@herbertland.com
> > > Subject: Re: Accelerated receive flow steering (aRFS) for UDP
> > >
> > > On Fri, 2016-10-07 at 22:55 +0000, Chopra, Manish wrote:
> > > > Hello Folks,
> > > >
> > > > I am experimenting aRFS with our NIC devices, and for that I have
> > > > kernel 4.8.x installed with below config.
> > > >
> > > > CONFIG_RPS=y
> > > > CONFIG_RFS_ACCEL=y
> > > >
> > > > # cat /proc/cpuinfo | grep processor
> > > > processor : 0
> > > > processor : 1
> > > > processor : 2
> > > > processor : 3
> > > > processor : 4
> > > > processor : 5
> > > > processor : 6
> > > > processor : 7
> > > > processor : 8
> > > > processor : 9
> > > > processor : 10
> > > > processor : 11
> > > > processor : 12
> > > > processor : 13
> > > > processor : 14
> > > > processor : 15
> > > >
> > > > I configured rps_sock_flow_entries and our NIC rx queues with below
> > > > values
> > > >
> > > > echo 32768 > /proc/sys/net/core/rps_sock_flow_entries
> > > > echo 4096 > /sys/class/net/p4p1/queues/rx-0/rps_flow_cnt
> > > > echo 4096 > /sys/class/net/p4p1/queues/rx-1/rps_flow_cnt
> > > > echo 4096 > /sys/class/net/p4p1/queues/rx-2/rps_flow_cnt
> > > > echo 4096 > /sys/class/net/p4p1/queues/rx-3/rps_flow_cnt
> > > > echo 4096 > /sys/class/net/p4p1/queues/rx-4/rps_flow_cnt
> > > > echo 4096 > /sys/class/net/p4p1/queues/rx-5/rps_flow_cnt
> > > > echo 4096 > /sys/class/net/p4p1/queues/rx-6/rps_flow_cnt
> > > > echo 4096 > /sys/class/net/p4p1/queues/rx-7/rps_flow_cnt
> > > >
> > > > echo ffff > /sys/class/net/p4p1/queues/rx-0/rps_cpus
> > > > echo ffff > /sys/class/net/p4p1/queues/rx-1/rps_cpus
> > > > echo ffff > /sys/class/net/p4p1/queues/rx-2/rps_cpus
> > > > echo ffff > /sys/class/net/p4p1/queues/rx-3/rps_cpus
> > > > echo ffff > /sys/class/net/p4p1/queues/rx-4/rps_cpus
> > > > echo ffff > /sys/class/net/p4p1/queues/rx-5/rps_cpus
> > > > echo ffff > /sys/class/net/p4p1/queues/rx-6/rps_cpus
> > > > echo ffff > /sys/class/net/p4p1/queues/rx-7/rps_cpus
> > > >
> > > > Below is IRQ affinity configuration for NIC irqs used.
> > > >
> > > > # cat /proc/irq/67/smp_affinity_list
> > > > 8
> > > > # cat /proc/irq/68/smp_affinity_list
> > > > 9
> > > > # cat /proc/irq/69/smp_affinity_list
> > > > 10
> > > > # cat /proc/irq/70/smp_affinity_list
> > > > 11
> > > > # cat /proc/irq/71/smp_affinity_list
> > > > 12
> > > > # cat /proc/irq/72/smp_affinity_list
> > > > 13
> > > > # cat /proc/irq/73/smp_affinity_list
> > > > 14
> > > > # cat /proc/irq/74/smp_affinity_list
> > > > 15
> > > >
> > > > Driver has required feature NETIF_F_NTUPLE set, ndo_rx_flow_steer()
> > > > registered and I am running UDP multiple connections stream using
> > > > netperf to the host where I am experimenting aRFS.
> > > >
> > > > # netperf -V
> > > > Netperf version 2.7.0
> > > >
> > > > netperf -H 192.168.200.40 -t UDP_STREAM -l 150 -T 8,8 -- -m 1470 -P
> > > > 5001,48512 &
> > > > netperf -H 192.168.200.40 -t UDP_STREAM -l 150 -T 9,9 -- -m 1470 -P
> > > > 5001,37990 &
> > > > netperf -H 192.168.200.40 -t UDP_STREAM -l 150 -T 10,10 -- -m 1470 -P
> > > > 5001,40302 &
> > > > netperf -H 192.168.200.40 -t UDP_STREAM -l 150 -T 11,11 -- -m 1470 -P
> > > > 5001,39071 &
> > > > netperf -H 192.168.200.40 -t UDP_STREAM -l 150 -T 12,12 -- -m 1470 -P
> > > > 5001,58994 &
> > > > netperf -H 192.168.200.40 -t UDP_STREAM -l 150 -T 13,13 -- -m 1470 -P
> > > > 5001,59884 &
> > > > netperf -H 192.168.200.40 -t UDP_STREAM -l 150 -T 14,14 -- -m 1470 -P
> > > > 5001,40282 &
> > > > netperf -H 192.168.200.40 -t UDP_STREAM -l 150 -T 15,15 -- -m 1470 -P
> > > > 5001,56042 &
> > > >
> > > > I see that our registered callback for ndo_rx_flow_steer() "NEVER"
> > > > gets invoked for UDP packets, with TCP_STREAM I do see it gets
> > > > invoked.
> > > > But while running UDP_STREAM I see it gets invoked for some of TCP
> > > > packets as netperf also uses TCP managed connections while running
> > > > UDP_STREAM.
> > > >
> > > > My initial investigation suspects that while running UDP_STREAM with
> > > > netperf, rps_sock_flow_table doesn't get updated, as packets never
> > > > reach to the flow of inet_recvmsg()
> > > > where it gets updated using sock_rps_record_flow(). Which might be the
> > > > reason it never invokes NIC's flow steering handler ?
> > > >
> > > > Please note that when I run UDP stream using "iperf" - I do see that
> > > > our registered callback function for flow steering gets invoked for
> > > > "UDP" packets.
> > > > I am not sure if I am missing something in configuration or something
> > > > else which is I am unware of ?
> > > >
> > > > I appreciate any help for this.
> > >
> > > Make sure you use connected UDP flows
> > >
> > >
> > > netperf -t UDP_STREAM ... -- -N -n
> > >
> > > Otherwise, one UDP socket can be involved in millions of 4-tuples (aka
> > > flows)
> > >
> > >
> >
> > Hi Eric, I tried with it but it doesn't help with the said issue. I still don't see that
> our registered handler for flow steering (ndo_rx_flow_steer()) is getting
> > invoked for UDP packets [ip->protocol = IPPROTO_UDP] .All it gets invoked for
> TCP packets only [ip->protocol = IPPROTO_TCP]
> >
> > netperf -H $1 -t UDP_STREAM -l 150 -T 8,8 -- -N -m 1470 -P 5001,48512 &
> > netperf -H $1 -t UDP_STREAM -l 150 -T 9,9 -- -N -m 1470 -P 5001,37990 &
> > netperf -H $1 -t UDP_STREAM -l 150 -T 10,10 -- -N -m 1470 -P 5001,40302 &
> > netperf -H $1 -t UDP_STREAM -l 150 -T 11,11 -- -N -m 1470 -P 5001,39071 &
> > netperf -H $1 -t UDP_STREAM -l 150 -T 12,12 -- -N -m 1470 -P 5001,58994 &
> > netperf -H $1 -t UDP_STREAM -l 150 -T 13,13 -- -N -m 1470 -P 5001,59884 &
> > netperf -H $1 -t UDP_STREAM -l 150 -T 14,14 -- -N -m 1470 -P 5001,40282 &
> > netperf -H $1 -t UDP_STREAM -l 150 -T 15,15 -- -N -m 1470 -P 5001,56042 &
> >
> > Thanks !!
>
> Please carefully read what I wrote, and carefully read netperf
> documentation.
>
> When you add -n option to netperf, it _will_ use connected UDP sockets
> and your problem will vanish.
>
> You added '-N' only, which is useless for UDP_STREAM.
>
> It might help for UDP_RR, but not UDP_STREAM.
>
>
>
Hi Eric, I used "-n" as well with "-N" but still the problem doesn't go away.
This is what I have done -
Started "netserver" on local/test setup
#netserver
Starting netserver with host 'IN(6)ADDR_ANY' port '12865' and family AF_UNSPEC
It starts listening on port "12865"
From remote setup, started multiple netperf using different ports for data sockets specified using "-P" with "-N" and "-n" options specified as well.
netperf -H 192.168.200.40 -l 150 -t UDP_STREAM -T 8,8 -- -N -n -m 1400 -P 6660,5550 &
netperf -H 192.168.200.40 -l 150 -t UDP_STREAM -T 9,9 -- -N -n -m 1400 -P 9990,9880 &
netperf -H 192.168.200.40 -l 150 -t UDP_STREAM -T 10,10 -- -N -n -m 1400 -P 4455,4400 &
netperf -H 192.168.200.40 -l 150 -t UDP_STREAM -T 11,11 -- -N -n -m 1400 -P 3300,7800 &
netperf -H 192.168.200.40 -l 150 -t UDP_STREAM -T 12,12 -- -N -n -m 1400 -P 50512,44444 &
netperf -H 192.168.200.40 -l 150 -t UDP_STREAM -T 13,13 -- -N -n -m 1400 -P 10512,45672 &
netperf -H 192.168.200.40 -l 150 -t UDP_STREAM -T 14,14 -- -N -n -m 1400 -P 8888,56721 &
netperf -H 192.168.200.40 -l 150 -t UDP_STREAM -T 15,15 -- -N -n -m 1400 -P 9300,8899 &
When on local/test receiving setup, I dump skb's IP header protocol field in .ndo_rx_flow_steer() handler - it is still always IPPROTO_TCP.
Which has destined port 12865. But that handler never receives a SKB whose IP header protocol field is set to IPPROTO_UDP.
As suspected, I believe in receive flow, packets always go in the path where it never match any entry in global flow table in get_rps_cpu() function
,possibly due to packets don't get received from the flow of inet_recvmsg() which updates the global flow table ?
3571 /* First check into global flow table if there is a match */
3572 ident = sock_flow_table->ents[hash & sock_flow_table->mask];
3573 if ((ident ^ hash) & ~rps_cpu_mask)
3574 goto try_rps;
Hence, it never call set_rps_cpu() which internally is supposed to call .ndo_rx_flow_steer() for the SKB's whose flows to be steered.
On another side, when I use "Iperf" for sending UDP stream, which I believe receives the packets from the intet_recvmsg() flow
and I do see flows getting steered for UDP packets. [Actually seeing SKB's whose IP header protocol set to IPPROTO_UDP arriving in .ndo-rx_flow_steer()].
iperf -s -u
iperf -u -c 192.168.200.40 -t 3000 -i 10 -P 8
Thanks,
Manish
^ permalink raw reply
* Re: [PATCH net-next v9 1/1] net: phy: Cleanup the Edge-Rate feature in Microsemi PHYs.
From: Andrew Lunn @ 2016-10-09 20:06 UTC (permalink / raw)
To: Allan W. Nielsen; +Cc: netdev, f.fainelli, raju.lakkaraju
In-Reply-To: <20161009194534.GA20767@microsemi.com>
> Year... I was actually a bit confused about this... But assumed that you had
> some conventions about saving "input" configuration.
Nope.
Humm, actually, i messed up here and missed something. Sorry.
You should really do all the DT parsing in the probe function, or a
function it calls. We want the probe to return -EINVAL if the device
tree is invalid. Either you can program the magic value immediately,
if it will survive a reset, or save it in the private structure until
the init is called.
Andrew
^ permalink raw reply
* [PATCH v2 3/3] net: smsc91x: add u16 workaround for pxa platforms
From: Robert Jarzmik @ 2016-10-09 20:33 UTC (permalink / raw)
To: Rob Herring, Mark Rutland, Nicolas Pitre,
Russell King - ARM Linux, Arnd Bergmann
Cc: netdev, devicetree, linux-kernel, Robert Jarzmik, Jeremy Linton
In-Reply-To: <1476045227-2970-1-git-send-email-robert.jarzmik@free.fr>
Add a workaround for mainstone, idp and stargate2 boards, for u16 writes
which must be aligned on 32 bits addresses.
Signed-off-by: Robert Jarzmik <robert.jarzmik@free.fr>
Cc: Jeremy Linton <jeremy.linton@arm.com>
---
Since v1: rename dt property to pxa-u16-align4
change the binding documentation file
---
Documentation/devicetree/bindings/net/smsc-lan91c111.txt | 2 ++
1 file changed, 2 insertions(+)
diff --git a/Documentation/devicetree/bindings/net/smsc-lan91c111.txt b/Documentation/devicetree/bindings/net/smsc-lan91c111.txt
index e77e167593db..309e37eb7c7c 100644
--- a/Documentation/devicetree/bindings/net/smsc-lan91c111.txt
+++ b/Documentation/devicetree/bindings/net/smsc-lan91c111.txt
@@ -13,3 +13,5 @@ Optional properties:
16-bit access only.
- power-gpios: GPIO to control the PWRDWN pin
- reset-gpios: GPIO to control the RESET pin
+- pxa-u16-align4 : Boolean, put in place the workaround the force all
+ u16 writes to be 32 bits aligned
--
2.1.4
^ permalink raw reply related
* [PATCH v2 1/3] net: smc91x: isolate u16 writes alignment workaround
From: Robert Jarzmik @ 2016-10-09 20:33 UTC (permalink / raw)
To: Rob Herring, Mark Rutland, Nicolas Pitre,
Russell King - ARM Linux, Arnd Bergmann
Cc: netdev, devicetree, linux-kernel, Robert Jarzmik
Writes to u16 has a special handling on 3 PXA platforms, where the
hardware wiring forces these writes to be u32 aligned.
This patch isolates this handling for PXA platforms as before, but
enables this "workaround" to be set up dynamically, which will be the
case in device-tree build types.
This patch was tested on 2 PXA platforms : mainstone, which relies on
the workaround, and lubbock, which doesn't.
Signed-off-by: Robert Jarzmik <robert.jarzmik@free.fr>
---
drivers/net/ethernet/smsc/smc91x.c | 6 ++-
drivers/net/ethernet/smsc/smc91x.h | 80 ++++++++++++++++++++++----------------
2 files changed, 52 insertions(+), 34 deletions(-)
diff --git a/drivers/net/ethernet/smsc/smc91x.c b/drivers/net/ethernet/smsc/smc91x.c
index 77ad2a3f59db..b1f74e06d98e 100644
--- a/drivers/net/ethernet/smsc/smc91x.c
+++ b/drivers/net/ethernet/smsc/smc91x.c
@@ -602,7 +602,8 @@ static void smc_hardware_send_pkt(unsigned long data)
SMC_PUSH_DATA(lp, buf, len & ~1);
/* Send final ctl word with the last byte if there is one */
- SMC_outw(((len & 1) ? (0x2000 | buf[len-1]) : 0), ioaddr, DATA_REG(lp));
+ SMC_outw(lp, ((len & 1) ? (0x2000 | buf[len-1]) : 0), ioaddr,
+ DATA_REG(lp));
/*
* If THROTTLE_TX_PKTS is set, we stop the queue here. This will
@@ -2276,6 +2277,9 @@ static int smc_drv_probe(struct platform_device *pdev)
memcpy(&lp->cfg, pd, sizeof(lp->cfg));
lp->io_shift = SMC91X_IO_SHIFT(lp->cfg.flags);
}
+ lp->half_word_align4 =
+ machine_is_mainstone() || machine_is_stargate2() ||
+ machine_is_pxa_idp();
#if IS_BUILTIN(CONFIG_OF)
match = of_match_device(of_match_ptr(smc91x_match), &pdev->dev);
diff --git a/drivers/net/ethernet/smsc/smc91x.h b/drivers/net/ethernet/smsc/smc91x.h
index 1a55c7976df0..2b7752db8635 100644
--- a/drivers/net/ethernet/smsc/smc91x.h
+++ b/drivers/net/ethernet/smsc/smc91x.h
@@ -66,10 +66,10 @@
#define SMC_IRQ_FLAGS (-1) /* from resource */
/* We actually can't write halfwords properly if not word aligned */
-static inline void SMC_outw(u16 val, void __iomem *ioaddr, int reg)
+static inline void _SMC_outw_align4(u16 val, void __iomem *ioaddr, int reg,
+ bool use_align4_workaround)
{
- if ((machine_is_mainstone() || machine_is_stargate2() ||
- machine_is_pxa_idp()) && reg & 2) {
+ if (use_align4_workaround) {
unsigned int v = val << 16;
v |= readl(ioaddr + (reg & ~2)) & 0xffff;
writel(v, ioaddr + (reg & ~2));
@@ -78,6 +78,12 @@ static inline void SMC_outw(u16 val, void __iomem *ioaddr, int reg)
}
}
+#define SMC_outw(lp, v, a, r) \
+ _SMC_outw_align4((v), (a), (r), \
+ IS_BUILTIN(CONFIG_ARCH_PXA) && ((r) & 2) && \
+ lp->half_word_align4)
+
+
#elif defined(CONFIG_SH_SH4202_MICRODEV)
#define SMC_CAN_USE_8BIT 0
@@ -88,7 +94,8 @@ static inline void SMC_outw(u16 val, void __iomem *ioaddr, int reg)
#define SMC_inw(a, r) inw((a) + (r) - 0xa0000000)
#define SMC_inl(a, r) inl((a) + (r) - 0xa0000000)
#define SMC_outb(v, a, r) outb(v, (a) + (r) - 0xa0000000)
-#define SMC_outw(v, a, r) outw(v, (a) + (r) - 0xa0000000)
+#define _SMC_outw(v, a, r) outw(v, (a) + (r) - 0xa0000000)
+#define SMC_outw(lp, v, a, r) _SMC_outw((v), (a), (r))
#define SMC_outl(v, a, r) outl(v, (a) + (r) - 0xa0000000)
#define SMC_insl(a, r, p, l) insl((a) + (r) - 0xa0000000, p, l)
#define SMC_outsl(a, r, p, l) outsl((a) + (r) - 0xa0000000, p, l)
@@ -106,7 +113,8 @@ static inline void SMC_outw(u16 val, void __iomem *ioaddr, int reg)
#define SMC_inb(a, r) inb(((u32)a) + (r))
#define SMC_inw(a, r) inw(((u32)a) + (r))
#define SMC_outb(v, a, r) outb(v, ((u32)a) + (r))
-#define SMC_outw(v, a, r) outw(v, ((u32)a) + (r))
+#define _SMC_outw(v, a, r) outw(v, ((u32)a) + (r))
+#define SMC_outw(lp, v, a, r) _SMC_outw((v), (a), (r))
#define SMC_insw(a, r, p, l) insw(((u32)a) + (r), p, l)
#define SMC_outsw(a, r, p, l) outsw(((u32)a) + (r), p, l)
@@ -134,7 +142,8 @@ static inline void SMC_outw(u16 val, void __iomem *ioaddr, int reg)
#define SMC_inw(a, r) readw((a) + (r))
#define SMC_inl(a, r) readl((a) + (r))
#define SMC_outb(v, a, r) writeb(v, (a) + (r))
-#define SMC_outw(v, a, r) writew(v, (a) + (r))
+#define _SMC_outw(v, a, r) writew(v, (a) + (r))
+#define SMC_outw(lp, v, a, r) _SMC_outw((v), (a), (r))
#define SMC_outl(v, a, r) writel(v, (a) + (r))
#define SMC_insw(a, r, p, l) readsw((a) + (r), p, l)
#define SMC_outsw(a, r, p, l) writesw((a) + (r), p, l)
@@ -166,7 +175,8 @@ static inline void mcf_outsw(void *a, unsigned char *p, int l)
}
#define SMC_inw(a, r) _swapw(readw((a) + (r)))
-#define SMC_outw(v, a, r) writew(_swapw(v), (a) + (r))
+#define _SMC_outw(v, a, r) writew(_swapw(v), (a) + (r))
+#define SMC_outw(lp, v, a, r) _SMC_outw((v), (a), (r))
#define SMC_insw(a, r, p, l) mcf_insw(a + r, p, l)
#define SMC_outsw(a, r, p, l) mcf_outsw(a + r, p, l)
@@ -200,7 +210,8 @@ static inline void mcf_outsw(void *a, unsigned char *p, int l)
#define SMC_inw(a, r) ioread16((a) + (r))
#define SMC_inl(a, r) ioread32((a) + (r))
#define SMC_outb(v, a, r) iowrite8(v, (a) + (r))
-#define SMC_outw(v, a, r) iowrite16(v, (a) + (r))
+#define _SMC_outw(v, a, r) iowrite16(v, (a) + (r))
+#define SMC_outw(lp, v, a, r) _SMC_outw((v), (a), (r))
#define SMC_outl(v, a, r) iowrite32(v, (a) + (r))
#define SMC_insw(a, r, p, l) ioread16_rep((a) + (r), p, l)
#define SMC_outsw(a, r, p, l) iowrite16_rep((a) + (r), p, l)
@@ -262,6 +273,8 @@ struct smc_local {
/* the low address lines on some platforms aren't connected... */
int io_shift;
+ /* on some platforms a u16 write must be 4-bytes aligned */
+ bool half_word_align4;
struct smc91x_platdata cfg;
};
@@ -420,12 +433,13 @@ smc_pxa_dma_insw(void __iomem *ioaddr, struct smc_local *lp, int reg, int dma,
* Any 16-bit access is performed with two 8-bit accesses if the hardware
* can't do it directly. Most registers are 16-bit so those are mandatory.
*/
-#define SMC_outw(x, ioaddr, reg) \
+#define _SMC_outw(x, ioaddr, reg) \
do { \
unsigned int __val16 = (x); \
SMC_outb( __val16, ioaddr, reg ); \
SMC_outb( __val16 >> 8, ioaddr, reg + (1 << SMC_IO_SHIFT));\
} while (0)
+#define SMC_outw(lp, v, a, r) _SMC_outw((v), (a), (r))
#define SMC_inw(ioaddr, reg) \
({ \
unsigned int __val16; \
@@ -882,7 +896,7 @@ static const char * chip_ids[ 16 ] = {
else if (SMC_8BIT(lp)) \
SMC_outb(x, ioaddr, PN_REG(lp)); \
else \
- SMC_outw(x, ioaddr, PN_REG(lp)); \
+ SMC_outw(lp, x, ioaddr, PN_REG(lp)); \
} while (0)
#define SMC_GET_AR(lp) \
@@ -910,7 +924,7 @@ static const char * chip_ids[ 16 ] = {
int __mask; \
local_irq_save(__flags); \
__mask = SMC_inw(ioaddr, INT_REG(lp)) & ~0xff; \
- SMC_outw(__mask | (x), ioaddr, INT_REG(lp)); \
+ SMC_outw(lp, __mask | (x), ioaddr, INT_REG(lp)); \
local_irq_restore(__flags); \
} \
} while (0)
@@ -924,7 +938,7 @@ static const char * chip_ids[ 16 ] = {
if (SMC_8BIT(lp)) \
SMC_outb(x, ioaddr, IM_REG(lp)); \
else \
- SMC_outw((x) << 8, ioaddr, INT_REG(lp)); \
+ SMC_outw(lp, (x) << 8, ioaddr, INT_REG(lp)); \
} while (0)
#define SMC_CURRENT_BANK(lp) SMC_inw(ioaddr, BANK_SELECT)
@@ -934,22 +948,22 @@ static const char * chip_ids[ 16 ] = {
if (SMC_MUST_ALIGN_WRITE(lp)) \
SMC_outl((x)<<16, ioaddr, 12<<SMC_IO_SHIFT); \
else \
- SMC_outw(x, ioaddr, BANK_SELECT); \
+ SMC_outw(lp, x, ioaddr, BANK_SELECT); \
} while (0)
#define SMC_GET_BASE(lp) SMC_inw(ioaddr, BASE_REG(lp))
-#define SMC_SET_BASE(lp, x) SMC_outw(x, ioaddr, BASE_REG(lp))
+#define SMC_SET_BASE(lp, x) SMC_outw(lp, x, ioaddr, BASE_REG(lp))
#define SMC_GET_CONFIG(lp) SMC_inw(ioaddr, CONFIG_REG(lp))
-#define SMC_SET_CONFIG(lp, x) SMC_outw(x, ioaddr, CONFIG_REG(lp))
+#define SMC_SET_CONFIG(lp, x) SMC_outw(lp, x, ioaddr, CONFIG_REG(lp))
#define SMC_GET_COUNTER(lp) SMC_inw(ioaddr, COUNTER_REG(lp))
#define SMC_GET_CTL(lp) SMC_inw(ioaddr, CTL_REG(lp))
-#define SMC_SET_CTL(lp, x) SMC_outw(x, ioaddr, CTL_REG(lp))
+#define SMC_SET_CTL(lp, x) SMC_outw(lp, x, ioaddr, CTL_REG(lp))
#define SMC_GET_MII(lp) SMC_inw(ioaddr, MII_REG(lp))
@@ -960,18 +974,18 @@ static const char * chip_ids[ 16 ] = {
if (SMC_MUST_ALIGN_WRITE(lp)) \
SMC_outl((x)<<16, ioaddr, SMC_REG(lp, 8, 1)); \
else \
- SMC_outw(x, ioaddr, GP_REG(lp)); \
+ SMC_outw(lp, x, ioaddr, GP_REG(lp)); \
} while (0)
-#define SMC_SET_MII(lp, x) SMC_outw(x, ioaddr, MII_REG(lp))
+#define SMC_SET_MII(lp, x) SMC_outw(lp, x, ioaddr, MII_REG(lp))
#define SMC_GET_MIR(lp) SMC_inw(ioaddr, MIR_REG(lp))
-#define SMC_SET_MIR(lp, x) SMC_outw(x, ioaddr, MIR_REG(lp))
+#define SMC_SET_MIR(lp, x) SMC_outw(lp, x, ioaddr, MIR_REG(lp))
#define SMC_GET_MMU_CMD(lp) SMC_inw(ioaddr, MMU_CMD_REG(lp))
-#define SMC_SET_MMU_CMD(lp, x) SMC_outw(x, ioaddr, MMU_CMD_REG(lp))
+#define SMC_SET_MMU_CMD(lp, x) SMC_outw(lp, x, ioaddr, MMU_CMD_REG(lp))
#define SMC_GET_FIFO(lp) SMC_inw(ioaddr, FIFO_REG(lp))
@@ -982,14 +996,14 @@ static const char * chip_ids[ 16 ] = {
if (SMC_MUST_ALIGN_WRITE(lp)) \
SMC_outl((x)<<16, ioaddr, SMC_REG(lp, 4, 2)); \
else \
- SMC_outw(x, ioaddr, PTR_REG(lp)); \
+ SMC_outw(lp, x, ioaddr, PTR_REG(lp)); \
} while (0)
#define SMC_GET_EPH_STATUS(lp) SMC_inw(ioaddr, EPH_STATUS_REG(lp))
#define SMC_GET_RCR(lp) SMC_inw(ioaddr, RCR_REG(lp))
-#define SMC_SET_RCR(lp, x) SMC_outw(x, ioaddr, RCR_REG(lp))
+#define SMC_SET_RCR(lp, x) SMC_outw(lp, x, ioaddr, RCR_REG(lp))
#define SMC_GET_REV(lp) SMC_inw(ioaddr, REV_REG(lp))
@@ -1000,12 +1014,12 @@ static const char * chip_ids[ 16 ] = {
if (SMC_MUST_ALIGN_WRITE(lp)) \
SMC_outl((x)<<16, ioaddr, SMC_REG(lp, 8, 0)); \
else \
- SMC_outw(x, ioaddr, RPC_REG(lp)); \
+ SMC_outw(lp, x, ioaddr, RPC_REG(lp)); \
} while (0)
#define SMC_GET_TCR(lp) SMC_inw(ioaddr, TCR_REG(lp))
-#define SMC_SET_TCR(lp, x) SMC_outw(x, ioaddr, TCR_REG(lp))
+#define SMC_SET_TCR(lp, x) SMC_outw(lp, x, ioaddr, TCR_REG(lp))
#ifndef SMC_GET_MAC_ADDR
#define SMC_GET_MAC_ADDR(lp, addr) \
@@ -1022,18 +1036,18 @@ static const char * chip_ids[ 16 ] = {
#define SMC_SET_MAC_ADDR(lp, addr) \
do { \
- SMC_outw(addr[0]|(addr[1] << 8), ioaddr, ADDR0_REG(lp)); \
- SMC_outw(addr[2]|(addr[3] << 8), ioaddr, ADDR1_REG(lp)); \
- SMC_outw(addr[4]|(addr[5] << 8), ioaddr, ADDR2_REG(lp)); \
+ SMC_outw(lp, addr[0]|(addr[1] << 8), ioaddr, ADDR0_REG(lp)); \
+ SMC_outw(lp, addr[2]|(addr[3] << 8), ioaddr, ADDR1_REG(lp)); \
+ SMC_outw(lp, addr[4]|(addr[5] << 8), ioaddr, ADDR2_REG(lp)); \
} while (0)
#define SMC_SET_MCAST(lp, x) \
do { \
const unsigned char *mt = (x); \
- SMC_outw(mt[0] | (mt[1] << 8), ioaddr, MCAST_REG1(lp)); \
- SMC_outw(mt[2] | (mt[3] << 8), ioaddr, MCAST_REG2(lp)); \
- SMC_outw(mt[4] | (mt[5] << 8), ioaddr, MCAST_REG3(lp)); \
- SMC_outw(mt[6] | (mt[7] << 8), ioaddr, MCAST_REG4(lp)); \
+ SMC_outw(lp, mt[0] | (mt[1] << 8), ioaddr, MCAST_REG1(lp)); \
+ SMC_outw(lp, mt[2] | (mt[3] << 8), ioaddr, MCAST_REG2(lp)); \
+ SMC_outw(lp, mt[4] | (mt[5] << 8), ioaddr, MCAST_REG3(lp)); \
+ SMC_outw(lp, mt[6] | (mt[7] << 8), ioaddr, MCAST_REG4(lp)); \
} while (0)
#define SMC_PUT_PKT_HDR(lp, status, length) \
@@ -1042,8 +1056,8 @@ static const char * chip_ids[ 16 ] = {
SMC_outl((status) | (length)<<16, ioaddr, \
DATA_REG(lp)); \
else { \
- SMC_outw(status, ioaddr, DATA_REG(lp)); \
- SMC_outw(length, ioaddr, DATA_REG(lp)); \
+ SMC_outw(lp, status, ioaddr, DATA_REG(lp)); \
+ SMC_outw(lp, length, ioaddr, DATA_REG(lp)); \
} \
} while (0)
--
2.1.4
^ permalink raw reply related
* [PATCH v2 2/3] net: smc91x: take into account half-word workaround
From: Robert Jarzmik @ 2016-10-09 20:33 UTC (permalink / raw)
To: Rob Herring, Mark Rutland, Nicolas Pitre,
Russell King - ARM Linux, Arnd Bergmann
Cc: netdev, devicetree, linux-kernel, Robert Jarzmik
In-Reply-To: <1476045227-2970-1-git-send-email-robert.jarzmik@free.fr>
For device-tree builds, platforms such as mainstone, idp and stargate2
must have their u16 writes all aligned on 32 bit boundaries. This is
already enabled in platform data builds, and this patch adds it to
device-tree builds.
Signed-off-by: Robert Jarzmik <robert.jarzmik@free.fr>
---
Since v1: rename dt property to pxa-u16-align4
---
drivers/net/ethernet/smsc/smc91x.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/net/ethernet/smsc/smc91x.c b/drivers/net/ethernet/smsc/smc91x.c
index b1f74e06d98e..e2f151258b38 100644
--- a/drivers/net/ethernet/smsc/smc91x.c
+++ b/drivers/net/ethernet/smsc/smc91x.c
@@ -2323,6 +2323,8 @@ static int smc_drv_probe(struct platform_device *pdev)
if (!device_property_read_u32(&pdev->dev, "reg-shift",
&val))
lp->io_shift = val;
+ lp->half_word_align4 =
+ device_property_read_bool(&pdev->dev, "pxa-u16-align4");
}
#endif
--
2.1.4
^ permalink raw reply related
* Please Check.
From: Jose Wong @ 2016-10-09 21:16 UTC (permalink / raw)
I have a proposal to share
Joseph
^ permalink raw reply
* slab corruption with current -git (was Re: [git pull] vfs pile 1 (splice))
From: Linus Torvalds @ 2016-10-09 21:31 UTC (permalink / raw)
To: Al Viro, Andrew Morton, Jens Axboe, Ted Ts'o,
Christoph Lameter, David Miller, Pablo Neira Ayuso, Aaron Conole
Cc: Linux Kernel Mailing List, linux-fsdevel, Network Development,
NetFilter
On Sun, Oct 9, 2016 at 12:11 PM, Linus Torvalds
<torvalds@linux-foundation.org> wrote:
>
> Anyway, I don't think I can bisect it, but I'll try to narrow it down
> a *bit* at least.
>
> Not doing any more pulls on this unstable base, I've been puttering
> around in trying to clean up some stupid printk logging issues
> instead.
So I finally got a oops with slub debugging enabled. It doesn't really
narrow things down, though, it kind of extends on the possible
suspects. Now adding David Miller and Pablo, because it looks like it
may be netfilter that does something bad and corrupts memory.
Of course, maybe this is another symptom, and not the root cause for
my troubles, but it does look like it might be getting closer to the
cause... In particular, now it very much looks like a use-after-free
in the netfilter code, which *could* explain my original symptom with
later allocation users oopsing randomly.
Without further ado, here's the new oops:
general protection fault: 0000 [#1] SMP
CPU: 7 PID: 169 Comm: kworker/u16:7 Not tainted 4.8.0-11288-gb66484cd7470 #1
Hardware name: System manufacturer System Product Name/Z170-K, BIOS
1803 05/06/2016
Workqueue: netns cleanup_net
task: ffff91935e001fc0 task.stack: ffffb4e2c213c000
RIP: nf_unregister_net_hook+0x5f/0x190
RSP: 0000:ffffb4e2c213fd40 EFLAGS: 00010202
RAX: 6b6b6b6b6b6b6b6b RBX: ffff91933c4ab968 RCX: 0000000000000002
RDX: 0000000000000002 RSI: ffffffffc0642280 RDI: ffffffff91cf9820
RBP: ffffb4e2c213fd58 R08: ffff91933c4a86c8 R09: 0000000000000025
R10: 00000000000000cc R11: ffff91935dd22000 R12: ffffffffc0642280
R13: ffff91934cc0ea80 R14: ffffffff91cf97e0 R15: 00000000ffffffff
FS: 0000000000000000(0000) GS:ffff919376dc0000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 0000000003e7c000 CR3: 00000003fdb62000 CR4: 00000000003406e0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
Call Trace:
netfilter_net_exit+0x2f/0x60
ops_exit_list.isra.4+0x38/0x60
cleanup_net+0x1ba/0x2a0
process_one_work+0x1f1/0x480
worker_thread+0x48/0x4d0
? process_one_work+0x480/0x480
? process_one_work+0x480/0x480
kthread+0xd9/0xf0
? kthread_park+0x60/0x60
ret_from_fork+0x22/0x30
Code: 0f b6 ca 48 8d 84 c8 00 01 00 00 49 8b 5c c5 00 48 85 db 0f
84 cb 00 00 00 4c 3b 63 40 48 8b 03 0f 84 e9 00 00 00 48 85 c0 74 26
<4c> 3b 60 40 75 08 e9 ef 00 00 00 48 89 d8 48 8b 18 48 85 db 0f
RIP [<ffffffff916bae8f>] nf_unregister_net_hook+0x5f/0x190
and note the value in %rax: 6b is POISON_FREE, so it very much looks
like it's a pointer loaded from a free'd allocation.
The code disassembles to
0: 0f b6 ca movzbl %dl,%ecx
3: 48 8d 84 c8 00 01 00 lea 0x100(%rax,%rcx,8),%rax
a: 00
b: 49 8b 5c c5 00 mov 0x0(%r13,%rax,8),%rbx
10: 48 85 db test %rbx,%rbx
13: 0f 84 cb 00 00 00 je 0xe4
19: 4c 3b 63 40 cmp 0x40(%rbx),%r12
1d: 48 8b 03 mov (%rbx),%rax
20: 0f 84 e9 00 00 00 je 0x10f
26: 48 85 c0 test %rax,%rax
29: 74 26 je 0x51
2b:* 4c 3b 60 40 cmp 0x40(%rax),%r12 <-- trapping instruction
2f: 75 08 jne 0x39
31: e9 ef 00 00 00 jmpq 0x125
36: 48 89 d8 mov %rbx,%rax
39: 48 8b 18 mov (%rax),%rbx
3c: 48 85 db test %rbx,%rbx
and that oopsing instruction seems to be the compare of
"hooks_entry->orig_ops" from hooks_entry in this expression:
if (hooks_entry && hooks_entry->orig_ops == reg) {
so hooks_entry() is bogus. It was gotten from
hooks_entry = nf_hook_entry_head(net, reg);
but that's as far as I dug. And yes, I do have
CONFIG_NETFILTER_INGRESS=y in case that matters.
And all this code has changed pretty radically in commit e3b37f11e6e4
("netfilter: replace list_head with single linked list"), and there
was clearly already something wrong with that code, with commit
5119e4381a90 ("netfilter: Fix potential null pointer dereference")
adding the test against NULL. But I suspect that only hid the "oops,
it's actually not NULL, it loaded some uninitialized value" problem.
Over to the networking guys.. Ideas?
Linus
^ permalink raw reply
* Re: [PATCH v2 1/3] net: smc91x: isolate u16 writes alignment workaround
From: Andy Shevchenko @ 2016-10-09 21:55 UTC (permalink / raw)
To: Robert Jarzmik
Cc: Rob Herring, Mark Rutland, Nicolas Pitre,
Russell King - ARM Linux, Arnd Bergmann, netdev, devicetree,
linux-kernel@vger.kernel.org
In-Reply-To: <1476045227-2970-1-git-send-email-robert.jarzmik@free.fr>
On Sun, Oct 9, 2016 at 11:33 PM, Robert Jarzmik <robert.jarzmik@free.fr> wrote:
> Writes to u16 has a special handling on 3 PXA platforms, where the
> hardware wiring forces these writes to be u32 aligned.
>
> This patch isolates this handling for PXA platforms as before, but
> enables this "workaround" to be set up dynamically, which will be the
> case in device-tree build types.
>
> This patch was tested on 2 PXA platforms : mainstone, which relies on
> the workaround, and lubbock, which doesn't.
> @@ -2276,6 +2277,9 @@ static int smc_drv_probe(struct platform_device *pdev)
> memcpy(&lp->cfg, pd, sizeof(lp->cfg));
> lp->io_shift = SMC91X_IO_SHIFT(lp->cfg.flags);
> }
> + lp->half_word_align4 =
> + machine_is_mainstone() || machine_is_stargate2() ||
> + machine_is_pxa_idp();
> /* We actually can't write halfwords properly if not word aligned */
> -static inline void SMC_outw(u16 val, void __iomem *ioaddr, int reg)
> +static inline void _SMC_outw_align4(u16 val, void __iomem *ioaddr, int reg,
> + bool use_align4_workaround)
> {
> - if ((machine_is_mainstone() || machine_is_stargate2() ||
> - machine_is_pxa_idp()) && reg & 2) {
> + if (use_align4_workaround) {
> unsigned int v = val << 16;
> v |= readl(ioaddr + (reg & ~2)) & 0xffff;
> writel(v, ioaddr + (reg & ~2));
> +#define SMC_outw(lp, v, a, r) \
> + _SMC_outw_align4((v), (a), (r), \
> + IS_BUILTIN(CONFIG_ARCH_PXA) && ((r) & 2) && \
> + lp->half_word_align4)
Hmm... Isn't enough to have just (r) & 2 && lp->half_word_align4 ?
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply
* Re: [PATCH net-next v9 1/1] net: phy: Cleanup the Edge-Rate feature in Microsemi PHYs.
From: Allan W. Nielsen @ 2016-10-09 19:45 UTC (permalink / raw)
To: Andrew Lunn; +Cc: netdev, f.fainelli, raju.lakkaraju
In-Reply-To: <20161007202225.GC8266@lunn.ch>
Hi,
On 07/10/16 22:22, Andrew Lunn wrote:
> Overall, this is much better. I just have a few nitpicks.
It is good to hear that we are getting closer ;-)
> dt-bindings/net/mscc-phy-vsc8531.h is removed by this patch. It would
> be good to also remove the reference.
My bad.
> You don't need edge_slowdown and vddmac in the private structure,
> since they are never used after determining what rate_magic is.
Year... I was actually a bit confused about this... But assumed that you had
some conventions about saving "input" configuration.
Well, clearly not - I will clean this up.
Actually, there is no need to store rate_magic either... It is only used in the
init function. This means that there is no need for private date...
The code could look somthing like this (it is not tested, so just look at see if
you like the idea):
#ifdef CONFIG_OF_MDIO
static int vsc85xx_edge_rate_magic_get(struct phy_device *phydev)
{
int rc;
u8 sd;
u16 vdd;
struct device *dev = &phydev->mdio.dev;
struct device_node *of_node = dev->of_node;
u8 sd_array_size = ARRAY_SIZE(edge_table[0].slowdown);
if (!of_node)
return -ENODEV;
rc = of_property_read_u16(of_node, "vsc8531,vddmac", &vdd);
if (rc != 0)
vdd = MSCC_VDDMAC_3300;
rc = of_property_read_u8(of_node, "vsc8531,edge-slowdown", &sd);
if (rc != 0)
sd = 0;
for (vdd = 0; vdd < ARRAY_SIZE(edge_table); vdd++)
if (edge_table[vdd].vddmac == vddmac)
for (sd = 0; sd < sd_array_size; sd++)
if (edge_table[vdd].slowdown[sd] == slowdown)
return (sd_array_size - sd - 1);
return -EINVAL;
}
#else
static int vsc85xx_edge_rate_magic_get(struct phy_device *phydev)
{
return 0;
}
#endif /* CONFIG_OF_MDIO */
static int vsc85xx_config_init(struct phy_device *phydev)
{
int rc, rate_magic;
...
rate_magic = vsc85xx_edge_rate_magic_get(phydev);
if (rate_magic < 0)
return rate_magic;
rc = vsc85xx_edge_rate_cntl_set(phydev, rate_magic);
if (rc)
return rc;
...
}
This is clearly how I would prefere it, as it would simplify the implementation.
It should be no problem to have this tested, and have a new patch avialable
tomorrow.
/Allan
^ permalink raw reply
* Re: Accelerated receive flow steering (aRFS) for UDP
From: Eric Dumazet @ 2016-10-09 22:33 UTC (permalink / raw)
To: Chopra, Manish, Rick Jones
Cc: netdev@vger.kernel.org, maorg@mellanox.com, tom@herbertland.com
In-Reply-To: <SN1PR07MB2447D70FD02730AFCEA410A089D80@SN1PR07MB2447.namprd07.prod.outlook.com>
On Sun, 2016-10-09 at 19:48 +0000, Chopra, Manish wrote:
> Hi Eric, I used "-n" as well with "-N" but still the problem doesn't
> go away.
>
> This is what I have done -
>
> Started "netserver" on local/test setup
>
> #netserver
> Starting netserver with host 'IN(6)ADDR_ANY' port '12865' and family
> AF_UNSPEC
>
> It starts listening on port "12865"
>
> From remote setup, started multiple netperf using different ports for
> data sockets specified using "-P" with "-N" and "-n" options specified
> as well.
> netperf -H 192.168.200.40 -l 150 -t UDP_STREAM -T 8,8 -- -N -n -m 1400
> -P 6660,5550 &
> netperf -H 192.168.200.40 -l 150 -t UDP_STREAM -T 9,9 -- -N -n -m 1400
> -P 9990,9880 &
> netperf -H 192.168.200.40 -l 150 -t UDP_STREAM -T 10,10 -- -N -n -m
> 1400 -P 4455,4400 &
> netperf -H 192.168.200.40 -l 150 -t UDP_STREAM -T 11,11 -- -N -n -m
> 1400 -P 3300,7800 &
> netperf -H 192.168.200.40 -l 150 -t UDP_STREAM -T 12,12 -- -N -n -m
> 1400 -P 50512,44444 &
> netperf -H 192.168.200.40 -l 150 -t UDP_STREAM -T 13,13 -- -N -n -m
> 1400 -P 10512,45672 &
> netperf -H 192.168.200.40 -l 150 -t UDP_STREAM -T 14,14 -- -N -n -m
> 1400 -P 8888,56721 &
> netperf -H 192.168.200.40 -l 150 -t UDP_STREAM -T 15,15 -- -N -n -m
> 1400 -P 9300,8899 &
>
> When on local/test receiving setup, I dump skb's IP header protocol
> field in .ndo_rx_flow_steer() handler - it is still always
> IPPROTO_TCP.
> Which has destined port 12865. But that handler never receives a SKB
> whose IP header protocol field is set to IPPROTO_UDP.
>
> As suspected, I believe in receive flow, packets always go in the path
> where it never match any entry in global flow table in get_rps_cpu()
> function
> ,possibly due to packets don't get received from the flow of
> inet_recvmsg() which updates the global flow table ?
>
> 3571 /* First check into global flow table if there is
> a match */
> 3572 ident = sock_flow_table->ents[hash &
> sock_flow_table->mask];
> 3573 if ((ident ^ hash) & ~rps_cpu_mask)
> 3574 goto try_rps;
>
> Hence, it never call set_rps_cpu() which internally is supposed to
> call .ndo_rx_flow_steer() for the SKB's whose flows to be steered.
>
> On another side, when I use "Iperf" for sending UDP stream, which I
> believe receives the packets from the intet_recvmsg() flow
> and I do see flows getting steered for UDP packets. [Actually seeing
> SKB's whose IP header protocol set to IPPROTO_UDP arriving
> in .ndo-rx_flow_steer()].
>
> iperf -s -u
> iperf -u -c 192.168.200.40 -t 3000 -i 10 -P 8
OK, I am adding/CC Rick Jones, netperf author, since it seems a netperf
bug, not a kernel one.
I believe I already mentioned fact that "UDP_STREAM -- -N" was not doing
a connect() on the receiver side.
>
>
>
^ permalink raw reply
* Re: [PATCH net-next 5/6] qed: Allow chance for fast ramrod completions
From: Eric Dumazet @ 2016-10-10 0:08 UTC (permalink / raw)
To: Yuval Mintz; +Cc: davem, netdev, Yuval Mintz
In-Reply-To: <1476026738-26069-6-git-send-email-Yuval.Mintz@qlogic.com>
On Sun, 2016-10-09 at 18:25 +0300, Yuval Mintz wrote:
> From: Yuval Mintz <Yuval.Mintz@caviumnetworks.com>
>
> Whenever a ramrod is being sent for some device configuration,
> the driver is going to sleep at least 5ms between each iteration
> of polling on the completion of the ramrod.
>
> However, in almost every configuration scenario the firmware
> would be able to comply and complete the ramrod in a manner of
> several usecs. This is especially important in cases where there
> might be a lot of sequential configurations applying to the hardware
> [e.g., RoCE], in which case the existing scheme might cause some
> visible user delays.
>
> This patch changes the completion scheme - instead of immediately
> starting to sleep for a 'long' period, allow the device to quickly
> poll on the first iteration after a couple of usecs.
>
> Signed-off-by: Yuval Mintz <Yuval.Mintz@caviumnetworks.com>
> ---
> drivers/net/ethernet/qlogic/qed/qed_spq.c | 85 +++++++++++++++++++++----------
> 1 file changed, 59 insertions(+), 26 deletions(-)
>
> diff --git a/drivers/net/ethernet/qlogic/qed/qed_spq.c b/drivers/net/ethernet/qlogic/qed/qed_spq.c
> index caff415..259a615 100644
> --- a/drivers/net/ethernet/qlogic/qed/qed_spq.c
> +++ b/drivers/net/ethernet/qlogic/qed/qed_spq.c
> @@ -37,7 +37,11 @@
> ***************************************************************************/
>
> #define SPQ_HIGH_PRI_RESERVE_DEFAULT (1)
> -#define SPQ_BLOCK_SLEEP_LENGTH (1000)
> +
> +#define SPQ_BLOCK_DELAY_MAX_ITER (10)
> +#define SPQ_BLOCK_DELAY_US (10)
> +#define SPQ_BLOCK_SLEEP_MAX_ITER (1000)
> +#define SPQ_BLOCK_SLEEP_MS (5)
>
> /***************************************************************************
> * Blocking Imp. (BLOCK/EBLOCK mode)
> @@ -57,53 +61,81 @@ static void qed_spq_blocking_cb(struct qed_hwfn *p_hwfn,
> smp_wmb();
> }
>
> -static int qed_spq_block(struct qed_hwfn *p_hwfn,
> - struct qed_spq_entry *p_ent,
> - u8 *p_fw_ret)
> +static int __qed_spq_block(struct qed_hwfn *p_hwfn,
> + struct qed_spq_entry *p_ent,
> + u8 *p_fw_ret, bool sleep_between_iter)
> {
> - int sleep_count = SPQ_BLOCK_SLEEP_LENGTH;
> struct qed_spq_comp_done *comp_done;
> - int rc;
> + u32 iter_cnt;
>
> comp_done = (struct qed_spq_comp_done *)p_ent->comp_cb.cookie;
> - while (sleep_count) {
> - /* validate we receive completion update */
> + iter_cnt = sleep_between_iter ? SPQ_BLOCK_SLEEP_MAX_ITER
> + : SPQ_BLOCK_DELAY_MAX_ITER;
> +
> + while (iter_cnt--) {
> + /* Validate we receive completion update */
> smp_rmb();
> if (comp_done->done == 1) {
> if (p_fw_ret)
> *p_fw_ret = comp_done->fw_return_code;
> return 0;
> }
Note that this smp_rmb() and accesses to ->done and ->fw_return_code are
racy.
fq_return_code needs to be written _before_ done.
Something like the following patch would make sense...
diff --git a/drivers/net/ethernet/qlogic/qed/qed_spq.c b/drivers/net/ethernet/qlogic/qed/qed_spq.c
index caff41544898baed09f45a41829cb0ba9c719fb9..eefa45eab3728791f4d15a088c4550f318a1d1da 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_spq.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_spq.c
@@ -50,11 +50,9 @@ static void qed_spq_blocking_cb(struct qed_hwfn *p_hwfn,
comp_done = (struct qed_spq_comp_done *)cookie;
- comp_done->done = 0x1;
- comp_done->fw_return_code = fw_return_code;
+ comp_done->fw_return_code = fw_return_code;
- /* make update visible to waiting thread */
- smp_wmb();
+ smp_store_release(&comp_done->done, 0x1);
}
static int qed_spq_block(struct qed_hwfn *p_hwfn,
@@ -68,8 +66,8 @@ static int qed_spq_block(struct qed_hwfn *p_hwfn,
comp_done = (struct qed_spq_comp_done *)p_ent->comp_cb.cookie;
while (sleep_count) {
/* validate we receive completion update */
- smp_rmb();
- if (comp_done->done == 1) {
+ if (READ_ONCE(comp_done->done) == 1) {
+ smp_read_barrier_depends();
if (p_fw_ret)
*p_fw_ret = comp_done->fw_return_code;
return 0;
@@ -87,8 +85,8 @@ static int qed_spq_block(struct qed_hwfn *p_hwfn,
sleep_count = SPQ_BLOCK_SLEEP_LENGTH;
while (sleep_count) {
/* validate we receive completion update */
- smp_rmb();
- if (comp_done->done == 1) {
+ if (READ_ONCE(comp_done->done) == 1) {
+ smp_read_barrier_depends();
if (p_fw_ret)
*p_fw_ret = comp_done->fw_return_code;
return 0;
@@ -97,7 +95,8 @@ static int qed_spq_block(struct qed_hwfn *p_hwfn,
sleep_count--;
}
- if (comp_done->done == 1) {
+ if (READ_ONCE(comp_done->done) == 1) {
+ smp_read_barrier_depends();
if (p_fw_ret)
*p_fw_ret = comp_done->fw_return_code;
return 0;
^ permalink raw reply related
* Re: slab corruption with current -git (was Re: [git pull] vfs pile 1 (splice))
From: Florian Westphal @ 2016-10-10 0:51 UTC (permalink / raw)
To: Linus Torvalds
Cc: Al Viro, Andrew Morton, Jens Axboe, Ted Ts'o,
Christoph Lameter, David Miller, Pablo Neira Ayuso, Aaron Conole,
Linux Kernel Mailing List, linux-fsdevel, Network Development,
NetFilter
In-Reply-To: <CA+55aFz2U83pG0v12E--nd5c6GZAUpVnT3jHuAwHCFk5XbVX0w@mail.gmail.com>
Linus Torvalds <torvalds@linux-foundation.org> wrote:
> On Sun, Oct 9, 2016 at 12:11 PM, Linus Torvalds
> <torvalds@linux-foundation.org> wrote:
> >
> > Anyway, I don't think I can bisect it, but I'll try to narrow it down
> > a *bit* at least.
> >
> > Not doing any more pulls on this unstable base, I've been puttering
> > around in trying to clean up some stupid printk logging issues
> > instead.
>
> So I finally got a oops with slub debugging enabled. It doesn't really
> narrow things down, though, it kind of extends on the possible
> suspects. Now adding David Miller and Pablo, because it looks like it
> may be netfilter that does something bad and corrupts memory.
Quite possible, the netns interactions are not nice :-/
> Without further ado, here's the new oops:
>
> general protection fault: 0000 [#1] SMP
> CPU: 7 PID: 169 Comm: kworker/u16:7 Not tainted 4.8.0-11288-gb66484cd7470 #1
> Hardware name: System manufacturer System Product Name/Z170-K, BIOS
..
> Call Trace:
> netfilter_net_exit+0x2f/0x60
> ops_exit_list.isra.4+0x38/0x60
> cleanup_net+0x1ba/0x2a0
> process_one_work+0x1f1/0x480
> worker_thread+0x48/0x4d0
> ? process_one_work+0x480/0x480
..
> like it's a pointer loaded from a free'd allocation.
>
> The code disassembles to
>
> 0: 0f b6 ca movzbl %dl,%ecx
> 3: 48 8d 84 c8 00 01 00 lea 0x100(%rax,%rcx,8),%rax
> a: 00
> b: 49 8b 5c c5 00 mov 0x0(%r13,%rax,8),%rbx
> 10: 48 85 db test %rbx,%rbx
> 13: 0f 84 cb 00 00 00 je 0xe4
> 19: 4c 3b 63 40 cmp 0x40(%rbx),%r12
> 1d: 48 8b 03 mov (%rbx),%rax
> 20: 0f 84 e9 00 00 00 je 0x10f
> 26: 48 85 c0 test %rax,%rax
> 29: 74 26 je 0x51
> 2b:* 4c 3b 60 40 cmp 0x40(%rax),%r12 <-- trapping instruction
> 2f: 75 08 jne 0x39
> 31: e9 ef 00 00 00 jmpq 0x125
> 36: 48 89 d8 mov %rbx,%rax
> 39: 48 8b 18 mov (%rax),%rbx
> 3c: 48 85 db test %rbx,%rbx
>
> and that oopsing instruction seems to be the compare of
> "hooks_entry->orig_ops" from hooks_entry in this expression:
>
> if (hooks_entry && hooks_entry->orig_ops == reg) {
>
> so hooks_entry() is bogus. It was gotten from
>
> hooks_entry = nf_hook_entry_head(net, reg);
>
> but that's as far as I dug. And yes, I do have
> CONFIG_NETFILTER_INGRESS=y in case that matters.
>
> And all this code has changed pretty radically in commit e3b37f11e6e4
> ("netfilter: replace list_head with single linked list"), and there
> was clearly already something wrong with that code, with commit
> 5119e4381a90 ("netfilter: Fix potential null pointer dereference")
> adding the test against NULL. But I suspect that only hid the "oops,
> it's actually not NULL, it loaded some uninitialized value" problem.
>
> Over to the networking guys.. Ideas?
Sorry, not off the top of my head.
Pablo is currently travelling back home from netdev 1.2 in Tokyo,
I can help starting Wednesday when I am back.
One shot in the dark (not even compile tested; wonder if we can end up
zapping bogus hook ...)
diff --git a/net/netfilter/core.c b/net/netfilter/core.c
index c9d90eb..fd6a2ce 100644
--- a/net/netfilter/core.c
+++ b/net/netfilter/core.c
@@ -189,6 +189,9 @@ void nf_unregister_net_hook(struct net *net, const struct nf_hook_ops *reg)
unlock:
mutex_unlock(&nf_hook_mutex);
+
+ WARN_ON(hooks_entry && hooks_entry->orig_ops != reg);
+
if (!hooks_entry) {
WARN(1, "nf_unregister_net_hook: hook not found!\n");
return;
^ permalink raw reply related
* Re: [PATCH kernel v2] PCI: Enable access to custom VPD for Chelsio devices (cxgb3)
From: Alexey Kardashevskiy @ 2016-10-10 1:18 UTC (permalink / raw)
To: Bjorn Helgaas
Cc: Netdev, Alexander Duyck, Santosh Raspatur, linux-kernel,
linux-pci
In-Reply-To: <1475126512-10722-1-git-send-email-aik@ozlabs.ru>
Anyone, ping?
On 29/09/16 15:21, Alexey Kardashevskiy wrote:
> There is at least one Chelsio 10Gb card which uses VPD area to store
> some custom blocks (example below). However pci_vpd_size() returns
> the length of the first block only assuming that there can be only
> one VPD "End Tag" and VFIO blocks access beyond that offset
> (since 4e1a63555) which leads to the situation when the guest "cxgb3"
> driver fails to probe the device. The host system does not have this
> problem as the drives accesses the config space directly without
> pci_read_vpd()/...
>
> This adds a quirk to override the VPD size to a bigger value.
> The maximum size is taken from EEPROMSIZE in
> drivers/net/ethernet/chelsio/cxgb3/common.h. We do not read the tag
> as the cxgb3 driver does as the driver supports writing to EEPROM/VPD
> and when it writes, it only checks for 8192 bytes boundary. The quirk
> is registerted for all devices supported by the cxgb3 driver.
>
> This adds a quirk to the PCI layer (not to the cxgb3 driver) as
> the cxgb3 driver itself accesses VPD directly and the problem only exists
> with the vfio-pci driver (when cxgb3 is not running on the host and
> may not be even loaded) which blocks accesses beyond the first block
> of VPD data. However vfio-pci itself does not have quirks mechanism so
> we add it to PCI.
>
> Tested on:
> Ethernet controller [0200]: Chelsio Communications Inc T310 10GbE Single Port Adapter [1425:0030]
>
> This is its VPD:
> 0000 Large item 42 bytes; name 0x2 Identifier String
> b'10 Gigabit Ethernet-SR PCI Express Adapter'
> #00 [EC] len=7: b'D76809 '
> #0a [FN] len=7: b'46K7897'
> #14 [PN] len=7: b'46K7897'
> #1e [MN] len=4: b'1037'
> #25 [FC] len=4: b'5769'
> #2c [SN] len=12: b'YL102035603V'
> #3b [NA] len=12: b'00145E992ED1'
>
> 0c00 Large item 16 bytes; name 0x2 Identifier String
> b'S310E-SR-X '
> 0c13 Large item 234 bytes; name 0x10
> #00 [PN] len=16: b'TBD '
> #13 [EC] len=16: b'110107730D2 '
> #26 [SN] len=16: b'97YL102035603V '
> #39 [NA] len=12: b'00145E992ED1'
> #48 [V0] len=6: b'175000'
> #51 [V1] len=6: b'266666'
> #5a [V2] len=6: b'266666'
> #63 [V3] len=6: b'2000 '
> #6c [V4] len=2: b'1 '
> #71 [V5] len=6: b'c2 '
> #7a [V6] len=6: b'0 '
> #83 [V7] len=2: b'1 '
> #88 [V8] len=2: b'0 '
> #8d [V9] len=2: b'0 '
> #92 [VA] len=2: b'0 '
> #97 [RV] len=80: b's\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'...
> 0d00 Large item 252 bytes; name 0x11
> #00 [VC] len=16: b'122310_1222 dp '
> #13 [VD] len=16: b'610-0001-00 H1\x00\x00'
> #26 [VE] len=16: b'122310_1353 fp '
> #39 [VF] len=16: b'610-0001-00 H1\x00\x00'
> #4c [RW] len=173: b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'...
> 0dff Small item 0 bytes; name 0xf End Tag
>
> Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
> ---
> Changes:
> v2:
> * used pci_set_vpd_size() helper
> * added explicit list of IDs from cxgb3 driver
> * added a note in the commit log why the quirk is not in cxgb3
> ---
> drivers/pci/quirks.c | 22 ++++++++++++++++++++++
> 1 file changed, 22 insertions(+)
>
> diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
> index 44e0ff3..b22fce5 100644
> --- a/drivers/pci/quirks.c
> +++ b/drivers/pci/quirks.c
> @@ -3243,6 +3243,28 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_4C
> DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PORT_RIDGE,
> quirk_thunderbolt_hotplug_msi);
>
> +static void quirk_chelsio_extend_vpd(struct pci_dev *dev)
> +{
> + if (!dev->vpd)
> + return;
> +
> + pci_set_vpd_size(dev, max_t(unsigned int, dev->vpd->len, 8192));
> +}
> +
> +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_CHELSIO, 0x20, quirk_chelsio_extend_vpd);
> +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_CHELSIO, 0x21, quirk_chelsio_extend_vpd);
> +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_CHELSIO, 0x22, quirk_chelsio_extend_vpd);
> +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_CHELSIO, 0x23, quirk_chelsio_extend_vpd);
> +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_CHELSIO, 0x24, quirk_chelsio_extend_vpd);
> +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_CHELSIO, 0x25, quirk_chelsio_extend_vpd);
> +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_CHELSIO, 0x26, quirk_chelsio_extend_vpd);
> +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_CHELSIO, 0x30, quirk_chelsio_extend_vpd);
> +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_CHELSIO, 0x31, quirk_chelsio_extend_vpd);
> +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_CHELSIO, 0x32, quirk_chelsio_extend_vpd);
> +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_CHELSIO, 0x35, quirk_chelsio_extend_vpd);
> +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_CHELSIO, 0x36, quirk_chelsio_extend_vpd);
> +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_CHELSIO, 0x37, quirk_chelsio_extend_vpd);
> +
> #ifdef CONFIG_ACPI
> /*
> * Apple: Shutdown Cactus Ridge Thunderbolt controller.
>
--
Alexey
^ permalink raw reply
* Re: slab corruption with current -git (was Re: [git pull] vfs pile 1 (splice))
From: Aaron Conole @ 2016-10-10 1:35 UTC (permalink / raw)
To: Florian Westphal
Cc: Linus Torvalds, Al Viro, Andrew Morton, Jens Axboe, Ted Ts'o,
Christoph Lameter, David Miller, Pablo Neira Ayuso,
Linux Kernel Mailing List, linux-fsdevel, Network Development,
NetFilter
In-Reply-To: <20161010005105.GA18349@breakpoint.cc>
Florian Westphal <fw@strlen.de> writes:
> Linus Torvalds <torvalds@linux-foundation.org> wrote:
>> On Sun, Oct 9, 2016 at 12:11 PM, Linus Torvalds
>> <torvalds@linux-foundation.org> wrote:
>> >
>> > Anyway, I don't think I can bisect it, but I'll try to narrow it down
>> > a *bit* at least.
>> >
>> > Not doing any more pulls on this unstable base, I've been puttering
>> > around in trying to clean up some stupid printk logging issues
>> > instead.
>>
>> So I finally got a oops with slub debugging enabled. It doesn't really
>> narrow things down, though, it kind of extends on the possible
>> suspects. Now adding David Miller and Pablo, because it looks like it
>> may be netfilter that does something bad and corrupts memory.
>
> Quite possible, the netns interactions are not nice :-/
>
>> Without further ado, here's the new oops:
>>
>> general protection fault: 0000 [#1] SMP
>> CPU: 7 PID: 169 Comm: kworker/u16:7 Not tainted
>> 4.8.0-11288-gb66484cd7470 #1
>> Hardware name: System manufacturer System Product Name/Z170-K, BIOS
> ..
>> Call Trace:
>> netfilter_net_exit+0x2f/0x60
>> ops_exit_list.isra.4+0x38/0x60
>> cleanup_net+0x1ba/0x2a0
>> process_one_work+0x1f1/0x480
>> worker_thread+0x48/0x4d0
>> ? process_one_work+0x480/0x480
>
> ..
>
>> like it's a pointer loaded from a free'd allocation.
>>
>> The code disassembles to
>>
>> 0: 0f b6 ca movzbl %dl,%ecx
>> 3: 48 8d 84 c8 00 01 00 lea 0x100(%rax,%rcx,8),%rax
>> a: 00
>> b: 49 8b 5c c5 00 mov 0x0(%r13,%rax,8),%rbx
>> 10: 48 85 db test %rbx,%rbx
>> 13: 0f 84 cb 00 00 00 je 0xe4
>> 19: 4c 3b 63 40 cmp 0x40(%rbx),%r12
>> 1d: 48 8b 03 mov (%rbx),%rax
>> 20: 0f 84 e9 00 00 00 je 0x10f
>> 26: 48 85 c0 test %rax,%rax
>> 29: 74 26 je 0x51
>> 2b:* 4c 3b 60 40 cmp 0x40(%rax),%r12 <-- trapping instruction
>> 2f: 75 08 jne 0x39
>> 31: e9 ef 00 00 00 jmpq 0x125
>> 36: 48 89 d8 mov %rbx,%rax
>> 39: 48 8b 18 mov (%rax),%rbx
>> 3c: 48 85 db test %rbx,%rbx
>>
>> and that oopsing instruction seems to be the compare of
>> "hooks_entry->orig_ops" from hooks_entry in this expression:
>>
>> if (hooks_entry && hooks_entry->orig_ops == reg) {
>>
>> so hooks_entry() is bogus. It was gotten from
>>
>> hooks_entry = nf_hook_entry_head(net, reg);
>>
>> but that's as far as I dug. And yes, I do have
>> CONFIG_NETFILTER_INGRESS=y in case that matters.
>>
>> And all this code has changed pretty radically in commit e3b37f11e6e4
>> ("netfilter: replace list_head with single linked list"), and there
>> was clearly already something wrong with that code, with commit
>> 5119e4381a90 ("netfilter: Fix potential null pointer dereference")
>> adding the test against NULL. But I suspect that only hid the "oops,
>> it's actually not NULL, it loaded some uninitialized value" problem.
>>
>> Over to the networking guys.. Ideas?
>
> Sorry, not off the top of my head.
> Pablo is currently travelling back home from netdev 1.2 in Tokyo,
> I can help starting Wednesday when I am back.
>
> One shot in the dark (not even compile tested; wonder if we can end up
> zapping bogus hook ...)
>
I was just about to build and test something similar:
diff --git a/net/netfilter/core.c b/net/netfilter/core.c
index c9d90eb..e84103f 100644
--- a/net/netfilter/core.c
+++ b/net/netfilter/core.c
@@ -189,7 +189,7 @@ void nf_unregister_net_hook(struct net *net, const struct nf_hook_ops *reg)
unlock:
mutex_unlock(&nf_hook_mutex);
- if (!hooks_entry) {
+ if (!hooks_entry || hooks_entry->orig_ops != reg) {
WARN(1, "nf_unregister_net_hook: hook not found!\n");
return;
}
^ permalink raw reply related
* Re: [PATCH v3] iproute2: build nsid-name cache only for commands that need it
From: Stephen Hemminger @ 2016-10-10 1:57 UTC (permalink / raw)
To: Anton Aksola; +Cc: netdev, nicolas.dichtel, vadim4j
In-Reply-To: <20160920060123.GA17211@toys.tundra.dog-lvm.novalocal>
On Tue, 20 Sep 2016 06:01:27 +0000
Anton Aksola <aakso@iki.fi> wrote:
> The calling of netns_map_init() before command parsing introduced
> a performance issue with large number of namespaces.
>
> As commands such as add, del and exec do not need to iterate through
> /var/run/netns it would be good not no build the cache before executing
> these commands.
>
> Example:
> unpatched:
> time seq 1 1000 | xargs -n 1 ip netns add
>
> real 0m16.832s
> user 0m1.350s
> sys 0m15.029s
>
> patched:
> time seq 1 1000 | xargs -n 1 ip netns add
>
> real 0m3.859s
> user 0m0.132s
> sys 0m3.205s
>
> Signed-off-by: Anton Aksola <aakso@iki.fi>
> ---
> ip/ip_common.h | 1 +
> ip/ipmonitor.c | 1 +
> ip/ipnetns.c | 31 ++++++++++++++++++++++---------
> testsuite/tests/ip/netns/set_nsid.t | 22 ++++++++++++++++++++++
> testsuite/tests/ip/netns/set_nsid_batch.t | 18 ++++++++++++++++++
> 5 files changed, 64 insertions(+), 9 deletions(-)
> create mode 100755 testsuite/tests/ip/netns/set_nsid.t
> create mode 100755 testsuite/tests/ip/netns/set_nsid_batch.t
>
Applied to net-next (ie for 4.9)
^ permalink raw reply
* Re: [PATCH] tc: f_u32: Fill in 'linkid' provided by user
From: Stephen Hemminger @ 2016-10-10 1:58 UTC (permalink / raw)
To: Sushma Sitaram; +Cc: netdev, john.r.fastabend
In-Reply-To: <20160928183016.23280.39364.stgit@localhost.localdomain>
On Wed, 28 Sep 2016 11:30:16 -0700
Sushma Sitaram <sushma.sitaram@intel.com> wrote:
> Currently, 'linkid' input by the user is parsed but 'handle' is appended to the netlink message.
>
> # tc filter add dev enp1s0f1 protocol ip parent ffff: prio 99 u32 ht 800: \
> order 1 link 1: offset at 0 mask 0f00 shift 6 plus 0 eat match ip \
> protocol 6 ff
>
> resulted in:
> filter protocol ip pref 99 u32 fh 800::1 order 1 key ht 800 bkt 0
> match 00060000/00ff0000 at 8
> offset 0f00>>6 at 0 eat
>
> This patch results in:
> filter protocol ip pref 99 u32 fh 800::1 order 1 key ht 800 bkt 0 link 1:
> match 00060000/00ff0000 at 8
> offset 0f00>>6 at 0 eat
>
>
> Signed-off-by Sushma Sitaram: Sushma Sitaram <sushma.sitaram@intel.com>
Applied (for 4.8).
^ 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