Skip to content

Commit 40735e7

Browse files
Jijie ShaoPaolo Abeni
authored andcommitted
net: hibmcge: Implement .ndo_start_xmit function
Implement .ndo_start_xmit function to fill the information of the packet to be transmitted into the tx descriptor, and then the hardware will transmit the packet using the information in the tx descriptor. In addition, we also implemented the tx_handler function to enable the tx descriptor to be reused, and .ndo_tx_timeout function to print some information when the hardware is busy. Signed-off-by: Jijie Shao <[email protected]> Signed-off-by: Paolo Abeni <[email protected]>
1 parent ff4edac commit 40735e7

File tree

8 files changed

+455
-3
lines changed

8 files changed

+455
-3
lines changed

drivers/net/ethernet/hisilicon/hibmcge/hbg_common.h

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,61 @@
1313
#define HBG_RX_SKIP1 0x00
1414
#define HBG_RX_SKIP2 0x01
1515
#define HBG_VECTOR_NUM 4
16+
#define HBG_PCU_CACHE_LINE_SIZE 32
17+
#define HBG_TX_TIMEOUT_BUF_LEN 1024
18+
19+
enum hbg_dir {
20+
HBG_DIR_TX = 1 << 0,
21+
HBG_DIR_RX = 1 << 1,
22+
HBG_DIR_TX_RX = HBG_DIR_TX | HBG_DIR_RX,
23+
};
24+
25+
enum hbg_tx_state {
26+
HBG_TX_STATE_COMPLETE = 0, /* clear state, must fix to 0 */
27+
HBG_TX_STATE_START,
28+
};
1629

1730
enum hbg_nic_state {
1831
HBG_NIC_STATE_EVENT_HANDLING = 0,
1932
};
2033

34+
struct hbg_buffer {
35+
u32 state;
36+
dma_addr_t state_dma;
37+
38+
struct sk_buff *skb;
39+
dma_addr_t skb_dma;
40+
u32 skb_len;
41+
42+
enum hbg_dir dir;
43+
struct hbg_ring *ring;
44+
struct hbg_priv *priv;
45+
};
46+
47+
struct hbg_ring {
48+
struct hbg_buffer *queue;
49+
dma_addr_t queue_dma;
50+
51+
union {
52+
u32 head;
53+
u32 ntc;
54+
};
55+
union {
56+
u32 tail;
57+
u32 ntu;
58+
};
59+
u32 len;
60+
61+
enum hbg_dir dir;
62+
struct hbg_priv *priv;
63+
struct napi_struct napi;
64+
char *tout_log_buf; /* tx timeout log buffer */
65+
};
66+
2167
enum hbg_hw_event_type {
2268
HBG_HW_EVENT_NONE = 0,
2369
HBG_HW_EVENT_INIT, /* driver is loading */
70+
HBG_HW_EVENT_RESET,
2471
};
2572

2673
struct hbg_dev_specs {
@@ -73,6 +120,7 @@ struct hbg_priv {
73120
unsigned long state;
74121
struct hbg_mac mac;
75122
struct hbg_vector vectors;
123+
struct hbg_ring tx_ring;
76124
};
77125

78126
#endif

drivers/net/ethernet/hisilicon/hibmcge/hbg_hw.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ static int hbg_hw_dev_specs_init(struct hbg_priv *priv)
7373
if (!is_valid_ether_addr((u8 *)specs->mac_addr.sa_data))
7474
return -EADDRNOTAVAIL;
7575

76+
specs->max_frame_len = HBG_PCU_CACHE_LINE_SIZE + specs->max_mtu;
7677
return 0;
7778
}
7879

@@ -171,6 +172,23 @@ void hbg_hw_mac_enable(struct hbg_priv *priv, u32 enable)
171172
HBG_REG_PORT_ENABLE_RX_B, enable);
172173
}
173174

175+
u32 hbg_hw_get_fifo_used_num(struct hbg_priv *priv, enum hbg_dir dir)
176+
{
177+
if (dir & HBG_DIR_TX)
178+
return hbg_reg_read_field(priv, HBG_REG_CF_CFF_DATA_NUM_ADDR,
179+
HBG_REG_CF_CFF_DATA_NUM_ADDR_TX_M);
180+
181+
return 0;
182+
}
183+
184+
void hbg_hw_set_tx_desc(struct hbg_priv *priv, struct hbg_tx_desc *tx_desc)
185+
{
186+
hbg_reg_write(priv, HBG_REG_TX_CFF_ADDR_0_ADDR, tx_desc->word0);
187+
hbg_reg_write(priv, HBG_REG_TX_CFF_ADDR_1_ADDR, tx_desc->word1);
188+
hbg_reg_write(priv, HBG_REG_TX_CFF_ADDR_2_ADDR, tx_desc->word2);
189+
hbg_reg_write(priv, HBG_REG_TX_CFF_ADDR_3_ADDR, tx_desc->word3);
190+
}
191+
174192
void hbg_hw_adjust_link(struct hbg_priv *priv, u32 speed, u32 duplex)
175193
{
176194
hbg_reg_write_field(priv, HBG_REG_PORT_MODE_ADDR,

drivers/net/ethernet/hisilicon/hibmcge/hbg_hw.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,5 +52,7 @@ void hbg_hw_irq_enable(struct hbg_priv *priv, u32 mask, bool enable);
5252
void hbg_hw_set_mtu(struct hbg_priv *priv, u16 mtu);
5353
void hbg_hw_mac_enable(struct hbg_priv *priv, u32 enable);
5454
void hbg_hw_set_uc_addr(struct hbg_priv *priv, u64 mac_addr);
55+
u32 hbg_hw_get_fifo_used_num(struct hbg_priv *priv, enum hbg_dir dir);
56+
void hbg_hw_set_tx_desc(struct hbg_priv *priv, struct hbg_tx_desc *tx_desc);
5557

5658
#endif

drivers/net/ethernet/hisilicon/hibmcge/hbg_irq.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,20 @@ static void hbg_irq_handle_err(struct hbg_priv *priv,
1313
"receive error interrupt: %s\n", irq_info->name);
1414
}
1515

16+
static void hbg_irq_handle_tx(struct hbg_priv *priv,
17+
struct hbg_irq_info *irq_info)
18+
{
19+
napi_schedule(&priv->tx_ring.napi);
20+
}
21+
1622
#define HBG_TXRX_IRQ_I(name, handle) \
1723
{#name, HBG_INT_MSK_##name##_B, false, false, 0, handle}
1824
#define HBG_ERR_IRQ_I(name, need_print) \
1925
{#name, HBG_INT_MSK_##name##_B, true, need_print, 0, hbg_irq_handle_err}
2026

2127
static struct hbg_irq_info hbg_irqs[] = {
2228
HBG_TXRX_IRQ_I(RX, NULL),
23-
HBG_TXRX_IRQ_I(TX, NULL),
29+
HBG_TXRX_IRQ_I(TX, hbg_irq_handle_tx),
2430
HBG_ERR_IRQ_I(MAC_MII_FIFO_ERR, true),
2531
HBG_ERR_IRQ_I(MAC_PCS_RX_FIFO_ERR, true),
2632
HBG_ERR_IRQ_I(MAC_PCS_TX_FIFO_ERR, true),

drivers/net/ethernet/hisilicon/hibmcge/hbg_main.c

Lines changed: 52 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@
99
#include "hbg_hw.h"
1010
#include "hbg_irq.h"
1111
#include "hbg_mdio.h"
12+
#include "hbg_txrx.h"
13+
14+
static void hbg_change_mtu(struct hbg_priv *priv, int new_mtu);
1215

1316
static void hbg_all_irq_enable(struct hbg_priv *priv, bool enabled)
1417
{
@@ -24,6 +27,11 @@ static void hbg_all_irq_enable(struct hbg_priv *priv, bool enabled)
2427
static int hbg_net_open(struct net_device *netdev)
2528
{
2629
struct hbg_priv *priv = netdev_priv(netdev);
30+
int ret;
31+
32+
ret = hbg_txrx_init(priv);
33+
if (ret)
34+
return ret;
2735

2836
hbg_all_irq_enable(priv, true);
2937
hbg_hw_mac_enable(priv, HBG_STATUS_ENABLE);
@@ -33,6 +41,26 @@ static int hbg_net_open(struct net_device *netdev)
3341
return 0;
3442
}
3543

44+
/* This function only can be called after hbg_txrx_uninit() */
45+
static int hbg_hw_txrx_clear(struct hbg_priv *priv)
46+
{
47+
int ret;
48+
49+
/* After ring buffers have been released,
50+
* do a reset to release hw fifo rx ring buffer
51+
*/
52+
ret = hbg_hw_event_notify(priv, HBG_HW_EVENT_RESET);
53+
if (ret)
54+
return ret;
55+
56+
/* After reset, regs need to be reconfigured */
57+
hbg_hw_init(priv);
58+
hbg_hw_set_uc_addr(priv, ether_addr_to_u64(priv->netdev->dev_addr));
59+
hbg_change_mtu(priv, priv->netdev->mtu);
60+
61+
return 0;
62+
}
63+
3664
static int hbg_net_stop(struct net_device *netdev)
3765
{
3866
struct hbg_priv *priv = netdev_priv(netdev);
@@ -41,8 +69,8 @@ static int hbg_net_stop(struct net_device *netdev)
4169
netif_stop_queue(netdev);
4270
hbg_hw_mac_enable(priv, HBG_STATUS_DISABLE);
4371
hbg_all_irq_enable(priv, false);
44-
45-
return 0;
72+
hbg_txrx_uninit(priv);
73+
return hbg_hw_txrx_clear(priv);
4674
}
4775

4876
static int hbg_net_set_mac_address(struct net_device *netdev, void *addr)
@@ -86,12 +114,33 @@ static int hbg_net_change_mtu(struct net_device *netdev, int new_mtu)
86114
return 0;
87115
}
88116

117+
static void hbg_net_tx_timeout(struct net_device *netdev, unsigned int txqueue)
118+
{
119+
struct hbg_priv *priv = netdev_priv(netdev);
120+
struct hbg_ring *ring = &priv->tx_ring;
121+
char *buf = ring->tout_log_buf;
122+
u32 pos = 0;
123+
124+
pos += scnprintf(buf + pos, HBG_TX_TIMEOUT_BUF_LEN - pos,
125+
"ring used num: %u, fifo used num: %u\n",
126+
hbg_get_queue_used_num(ring),
127+
hbg_hw_get_fifo_used_num(priv, HBG_DIR_TX));
128+
pos += scnprintf(buf + pos, HBG_TX_TIMEOUT_BUF_LEN - pos,
129+
"ntc: %u, ntu: %u, irq enabled: %u\n",
130+
ring->ntc, ring->ntu,
131+
hbg_hw_irq_is_enabled(priv, HBG_INT_MSK_TX_B));
132+
133+
netdev_info(netdev, "%s", buf);
134+
}
135+
89136
static const struct net_device_ops hbg_netdev_ops = {
90137
.ndo_open = hbg_net_open,
91138
.ndo_stop = hbg_net_stop,
139+
.ndo_start_xmit = hbg_net_start_xmit,
92140
.ndo_validate_addr = eth_validate_addr,
93141
.ndo_set_mac_address = hbg_net_set_mac_address,
94142
.ndo_change_mtu = hbg_net_change_mtu,
143+
.ndo_tx_timeout = hbg_net_tx_timeout,
95144
};
96145

97146
static int hbg_init(struct hbg_priv *priv)
@@ -170,6 +219,7 @@ static int hbg_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
170219
netdev->max_mtu = priv->dev_specs.max_mtu;
171220
netdev->min_mtu = priv->dev_specs.min_mtu;
172221
netdev->netdev_ops = &hbg_netdev_ops;
222+
netdev->watchdog_timeo = 5 * HZ;
173223

174224
hbg_change_mtu(priv, ETH_DATA_LEN);
175225
hbg_net_set_mac_address(priv->netdev, &priv->dev_specs.mac_addr);

drivers/net/ethernet/hisilicon/hibmcge/hbg_reg.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,12 @@
8080
#define HBG_REG_CF_INTRPT_CLR_ADDR (HBG_REG_SGMII_BASE + 0x0438)
8181
#define HBG_REG_MAX_FRAME_LEN_ADDR (HBG_REG_SGMII_BASE + 0x0444)
8282
#define HBG_REG_MAX_FRAME_LEN_M GENMASK(15, 0)
83+
#define HBG_REG_CF_CFF_DATA_NUM_ADDR (HBG_REG_SGMII_BASE + 0x045C)
84+
#define HBG_REG_CF_CFF_DATA_NUM_ADDR_TX_M GENMASK(8, 0)
85+
#define HBG_REG_TX_CFF_ADDR_0_ADDR (HBG_REG_SGMII_BASE + 0x0488)
86+
#define HBG_REG_TX_CFF_ADDR_1_ADDR (HBG_REG_SGMII_BASE + 0x048C)
87+
#define HBG_REG_TX_CFF_ADDR_2_ADDR (HBG_REG_SGMII_BASE + 0x0490)
88+
#define HBG_REG_TX_CFF_ADDR_3_ADDR (HBG_REG_SGMII_BASE + 0x0494)
8389
#define HBG_REG_RX_BUF_SIZE_ADDR (HBG_REG_SGMII_BASE + 0x04E4)
8490
#define HBG_REG_RX_BUF_SIZE_M GENMASK(15, 0)
8591
#define HBG_REG_BUS_CTRL_ADDR (HBG_REG_SGMII_BASE + 0x04E8)
@@ -108,4 +114,17 @@ enum hbg_port_mode {
108114
HBG_PORT_MODE_SGMII_1000M = 0x8,
109115
};
110116

117+
struct hbg_tx_desc {
118+
u32 word0;
119+
u32 word1;
120+
u32 word2; /* pkt_addr */
121+
u32 word3; /* clear_addr */
122+
};
123+
124+
#define HBG_TX_DESC_W0_IP_OFF_M GENMASK(30, 26)
125+
#define HBG_TX_DESC_W0_l3_CS_B BIT(2)
126+
#define HBG_TX_DESC_W0_WB_B BIT(1)
127+
#define HBG_TX_DESC_W0_l4_CS_B BIT(0)
128+
#define HBG_TX_DESC_W1_SEND_LEN_M GENMASK(19, 4)
129+
111130
#endif

0 commit comments

Comments
 (0)