diff options
Diffstat (limited to 'drivers/net/ethernet/hisilicon')
| -rw-r--r-- | drivers/net/ethernet/hisilicon/Kconfig | 1 | ||||
| -rw-r--r-- | drivers/net/ethernet/hisilicon/hibmcge/Makefile | 1 | ||||
| -rw-r--r-- | drivers/net/ethernet/hisilicon/hibmcge/hbg_common.h | 8 | ||||
| -rw-r--r-- | drivers/net/ethernet/hisilicon/hibmcge/hbg_main.c | 17 | ||||
| -rw-r--r-- | drivers/net/ethernet/hisilicon/hibmcge/hbg_reg.h | 4 | ||||
| -rw-r--r-- | drivers/net/ethernet/hisilicon/hibmcge/hbg_trace.h | 84 | ||||
| -rw-r--r-- | drivers/net/ethernet/hisilicon/hibmcge/hbg_txrx.c | 217 | ||||
| -rw-r--r-- | drivers/net/ethernet/hisilicon/hns3/hnae3.h | 5 | ||||
| -rw-r--r-- | drivers/net/ethernet/hisilicon/hns3/hns3_enet.c | 31 | ||||
| -rw-r--r-- | drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 13 | ||||
| -rw-r--r-- | drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_ptp.c | 32 | ||||
| -rw-r--r-- | drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_ptp.h | 9 |
12 files changed, 353 insertions, 69 deletions
diff --git a/drivers/net/ethernet/hisilicon/Kconfig b/drivers/net/ethernet/hisilicon/Kconfig index 38875c196cb6..18eca7d12c20 100644 --- a/drivers/net/ethernet/hisilicon/Kconfig +++ b/drivers/net/ethernet/hisilicon/Kconfig @@ -151,6 +151,7 @@ config HIBMCGE select FIXED_PHY select MOTORCOMM_PHY select REALTEK_PHY + select PAGE_POOL help If you wish to compile a kernel for a BMC with HIBMC-xx_gmac then you should answer Y to this. This makes this driver suitable for use diff --git a/drivers/net/ethernet/hisilicon/hibmcge/Makefile b/drivers/net/ethernet/hisilicon/hibmcge/Makefile index 1a9da564b306..d6610ba16855 100644 --- a/drivers/net/ethernet/hisilicon/hibmcge/Makefile +++ b/drivers/net/ethernet/hisilicon/hibmcge/Makefile @@ -3,6 +3,7 @@ # Makefile for the HISILICON BMC GE network device drivers. # +ccflags-y += -I$(src) obj-$(CONFIG_HIBMCGE) += hibmcge.o hibmcge-objs = hbg_main.o hbg_hw.o hbg_mdio.o hbg_irq.o hbg_txrx.o hbg_ethtool.o \ diff --git a/drivers/net/ethernet/hisilicon/hibmcge/hbg_common.h b/drivers/net/ethernet/hisilicon/hibmcge/hbg_common.h index 2097e4c2b3d7..8e134da3e217 100644 --- a/drivers/net/ethernet/hisilicon/hibmcge/hbg_common.h +++ b/drivers/net/ethernet/hisilicon/hibmcge/hbg_common.h @@ -7,6 +7,7 @@ #include <linux/ethtool.h> #include <linux/netdevice.h> #include <linux/pci.h> +#include <net/page_pool/helpers.h> #include "hbg_reg.h" #define HBG_STATUS_DISABLE 0x0 @@ -55,6 +56,12 @@ struct hbg_buffer { dma_addr_t skb_dma; u32 skb_len; + struct page *page; + void *page_addr; + dma_addr_t page_dma; + u32 page_size; + u32 page_offset; + enum hbg_dir dir; struct hbg_ring *ring; struct hbg_priv *priv; @@ -78,6 +85,7 @@ struct hbg_ring { struct hbg_priv *priv; struct napi_struct napi; char *tout_log_buf; /* tx timeout log buffer */ + struct page_pool *page_pool; /* only for rx */ }; enum hbg_hw_event_type { diff --git a/drivers/net/ethernet/hisilicon/hibmcge/hbg_main.c b/drivers/net/ethernet/hisilicon/hibmcge/hbg_main.c index 0b92a2e5e986..068da2fd1fea 100644 --- a/drivers/net/ethernet/hisilicon/hibmcge/hbg_main.c +++ b/drivers/net/ethernet/hisilicon/hibmcge/hbg_main.c @@ -472,6 +472,22 @@ static int hbg_probe(struct pci_dev *pdev, const struct pci_device_id *ent) return 0; } +static void hbg_shutdown(struct pci_dev *pdev) +{ + struct net_device *netdev = pci_get_drvdata(pdev); + + rtnl_lock(); + if (netif_running(netdev)) + dev_close(netdev); + rtnl_unlock(); + + pci_disable_device(pdev); + pci_set_drvdata(pdev, NULL); + + if (system_state == SYSTEM_POWER_OFF) + pci_set_power_state(pdev, PCI_D3hot); +} + static const struct pci_device_id hbg_pci_tbl[] = { {PCI_VDEVICE(HUAWEI, 0x3730), 0}, { } @@ -482,6 +498,7 @@ static struct pci_driver hbg_driver = { .name = "hibmcge", .id_table = hbg_pci_tbl, .probe = hbg_probe, + .shutdown = hbg_shutdown, }; static int __init hbg_module_init(void) diff --git a/drivers/net/ethernet/hisilicon/hibmcge/hbg_reg.h b/drivers/net/ethernet/hisilicon/hibmcge/hbg_reg.h index a39d1e796e4a..30b3903c8f2d 100644 --- a/drivers/net/ethernet/hisilicon/hibmcge/hbg_reg.h +++ b/drivers/net/ethernet/hisilicon/hibmcge/hbg_reg.h @@ -252,6 +252,8 @@ struct hbg_rx_desc { #define HBG_RX_DESC_W2_PKT_LEN_M GENMASK(31, 16) #define HBG_RX_DESC_W2_PORT_NUM_M GENMASK(15, 12) +#define HBG_RX_DESC_W3_IP_OFFSET_M GENMASK(23, 16) +#define HBG_RX_DESC_W3_VLAN_M GENMASK(15, 0) #define HBG_RX_DESC_W4_IP_TCP_UDP_M GENMASK(31, 30) #define HBG_RX_DESC_W4_IPSEC_B BIT(29) #define HBG_RX_DESC_W4_IP_VERSION_B BIT(28) @@ -269,6 +271,8 @@ struct hbg_rx_desc { #define HBG_RX_DESC_W4_L3_ERR_CODE_M GENMASK(12, 9) #define HBG_RX_DESC_W4_L2_ERR_B BIT(8) #define HBG_RX_DESC_W4_IDX_MATCH_B BIT(7) +#define HBG_RX_DESC_W4_PARSE_MODE_M GENMASK(6, 5) +#define HBG_RX_DESC_W5_VALID_SIZE_M GENMASK(15, 0) enum hbg_l3_err_code { HBG_L3_OK = 0, diff --git a/drivers/net/ethernet/hisilicon/hibmcge/hbg_trace.h b/drivers/net/ethernet/hisilicon/hibmcge/hbg_trace.h new file mode 100644 index 000000000000..b70fd960da8d --- /dev/null +++ b/drivers/net/ethernet/hisilicon/hibmcge/hbg_trace.h @@ -0,0 +1,84 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* Copyright (c) 2025 Hisilicon Limited. */ + +/* This must be outside ifdef _HBG_TRACE_H */ +#undef TRACE_SYSTEM +#define TRACE_SYSTEM hibmcge + +#if !defined(_HBG_TRACE_H_) || defined(TRACE_HEADER_MULTI_READ) +#define _HBG_TRACE_H_ + +#include <linux/bitfield.h> +#include <linux/pci.h> +#include <linux/tracepoint.h> +#include <linux/types.h> +#include "hbg_reg.h" + +TRACE_EVENT(hbg_rx_desc, + TP_PROTO(struct hbg_priv *priv, u32 index, + struct hbg_rx_desc *rx_desc), + TP_ARGS(priv, index, rx_desc), + + TP_STRUCT__entry(__field(u32, index) + __field(u8, port_num) + __field(u8, ip_offset) + __field(u8, parse_mode) + __field(u8, l4_error_code) + __field(u8, l3_error_code) + __field(u8, l2_error_code) + __field(u16, packet_len) + __field(u16, valid_size) + __field(u16, vlan) + __string(pciname, pci_name(priv->pdev)) + __string(devname, priv->netdev->name) + ), + + TP_fast_assign(__entry->index = index, + __entry->packet_len = + FIELD_GET(HBG_RX_DESC_W2_PKT_LEN_M, + rx_desc->word2); + __entry->port_num = + FIELD_GET(HBG_RX_DESC_W2_PORT_NUM_M, + rx_desc->word2); + __entry->ip_offset = + FIELD_GET(HBG_RX_DESC_W3_IP_OFFSET_M, + rx_desc->word3); + __entry->vlan = + FIELD_GET(HBG_RX_DESC_W3_VLAN_M, + rx_desc->word3); + __entry->parse_mode = + FIELD_GET(HBG_RX_DESC_W4_PARSE_MODE_M, + rx_desc->word4); + __entry->l4_error_code = + FIELD_GET(HBG_RX_DESC_W4_L4_ERR_CODE_M, + rx_desc->word4); + __entry->l3_error_code = + FIELD_GET(HBG_RX_DESC_W4_L3_ERR_CODE_M, + rx_desc->word4); + __entry->l2_error_code = + FIELD_GET(HBG_RX_DESC_W4_L2_ERR_B, + rx_desc->word4); + __entry->valid_size = + FIELD_GET(HBG_RX_DESC_W5_VALID_SIZE_M, + rx_desc->word5); + __assign_str(pciname); + __assign_str(devname); + ), + + TP_printk("%s %s index:%u, port num:%u, len:%u, valid size:%u, ip_offset:%u, vlan:0x%04x, parse mode:%u, l4_err:0x%x, l3_err:0x%x, l2_err:0x%x", + __get_str(pciname), __get_str(devname), __entry->index, + __entry->port_num, __entry->packet_len, + __entry->valid_size, __entry->ip_offset, __entry->vlan, + __entry->parse_mode, __entry->l4_error_code, + __entry->l3_error_code, __entry->l2_error_code + ) +); + +#endif /* _HBG_TRACE_H_ */ + +/* This must be outside ifdef _HBG_TRACE_H */ +#undef TRACE_INCLUDE_PATH +#define TRACE_INCLUDE_PATH . +#undef TRACE_INCLUDE_FILE +#define TRACE_INCLUDE_FILE hbg_trace +#include <trace/define_trace.h> diff --git a/drivers/net/ethernet/hisilicon/hibmcge/hbg_txrx.c b/drivers/net/ethernet/hisilicon/hibmcge/hbg_txrx.c index 8d814c8f19ea..a4ea92c31c2f 100644 --- a/drivers/net/ethernet/hisilicon/hibmcge/hbg_txrx.c +++ b/drivers/net/ethernet/hisilicon/hibmcge/hbg_txrx.c @@ -7,6 +7,9 @@ #include "hbg_reg.h" #include "hbg_txrx.h" +#define CREATE_TRACE_POINTS +#include "hbg_trace.h" + #define netdev_get_tx_ring(netdev) \ (&(((struct hbg_priv *)netdev_priv(netdev))->tx_ring)) @@ -28,6 +31,11 @@ typeof(ring) _ring = (ring); \ _ring->p = hbg_queue_next_prt(_ring->p, _ring); }) +#define hbg_get_page_order(ring) ({ \ + typeof(ring) _ring = (ring); \ + get_order(hbg_spec_max_frame_len(_ring->priv, _ring->dir)); }) +#define hbg_get_page_size(ring) (PAGE_SIZE << hbg_get_page_order((ring))) + #define HBG_TX_STOP_THRS 2 #define HBG_TX_START_THRS (2 * HBG_TX_STOP_THRS) @@ -62,6 +70,43 @@ static void hbg_dma_unmap(struct hbg_buffer *buffer) buffer->skb_dma = 0; } +static void hbg_buffer_free_page(struct hbg_buffer *buffer) +{ + struct hbg_ring *ring = buffer->ring; + + if (unlikely(!buffer->page)) + return; + + page_pool_put_full_page(ring->page_pool, buffer->page, false); + + buffer->page = NULL; + buffer->page_dma = 0; + buffer->page_addr = NULL; + buffer->page_size = 0; + buffer->page_offset = 0; +} + +static int hbg_buffer_alloc_page(struct hbg_buffer *buffer) +{ + struct hbg_ring *ring = buffer->ring; + u32 len = hbg_get_page_size(ring); + u32 offset; + + if (unlikely(!ring->page_pool)) + return 0; + + buffer->page = page_pool_dev_alloc_frag(ring->page_pool, &offset, len); + if (unlikely(!buffer->page)) + return -ENOMEM; + + buffer->page_dma = page_pool_get_dma_addr(buffer->page) + offset; + buffer->page_addr = page_address(buffer->page) + offset; + buffer->page_size = len; + buffer->page_offset = offset; + + return 0; +} + static void hbg_init_tx_desc(struct hbg_buffer *buffer, struct hbg_tx_desc *tx_desc) { @@ -135,24 +180,14 @@ static void hbg_buffer_free_skb(struct hbg_buffer *buffer) buffer->skb = NULL; } -static int hbg_buffer_alloc_skb(struct hbg_buffer *buffer) -{ - u32 len = hbg_spec_max_frame_len(buffer->priv, buffer->dir); - struct hbg_priv *priv = buffer->priv; - - buffer->skb = netdev_alloc_skb(priv->netdev, len); - if (unlikely(!buffer->skb)) - return -ENOMEM; - - buffer->skb_len = len; - memset(buffer->skb->data, 0, HBG_PACKET_HEAD_SIZE); - return 0; -} - static void hbg_buffer_free(struct hbg_buffer *buffer) { - hbg_dma_unmap(buffer); - hbg_buffer_free_skb(buffer); + if (buffer->skb) { + hbg_dma_unmap(buffer); + return hbg_buffer_free_skb(buffer); + } + + hbg_buffer_free_page(buffer); } static int hbg_napi_tx_recycle(struct napi_struct *napi, int budget) @@ -374,25 +409,44 @@ static int hbg_rx_fill_one_buffer(struct hbg_priv *priv) struct hbg_buffer *buffer; int ret; - if (hbg_queue_is_full(ring->ntc, ring->ntu, ring)) + if (hbg_queue_is_full(ring->ntc, ring->ntu, ring) || + hbg_fifo_is_full(priv, ring->dir)) return 0; buffer = &ring->queue[ring->ntu]; - ret = hbg_buffer_alloc_skb(buffer); + ret = hbg_buffer_alloc_page(buffer); if (unlikely(ret)) return ret; - ret = hbg_dma_map(buffer); - if (unlikely(ret)) { - hbg_buffer_free_skb(buffer); - return ret; - } + memset(buffer->page_addr, 0, HBG_PACKET_HEAD_SIZE); + dma_sync_single_for_device(&priv->pdev->dev, buffer->page_dma, + HBG_PACKET_HEAD_SIZE, DMA_TO_DEVICE); - hbg_hw_fill_buffer(priv, buffer->skb_dma); + hbg_hw_fill_buffer(priv, buffer->page_dma); hbg_queue_move_next(ntu, ring); return 0; } +static int hbg_rx_fill_buffers(struct hbg_priv *priv) +{ + u32 remained = hbg_hw_get_fifo_used_num(priv, HBG_DIR_RX); + u32 max_count = priv->dev_specs.rx_fifo_num; + u32 refill_count; + int ret; + + if (unlikely(remained >= max_count)) + return 0; + + refill_count = max_count - remained; + while (refill_count--) { + ret = hbg_rx_fill_one_buffer(priv); + if (unlikely(ret)) + break; + } + + return ret; +} + static bool hbg_sync_data_from_hw(struct hbg_priv *priv, struct hbg_buffer *buffer) { @@ -401,13 +455,29 @@ static bool hbg_sync_data_from_hw(struct hbg_priv *priv, /* make sure HW write desc complete */ dma_rmb(); - dma_sync_single_for_cpu(&priv->pdev->dev, buffer->skb_dma, - buffer->skb_len, DMA_FROM_DEVICE); + dma_sync_single_for_cpu(&priv->pdev->dev, buffer->page_dma, + buffer->page_size, DMA_FROM_DEVICE); - rx_desc = (struct hbg_rx_desc *)buffer->skb->data; + rx_desc = (struct hbg_rx_desc *)buffer->page_addr; return FIELD_GET(HBG_RX_DESC_W2_PKT_LEN_M, rx_desc->word2) != 0; } +static int hbg_build_skb(struct hbg_priv *priv, + struct hbg_buffer *buffer, u32 pkt_len) +{ + net_prefetch(buffer->page_addr); + + buffer->skb = napi_build_skb(buffer->page_addr, buffer->page_size); + if (unlikely(!buffer->skb)) + return -ENOMEM; + skb_mark_for_recycle(buffer->skb); + + /* page will be freed together with the skb */ + buffer->page = NULL; + + return 0; +} + static int hbg_napi_rx_poll(struct napi_struct *napi, int budget) { struct hbg_ring *ring = container_of(napi, struct hbg_ring, napi); @@ -417,33 +487,39 @@ static int hbg_napi_rx_poll(struct napi_struct *napi, int budget) u32 packet_done = 0; u32 pkt_len; + hbg_rx_fill_buffers(priv); while (packet_done < budget) { if (unlikely(hbg_queue_is_empty(ring->ntc, ring->ntu, ring))) break; buffer = &ring->queue[ring->ntc]; - if (unlikely(!buffer->skb)) + if (unlikely(!buffer->page)) goto next_buffer; if (unlikely(!hbg_sync_data_from_hw(priv, buffer))) break; - rx_desc = (struct hbg_rx_desc *)buffer->skb->data; + rx_desc = (struct hbg_rx_desc *)buffer->page_addr; pkt_len = FIELD_GET(HBG_RX_DESC_W2_PKT_LEN_M, rx_desc->word2); + trace_hbg_rx_desc(priv, ring->ntc, rx_desc); + + if (unlikely(hbg_build_skb(priv, buffer, pkt_len))) { + hbg_buffer_free_page(buffer); + goto next_buffer; + } if (unlikely(!hbg_rx_pkt_check(priv, rx_desc, buffer->skb))) { - hbg_buffer_free(buffer); + hbg_buffer_free_skb(buffer); goto next_buffer; } - hbg_dma_unmap(buffer); skb_reserve(buffer->skb, HBG_PACKET_HEAD_SIZE + NET_IP_ALIGN); skb_put(buffer->skb, pkt_len); buffer->skb->protocol = eth_type_trans(buffer->skb, priv->netdev); - dev_sw_netstats_rx_add(priv->netdev, pkt_len); napi_gro_receive(napi, buffer->skb); buffer->skb = NULL; + buffer->page = NULL; next_buffer: hbg_rx_fill_one_buffer(priv); @@ -458,6 +534,42 @@ next_buffer: return packet_done; } +static void hbg_ring_page_pool_destory(struct hbg_ring *ring) +{ + if (!ring->page_pool) + return; + + page_pool_destroy(ring->page_pool); + ring->page_pool = NULL; +} + +static int hbg_ring_page_pool_init(struct hbg_priv *priv, struct hbg_ring *ring) +{ + u32 buf_size = hbg_spec_max_frame_len(priv, ring->dir); + struct page_pool_params pp_params = { + .flags = PP_FLAG_DMA_MAP | PP_FLAG_DMA_SYNC_DEV, + .order = hbg_get_page_order(ring), + .pool_size = ring->len * buf_size / hbg_get_page_size(ring), + .nid = dev_to_node(&priv->pdev->dev), + .dev = &priv->pdev->dev, + .napi = &ring->napi, + .dma_dir = DMA_FROM_DEVICE, + .offset = 0, + .max_len = hbg_get_page_size(ring), + }; + int ret = 0; + + ring->page_pool = page_pool_create(&pp_params); + if (IS_ERR(ring->page_pool)) { + ret = PTR_ERR(ring->page_pool); + dev_err(&priv->pdev->dev, + "failed to create page pool, ret = %d\n", ret); + ring->page_pool = NULL; + } + + return ret; +} + static void hbg_ring_uninit(struct hbg_ring *ring) { struct hbg_buffer *buffer; @@ -476,6 +588,7 @@ static void hbg_ring_uninit(struct hbg_ring *ring) buffer->priv = NULL; } + hbg_ring_page_pool_destory(ring); dma_free_coherent(&ring->priv->pdev->dev, ring->len * sizeof(*ring->queue), ring->queue, ring->queue_dma); @@ -491,8 +604,19 @@ static int hbg_ring_init(struct hbg_priv *priv, struct hbg_ring *ring, { struct hbg_buffer *buffer; u32 i, len; + int ret; len = hbg_get_spec_fifo_max_num(priv, dir) + 1; + /* To improve receiving performance under high-stress scenarios, + * in the `hbg_napi_rx_poll()`, we first use the other half of + * the buffer to receive packets from the hardware via the + * `hbg_rx_fill_buffers()`, and then process the packets in the + * original half of the buffer to avoid packet loss caused by + * hardware overflow as much as possible. + */ + if (dir == HBG_DIR_RX) + len += hbg_get_spec_fifo_max_num(priv, dir); + ring->queue = dma_alloc_coherent(&priv->pdev->dev, len * sizeof(*ring->queue), &ring->queue_dma, GFP_KERNEL); @@ -514,11 +638,23 @@ static int hbg_ring_init(struct hbg_priv *priv, struct hbg_ring *ring, ring->ntu = 0; ring->len = len; - if (dir == HBG_DIR_TX) + if (dir == HBG_DIR_TX) { netif_napi_add_tx(priv->netdev, &ring->napi, napi_poll); - else + } else { netif_napi_add(priv->netdev, &ring->napi, napi_poll); + ret = hbg_ring_page_pool_init(priv, ring); + if (ret) { + netif_napi_del(&ring->napi); + dma_free_coherent(&ring->priv->pdev->dev, + ring->len * sizeof(*ring->queue), + ring->queue, ring->queue_dma); + ring->queue = NULL; + ring->len = 0; + return ret; + } + } + napi_enable(&ring->napi); return 0; } @@ -541,21 +677,16 @@ static int hbg_tx_ring_init(struct hbg_priv *priv) static int hbg_rx_ring_init(struct hbg_priv *priv) { int ret; - u32 i; ret = hbg_ring_init(priv, &priv->rx_ring, hbg_napi_rx_poll, HBG_DIR_RX); if (ret) return ret; - for (i = 0; i < priv->rx_ring.len - 1; i++) { - ret = hbg_rx_fill_one_buffer(priv); - if (ret) { - hbg_ring_uninit(&priv->rx_ring); - return ret; - } - } + ret = hbg_rx_fill_buffers(priv); + if (ret) + hbg_ring_uninit(&priv->rx_ring); - return 0; + return ret; } int hbg_txrx_init(struct hbg_priv *priv) diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h b/drivers/net/ethernet/hisilicon/hns3/hnae3.h index 3b548f71fa8a..d7c3df1958f3 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hnae3.h +++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h @@ -804,6 +804,11 @@ struct hnae3_ae_ops { int (*dbg_get_read_func)(struct hnae3_handle *handle, enum hnae3_dbg_cmd cmd, read_func *func); + int (*hwtstamp_get)(struct hnae3_handle *handle, + struct kernel_hwtstamp_config *config); + int (*hwtstamp_set)(struct hnae3_handle *handle, + struct kernel_hwtstamp_config *config, + struct netlink_ext_ack *extack); }; struct hnae3_dcb_ops { diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index bfa5568baa92..7a0654e2d3dd 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -2419,6 +2419,35 @@ static int hns3_nic_do_ioctl(struct net_device *netdev, return h->ae_algo->ops->do_ioctl(h, ifr, cmd); } +static int hns3_nic_hwtstamp_get(struct net_device *netdev, + struct kernel_hwtstamp_config *config) +{ + struct hnae3_handle *h = hns3_get_handle(netdev); + + if (!netif_running(netdev)) + return -EINVAL; + + if (!h->ae_algo->ops->hwtstamp_get) + return -EOPNOTSUPP; + + return h->ae_algo->ops->hwtstamp_get(h, config); +} + +static int hns3_nic_hwtstamp_set(struct net_device *netdev, + struct kernel_hwtstamp_config *config, + struct netlink_ext_ack *extack) +{ + struct hnae3_handle *h = hns3_get_handle(netdev); + + if (!netif_running(netdev)) + return -EINVAL; + + if (!h->ae_algo->ops->hwtstamp_set) + return -EOPNOTSUPP; + + return h->ae_algo->ops->hwtstamp_set(h, config, extack); +} + static int hns3_nic_set_features(struct net_device *netdev, netdev_features_t features) { @@ -3048,6 +3077,8 @@ static const struct net_device_ops hns3_nic_netdev_ops = { .ndo_set_vf_rate = hns3_nic_set_vf_rate, .ndo_set_vf_mac = hns3_nic_set_vf_mac, .ndo_select_queue = hns3_nic_select_queue, + .ndo_hwtstamp_get = hns3_nic_hwtstamp_get, + .ndo_hwtstamp_set = hns3_nic_hwtstamp_set, }; bool hns3_is_phys_func(struct pci_dev *pdev) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index 782bb48c9f3d..cf8abbe01840 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -9444,15 +9444,8 @@ static int hclge_do_ioctl(struct hnae3_handle *handle, struct ifreq *ifr, struct hclge_vport *vport = hclge_get_vport(handle); struct hclge_dev *hdev = vport->back; - switch (cmd) { - case SIOCGHWTSTAMP: - return hclge_ptp_get_cfg(hdev, ifr); - case SIOCSHWTSTAMP: - return hclge_ptp_set_cfg(hdev, ifr); - default: - if (!hdev->hw.mac.phydev) - return hclge_mii_ioctl(hdev, ifr, cmd); - } + if (!hdev->hw.mac.phydev) + return hclge_mii_ioctl(hdev, ifr, cmd); return phy_mii_ioctl(hdev->hw.mac.phydev, ifr, cmd); } @@ -12900,6 +12893,8 @@ static const struct hnae3_ae_ops hclge_ops = { .get_dscp_prio = hclge_get_dscp_prio, .get_wol = hclge_get_wol, .set_wol = hclge_set_wol, + .hwtstamp_get = hclge_ptp_get_cfg, + .hwtstamp_set = hclge_ptp_set_cfg, }; static struct hnae3_ae_algo ae_algo = { diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_ptp.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_ptp.c index 4bd52eab3914..0081c5281455 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_ptp.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_ptp.c @@ -204,13 +204,17 @@ static int hclge_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta) return 0; } -int hclge_ptp_get_cfg(struct hclge_dev *hdev, struct ifreq *ifr) +int hclge_ptp_get_cfg(struct hnae3_handle *handle, + struct kernel_hwtstamp_config *config) { + struct hclge_vport *vport = hclge_get_vport(handle); + struct hclge_dev *hdev = vport->back; + if (!test_bit(HCLGE_STATE_PTP_EN, &hdev->state)) return -EOPNOTSUPP; - return copy_to_user(ifr->ifr_data, &hdev->ptp->ts_cfg, - sizeof(struct hwtstamp_config)) ? -EFAULT : 0; + *config = hdev->ptp->ts_cfg; + return 0; } static int hclge_ptp_int_en(struct hclge_dev *hdev, bool en) @@ -269,7 +273,7 @@ static int hclge_ptp_cfg(struct hclge_dev *hdev, u32 cfg) return ret; } -static int hclge_ptp_set_tx_mode(struct hwtstamp_config *cfg, +static int hclge_ptp_set_tx_mode(struct kernel_hwtstamp_config *cfg, unsigned long *flags, u32 *ptp_cfg) { switch (cfg->tx_type) { @@ -287,7 +291,7 @@ static int hclge_ptp_set_tx_mode(struct hwtstamp_config *cfg, return 0; } -static int hclge_ptp_set_rx_mode(struct hwtstamp_config *cfg, +static int hclge_ptp_set_rx_mode(struct kernel_hwtstamp_config *cfg, unsigned long *flags, u32 *ptp_cfg) { int rx_filter = cfg->rx_filter; @@ -332,7 +336,7 @@ static int hclge_ptp_set_rx_mode(struct hwtstamp_config *cfg, } static int hclge_ptp_set_ts_mode(struct hclge_dev *hdev, - struct hwtstamp_config *cfg) + struct kernel_hwtstamp_config *cfg) { unsigned long flags = hdev->ptp->flags; u32 ptp_cfg = 0; @@ -359,9 +363,12 @@ static int hclge_ptp_set_ts_mode(struct hclge_dev *hdev, return 0; } -int hclge_ptp_set_cfg(struct hclge_dev *hdev, struct ifreq *ifr) +int hclge_ptp_set_cfg(struct hnae3_handle *handle, + struct kernel_hwtstamp_config *config, + struct netlink_ext_ack *extack) { - struct hwtstamp_config cfg; + struct hclge_vport *vport = hclge_get_vport(handle); + struct hclge_dev *hdev = vport->back; int ret; if (!test_bit(HCLGE_STATE_PTP_EN, &hdev->state)) { @@ -369,16 +376,13 @@ int hclge_ptp_set_cfg(struct hclge_dev *hdev, struct ifreq *ifr) return -EOPNOTSUPP; } - if (copy_from_user(&cfg, ifr->ifr_data, sizeof(cfg))) - return -EFAULT; - - ret = hclge_ptp_set_ts_mode(hdev, &cfg); + ret = hclge_ptp_set_ts_mode(hdev, config); if (ret) return ret; - hdev->ptp->ts_cfg = cfg; + hdev->ptp->ts_cfg = *config; - return copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)) ? -EFAULT : 0; + return 0; } int hclge_ptp_get_ts_info(struct hnae3_handle *handle, diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_ptp.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_ptp.h index 61faddcc3dd0..0162fa5ac146 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_ptp.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_ptp.h @@ -62,7 +62,7 @@ struct hclge_ptp { unsigned long flags; void __iomem *io_base; struct ptp_clock_info info; - struct hwtstamp_config ts_cfg; + struct kernel_hwtstamp_config ts_cfg; spinlock_t lock; /* protects ptp registers */ u32 ptp_cfg; u32 last_tx_seqid; @@ -133,8 +133,11 @@ bool hclge_ptp_set_tx_info(struct hnae3_handle *handle, struct sk_buff *skb); void hclge_ptp_clean_tx_hwts(struct hclge_dev *hdev); void hclge_ptp_get_rx_hwts(struct hnae3_handle *handle, struct sk_buff *skb, u32 nsec, u32 sec); -int hclge_ptp_get_cfg(struct hclge_dev *hdev, struct ifreq *ifr); -int hclge_ptp_set_cfg(struct hclge_dev *hdev, struct ifreq *ifr); +int hclge_ptp_get_cfg(struct hnae3_handle *handle, + struct kernel_hwtstamp_config *config); +int hclge_ptp_set_cfg(struct hnae3_handle *handle, + struct kernel_hwtstamp_config *config, + struct netlink_ext_ack *extack); int hclge_ptp_init(struct hclge_dev *hdev); void hclge_ptp_uninit(struct hclge_dev *hdev); int hclge_ptp_get_ts_info(struct hnae3_handle *handle, |
