* [PATCH net-next v1 2/5] hinic: add support to set and get irq coalesce
From: Luo bin @ 2020-06-20 9:42 UTC (permalink / raw)
To: davem; +Cc: linux-kernel, netdev, luoxianjun, yin.yinshi, cloud.wangxiaoyun
In-Reply-To: <20200620094258.13181-1-luobin9@huawei.com>
add support to set TX/RX irq coalesce params with ethtool -C and
get these params with ethtool -c.
Signed-off-by: Luo bin <luobin9@huawei.com>
---
drivers/net/ethernet/huawei/hinic/hinic_dev.h | 8 +
.../net/ethernet/huawei/hinic/hinic_ethtool.c | 294 ++++++++++++++++++
.../net/ethernet/huawei/hinic/hinic_hw_dev.c | 62 ++++
.../net/ethernet/huawei/hinic/hinic_hw_dev.h | 21 ++
.../net/ethernet/huawei/hinic/hinic_hw_mgmt.h | 3 +
.../net/ethernet/huawei/hinic/hinic_main.c | 56 ++++
drivers/net/ethernet/huawei/hinic/hinic_rx.c | 19 +-
drivers/net/ethernet/huawei/hinic/hinic_tx.c | 19 ++
8 files changed, 481 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_dev.h b/drivers/net/ethernet/huawei/hinic/hinic_dev.h
index 48b40be3e84d..75d6dee948f5 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_dev.h
+++ b/drivers/net/ethernet/huawei/hinic/hinic_dev.h
@@ -49,6 +49,12 @@ enum hinic_rss_hash_type {
HINIC_RSS_HASH_ENGINE_TYPE_MAX,
};
+struct hinic_intr_coal_info {
+ u8 pending_limt;
+ u8 coalesce_timer_cfg;
+ u8 resend_timer_cfg;
+};
+
struct hinic_dev {
struct net_device *netdev;
struct hinic_hwdev *hwdev;
@@ -82,6 +88,8 @@ struct hinic_dev {
struct hinic_rss_type rss_type;
u8 *rss_hkey_user;
s32 *rss_indir_user;
+ struct hinic_intr_coal_info *rx_intr_coalesce;
+ struct hinic_intr_coal_info *tx_intr_coalesce;
struct hinic_sriov_info sriov_info;
};
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_ethtool.c b/drivers/net/ethernet/huawei/hinic/hinic_ethtool.c
index c2afa0585dbf..750b4d786c50 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_ethtool.c
+++ b/drivers/net/ethernet/huawei/hinic/hinic_ethtool.c
@@ -49,6 +49,30 @@
#define ETHTOOL_ADD_ADVERTISED_LINK_MODE(ecmd, mode) \
((ecmd)->advertising |= ADVERTISED_##mode)
+#define COALESCE_PENDING_LIMIT_UNIT 8
+#define COALESCE_TIMER_CFG_UNIT 9
+#define COALESCE_ALL_QUEUE 0xFFFF
+#define COALESCE_MAX_PENDING_LIMIT (255 * COALESCE_PENDING_LIMIT_UNIT)
+#define COALESCE_MAX_TIMER_CFG (255 * COALESCE_TIMER_CFG_UNIT)
+#define OBJ_STR_MAX_LEN 32
+
+#define CHECK_COALESCE_ALIGN(coal, item, unit) \
+do { \
+ if ((coal)->item % (unit)) \
+ netif_warn(nic_dev, drv, netdev, \
+ "%s in %d units, change to %d\n", \
+ #item, (unit), (((coal)->item / (unit)) * (unit)));\
+} while (0)
+
+#define CHECK_COALESCE_CHANGED(coal, item, unit, ori_val, obj_str) \
+do { \
+ if (((coal)->item / (unit)) != (ori_val)) \
+ netif_info(nic_dev, drv, netdev, \
+ "Change %s from %d to %d %s\n", \
+ #item, (ori_val) * (unit), \
+ (((coal)->item / (unit)) * (unit)), (obj_str));\
+} while (0)
+
struct hw2ethtool_link_mode {
enum ethtool_link_mode_bit_indices link_mode_bit;
u32 speed;
@@ -614,6 +638,258 @@ static int hinic_set_ringparam(struct net_device *netdev,
return 0;
}
+static int __hinic_get_coalesce(struct net_device *netdev,
+ struct ethtool_coalesce *coal, u16 queue)
+{
+ struct hinic_dev *nic_dev = netdev_priv(netdev);
+ struct hinic_intr_coal_info *rx_intr_coal_info;
+ struct hinic_intr_coal_info *tx_intr_coal_info;
+
+ if (queue == COALESCE_ALL_QUEUE) {
+ /* get tx/rx irq0 as default parameters */
+ rx_intr_coal_info = &nic_dev->rx_intr_coalesce[0];
+ tx_intr_coal_info = &nic_dev->tx_intr_coalesce[0];
+ } else {
+ if (queue >= nic_dev->num_qps) {
+ netif_err(nic_dev, drv, netdev,
+ "Invalid queue_id: %d\n", queue);
+ return -EINVAL;
+ }
+ rx_intr_coal_info = &nic_dev->rx_intr_coalesce[queue];
+ tx_intr_coal_info = &nic_dev->tx_intr_coalesce[queue];
+ }
+
+ /* coalesce_timer is in unit of 9us */
+ coal->rx_coalesce_usecs = rx_intr_coal_info->coalesce_timer_cfg *
+ COALESCE_TIMER_CFG_UNIT;
+ /* coalesced_frames is in unit of 8 */
+ coal->rx_max_coalesced_frames = rx_intr_coal_info->pending_limt *
+ COALESCE_PENDING_LIMIT_UNIT;
+ coal->tx_coalesce_usecs = tx_intr_coal_info->coalesce_timer_cfg *
+ COALESCE_TIMER_CFG_UNIT;
+ coal->tx_max_coalesced_frames = tx_intr_coal_info->pending_limt *
+ COALESCE_PENDING_LIMIT_UNIT;
+
+ return 0;
+}
+
+static int is_coalesce_exceed_limit(struct net_device *netdev,
+ const struct ethtool_coalesce *coal)
+{
+ struct hinic_dev *nic_dev = netdev_priv(netdev);
+
+ if (coal->rx_coalesce_usecs > COALESCE_MAX_TIMER_CFG) {
+ netif_err(nic_dev, drv, netdev,
+ "Rx_coalesce_usecs out of range[%d-%d]\n", 0,
+ COALESCE_MAX_TIMER_CFG);
+ return -EOPNOTSUPP;
+ }
+
+ if (coal->rx_max_coalesced_frames > COALESCE_MAX_PENDING_LIMIT) {
+ netif_err(nic_dev, drv, netdev,
+ "Rx_max_coalesced_frames out of range[%d-%d]\n", 0,
+ COALESCE_MAX_PENDING_LIMIT);
+ return -EOPNOTSUPP;
+ }
+
+ if (coal->tx_coalesce_usecs > COALESCE_MAX_TIMER_CFG) {
+ netif_err(nic_dev, drv, netdev,
+ "Tx_coalesce_usecs out of range[%d-%d]\n", 0,
+ COALESCE_MAX_TIMER_CFG);
+ return -EOPNOTSUPP;
+ }
+
+ if (coal->tx_max_coalesced_frames > COALESCE_MAX_PENDING_LIMIT) {
+ netif_err(nic_dev, drv, netdev,
+ "Tx_max_coalesced_frames out of range[%d-%d]\n", 0,
+ COALESCE_MAX_PENDING_LIMIT);
+ return -EOPNOTSUPP;
+ }
+
+ return 0;
+}
+
+static int set_queue_coalesce(struct hinic_dev *nic_dev, u16 q_id,
+ struct hinic_intr_coal_info *coal,
+ bool set_rx_coal)
+{
+ struct hinic_intr_coal_info *intr_coal = NULL;
+ struct hinic_msix_config interrupt_info = {0};
+ struct net_device *netdev = nic_dev->netdev;
+ u16 msix_idx;
+ int err;
+
+ intr_coal = set_rx_coal ? &nic_dev->rx_intr_coalesce[q_id] :
+ &nic_dev->tx_intr_coalesce[q_id];
+
+ intr_coal->coalesce_timer_cfg = coal->coalesce_timer_cfg;
+ intr_coal->pending_limt = coal->pending_limt;
+
+ /* netdev not running or qp not in using,
+ * don't need to set coalesce to hw
+ */
+ if (!(nic_dev->flags & HINIC_INTF_UP) ||
+ q_id >= nic_dev->num_qps)
+ return 0;
+
+ msix_idx = set_rx_coal ? nic_dev->rxqs[q_id].rq->msix_entry :
+ nic_dev->txqs[q_id].sq->msix_entry;
+ interrupt_info.msix_index = msix_idx;
+ interrupt_info.coalesce_timer_cnt = intr_coal->coalesce_timer_cfg;
+ interrupt_info.pending_cnt = intr_coal->pending_limt;
+ interrupt_info.resend_timer_cnt = intr_coal->resend_timer_cfg;
+
+ err = hinic_set_interrupt_cfg(nic_dev->hwdev, &interrupt_info);
+ if (err)
+ netif_warn(nic_dev, drv, netdev,
+ "Failed to set %s queue%d coalesce",
+ set_rx_coal ? "rx" : "tx", q_id);
+
+ return err;
+}
+
+static int __set_hw_coal_param(struct hinic_dev *nic_dev,
+ struct hinic_intr_coal_info *intr_coal,
+ u16 queue, bool set_rx_coal)
+{
+ int err;
+ u16 i;
+
+ if (queue == COALESCE_ALL_QUEUE) {
+ for (i = 0; i < nic_dev->max_qps; i++) {
+ err = set_queue_coalesce(nic_dev, i, intr_coal,
+ set_rx_coal);
+ if (err)
+ return err;
+ }
+ } else {
+ if (queue >= nic_dev->num_qps) {
+ netif_err(nic_dev, drv, nic_dev->netdev,
+ "Invalid queue_id: %d\n", queue);
+ return -EINVAL;
+ }
+ err = set_queue_coalesce(nic_dev, queue, intr_coal,
+ set_rx_coal);
+ if (err)
+ return err;
+ }
+
+ return 0;
+}
+
+static int __hinic_set_coalesce(struct net_device *netdev,
+ struct ethtool_coalesce *coal, u16 queue)
+{
+ struct hinic_intr_coal_info *ori_rx_intr_coal = NULL;
+ struct hinic_intr_coal_info *ori_tx_intr_coal = NULL;
+ struct hinic_dev *nic_dev = netdev_priv(netdev);
+ struct hinic_intr_coal_info rx_intr_coal = {0};
+ struct hinic_intr_coal_info tx_intr_coal = {0};
+ char obj_str[OBJ_STR_MAX_LEN] = {0};
+ bool set_rx_coal = false;
+ bool set_tx_coal = false;
+ int err;
+
+ err = is_coalesce_exceed_limit(netdev, coal);
+ if (err)
+ return err;
+
+ CHECK_COALESCE_ALIGN(coal, rx_coalesce_usecs, COALESCE_TIMER_CFG_UNIT);
+ CHECK_COALESCE_ALIGN(coal, rx_max_coalesced_frames,
+ COALESCE_PENDING_LIMIT_UNIT);
+ CHECK_COALESCE_ALIGN(coal, tx_coalesce_usecs, COALESCE_TIMER_CFG_UNIT);
+ CHECK_COALESCE_ALIGN(coal, tx_max_coalesced_frames,
+ COALESCE_PENDING_LIMIT_UNIT);
+
+ if (coal->rx_coalesce_usecs || coal->rx_max_coalesced_frames) {
+ rx_intr_coal.coalesce_timer_cfg =
+ (u8)(coal->rx_coalesce_usecs / COALESCE_TIMER_CFG_UNIT);
+ rx_intr_coal.pending_limt = (u8)(coal->rx_max_coalesced_frames /
+ COALESCE_PENDING_LIMIT_UNIT);
+ set_rx_coal = true;
+ }
+
+ if (coal->tx_coalesce_usecs || coal->tx_max_coalesced_frames) {
+ tx_intr_coal.coalesce_timer_cfg =
+ (u8)(coal->tx_coalesce_usecs / COALESCE_TIMER_CFG_UNIT);
+ tx_intr_coal.pending_limt = (u8)(coal->tx_max_coalesced_frames /
+ COALESCE_PENDING_LIMIT_UNIT);
+ set_tx_coal = true;
+ }
+
+ if (queue == COALESCE_ALL_QUEUE) {
+ ori_rx_intr_coal = &nic_dev->rx_intr_coalesce[0];
+ ori_tx_intr_coal = &nic_dev->tx_intr_coalesce[0];
+ err = snprintf(obj_str, OBJ_STR_MAX_LEN, "for netdev");
+ } else {
+ ori_rx_intr_coal = &nic_dev->rx_intr_coalesce[queue];
+ ori_tx_intr_coal = &nic_dev->tx_intr_coalesce[queue];
+ err = snprintf(obj_str, OBJ_STR_MAX_LEN, "for queue %d", queue);
+ }
+ if (err <= 0 || err >= OBJ_STR_MAX_LEN) {
+ netif_err(nic_dev, drv, netdev, "Failed to snprintf string, function return(%d) and dest_len(%d)\n",
+ err, OBJ_STR_MAX_LEN);
+ return -EFAULT;
+ }
+
+ CHECK_COALESCE_CHANGED(coal, rx_coalesce_usecs, COALESCE_TIMER_CFG_UNIT,
+ ori_rx_intr_coal->coalesce_timer_cfg, obj_str);
+ CHECK_COALESCE_CHANGED(coal, rx_max_coalesced_frames,
+ COALESCE_PENDING_LIMIT_UNIT,
+ ori_rx_intr_coal->pending_limt, obj_str);
+ CHECK_COALESCE_CHANGED(coal, tx_coalesce_usecs, COALESCE_TIMER_CFG_UNIT,
+ ori_tx_intr_coal->coalesce_timer_cfg, obj_str);
+ CHECK_COALESCE_CHANGED(coal, tx_max_coalesced_frames,
+ COALESCE_PENDING_LIMIT_UNIT,
+ ori_tx_intr_coal->pending_limt, obj_str);
+
+ /* setting coalesce timer or pending limit to zero will disable
+ * coalesce
+ */
+ if (set_rx_coal && (!rx_intr_coal.coalesce_timer_cfg ||
+ !rx_intr_coal.pending_limt))
+ netif_warn(nic_dev, drv, netdev, "RX coalesce will be disabled\n");
+ if (set_tx_coal && (!tx_intr_coal.coalesce_timer_cfg ||
+ !tx_intr_coal.pending_limt))
+ netif_warn(nic_dev, drv, netdev, "TX coalesce will be disabled\n");
+
+ if (set_rx_coal) {
+ err = __set_hw_coal_param(nic_dev, &rx_intr_coal, queue, true);
+ if (err)
+ return err;
+ }
+ if (set_tx_coal) {
+ err = __set_hw_coal_param(nic_dev, &tx_intr_coal, queue, false);
+ if (err)
+ return err;
+ }
+ return 0;
+}
+
+static int hinic_get_coalesce(struct net_device *netdev,
+ struct ethtool_coalesce *coal)
+{
+ return __hinic_get_coalesce(netdev, coal, COALESCE_ALL_QUEUE);
+}
+
+static int hinic_set_coalesce(struct net_device *netdev,
+ struct ethtool_coalesce *coal)
+{
+ return __hinic_set_coalesce(netdev, coal, COALESCE_ALL_QUEUE);
+}
+
+static int hinic_get_per_queue_coalesce(struct net_device *netdev, u32 queue,
+ struct ethtool_coalesce *coal)
+{
+ return __hinic_get_coalesce(netdev, coal, queue);
+}
+
+static int hinic_set_per_queue_coalesce(struct net_device *netdev, u32 queue,
+ struct ethtool_coalesce *coal)
+{
+ return __hinic_set_coalesce(netdev, coal, queue);
+}
+
static void hinic_get_pauseparam(struct net_device *netdev,
struct ethtool_pauseparam *pause)
{
@@ -1303,12 +1579,21 @@ static void hinic_get_strings(struct net_device *netdev,
}
static const struct ethtool_ops hinic_ethtool_ops = {
+ .supported_coalesce_params = ETHTOOL_COALESCE_RX_USECS |
+ ETHTOOL_COALESCE_RX_MAX_FRAMES |
+ ETHTOOL_COALESCE_TX_USECS |
+ ETHTOOL_COALESCE_TX_MAX_FRAMES,
+
.get_link_ksettings = hinic_get_link_ksettings,
.set_link_ksettings = hinic_set_link_ksettings,
.get_drvinfo = hinic_get_drvinfo,
.get_link = ethtool_op_get_link,
.get_ringparam = hinic_get_ringparam,
.set_ringparam = hinic_set_ringparam,
+ .get_coalesce = hinic_get_coalesce,
+ .set_coalesce = hinic_set_coalesce,
+ .get_per_queue_coalesce = hinic_get_per_queue_coalesce,
+ .set_per_queue_coalesce = hinic_set_per_queue_coalesce,
.get_pauseparam = hinic_get_pauseparam,
.set_pauseparam = hinic_set_pauseparam,
.get_channels = hinic_get_channels,
@@ -1325,11 +1610,20 @@ static const struct ethtool_ops hinic_ethtool_ops = {
};
static const struct ethtool_ops hinicvf_ethtool_ops = {
+ .supported_coalesce_params = ETHTOOL_COALESCE_RX_USECS |
+ ETHTOOL_COALESCE_RX_MAX_FRAMES |
+ ETHTOOL_COALESCE_TX_USECS |
+ ETHTOOL_COALESCE_TX_MAX_FRAMES,
+
.get_link_ksettings = hinic_get_link_ksettings,
.get_drvinfo = hinic_get_drvinfo,
.get_link = ethtool_op_get_link,
.get_ringparam = hinic_get_ringparam,
.set_ringparam = hinic_set_ringparam,
+ .get_coalesce = hinic_get_coalesce,
+ .set_coalesce = hinic_set_coalesce,
+ .get_per_queue_coalesce = hinic_get_per_queue_coalesce,
+ .set_per_queue_coalesce = hinic_set_per_queue_coalesce,
.get_channels = hinic_get_channels,
.set_channels = hinic_set_channels,
.get_rxnfc = hinic_get_rxnfc,
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c b/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c
index 747d50b841ba..4de50e4ba4df 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c
+++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c
@@ -705,6 +705,68 @@ static int hinic_l2nic_reset(struct hinic_hwdev *hwdev)
return 0;
}
+int hinic_get_interrupt_cfg(struct hinic_hwdev *hwdev,
+ struct hinic_msix_config *interrupt_info)
+{
+ u16 out_size = sizeof(*interrupt_info);
+ struct hinic_pfhwdev *pfhwdev;
+ int err;
+
+ if (!hwdev || !interrupt_info)
+ return -EINVAL;
+
+ pfhwdev = container_of(hwdev, struct hinic_pfhwdev, hwdev);
+
+ interrupt_info->func_id = HINIC_HWIF_FUNC_IDX(hwdev->hwif);
+
+ err = hinic_msg_to_mgmt(&pfhwdev->pf_to_mgmt, HINIC_MOD_COMM,
+ HINIC_COMM_CMD_MSI_CTRL_REG_RD_BY_UP,
+ interrupt_info, sizeof(*interrupt_info),
+ interrupt_info, &out_size, HINIC_MGMT_MSG_SYNC);
+ if (err || !out_size || interrupt_info->status) {
+ dev_err(&hwdev->hwif->pdev->dev, "Failed to get interrupt config, err: %d, status: 0x%x, out size: 0x%x\n",
+ err, interrupt_info->status, out_size);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+int hinic_set_interrupt_cfg(struct hinic_hwdev *hwdev,
+ struct hinic_msix_config *interrupt_info)
+{
+ u16 out_size = sizeof(*interrupt_info);
+ struct hinic_msix_config temp_info;
+ struct hinic_pfhwdev *pfhwdev;
+ int err;
+
+ if (!hwdev)
+ return -EINVAL;
+
+ pfhwdev = container_of(hwdev, struct hinic_pfhwdev, hwdev);
+
+ interrupt_info->func_id = HINIC_HWIF_FUNC_IDX(hwdev->hwif);
+
+ err = hinic_get_interrupt_cfg(hwdev, &temp_info);
+ if (err)
+ return -EINVAL;
+
+ interrupt_info->lli_credit_cnt = temp_info.lli_timer_cnt;
+ interrupt_info->lli_timer_cnt = temp_info.lli_timer_cnt;
+
+ err = hinic_msg_to_mgmt(&pfhwdev->pf_to_mgmt, HINIC_MOD_COMM,
+ HINIC_COMM_CMD_MSI_CTRL_REG_WR_BY_UP,
+ interrupt_info, sizeof(*interrupt_info),
+ interrupt_info, &out_size, HINIC_MGMT_MSG_SYNC);
+ if (err || !out_size || interrupt_info->status) {
+ dev_err(&hwdev->hwif->pdev->dev, "Failed to get interrupt config, err: %d, status: 0x%x, out size: 0x%x\n",
+ err, interrupt_info->status, out_size);
+ return -EIO;
+ }
+
+ return 0;
+}
+
/**
* hinic_init_hwdev - Initialize the NIC HW
* @pdev: the NIC pci device
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.h b/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.h
index cc776ca2d737..ed3cc154ce18 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.h
+++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.h
@@ -285,6 +285,21 @@ struct hinic_cmd_l2nic_reset {
u16 reset_flag;
};
+struct hinic_msix_config {
+ u8 status;
+ u8 version;
+ u8 rsvd0[6];
+
+ u16 func_id;
+ u16 msix_index;
+ u8 pending_cnt;
+ u8 coalesce_timer_cnt;
+ u8 lli_timer_cnt;
+ u8 lli_credit_cnt;
+ u8 resend_timer_cnt;
+ u8 rsvd1[3];
+};
+
struct hinic_hwdev {
struct hinic_hwif *hwif;
struct msix_entry *msix_entries;
@@ -378,4 +393,10 @@ int hinic_hwdev_hw_ci_addr_set(struct hinic_hwdev *hwdev, struct hinic_sq *sq,
void hinic_hwdev_set_msix_state(struct hinic_hwdev *hwdev, u16 msix_index,
enum hinic_msix_state flag);
+int hinic_get_interrupt_cfg(struct hinic_hwdev *hwdev,
+ struct hinic_msix_config *interrupt_info);
+
+int hinic_set_interrupt_cfg(struct hinic_hwdev *hwdev,
+ struct hinic_msix_config *interrupt_info);
+
#endif
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.h b/drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.h
index c2b142c08b0e..a3349ae30ff3 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.h
+++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.h
@@ -78,6 +78,9 @@ enum hinic_comm_cmd {
HINIC_COMM_CMD_CEQ_CTRL_REG_WR_BY_UP = 0x33,
+ HINIC_COMM_CMD_MSI_CTRL_REG_WR_BY_UP,
+ HINIC_COMM_CMD_MSI_CTRL_REG_RD_BY_UP,
+
HINIC_COMM_CMD_L2NIC_RESET = 0x4b,
HINIC_COMM_CMD_PAGESIZE_SET = 0x50,
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_main.c b/drivers/net/ethernet/huawei/hinic/hinic_main.c
index e69edb01fd9b..e328effd12d2 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_main.c
+++ b/drivers/net/ethernet/huawei/hinic/hinic_main.c
@@ -69,6 +69,10 @@ MODULE_PARM_DESC(rx_weight, "Number Rx packets for NAPI budget (default=64)");
#define HINIC_WAIT_SRIOV_CFG_TIMEOUT 15000
+#define HINIC_DEAULT_TXRX_MSIX_PENDING_LIMIT 2
+#define HINIC_DEAULT_TXRX_MSIX_COALESC_TIMER_CFG 32
+#define HINIC_DEAULT_TXRX_MSIX_RESEND_TIMER_CFG 7
+
static int change_mac_addr(struct net_device *netdev, const u8 *addr);
static int set_features(struct hinic_dev *nic_dev,
@@ -1008,6 +1012,48 @@ static int set_features(struct hinic_dev *nic_dev,
return hinic_dcb_set_pfc(nic_dev->hwdev, 0, 0);
}
+static int hinic_init_intr_coalesce(struct hinic_dev *nic_dev)
+{
+ u64 size;
+ u16 i;
+
+ size = sizeof(struct hinic_intr_coal_info) * nic_dev->max_qps;
+ nic_dev->rx_intr_coalesce = kzalloc(size, GFP_KERNEL);
+ if (!nic_dev->rx_intr_coalesce) {
+ dev_err(&nic_dev->hwdev->hwif->pdev->dev, "Failed to alloc rx intr coalesce\n");
+ return -ENOMEM;
+ }
+ nic_dev->tx_intr_coalesce = kzalloc(size, GFP_KERNEL);
+ if (!nic_dev->tx_intr_coalesce) {
+ kfree(nic_dev->rx_intr_coalesce);
+ dev_err(&nic_dev->hwdev->hwif->pdev->dev, "Failed to alloc tx intr coalesce\n");
+ return -ENOMEM;
+ }
+
+ for (i = 0; i < nic_dev->max_qps; i++) {
+ nic_dev->rx_intr_coalesce[i].pending_limt =
+ HINIC_DEAULT_TXRX_MSIX_PENDING_LIMIT;
+ nic_dev->rx_intr_coalesce[i].coalesce_timer_cfg =
+ HINIC_DEAULT_TXRX_MSIX_COALESC_TIMER_CFG;
+ nic_dev->rx_intr_coalesce[i].resend_timer_cfg =
+ HINIC_DEAULT_TXRX_MSIX_RESEND_TIMER_CFG;
+ nic_dev->tx_intr_coalesce[i].pending_limt =
+ HINIC_DEAULT_TXRX_MSIX_PENDING_LIMIT;
+ nic_dev->tx_intr_coalesce[i].coalesce_timer_cfg =
+ HINIC_DEAULT_TXRX_MSIX_COALESC_TIMER_CFG;
+ nic_dev->tx_intr_coalesce[i].resend_timer_cfg =
+ HINIC_DEAULT_TXRX_MSIX_RESEND_TIMER_CFG;
+ }
+
+ return 0;
+}
+
+static void hinic_free_intr_coalesce(struct hinic_dev *nic_dev)
+{
+ kfree(nic_dev->tx_intr_coalesce);
+ kfree(nic_dev->rx_intr_coalesce);
+}
+
/**
* nic_dev_init - Initialize the NIC device
* @pdev: the NIC pci device
@@ -1144,8 +1190,16 @@ static int nic_dev_init(struct pci_dev *pdev)
goto err_reg_netdev;
}
+ err = hinic_init_intr_coalesce(nic_dev);
+ if (err) {
+ netif_err(nic_dev, drv, netdev, "Failed to init_intr_coalesce\n");
+ goto err_init_intr;
+ }
+
return 0;
+err_init_intr:
+ unregister_netdev(netdev);
err_reg_netdev:
err_set_features:
hinic_hwdev_cb_unregister(nic_dev->hwdev,
@@ -1258,6 +1312,8 @@ static void hinic_remove(struct pci_dev *pdev)
hinic_pci_sriov_disable(pdev);
}
+ hinic_free_intr_coalesce(nic_dev);
+
unregister_netdev(netdev);
hinic_port_del_mac(nic_dev, netdev->dev_addr, 0);
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_rx.c b/drivers/net/ethernet/huawei/hinic/hinic_rx.c
index af20d0dd6de7..c9a65a1f0347 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_rx.c
+++ b/drivers/net/ethernet/huawei/hinic/hinic_rx.c
@@ -478,11 +478,15 @@ static irqreturn_t rx_irq(int irq, void *data)
static int rx_request_irq(struct hinic_rxq *rxq)
{
struct hinic_dev *nic_dev = netdev_priv(rxq->netdev);
+ struct hinic_msix_config interrupt_info = {0};
+ struct hinic_intr_coal_info *intr_coal = NULL;
struct hinic_hwdev *hwdev = nic_dev->hwdev;
struct hinic_rq *rq = rxq->rq;
struct hinic_qp *qp;
int err;
+ qp = container_of(rq, struct hinic_qp, rq);
+
rx_add_napi(rxq);
hinic_hwdev_msix_set(hwdev, rq->msix_entry,
@@ -490,13 +494,26 @@ static int rx_request_irq(struct hinic_rxq *rxq)
RX_IRQ_NO_LLI_TIMER, RX_IRQ_NO_CREDIT,
RX_IRQ_NO_RESEND_TIMER);
+ intr_coal = &nic_dev->rx_intr_coalesce[qp->q_id];
+ interrupt_info.msix_index = rq->msix_entry;
+ interrupt_info.coalesce_timer_cnt = intr_coal->coalesce_timer_cfg;
+ interrupt_info.pending_cnt = intr_coal->pending_limt;
+ interrupt_info.resend_timer_cnt = intr_coal->resend_timer_cfg;
+
+ err = hinic_set_interrupt_cfg(hwdev, &interrupt_info);
+ if (err) {
+ netif_err(nic_dev, drv, rxq->netdev,
+ "Failed to set RX interrupt coalescing attribute\n");
+ rx_del_napi(rxq);
+ return err;
+ }
+
err = request_irq(rq->irq, rx_irq, 0, rxq->irq_name, rxq);
if (err) {
rx_del_napi(rxq);
return err;
}
- qp = container_of(rq, struct hinic_qp, rq);
cpumask_set_cpu(qp->q_id % num_online_cpus(), &rq->affinity_mask);
return irq_set_affinity_hint(rq->irq, &rq->affinity_mask);
}
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_tx.c b/drivers/net/ethernet/huawei/hinic/hinic_tx.c
index 4c66a0bc1b28..0f6d27f29de5 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_tx.c
+++ b/drivers/net/ethernet/huawei/hinic/hinic_tx.c
@@ -718,12 +718,17 @@ static irqreturn_t tx_irq(int irq, void *data)
static int tx_request_irq(struct hinic_txq *txq)
{
struct hinic_dev *nic_dev = netdev_priv(txq->netdev);
+ struct hinic_msix_config interrupt_info = {0};
+ struct hinic_intr_coal_info *intr_coal = NULL;
struct hinic_hwdev *hwdev = nic_dev->hwdev;
struct hinic_hwif *hwif = hwdev->hwif;
struct pci_dev *pdev = hwif->pdev;
struct hinic_sq *sq = txq->sq;
+ struct hinic_qp *qp;
int err;
+ qp = container_of(sq, struct hinic_qp, sq);
+
tx_napi_add(txq, nic_dev->tx_weight);
hinic_hwdev_msix_set(nic_dev->hwdev, sq->msix_entry,
@@ -731,6 +736,20 @@ static int tx_request_irq(struct hinic_txq *txq)
TX_IRQ_NO_LLI_TIMER, TX_IRQ_NO_CREDIT,
TX_IRQ_NO_RESEND_TIMER);
+ intr_coal = &nic_dev->tx_intr_coalesce[qp->q_id];
+ interrupt_info.msix_index = sq->msix_entry;
+ interrupt_info.coalesce_timer_cnt = intr_coal->coalesce_timer_cfg;
+ interrupt_info.pending_cnt = intr_coal->pending_limt;
+ interrupt_info.resend_timer_cnt = intr_coal->resend_timer_cfg;
+
+ err = hinic_set_interrupt_cfg(hwdev, &interrupt_info);
+ if (err) {
+ netif_err(nic_dev, drv, txq->netdev,
+ "Failed to set TX interrupt coalescing attribute\n");
+ tx_napi_del(txq);
+ return err;
+ }
+
err = request_irq(sq->irq, tx_irq, 0, txq->irq_name, txq);
if (err) {
dev_err(&pdev->dev, "Failed to request Tx irq\n");
--
2.17.1
^ permalink raw reply related
* [PATCH net-next v1 4/5] hinic: add support to identify physical device
From: Luo bin @ 2020-06-20 9:42 UTC (permalink / raw)
To: davem; +Cc: linux-kernel, netdev, luoxianjun, yin.yinshi, cloud.wangxiaoyun
In-Reply-To: <20200620094258.13181-1-luobin9@huawei.com>
add support to identify physical device by flashing an LED
attached to it with ethtool -p cmd.
Signed-off-by: Luo bin <luobin9@huawei.com>
---
.../net/ethernet/huawei/hinic/hinic_ethtool.c | 41 ++++++++++++++
.../net/ethernet/huawei/hinic/hinic_hw_dev.c | 2 +
.../net/ethernet/huawei/hinic/hinic_hw_dev.h | 1 +
.../net/ethernet/huawei/hinic/hinic_hw_mgmt.h | 4 +-
.../net/ethernet/huawei/hinic/hinic_port.c | 55 +++++++++++++++++++
.../net/ethernet/huawei/hinic/hinic_port.h | 35 ++++++++++++
.../net/ethernet/huawei/hinic/hinic_sriov.c | 4 +-
7 files changed, 139 insertions(+), 3 deletions(-)
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_ethtool.c b/drivers/net/ethernet/huawei/hinic/hinic_ethtool.c
index a461099dfbb9..7be5564346cf 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_ethtool.c
+++ b/drivers/net/ethernet/huawei/hinic/hinic_ethtool.c
@@ -1755,6 +1755,46 @@ static void hinic_diag_test(struct net_device *netdev,
netif_carrier_on(netdev);
}
+static int hinic_set_phys_id(struct net_device *netdev,
+ enum ethtool_phys_id_state state)
+{
+ struct hinic_dev *nic_dev = netdev_priv(netdev);
+ int err = 0;
+ u8 port;
+
+ port = nic_dev->hwdev->port_id;
+
+ switch (state) {
+ case ETHTOOL_ID_ACTIVE:
+ err = hinic_set_led_status(nic_dev->hwdev, port,
+ HINIC_LED_TYPE_LINK,
+ HINIC_LED_MODE_FORCE_2HZ);
+ if (err)
+ netif_err(nic_dev, drv, netdev,
+ "Set LED blinking in 2HZ failed\n");
+ else
+ netif_info(nic_dev, drv, netdev,
+ "Set LED blinking in 2HZ success\n");
+ break;
+
+ case ETHTOOL_ID_INACTIVE:
+ err = hinic_reset_led_status(nic_dev->hwdev, port);
+ if (err)
+ netif_err(nic_dev, drv, netdev,
+ "Reset LED to original status failed\n");
+ else
+ netif_info(nic_dev, drv, netdev,
+ "Reset LED to original status success\n");
+
+ break;
+
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ return err;
+}
+
static const struct ethtool_ops hinic_ethtool_ops = {
.supported_coalesce_params = ETHTOOL_COALESCE_RX_USECS |
ETHTOOL_COALESCE_RX_MAX_FRAMES |
@@ -1785,6 +1825,7 @@ static const struct ethtool_ops hinic_ethtool_ops = {
.get_ethtool_stats = hinic_get_ethtool_stats,
.get_strings = hinic_get_strings,
.self_test = hinic_diag_test,
+ .set_phys_id = hinic_set_phys_id,
};
static const struct ethtool_ops hinicvf_ethtool_ops = {
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c b/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c
index 4de50e4ba4df..45c137827a16 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c
+++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c
@@ -83,6 +83,8 @@ static int parse_capability(struct hinic_hwdev *hwdev,
nic_cap->max_vf_qps = dev_cap->max_vf_sqs + 1;
}
+ hwdev->port_id = dev_cap->port_id;
+
return 0;
}
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.h b/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.h
index c92c39a50b81..01fe94f2d4bc 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.h
+++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.h
@@ -312,6 +312,7 @@ struct hinic_hwdev {
struct hinic_mbox_func_to_func *func_to_func;
struct hinic_cap nic_cap;
+ u8 port_id;
};
struct hinic_nic_cb {
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.h b/drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.h
index a3349ae30ff3..919d2c6ffc35 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.h
+++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.h
@@ -81,7 +81,9 @@ enum hinic_comm_cmd {
HINIC_COMM_CMD_MSI_CTRL_REG_WR_BY_UP,
HINIC_COMM_CMD_MSI_CTRL_REG_RD_BY_UP,
- HINIC_COMM_CMD_L2NIC_RESET = 0x4b,
+ HINIC_COMM_CMD_SET_LED_STATUS = 0x4a,
+
+ HINIC_COMM_CMD_L2NIC_RESET = 0x4b,
HINIC_COMM_CMD_PAGESIZE_SET = 0x50,
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_port.c b/drivers/net/ethernet/huawei/hinic/hinic_port.c
index 53ea2740ba9f..fc99d9f6799a 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_port.c
+++ b/drivers/net/ethernet/huawei/hinic/hinic_port.c
@@ -1271,3 +1271,58 @@ int hinic_set_loopback_mode(struct hinic_hwdev *hwdev, u32 mode, u32 enable)
return 0;
}
+
+static int _set_led_status(struct hinic_hwdev *hwdev, u8 port,
+ enum hinic_led_type type,
+ enum hinic_led_mode mode, u8 reset)
+{
+ struct hinic_led_info led_info = {0};
+ u16 out_size = sizeof(led_info);
+ struct hinic_pfhwdev *pfhwdev;
+ int err;
+
+ pfhwdev = container_of(hwdev, struct hinic_pfhwdev, hwdev);
+
+ led_info.port = port;
+ led_info.reset = reset;
+
+ led_info.type = type;
+ led_info.mode = mode;
+
+ err = hinic_msg_to_mgmt(&pfhwdev->pf_to_mgmt, HINIC_MOD_COMM,
+ HINIC_COMM_CMD_SET_LED_STATUS,
+ &led_info, sizeof(led_info),
+ &led_info, &out_size, HINIC_MGMT_MSG_SYNC);
+ if (err || led_info.status || !out_size) {
+ dev_err(&hwdev->hwif->pdev->dev, "Failed to set led status, err: %d, status: 0x%x, out size: 0x%x\n",
+ err, led_info.status, out_size);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+int hinic_set_led_status(struct hinic_hwdev *hwdev, u8 port,
+ enum hinic_led_type type, enum hinic_led_mode mode)
+{
+ if (!hwdev)
+ return -EINVAL;
+
+ return _set_led_status(hwdev, port, type, mode, 0);
+}
+
+int hinic_reset_led_status(struct hinic_hwdev *hwdev, u8 port)
+{
+ int err;
+
+ if (!hwdev)
+ return -EINVAL;
+
+ err = _set_led_status(hwdev, port, HINIC_LED_TYPE_INVALID,
+ HINIC_LED_MODE_INVALID, 1);
+ if (err)
+ dev_err(&hwdev->hwif->pdev->dev,
+ "Failed to reset led status\n");
+
+ return err;
+}
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_port.h b/drivers/net/ethernet/huawei/hinic/hinic_port.h
index b21956d7232e..5c916875f295 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_port.h
+++ b/drivers/net/ethernet/huawei/hinic/hinic_port.h
@@ -666,6 +666,17 @@ struct hinic_port_loopback {
u32 en;
};
+struct hinic_led_info {
+ u8 status;
+ u8 version;
+ u8 rsvd0[6];
+
+ u8 port;
+ u8 type;
+ u8 mode;
+ u8 reset;
+};
+
int hinic_port_add_mac(struct hinic_dev *nic_dev, const u8 *addr,
u16 vlan_id);
@@ -765,6 +776,30 @@ int hinic_dcb_set_pfc(struct hinic_hwdev *hwdev, u8 pfc_en, u8 pfc_bitmap);
int hinic_set_loopback_mode(struct hinic_hwdev *hwdev, u32 mode, u32 enable);
+enum hinic_led_mode {
+ HINIC_LED_MODE_ON,
+ HINIC_LED_MODE_OFF,
+ HINIC_LED_MODE_FORCE_1HZ,
+ HINIC_LED_MODE_FORCE_2HZ,
+ HINIC_LED_MODE_FORCE_4HZ,
+ HINIC_LED_MODE_1HZ,
+ HINIC_LED_MODE_2HZ,
+ HINIC_LED_MODE_4HZ,
+ HINIC_LED_MODE_INVALID,
+};
+
+enum hinic_led_type {
+ HINIC_LED_TYPE_LINK,
+ HINIC_LED_TYPE_LOW_SPEED,
+ HINIC_LED_TYPE_HIGH_SPEED,
+ HINIC_LED_TYPE_INVALID,
+};
+
+int hinic_reset_led_status(struct hinic_hwdev *hwdev, u8 port);
+
+int hinic_set_led_status(struct hinic_hwdev *hwdev, u8 port,
+ enum hinic_led_type type, enum hinic_led_mode mode);
+
int hinic_open(struct net_device *netdev);
int hinic_close(struct net_device *netdev);
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_sriov.c b/drivers/net/ethernet/huawei/hinic/hinic_sriov.c
index efab2dd2c889..f5c7c1f48542 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_sriov.c
+++ b/drivers/net/ethernet/huawei/hinic/hinic_sriov.c
@@ -383,7 +383,7 @@ static int hinic_del_vf_mac_msg_handler(void *hwdev, u16 vf_id,
nic_io = &hw_dev->func_to_io;
vf_info = nic_io->vf_infos + HW_VF_ID_TO_OS(vf_id);
- if (vf_info->pf_set_mac && is_valid_ether_addr(mac_in->mac) &&
+ if (vf_info->pf_set_mac && is_valid_ether_addr(mac_in->mac) &&
!memcmp(vf_info->vf_mac_addr, mac_in->mac, ETH_ALEN)) {
dev_warn(&hw_dev->hwif->pdev->dev, "PF has already set VF mac.\n");
mac_out->status = HINIC_PF_SET_VF_ALREADY;
@@ -905,7 +905,6 @@ int hinic_ndo_set_vf_spoofchk(struct net_device *netdev, int vf, bool setting)
err = hinic_set_vf_spoofchk(sriov_info->hwdev,
OS_VF_ID_TO_HW(vf), setting);
-
if (!err) {
netif_info(nic_dev, drv, netdev, "Set VF %d spoofchk %s successfully\n",
vf, setting ? "on" : "off");
@@ -1020,6 +1019,7 @@ static int cfg_mbx_pf_proc_vf_msg(void *hwdev, u16 vf_id, u8 cmd, void *buf_in,
dev_cap->max_vf = cap->max_vf;
dev_cap->max_sqs = cap->max_vf_qps;
dev_cap->max_rqs = cap->max_vf_qps;
+ dev_cap->port_id = dev->port_id;
*out_size = sizeof(*dev_cap);
--
2.17.1
^ permalink raw reply related
* [PATCH net-next v1 5/5] hinic: add support to get eeprom information
From: Luo bin @ 2020-06-20 9:42 UTC (permalink / raw)
To: davem; +Cc: linux-kernel, netdev, luoxianjun, yin.yinshi, cloud.wangxiaoyun
In-Reply-To: <20200620094258.13181-1-luobin9@huawei.com>
add support to get eeprom information from the plug-in module
with ethtool -m cmd.
Signed-off-by: Luo bin <luobin9@huawei.com>
---
V0->V1: remove unused variable port_id
.../net/ethernet/huawei/hinic/hinic_ethtool.c | 68 +++++++++++++++++
.../net/ethernet/huawei/hinic/hinic_hw_dev.h | 4 +
.../net/ethernet/huawei/hinic/hinic_port.c | 75 +++++++++++++++++++
.../net/ethernet/huawei/hinic/hinic_port.h | 35 +++++++++
4 files changed, 182 insertions(+)
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_ethtool.c b/drivers/net/ethernet/huawei/hinic/hinic_ethtool.c
index 7be5564346cf..5bf0432b3fda 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_ethtool.c
+++ b/drivers/net/ethernet/huawei/hinic/hinic_ethtool.c
@@ -1795,6 +1795,72 @@ static int hinic_set_phys_id(struct net_device *netdev,
return err;
}
+static int hinic_get_module_info(struct net_device *netdev,
+ struct ethtool_modinfo *modinfo)
+{
+ struct hinic_dev *nic_dev = netdev_priv(netdev);
+ u8 sfp_type_ext;
+ u8 sfp_type;
+ int err;
+
+ err = hinic_get_sfp_type(nic_dev->hwdev, &sfp_type, &sfp_type_ext);
+ if (err)
+ return err;
+
+ switch (sfp_type) {
+ case MODULE_TYPE_SFP:
+ modinfo->type = ETH_MODULE_SFF_8472;
+ modinfo->eeprom_len = ETH_MODULE_SFF_8472_LEN;
+ break;
+ case MODULE_TYPE_QSFP:
+ modinfo->type = ETH_MODULE_SFF_8436;
+ modinfo->eeprom_len = ETH_MODULE_SFF_8436_MAX_LEN;
+ break;
+ case MODULE_TYPE_QSFP_PLUS:
+ if (sfp_type_ext >= 0x3) {
+ modinfo->type = ETH_MODULE_SFF_8636;
+ modinfo->eeprom_len = ETH_MODULE_SFF_8636_MAX_LEN;
+
+ } else {
+ modinfo->type = ETH_MODULE_SFF_8436;
+ modinfo->eeprom_len = ETH_MODULE_SFF_8436_MAX_LEN;
+ }
+ break;
+ case MODULE_TYPE_QSFP28:
+ modinfo->type = ETH_MODULE_SFF_8636;
+ modinfo->eeprom_len = ETH_MODULE_SFF_8636_MAX_LEN;
+ break;
+ default:
+ netif_warn(nic_dev, drv, netdev,
+ "Optical module unknown: 0x%x\n", sfp_type);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int hinic_get_module_eeprom(struct net_device *netdev,
+ struct ethtool_eeprom *ee, u8 *data)
+{
+ struct hinic_dev *nic_dev = netdev_priv(netdev);
+ u8 sfp_data[STD_SFP_INFO_MAX_SIZE];
+ u16 len;
+ int err;
+
+ if (!ee->len || ((ee->len + ee->offset) > STD_SFP_INFO_MAX_SIZE))
+ return -EINVAL;
+
+ memset(data, 0, ee->len);
+
+ err = hinic_get_sfp_eeprom(nic_dev->hwdev, sfp_data, &len);
+ if (err)
+ return err;
+
+ memcpy(data, sfp_data + ee->offset, ee->len);
+
+ return 0;
+}
+
static const struct ethtool_ops hinic_ethtool_ops = {
.supported_coalesce_params = ETHTOOL_COALESCE_RX_USECS |
ETHTOOL_COALESCE_RX_MAX_FRAMES |
@@ -1826,6 +1892,8 @@ static const struct ethtool_ops hinic_ethtool_ops = {
.get_strings = hinic_get_strings,
.self_test = hinic_diag_test,
.set_phys_id = hinic_set_phys_id,
+ .get_module_info = hinic_get_module_info,
+ .get_module_eeprom = hinic_get_module_eeprom,
};
static const struct ethtool_ops hinicvf_ethtool_ops = {
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.h b/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.h
index 01fe94f2d4bc..958ea1a6a60d 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.h
+++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.h
@@ -130,9 +130,13 @@ enum hinic_port_cmd {
HINIC_PORT_CMD_SET_AUTONEG = 219,
+ HINIC_PORT_CMD_GET_STD_SFP_INFO = 240,
+
HINIC_PORT_CMD_SET_LRO_TIMER = 244,
HINIC_PORT_CMD_SET_VF_MAX_MIN_RATE = 249,
+
+ HINIC_PORT_CMD_GET_SFP_ABS = 251,
};
/* cmd of mgmt CPU message for HILINK module */
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_port.c b/drivers/net/ethernet/huawei/hinic/hinic_port.c
index fc99d9f6799a..428d186956f3 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_port.c
+++ b/drivers/net/ethernet/huawei/hinic/hinic_port.c
@@ -1326,3 +1326,78 @@ int hinic_reset_led_status(struct hinic_hwdev *hwdev, u8 port)
return err;
}
+
+static bool hinic_if_sfp_absent(struct hinic_hwdev *hwdev)
+{
+ struct hinic_cmd_get_light_module_abs sfp_abs = {0};
+ u16 out_size = sizeof(sfp_abs);
+ u8 port_id = hwdev->port_id;
+ int err;
+
+ sfp_abs.port_id = port_id;
+ err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_GET_SFP_ABS,
+ &sfp_abs, sizeof(sfp_abs), &sfp_abs,
+ &out_size);
+ if (sfp_abs.status || err || !out_size) {
+ dev_err(&hwdev->hwif->pdev->dev,
+ "Failed to get port%d sfp absent status, err: %d, status: 0x%x, out size: 0x%x\n",
+ port_id, err, sfp_abs.status, out_size);
+ return true;
+ }
+
+ return ((sfp_abs.abs_status == 0) ? false : true);
+}
+
+int hinic_get_sfp_eeprom(struct hinic_hwdev *hwdev, u8 *data, u16 *len)
+{
+ struct hinic_cmd_get_std_sfp_info sfp_info = {0};
+ u16 out_size = sizeof(sfp_info);
+ u8 port_id;
+ int err;
+
+ if (!hwdev || !data || !len)
+ return -EINVAL;
+
+ port_id = hwdev->port_id;
+
+ if (hinic_if_sfp_absent(hwdev))
+ return -ENXIO;
+
+ sfp_info.port_id = port_id;
+ err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_GET_STD_SFP_INFO,
+ &sfp_info, sizeof(sfp_info), &sfp_info,
+ &out_size);
+ if (sfp_info.status || err || !out_size) {
+ dev_err(&hwdev->hwif->pdev->dev,
+ "Failed to get port%d sfp eeprom information, err: %d, status: 0x%x, out size: 0x%x\n",
+ port_id, err, sfp_info.status, out_size);
+ return -EIO;
+ }
+
+ *len = min_t(u16, sfp_info.eeprom_len, STD_SFP_INFO_MAX_SIZE);
+ memcpy(data, sfp_info.sfp_info, STD_SFP_INFO_MAX_SIZE);
+
+ return 0;
+}
+
+int hinic_get_sfp_type(struct hinic_hwdev *hwdev, u8 *data0, u8 *data1)
+{
+ u8 sfp_data[STD_SFP_INFO_MAX_SIZE];
+ u16 len;
+ int err;
+
+ if (!hwdev || !data0 || !data1)
+ return -EINVAL;
+
+ if (hinic_if_sfp_absent(hwdev))
+ return -ENXIO;
+
+ err = hinic_get_sfp_eeprom(hwdev, sfp_data, &len);
+ if (err)
+ return err;
+
+ *data0 = sfp_data[0];
+ *data1 = sfp_data[1];
+
+ return 0;
+}
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_port.h b/drivers/net/ethernet/huawei/hinic/hinic_port.h
index 5c916875f295..0d0354241345 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_port.h
+++ b/drivers/net/ethernet/huawei/hinic/hinic_port.h
@@ -677,6 +677,37 @@ struct hinic_led_info {
u8 reset;
};
+#define MODULE_TYPE_SFP 0x3
+#define MODULE_TYPE_QSFP28 0x11
+#define MODULE_TYPE_QSFP 0x0C
+#define MODULE_TYPE_QSFP_PLUS 0x0D
+
+#define STD_SFP_INFO_MAX_SIZE 640
+
+struct hinic_cmd_get_light_module_abs {
+ u8 status;
+ u8 version;
+ u8 rsvd0[6];
+
+ u8 port_id;
+ u8 abs_status; /* 0:present, 1:absent */
+ u8 rsv[2];
+};
+
+#define STD_SFP_INFO_MAX_SIZE 640
+
+struct hinic_cmd_get_std_sfp_info {
+ u8 status;
+ u8 version;
+ u8 rsvd0[6];
+
+ u8 port_id;
+ u8 wire_type;
+ u16 eeprom_len;
+ u32 rsvd;
+ u8 sfp_info[STD_SFP_INFO_MAX_SIZE];
+};
+
int hinic_port_add_mac(struct hinic_dev *nic_dev, const u8 *addr,
u16 vlan_id);
@@ -800,6 +831,10 @@ int hinic_reset_led_status(struct hinic_hwdev *hwdev, u8 port);
int hinic_set_led_status(struct hinic_hwdev *hwdev, u8 port,
enum hinic_led_type type, enum hinic_led_mode mode);
+int hinic_get_sfp_type(struct hinic_hwdev *hwdev, u8 *data0, u8 *data1);
+
+int hinic_get_sfp_eeprom(struct hinic_hwdev *hwdev, u8 *data, u16 *len);
+
int hinic_open(struct net_device *netdev);
int hinic_close(struct net_device *netdev);
--
2.17.1
^ permalink raw reply related
* [PATCH net-next v1 1/5] hinic: add support to set and get pause params
From: Luo bin @ 2020-06-20 9:42 UTC (permalink / raw)
To: davem; +Cc: linux-kernel, netdev, luoxianjun, yin.yinshi, cloud.wangxiaoyun
In-Reply-To: <20200620094258.13181-1-luobin9@huawei.com>
add support to set pause params with ethtool -A and get pause
params with ethtool -a. Also remove set_link_ksettings ops for VF
and enable pause by default.
Signed-off-by: Luo bin <luobin9@huawei.com>
---
.../net/ethernet/huawei/hinic/hinic_ethtool.c | 96 ++++++++++++++++++-
.../net/ethernet/huawei/hinic/hinic_hw_dev.c | 2 +
.../net/ethernet/huawei/hinic/hinic_hw_dev.h | 2 +
.../net/ethernet/huawei/hinic/hinic_hw_io.h | 10 ++
.../net/ethernet/huawei/hinic/hinic_main.c | 48 ++++++++--
.../net/ethernet/huawei/hinic/hinic_port.c | 40 ++++++++
.../net/ethernet/huawei/hinic/hinic_port.h | 13 +++
7 files changed, 204 insertions(+), 7 deletions(-)
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_ethtool.c b/drivers/net/ethernet/huawei/hinic/hinic_ethtool.c
index efb02e03e7da..c2afa0585dbf 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_ethtool.c
+++ b/drivers/net/ethernet/huawei/hinic/hinic_ethtool.c
@@ -613,6 +613,74 @@ static int hinic_set_ringparam(struct net_device *netdev,
return 0;
}
+
+static void hinic_get_pauseparam(struct net_device *netdev,
+ struct ethtool_pauseparam *pause)
+{
+ struct hinic_dev *nic_dev = netdev_priv(netdev);
+ struct hinic_pause_config pause_info = {0};
+ struct hinic_nic_cfg *nic_cfg;
+ int err;
+
+ nic_cfg = &nic_dev->hwdev->func_to_io.nic_cfg;
+
+ err = hinic_get_hw_pause_info(nic_dev->hwdev, &pause_info);
+ if (err) {
+ netif_err(nic_dev, drv, netdev,
+ "Failed to get pauseparam from hw\n");
+ } else {
+ pause->autoneg = pause_info.auto_neg;
+ if (nic_cfg->pause_set || !pause_info.auto_neg) {
+ pause->rx_pause = nic_cfg->rx_pause;
+ pause->tx_pause = nic_cfg->tx_pause;
+ } else {
+ pause->rx_pause = pause_info.rx_pause;
+ pause->tx_pause = pause_info.tx_pause;
+ }
+ }
+}
+
+static int hinic_set_pauseparam(struct net_device *netdev,
+ struct ethtool_pauseparam *pause)
+{
+ struct hinic_dev *nic_dev = netdev_priv(netdev);
+ struct hinic_pause_config pause_info = {0};
+ struct hinic_port_cap port_cap = {0};
+ int err;
+
+ err = hinic_port_get_cap(nic_dev, &port_cap);
+ if (err) {
+ netif_err(nic_dev, drv, netdev,
+ "Failed to get port capability\n");
+ return -EIO;
+ }
+
+ if (pause->autoneg != port_cap.autoneg_state) {
+ netif_err(nic_dev, drv, netdev,
+ "To change autoneg please use: ethtool -s <dev> autoneg <on|off>\n");
+ return -EOPNOTSUPP;
+ }
+
+ pause_info.auto_neg = pause->autoneg;
+ pause_info.rx_pause = pause->rx_pause;
+ pause_info.tx_pause = pause->tx_pause;
+
+ mutex_lock(&nic_dev->hwdev->func_to_io.nic_cfg.cfg_mutex);
+ err = hinic_set_hw_pause_info(nic_dev->hwdev, &pause_info);
+ if (err) {
+ netif_err(nic_dev, drv, netdev, "Failed to set pauseparam\n");
+ mutex_unlock(&nic_dev->hwdev->func_to_io.nic_cfg.cfg_mutex);
+ return err;
+ }
+ nic_dev->hwdev->func_to_io.nic_cfg.pause_set = true;
+ nic_dev->hwdev->func_to_io.nic_cfg.auto_neg = pause->autoneg;
+ nic_dev->hwdev->func_to_io.nic_cfg.rx_pause = pause->rx_pause;
+ nic_dev->hwdev->func_to_io.nic_cfg.tx_pause = pause->tx_pause;
+ mutex_unlock(&nic_dev->hwdev->func_to_io.nic_cfg.cfg_mutex);
+
+ return 0;
+}
+
static void hinic_get_channels(struct net_device *netdev,
struct ethtool_channels *channels)
{
@@ -1241,6 +1309,27 @@ static const struct ethtool_ops hinic_ethtool_ops = {
.get_link = ethtool_op_get_link,
.get_ringparam = hinic_get_ringparam,
.set_ringparam = hinic_set_ringparam,
+ .get_pauseparam = hinic_get_pauseparam,
+ .set_pauseparam = hinic_set_pauseparam,
+ .get_channels = hinic_get_channels,
+ .set_channels = hinic_set_channels,
+ .get_rxnfc = hinic_get_rxnfc,
+ .set_rxnfc = hinic_set_rxnfc,
+ .get_rxfh_key_size = hinic_get_rxfh_key_size,
+ .get_rxfh_indir_size = hinic_get_rxfh_indir_size,
+ .get_rxfh = hinic_get_rxfh,
+ .set_rxfh = hinic_set_rxfh,
+ .get_sset_count = hinic_get_sset_count,
+ .get_ethtool_stats = hinic_get_ethtool_stats,
+ .get_strings = hinic_get_strings,
+};
+
+static const struct ethtool_ops hinicvf_ethtool_ops = {
+ .get_link_ksettings = hinic_get_link_ksettings,
+ .get_drvinfo = hinic_get_drvinfo,
+ .get_link = ethtool_op_get_link,
+ .get_ringparam = hinic_get_ringparam,
+ .set_ringparam = hinic_set_ringparam,
.get_channels = hinic_get_channels,
.set_channels = hinic_set_channels,
.get_rxnfc = hinic_get_rxnfc,
@@ -1256,5 +1345,10 @@ static const struct ethtool_ops hinic_ethtool_ops = {
void hinic_set_ethtool_ops(struct net_device *netdev)
{
- netdev->ethtool_ops = &hinic_ethtool_ops;
+ struct hinic_dev *nic_dev = netdev_priv(netdev);
+
+ if (!HINIC_IS_VF(nic_dev->hwdev->hwif))
+ netdev->ethtool_ops = &hinic_ethtool_ops;
+ else
+ netdev->ethtool_ops = &hinicvf_ethtool_ops;
}
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c b/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c
index 0245da02efbb..747d50b841ba 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c
+++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c
@@ -777,6 +777,8 @@ struct hinic_hwdev *hinic_init_hwdev(struct pci_dev *pdev)
goto err_dev_cap;
}
+ mutex_init(&hwdev->func_to_io.nic_cfg.cfg_mutex);
+
err = hinic_vf_func_init(hwdev);
if (err) {
dev_err(&pdev->dev, "Failed to init nic mbox\n");
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.h b/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.h
index 71ea7e46dbbc..cc776ca2d737 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.h
+++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.h
@@ -48,6 +48,8 @@ enum hinic_port_cmd {
HINIC_PORT_CMD_ADD_VLAN = 3,
HINIC_PORT_CMD_DEL_VLAN = 4,
+ HINIC_PORT_CMD_SET_PFC = 5,
+
HINIC_PORT_CMD_SET_MAC = 9,
HINIC_PORT_CMD_GET_MAC = 10,
HINIC_PORT_CMD_DEL_MAC = 11,
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_io.h b/drivers/net/ethernet/huawei/hinic/hinic_hw_io.h
index 214f162f7579..ee6d60762d84 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_hw_io.h
+++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_io.h
@@ -47,6 +47,15 @@ struct hinic_free_db_area {
struct semaphore idx_lock;
};
+struct hinic_nic_cfg {
+ /* lock for getting nic cfg */
+ struct mutex cfg_mutex;
+ bool pause_set;
+ u32 auto_neg;
+ u32 rx_pause;
+ u32 tx_pause;
+};
+
struct hinic_func_to_io {
struct hinic_hwif *hwif;
struct hinic_hwdev *hwdev;
@@ -78,6 +87,7 @@ struct hinic_func_to_io {
u16 max_vfs;
struct vf_data_storage *vf_infos;
u8 link_status;
+ struct hinic_nic_cfg nic_cfg;
};
struct hinic_wq_page_size {
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_main.c b/drivers/net/ethernet/huawei/hinic/hinic_main.c
index e9e6f4c9309a..e69edb01fd9b 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_main.c
+++ b/drivers/net/ethernet/huawei/hinic/hinic_main.c
@@ -467,6 +467,7 @@ int hinic_open(struct net_device *netdev)
if (ret)
netif_warn(nic_dev, drv, netdev,
"Failed to revert port state\n");
+
err_port_state:
free_rxqs(nic_dev);
if (nic_dev->flags & HINIC_RSS_ENABLE) {
@@ -887,6 +888,26 @@ static void netdev_features_init(struct net_device *netdev)
netdev->features = netdev->hw_features | NETIF_F_HW_VLAN_CTAG_FILTER;
}
+static void hinic_refresh_nic_cfg(struct hinic_dev *nic_dev)
+{
+ struct hinic_nic_cfg *nic_cfg = &nic_dev->hwdev->func_to_io.nic_cfg;
+ struct hinic_pause_config pause_info = {0};
+ struct hinic_port_cap port_cap = {0};
+
+ if (hinic_port_get_cap(nic_dev, &port_cap))
+ return;
+
+ mutex_lock(&nic_cfg->cfg_mutex);
+ if (nic_cfg->pause_set || !port_cap.autoneg_state) {
+ nic_cfg->auto_neg = port_cap.autoneg_state;
+ pause_info.auto_neg = nic_cfg->auto_neg;
+ pause_info.rx_pause = nic_cfg->rx_pause;
+ pause_info.tx_pause = nic_cfg->tx_pause;
+ hinic_set_hw_pause_info(nic_dev->hwdev, &pause_info);
+ }
+ mutex_unlock(&nic_cfg->cfg_mutex);
+}
+
/**
* link_status_event_handler - link event handler
* @handle: nic device for the handler
@@ -918,6 +939,9 @@ static void link_status_event_handler(void *handle, void *buf_in, u16 in_size,
up(&nic_dev->mgmt_lock);
+ if (!HINIC_IS_VF(nic_dev->hwdev->hwif))
+ hinic_refresh_nic_cfg(nic_dev);
+
netif_info(nic_dev, drv, nic_dev->netdev, "HINIC_Link is UP\n");
} else {
down(&nic_dev->mgmt_lock);
@@ -950,26 +974,38 @@ static int set_features(struct hinic_dev *nic_dev,
u32 csum_en = HINIC_RX_CSUM_OFFLOAD_EN;
int err = 0;
- if (changed & NETIF_F_TSO)
+ if (changed & NETIF_F_TSO) {
err = hinic_port_set_tso(nic_dev, (features & NETIF_F_TSO) ?
HINIC_TSO_ENABLE : HINIC_TSO_DISABLE);
+ if (err)
+ return err;
+ }
- if (changed & NETIF_F_RXCSUM)
+ if (changed & NETIF_F_RXCSUM) {
err = hinic_set_rx_csum_offload(nic_dev, csum_en);
+ if (err)
+ return err;
+ }
if (changed & NETIF_F_LRO) {
err = hinic_set_rx_lro_state(nic_dev,
!!(features & NETIF_F_LRO),
HINIC_LRO_RX_TIMER_DEFAULT,
HINIC_LRO_MAX_WQE_NUM_DEFAULT);
+ if (err)
+ return err;
}
- if (changed & NETIF_F_HW_VLAN_CTAG_RX)
+ if (changed & NETIF_F_HW_VLAN_CTAG_RX) {
err = hinic_set_rx_vlan_offload(nic_dev,
!!(features &
NETIF_F_HW_VLAN_CTAG_RX));
+ if (err)
+ return err;
+ }
- return err;
+ /* enable pause and disable pfc by default */
+ return hinic_dcb_set_pfc(nic_dev->hwdev, 0, 0);
}
/**
@@ -1008,8 +1044,6 @@ static int nic_dev_init(struct pci_dev *pdev)
goto err_alloc_etherdev;
}
- hinic_set_ethtool_ops(netdev);
-
if (!HINIC_IS_VF(hwdev->hwif))
netdev->netdev_ops = &hinic_netdev_ops;
else
@@ -1032,6 +1066,8 @@ static int nic_dev_init(struct pci_dev *pdev)
nic_dev->sriov_info.pdev = pdev;
nic_dev->max_qps = num_qps;
+ hinic_set_ethtool_ops(netdev);
+
sema_init(&nic_dev->mgmt_lock, 1);
tx_stats = &nic_dev->tx_stats;
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_port.c b/drivers/net/ethernet/huawei/hinic/hinic_port.c
index 175c0ee00038..8b007a268675 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_port.c
+++ b/drivers/net/ethernet/huawei/hinic/hinic_port.c
@@ -1082,6 +1082,7 @@ int hinic_get_link_mode(struct hinic_hwdev *hwdev,
if (!hwdev || !link_mode)
return -EINVAL;
+ link_mode->func_id = HINIC_HWIF_FUNC_IDX(hwdev->hwif);
out_size = sizeof(*link_mode);
err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_GET_LINK_MODE,
@@ -1172,6 +1173,8 @@ int hinic_get_hw_pause_info(struct hinic_hwdev *hwdev,
u16 out_size = sizeof(*pause_info);
int err;
+ pause_info->func_id = HINIC_HWIF_FUNC_IDX(hwdev->hwif);
+
err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_GET_PAUSE_INFO,
pause_info, sizeof(*pause_info),
pause_info, &out_size);
@@ -1190,6 +1193,8 @@ int hinic_set_hw_pause_info(struct hinic_hwdev *hwdev,
u16 out_size = sizeof(*pause_info);
int err;
+ pause_info->func_id = HINIC_HWIF_FUNC_IDX(hwdev->hwif);
+
err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_SET_PAUSE_INFO,
pause_info, sizeof(*pause_info),
pause_info, &out_size);
@@ -1201,3 +1206,38 @@ int hinic_set_hw_pause_info(struct hinic_hwdev *hwdev,
return 0;
}
+
+int hinic_dcb_set_pfc(struct hinic_hwdev *hwdev, u8 pfc_en, u8 pfc_bitmap)
+{
+ struct hinic_nic_cfg *nic_cfg = &hwdev->func_to_io.nic_cfg;
+ struct hinic_set_pfc pfc = {0};
+ u16 out_size = sizeof(pfc);
+ int err;
+
+ if (HINIC_IS_VF(hwdev->hwif))
+ return 0;
+
+ mutex_lock(&nic_cfg->cfg_mutex);
+
+ pfc.func_id = HINIC_HWIF_FUNC_IDX(hwdev->hwif);
+ pfc.pfc_bitmap = pfc_bitmap;
+ pfc.pfc_en = pfc_en;
+
+ err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_SET_PFC,
+ &pfc, sizeof(pfc), &pfc, &out_size);
+ if (err || pfc.status || !out_size) {
+ dev_err(&hwdev->hwif->pdev->dev, "Failed to %s pfc, err: %d, status: 0x%x, out size: 0x%x\n",
+ pfc_en ? "enable" : "disable", err, pfc.status,
+ out_size);
+ mutex_unlock(&nic_cfg->cfg_mutex);
+ return -EIO;
+ }
+
+ /* pause settings is opposite from pfc */
+ nic_cfg->rx_pause = pfc_en ? 0 : 1;
+ nic_cfg->tx_pause = pfc_en ? 0 : 1;
+
+ mutex_unlock(&nic_cfg->cfg_mutex);
+
+ return 0;
+}
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_port.h b/drivers/net/ethernet/huawei/hinic/hinic_port.h
index 661c6322dc15..7b17460d4e2c 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_port.h
+++ b/drivers/net/ethernet/huawei/hinic/hinic_port.h
@@ -641,6 +641,17 @@ struct hinic_pause_config {
u32 tx_pause;
};
+struct hinic_set_pfc {
+ u8 status;
+ u8 version;
+ u8 rsvd0[6];
+
+ u16 func_id;
+ u8 pfc_en;
+ u8 pfc_bitmap;
+ u8 rsvd1[4];
+};
+
int hinic_port_add_mac(struct hinic_dev *nic_dev, const u8 *addr,
u16 vlan_id);
@@ -736,6 +747,8 @@ int hinic_get_hw_pause_info(struct hinic_hwdev *hwdev,
int hinic_set_hw_pause_info(struct hinic_hwdev *hwdev,
struct hinic_pause_config *pause_info);
+int hinic_dcb_set_pfc(struct hinic_hwdev *hwdev, u8 pfc_en, u8 pfc_bitmap);
+
int hinic_open(struct net_device *netdev);
int hinic_close(struct net_device *netdev);
--
2.17.1
^ permalink raw reply related
* [PATCH net-next v1 0/5] hinic: add some ethtool ops support
From: Luo bin @ 2020-06-20 9:42 UTC (permalink / raw)
To: davem; +Cc: linux-kernel, netdev, luoxianjun, yin.yinshi, cloud.wangxiaoyun
patch #1: support to set and get pause params with
"ethtool -A/a" cmd
patch #2: support to set and get irq coalesce params with
"ethtool -C/c" cmd
patch #3: support to do self test with "ethtool -t" cmd
patch #4: support to identify physical device with "ethtool -p" cmd
patch #5: support to get eeprom information with "ethtool -m" cmd
Luo bin (5):
hinic: add support to set and get pause params
hinic: add support to set and get irq coalesce
hinic: add self test support
hinic: add support to identify physical device
hinic: add support to get eeprom information
drivers/net/ethernet/huawei/hinic/hinic_dev.h | 14 +
.../net/ethernet/huawei/hinic/hinic_ethtool.c | 677 +++++++++++++++++-
.../net/ethernet/huawei/hinic/hinic_hw_dev.c | 66 ++
.../net/ethernet/huawei/hinic/hinic_hw_dev.h | 31 +
.../net/ethernet/huawei/hinic/hinic_hw_io.h | 10 +
.../net/ethernet/huawei/hinic/hinic_hw_mgmt.h | 7 +-
.../net/ethernet/huawei/hinic/hinic_main.c | 104 ++-
.../net/ethernet/huawei/hinic/hinic_port.c | 200 ++++++
.../net/ethernet/huawei/hinic/hinic_port.h | 99 +++
drivers/net/ethernet/huawei/hinic/hinic_rx.c | 58 +-
.../net/ethernet/huawei/hinic/hinic_sriov.c | 4 +-
drivers/net/ethernet/huawei/hinic/hinic_tx.c | 80 +++
drivers/net/ethernet/huawei/hinic/hinic_tx.h | 2 +
13 files changed, 1341 insertions(+), 11 deletions(-)
--
2.17.1
^ permalink raw reply
* Re: [PATCH v13 4/9] ptp: Reorganize ptp_kvm module to make it arch-independent.
From: kernel test robot @ 2020-06-20 9:21 UTC (permalink / raw)
To: Jianyong Wu, netdev, yangbo.lu, john.stultz, tglx, pbonzini,
sean.j.christopherson, maz, richardcochran, Mark.Rutland, will
Cc: kbuild-all
In-Reply-To: <20200619130120.40556-5-jianyong.wu@arm.com>
[-- Attachment #1: Type: text/plain, Size: 1384 bytes --]
Hi Jianyong,
Thank you for the patch! Yet something to improve:
[auto build test ERROR on linus/master]
[also build test ERROR on v5.8-rc1 next-20200618]
[cannot apply to tip/timers/core kvmarm/next arm64/for-next/core]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use as documented in
https://git-scm.com/docs/git-format-patch]
url: https://github.com/0day-ci/linux/commits/Jianyong-Wu/Enable-ptp_kvm-for-arm64/20200619-210545
base: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git 5e857ce6eae7ca21b2055cca4885545e29228fe2
config: x86_64-randconfig-s022-20200619 (attached as .config)
compiler: gcc-9 (Debian 9.3.0-13) 9.3.0
reproduce:
# apt-get install sparse
# sparse version: v0.6.2-rc1-18-g27caae40-dirty
# save the attached .config to linux build tree
make W=1 C=1 ARCH=x86_64 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__'
If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>
All errors (new ones prefixed by >>):
>> make[3]: *** No rule to make target 'drivers/ptp/ptp_kvm_x86_64.o', needed by 'drivers/ptp/built-in.a'.
make[3]: Target '__build' not remade because of errors.
---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 32195 bytes --]
^ permalink raw reply
* [PATCH net-next 4/4] net: mvpp2: set xlg flow control in mvpp2_mac_link_up()
From: Russell King @ 2020-06-20 9:21 UTC (permalink / raw)
To: Antoine Tenart, Alexandre Belloni; +Cc: David S. Miller, Jakub Kicinski, netdev
In-Reply-To: <20200620092047.GR1551@shell.armlinux.org.uk>
Set the flow control settings in mvpp2_mac_link_up() for 10G links
just as we do for 1G and slower links. This is now the preferred
location.
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
---
.../net/ethernet/marvell/mvpp2/mvpp2_main.c | 23 +++++++++----------
1 file changed, 11 insertions(+), 12 deletions(-)
diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
index 375e3c657162..22891f588c8a 100644
--- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
+++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
@@ -4959,17 +4959,9 @@ static void mvpp2_xlg_config(struct mvpp2_port *port, unsigned int mode,
{
u32 val;
- val = MVPP22_XLG_CTRL0_MAC_RESET_DIS;
- if (state->pause & MLO_PAUSE_TX)
- val |= MVPP22_XLG_CTRL0_TX_FLOW_CTRL_EN;
-
- if (state->pause & MLO_PAUSE_RX)
- val |= MVPP22_XLG_CTRL0_RX_FLOW_CTRL_EN;
-
mvpp2_modify(port->base + MVPP22_XLG_CTRL0_REG,
- MVPP22_XLG_CTRL0_MAC_RESET_DIS |
- MVPP22_XLG_CTRL0_TX_FLOW_CTRL_EN |
- MVPP22_XLG_CTRL0_RX_FLOW_CTRL_EN, val);
+ MVPP22_XLG_CTRL0_MAC_RESET_DIS,
+ MVPP22_XLG_CTRL0_MAC_RESET_DIS);
mvpp2_modify(port->base + MVPP22_XLG_CTRL4_REG,
MVPP22_XLG_CTRL4_MACMODSELECT_GMAC |
MVPP22_XLG_CTRL4_EN_IDLE_CHECK |
@@ -5159,10 +5151,17 @@ static void mvpp2_mac_link_up(struct phylink_config *config,
if (mvpp2_is_xlg(interface)) {
if (!phylink_autoneg_inband(mode)) {
+ val = MVPP22_XLG_CTRL0_FORCE_LINK_PASS;
+ if (tx_pause)
+ val |= MVPP22_XLG_CTRL0_TX_FLOW_CTRL_EN;
+ if (rx_pause)
+ val |= MVPP22_XLG_CTRL0_RX_FLOW_CTRL_EN;
+
mvpp2_modify(port->base + MVPP22_XLG_CTRL0_REG,
MVPP22_XLG_CTRL0_FORCE_LINK_DOWN |
- MVPP22_XLG_CTRL0_FORCE_LINK_PASS,
- MVPP22_XLG_CTRL0_FORCE_LINK_PASS);
+ MVPP22_XLG_CTRL0_FORCE_LINK_PASS |
+ MVPP22_XLG_CTRL0_TX_FLOW_CTRL_EN |
+ MVPP22_XLG_CTRL0_RX_FLOW_CTRL_EN, val);
}
} else {
if (!phylink_autoneg_inband(mode)) {
--
2.20.1
^ permalink raw reply related
* [PATCH net-next 3/4] net: mvpp2: add register modification helper
From: Russell King @ 2020-06-20 9:21 UTC (permalink / raw)
To: Antoine Tenart, Alexandre Belloni; +Cc: David S. Miller, Jakub Kicinski, netdev
In-Reply-To: <20200620092047.GR1551@shell.armlinux.org.uk>
Add a helper to read-modify-write a register, and use it in the phylink
helpers.
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
---
.../net/ethernet/marvell/mvpp2/mvpp2_main.c | 88 ++++++++++---------
1 file changed, 46 insertions(+), 42 deletions(-)
diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
index 313f5a60a605..375e3c657162 100644
--- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
+++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
@@ -1132,6 +1132,17 @@ static bool mvpp2_is_xlg(phy_interface_t interface)
interface == PHY_INTERFACE_MODE_XAUI;
}
+static void mvpp2_modify(void __iomem *ptr, u32 mask, u32 set)
+{
+ u32 old, val;
+
+ old = val = readl(ptr);
+ val &= ~mask;
+ val |= set;
+ if (old != val)
+ writel(val, ptr);
+}
+
static void mvpp22_gop_init_rgmii(struct mvpp2_port *port)
{
struct mvpp2 *priv = port->priv;
@@ -4946,38 +4957,29 @@ static void mvpp2_mac_an_restart(struct phylink_config *config)
static void mvpp2_xlg_config(struct mvpp2_port *port, unsigned int mode,
const struct phylink_link_state *state)
{
- u32 old_ctrl0, ctrl0;
- u32 old_ctrl4, ctrl4;
-
- old_ctrl0 = ctrl0 = readl(port->base + MVPP22_XLG_CTRL0_REG);
- old_ctrl4 = ctrl4 = readl(port->base + MVPP22_XLG_CTRL4_REG);
-
- ctrl0 |= MVPP22_XLG_CTRL0_MAC_RESET_DIS;
+ u32 val;
+ val = MVPP22_XLG_CTRL0_MAC_RESET_DIS;
if (state->pause & MLO_PAUSE_TX)
- ctrl0 |= MVPP22_XLG_CTRL0_TX_FLOW_CTRL_EN;
- else
- ctrl0 &= ~MVPP22_XLG_CTRL0_TX_FLOW_CTRL_EN;
+ val |= MVPP22_XLG_CTRL0_TX_FLOW_CTRL_EN;
if (state->pause & MLO_PAUSE_RX)
- ctrl0 |= MVPP22_XLG_CTRL0_RX_FLOW_CTRL_EN;
- else
- ctrl0 &= ~MVPP22_XLG_CTRL0_RX_FLOW_CTRL_EN;
-
- ctrl4 &= ~(MVPP22_XLG_CTRL4_MACMODSELECT_GMAC |
- MVPP22_XLG_CTRL4_EN_IDLE_CHECK);
- ctrl4 |= MVPP22_XLG_CTRL4_FWD_FC | MVPP22_XLG_CTRL4_FWD_PFC;
-
- if (old_ctrl0 != ctrl0)
- writel(ctrl0, port->base + MVPP22_XLG_CTRL0_REG);
- if (old_ctrl4 != ctrl4)
- writel(ctrl4, port->base + MVPP22_XLG_CTRL4_REG);
-
- if (!(old_ctrl0 & MVPP22_XLG_CTRL0_MAC_RESET_DIS)) {
- while (!(readl(port->base + MVPP22_XLG_CTRL0_REG) &
- MVPP22_XLG_CTRL0_MAC_RESET_DIS))
- continue;
- }
+ val |= MVPP22_XLG_CTRL0_RX_FLOW_CTRL_EN;
+
+ mvpp2_modify(port->base + MVPP22_XLG_CTRL0_REG,
+ MVPP22_XLG_CTRL0_MAC_RESET_DIS |
+ MVPP22_XLG_CTRL0_TX_FLOW_CTRL_EN |
+ MVPP22_XLG_CTRL0_RX_FLOW_CTRL_EN, val);
+ mvpp2_modify(port->base + MVPP22_XLG_CTRL4_REG,
+ MVPP22_XLG_CTRL4_MACMODSELECT_GMAC |
+ MVPP22_XLG_CTRL4_EN_IDLE_CHECK |
+ MVPP22_XLG_CTRL4_FWD_FC | MVPP22_XLG_CTRL4_FWD_PFC,
+ MVPP22_XLG_CTRL4_FWD_FC | MVPP22_XLG_CTRL4_FWD_PFC);
+
+ /* Wait for reset to deassert */
+ do {
+ val = readl(port->base + MVPP22_XLG_CTRL0_REG);
+ } while (!(val & MVPP22_XLG_CTRL0_MAC_RESET_DIS));
}
static void mvpp2_gmac_config(struct mvpp2_port *port, unsigned int mode,
@@ -5157,19 +5159,14 @@ static void mvpp2_mac_link_up(struct phylink_config *config,
if (mvpp2_is_xlg(interface)) {
if (!phylink_autoneg_inband(mode)) {
- val = readl(port->base + MVPP22_XLG_CTRL0_REG);
- val &= ~MVPP22_XLG_CTRL0_FORCE_LINK_DOWN;
- val |= MVPP22_XLG_CTRL0_FORCE_LINK_PASS;
- writel(val, port->base + MVPP22_XLG_CTRL0_REG);
+ mvpp2_modify(port->base + MVPP22_XLG_CTRL0_REG,
+ MVPP22_XLG_CTRL0_FORCE_LINK_DOWN |
+ MVPP22_XLG_CTRL0_FORCE_LINK_PASS,
+ MVPP22_XLG_CTRL0_FORCE_LINK_PASS);
}
} else {
if (!phylink_autoneg_inband(mode)) {
- val = readl(port->base + MVPP2_GMAC_AUTONEG_CONFIG);
- val &= ~(MVPP2_GMAC_FORCE_LINK_DOWN |
- MVPP2_GMAC_CONFIG_MII_SPEED |
- MVPP2_GMAC_CONFIG_GMII_SPEED |
- MVPP2_GMAC_CONFIG_FULL_DUPLEX);
- val |= MVPP2_GMAC_FORCE_LINK_PASS;
+ val = MVPP2_GMAC_FORCE_LINK_PASS;
if (speed == SPEED_1000 || speed == SPEED_2500)
val |= MVPP2_GMAC_CONFIG_GMII_SPEED;
@@ -5179,20 +5176,27 @@ static void mvpp2_mac_link_up(struct phylink_config *config,
if (duplex == DUPLEX_FULL)
val |= MVPP2_GMAC_CONFIG_FULL_DUPLEX;
- writel(val, port->base + MVPP2_GMAC_AUTONEG_CONFIG);
+ mvpp2_modify(port->base + MVPP2_GMAC_AUTONEG_CONFIG,
+ MVPP2_GMAC_FORCE_LINK_DOWN |
+ MVPP2_GMAC_FORCE_LINK_PASS |
+ MVPP2_GMAC_CONFIG_MII_SPEED |
+ MVPP2_GMAC_CONFIG_GMII_SPEED |
+ MVPP2_GMAC_CONFIG_FULL_DUPLEX, val);
}
/* We can always update the flow control enable bits;
* these will only be effective if flow control AN
* (MVPP2_GMAC_FLOW_CTRL_AUTONEG) is disabled.
*/
- val = readl(port->base + MVPP22_GMAC_CTRL_4_REG);
- val &= ~(MVPP22_CTRL4_RX_FC_EN | MVPP22_CTRL4_TX_FC_EN);
+ val = 0;
if (tx_pause)
val |= MVPP22_CTRL4_TX_FC_EN;
if (rx_pause)
val |= MVPP22_CTRL4_RX_FC_EN;
- writel(val, port->base + MVPP22_GMAC_CTRL_4_REG);
+
+ mvpp2_modify(port->base + MVPP22_GMAC_CTRL_4_REG,
+ MVPP22_CTRL4_RX_FC_EN | MVPP22_CTRL4_TX_FC_EN,
+ val);
}
mvpp2_port_enable(port);
--
2.20.1
^ permalink raw reply related
* [PATCH net-next 2/4] net: mvpp2: add mvpp2_phylink_to_port() helper
From: Russell King @ 2020-06-20 9:21 UTC (permalink / raw)
To: Antoine Tenart, Alexandre Belloni; +Cc: David S. Miller, Jakub Kicinski, netdev
In-Reply-To: <20200620092047.GR1551@shell.armlinux.org.uk>
Add a helper to convert the struct phylink_config pointer passed in
from phylink to the drivers internal struct mvpp2_port.
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
---
.../net/ethernet/marvell/mvpp2/mvpp2_main.c | 29 +++++++++----------
1 file changed, 14 insertions(+), 15 deletions(-)
diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
index 7653277d03b7..313f5a60a605 100644
--- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
+++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
@@ -4767,12 +4767,16 @@ static void mvpp2_port_copy_mac_addr(struct net_device *dev, struct mvpp2 *priv,
eth_hw_addr_random(dev);
}
+static struct mvpp2_port *mvpp2_phylink_to_port(struct phylink_config *config)
+{
+ return container_of(config, struct mvpp2_port, phylink_config);
+}
+
static void mvpp2_phylink_validate(struct phylink_config *config,
unsigned long *supported,
struct phylink_link_state *state)
{
- struct mvpp2_port *port = container_of(config, struct mvpp2_port,
- phylink_config);
+ struct mvpp2_port *port = mvpp2_phylink_to_port(config);
__ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, };
/* Invalid combinations */
@@ -4913,8 +4917,7 @@ static void mvpp2_gmac_pcs_get_state(struct mvpp2_port *port,
static void mvpp2_phylink_mac_pcs_get_state(struct phylink_config *config,
struct phylink_link_state *state)
{
- struct mvpp2_port *port = container_of(config, struct mvpp2_port,
- phylink_config);
+ struct mvpp2_port *port = mvpp2_phylink_to_port(config);
if (port->priv->hw_version == MVPP22 && port->gop_id == 0) {
u32 mode = readl(port->base + MVPP22_XLG_CTRL3_REG);
@@ -4931,8 +4934,7 @@ static void mvpp2_phylink_mac_pcs_get_state(struct phylink_config *config,
static void mvpp2_mac_an_restart(struct phylink_config *config)
{
- struct mvpp2_port *port = container_of(config, struct mvpp2_port,
- phylink_config);
+ struct mvpp2_port *port = mvpp2_phylink_to_port(config);
u32 val = readl(port->base + MVPP2_GMAC_AUTONEG_CONFIG);
writel(val | MVPP2_GMAC_IN_BAND_RESTART_AN,
@@ -5105,13 +5107,12 @@ static void mvpp2_gmac_config(struct mvpp2_port *port, unsigned int mode,
static void mvpp2_mac_config(struct phylink_config *config, unsigned int mode,
const struct phylink_link_state *state)
{
- struct net_device *dev = to_net_dev(config->dev);
- struct mvpp2_port *port = netdev_priv(dev);
+ struct mvpp2_port *port = mvpp2_phylink_to_port(config);
bool change_interface = port->phy_interface != state->interface;
/* Check for invalid configuration */
if (mvpp2_is_xlg(state->interface) && port->gop_id != 0) {
- netdev_err(dev, "Invalid mode on %s\n", dev->name);
+ netdev_err(port->dev, "Invalid mode on %s\n", port->dev->name);
return;
}
@@ -5151,8 +5152,7 @@ static void mvpp2_mac_link_up(struct phylink_config *config,
int speed, int duplex,
bool tx_pause, bool rx_pause)
{
- struct net_device *dev = to_net_dev(config->dev);
- struct mvpp2_port *port = netdev_priv(dev);
+ struct mvpp2_port *port = mvpp2_phylink_to_port(config);
u32 val;
if (mvpp2_is_xlg(interface)) {
@@ -5199,14 +5199,13 @@ static void mvpp2_mac_link_up(struct phylink_config *config,
mvpp2_egress_enable(port);
mvpp2_ingress_enable(port);
- netif_tx_wake_all_queues(dev);
+ netif_tx_wake_all_queues(port->dev);
}
static void mvpp2_mac_link_down(struct phylink_config *config,
unsigned int mode, phy_interface_t interface)
{
- struct net_device *dev = to_net_dev(config->dev);
- struct mvpp2_port *port = netdev_priv(dev);
+ struct mvpp2_port *port = mvpp2_phylink_to_port(config);
u32 val;
if (!phylink_autoneg_inband(mode)) {
@@ -5223,7 +5222,7 @@ static void mvpp2_mac_link_down(struct phylink_config *config,
}
}
- netif_tx_stop_all_queues(dev);
+ netif_tx_stop_all_queues(port->dev);
mvpp2_egress_disable(port);
mvpp2_ingress_disable(port);
--
2.20.1
^ permalink raw reply related
* [PATCH net-next 1/4] net: mvpp2: add port support helpers
From: Russell King @ 2020-06-20 9:21 UTC (permalink / raw)
To: Antoine Tenart, Alexandre Belloni; +Cc: David S. Miller, Jakub Kicinski, netdev
In-Reply-To: <20200620092047.GR1551@shell.armlinux.org.uk>
The mvpp2 code has tests scattered amongst the code to determine
whether the port supports the XLG, and whether the port supports
RGMII mode.
Rather than having these tests scattered, provide a couple of helper
functions, so that future additions can ensure that they get these
tests correct.
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
---
.../net/ethernet/marvell/mvpp2/mvpp2_main.c | 43 ++++++++++++-------
1 file changed, 27 insertions(+), 16 deletions(-)
diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
index 24f4d8e0da98..7653277d03b7 100644
--- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
+++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
@@ -1114,6 +1114,17 @@ mvpp2_shared_interrupt_mask_unmask(struct mvpp2_port *port, bool mask)
}
}
+/* Only GOP port 0 has an XLG MAC */
+static bool mvpp2_port_supports_xlg(struct mvpp2_port *port)
+{
+ return port->gop_id == 0;
+}
+
+static bool mvpp2_port_supports_rgmii(struct mvpp2_port *port)
+{
+ return !(port->priv->hw_version == MVPP22 && port->gop_id == 0);
+}
+
/* Port configuration routines */
static bool mvpp2_is_xlg(phy_interface_t interface)
{
@@ -1194,7 +1205,7 @@ static int mvpp22_gop_init(struct mvpp2_port *port)
case PHY_INTERFACE_MODE_RGMII_ID:
case PHY_INTERFACE_MODE_RGMII_RXID:
case PHY_INTERFACE_MODE_RGMII_TXID:
- if (port->gop_id == 0)
+ if (!mvpp2_port_supports_rgmii(port))
goto invalid_conf;
mvpp22_gop_init_rgmii(port);
break;
@@ -1204,7 +1215,7 @@ static int mvpp22_gop_init(struct mvpp2_port *port)
mvpp22_gop_init_sgmii(port);
break;
case PHY_INTERFACE_MODE_10GBASER:
- if (port->gop_id != 0)
+ if (!mvpp2_port_supports_xlg(port))
goto invalid_conf;
mvpp22_gop_init_10gkr(port);
break;
@@ -1246,7 +1257,7 @@ static void mvpp22_gop_unmask_irq(struct mvpp2_port *port)
writel(val, port->base + MVPP22_GMAC_INT_SUM_MASK);
}
- if (port->gop_id == 0) {
+ if (mvpp2_port_supports_xlg(port)) {
/* Enable the XLG/GIG irqs for this port */
val = readl(port->base + MVPP22_XLG_EXT_INT_MASK);
if (mvpp2_is_xlg(port->phy_interface))
@@ -1261,7 +1272,7 @@ static void mvpp22_gop_mask_irq(struct mvpp2_port *port)
{
u32 val;
- if (port->gop_id == 0) {
+ if (mvpp2_port_supports_xlg(port)) {
val = readl(port->base + MVPP22_XLG_EXT_INT_MASK);
val &= ~(MVPP22_XLG_EXT_INT_MASK_XLG |
MVPP22_XLG_EXT_INT_MASK_GIG);
@@ -1290,7 +1301,7 @@ static void mvpp22_gop_setup_irq(struct mvpp2_port *port)
writel(val, port->base + MVPP22_GMAC_INT_MASK);
}
- if (port->gop_id == 0) {
+ if (mvpp2_port_supports_xlg(port)) {
val = readl(port->base + MVPP22_XLG_INT_MASK);
val |= MVPP22_XLG_INT_MASK_LINK;
writel(val, port->base + MVPP22_XLG_INT_MASK);
@@ -1328,8 +1339,8 @@ static void mvpp2_port_enable(struct mvpp2_port *port)
{
u32 val;
- /* Only GOP port 0 has an XLG MAC */
- if (port->gop_id == 0 && mvpp2_is_xlg(port->phy_interface)) {
+ if (mvpp2_port_supports_xlg(port) &&
+ mvpp2_is_xlg(port->phy_interface)) {
val = readl(port->base + MVPP22_XLG_CTRL0_REG);
val |= MVPP22_XLG_CTRL0_PORT_EN;
val &= ~MVPP22_XLG_CTRL0_MIB_CNT_DIS;
@@ -1346,8 +1357,8 @@ static void mvpp2_port_disable(struct mvpp2_port *port)
{
u32 val;
- /* Only GOP port 0 has an XLG MAC */
- if (port->gop_id == 0 && mvpp2_is_xlg(port->phy_interface)) {
+ if (mvpp2_port_supports_xlg(port) &&
+ mvpp2_is_xlg(port->phy_interface)) {
val = readl(port->base + MVPP22_XLG_CTRL0_REG);
val &= ~MVPP22_XLG_CTRL0_PORT_EN;
writel(val, port->base + MVPP22_XLG_CTRL0_REG);
@@ -2740,7 +2751,8 @@ static irqreturn_t mvpp2_link_status_isr(int irq, void *dev_id)
mvpp22_gop_mask_irq(port);
- if (port->gop_id == 0 && mvpp2_is_xlg(port->phy_interface)) {
+ if (mvpp2_port_supports_xlg(port) &&
+ mvpp2_is_xlg(port->phy_interface)) {
val = readl(port->base + MVPP22_XLG_INT_STAT);
if (val & MVPP22_XLG_INT_STAT_LINK) {
event = true;
@@ -3430,8 +3442,7 @@ static void mvpp22_mode_reconfigure(struct mvpp2_port *port)
mvpp22_pcs_reset_deassert(port);
- /* Only GOP port 0 has an XLG MAC */
- if (port->gop_id == 0) {
+ if (mvpp2_port_supports_xlg(port)) {
ctrl3 = readl(port->base + MVPP22_XLG_CTRL3_REG);
ctrl3 &= ~MVPP22_XLG_CTRL3_MACMODESELECT_MASK;
@@ -3443,7 +3454,7 @@ static void mvpp22_mode_reconfigure(struct mvpp2_port *port)
writel(ctrl3, port->base + MVPP22_XLG_CTRL3_REG);
}
- if (port->gop_id == 0 && mvpp2_is_xlg(port->phy_interface))
+ if (mvpp2_port_supports_xlg(port) && mvpp2_is_xlg(port->phy_interface))
mvpp2_xlg_max_rx_size_set(port);
else
mvpp2_gmac_max_rx_size_set(port);
@@ -4768,14 +4779,14 @@ static void mvpp2_phylink_validate(struct phylink_config *config,
switch (state->interface) {
case PHY_INTERFACE_MODE_10GBASER:
case PHY_INTERFACE_MODE_XAUI:
- if (port->gop_id != 0)
+ if (!mvpp2_port_supports_xlg(port))
goto empty_set;
break;
case PHY_INTERFACE_MODE_RGMII:
case PHY_INTERFACE_MODE_RGMII_ID:
case PHY_INTERFACE_MODE_RGMII_RXID:
case PHY_INTERFACE_MODE_RGMII_TXID:
- if (port->priv->hw_version == MVPP22 && port->gop_id == 0)
+ if (!mvpp2_port_supports_rgmii(port))
goto empty_set;
break;
default:
@@ -4791,7 +4802,7 @@ static void mvpp2_phylink_validate(struct phylink_config *config,
case PHY_INTERFACE_MODE_10GBASER:
case PHY_INTERFACE_MODE_XAUI:
case PHY_INTERFACE_MODE_NA:
- if (port->gop_id == 0) {
+ if (mvpp2_port_supports_xlg(port)) {
phylink_set(mask, 10000baseT_Full);
phylink_set(mask, 10000baseCR_Full);
phylink_set(mask, 10000baseSR_Full);
--
2.20.1
^ permalink raw reply related
* [PATCH net-next v2 0/4] Marvell mvpp2 improvements
From: Russell King - ARM Linux admin @ 2020-06-20 9:20 UTC (permalink / raw)
To: Antoine Tenart, Alexandre Belloni; +Cc: David S. Miller, Jakub Kicinski, netdev
Hi,
This series primarily cleans up mvpp2, but also fixes a left-over from
91a208f2185a ("net: phylink: propagate resolved link config via
mac_link_up()").
Patch 1 introduces some port helpers:
mvpp2_port_supports_xlg() - does the port support the XLG MAC
mvpp2_port_supports_rgmii() - does the port support RGMII modes
Patch 2 introduces mvpp2_phylink_to_port(), rather than having repeated
open coding of container_of().
Patch 3 introduces mvpp2_modify(), which reads-modifies-writes a
register - I've converted the phylink specific code to use this
helper.
Patch 4 moves the hardware control of the pause modes from
mvpp2_xlg_config() (which is called via the phylink_config method)
to mvpp2_mac_link_up() - a change that was missed in the above
referenced commit.
v2: remove "inline" in patch 2.
drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c | 163 +++++++++++++-----------
1 file changed, 88 insertions(+), 75 deletions(-)
--
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 40Mbps down 10Mbps up. Decent connectivity at last!
^ permalink raw reply
* [PATCH net-next 2/2] bnxt_en: Add board_serial_number field to info_get cb
From: Vasundhara Volam @ 2020-06-20 8:15 UTC (permalink / raw)
To: davem; +Cc: netdev, michael.chan, kuba, jiri, jacob.e.keller,
Vasundhara Volam
In-Reply-To: <1592640947-10421-1-git-send-email-vasundhara-v.volam@broadcom.com>
Add board_serial_number field info to info_get cb via devlink,
if driver can fetch the information from the device.
Cc: Jiri Pirko <jiri@mellanox.com>
Cc: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Vasundhara Volam <vasundhara-v.volam@broadcom.com>
Reviewed-by: Michael Chan <michael.chan@broadcom.com>
---
drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c
index a812beb..16eca3b 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c
@@ -411,6 +411,13 @@ static int bnxt_dl_info_get(struct devlink *dl, struct devlink_info_req *req,
return rc;
}
+ if (strlen(bp->board_serialno)) {
+ rc = devlink_info_board_serial_number_put(req,
+ bp->board_serialno);
+ if (rc)
+ return rc;
+ }
+
sprintf(buf, "%X", bp->chip_num);
rc = devlink_info_version_fixed_put(req,
DEVLINK_INFO_VERSION_GENERIC_ASIC_ID, buf);
--
1.8.3.1
^ permalink raw reply related
* [PATCH net-next 1/2] devlink: Add support for board_serial_number to info_get cb.
From: Vasundhara Volam @ 2020-06-20 8:15 UTC (permalink / raw)
To: davem; +Cc: netdev, michael.chan, kuba, jiri, jacob.e.keller,
Vasundhara Volam
In-Reply-To: <1592640947-10421-1-git-send-email-vasundhara-v.volam@broadcom.com>
Board serial number is a serial number, often available in PCI
*Vital Product Data*.
Also, update devlink-info.rst documentation file.
Cc: Jiri Pirko <jiri@mellanox.com>
Cc: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Vasundhara Volam <vasundhara-v.volam@broadcom.com>
Reviewed-by: Michael Chan <michael.chan@broadcom.com>
---
Documentation/networking/devlink/devlink-info.rst | 12 +++++-------
include/net/devlink.h | 2 ++
include/uapi/linux/devlink.h | 2 ++
net/core/devlink.c | 8 ++++++++
4 files changed, 17 insertions(+), 7 deletions(-)
diff --git a/Documentation/networking/devlink/devlink-info.rst b/Documentation/networking/devlink/devlink-info.rst
index 3fe1140..d80c846 100644
--- a/Documentation/networking/devlink/devlink-info.rst
+++ b/Documentation/networking/devlink/devlink-info.rst
@@ -44,9 +44,11 @@ versions is generally discouraged - here, and via any other Linux API.
reported for two ports of the same device or on two hosts of
a multi-host device should be identical.
- .. note:: ``devlink-info`` API should be extended with a new field
- if devices want to report board/product serial number (often
- reported in PCI *Vital Product Data* capability).
+ * - ``board_serial_number``
+ - Board serial number of the device.
+
+ This is usually the serial number of the board, often available in
+ PCI *Vital Product Data*.
* - ``fixed``
- Group for hardware identifiers, and versions of components
@@ -201,10 +203,6 @@ Future work
The following extensions could be useful:
- - product serial number - NIC boards often get labeled with a board serial
- number rather than ASIC serial number; it'd be useful to add board serial
- numbers to the API if they can be retrieved from the device;
-
- on-disk firmware file names - drivers list the file names of firmware they
may need to load onto devices via the ``MODULE_FIRMWARE()`` macro. These,
however, are per module, rather than per device. It'd be useful to list
diff --git a/include/net/devlink.h b/include/net/devlink.h
index 1df6dfe..a8ceb7b 100644
--- a/include/net/devlink.h
+++ b/include/net/devlink.h
@@ -1262,6 +1262,8 @@ int devlink_info_serial_number_put(struct devlink_info_req *req,
const char *sn);
int devlink_info_driver_name_put(struct devlink_info_req *req,
const char *name);
+int devlink_info_board_serial_number_put(struct devlink_info_req *req,
+ const char *bsn);
int devlink_info_version_fixed_put(struct devlink_info_req *req,
const char *version_name,
const char *version_value);
diff --git a/include/uapi/linux/devlink.h b/include/uapi/linux/devlink.h
index 08563e6..06eb29c 100644
--- a/include/uapi/linux/devlink.h
+++ b/include/uapi/linux/devlink.h
@@ -451,6 +451,8 @@ enum devlink_attr {
DEVLINK_ATTR_TRAP_POLICER_RATE, /* u64 */
DEVLINK_ATTR_TRAP_POLICER_BURST, /* u64 */
+ DEVLINK_ATTR_INFO_BOARD_SERIAL_NUMBER, /* string */
+
/* add new attributes above here, update the policy in devlink.c */
__DEVLINK_ATTR_MAX,
diff --git a/net/core/devlink.c b/net/core/devlink.c
index 2cafbc8..a97c169 100644
--- a/net/core/devlink.c
+++ b/net/core/devlink.c
@@ -4378,6 +4378,14 @@ int devlink_info_serial_number_put(struct devlink_info_req *req, const char *sn)
}
EXPORT_SYMBOL_GPL(devlink_info_serial_number_put);
+int devlink_info_board_serial_number_put(struct devlink_info_req *req,
+ const char *bsn)
+{
+ return nla_put_string(req->msg, DEVLINK_ATTR_INFO_BOARD_SERIAL_NUMBER,
+ bsn);
+}
+EXPORT_SYMBOL_GPL(devlink_info_board_serial_number_put);
+
static int devlink_info_version_put(struct devlink_info_req *req, int attr,
const char *version_name,
const char *version_value)
--
1.8.3.1
^ permalink raw reply related
* [PATCH net-next 0/2] devlink: Add board_serial_number field to info_get cb.
From: Vasundhara Volam @ 2020-06-20 8:15 UTC (permalink / raw)
To: davem; +Cc: netdev, michael.chan, kuba, jiri, jacob.e.keller,
Vasundhara Volam
This patchset adds support for board_serial_number to devlink info_get
cb and also use it in bnxt_en driver.
Sample output:
$ devlink dev info pci/0000:af:00.1
pci/0000:af:00.1:
driver bnxt_en
serial_number 00-10-18-FF-FE-AD-1A-00
board_serial_number 433551F+172300000
versions:
fixed:
board.id 7339763 Rev 0.
asic.id 16D7
asic.rev 1
running:
fw 216.1.216.0
fw.psid 0.0.0
fw.mgmt 216.1.192.0
fw.mgmt.api 1.10.1
fw.ncsi 0.0.0.0
fw.roce 216.1.16.0
Vasundhara Volam (2):
devlink: Add support for board_serial_number to info_get cb.
bnxt_en: Add board_serial_number field to info_get cb
Documentation/networking/devlink/devlink-info.rst | 12 +++++-------
drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c | 7 +++++++
include/net/devlink.h | 2 ++
include/uapi/linux/devlink.h | 2 ++
net/core/devlink.c | 8 ++++++++
5 files changed, 24 insertions(+), 7 deletions(-)
--
1.8.3.1
^ permalink raw reply
* Re: [PATCH v13 4/9] ptp: Reorganize ptp_kvm module to make it arch-independent.
From: kernel test robot @ 2020-06-20 8:04 UTC (permalink / raw)
To: Jianyong Wu, netdev, yangbo.lu, john.stultz, tglx, pbonzini,
sean.j.christopherson, maz, richardcochran, Mark.Rutland, will
Cc: kbuild-all
In-Reply-To: <20200619130120.40556-5-jianyong.wu@arm.com>
[-- Attachment #1: Type: text/plain, Size: 1383 bytes --]
Hi Jianyong,
Thank you for the patch! Yet something to improve:
[auto build test ERROR on linus/master]
[also build test ERROR on v5.8-rc1 next-20200618]
[cannot apply to tip/timers/core kvmarm/next arm64/for-next/core]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use as documented in
https://git-scm.com/docs/git-format-patch]
url: https://github.com/0day-ci/linux/commits/Jianyong-Wu/Enable-ptp_kvm-for-arm64/20200619-210545
base: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git 5e857ce6eae7ca21b2055cca4885545e29228fe2
config: x86_64-randconfig-s021-20200619 (attached as .config)
compiler: gcc-9 (Debian 9.3.0-13) 9.3.0
reproduce:
# apt-get install sparse
# sparse version: v0.6.2-rc1-18-g27caae40-dirty
# save the attached .config to linux build tree
make W=1 C=1 ARCH=x86_64 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__'
If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>
All errors (new ones prefixed by >>):
>> make[3]: *** No rule to make target 'drivers/ptp/ptp_kvm_x86_64.o', needed by 'drivers/ptp/ptp_kvm.o'.
make[3]: Target '__build' not remade because of errors.
---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 34548 bytes --]
^ permalink raw reply
* Re: [PATCH] linux++, this: rename "struct notifier_block *this"
From: Alexey Dobriyan @ 2020-06-20 7:57 UTC (permalink / raw)
To: Linus Torvalds; +Cc: Linux Kernel Mailing List, Netdev, linux-arch, NetFilter
In-Reply-To: <CAHk-=whz7xz1EBqfyS-C8zTx3_q54R1GuX9tDHdK1-TG91WH-Q@mail.gmail.com>
On Fri, Jun 19, 2020 at 11:37:47AM -0700, Linus Torvalds wrote:
> On Thu, Jun 18, 2020 at 2:06 PM Alexey Dobriyan <adobriyan@gmail.com> wrote:
> >
> > Rename
> > struct notifier_block *this
> > to
> > struct notifier_block *nb
> >
> > "nb" is arguably a better name for notifier block.
>
> Maybe it's a better name. But it doesn't seem worth it.
>
> Because C++ reserved words are entirely irrelevant.
>
> We did this same dance almost three decades ago, and the fact is, C++
> has other reserved words that make it all pointless.
The real problems are "class" and "new" indeed.
> There is no way I will accept the renaming of various "new" variables.
I'm not sending "new".
> We did it, it was bad, we undid it, and we now have a _lot_ more uses
> of 'new' and 'old', and no, we're not changing it for a braindead
> language that isn't relevant to the kernel.
>
> The fact is, C++ chose bad identifiers to make reserved words.
>
> If you want to build the kernel with C++, you'd be a lot better off just doing
>
> /* C++ braindamage */
> #define this __this
> #define new __new
>
> and deal with that instead.
Can't do this because of placement new.
> Because no, the 'new' renaming will never happen, and while 'this'
> isn't nearly as common or relevant a name, once you have the same
> issue with 'new', what's the point of trying to deal with 'this'?
I'm not sending "new".
There is stuff which can be merge without breaking source compatibility
and readability of C version:
private => priv
virtual => virt
this => self (in some contexts)
and those which can not. I'm not sending the latter.
^ permalink raw reply
* Re: [Patch net] cgroup: fix cgroup_sk_alloc() for sk_clone_lock()
From: Zefan Li @ 2020-06-20 7:52 UTC (permalink / raw)
To: Cong Wang
Cc: Roman Gushchin, Linux Kernel Network Developers,
Cameron Berkenpas, Peter Geis, Lu Fengqi, Daniël Sonck,
Daniel Borkmann, Tejun Heo
In-Reply-To: <CAM_iQpXpZd6ZaQyQifWOHSnqgAgdu1qP+fF_Na7rQ_H1vQ6eig@mail.gmail.com>
在 2020/6/20 11:31, Cong Wang 写道:
> On Fri, Jun 19, 2020 at 5:51 PM Zefan Li <lizefan@huawei.com> wrote:
>>
>> 在 2020/6/20 8:45, Zefan Li 写道:
>>> On 2020/6/20 3:51, Cong Wang wrote:
>>>> On Thu, Jun 18, 2020 at 11:40 PM Zefan Li <lizefan@huawei.com> wrote:
>>>>>
>>>>> On 2020/6/19 5:09, Cong Wang wrote:
>>>>>> On Thu, Jun 18, 2020 at 12:36 PM Roman Gushchin <guro@fb.com> wrote:
>>>>>>>
>>>>>>> On Thu, Jun 18, 2020 at 12:19:13PM -0700, Cong Wang wrote:
>>>>>>>> On Wed, Jun 17, 2020 at 6:44 PM Zefan Li <lizefan@huawei.com> wrote:
>>>>>>>>>
>>>>>>>>> Cc: Roman Gushchin <guro@fb.com>
>>>>>>>>>
>>>>>>>>> Thanks for fixing this.
>>>>>>>>>
>>>>>>>>> On 2020/6/17 2:03, Cong Wang wrote:
>>>>>>>>>> When we clone a socket in sk_clone_lock(), its sk_cgrp_data is
>>>>>>>>>> copied, so the cgroup refcnt must be taken too. And, unlike the
>>>>>>>>>> sk_alloc() path, sock_update_netprioidx() is not called here.
>>>>>>>>>> Therefore, it is safe and necessary to grab the cgroup refcnt
>>>>>>>>>> even when cgroup_sk_alloc is disabled.
>>>>>>>>>>
>>>>>>>>>> sk_clone_lock() is in BH context anyway, the in_interrupt()
>>>>>>>>>> would terminate this function if called there. And for sk_alloc()
>>>>>>>>>> skcd->val is always zero. So it's safe to factor out the code
>>>>>>>>>> to make it more readable.
>>>>>>>>>>
>>>>>>>>>> Fixes: 090e28b229af92dc5b ("netprio_cgroup: Fix unlimited memory leak of v2 cgroups")
>>>>>>>>>
>>>>>>>>> but I don't think the bug was introduced by this commit, because there
>>>>>>>>> are already calls to cgroup_sk_alloc_disable() in write_priomap() and
>>>>>>>>> write_classid(), which can be triggered by writing to ifpriomap or
>>>>>>>>> classid in cgroupfs. This commit just made it much easier to happen
>>>>>>>>> with systemd invovled.
>>>>>>>>>
>>>>>>>>> I think it's 4bfc0bb2c60e2f4c ("bpf: decouple the lifetime of cgroup_bpf from cgroup itself"),
>>>>>>>>> which added cgroup_bpf_get() in cgroup_sk_alloc().
>>>>>>>>
>>>>>>>> Good point.
>>>>>>>>
>>>>>>>> I take a deeper look, it looks like commit d979a39d7242e06
>>>>>>>> is the one to blame, because it is the first commit that began to
>>>>>>>> hold cgroup refcnt in cgroup_sk_alloc().
>>>>>>>
>>>>>>> I agree, ut seems that the issue is not related to bpf and probably
>>>>>>> can be reproduced without CONFIG_CGROUP_BPF. d979a39d7242e06 indeed
>>>>>>> seems closer to the origin.
>>>>>>
>>>>>> Yeah, I will update the Fixes tag and send V2.
>>>>>>
>>>>>
>>>>> Commit d979a39d7242e06 looks innocent to me. With this commit when cgroup_sk_alloc
>>>>> is disabled and then a socket is cloned the cgroup refcnt will not be incremented,
>>>>> but this is fine, because when the socket is to be freed:
>>>>>
>>>>> sk_prot_free()
>>>>> cgroup_sk_free()
>>>>> cgroup_put(sock_cgroup_ptr(skcd)) == cgroup_put(&cgrp_dfl_root.cgrp)
>>>>>
>>>>> cgroup_put() does nothing for the default root cgroup, so nothing bad will happen.
>>>>
>>>> But skcd->val can be a pointer to a non-root cgroup:
>>>
>>> It returns a non-root cgroup when cgroup_sk_alloc is not disabled. The bug happens
>>> when cgroup_sk_alloc is disabled.
>>>
>>
>> And please read those recent bug reports, they all happened when bpf cgroup was in use,
>> and there was no bpf cgroup when d979a39d7242e06 was merged into mainline.
>
> I am totally aware of this. My concern is whether cgroup
> has the same refcnt bug as it always pairs with the bpf refcnt.
>
> But, after a second look, the non-root cgroup refcnt is immediately
> overwritten by sock_update_classid() or sock_update_netprioidx(),
> which effectively turns into a root cgroup again. :-/
>
> (It seems we leak a refcnt here, but this is not related to my patch).
>
Indead, but it's well known, see bd1060a1d67128bb8fbe2. But now bpf cgroup comes into play...
Your patch doesn't seem to fix the bug completely. If cgroup_sk_alloc_disable happens after
socket cloning, then we will deref the bpf of the root cgroup while incref-ed the bpf of a
non-root cgroup.
^ permalink raw reply
* Re: [PATCH bpf] libbpf: fix CO-RE relocs against .text section
From: Yonghong Song @ 2020-06-20 7:04 UTC (permalink / raw)
To: Andrii Nakryiko, bpf, netdev, ast, daniel; +Cc: andrii.nakryiko, kernel-team
In-Reply-To: <20200619230423.691274-1-andriin@fb.com>
On 6/19/20 4:04 PM, Andrii Nakryiko wrote:
> bpf_object__find_program_by_title(), used by CO-RE relocation code, doesn't
> return .text "BPF program", if it is a function storage for sub-programs.
> Because of that, any CO-RE relocation in helper non-inlined functions will
> fail. Fix this by searching for .text-corresponding BPF program manually.
>
> Adjust one of bpf_iter selftest to exhibit this pattern.
>
> Reported-by: Yonghong Song <yhs@fb.com>
> Fixes: ddc7c3042614 ("libbpf: implement BPF CO-RE offset relocation algorithm")
> Signed-off-by: Andrii Nakryiko <andriin@fb.com>
Acked-by: Yonghong Song <yhs@fb.com>
But the fix here only fixed the issue for interpreter mode.
For jit only mode, we still have issues. The following patch can fix
the jit mode issue,
=============
From 4d66814513ec45b86a30a1231b8a000d4bfc6f1a Mon Sep 17 00:00:00 2001
From: Yonghong Song <yhs@fb.com>
Date: Fri, 19 Jun 2020 23:26:13 -0700
Subject: [PATCH bpf] bpf: set the number of exception entries properly for
subprograms
Currently, if a bpf program has more than one subprograms, each
program will be jitted separately. For tracing problem, the
prog->aux->num_exentries is not setup properly. For example,
with bpf_iter_netlink.c modified to force one function not inlined,
and with proper libbpf fix, with CONFIG_BPF_JIT_ALWAYS_ON,
we will have error like below:
$ ./test_progs -n 3/3
...
libbpf: failed to load program 'iter/netlink'
libbpf: failed to load object 'bpf_iter_netlink'
libbpf: failed to load BPF skeleton 'bpf_iter_netlink': -4007
test_netlink:FAIL:bpf_iter_netlink__open_and_load skeleton
open_and_load failed
#3/3 netlink:FAIL
The dmesg shows the following errors:
ex gen bug
which is triggered by the following code in arch/x86/net/bpf_jit_comp.c:
if (excnt >= bpf_prog->aux->num_exentries) {
pr_err("ex gen bug\n");
return -EFAULT;
}
If the program has more than one subprograms, num_exentries is actually
0 since it is not setup.
This patch fixed the issue by setuping proper num_exentries for
each subprogram before calling jit function.
Signed-off-by: Yonghong Song <yhs@fb.com>
---
kernel/bpf/verifier.c | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 34cde841ab68..7d8b23ba825c 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -9801,7 +9801,7 @@ static int jit_subprogs(struct bpf_verifier_env *env)
int i, j, subprog_start, subprog_end = 0, len, subprog;
struct bpf_insn *insn;
void *old_bpf_func;
- int err;
+ int err, num_exentries;
if (env->subprog_cnt <= 1)
return 0;
@@ -9876,6 +9876,16 @@ static int jit_subprogs(struct bpf_verifier_env *env)
func[i]->aux->nr_linfo = prog->aux->nr_linfo;
func[i]->aux->jited_linfo = prog->aux->jited_linfo;
func[i]->aux->linfo_idx = env->subprog_info[i].linfo_idx;
+
+ num_exentries = 0;
+ insn = func[i]->insnsi;
+ for (j = 0; j < func[i]->len; j++, insn++) {
+ if (BPF_CLASS(insn->code) == BPF_LDX &&
+ BPF_MODE(insn->code) == BPF_PROBE_MEM)
+ num_exentries++;
+ }
+ func[i]->aux->num_exentries = num_exentries;
+
func[i] = bpf_int_jit_compile(func[i]);
if (!func[i]->jited) {
err = -ENOTSUPP;
--
2.24.1
================
We need this (or similar fixes) go in together with libbpf fix
to avoid bpf_iter_netlink.c test failure at jit only mode.
Do we need a separate patch for the above fix? Or Andrii can
fold this into his patch and resubmit? Maybe the latter is better.
> ---
> tools/lib/bpf/libbpf.c | 8 +++++++-
> tools/testing/selftests/bpf/progs/bpf_iter_netlink.c | 2 +-
> 2 files changed, 8 insertions(+), 2 deletions(-)
>
> diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
> index 477c679ed945..f17151d866e6 100644
> --- a/tools/lib/bpf/libbpf.c
> +++ b/tools/lib/bpf/libbpf.c
> @@ -4818,7 +4818,13 @@ bpf_core_reloc_fields(struct bpf_object *obj, const char *targ_btf_path)
> err = -EINVAL;
> goto out;
> }
> - prog = bpf_object__find_program_by_title(obj, sec_name);
> + prog = NULL;
> + for (i = 0; i < obj->nr_programs; i++) {
> + if (!strcmp(obj->programs[i].section_name, sec_name)) {
> + prog = &obj->programs[i];
> + break;
> + }
> + }
> if (!prog) {
> pr_warn("failed to find program '%s' for CO-RE offset relocation\n",
> sec_name);
> diff --git a/tools/testing/selftests/bpf/progs/bpf_iter_netlink.c b/tools/testing/selftests/bpf/progs/bpf_iter_netlink.c
> index e7b8753eac0b..75ecf956a2df 100644
> --- a/tools/testing/selftests/bpf/progs/bpf_iter_netlink.c
> +++ b/tools/testing/selftests/bpf/progs/bpf_iter_netlink.c
> @@ -25,7 +25,7 @@ struct bpf_iter__netlink {
> struct netlink_sock *sk;
> } __attribute__((preserve_access_index));
>
> -static inline struct inode *SOCK_INODE(struct socket *socket)
> +static __attribute__((noinline)) struct inode *SOCK_INODE(struct socket *socket)
> {
> return &container_of(socket, struct socket_alloc, socket)->vfs_inode;
> }
>
^ permalink raw reply related
* Re: [PATCH v2 00/16] Remove uninitialized_var() macro
From: Sedat Dilek @ 2020-06-20 7:03 UTC (permalink / raw)
To: Kees Cook
Cc: linux-kernel, Linus Torvalds, Miguel Ojeda, Alexander Potapenko,
Joe Perches, Andy Whitcroft, x86, drbd-dev, linux-block, b43-dev,
netdev, linux-doc, linux-wireless, linux-ide, linux-clk,
linux-spi, linux-mm, Clang-Built-Linux ML
In-Reply-To: <20200620033007.1444705-1-keescook@chromium.org>
On Sat, Jun 20, 2020 at 5:30 AM Kees Cook <keescook@chromium.org> wrote:
>
> v2:
> - more special-cased fixes
> - add reviews
> v1: https://lore.kernel.org/lkml/20200603233203.1695403-1-keescook@chromium.org
>
> Using uninitialized_var() is dangerous as it papers over real bugs[1]
> (or can in the future), and suppresses unrelated compiler warnings
> (e.g. "unused variable"). If the compiler thinks it is uninitialized,
> either simply initialize the variable or make compiler changes.
>
> As recommended[2] by[3] Linus[4], remove the macro.
>
> Most of the 300 uses don't cause any warnings on gcc 9.3.0, so they're in
> a single treewide commit in this series. A few others needed to actually
> get cleaned up, and I broke those out into individual patches.
>
> The tree is:
> https://git.kernel.org/pub/scm/linux/kernel/git/kees/linux.git/log/?h=kspp/uninit/macro
>
> -Kees
>
Hi Kees,
thanks for doing a v2 of your patchset.
As I saw Jason Yan providing some "uninitialized_var() macro" patches
to the MLs I pointen him to your tree "v1".
BTW, I have tested your "v1" against Linux v5.7 (see [1]) - just
yesterday with Linux v5.7.5-rc1.
Is it possible to have a v2 of this patchset on top od Linux v5.7 - if
you do not mind.
Thanks.
Best regards,
- Sedat -
[1] https://git.kernel.org/pub/scm/linux/kernel/git/kees/linux.git/log/?h=kspp/uninit/v5.7/macro
> [1] https://lore.kernel.org/lkml/20200603174714.192027-1-glider@google.com/
> [2] https://lore.kernel.org/lkml/CA+55aFw+Vbj0i=1TGqCR5vQkCzWJ0QxK6CernOU6eedsudAixw@mail.gmail.com/
> [3] https://lore.kernel.org/lkml/CA+55aFwgbgqhbp1fkxvRKEpzyR5J8n1vKT1VZdz9knmPuXhOeg@mail.gmail.com/
> [4] https://lore.kernel.org/lkml/CA+55aFz2500WfbKXAx8s67wrm9=yVJu65TpLgN_ybYNv0VEOKA@mail.gmail.com/
>
> Jason Yan (1):
> f2fs: Eliminate usage of uninitialized_var() macro
>
> Kees Cook (15):
> docs: deprecated.rst: Add uninitialized_var()
> x86/mm/numa: Remove uninitialized_var() usage
> drbd: Remove uninitialized_var() usage
> b43: Remove uninitialized_var() usage
> rtlwifi: rtl8192cu: Remove uninitialized_var() usage
> ide: Remove uninitialized_var() usage
> clk: st: Remove uninitialized_var() usage
> spi: davinci: Remove uninitialized_var() usage
> clk: spear: Remove uninitialized_var() usage
> KVM: PPC: Book3S PR: Remove uninitialized_var() usage
> media: sur40: Remove uninitialized_var() usage
> checkpatch: Remove awareness of uninitialized_var() macro
> treewide: Remove uninitialized_var() usage
> compiler: Remove uninitialized_var() macro
> mm/debug_vm_pgtable: Remove uninitialized_var() usage
>
> Documentation/process/deprecated.rst | 18 ++++++++++++++++++
> arch/arm/mach-sa1100/assabet.c | 2 +-
> arch/arm/mm/alignment.c | 2 +-
> arch/ia64/kernel/process.c | 2 +-
> arch/ia64/mm/discontig.c | 2 +-
> arch/ia64/mm/tlb.c | 2 +-
> arch/mips/lib/dump_tlb.c | 2 +-
> arch/mips/mm/init.c | 2 +-
> arch/mips/mm/tlb-r4k.c | 6 +++---
> arch/powerpc/kvm/book3s_64_mmu_radix.c | 2 +-
> arch/powerpc/kvm/book3s_pr.c | 3 ---
> arch/powerpc/kvm/powerpc.c | 2 +-
> arch/powerpc/platforms/52xx/mpc52xx_pic.c | 2 +-
> arch/s390/kernel/smp.c | 2 +-
> arch/x86/kernel/quirks.c | 10 +++++-----
> arch/x86/kvm/mmu/mmu.c | 2 +-
> arch/x86/kvm/mmu/paging_tmpl.h | 2 +-
> arch/x86/kvm/x86.c | 2 +-
> arch/x86/mm/numa.c | 18 +++++++++---------
> block/blk-merge.c | 2 +-
> drivers/acpi/acpi_pad.c | 2 +-
> drivers/ata/libata-scsi.c | 2 +-
> drivers/atm/zatm.c | 2 +-
> drivers/block/drbd/drbd_nl.c | 6 +++---
> drivers/block/drbd/drbd_state.c | 2 +-
> drivers/block/rbd.c | 2 +-
> drivers/clk/clk-gate.c | 2 +-
> drivers/clk/spear/clk-vco-pll.c | 2 +-
> drivers/clk/st/clkgen-fsyn.c | 1 -
> drivers/firewire/ohci.c | 14 +++++++-------
> drivers/gpu/drm/bridge/sil-sii8620.c | 2 +-
> drivers/gpu/drm/drm_edid.c | 2 +-
> drivers/gpu/drm/exynos/exynos_drm_dsi.c | 6 +++---
> drivers/gpu/drm/i915/display/intel_fbc.c | 2 +-
> drivers/gpu/drm/i915/gt/intel_lrc.c | 2 +-
> drivers/gpu/drm/i915/intel_uncore.c | 2 +-
> .../gpu/drm/rockchip/dw-mipi-dsi-rockchip.c | 4 ++--
> drivers/i2c/busses/i2c-rk3x.c | 2 +-
> drivers/ide/ide-acpi.c | 2 +-
> drivers/ide/ide-atapi.c | 2 +-
> drivers/ide/ide-io-std.c | 4 ++--
> drivers/ide/ide-io.c | 8 ++++----
> drivers/ide/ide-sysfs.c | 2 +-
> drivers/ide/ide-taskfile.c | 1 -
> drivers/ide/umc8672.c | 2 +-
> drivers/idle/intel_idle.c | 2 +-
> drivers/infiniband/core/uverbs_cmd.c | 4 ++--
> drivers/infiniband/hw/cxgb4/cm.c | 2 +-
> drivers/infiniband/hw/cxgb4/cq.c | 2 +-
> drivers/infiniband/hw/mlx4/qp.c | 6 +++---
> drivers/infiniband/hw/mlx5/cq.c | 6 +++---
> drivers/infiniband/hw/mlx5/devx.c | 2 +-
> drivers/infiniband/hw/mlx5/wr.c | 2 +-
> drivers/infiniband/hw/mthca/mthca_qp.c | 10 +++++-----
> drivers/infiniband/sw/siw/siw_qp_rx.c | 2 +-
> drivers/input/serio/serio_raw.c | 2 +-
> drivers/input/touchscreen/sur40.c | 4 +---
> drivers/iommu/intel/iommu.c | 2 +-
> drivers/md/dm-io.c | 2 +-
> drivers/md/dm-ioctl.c | 2 +-
> drivers/md/dm-snap-persistent.c | 2 +-
> drivers/md/dm-table.c | 2 +-
> drivers/md/dm-writecache.c | 2 +-
> drivers/md/raid5.c | 2 +-
> drivers/media/dvb-frontends/rtl2832.c | 2 +-
> drivers/media/tuners/qt1010.c | 4 ++--
> drivers/media/usb/gspca/vicam.c | 2 +-
> drivers/media/usb/uvc/uvc_video.c | 8 ++++----
> drivers/memstick/host/jmb38x_ms.c | 2 +-
> drivers/memstick/host/tifm_ms.c | 2 +-
> drivers/mmc/host/sdhci.c | 2 +-
> drivers/mtd/nand/raw/nand_ecc.c | 2 +-
> drivers/mtd/nand/raw/s3c2410.c | 2 +-
> drivers/mtd/parsers/afs.c | 4 ++--
> drivers/mtd/ubi/eba.c | 2 +-
> drivers/net/can/janz-ican3.c | 2 +-
> drivers/net/ethernet/broadcom/bnx2.c | 4 ++--
> .../ethernet/mellanox/mlx5/core/pagealloc.c | 4 ++--
> drivers/net/ethernet/neterion/s2io.c | 2 +-
> drivers/net/ethernet/qlogic/qla3xxx.c | 2 +-
> drivers/net/ethernet/sun/cassini.c | 2 +-
> drivers/net/ethernet/sun/niu.c | 6 +++---
> drivers/net/wan/z85230.c | 2 +-
> drivers/net/wireless/ath/ath10k/core.c | 2 +-
> drivers/net/wireless/ath/ath6kl/init.c | 2 +-
> drivers/net/wireless/ath/ath9k/init.c | 2 +-
> drivers/net/wireless/broadcom/b43/debugfs.c | 2 +-
> drivers/net/wireless/broadcom/b43/dma.c | 2 +-
> drivers/net/wireless/broadcom/b43/lo.c | 2 +-
> drivers/net/wireless/broadcom/b43/phy_n.c | 4 ++--
> drivers/net/wireless/broadcom/b43/xmit.c | 12 ++++++------
> .../net/wireless/broadcom/b43legacy/debugfs.c | 2 +-
> drivers/net/wireless/broadcom/b43legacy/main.c | 2 +-
> drivers/net/wireless/intel/iwlegacy/3945.c | 2 +-
> drivers/net/wireless/intel/iwlegacy/4965-mac.c | 2 +-
> .../wireless/realtek/rtlwifi/rtl8192cu/hw.c | 8 ++++----
> drivers/pci/pcie/aer.c | 2 +-
> drivers/platform/x86/hdaps.c | 4 ++--
> drivers/scsi/dc395x.c | 2 +-
> drivers/scsi/pm8001/pm8001_hwi.c | 2 +-
> drivers/scsi/pm8001/pm80xx_hwi.c | 2 +-
> drivers/spi/spi-davinci.c | 1 -
> drivers/ssb/driver_chipcommon.c | 4 ++--
> drivers/tty/cyclades.c | 2 +-
> drivers/tty/isicom.c | 2 +-
> drivers/usb/musb/cppi_dma.c | 2 +-
> drivers/usb/storage/sddr55.c | 4 ++--
> drivers/vhost/net.c | 6 +++---
> drivers/video/fbdev/matrox/matroxfb_maven.c | 6 +++---
> drivers/video/fbdev/pm3fb.c | 6 +++---
> drivers/video/fbdev/riva/riva_hw.c | 3 +--
> drivers/virtio/virtio_ring.c | 6 +++---
> fs/afs/dir.c | 2 +-
> fs/afs/security.c | 2 +-
> fs/dlm/netlink.c | 2 +-
> fs/erofs/data.c | 4 ++--
> fs/erofs/zdata.c | 2 +-
> fs/f2fs/data.c | 4 +---
> fs/fat/dir.c | 2 +-
> fs/fuse/control.c | 4 ++--
> fs/fuse/cuse.c | 2 +-
> fs/fuse/file.c | 2 +-
> fs/gfs2/aops.c | 2 +-
> fs/gfs2/bmap.c | 2 +-
> fs/gfs2/lops.c | 2 +-
> fs/hfsplus/unicode.c | 2 +-
> fs/isofs/namei.c | 4 ++--
> fs/jffs2/erase.c | 2 +-
> fs/nfsd/nfsctl.c | 2 +-
> fs/ocfs2/alloc.c | 4 ++--
> fs/ocfs2/dir.c | 14 +++++++-------
> fs/ocfs2/extent_map.c | 4 ++--
> fs/ocfs2/namei.c | 2 +-
> fs/ocfs2/refcounttree.c | 2 +-
> fs/ocfs2/xattr.c | 2 +-
> fs/omfs/file.c | 2 +-
> fs/overlayfs/copy_up.c | 2 +-
> fs/ubifs/commit.c | 6 +++---
> fs/ubifs/dir.c | 2 +-
> fs/ubifs/file.c | 4 ++--
> fs/ubifs/journal.c | 4 ++--
> fs/ubifs/lpt.c | 2 +-
> fs/ubifs/tnc.c | 6 +++---
> fs/ubifs/tnc_misc.c | 4 ++--
> fs/udf/balloc.c | 2 +-
> fs/xfs/xfs_bmap_util.c | 2 +-
> include/linux/compiler-clang.h | 2 --
> include/linux/compiler-gcc.h | 6 ------
> include/linux/page-flags-layout.h | 4 +++-
> include/net/flow_offload.h | 2 +-
> kernel/async.c | 4 ++--
> kernel/audit.c | 2 +-
> kernel/debug/kdb/kdb_io.c | 2 +-
> kernel/dma/debug.c | 2 +-
> kernel/events/core.c | 2 +-
> kernel/events/uprobes.c | 2 +-
> kernel/exit.c | 2 +-
> kernel/futex.c | 14 +++++++-------
> kernel/locking/lockdep.c | 16 ++++++++--------
> kernel/trace/ring_buffer.c | 2 +-
> lib/radix-tree.c | 2 +-
> lib/test_lockup.c | 2 +-
> mm/debug_vm_pgtable.c | 2 +-
> mm/frontswap.c | 2 +-
> mm/ksm.c | 2 +-
> mm/memcontrol.c | 2 +-
> mm/memory.c | 2 +-
> mm/mempolicy.c | 4 ++--
> mm/page_alloc.c | 2 +-
> mm/percpu.c | 2 +-
> mm/slub.c | 4 ++--
> mm/swap.c | 4 ++--
> net/dccp/options.c | 2 +-
> net/ipv4/netfilter/nf_socket_ipv4.c | 6 +++---
> net/ipv6/ip6_flowlabel.c | 2 +-
> net/ipv6/netfilter/nf_socket_ipv6.c | 2 +-
> net/netfilter/nf_conntrack_ftp.c | 2 +-
> net/netfilter/nfnetlink_log.c | 2 +-
> net/netfilter/nfnetlink_queue.c | 4 ++--
> net/sched/cls_flow.c | 2 +-
> net/sched/sch_cake.c | 2 +-
> net/sched/sch_cbq.c | 2 +-
> net/sched/sch_fq_codel.c | 2 +-
> net/sched/sch_fq_pie.c | 2 +-
> net/sched/sch_hfsc.c | 2 +-
> net/sched/sch_htb.c | 2 +-
> net/sched/sch_sfq.c | 2 +-
> net/sunrpc/svcsock.c | 4 ++--
> net/sunrpc/xprtsock.c | 10 +++++-----
> net/tls/tls_sw.c | 2 +-
> scripts/checkpatch.pl | 16 +++++-----------
> sound/core/control_compat.c | 2 +-
> sound/isa/sb/sb16_csp.c | 2 +-
> sound/usb/endpoint.c | 2 +-
> tools/include/linux/compiler.h | 2 --
> tools/virtio/linux/kernel.h | 2 --
> 196 files changed, 321 insertions(+), 330 deletions(-)
>
> --
> 2.25.1
>
> --
> You received this message because you are subscribed to the Google Groups "Clang Built Linux" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to clang-built-linux+unsubscribe@googlegroups.com.
> To view this discussion on the web visit https://groups.google.com/d/msgid/clang-built-linux/20200620033007.1444705-1-keescook%40chromium.org.
^ permalink raw reply
* Re: [PATCH net] openvswitch: take into account de-fragmentation in execute_check_pkt_len
From: Pravin Shelar @ 2020-06-20 7:01 UTC (permalink / raw)
To: Lorenzo Bianconi
Cc: Linux Kernel Network Developers, David S. Miller, Numan Siddique,
Greg Rose, lorenzo.bianconi, ovs dev
In-Reply-To: <74266291a0aba929919f71ff3dbd1c36392bb4c4.1592567032.git.lorenzo@kernel.org>
On Fri, Jun 19, 2020 at 4:48 AM Lorenzo Bianconi <lorenzo@kernel.org> wrote:
>
> ovs connection tracking module performs de-fragmentation on incoming
> fragmented traffic. Take info account if traffic has been de-fragmented
> in execute_check_pkt_len action otherwise we will perform the wrong
> nested action considering the original packet size. This issue typically
> occurs if ovs-vswitchd adds a rule in the pipeline that requires connection
> tracking (e.g. OVN stateful ACLs) before execute_check_pkt_len action.
>
> Fixes: 4d5ec89fc8d14 ("net: openvswitch: Add a new action check_pkt_len")
> Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
> ---
> net/openvswitch/actions.c | 6 ++++--
> 1 file changed, 4 insertions(+), 2 deletions(-)
>
> diff --git a/net/openvswitch/actions.c b/net/openvswitch/actions.c
> index fc0efd8833c8..9f4dd64e53bb 100644
> --- a/net/openvswitch/actions.c
> +++ b/net/openvswitch/actions.c
> @@ -1169,9 +1169,10 @@ static int execute_check_pkt_len(struct datapath *dp, struct sk_buff *skb,
> struct sw_flow_key *key,
> const struct nlattr *attr, bool last)
> {
> + struct ovs_skb_cb *ovs_cb = OVS_CB(skb);
> const struct nlattr *actions, *cpl_arg;
> const struct check_pkt_len_arg *arg;
> - int rem = nla_len(attr);
> + int len, rem = nla_len(attr);
> bool clone_flow_key;
>
> /* The first netlink attribute in 'attr' is always
> @@ -1180,7 +1181,8 @@ static int execute_check_pkt_len(struct datapath *dp, struct sk_buff *skb,
> cpl_arg = nla_data(attr);
> arg = nla_data(cpl_arg);
>
> - if (skb->len <= arg->pkt_len) {
> + len = ovs_cb->mru ? ovs_cb->mru : skb->len;
> + if (len <= arg->pkt_len) {
We could also check for the segmented packet and use segment length
for this check.
^ permalink raw reply
* Re: Question on DSA switches, IGMP forwarding and switchdev
From: Daniel Mack @ 2020-06-20 6:02 UTC (permalink / raw)
To: Andrew Lunn, Jason Cobham
Cc: netdev@vger.kernel.org, Ido Schimmel, Jiri Pirko, Ivan Vecera,
Florian Fainelli
In-Reply-To: <20200619223606.GO279339@lunn.ch>
On 6/20/20 12:36 AM, Andrew Lunn wrote:
>> I've run into the same issue. To resolve it, In my case, in the same file, I've had to send all IGMP control traffic to the CPU:
>> skb->offload_fwd_mark = 1;
>> switch (ih->type) {
>> case IGMP_HOST_MEMBERSHIP_REPORT:
>> case IGMPV2_HOST_MEMBERSHIP_REPORT:
>> case IGMPV3_HOST_MEMBERSHIP_REPORT:
>> case IGMP_HOST_MEMBERSHIP_QUERY:
>> case IGMP_HOST_LEAVE_MESSAGE:
>> skb->offload_fwd_mark = 0;
>> break;
>> }
>>
>> I'd be interested if there is a better way.
>
> It might depend on the switch generation, but i think some switches
> indicate the sort of packet in the DSA header. For 6390, Octet 3 of
> the header, bits 3-5 contains a code.
>
> 0=BDPU
> 1=Frame2Reg
> 2=IGMP/MLD
> 3=Policy
> 4=ARP Mirror
> 5=Policy Mirror
>
> We can look at these bits and not set skb->offload_fwd_mark depending
> on its value.
>
> The 6352 family has the same bits. 6161 has a few less bits, but does
> have IGMP/MLD. I don't know about the 6085. Do you have the datasheet?
Sorry, I was mistaken in the model the board is using, it's a 6352.
So yes, we can read the code here, but I'm wondering which packet types
would then get this flag set, and which won't. Because in case of
IGMP/MLD, the packets are in fact forwarded, but the meaning of the flag
in skb is to prevent the skb from being forwarded further, which seems
wrong in all cases.
I'm thinking maybe the flag should never be set?
Thanks,
Daniel
^ permalink raw reply
* Re: [PATCH/RFC 1/5] dt-bindings: net: renesas,ravb: Document internal clock delay properties
From: Oleksij Rempel @ 2020-06-20 5:47 UTC (permalink / raw)
To: Geert Uytterhoeven, Sergei Shtylyov, David S . Miller,
Jakub Kicinski, Rob Herring
Cc: Andrew Lunn, Philippe Schenker, Florian Fainelli, Heiner Kallweit,
Kazuya Mizuguchi, Wolfram Sang, netdev, devicetree,
linux-renesas-soc
In-Reply-To: <20200619191554.24942-2-geert+renesas@glider.be>
Hi Geert,
Am 19.06.20 um 21:15 schrieb Geert Uytterhoeven:
> Some EtherAVB variants support internal clock delay configuration, which
> can add larger delays than the delays that are typically supported by
> the PHY (using an "rgmii-*id" PHY mode, and/or "[rt]xc-skew-ps"
> properties).
>
> Add properties for configuring the internal MAC delays.
> These properties are mandatory, even when specified as zero, to
> distinguish between old and new DTBs.
>
> Update the example accordingly.
>
> Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
> ---
> .../devicetree/bindings/net/renesas,ravb.txt | 29 ++++++++++---------
> 1 file changed, 16 insertions(+), 13 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/net/renesas,ravb.txt b/Documentation/devicetree/bindings/net/renesas,ravb.txt
> index 032b76f14f4fdb38..488ada78b6169b8e 100644
> --- a/Documentation/devicetree/bindings/net/renesas,ravb.txt
> +++ b/Documentation/devicetree/bindings/net/renesas,ravb.txt
> @@ -64,6 +64,18 @@ Optional properties:
> AVB_LINK signal.
> - renesas,ether-link-active-low: boolean, specify when the AVB_LINK signal is
> active-low instead of normal active-high.
> +- renesas,rxc-delay-ps: Internal RX clock delay.
may be it make sense to add a generic delay property for MACs and PHYs?
> + This property is mandatory and valid only on R-Car Gen3
> + and RZ/G2 SoCs.
> + Valid values are 0 and 1800.
> + A non-zero value is allowed only if phy-mode = "rgmii".
> + Zero is not supported on R-Car D3.
> +- renesas,txc-delay-ps: Internal TX clock delay.
> + This property is mandatory and valid only on R-Car H3,
> + M3-W, M3-W+, M3-N, V3M, and V3H, and RZ/G2M and RZ/G2N.
> + Valid values are 0 and 2000.
In the driver i didn't found sanity check for valid values.
> + A non-zero value is allowed only if phy-mode = "rgmii".
> + Zero is not supported on R-Car V3H.> Example:
>
> @@ -105,8 +117,10 @@ Example:
> "ch24";
> clocks = <&cpg CPG_MOD 812>;
> power-domains = <&cpg>;
> - phy-mode = "rgmii-id";
> + phy-mode = "rgmii";
> phy-handle = <&phy0>;
> + renesas,rxc-delay-ps = <0>;
> + renesas,txc-delay-ps = <2000>;
>
> pinctrl-0 = <ðer_pins>;
> pinctrl-names = "default";
> @@ -115,18 +129,7 @@ Example:
> #size-cells = <0>;
>
> phy0: ethernet-phy@0 {
> - rxc-skew-ps = <900>;
> - rxdv-skew-ps = <0>;
> - rxd0-skew-ps = <0>;
> - rxd1-skew-ps = <0>;
> - rxd2-skew-ps = <0>;
> - rxd3-skew-ps = <0>;
> - txc-skew-ps = <900>;
> - txen-skew-ps = <0>;
> - txd0-skew-ps = <0>;
> - txd1-skew-ps = <0>;
> - txd2-skew-ps = <0>;
> - txd3-skew-ps = <0>;
> + rxc-skew-ps = <1500>;
I'm curios, how this numbers ware taken?
Old configurations was:
TX delay:
(txd*-skew-ps = 0) == -420ns
(txc-skew-ps = 900) == 0ns
resulting delays 0.420ns
RX delay:
(rxd*-skew-ps = 0) == -420ns
(rxc-skew-ps = 900) == 0ns
internal delay 1.2 + 420ns will be 1.62ns
I was not able to find actual delay values provided by the MAC. But from your patches it looks like 2ns.
So, end result will be:
TXID = 2.4ns
RXID = 3.62ns
Both values seems to be a bit out of spec. New values are:
TXID = PHY 0ns + MAC 2.0ns
RXID =
(rxd*-skew-ps = no change) == 0ns
(rxc-skew-ps = 1500) == +600ns
internal delay 1.2 + 600ns = 1.8ns
From the PHY point of view, it is RGMII_RXID mode. Are you sure, RGMII_ID is not working for you?
Till now the numbers was not looking as a fine tuning.
I assume, it is better to use proper phy-mode instead of skew-ps values. I feel like no one had time
to understand real configured values in this PHY.
> reg = <0>;
> interrupt-parent = <&gpio2>;
> interrupts = <11 IRQ_TYPE_LEVEL_LOW>;
>
--
Regards,
Oleksij
^ permalink raw reply
* Re: Question on DSA switches, IGMP forwarding and switchdev
From: Daniel Mack @ 2020-06-20 5:32 UTC (permalink / raw)
To: Andrew Lunn
Cc: netdev, Ido Schimmel, Jiri Pirko, Ivan Vecera, Florian Fainelli
In-Reply-To: <20200619215817.GN279339@lunn.ch>
Hi Andrew,
Thanks a lot for the quick reply!
On 6/19/20 11:58 PM, Andrew Lunn wrote:
> On Fri, Jun 19, 2020 at 11:31:04PM +0200, Daniel Mack wrote:
>> When an IGMP query enters the switch, it is redirected to the CPU port
>> as all 'external' ports are configured for IGMP/MLP snooping by the
>> driver. The issue that I'm seeing is that the Linux bridge does not
>> forward the IGMP frames to any other port, no matter whether the bridge
>> is in snooping mode or not. This needs to happen however, otherwise the
>> stations will not see IGMP queries, and unsolicited membership reports
>> are not being transferred either.
>
> I think all the testing i've done in this area i've had the bridge
> acting as the IGMP queirer. Hence it has replied to the query, rather
> than forward it out other ports.
Yes, if the bridge is itself generating the queries, this works.
> To get this far, has the bridge determined it is not the elected
> querier? I guess it must of done. Otherwise it would not be
> forwarding it.
No, the querier is connected to one of the switch ports in a larger
topology. But the bridge must still forward such frames, otherwise IGMP
queries won't reach the senders, and membership reports won't reach the
querier.
> The problem here is:
>
> https://elixir.bootlin.com/linux/v5.8-rc1/source/net/dsa/tag_edsa.c#L159
Ah, right!
> Setting offload_fwd_mark means the switch has forwarded the frame as
> needed to other ports of the switch. If the frame is an IGMP query
> frame, and the bridge is not the elected quierer, i guess we need to
> set this false? Or we need an FDB in the switch to forward it. What
> group address is being used?
If such a frame is ingressing, the software bridge must be able to
forward it again. So I suppose we need to set the forward flag to false
here, yes.
Thanks,
Daniel
^ permalink raw reply
* [PATCH v2 04/16] b43: Remove uninitialized_var() usage
From: Kees Cook @ 2020-06-20 3:29 UTC (permalink / raw)
To: linux-kernel
Cc: Kees Cook, Linus Torvalds, Miguel Ojeda, Alexander Potapenko,
Joe Perches, Andy Whitcroft, x86, drbd-dev, linux-block, b43-dev,
netdev, linux-doc, linux-wireless, linux-ide, linux-clk,
linux-spi, linux-mm, clang-built-linux
In-Reply-To: <20200620033007.1444705-1-keescook@chromium.org>
Using uninitialized_var() is dangerous as it papers over real bugs[1]
(or can in the future), and suppresses unrelated compiler warnings (e.g.
"unused variable"). If the compiler thinks it is uninitialized, either
simply initialize the variable or make compiler changes. As a precursor
to removing[2] this[3] macro[4], just initialize this variable to NULL.
No later NULL deref is possible due to the early returns outside of the
(phy->rev >= 7 && phy->rev < 19) case, which explicitly tests for NULL.
[1] https://lore.kernel.org/lkml/20200603174714.192027-1-glider@google.com/
[2] https://lore.kernel.org/lkml/CA+55aFw+Vbj0i=1TGqCR5vQkCzWJ0QxK6CernOU6eedsudAixw@mail.gmail.com/
[3] https://lore.kernel.org/lkml/CA+55aFwgbgqhbp1fkxvRKEpzyR5J8n1vKT1VZdz9knmPuXhOeg@mail.gmail.com/
[4] https://lore.kernel.org/lkml/CA+55aFz2500WfbKXAx8s67wrm9=yVJu65TpLgN_ybYNv0VEOKA@mail.gmail.com/
Fixes: 58619b14d106 ("b43: move under broadcom vendor directory")
Signed-off-by: Kees Cook <keescook@chromium.org>
---
drivers/net/wireless/broadcom/b43/phy_n.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/wireless/broadcom/b43/phy_n.c b/drivers/net/wireless/broadcom/b43/phy_n.c
index c33b4235839d..46db91846007 100644
--- a/drivers/net/wireless/broadcom/b43/phy_n.c
+++ b/drivers/net/wireless/broadcom/b43/phy_n.c
@@ -4222,7 +4222,7 @@ static void b43_nphy_tx_gain_table_upload(struct b43_wldev *dev)
u32 rfpwr_offset;
u8 pga_gain, pad_gain;
int i;
- const s16 *uninitialized_var(rf_pwr_offset_table);
+ const s16 *rf_pwr_offset_table = NULL;
table = b43_nphy_get_tx_gain_table(dev);
if (!table)
--
2.25.1
^ permalink raw reply related
* [PATCH v2 03/16] drbd: Remove uninitialized_var() usage
From: Kees Cook @ 2020-06-20 3:29 UTC (permalink / raw)
To: linux-kernel
Cc: Kees Cook, Nick Desaulniers, Linus Torvalds, Miguel Ojeda,
Alexander Potapenko, Joe Perches, Andy Whitcroft, x86, drbd-dev,
linux-block, b43-dev, netdev, linux-doc, linux-wireless,
linux-ide, linux-clk, linux-spi, linux-mm, clang-built-linux
In-Reply-To: <20200620033007.1444705-1-keescook@chromium.org>
Using uninitialized_var() is dangerous as it papers over real bugs[1]
(or can in the future), and suppresses unrelated compiler warnings (e.g.
"unused variable"). If the compiler thinks it is uninitialized, either
simply initialize the variable or make compiler changes. As a precursor
to removing[2] this[3] macro[4], just initialize this variable to NULL.
[1] https://lore.kernel.org/lkml/20200603174714.192027-1-glider@google.com/
[2] https://lore.kernel.org/lkml/CA+55aFw+Vbj0i=1TGqCR5vQkCzWJ0QxK6CernOU6eedsudAixw@mail.gmail.com/
[3] https://lore.kernel.org/lkml/CA+55aFwgbgqhbp1fkxvRKEpzyR5J8n1vKT1VZdz9knmPuXhOeg@mail.gmail.com/
[4] https://lore.kernel.org/lkml/CA+55aFz2500WfbKXAx8s67wrm9=yVJu65TpLgN_ybYNv0VEOKA@mail.gmail.com/
Fixes: a29728463b25 ("drbd: Backport the "events2" command")
Reviewed-by: Nick Desaulniers <ndesaulniers@google.com>
Signed-off-by: Kees Cook <keescook@chromium.org>
---
drivers/block/drbd/drbd_state.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/block/drbd/drbd_state.c b/drivers/block/drbd/drbd_state.c
index eeaa3b49b264..0067d328f0b5 100644
--- a/drivers/block/drbd/drbd_state.c
+++ b/drivers/block/drbd/drbd_state.c
@@ -1604,7 +1604,7 @@ static void broadcast_state_change(struct drbd_state_change *state_change)
unsigned int n_device, n_connection, n_peer_device, n_peer_devices;
void (*last_func)(struct sk_buff *, unsigned int, void *,
enum drbd_notification_type) = NULL;
- void *uninitialized_var(last_arg);
+ void *last_arg = NULL;
#define HAS_CHANGED(state) ((state)[OLD] != (state)[NEW])
#define FINAL_STATE_CHANGE(type) \
--
2.25.1
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox