Skip to content

Commit

Permalink
Merge branch 'net-hns3-some-code-optimizations-bugfixes-features'
Browse files Browse the repository at this point in the history
Huazhong Tan says:

====================
net: hns3: some code optimizations & bugfixes & features

This patch-set includes code optimizations, bugfixes and features for
the HNS3 ethernet controller driver.

[patch 01/12] adds support for reporting link change event.

[patch 02/12] adds handler for NCSI error.

[patch 03/12] fixes bug related to debugfs.

[patch 04/12] adds a code optimization for setting ring parameters.

[patch 05/12 - 09/12] adds some cleanups.

[patch 10/12 - 12/12] adds some patches related to reset issue.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Aug 1, 2019
2 parents 0ae9fce + 012fcb5 commit 9b59e39
Show file tree
Hide file tree
Showing 16 changed files with 397 additions and 153 deletions.
2 changes: 2 additions & 0 deletions drivers/net/ethernet/hisilicon/hns3/hclge_mbx.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ enum HCLGE_MBX_OPCODE {
HCLGE_MBX_GET_MEDIA_TYPE, /* (VF -> PF) get media type */

HCLGE_MBX_GET_VF_FLR_STATUS = 200, /* (M7 -> PF) get vf reset status */
HCLGE_MBX_PUSH_LINK_STATUS, /* (M7 -> PF) get port link status */
HCLGE_MBX_NCSI_ERROR, /* (M7 -> PF) receive a NCSI error */
};

/* below are per-VF mac-vlan subcodes */
Expand Down
22 changes: 10 additions & 12 deletions drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
Original file line number Diff line number Diff line change
Expand Up @@ -2909,24 +2909,22 @@ int hns3_clean_rx_ring(struct hns3_enet_ring *ring, int budget,
void (*rx_fn)(struct hns3_enet_ring *, struct sk_buff *))
{
#define RCB_NOF_ALLOC_RX_BUFF_ONCE 16
int recv_pkts, recv_bds, clean_count, err;
int unused_count = hns3_desc_unused(ring);
struct sk_buff *skb = ring->skb;
int num;
int recv_pkts = 0;
int recv_bds = 0;
int err, num;

num = readl_relaxed(ring->tqp->io_base + HNS3_RING_RX_RING_FBDNUM_REG);
rmb(); /* Make sure num taken effect before the other data is touched */

recv_pkts = 0, recv_bds = 0, clean_count = 0;
num -= unused_count;
unused_count -= ring->pending_buf;

while (recv_pkts < budget && recv_bds < num) {
/* Reuse or realloc buffers */
if (clean_count + unused_count >= RCB_NOF_ALLOC_RX_BUFF_ONCE) {
hns3_nic_alloc_rx_buffers(ring,
clean_count + unused_count);
clean_count = 0;
if (unused_count >= RCB_NOF_ALLOC_RX_BUFF_ONCE) {
hns3_nic_alloc_rx_buffers(ring, unused_count);
unused_count = hns3_desc_unused(ring) -
ring->pending_buf;
}
Expand All @@ -2940,15 +2938,15 @@ int hns3_clean_rx_ring(struct hns3_enet_ring *ring, int budget,
goto out;
} else if (unlikely(err)) { /* Do jump the err */
recv_bds += ring->pending_buf;
clean_count += ring->pending_buf;
unused_count += ring->pending_buf;
ring->skb = NULL;
ring->pending_buf = 0;
continue;
}

rx_fn(ring, skb);
recv_bds += ring->pending_buf;
clean_count += ring->pending_buf;
unused_count += ring->pending_buf;
ring->skb = NULL;
ring->pending_buf = 0;

Expand All @@ -2957,8 +2955,8 @@ int hns3_clean_rx_ring(struct hns3_enet_ring *ring, int budget,

out:
/* Make all data has been write before submit */
if (clean_count + unused_count > 0)
hns3_nic_alloc_rx_buffers(ring, clean_count + unused_count);
if (unused_count > 0)
hns3_nic_alloc_rx_buffers(ring, unused_count);

return recv_pkts;
}
Expand Down Expand Up @@ -3588,7 +3586,7 @@ static int hns3_alloc_ring_memory(struct hns3_enet_ring *ring)
return ret;
}

static void hns3_fini_ring(struct hns3_enet_ring *ring)
void hns3_fini_ring(struct hns3_enet_ring *ring)
{
hns3_free_desc(ring);
devm_kfree(ring_to_dev(ring), ring->desc_cb);
Expand Down
3 changes: 2 additions & 1 deletion drivers/net/ethernet/hisilicon/hns3/hns3_enet.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ enum hns3_nic_state {
#define HNS3_TX_TIMEOUT (5 * HZ)
#define HNS3_RING_NAME_LEN 16
#define HNS3_BUFFER_SIZE_2048 2048
#define HNS3_RING_MAX_PENDING 32768
#define HNS3_RING_MAX_PENDING 32760
#define HNS3_RING_MIN_PENDING 24
#define HNS3_RING_BD_MULTIPLE 8
/* max frame size of mac */
Expand Down Expand Up @@ -642,6 +642,7 @@ void hns3_clean_tx_ring(struct hns3_enet_ring *ring);
int hns3_init_all_ring(struct hns3_nic_priv *priv);
int hns3_uninit_all_ring(struct hns3_nic_priv *priv);
int hns3_nic_reset_all_ring(struct hnae3_handle *h);
void hns3_fini_ring(struct hns3_enet_ring *ring);
netdev_tx_t hns3_nic_net_xmit(struct sk_buff *skb, struct net_device *netdev);
bool hns3_is_phys_func(struct pci_dev *pdev);
int hns3_clean_rx_ring(
Expand Down
88 changes: 62 additions & 26 deletions drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c
Original file line number Diff line number Diff line change
Expand Up @@ -867,8 +867,8 @@ static int hns3_get_rxnfc(struct net_device *netdev,
}
}

static int hns3_change_all_ring_bd_num(struct hns3_nic_priv *priv,
u32 tx_desc_num, u32 rx_desc_num)
static void hns3_change_all_ring_bd_num(struct hns3_nic_priv *priv,
u32 tx_desc_num, u32 rx_desc_num)
{
struct hnae3_handle *h = priv->ae_handle;
int i;
Expand All @@ -881,21 +881,29 @@ static int hns3_change_all_ring_bd_num(struct hns3_nic_priv *priv,
priv->ring_data[i + h->kinfo.num_tqps].ring->desc_num =
rx_desc_num;
}

return hns3_init_all_ring(priv);
}

static int hns3_set_ringparam(struct net_device *ndev,
struct ethtool_ringparam *param)
static struct hns3_enet_ring *hns3_backup_ringparam(struct hns3_nic_priv *priv)
{
struct hns3_nic_priv *priv = netdev_priv(ndev);
struct hnae3_handle *h = priv->ae_handle;
bool if_running = netif_running(ndev);
u32 old_tx_desc_num, new_tx_desc_num;
u32 old_rx_desc_num, new_rx_desc_num;
int queue_num = h->kinfo.num_tqps;
int ret;
struct hnae3_handle *handle = priv->ae_handle;
struct hns3_enet_ring *tmp_rings;
int i;

tmp_rings = kcalloc(handle->kinfo.num_tqps * 2,
sizeof(struct hns3_enet_ring), GFP_KERNEL);
if (!tmp_rings)
return NULL;

for (i = 0; i < handle->kinfo.num_tqps * 2; i++)
memcpy(&tmp_rings[i], priv->ring_data[i].ring,
sizeof(struct hns3_enet_ring));

return tmp_rings;
}

static int hns3_check_ringparam(struct net_device *ndev,
struct ethtool_ringparam *param)
{
if (hns3_nic_resetting(ndev))
return -EBUSY;

Expand All @@ -911,6 +919,25 @@ static int hns3_set_ringparam(struct net_device *ndev,
return -EINVAL;
}

return 0;
}

static int hns3_set_ringparam(struct net_device *ndev,
struct ethtool_ringparam *param)
{
struct hns3_nic_priv *priv = netdev_priv(ndev);
struct hnae3_handle *h = priv->ae_handle;
struct hns3_enet_ring *tmp_rings;
bool if_running = netif_running(ndev);
u32 old_tx_desc_num, new_tx_desc_num;
u32 old_rx_desc_num, new_rx_desc_num;
u16 queue_num = h->kinfo.num_tqps;
int ret, i;

ret = hns3_check_ringparam(ndev, param);
if (ret)
return ret;

/* Hardware requires that its descriptors must be multiple of eight */
new_tx_desc_num = ALIGN(param->tx_pending, HNS3_RING_BD_MULTIPLE);
new_rx_desc_num = ALIGN(param->rx_pending, HNS3_RING_BD_MULTIPLE);
Expand All @@ -920,6 +947,13 @@ static int hns3_set_ringparam(struct net_device *ndev,
old_rx_desc_num == new_rx_desc_num)
return 0;

tmp_rings = hns3_backup_ringparam(priv);
if (!tmp_rings) {
netdev_err(ndev,
"backup ring param failed by allocating memory fail\n");
return -ENOMEM;
}

netdev_info(ndev,
"Changing Tx/Rx ring depth from %d/%d to %d/%d\n",
old_tx_desc_num, old_rx_desc_num,
Expand All @@ -928,22 +962,24 @@ static int hns3_set_ringparam(struct net_device *ndev,
if (if_running)
ndev->netdev_ops->ndo_stop(ndev);

ret = hns3_uninit_all_ring(priv);
if (ret)
return ret;

ret = hns3_change_all_ring_bd_num(priv, new_tx_desc_num,
new_rx_desc_num);
hns3_change_all_ring_bd_num(priv, new_tx_desc_num, new_rx_desc_num);
ret = hns3_init_all_ring(priv);
if (ret) {
ret = hns3_change_all_ring_bd_num(priv, old_tx_desc_num,
old_rx_desc_num);
if (ret) {
netdev_err(ndev,
"Revert to old bd num fail, ret=%d.\n", ret);
return ret;
}
netdev_err(ndev, "Change bd num fail, revert to old value(%d)\n",
ret);

hns3_change_all_ring_bd_num(priv, old_tx_desc_num,
old_rx_desc_num);
for (i = 0; i < h->kinfo.num_tqps * 2; i++)
memcpy(priv->ring_data[i].ring, &tmp_rings[i],
sizeof(struct hns3_enet_ring));
} else {
for (i = 0; i < h->kinfo.num_tqps * 2; i++)
hns3_fini_ring(&tmp_rings[i]);
}

kfree(tmp_rings);

if (if_running)
ret = ndev->netdev_ops->ndo_open(ndev);

Expand Down
33 changes: 31 additions & 2 deletions drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c
Original file line number Diff line number Diff line change
Expand Up @@ -103,14 +103,17 @@ static void hclge_cmd_config_regs(struct hclge_cmq_ring *ring)
dma_addr_t dma = ring->desc_dma_addr;
struct hclge_dev *hdev = ring->dev;
struct hclge_hw *hw = &hdev->hw;
u32 reg_val;

if (ring->ring_type == HCLGE_TYPE_CSQ) {
hclge_write_dev(hw, HCLGE_NIC_CSQ_BASEADDR_L_REG,
lower_32_bits(dma));
hclge_write_dev(hw, HCLGE_NIC_CSQ_BASEADDR_H_REG,
upper_32_bits(dma));
hclge_write_dev(hw, HCLGE_NIC_CSQ_DEPTH_REG,
ring->desc_num >> HCLGE_NIC_CMQ_DESC_NUM_S);
reg_val = hclge_read_dev(hw, HCLGE_NIC_CSQ_DEPTH_REG);
reg_val &= HCLGE_NIC_SW_RST_RDY;
reg_val |= ring->desc_num >> HCLGE_NIC_CMQ_DESC_NUM_S;
hclge_write_dev(hw, HCLGE_NIC_CSQ_DEPTH_REG, reg_val);
hclge_write_dev(hw, HCLGE_NIC_CSQ_HEAD_REG, 0);
hclge_write_dev(hw, HCLGE_NIC_CSQ_TAIL_REG, 0);
} else {
Expand Down Expand Up @@ -383,6 +386,23 @@ int hclge_cmd_queue_init(struct hclge_dev *hdev)
return ret;
}

static int hclge_firmware_compat_config(struct hclge_dev *hdev)
{
struct hclge_firmware_compat_cmd *req;
struct hclge_desc desc;
u32 compat = 0;

hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_M7_COMPAT_CFG, false);

req = (struct hclge_firmware_compat_cmd *)desc.data;

hnae3_set_bit(compat, HCLGE_LINK_EVENT_REPORT_EN_B, 1);
hnae3_set_bit(compat, HCLGE_NCSI_ERROR_REPORT_EN_B, 1);
req->compat = cpu_to_le32(compat);

return hclge_cmd_send(&hdev->hw, &desc, 1);
}

int hclge_cmd_init(struct hclge_dev *hdev)
{
u32 version;
Expand Down Expand Up @@ -429,6 +449,15 @@ int hclge_cmd_init(struct hclge_dev *hdev)
hnae3_get_field(version, HNAE3_FW_VERSION_BYTE0_MASK,
HNAE3_FW_VERSION_BYTE0_SHIFT));

/* ask the firmware to enable some features, driver can work without
* it.
*/
ret = hclge_firmware_compat_config(hdev);
if (ret)
dev_warn(&hdev->pdev->dev,
"Firmware compatible features not enabled(%d).\n",
ret);

return 0;

err_cmd_init:
Expand Down
25 changes: 22 additions & 3 deletions drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ enum hclge_opcode_type {
HCLGE_OPC_QUERY_PF_RSRC = 0x0023,
HCLGE_OPC_QUERY_VF_RSRC = 0x0024,
HCLGE_OPC_GET_CFG_PARAM = 0x0025,
HCLGE_OPC_PF_RST_DONE = 0x0026,

HCLGE_OPC_STATS_64_BIT = 0x0030,
HCLGE_OPC_STATS_32_BIT = 0x0031,
Expand Down Expand Up @@ -257,6 +258,7 @@ enum hclge_opcode_type {
/* M7 stats command */
HCLGE_OPC_M7_STATS_BD = 0x7012,
HCLGE_OPC_M7_STATS_INFO = 0x7013,
HCLGE_OPC_M7_COMPAT_CFG = 0x701A,

/* SFP command */
HCLGE_OPC_GET_SFP_INFO = 0x7104,
Expand Down Expand Up @@ -827,7 +829,7 @@ struct hclge_mac_ethertype_idx_rd_cmd {
u8 flags;
u8 resp_code;
__le16 vlan_tag;
u8 mac_add[6];
u8 mac_addr[6];
__le16 index;
__le16 ethter_type;
__le16 egress_port;
Expand Down Expand Up @@ -877,6 +879,13 @@ struct hclge_reset_cmd {
u8 rsv[22];
};

#define HCLGE_PF_RESET_DONE_BIT BIT(0)

struct hclge_pf_rst_done_cmd {
u8 pf_rst_done;
u8 rsv[23];
};

#define HCLGE_CMD_SERDES_SERIAL_INNER_LOOP_B BIT(0)
#define HCLGE_CMD_SERDES_PARALLEL_INNER_LOOP_B BIT(2)
#define HCLGE_CMD_SERDES_DONE_B BIT(0)
Expand Down Expand Up @@ -906,8 +915,11 @@ struct hclge_serdes_lb_cmd {
#define HCLGE_NIC_CRQ_DEPTH_REG 0x27020
#define HCLGE_NIC_CRQ_TAIL_REG 0x27024
#define HCLGE_NIC_CRQ_HEAD_REG 0x27028
#define HCLGE_NIC_CMQ_EN_B 16
#define HCLGE_NIC_CMQ_ENABLE BIT(HCLGE_NIC_CMQ_EN_B)

/* this bit indicates that the driver is ready for hardware reset */
#define HCLGE_NIC_SW_RST_RDY_B 16
#define HCLGE_NIC_SW_RST_RDY BIT(HCLGE_NIC_SW_RST_RDY_B)

#define HCLGE_NIC_CMQ_DESC_NUM 1024
#define HCLGE_NIC_CMQ_DESC_NUM_S 3

Expand Down Expand Up @@ -1009,6 +1021,13 @@ struct hclge_query_ppu_pf_other_int_dfx_cmd {
u8 rsv[4];
};

#define HCLGE_LINK_EVENT_REPORT_EN_B 0
#define HCLGE_NCSI_ERROR_REPORT_EN_B 1
struct hclge_firmware_compat_cmd {
__le32 compat;
u8 rsv[20];
};

int hclge_cmd_init(struct hclge_dev *hdev);
static inline void hclge_write_reg(void __iomem *base, u32 reg, u32 value)
{
Expand Down
Loading

0 comments on commit 9b59e39

Please sign in to comment.