Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'net-hinic3-pf-initialization'

Fan Gong says:

====================
net: hinic3: PF initialization

This is [1/3] part of hinic3 Ethernet driver second submission.
With this patch hinic3 becomes a complete Ethernet driver with
pf and vf.

The driver parts contained in this patch:
Add support for PF framework based on the VF code.
Add PF management interfaces to communicate with HW.
Add 8 netdev ops to configure NIC features.
Support mac filter to unicast and multicast.
Add HW event handler to manage port and link status.

V01: https://lore.kernel.org/netdev/cover.1760502478.git.zhuyikai1@h-partners.com/
V02: https://lore.kernel.org/netdev/cover.1760685059.git.zhuyikai1@h-partners.com/
V03: https://lore.kernel.org/netdev/cover.1761362580.git.zhuyikai1@h-partners.com/
V04: https://lore.kernel.org/netdev/cover.1761711549.git.zhuyikai1@h-partners.com/
V05: https://lore.kernel.org/netdev/cover.1762414088.git.zhuyikai1@h-partners.com/
V06: https://lore.kernel.org/netdev/cover.1762581665.git.zhuyikai1@h-partners.com/
V07: https://lore.kernel.org/netdev/cover.1763555878.git.zhuyikai1@h-partners.com/
V08: https://lore.kernel.org/netdev/cover.1767495881.git.zhuyikai1@h-partners.com/
V09: https://lore.kernel.org/netdev/cover.1767707500.git.zhuyikai1@h-partners.com/
V10: https://lore.kernel.org/netdev/cover.1767861236.git.zhuyikai1@h-partners.com/
====================

Link: https://patch.msgid.link/cover.1768375903.git.zhuyikai1@h-partners.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>

+2443 -36
+1
drivers/net/ethernet/huawei/hinic3/Makefile
··· 6 6 hinic3-objs := hinic3_cmdq.o \ 7 7 hinic3_common.o \ 8 8 hinic3_eqs.o \ 9 + hinic3_filter.o \ 9 10 hinic3_hw_cfg.o \ 10 11 hinic3_hw_comm.o \ 11 12 hinic3_hwdev.o \
+6
drivers/net/ethernet/huawei/hinic3/hinic3_csr.h
··· 5 5 #define _HINIC3_CSR_H_ 6 6 7 7 #define HINIC3_CFG_REGS_FLAG 0x40000000 8 + #define HINIC3_MGMT_REGS_FLAG 0xC0000000 8 9 #define HINIC3_REGS_FLAG_MASK 0x3FFFFFFF 9 10 10 11 #define HINIC3_VF_CFG_REG_OFFSET 0x2000 ··· 24 23 #define HINIC3_FUNC_CSR_MAILBOX_INT_OFF (HINIC3_CFG_REGS_FLAG + 0x0104) 25 24 #define HINIC3_FUNC_CSR_MAILBOX_RESULT_H_OFF (HINIC3_CFG_REGS_FLAG + 0x0108) 26 25 #define HINIC3_FUNC_CSR_MAILBOX_RESULT_L_OFF (HINIC3_CFG_REGS_FLAG + 0x010C) 26 + 27 + #define HINIC3_HOST_CSR_BASE_ADDR (HINIC3_MGMT_REGS_FLAG + 0x6000) 28 + #define HINIC3_PPF_ELECTION_OFFSET 0x0 29 + #define HINIC3_CSR_PPF_ELECTION_ADDR \ 30 + (HINIC3_HOST_CSR_BASE_ADDR + HINIC3_PPF_ELECTION_OFFSET) 27 31 28 32 #define HINIC3_CSR_DMA_ATTR_TBL_ADDR (HINIC3_CFG_REGS_FLAG + 0x380) 29 33 #define HINIC3_CSR_DMA_ATTR_INDIR_IDX_ADDR (HINIC3_CFG_REGS_FLAG + 0x390)
+417
drivers/net/ethernet/huawei/hinic3/hinic3_filter.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + // Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved. 3 + 4 + #include <linux/kernel.h> 5 + #include <linux/pci.h> 6 + #include <linux/device.h> 7 + #include <linux/types.h> 8 + #include <linux/errno.h> 9 + #include <linux/etherdevice.h> 10 + #include <linux/netdevice.h> 11 + #include <linux/module.h> 12 + #include <linux/moduleparam.h> 13 + 14 + #include "hinic3_hwif.h" 15 + #include "hinic3_nic_dev.h" 16 + #include "hinic3_nic_cfg.h" 17 + 18 + static int hinic3_filter_addr_sync(struct net_device *netdev, u8 *addr) 19 + { 20 + struct hinic3_nic_dev *nic_dev = netdev_priv(netdev); 21 + 22 + return hinic3_set_mac(nic_dev->hwdev, addr, 0, 23 + hinic3_global_func_id(nic_dev->hwdev)); 24 + } 25 + 26 + static int hinic3_filter_addr_unsync(struct net_device *netdev, u8 *addr) 27 + { 28 + struct hinic3_nic_dev *nic_dev = netdev_priv(netdev); 29 + 30 + /* The addr is in use */ 31 + if (ether_addr_equal(addr, netdev->dev_addr)) 32 + return 0; 33 + 34 + return hinic3_del_mac(nic_dev->hwdev, addr, 0, 35 + hinic3_global_func_id(nic_dev->hwdev)); 36 + } 37 + 38 + void hinic3_clean_mac_list_filter(struct net_device *netdev) 39 + { 40 + struct hinic3_nic_dev *nic_dev = netdev_priv(netdev); 41 + struct hinic3_mac_filter *ftmp; 42 + struct hinic3_mac_filter *f; 43 + 44 + list_for_each_entry_safe(f, ftmp, &nic_dev->uc_filter_list, list) { 45 + if (f->state == HINIC3_MAC_HW_SYNCED) 46 + hinic3_filter_addr_unsync(netdev, f->addr); 47 + list_del(&f->list); 48 + kfree(f); 49 + } 50 + 51 + list_for_each_entry_safe(f, ftmp, &nic_dev->mc_filter_list, list) { 52 + if (f->state == HINIC3_MAC_HW_SYNCED) 53 + hinic3_filter_addr_unsync(netdev, f->addr); 54 + list_del(&f->list); 55 + kfree(f); 56 + } 57 + } 58 + 59 + static struct hinic3_mac_filter * 60 + hinic3_find_mac(const struct list_head *filter_list, u8 *addr) 61 + { 62 + struct hinic3_mac_filter *f; 63 + 64 + list_for_each_entry(f, filter_list, list) { 65 + if (ether_addr_equal(addr, f->addr)) 66 + return f; 67 + } 68 + return NULL; 69 + } 70 + 71 + static void hinic3_add_filter(struct net_device *netdev, 72 + struct list_head *mac_filter_list, 73 + u8 *addr) 74 + { 75 + struct hinic3_nic_dev *nic_dev = netdev_priv(netdev); 76 + struct hinic3_mac_filter *f; 77 + 78 + f = kzalloc(sizeof(*f), GFP_ATOMIC); 79 + if (!f) 80 + return; 81 + 82 + ether_addr_copy(f->addr, addr); 83 + 84 + INIT_LIST_HEAD(&f->list); 85 + list_add_tail(&f->list, mac_filter_list); 86 + 87 + f->state = HINIC3_MAC_WAIT_HW_SYNC; 88 + set_bit(HINIC3_MAC_FILTER_CHANGED, &nic_dev->flags); 89 + } 90 + 91 + static void hinic3_del_filter(struct net_device *netdev, 92 + struct hinic3_mac_filter *f) 93 + { 94 + struct hinic3_nic_dev *nic_dev = netdev_priv(netdev); 95 + 96 + set_bit(HINIC3_MAC_FILTER_CHANGED, &nic_dev->flags); 97 + 98 + if (f->state == HINIC3_MAC_WAIT_HW_SYNC) { 99 + /* have not added to hw, delete it directly */ 100 + list_del(&f->list); 101 + kfree(f); 102 + return; 103 + } 104 + 105 + f->state = HINIC3_MAC_WAIT_HW_UNSYNC; 106 + } 107 + 108 + static struct hinic3_mac_filter * 109 + hinic3_mac_filter_entry_clone(const struct hinic3_mac_filter *src) 110 + { 111 + struct hinic3_mac_filter *f; 112 + 113 + f = kzalloc(sizeof(*f), GFP_ATOMIC); 114 + if (!f) 115 + return NULL; 116 + 117 + *f = *src; 118 + INIT_LIST_HEAD(&f->list); 119 + 120 + return f; 121 + } 122 + 123 + static void hinic3_undo_del_filter_entries(struct list_head *filter_list, 124 + const struct list_head *from) 125 + { 126 + struct hinic3_mac_filter *ftmp; 127 + struct hinic3_mac_filter *f; 128 + 129 + list_for_each_entry_safe(f, ftmp, from, list) { 130 + if (hinic3_find_mac(filter_list, f->addr)) 131 + continue; 132 + 133 + if (f->state == HINIC3_MAC_HW_UNSYNCED) 134 + f->state = HINIC3_MAC_WAIT_HW_UNSYNC; 135 + 136 + list_move_tail(&f->list, filter_list); 137 + } 138 + } 139 + 140 + static void hinic3_undo_add_filter_entries(struct list_head *filter_list, 141 + const struct list_head *from) 142 + { 143 + struct hinic3_mac_filter *ftmp; 144 + struct hinic3_mac_filter *tmp; 145 + struct hinic3_mac_filter *f; 146 + 147 + list_for_each_entry_safe(f, ftmp, from, list) { 148 + tmp = hinic3_find_mac(filter_list, f->addr); 149 + if (tmp && tmp->state == HINIC3_MAC_HW_SYNCING) 150 + tmp->state = HINIC3_MAC_WAIT_HW_SYNC; 151 + } 152 + } 153 + 154 + static void hinic3_cleanup_filter_list(const struct list_head *head) 155 + { 156 + struct hinic3_mac_filter *ftmp; 157 + struct hinic3_mac_filter *f; 158 + 159 + list_for_each_entry_safe(f, ftmp, head, list) { 160 + list_del(&f->list); 161 + kfree(f); 162 + } 163 + } 164 + 165 + static int hinic3_mac_filter_sync_hw(struct net_device *netdev, 166 + struct list_head *del_list, 167 + struct list_head *add_list, 168 + int *add_count) 169 + { 170 + struct hinic3_mac_filter *ftmp; 171 + struct hinic3_mac_filter *f; 172 + int err; 173 + 174 + if (!list_empty(del_list)) { 175 + list_for_each_entry_safe(f, ftmp, del_list, list) { 176 + /* ignore errors when deleting mac */ 177 + hinic3_filter_addr_unsync(netdev, f->addr); 178 + list_del(&f->list); 179 + kfree(f); 180 + } 181 + } 182 + 183 + if (!list_empty(add_list)) { 184 + list_for_each_entry_safe(f, ftmp, add_list, list) { 185 + if (f->state != HINIC3_MAC_HW_SYNCING) 186 + continue; 187 + 188 + err = hinic3_filter_addr_sync(netdev, f->addr); 189 + if (err) { 190 + netdev_err(netdev, "Failed to add mac\n"); 191 + return err; 192 + } 193 + 194 + f->state = HINIC3_MAC_HW_SYNCED; 195 + (*add_count)++; 196 + } 197 + } 198 + 199 + return 0; 200 + } 201 + 202 + static int hinic3_mac_filter_sync(struct net_device *netdev, 203 + struct list_head *mac_filter_list, bool uc) 204 + { 205 + struct hinic3_nic_dev *nic_dev = netdev_priv(netdev); 206 + struct list_head tmp_del_list, tmp_add_list; 207 + struct hinic3_mac_filter *fclone; 208 + struct hinic3_mac_filter *ftmp; 209 + struct hinic3_mac_filter *f; 210 + int err = 0, add_count = 0; 211 + 212 + INIT_LIST_HEAD(&tmp_del_list); 213 + INIT_LIST_HEAD(&tmp_add_list); 214 + 215 + list_for_each_entry_safe(f, ftmp, mac_filter_list, list) { 216 + if (f->state != HINIC3_MAC_WAIT_HW_UNSYNC) 217 + continue; 218 + 219 + f->state = HINIC3_MAC_HW_UNSYNCED; 220 + list_move_tail(&f->list, &tmp_del_list); 221 + } 222 + 223 + list_for_each_entry_safe(f, ftmp, mac_filter_list, list) { 224 + if (f->state != HINIC3_MAC_WAIT_HW_SYNC) 225 + continue; 226 + 227 + fclone = hinic3_mac_filter_entry_clone(f); 228 + if (!fclone) { 229 + hinic3_undo_del_filter_entries(mac_filter_list, 230 + &tmp_del_list); 231 + hinic3_undo_add_filter_entries(mac_filter_list, 232 + &tmp_add_list); 233 + 234 + netdev_err(netdev, 235 + "Failed to clone mac_filter_entry\n"); 236 + err = -ENOMEM; 237 + goto cleanup_tmp_filter_list; 238 + } 239 + 240 + f->state = HINIC3_MAC_HW_SYNCING; 241 + list_add_tail(&fclone->list, &tmp_add_list); 242 + } 243 + 244 + err = hinic3_mac_filter_sync_hw(netdev, &tmp_del_list, 245 + &tmp_add_list, &add_count); 246 + if (err) { 247 + /* there were errors, delete all mac in hw */ 248 + hinic3_undo_add_filter_entries(mac_filter_list, &tmp_add_list); 249 + add_count = 0; 250 + /* VF does not support promiscuous mode, 251 + * don't delete any other uc mac. 252 + */ 253 + if (!HINIC3_IS_VF(nic_dev->hwdev) || !uc) { 254 + list_for_each_entry_safe(f, ftmp, mac_filter_list, 255 + list) { 256 + if (f->state != HINIC3_MAC_HW_SYNCED) 257 + continue; 258 + 259 + fclone = hinic3_mac_filter_entry_clone(f); 260 + if (!fclone) 261 + break; 262 + 263 + f->state = HINIC3_MAC_WAIT_HW_SYNC; 264 + list_add_tail(&fclone->list, &tmp_del_list); 265 + } 266 + } 267 + 268 + hinic3_mac_filter_sync_hw(netdev, &tmp_del_list, 269 + &tmp_add_list, &add_count); 270 + } 271 + 272 + cleanup_tmp_filter_list: 273 + hinic3_cleanup_filter_list(&tmp_del_list); 274 + hinic3_cleanup_filter_list(&tmp_add_list); 275 + 276 + return err ? err : add_count; 277 + } 278 + 279 + static void hinic3_mac_filter_sync_all(struct net_device *netdev) 280 + { 281 + struct hinic3_nic_dev *nic_dev = netdev_priv(netdev); 282 + int add_count; 283 + 284 + if (test_bit(HINIC3_MAC_FILTER_CHANGED, &nic_dev->flags)) { 285 + clear_bit(HINIC3_MAC_FILTER_CHANGED, &nic_dev->flags); 286 + add_count = hinic3_mac_filter_sync(netdev, 287 + &nic_dev->uc_filter_list, 288 + true); 289 + if (add_count < 0 && 290 + hinic3_test_support(nic_dev, HINIC3_NIC_F_PROMISC)) 291 + set_bit(HINIC3_PROMISC_FORCE_ON, 292 + &nic_dev->rx_mod_state); 293 + else if (add_count) 294 + clear_bit(HINIC3_PROMISC_FORCE_ON, 295 + &nic_dev->rx_mod_state); 296 + 297 + add_count = hinic3_mac_filter_sync(netdev, 298 + &nic_dev->mc_filter_list, 299 + false); 300 + if (add_count < 0 && 301 + hinic3_test_support(nic_dev, HINIC3_NIC_F_ALLMULTI)) 302 + set_bit(HINIC3_ALLMULTI_FORCE_ON, 303 + &nic_dev->rx_mod_state); 304 + else if (add_count) 305 + clear_bit(HINIC3_ALLMULTI_FORCE_ON, 306 + &nic_dev->rx_mod_state); 307 + } 308 + } 309 + 310 + #define HINIC3_DEFAULT_RX_MODE \ 311 + (L2NIC_RX_MODE_UC | L2NIC_RX_MODE_MC | L2NIC_RX_MODE_BC) 312 + 313 + static void hinic3_update_mac_filter(struct net_device *netdev, 314 + const struct netdev_hw_addr_list *src_list, 315 + struct list_head *filter_list) 316 + { 317 + struct hinic3_mac_filter *filter; 318 + struct hinic3_mac_filter *ftmp; 319 + struct hinic3_mac_filter *f; 320 + struct netdev_hw_addr *ha; 321 + 322 + /* add addr if not already in the filter list */ 323 + netif_addr_lock_bh(netdev); 324 + netdev_hw_addr_list_for_each(ha, src_list) { 325 + filter = hinic3_find_mac(filter_list, ha->addr); 326 + if (!filter) 327 + hinic3_add_filter(netdev, filter_list, ha->addr); 328 + else if (filter->state == HINIC3_MAC_WAIT_HW_UNSYNC) 329 + filter->state = HINIC3_MAC_HW_SYNCED; 330 + } 331 + netif_addr_unlock_bh(netdev); 332 + 333 + /* delete addr if not in netdev list */ 334 + list_for_each_entry_safe(f, ftmp, filter_list, list) { 335 + bool found = false; 336 + 337 + netif_addr_lock_bh(netdev); 338 + netdev_hw_addr_list_for_each(ha, src_list) 339 + if (ether_addr_equal(ha->addr, f->addr)) { 340 + found = true; 341 + break; 342 + } 343 + netif_addr_unlock_bh(netdev); 344 + 345 + if (found) 346 + continue; 347 + 348 + hinic3_del_filter(netdev, f); 349 + } 350 + } 351 + 352 + static void hinic3_sync_rx_mode_to_hw(struct net_device *netdev, int promisc_en, 353 + int allmulti_en) 354 + { 355 + struct hinic3_nic_dev *nic_dev = netdev_priv(netdev); 356 + u32 rx_mode = HINIC3_DEFAULT_RX_MODE; 357 + int err; 358 + 359 + rx_mode |= (promisc_en ? L2NIC_RX_MODE_PROMISC : 0); 360 + rx_mode |= (allmulti_en ? L2NIC_RX_MODE_MC_ALL : 0); 361 + 362 + if (promisc_en != test_bit(HINIC3_HW_PROMISC_ON, 363 + &nic_dev->rx_mod_state)) 364 + netdev_dbg(netdev, "%s promisc mode\n", 365 + promisc_en ? "Enter" : "Left"); 366 + if (allmulti_en != 367 + test_bit(HINIC3_HW_ALLMULTI_ON, &nic_dev->rx_mod_state)) 368 + netdev_dbg(netdev, "%s all_multi mode\n", 369 + allmulti_en ? "Enter" : "Left"); 370 + 371 + err = hinic3_set_rx_mode(nic_dev->hwdev, rx_mode); 372 + if (err) { 373 + netdev_err(netdev, "Failed to set rx_mode\n"); 374 + return; 375 + } 376 + 377 + promisc_en ? set_bit(HINIC3_HW_PROMISC_ON, &nic_dev->rx_mod_state) : 378 + clear_bit(HINIC3_HW_PROMISC_ON, &nic_dev->rx_mod_state); 379 + 380 + allmulti_en ? set_bit(HINIC3_HW_ALLMULTI_ON, &nic_dev->rx_mod_state) : 381 + clear_bit(HINIC3_HW_ALLMULTI_ON, &nic_dev->rx_mod_state); 382 + } 383 + 384 + void hinic3_set_rx_mode_work(struct work_struct *work) 385 + { 386 + int promisc_en = 0, allmulti_en = 0; 387 + struct hinic3_nic_dev *nic_dev; 388 + struct net_device *netdev; 389 + 390 + nic_dev = container_of(work, struct hinic3_nic_dev, rx_mode_work); 391 + netdev = nic_dev->netdev; 392 + 393 + if (test_and_clear_bit(HINIC3_UPDATE_MAC_FILTER, &nic_dev->flags)) { 394 + hinic3_update_mac_filter(netdev, &netdev->uc, 395 + &nic_dev->uc_filter_list); 396 + hinic3_update_mac_filter(netdev, &netdev->mc, 397 + &nic_dev->mc_filter_list); 398 + } 399 + 400 + hinic3_mac_filter_sync_all(netdev); 401 + 402 + if (hinic3_test_support(nic_dev, HINIC3_NIC_F_PROMISC)) 403 + promisc_en = !!(netdev->flags & IFF_PROMISC) || 404 + test_bit(HINIC3_PROMISC_FORCE_ON, 405 + &nic_dev->rx_mod_state); 406 + 407 + if (hinic3_test_support(nic_dev, HINIC3_NIC_F_ALLMULTI)) 408 + allmulti_en = !!(netdev->flags & IFF_ALLMULTI) || 409 + test_bit(HINIC3_ALLMULTI_FORCE_ON, 410 + &nic_dev->rx_mod_state); 411 + 412 + if (promisc_en != test_bit(HINIC3_HW_PROMISC_ON, 413 + &nic_dev->rx_mod_state) || 414 + allmulti_en != test_bit(HINIC3_HW_ALLMULTI_ON, 415 + &nic_dev->rx_mod_state)) 416 + hinic3_sync_rx_mode_to_hw(netdev, promisc_en, allmulti_en); 417 + }
+115
drivers/net/ethernet/huawei/hinic3/hinic3_hw_comm.c
··· 9 9 #include "hinic3_hwif.h" 10 10 #include "hinic3_mbox.h" 11 11 12 + static int hinic3_get_interrupt_cfg(struct hinic3_hwdev *hwdev, 13 + struct hinic3_interrupt_info *info) 14 + { 15 + struct comm_cmd_cfg_msix_ctrl_reg msix_cfg = {}; 16 + struct mgmt_msg_params msg_params = {}; 17 + int err; 18 + 19 + msix_cfg.func_id = hinic3_global_func_id(hwdev); 20 + msix_cfg.msix_index = info->msix_index; 21 + msix_cfg.opcode = MGMT_MSG_CMD_OP_GET; 22 + 23 + mgmt_msg_params_init_default(&msg_params, &msix_cfg, sizeof(msix_cfg)); 24 + 25 + err = hinic3_send_mbox_to_mgmt(hwdev, MGMT_MOD_COMM, 26 + COMM_CMD_CFG_MSIX_CTRL_REG, &msg_params); 27 + if (err || msix_cfg.head.status) { 28 + dev_err(hwdev->dev, "Failed to get interrupt config, err: %d, status: 0x%x\n", 29 + err, msix_cfg.head.status); 30 + return -EFAULT; 31 + } 32 + 33 + info->lli_credit_limit = msix_cfg.lli_credit_cnt; 34 + info->lli_timer_cfg = msix_cfg.lli_timer_cnt; 35 + info->pending_limit = msix_cfg.pending_cnt; 36 + info->coalesc_timer_cfg = msix_cfg.coalesce_timer_cnt; 37 + info->resend_timer_cfg = msix_cfg.resend_timer_cnt; 38 + 39 + return 0; 40 + } 41 + 12 42 int hinic3_set_interrupt_cfg_direct(struct hinic3_hwdev *hwdev, 13 43 const struct hinic3_interrupt_info *info) 14 44 { ··· 68 38 } 69 39 70 40 return 0; 41 + } 42 + 43 + int hinic3_set_interrupt_cfg(struct hinic3_hwdev *hwdev, 44 + struct hinic3_interrupt_info info) 45 + { 46 + struct hinic3_interrupt_info temp_info; 47 + int err; 48 + 49 + temp_info.msix_index = info.msix_index; 50 + 51 + err = hinic3_get_interrupt_cfg(hwdev, &temp_info); 52 + if (err) 53 + return err; 54 + 55 + info.lli_credit_limit = temp_info.lli_credit_limit; 56 + info.lli_timer_cfg = temp_info.lli_timer_cfg; 57 + 58 + if (!info.interrupt_coalesc_set) { 59 + info.pending_limit = temp_info.pending_limit; 60 + info.coalesc_timer_cfg = temp_info.coalesc_timer_cfg; 61 + info.resend_timer_cfg = temp_info.resend_timer_cfg; 62 + } 63 + 64 + return hinic3_set_interrupt_cfg_direct(hwdev, &info); 71 65 } 72 66 73 67 int hinic3_func_reset(struct hinic3_hwdev *hwdev, u16 func_id, u64 reset_flag) ··· 368 314 ret = -EFAULT; 369 315 } 370 316 317 + hinic3_set_pf_status(hwif, HINIC3_PF_STATUS_FLR_START_FLAG); 318 + 371 319 clr_res.func_id = hwif->attr.func_global_idx; 372 320 msg_params.buf_in = &clr_res; 373 321 msg_params.in_size = sizeof(clr_res); ··· 391 335 } 392 336 393 337 return ret; 338 + } 339 + 340 + int hinic3_set_bdf_ctxt(struct hinic3_hwdev *hwdev, 341 + struct comm_cmd_bdf_info *bdf_info) 342 + { 343 + struct mgmt_msg_params msg_params = {}; 344 + int err; 345 + 346 + mgmt_msg_params_init_default(&msg_params, bdf_info, sizeof(*bdf_info)); 347 + 348 + err = hinic3_send_mbox_to_mgmt(hwdev, MGMT_MOD_COMM, 349 + COMM_CMD_SEND_BDF_INFO, &msg_params); 350 + if (err || bdf_info->head.status) { 351 + dev_err(hwdev->dev, 352 + "Failed to set bdf info to fw, err: %d, status: 0x%x\n", 353 + err, bdf_info->head.status); 354 + return -EFAULT; 355 + } 356 + 357 + return 0; 358 + } 359 + 360 + static int hinic3_sync_time(struct hinic3_hwdev *hwdev, u64 time) 361 + { 362 + struct comm_cmd_sync_time time_info = {}; 363 + struct mgmt_msg_params msg_params = {}; 364 + int err; 365 + 366 + time_info.mstime = time; 367 + 368 + mgmt_msg_params_init_default(&msg_params, &time_info, 369 + sizeof(time_info)); 370 + 371 + err = hinic3_send_mbox_to_mgmt(hwdev, MGMT_MOD_COMM, 372 + COMM_CMD_SYNC_TIME, &msg_params); 373 + if (err || time_info.head.status) { 374 + dev_err(hwdev->dev, 375 + "Failed to sync time to mgmt, err: %d, status: 0x%x\n", 376 + err, time_info.head.status); 377 + return -EFAULT; 378 + } 379 + 380 + return 0; 381 + } 382 + 383 + void hinic3_sync_time_to_fw(struct hinic3_hwdev *hwdev) 384 + { 385 + struct timespec64 ts = {}; 386 + u64 time; 387 + int err; 388 + 389 + ktime_get_real_ts64(&ts); 390 + time = (u64)(ts.tv_sec * MSEC_PER_SEC + ts.tv_nsec / NSEC_PER_MSEC); 391 + 392 + err = hinic3_sync_time(hwdev, time); 393 + if (err) 394 + dev_err(hwdev->dev, 395 + "Synchronize UTC time to firmware failed, err=%d\n", 396 + err); 394 397 } 395 398 396 399 static int get_hw_rx_buf_size_idx(int rx_buf_sz, u16 *buf_sz_idx)
+6
drivers/net/ethernet/huawei/hinic3/hinic3_hw_comm.h
··· 23 23 24 24 int hinic3_set_interrupt_cfg_direct(struct hinic3_hwdev *hwdev, 25 25 const struct hinic3_interrupt_info *info); 26 + int hinic3_set_interrupt_cfg(struct hinic3_hwdev *hwdev, 27 + struct hinic3_interrupt_info info); 26 28 int hinic3_func_reset(struct hinic3_hwdev *hwdev, u16 func_id, u64 reset_flag); 27 29 28 30 int hinic3_get_comm_features(struct hinic3_hwdev *hwdev, u64 *s_feature, ··· 42 40 u32 page_size); 43 41 int hinic3_set_cmdq_depth(struct hinic3_hwdev *hwdev, u16 cmdq_depth); 44 42 int hinic3_func_rx_tx_flush(struct hinic3_hwdev *hwdev); 43 + int hinic3_set_bdf_ctxt(struct hinic3_hwdev *hwdev, 44 + struct comm_cmd_bdf_info *bdf_info); 45 + void hinic3_sync_time_to_fw(struct hinic3_hwdev *hwdev); 46 + 45 47 int hinic3_set_root_ctxt(struct hinic3_hwdev *hwdev, u32 rq_depth, u32 sq_depth, 46 48 int rx_buf_sz); 47 49 int hinic3_clean_root_ctxt(struct hinic3_hwdev *hwdev);
+24
drivers/net/ethernet/huawei/hinic3/hinic3_hw_intf.h
··· 39 39 /* Configuration module */ 40 40 MGMT_MOD_CFGM = 7, 41 41 MGMT_MOD_HILINK = 14, 42 + /* hardware max module id */ 43 + MGMT_MOD_HW_MAX = 20, 42 44 }; 43 45 44 46 static inline void mgmt_msg_params_init_default(struct mgmt_msg_params *msg_params, ··· 112 110 COMM_CMD_CFG_MSIX_CTRL_REG = 23, 113 111 COMM_CMD_SET_CEQ_CTRL_REG = 24, 114 112 COMM_CMD_SET_DMA_ATTR = 25, 113 + 114 + /* Commands for obtaining information */ 115 + COMM_CMD_SYNC_TIME = 62, 116 + COMM_CMD_SEND_BDF_INFO = 64, 115 117 }; 116 118 117 119 struct comm_cmd_cfg_msix_ctrl_reg { ··· 255 249 struct mgmt_msg_head head; 256 250 u16 func_id; 257 251 u16 rsvd1[3]; 252 + }; 253 + 254 + struct comm_cmd_sync_time { 255 + struct mgmt_msg_head head; 256 + 257 + u64 mstime; 258 + u64 rsvd1; 259 + }; 260 + 261 + struct comm_cmd_bdf_info { 262 + struct mgmt_msg_head head; 263 + 264 + u16 function_idx; 265 + u8 rsvd1[2]; 266 + u8 bus; 267 + u8 device; 268 + u8 function; 269 + u8 rsvd2[5]; 258 270 }; 259 271 260 272 /* Services supported by HW. HW uses these values when delivering events.
+94 -3
drivers/net/ethernet/huawei/hinic3/hinic3_hwdev.c
··· 13 13 #define HINIC3_PCIE_SNOOP 0 14 14 #define HINIC3_PCIE_TPH_DISABLE 0 15 15 16 + #define HINIC3_SYNFW_TIME_PERIOD (60 * 60 * 1000) 17 + 16 18 #define HINIC3_DMA_ATTR_INDIR_IDX_MASK GENMASK(9, 0) 17 19 #define HINIC3_DMA_ATTR_INDIR_IDX_SET(val, member) \ 18 20 FIELD_PREP(HINIC3_DMA_ATTR_INDIR_##member##_MASK, val) ··· 40 38 #define HINIC3_WQ_MAX_REQ 10 41 39 42 40 enum hinic3_hwdev_init_state { 41 + HINIC3_HWDEV_MGMT_INITED = 1, 43 42 HINIC3_HWDEV_MBOX_INITED = 2, 44 43 HINIC3_HWDEV_CMDQ_INITED = 3, 45 44 }; ··· 200 197 for (q_id = 0; q_id < ceqs->num_ceqs; q_id++) { 201 198 eq = &ceqs->ceq[q_id]; 202 199 info.msix_index = eq->msix_entry_idx; 203 - err = hinic3_set_interrupt_cfg_direct(hwdev, &info); 200 + err = hinic3_set_interrupt_cfg(hwdev, info); 204 201 if (err) { 205 202 dev_err(hwdev->dev, "Set msix attr for ceq %u failed\n", 206 203 q_id); ··· 209 206 } 210 207 211 208 return 0; 209 + } 210 + 211 + static int hinic3_comm_pf_to_mgmt_init(struct hinic3_hwdev *hwdev) 212 + { 213 + int err; 214 + 215 + if (HINIC3_IS_VF(hwdev)) 216 + return 0; 217 + 218 + err = hinic3_pf_to_mgmt_init(hwdev); 219 + if (err) 220 + return err; 221 + 222 + set_bit(HINIC3_HWDEV_MGMT_INITED, &hwdev->func_state); 223 + 224 + return 0; 225 + } 226 + 227 + static void hinic3_comm_pf_to_mgmt_free(struct hinic3_hwdev *hwdev) 228 + { 229 + if (HINIC3_IS_VF(hwdev)) 230 + return; 231 + 232 + spin_lock_bh(&hwdev->channel_lock); 233 + clear_bit(HINIC3_HWDEV_MGMT_INITED, &hwdev->func_state); 234 + spin_unlock_bh(&hwdev->channel_lock); 235 + 236 + hinic3_aeq_unregister_cb(hwdev, HINIC3_MSG_FROM_FW); 237 + 238 + hinic3_pf_to_mgmt_free(hwdev); 212 239 } 213 240 214 241 static int init_basic_mgmt_channel(struct hinic3_hwdev *hwdev) ··· 442 409 if (err) 443 410 return err; 444 411 445 - err = init_basic_attributes(hwdev); 412 + err = hinic3_comm_pf_to_mgmt_init(hwdev); 446 413 if (err) 447 414 goto err_free_basic_mgmt_ch; 415 + 416 + err = init_basic_attributes(hwdev); 417 + if (err) 418 + goto err_free_comm_pf_to_mgmt; 448 419 449 420 err = init_cmdqs_channel(hwdev); 450 421 if (err) { ··· 456 419 goto err_clear_func_svc_used_state; 457 420 } 458 421 422 + hinic3_set_pf_status(hwdev->hwif, HINIC3_PF_STATUS_ACTIVE_FLAG); 423 + 459 424 return 0; 460 425 461 426 err_clear_func_svc_used_state: 462 427 hinic3_set_func_svc_used_state(hwdev, COMM_FUNC_SVC_T_COMM, 0); 428 + err_free_comm_pf_to_mgmt: 429 + hinic3_comm_pf_to_mgmt_free(hwdev); 463 430 err_free_basic_mgmt_ch: 464 431 free_base_mgmt_channel(hwdev); 465 432 ··· 472 431 473 432 static void hinic3_uninit_comm_ch(struct hinic3_hwdev *hwdev) 474 433 { 434 + hinic3_set_pf_status(hwdev->hwif, HINIC3_PF_STATUS_INIT); 475 435 hinic3_free_cmdqs_channel(hwdev); 476 436 hinic3_set_func_svc_used_state(hwdev, COMM_FUNC_SVC_T_COMM, 0); 437 + hinic3_comm_pf_to_mgmt_free(hwdev); 477 438 free_base_mgmt_channel(hwdev); 439 + } 440 + 441 + static void hinic3_auto_sync_time_work(struct work_struct *work) 442 + { 443 + struct delayed_work *delay = to_delayed_work(work); 444 + struct hinic3_hwdev *hwdev; 445 + 446 + hwdev = container_of(delay, struct hinic3_hwdev, sync_time_task); 447 + 448 + hinic3_sync_time_to_fw(hwdev); 449 + 450 + queue_delayed_work(hwdev->workq, &hwdev->sync_time_task, 451 + msecs_to_jiffies(HINIC3_SYNFW_TIME_PERIOD)); 452 + } 453 + 454 + static void hinic3_init_ppf_work(struct hinic3_hwdev *hwdev) 455 + { 456 + if (hinic3_ppf_idx(hwdev) != hinic3_global_func_id(hwdev)) 457 + return; 458 + 459 + INIT_DELAYED_WORK(&hwdev->sync_time_task, hinic3_auto_sync_time_work); 460 + queue_delayed_work(hwdev->workq, &hwdev->sync_time_task, 461 + msecs_to_jiffies(HINIC3_SYNFW_TIME_PERIOD)); 462 + } 463 + 464 + static void hinic3_free_ppf_work(struct hinic3_hwdev *hwdev) 465 + { 466 + if (hinic3_ppf_idx(hwdev) != hinic3_global_func_id(hwdev)) 467 + return; 468 + 469 + disable_delayed_work_sync(&hwdev->sync_time_task); 478 470 } 479 471 480 472 static DEFINE_IDA(hinic3_adev_ida); ··· 572 498 goto err_uninit_comm_ch; 573 499 } 574 500 501 + hinic3_init_ppf_work(hwdev); 502 + 575 503 err = hinic3_set_comm_features(hwdev, hwdev->features, 576 504 COMM_MAX_FEATURE_QWORD); 577 505 if (err) { 578 506 dev_err(hwdev->dev, "Failed to set comm features\n"); 579 - goto err_uninit_comm_ch; 507 + goto err_free_ppf_work; 580 508 } 581 509 582 510 return 0; 583 511 512 + err_free_ppf_work: 513 + hinic3_free_ppf_work(hwdev); 584 514 err_uninit_comm_ch: 585 515 hinic3_uninit_comm_ch(hwdev); 586 516 err_free_cfg_mgmt: ··· 606 528 u64 drv_features[COMM_MAX_FEATURE_QWORD] = {}; 607 529 608 530 hinic3_set_comm_features(hwdev, drv_features, COMM_MAX_FEATURE_QWORD); 531 + hinic3_free_ppf_work(hwdev); 609 532 hinic3_func_rx_tx_flush(hwdev); 610 533 hinic3_uninit_comm_ch(hwdev); 611 534 hinic3_free_cfg_mgmt(hwdev); ··· 618 539 619 540 void hinic3_set_api_stop(struct hinic3_hwdev *hwdev) 620 541 { 542 + struct hinic3_recv_msg *recv_resp_msg; 621 543 struct hinic3_mbox *mbox; 622 544 623 545 spin_lock_bh(&hwdev->channel_lock); 546 + if (HINIC3_IS_PF(hwdev) && 547 + test_bit(HINIC3_HWDEV_MGMT_INITED, &hwdev->func_state)) { 548 + recv_resp_msg = &hwdev->pf_to_mgmt->recv_resp_msg_from_mgmt; 549 + spin_lock_bh(&hwdev->pf_to_mgmt->sync_event_lock); 550 + if (hwdev->pf_to_mgmt->event_flag == COMM_SEND_EVENT_START) { 551 + complete(&recv_resp_msg->recv_done); 552 + hwdev->pf_to_mgmt->event_flag = COMM_SEND_EVENT_TIMEOUT; 553 + } 554 + spin_unlock_bh(&hwdev->pf_to_mgmt->sync_event_lock); 555 + } 556 + 624 557 if (test_bit(HINIC3_HWDEV_MBOX_INITED, &hwdev->func_state)) { 625 558 mbox = hwdev->mbox; 626 559 spin_lock(&mbox->mbox_lock);
+21
drivers/net/ethernet/huawei/hinic3/hinic3_hwdev.h
··· 17 17 HINIC3_EVENT_SRV_NIC = 1 18 18 }; 19 19 20 + enum hinic3_comm_event_type { 21 + HINIC3_COMM_EVENT_PCIE_LINK_DOWN = 0, 22 + HINIC3_COMM_EVENT_HEART_LOST = 1, 23 + HINIC3_COMM_EVENT_FAULT = 2, 24 + HINIC3_COMM_EVENT_SRIOV_STATE_CHANGE = 3, 25 + HINIC3_COMM_EVENT_CARD_REMOVE = 4, 26 + HINIC3_COMM_EVENT_MGMT_WATCHDOG = 5, 27 + }; 28 + 29 + enum hinic3_fault_err_level { 30 + HINIC3_FAULT_LEVEL_SERIOUS_FLR = 3, 31 + }; 32 + 33 + enum hinic3_fault_source_type { 34 + HINIC3_FAULT_SRC_HW_PHY_FAULT = 9, 35 + HINIC3_FAULT_SRC_TX_TIMEOUT = 22, 36 + }; 37 + 20 38 #define HINIC3_SRV_EVENT_TYPE(svc, type) (((svc) << 16) | (type)) 21 39 22 40 /* driver-specific data of pci_dev */ ··· 46 28 47 29 void __iomem *cfg_reg_base; 48 30 void __iomem *intr_reg_base; 31 + void __iomem *mgmt_reg_base; 49 32 void __iomem *db_base; 50 33 u64 db_dwqe_len; 51 34 u64 db_base_phy; ··· 67 48 struct hinic3_ceqs *ceqs; 68 49 struct hinic3_mbox *mbox; 69 50 struct hinic3_cmdqs *cmdqs; 51 + struct delayed_work sync_time_task; 70 52 struct workqueue_struct *workq; 53 + struct hinic3_msg_pf_to_mgmt *pf_to_mgmt; 71 54 /* protect channel init and uninit */ 72 55 spinlock_t channel_lock; 73 56 u64 features[COMM_MAX_FEATURE_QWORD];
+89 -1
drivers/net/ethernet/huawei/hinic3/hinic3_hwif.c
··· 31 31 #define HINIC3_AF0_GET(val, member) \ 32 32 FIELD_GET(HINIC3_AF0_##member##_MASK, val) 33 33 34 + #define HINIC3_AF1_PPF_IDX_MASK GENMASK(5, 0) 34 35 #define HINIC3_AF1_AEQS_PER_FUNC_MASK GENMASK(9, 8) 35 36 #define HINIC3_AF1_MGMT_INIT_STATUS_MASK BIT(30) 36 37 #define HINIC3_AF1_GET(val, member) \ ··· 41 40 #define HINIC3_AF2_IRQS_PER_FUNC_MASK GENMASK(26, 16) 42 41 #define HINIC3_AF2_GET(val, member) \ 43 42 FIELD_GET(HINIC3_AF2_##member##_MASK, val) 43 + 44 + #define HINIC3_AF3_GLOBAL_VF_ID_OF_PF_MASK GENMASK(27, 16) 45 + #define HINIC3_AF3_GET(val, member) \ 46 + FIELD_GET(HINIC3_AF3_##member##_MASK, val) 44 47 45 48 #define HINIC3_AF4_DOORBELL_CTRL_MASK BIT(0) 46 49 #define HINIC3_AF4_GET(val, member) \ ··· 59 54 #define HINIC3_AF6_PF_STATUS_MASK GENMASK(15, 0) 60 55 #define HINIC3_AF6_FUNC_MAX_SQ_MASK GENMASK(31, 23) 61 56 #define HINIC3_AF6_MSIX_FLEX_EN_MASK BIT(22) 57 + #define HINIC3_AF6_SET(val, member) \ 58 + FIELD_PREP(HINIC3_AF6_##member##_MASK, val) 62 59 #define HINIC3_AF6_GET(val, member) \ 63 60 FIELD_GET(HINIC3_AF6_##member##_MASK, val) 61 + 62 + #define HINIC3_PPF_ELECTION_IDX_MASK GENMASK(5, 0) 63 + #define HINIC3_PPF_ELECTION_SET(val, member) \ 64 + FIELD_PREP(HINIC3_PPF_ELECTION_##member##_MASK, val) 65 + #define HINIC3_PPF_ELECTION_GET(val, member) \ 66 + FIELD_GET(HINIC3_PPF_ELECTION_##member##_MASK, val) 64 67 65 68 #define HINIC3_GET_REG_ADDR(reg) ((reg) & (HINIC3_REGS_FLAG_MASK)) 66 69 ··· 118 105 attr->pci_intf_idx = HINIC3_AF0_GET(attr0, PCI_INTF_IDX); 119 106 attr->func_type = HINIC3_AF0_GET(attr0, FUNC_TYPE); 120 107 108 + attr->ppf_idx = HINIC3_AF1_GET(attr1, PPF_IDX); 121 109 attr->num_aeqs = BIT(HINIC3_AF1_GET(attr1, AEQS_PER_FUNC)); 122 110 attr->num_ceqs = HINIC3_AF2_GET(attr2, CEQS_PER_FUNC); 123 111 attr->num_irqs = HINIC3_AF2_GET(attr2, IRQS_PER_FUNC); 124 112 if (attr->num_irqs > HINIC3_MAX_MSIX_ENTRY) 125 113 attr->num_irqs = HINIC3_MAX_MSIX_ENTRY; 114 + 115 + attr->global_vf_id_of_pf = HINIC3_AF3_GET(attr3, GLOBAL_VF_ID_OF_PF); 126 116 127 117 attr->num_sq = HINIC3_AF6_GET(attr6, FUNC_MAX_SQ); 128 118 attr->msix_flex_en = HINIC3_AF6_GET(attr6, MSIX_FLEX_EN); ··· 201 185 attr4 |= HINIC3_AF4_SET(flag, DOORBELL_CTRL); 202 186 203 187 hinic3_hwif_write_reg(hwif, addr, attr4); 188 + } 189 + 190 + static void hinic3_set_ppf(struct hinic3_hwdev *hwdev) 191 + { 192 + struct hinic3_hwif *hwif = hwdev->hwif; 193 + struct hinic3_func_attr *attr; 194 + u32 addr, val; 195 + 196 + if (HINIC3_IS_VF(hwdev)) 197 + return; 198 + 199 + /* Read Modify Write */ 200 + attr = &hwif->attr; 201 + addr = HINIC3_CSR_PPF_ELECTION_ADDR; 202 + val = hinic3_hwif_read_reg(hwif, addr); 203 + val &= ~HINIC3_PPF_ELECTION_IDX_MASK; 204 + val |= HINIC3_PPF_ELECTION_SET(attr->func_global_idx, IDX); 205 + hinic3_hwif_write_reg(hwif, addr, val); 206 + 207 + /* Check PPF index */ 208 + val = hinic3_hwif_read_reg(hwif, addr); 209 + attr->ppf_idx = HINIC3_PPF_ELECTION_GET(val, IDX); 204 210 } 205 211 206 212 static int db_area_idx_init(struct hinic3_hwif *hwif, u64 db_base_phy, ··· 404 366 USEC_PER_MSEC); 405 367 } 406 368 369 + void hinic3_set_pf_status(struct hinic3_hwif *hwif, 370 + enum hinic3_pf_status status) 371 + { 372 + u32 attr6 = hinic3_hwif_read_reg(hwif, HINIC3_CSR_FUNC_ATTR6_ADDR); 373 + 374 + attr6 &= ~HINIC3_AF6_PF_STATUS_MASK; 375 + attr6 |= HINIC3_AF6_SET(status, PF_STATUS); 376 + 377 + if (hwif->attr.func_type == HINIC3_FUNC_TYPE_VF) 378 + return; 379 + 380 + hinic3_hwif_write_reg(hwif, HINIC3_CSR_FUNC_ATTR6_ADDR, attr6); 381 + } 382 + 383 + enum hinic3_pf_status hinic3_get_pf_status(struct hinic3_hwif *hwif) 384 + { 385 + u32 attr6 = hinic3_hwif_read_reg(hwif, HINIC3_CSR_FUNC_ATTR6_ADDR); 386 + 387 + return HINIC3_AF6_GET(attr6, PF_STATUS); 388 + } 389 + 407 390 int hinic3_init_hwif(struct hinic3_hwdev *hwdev) 408 391 { 409 392 struct hinic3_pcidev *pci_adapter = hwdev->adapter; ··· 437 378 return -ENOMEM; 438 379 439 380 hwdev->hwif = hwif; 440 - hwif->cfg_regs_base = (u8 __iomem *)pci_adapter->cfg_reg_base + 381 + /* if function is VF, mgmt_regs_base will be NULL */ 382 + hwif->cfg_regs_base = pci_adapter->mgmt_reg_base ? 383 + pci_adapter->cfg_reg_base : 384 + (u8 __iomem *)pci_adapter->cfg_reg_base + 441 385 HINIC3_VF_CFG_REG_OFFSET; 386 + 387 + hwif->intr_regs_base = pci_adapter->intr_reg_base; 388 + hwif->mgmt_regs_base = pci_adapter->mgmt_reg_base; 442 389 443 390 err = db_area_idx_init(hwif, pci_adapter->db_base_phy, 444 391 pci_adapter->db_base, ··· 477 412 goto err_free_db_area_idx; 478 413 } 479 414 415 + hinic3_set_ppf(hwdev); 416 + 480 417 disable_all_msix(hwdev); 418 + /* disable mgmt cpu from reporting any event */ 419 + hinic3_set_pf_status(hwdev->hwif, HINIC3_PF_STATUS_INIT); 420 + 421 + dev_dbg(hwdev->dev, "global_func_idx: %u, func_type: %d, host_id: %u, ppf: %u\n", 422 + hwif->attr.func_global_idx, hwif->attr.func_type, 423 + hwif->attr.pci_intf_idx, hwif->attr.ppf_idx); 481 424 482 425 return 0; 483 426 ··· 506 433 u16 hinic3_global_func_id(struct hinic3_hwdev *hwdev) 507 434 { 508 435 return hwdev->hwif->attr.func_global_idx; 436 + } 437 + 438 + u8 hinic3_pf_id_of_vf(struct hinic3_hwdev *hwdev) 439 + { 440 + return hwdev->hwif->attr.port_to_port_idx; 441 + } 442 + 443 + u16 hinic3_glb_pf_vf_offset(struct hinic3_hwdev *hwdev) 444 + { 445 + return hwdev->hwif->attr.global_vf_id_of_pf; 446 + } 447 + 448 + u8 hinic3_ppf_idx(struct hinic3_hwdev *hwdev) 449 + { 450 + return hwdev->hwif->attr.ppf_idx; 509 451 }
+23
drivers/net/ethernet/huawei/hinic3/hinic3_hwif.h
··· 10 10 struct hinic3_hwdev; 11 11 12 12 enum hinic3_func_type { 13 + HINIC3_FUNC_TYPE_PF = 0, 13 14 HINIC3_FUNC_TYPE_VF = 1, 14 15 }; 15 16 ··· 39 38 40 39 struct hinic3_hwif { 41 40 u8 __iomem *cfg_regs_base; 41 + u8 __iomem *intr_regs_base; 42 + u8 __iomem *mgmt_regs_base; 42 43 u64 db_base_phy; 43 44 u64 db_dwqe_len; 44 45 u8 __iomem *db_base; ··· 51 48 enum hinic3_outbound_ctrl { 52 49 ENABLE_OUTBOUND = 0x0, 53 50 DISABLE_OUTBOUND = 0x1, 51 + }; 52 + 53 + enum hinic3_pf_status { 54 + HINIC3_PF_STATUS_INIT = 0x0, 55 + HINIC3_PF_STATUS_ACTIVE_FLAG = 0x11, 56 + HINIC3_PF_STATUS_FLR_START_FLAG = 0x12, 57 + HINIC3_PF_STATUS_FLR_FINISH_FLAG = 0x13, 54 58 }; 55 59 56 60 enum hinic3_doorbell_ctrl { ··· 75 65 HINIC3_SET_MSIX_AUTO_MASK, 76 66 }; 77 67 68 + #define HINIC3_FUNC_TYPE(hwdev) ((hwdev)->hwif->attr.func_type) 69 + #define HINIC3_IS_PF(hwdev) \ 70 + (HINIC3_FUNC_TYPE(hwdev) == HINIC3_FUNC_TYPE_PF) 71 + #define HINIC3_IS_VF(hwdev) \ 72 + (HINIC3_FUNC_TYPE(hwdev) == HINIC3_FUNC_TYPE_VF) 73 + 78 74 u32 hinic3_hwif_read_reg(struct hinic3_hwif *hwif, u32 reg); 79 75 void hinic3_hwif_write_reg(struct hinic3_hwif *hwif, u32 reg, u32 val); 80 76 ··· 90 74 int hinic3_alloc_db_addr(struct hinic3_hwdev *hwdev, void __iomem **db_base, 91 75 void __iomem **dwqe_base); 92 76 void hinic3_free_db_addr(struct hinic3_hwdev *hwdev, const u8 __iomem *db_base); 77 + 78 + void hinic3_set_pf_status(struct hinic3_hwif *hwif, 79 + enum hinic3_pf_status status); 80 + enum hinic3_pf_status hinic3_get_pf_status(struct hinic3_hwif *hwif); 93 81 94 82 int hinic3_init_hwif(struct hinic3_hwdev *hwdev); 95 83 void hinic3_free_hwif(struct hinic3_hwdev *hwdev); ··· 106 86 enum hinic3_msix_auto_mask flag); 107 87 108 88 u16 hinic3_global_func_id(struct hinic3_hwdev *hwdev); 89 + u8 hinic3_pf_id_of_vf(struct hinic3_hwdev *hwdev); 90 + u16 hinic3_glb_pf_vf_offset(struct hinic3_hwdev *hwdev); 91 + u8 hinic3_ppf_idx(struct hinic3_hwdev *hwdev); 109 92 110 93 #endif
+95 -2
drivers/net/ethernet/huawei/hinic3/hinic3_irq.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0 2 2 // Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved. 3 3 4 + #include <linux/dim.h> 4 5 #include <linux/netdevice.h> 5 6 6 7 #include "hinic3_hw_comm.h" ··· 10 9 #include "hinic3_nic_dev.h" 11 10 #include "hinic3_rx.h" 12 11 #include "hinic3_tx.h" 12 + 13 + #define HINIC3_COAL_PKT_SHIFT 5 14 + 15 + static void hinic3_net_dim(struct hinic3_nic_dev *nic_dev, 16 + struct hinic3_irq_cfg *irq_cfg) 17 + { 18 + struct hinic3_rxq *rxq = irq_cfg->rxq; 19 + struct dim_sample sample = {}; 20 + 21 + if (!test_bit(HINIC3_INTF_UP, &nic_dev->flags) || 22 + !nic_dev->adaptive_rx_coal) 23 + return; 24 + 25 + dim_update_sample(irq_cfg->total_events, rxq->rxq_stats.packets, 26 + rxq->rxq_stats.bytes, &sample); 27 + net_dim(&rxq->dim, &sample); 28 + } 13 29 14 30 static int hinic3_poll(struct napi_struct *napi, int budget) 15 31 { ··· 49 31 if (busy) 50 32 return budget; 51 33 52 - if (likely(napi_complete_done(napi, work_done))) 34 + if (likely(napi_complete_done(napi, work_done))) { 35 + hinic3_net_dim(nic_dev, irq_cfg); 53 36 hinic3_set_msix_state(nic_dev->hwdev, irq_cfg->msix_entry_idx, 54 37 HINIC3_MSIX_ENABLE); 38 + } 55 39 56 40 return work_done; 57 41 } ··· 90 70 hinic3_msix_intr_clear_resend_bit(nic_dev->hwdev, 91 71 irq_cfg->msix_entry_idx, 1); 92 72 73 + irq_cfg->total_events++; 74 + 93 75 napi_schedule(&irq_cfg->napi); 94 76 95 77 return IRQ_HANDLED; ··· 114 92 info.coalesc_timer_cfg = 115 93 nic_dev->intr_coalesce[q_id].coalesce_timer_cfg; 116 94 info.resend_timer_cfg = nic_dev->intr_coalesce[q_id].resend_timer_cfg; 117 - err = hinic3_set_interrupt_cfg_direct(nic_dev->hwdev, &info); 95 + err = hinic3_set_interrupt_cfg(nic_dev->hwdev, info); 118 96 if (err) { 119 97 netdev_err(netdev, "Failed to set RX interrupt coalescing attribute.\n"); 120 98 qp_del_napi(irq_cfg); ··· 137 115 { 138 116 irq_set_affinity_hint(irq_cfg->irq_id, NULL); 139 117 free_irq(irq_cfg->irq_id, irq_cfg); 118 + } 119 + 120 + static int hinic3_set_interrupt_moder(struct net_device *netdev, u16 q_id, 121 + u8 coalesc_timer_cfg, u8 pending_limit) 122 + { 123 + struct hinic3_nic_dev *nic_dev = netdev_priv(netdev); 124 + struct hinic3_interrupt_info info = {}; 125 + int err; 126 + 127 + if (q_id >= nic_dev->q_params.num_qps) 128 + return 0; 129 + 130 + info.interrupt_coalesc_set = 1; 131 + info.coalesc_timer_cfg = coalesc_timer_cfg; 132 + info.pending_limit = pending_limit; 133 + info.msix_index = nic_dev->q_params.irq_cfg[q_id].msix_entry_idx; 134 + info.resend_timer_cfg = 135 + nic_dev->intr_coalesce[q_id].resend_timer_cfg; 136 + 137 + err = hinic3_set_interrupt_cfg(nic_dev->hwdev, info); 138 + if (err) { 139 + netdev_err(netdev, 140 + "Failed to modify moderation for Queue: %u\n", q_id); 141 + } else { 142 + nic_dev->rxqs[q_id].last_coalesc_timer_cfg = coalesc_timer_cfg; 143 + nic_dev->rxqs[q_id].last_pending_limit = pending_limit; 144 + } 145 + 146 + return err; 147 + } 148 + 149 + static void hinic3_update_queue_coal(struct net_device *netdev, u16 q_id, 150 + u16 coal_timer, u16 coal_pkts) 151 + { 152 + struct hinic3_intr_coal_info *q_coal; 153 + u8 coalesc_timer_cfg, pending_limit; 154 + struct hinic3_nic_dev *nic_dev; 155 + 156 + nic_dev = netdev_priv(netdev); 157 + 158 + q_coal = &nic_dev->intr_coalesce[q_id]; 159 + coalesc_timer_cfg = (u8)coal_timer; 160 + pending_limit = clamp_t(u8, coal_pkts >> HINIC3_COAL_PKT_SHIFT, 161 + q_coal->rx_pending_limit_low, 162 + q_coal->rx_pending_limit_high); 163 + 164 + hinic3_set_interrupt_moder(nic_dev->netdev, q_id, 165 + coalesc_timer_cfg, pending_limit); 166 + } 167 + 168 + static void hinic3_rx_dim_work(struct work_struct *work) 169 + { 170 + struct dim_cq_moder cur_moder; 171 + struct hinic3_rxq *rxq; 172 + struct dim *dim; 173 + 174 + dim = container_of(work, struct dim, work); 175 + rxq = container_of(dim, struct hinic3_rxq, dim); 176 + 177 + cur_moder = net_dim_get_rx_moderation(dim->mode, dim->profile_ix); 178 + 179 + hinic3_update_queue_coal(rxq->netdev, rxq->q_id, 180 + cur_moder.usec, cur_moder.pkts); 181 + 182 + dim->state = DIM_START_MEASURE; 140 183 } 141 184 142 185 int hinic3_qps_irq_init(struct net_device *netdev) ··· 237 150 goto err_release_irqs; 238 151 } 239 152 153 + INIT_WORK(&irq_cfg->rxq->dim.work, hinic3_rx_dim_work); 154 + irq_cfg->rxq->dim.mode = DIM_CQ_PERIOD_MODE_START_FROM_CQE; 155 + 240 156 hinic3_set_msix_auto_mask_state(nic_dev->hwdev, 241 157 irq_cfg->msix_entry_idx, 242 158 HINIC3_SET_MSIX_AUTO_MASK); ··· 254 164 q_id--; 255 165 irq_cfg = &nic_dev->q_params.irq_cfg[q_id]; 256 166 qp_del_napi(irq_cfg); 167 + 257 168 hinic3_set_msix_state(nic_dev->hwdev, irq_cfg->msix_entry_idx, 258 169 HINIC3_MSIX_DISABLE); 259 170 hinic3_set_msix_auto_mask_state(nic_dev->hwdev, 260 171 irq_cfg->msix_entry_idx, 261 172 HINIC3_CLR_MSIX_AUTO_MASK); 262 173 hinic3_release_irq(irq_cfg); 174 + disable_work_sync(&irq_cfg->rxq->dim.work); 263 175 } 264 176 265 177 return err; ··· 282 190 irq_cfg->msix_entry_idx, 283 191 HINIC3_CLR_MSIX_AUTO_MASK); 284 192 hinic3_release_irq(irq_cfg); 193 + disable_work_sync(&irq_cfg->rxq->dim.work); 285 194 } 286 195 }
+50 -3
drivers/net/ethernet/huawei/hinic3/hinic3_lld.c
··· 5 5 #include <linux/iopoll.h> 6 6 7 7 #include "hinic3_hw_cfg.h" 8 + #include "hinic3_hw_comm.h" 8 9 #include "hinic3_hwdev.h" 10 + #include "hinic3_hwif.h" 9 11 #include "hinic3_lld.h" 10 12 #include "hinic3_mgmt.h" 11 13 #include "hinic3_pci_id_tbl.h" 12 14 13 15 #define HINIC3_VF_PCI_CFG_REG_BAR 0 16 + #define HINIC3_PF_PCI_CFG_REG_BAR 1 14 17 #define HINIC3_PCI_INTR_REG_BAR 2 18 + /* Only PF has mgmt bar */ 19 + #define HINIC3_PCI_MGMT_REG_BAR 3 15 20 #define HINIC3_PCI_DB_BAR 4 21 + 22 + #define HINIC3_IS_VF_DEV(pdev) ((pdev)->device == PCI_DEV_ID_HINIC3_VF) 16 23 17 24 #define HINIC3_EVENT_POLL_SLEEP_US 1000 18 25 #define HINIC3_EVENT_POLL_TIMEOUT_US 10000000 ··· 188 181 static int hinic3_mapping_bar(struct pci_dev *pdev, 189 182 struct hinic3_pcidev *pci_adapter) 190 183 { 191 - pci_adapter->cfg_reg_base = pci_ioremap_bar(pdev, 192 - HINIC3_VF_PCI_CFG_REG_BAR); 184 + int cfg_bar; 185 + 186 + cfg_bar = HINIC3_IS_VF_DEV(pdev) ? 187 + HINIC3_VF_PCI_CFG_REG_BAR : HINIC3_PF_PCI_CFG_REG_BAR; 188 + 189 + pci_adapter->cfg_reg_base = pci_ioremap_bar(pdev, cfg_bar); 193 190 if (!pci_adapter->cfg_reg_base) { 194 191 dev_err(&pdev->dev, "Failed to map configuration regs\n"); 195 192 return -ENOMEM; ··· 206 195 goto err_unmap_cfg_reg_base; 207 196 } 208 197 198 + if (!HINIC3_IS_VF_DEV(pdev)) { 199 + pci_adapter->mgmt_reg_base = 200 + pci_ioremap_bar(pdev, HINIC3_PCI_MGMT_REG_BAR); 201 + if (!pci_adapter->mgmt_reg_base) { 202 + dev_err(&pdev->dev, "Failed to map mgmt regs\n"); 203 + goto err_unmap_intr_reg_base; 204 + } 205 + } 206 + 209 207 pci_adapter->db_base_phy = pci_resource_start(pdev, HINIC3_PCI_DB_BAR); 210 208 pci_adapter->db_dwqe_len = pci_resource_len(pdev, HINIC3_PCI_DB_BAR); 211 209 pci_adapter->db_base = pci_ioremap_bar(pdev, HINIC3_PCI_DB_BAR); 212 210 if (!pci_adapter->db_base) { 213 211 dev_err(&pdev->dev, "Failed to map doorbell regs\n"); 214 - goto err_unmap_intr_reg_base; 212 + goto err_unmap_mgmt_reg_base; 215 213 } 216 214 217 215 return 0; 218 216 217 + err_unmap_mgmt_reg_base: 218 + if (!HINIC3_IS_VF_DEV(pdev)) 219 + iounmap(pci_adapter->mgmt_reg_base); 219 220 err_unmap_intr_reg_base: 220 221 iounmap(pci_adapter->intr_reg_base); 221 222 ··· 240 217 static void hinic3_unmapping_bar(struct hinic3_pcidev *pci_adapter) 241 218 { 242 219 iounmap(pci_adapter->db_base); 220 + if (!HINIC3_IS_VF_DEV(pci_adapter->pdev)) 221 + iounmap(pci_adapter->mgmt_reg_base); 243 222 iounmap(pci_adapter->intr_reg_base); 244 223 iounmap(pci_adapter->cfg_reg_base); 245 224 } ··· 320 295 return err; 321 296 } 322 297 298 + if (HINIC3_IS_PF(pci_adapter->hwdev)) 299 + hinic3_sync_time_to_fw(pci_adapter->hwdev); 300 + 323 301 err = hinic3_attach_aux_devices(pci_adapter->hwdev); 324 302 if (err) 325 303 goto err_free_hwdev; ··· 339 311 { 340 312 struct hinic3_pcidev *pci_adapter = pci_get_drvdata(pdev); 341 313 314 + /* disable mgmt reporting before flushing mgmt work-queue. */ 315 + hinic3_set_pf_status(pci_adapter->hwdev->hwif, HINIC3_PF_STATUS_INIT); 342 316 hinic3_flush_mgmt_workq(pci_adapter->hwdev); 343 317 hinic3_detach_aux_devices(pci_adapter->hwdev); 344 318 hinic3_free_hwdev(pci_adapter->hwdev); ··· 349 319 static int hinic3_probe_func(struct hinic3_pcidev *pci_adapter) 350 320 { 351 321 struct pci_dev *pdev = pci_adapter->pdev; 322 + struct comm_cmd_bdf_info bdf_info = {}; 352 323 int err; 353 324 354 325 err = hinic3_mapping_bar(pdev, pci_adapter); ··· 362 331 if (err) 363 332 goto err_unmap_bar; 364 333 334 + if (HINIC3_IS_PF(pci_adapter->hwdev)) { 335 + bdf_info.function_idx = 336 + hinic3_global_func_id(pci_adapter->hwdev); 337 + bdf_info.bus = pdev->bus->number; 338 + bdf_info.device = PCI_SLOT(pdev->devfn); 339 + bdf_info.function = PCI_FUNC(pdev->devfn); 340 + 341 + err = hinic3_set_bdf_ctxt(pci_adapter->hwdev, &bdf_info); 342 + if (err) { 343 + dev_err(&pdev->dev, "Failed to set BDF info to fw\n"); 344 + goto err_uninit_func; 345 + } 346 + } 347 + 365 348 return 0; 366 349 350 + err_uninit_func: 351 + hinic3_func_uninit(pdev); 367 352 err_unmap_bar: 368 353 hinic3_unmapping_bar(pci_adapter); 369 354
+169 -13
drivers/net/ethernet/huawei/hinic3/hinic3_main.c
··· 29 29 #define HINIC3_DEFAULT_TXRX_MSIX_COALESC_TIMER_CFG 25 30 30 #define HINIC3_DEFAULT_TXRX_MSIX_RESEND_TIMER_CFG 7 31 31 32 + #define HINIC3_RX_PENDING_LIMIT_LOW 2 33 + #define HINIC3_RX_PENDING_LIMIT_HIGH 8 34 + 32 35 static void init_intr_coal_param(struct net_device *netdev) 33 36 { 34 37 struct hinic3_nic_dev *nic_dev = netdev_priv(netdev); ··· 41 38 for (i = 0; i < nic_dev->max_qps; i++) { 42 39 info = &nic_dev->intr_coalesce[i]; 43 40 info->pending_limit = HINIC3_DEFAULT_TXRX_MSIX_PENDING_LIMIT; 44 - info->coalesce_timer_cfg = HINIC3_DEFAULT_TXRX_MSIX_COALESC_TIMER_CFG; 45 - info->resend_timer_cfg = HINIC3_DEFAULT_TXRX_MSIX_RESEND_TIMER_CFG; 41 + info->coalesce_timer_cfg = 42 + HINIC3_DEFAULT_TXRX_MSIX_COALESC_TIMER_CFG; 43 + info->resend_timer_cfg = 44 + HINIC3_DEFAULT_TXRX_MSIX_RESEND_TIMER_CFG; 45 + 46 + info->rx_pending_limit_high = HINIC3_RX_PENDING_LIMIT_HIGH; 47 + info->rx_pending_limit_low = HINIC3_RX_PENDING_LIMIT_LOW; 46 48 } 49 + 50 + nic_dev->adaptive_rx_coal = 1; 47 51 } 48 52 49 53 static int hinic3_init_intr_coalesce(struct net_device *netdev) ··· 118 108 hinic3_free_txqs(netdev); 119 109 } 120 110 111 + static void hinic3_periodic_work_handler(struct work_struct *work) 112 + { 113 + struct delayed_work *delay = to_delayed_work(work); 114 + struct hinic3_nic_dev *nic_dev; 115 + 116 + nic_dev = container_of(delay, struct hinic3_nic_dev, periodic_work); 117 + if (test_and_clear_bit(HINIC3_EVENT_WORK_TX_TIMEOUT, 118 + &nic_dev->event_flag)) 119 + dev_info(nic_dev->hwdev->dev, 120 + "Fault event report, src: %u, level: %u\n", 121 + HINIC3_FAULT_SRC_TX_TIMEOUT, 122 + HINIC3_FAULT_LEVEL_SERIOUS_FLR); 123 + 124 + queue_delayed_work(nic_dev->workq, &nic_dev->periodic_work, HZ); 125 + } 126 + 121 127 static int hinic3_init_nic_dev(struct net_device *netdev, 122 128 struct hinic3_hwdev *hwdev) 123 129 { ··· 147 121 148 122 nic_dev->rx_buf_len = HINIC3_RX_BUF_LEN; 149 123 nic_dev->lro_replenish_thld = HINIC3_LRO_REPLENISH_THLD; 124 + nic_dev->vlan_bitmap = kzalloc(HINIC3_VLAN_BITMAP_SIZE(nic_dev), 125 + GFP_KERNEL); 126 + if (!nic_dev->vlan_bitmap) 127 + return -ENOMEM; 128 + 150 129 nic_dev->nic_svc_cap = hwdev->cfg_mgmt->cap.nic_svc_cap; 130 + 131 + nic_dev->workq = create_singlethread_workqueue(HINIC3_NIC_DEV_WQ_NAME); 132 + if (!nic_dev->workq) { 133 + dev_err(hwdev->dev, "Failed to initialize nic workqueue\n"); 134 + kfree(nic_dev->vlan_bitmap); 135 + return -ENOMEM; 136 + } 137 + 138 + INIT_DELAYED_WORK(&nic_dev->periodic_work, 139 + hinic3_periodic_work_handler); 140 + 141 + INIT_LIST_HEAD(&nic_dev->uc_filter_list); 142 + INIT_LIST_HEAD(&nic_dev->mc_filter_list); 143 + INIT_WORK(&nic_dev->rx_mode_work, hinic3_set_rx_mode_work); 151 144 152 145 return 0; 153 146 } ··· 175 130 { 176 131 struct hinic3_nic_dev *nic_dev = netdev_priv(netdev); 177 132 struct hinic3_hwdev *hwdev = nic_dev->hwdev; 133 + u8 mac_addr[ETH_ALEN]; 178 134 int err; 135 + 136 + mutex_init(&nic_dev->port_state_mutex); 179 137 180 138 nic_dev->q_params.sq_depth = HINIC3_SQ_DEPTH; 181 139 nic_dev->q_params.rq_depth = HINIC3_RQ_DEPTH; 182 140 183 141 hinic3_try_to_enable_rss(netdev); 184 142 185 - /* VF driver always uses random MAC address. During VM migration to a 186 - * new device, the new device should learn the VMs old MAC rather than 187 - * provide its own MAC. The product design assumes that every VF is 188 - * suspectable to migration so the device avoids offering MAC address 189 - * to VFs. 190 - */ 191 - eth_hw_addr_random(netdev); 143 + if (HINIC3_IS_VF(hwdev)) { 144 + /* VF driver always uses random MAC address. During VM migration 145 + * to a new device, the new device should learn the VMs old MAC 146 + * rather than provide its own MAC. The product design assumes 147 + * that every VF is susceptible to migration so the device 148 + * avoids offering MAC address to VFs. 149 + */ 150 + eth_hw_addr_random(netdev); 151 + } else { 152 + err = hinic3_get_default_mac(hwdev, mac_addr); 153 + if (err) { 154 + dev_err(hwdev->dev, "Failed to get MAC address\n"); 155 + goto err_clear_rss_config; 156 + } 157 + eth_hw_addr_set(netdev, mac_addr); 158 + } 159 + 192 160 err = hinic3_set_mac(hwdev, netdev->dev_addr, 0, 193 161 hinic3_global_func_id(hwdev)); 194 - if (err) { 162 + /* Failure to set MAC is not a fatal error for VF since its MAC may have 163 + * already been set by PF 164 + */ 165 + if (err && err != -EADDRINUSE) { 195 166 dev_err(hwdev->dev, "Failed to set default MAC\n"); 196 167 goto err_clear_rss_config; 197 168 } ··· 234 173 struct hinic3_nic_dev *nic_dev = netdev_priv(netdev); 235 174 236 175 hinic3_free_txrxqs(netdev); 176 + hinic3_clean_mac_list_filter(netdev); 237 177 hinic3_del_mac(nic_dev->hwdev, netdev->dev_addr, 0, 238 178 hinic3_global_func_id(nic_dev->hwdev)); 239 179 hinic3_clear_rss_config(netdev); ··· 248 186 static void netdev_feature_init(struct net_device *netdev) 249 187 { 250 188 struct hinic3_nic_dev *nic_dev = netdev_priv(netdev); 189 + netdev_features_t hw_features = 0; 190 + netdev_features_t vlan_fts = 0; 251 191 netdev_features_t cso_fts = 0; 252 192 netdev_features_t tso_fts = 0; 253 193 netdev_features_t dft_fts; ··· 262 198 if (hinic3_test_support(nic_dev, HINIC3_NIC_F_TSO)) 263 199 tso_fts |= NETIF_F_TSO | NETIF_F_TSO6; 264 200 265 - netdev->features |= dft_fts | cso_fts | tso_fts; 201 + if (hinic3_test_support(nic_dev, HINIC3_NIC_F_RX_VLAN_STRIP | 202 + HINIC3_NIC_F_TX_VLAN_INSERT)) 203 + vlan_fts |= NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX; 204 + 205 + if (hinic3_test_support(nic_dev, HINIC3_NIC_F_RX_VLAN_FILTER)) 206 + vlan_fts |= NETIF_F_HW_VLAN_CTAG_FILTER; 207 + 208 + if (hinic3_test_support(nic_dev, HINIC3_NIC_F_VXLAN_OFFLOAD)) 209 + tso_fts |= NETIF_F_GSO_UDP_TUNNEL | NETIF_F_GSO_UDP_TUNNEL_CSUM; 210 + 211 + /* LRO is disabled by default, only set hw features */ 212 + if (hinic3_test_support(nic_dev, HINIC3_NIC_F_LRO)) 213 + hw_features |= NETIF_F_LRO; 214 + 215 + netdev->features |= dft_fts | cso_fts | tso_fts | vlan_fts; 216 + netdev->vlan_features |= dft_fts | cso_fts | tso_fts; 217 + hw_features |= netdev->hw_features | netdev->features; 218 + netdev->hw_features = hw_features; 219 + netdev->priv_flags |= IFF_UNICAST_FLT; 220 + 221 + netdev->hw_enc_features |= dft_fts; 222 + if (hinic3_test_support(nic_dev, HINIC3_NIC_F_VXLAN_OFFLOAD)) 223 + netdev->hw_enc_features |= cso_fts | tso_fts | NETIF_F_TSO_ECN; 266 224 } 267 225 268 226 static int hinic3_set_default_hw_feature(struct net_device *netdev) ··· 296 210 err = hinic3_set_nic_feature_to_hw(nic_dev); 297 211 if (err) { 298 212 dev_err(hwdev->dev, "Failed to set nic features\n"); 213 + return err; 214 + } 215 + 216 + err = hinic3_set_hw_features(netdev); 217 + if (err) { 218 + hinic3_update_nic_feature(nic_dev, 0); 219 + hinic3_set_nic_feature_to_hw(nic_dev); 299 220 return err; 300 221 } 301 222 ··· 331 238 } 332 239 } 333 240 241 + static void hinic3_port_module_event_handler(struct net_device *netdev, 242 + struct hinic3_event_info *event) 243 + { 244 + const char *g_hinic3_module_link_err[LINK_ERR_NUM] = { 245 + "Unrecognized module" 246 + }; 247 + struct hinic3_port_module_event *module_event; 248 + enum port_module_event_type type; 249 + enum link_err_type err_type; 250 + 251 + module_event = (struct hinic3_port_module_event *)event->event_data; 252 + type = module_event->type; 253 + err_type = module_event->err_type; 254 + 255 + switch (type) { 256 + case HINIC3_PORT_MODULE_CABLE_PLUGGED: 257 + case HINIC3_PORT_MODULE_CABLE_UNPLUGGED: 258 + netdev_info(netdev, "Port module event: Cable %s\n", 259 + type == HINIC3_PORT_MODULE_CABLE_PLUGGED ? 260 + "plugged" : "unplugged"); 261 + break; 262 + case HINIC3_PORT_MODULE_LINK_ERR: 263 + if (err_type >= LINK_ERR_NUM) { 264 + netdev_info(netdev, "Link failed, Unknown error type: 0x%x\n", 265 + err_type); 266 + } else { 267 + netdev_info(netdev, 268 + "Link failed, error type: 0x%x: %s\n", 269 + err_type, 270 + g_hinic3_module_link_err[err_type]); 271 + } 272 + break; 273 + default: 274 + netdev_err(netdev, "Unknown port module type %d\n", type); 275 + break; 276 + } 277 + } 278 + 334 279 static void hinic3_nic_event(struct auxiliary_device *adev, 335 280 struct hinic3_event_info *event) 336 281 { ··· 383 252 hinic3_link_status_change(netdev, true); 384 253 break; 385 254 case HINIC3_SRV_EVENT_TYPE(HINIC3_EVENT_SRV_NIC, 255 + HINIC3_NIC_EVENT_PORT_MODULE_EVENT): 256 + hinic3_port_module_event_handler(netdev, event); 257 + break; 258 + case HINIC3_SRV_EVENT_TYPE(HINIC3_EVENT_SRV_NIC, 386 259 HINIC3_NIC_EVENT_LINK_DOWN): 260 + case HINIC3_SRV_EVENT_TYPE(HINIC3_EVENT_SRV_COMM, 261 + HINIC3_COMM_EVENT_FAULT): 262 + case HINIC3_SRV_EVENT_TYPE(HINIC3_EVENT_SRV_COMM, 263 + HINIC3_COMM_EVENT_PCIE_LINK_DOWN): 264 + case HINIC3_SRV_EVENT_TYPE(HINIC3_EVENT_SRV_COMM, 265 + HINIC3_COMM_EVENT_HEART_LOST): 266 + case HINIC3_SRV_EVENT_TYPE(HINIC3_EVENT_SRV_COMM, 267 + HINIC3_COMM_EVENT_MGMT_WATCHDOG): 387 268 hinic3_link_status_change(netdev, false); 388 269 break; 389 270 default: 390 271 break; 391 272 } 273 + } 274 + 275 + static void hinic3_free_nic_dev(struct hinic3_nic_dev *nic_dev) 276 + { 277 + destroy_workqueue(nic_dev->workq); 278 + kfree(nic_dev->vlan_bitmap); 392 279 } 393 280 394 281 static int hinic3_nic_probe(struct auxiliary_device *adev, ··· 449 300 450 301 err = hinic3_init_nic_io(nic_dev); 451 302 if (err) 452 - goto err_free_netdev; 303 + goto err_free_nic_dev; 453 304 454 305 err = hinic3_sw_init(netdev); 455 306 if (err) ··· 462 313 if (err) 463 314 goto err_uninit_sw; 464 315 316 + queue_delayed_work(nic_dev->workq, &nic_dev->periodic_work, HZ); 465 317 netif_carrier_off(netdev); 466 318 467 319 err = register_netdev(netdev); ··· 472 322 return 0; 473 323 474 324 err_uninit_nic_feature: 325 + disable_delayed_work_sync(&nic_dev->periodic_work); 475 326 hinic3_update_nic_feature(nic_dev, 0); 476 327 hinic3_set_nic_feature_to_hw(nic_dev); 477 328 ··· 481 330 482 331 err_free_nic_io: 483 332 hinic3_free_nic_io(nic_dev); 484 - 333 + err_free_nic_dev: 334 + hinic3_free_nic_dev(nic_dev); 485 335 err_free_netdev: 486 336 free_netdev(netdev); 487 337 ··· 503 351 504 352 netdev = nic_dev->netdev; 505 353 unregister_netdev(netdev); 354 + 355 + disable_delayed_work_sync(&nic_dev->periodic_work); 356 + cancel_work_sync(&nic_dev->rx_mode_work); 357 + hinic3_free_nic_dev(nic_dev); 506 358 507 359 hinic3_update_nic_feature(nic_dev, 0); 508 360 hinic3_set_nic_feature_to_hw(nic_dev);
+45 -8
drivers/net/ethernet/huawei/hinic3/hinic3_mbox.c
··· 82 82 enum mbox_msg_direction_type dir, 83 83 u16 src_func_id) 84 84 { 85 + struct hinic3_hwdev *hwdev = mbox->hwdev; 85 86 struct hinic3_msg_channel *msg_ch; 86 87 87 - msg_ch = (src_func_id == MBOX_MGMT_FUNC_ID) ? 88 - &mbox->mgmt_msg : mbox->func_msg; 88 + if (src_func_id == MBOX_MGMT_FUNC_ID) { 89 + msg_ch = &mbox->mgmt_msg; 90 + } else if (HINIC3_IS_VF(hwdev)) { 91 + /* message from pf */ 92 + msg_ch = mbox->func_msg; 93 + if (src_func_id != hinic3_pf_id_of_vf(hwdev) || !msg_ch) 94 + return NULL; 95 + } else { 96 + return NULL; 97 + } 89 98 90 99 return (dir == MBOX_MSG_SEND) ? 91 100 &msg_ch->recv_msg : &msg_ch->resp_msg; ··· 200 191 dir = MBOX_MSG_HEADER_GET(mbox_header, DIRECTION); 201 192 src_func_id = MBOX_MSG_HEADER_GET(mbox_header, SRC_GLB_FUNC_IDX); 202 193 msg_desc = get_mbox_msg_desc(mbox, dir, src_func_id); 194 + if (!msg_desc) { 195 + dev_err(mbox->hwdev->dev, 196 + "Mailbox source function id: %u is invalid for current function\n", 197 + src_func_id); 198 + return; 199 + } 203 200 recv_mbox_handler(mbox, header, msg_desc); 204 201 } 205 202 ··· 424 409 if (err) 425 410 goto err_destroy_workqueue; 426 411 427 - err = hinic3_init_func_mbox_msg_channel(hwdev); 428 - if (err) 429 - goto err_uninit_mgmt_msg_ch; 412 + if (HINIC3_IS_VF(hwdev)) { 413 + /* VF to PF mbox message channel */ 414 + err = hinic3_init_func_mbox_msg_channel(hwdev); 415 + if (err) 416 + goto err_uninit_mgmt_msg_ch; 417 + } 430 418 431 419 err = alloc_mbox_wb_status(mbox); 432 420 if (err) { ··· 442 424 return 0; 443 425 444 426 err_uninit_func_mbox_msg_ch: 445 - hinic3_uninit_func_mbox_msg_channel(hwdev); 446 - 427 + if (HINIC3_IS_VF(hwdev)) 428 + hinic3_uninit_func_mbox_msg_channel(hwdev); 447 429 err_uninit_mgmt_msg_ch: 448 430 uninit_mgmt_msg_channel(mbox); 449 431 ··· 594 576 { 595 577 struct hinic3_hwif *hwif = mbox->hwdev->hwif; 596 578 u32 mbox_int, mbox_ctrl, tx_size; 579 + u16 func = dst_func; 597 580 581 + /* VF can send non-management messages only to PF. We set DST_FUNC field 582 + * to 0 since HW will ignore it anyway. 583 + */ 584 + if (HINIC3_IS_VF(mbox->hwdev) && dst_func != MBOX_MGMT_FUNC_ID) 585 + func = 0; 598 586 tx_size = ALIGN(seg_len + MBOX_HEADER_SZ, MBOX_SEG_LEN_ALIGN) >> 2; 599 587 600 588 mbox_int = MBOX_INT_SET(dst_aeqn, DST_AEQN) | ··· 611 587 612 588 mbox_ctrl = MBOX_CTRL_SET(1, TX_STATUS) | 613 589 MBOX_CTRL_SET(0, TRIGGER_AEQE) | 614 - MBOX_CTRL_SET(dst_func, DST_FUNC); 590 + MBOX_CTRL_SET(func, DST_FUNC); 615 591 616 592 hinic3_hwif_write_reg(hwif, HINIC3_FUNC_CSR_MAILBOX_INT_OFF, mbox_int); 617 593 hinic3_hwif_write_reg(hwif, HINIC3_FUNC_CSR_MAILBOX_CONTROL_OFF, ··· 862 838 mutex_unlock(&mbox->mbox_send_lock); 863 839 864 840 return err; 841 + } 842 + 843 + void hinic3_response_mbox_to_mgmt(struct hinic3_hwdev *hwdev, u8 mod, u16 cmd, 844 + const void *buf_in, u32 in_size, u16 msg_id) 845 + { 846 + struct mbox_msg_info msg_info; 847 + 848 + msg_info.msg_id = (u8)msg_id; 849 + msg_info.status = 0; 850 + 851 + send_mbox_msg(hwdev->mbox, mod, cmd, buf_in, in_size, 852 + MBOX_MGMT_FUNC_ID, MBOX_MSG_RESP, 853 + MBOX_MSG_NO_ACK, &msg_info); 865 854 } 866 855 867 856 int hinic3_send_mbox_to_mgmt_no_ack(struct hinic3_hwdev *hwdev, u8 mod, u16 cmd,
+2
drivers/net/ethernet/huawei/hinic3/hinic3_mbox.h
··· 135 135 136 136 int hinic3_send_mbox_to_mgmt(struct hinic3_hwdev *hwdev, u8 mod, u16 cmd, 137 137 const struct mgmt_msg_params *msg_params); 138 + void hinic3_response_mbox_to_mgmt(struct hinic3_hwdev *hwdev, u8 mod, u16 cmd, 139 + const void *buf_in, u32 in_size, u16 msg_id); 138 140 int hinic3_send_mbox_to_mgmt_no_ack(struct hinic3_hwdev *hwdev, u8 mod, u16 cmd, 139 141 const struct mgmt_msg_params *msg_params); 140 142
+312 -1
drivers/net/ethernet/huawei/hinic3/hinic3_mgmt.c
··· 3 3 4 4 #include "hinic3_eqs.h" 5 5 #include "hinic3_hwdev.h" 6 + #include "hinic3_hwif.h" 6 7 #include "hinic3_mbox.h" 7 8 #include "hinic3_mgmt.h" 9 + 10 + #define HINIC3_MSG_TO_MGMT_MAX_LEN 2016 11 + 12 + #define MGMT_MAX_PF_BUF_SIZE 2048UL 13 + #define MGMT_SEG_LEN_MAX 48 14 + #define MGMT_ASYNC_MSG_FLAG 0x8 15 + 16 + #define HINIC3_MGMT_WQ_NAME "hinic3_mgmt" 17 + 18 + /* Bogus sequence ID to prevent accidental match following partial message */ 19 + #define MGMT_BOGUS_SEQ_ID \ 20 + (MGMT_MAX_PF_BUF_SIZE / MGMT_SEG_LEN_MAX + 1) 21 + 22 + static void 23 + hinic3_mgmt_resp_msg_handler(struct hinic3_msg_pf_to_mgmt *pf_to_mgmt, 24 + struct hinic3_recv_msg *recv_msg) 25 + { 26 + struct device *dev = pf_to_mgmt->hwdev->dev; 27 + 28 + /* Ignore async msg */ 29 + if (recv_msg->msg_id & MGMT_ASYNC_MSG_FLAG) 30 + return; 31 + 32 + spin_lock(&pf_to_mgmt->sync_event_lock); 33 + if (recv_msg->msg_id != pf_to_mgmt->sync_msg_id) { 34 + dev_err(dev, "msg id mismatch, send msg id: 0x%x, recv msg id: 0x%x, event state: %d\n", 35 + pf_to_mgmt->sync_msg_id, recv_msg->msg_id, 36 + pf_to_mgmt->event_flag); 37 + } else if (pf_to_mgmt->event_flag == COMM_SEND_EVENT_START) { 38 + pf_to_mgmt->event_flag = COMM_SEND_EVENT_SUCCESS; 39 + complete(&recv_msg->recv_done); 40 + } else { 41 + dev_err(dev, "Wait timeout, send msg id: 0x%x, recv msg id: 0x%x, event state: %d\n", 42 + pf_to_mgmt->sync_msg_id, recv_msg->msg_id, 43 + pf_to_mgmt->event_flag); 44 + } 45 + spin_unlock(&pf_to_mgmt->sync_event_lock); 46 + } 47 + 48 + static void hinic3_recv_mgmt_msg_work_handler(struct work_struct *work) 49 + { 50 + struct hinic3_msg_pf_to_mgmt *pf_to_mgmt; 51 + struct mgmt_msg_handle_work *mgmt_work; 52 + struct mgmt_msg_head *ack_cmd; 53 + 54 + mgmt_work = container_of(work, struct mgmt_msg_handle_work, work); 55 + 56 + /* At the moment, we do not expect any meaningful messages but if the 57 + * sender expects an ACK we still need to provide one with "unsupported" 58 + * status. 59 + */ 60 + if (mgmt_work->async_mgmt_to_pf) 61 + goto out; 62 + 63 + pf_to_mgmt = mgmt_work->pf_to_mgmt; 64 + ack_cmd = pf_to_mgmt->mgmt_ack_buf; 65 + memset(ack_cmd, 0, sizeof(*ack_cmd)); 66 + ack_cmd->status = MGMT_STATUS_CMD_UNSUPPORTED; 67 + 68 + hinic3_response_mbox_to_mgmt(pf_to_mgmt->hwdev, mgmt_work->mod, 69 + mgmt_work->cmd, ack_cmd, sizeof(*ack_cmd), 70 + mgmt_work->msg_id); 71 + 72 + out: 73 + kfree(mgmt_work->msg); 74 + kfree(mgmt_work); 75 + } 76 + 77 + static int hinic3_recv_msg_add_seg(struct hinic3_recv_msg *recv_msg, 78 + __le64 msg_header, const void *seg_data, 79 + bool *is_complete) 80 + { 81 + u8 seq_id, msg_id, seg_len, is_last; 82 + char *msg_buff; 83 + u32 offset; 84 + 85 + seg_len = MBOX_MSG_HEADER_GET(msg_header, SEG_LEN); 86 + is_last = MBOX_MSG_HEADER_GET(msg_header, LAST); 87 + seq_id = MBOX_MSG_HEADER_GET(msg_header, SEQID); 88 + msg_id = MBOX_MSG_HEADER_GET(msg_header, MSG_ID); 89 + 90 + if (seg_len > MGMT_SEG_LEN_MAX) 91 + return -EINVAL; 92 + 93 + /* All segments but last must be of maximal size */ 94 + if (seg_len != MGMT_SEG_LEN_MAX && !is_last) 95 + return -EINVAL; 96 + 97 + if (seq_id == 0) { 98 + recv_msg->seq_id = seq_id; 99 + recv_msg->msg_id = msg_id; 100 + } else if (seq_id != recv_msg->seq_id + 1 || 101 + msg_id != recv_msg->msg_id) { 102 + return -EINVAL; 103 + } 104 + 105 + offset = seq_id * MGMT_SEG_LEN_MAX; 106 + if (offset + seg_len > MGMT_MAX_PF_BUF_SIZE) 107 + return -EINVAL; 108 + 109 + msg_buff = recv_msg->msg; 110 + memcpy(msg_buff + offset, seg_data, seg_len); 111 + recv_msg->msg_len = offset + seg_len; 112 + recv_msg->seq_id = seq_id; 113 + *is_complete = !!is_last; 114 + 115 + return 0; 116 + } 117 + 118 + static void hinic3_init_mgmt_msg_work(struct hinic3_msg_pf_to_mgmt *pf_to_mgmt, 119 + struct hinic3_recv_msg *recv_msg) 120 + { 121 + struct mgmt_msg_handle_work *mgmt_work; 122 + 123 + mgmt_work = kmalloc(sizeof(*mgmt_work), GFP_KERNEL); 124 + if (!mgmt_work) 125 + return; 126 + 127 + if (recv_msg->msg_len) { 128 + mgmt_work->msg = kmemdup(recv_msg->msg, recv_msg->msg_len, 129 + GFP_KERNEL); 130 + if (!mgmt_work->msg) { 131 + kfree(mgmt_work); 132 + return; 133 + } 134 + } else { 135 + mgmt_work->msg = NULL; 136 + } 137 + 138 + mgmt_work->pf_to_mgmt = pf_to_mgmt; 139 + mgmt_work->msg_len = recv_msg->msg_len; 140 + mgmt_work->msg_id = recv_msg->msg_id; 141 + mgmt_work->mod = recv_msg->mod; 142 + mgmt_work->cmd = recv_msg->cmd; 143 + mgmt_work->async_mgmt_to_pf = recv_msg->async_mgmt_to_pf; 144 + 145 + INIT_WORK(&mgmt_work->work, hinic3_recv_mgmt_msg_work_handler); 146 + queue_work(pf_to_mgmt->workq, &mgmt_work->work); 147 + } 148 + 149 + static void 150 + hinic3_recv_mgmt_msg_handler(struct hinic3_msg_pf_to_mgmt *pf_to_mgmt, 151 + const u8 *header, 152 + struct hinic3_recv_msg *recv_msg) 153 + { 154 + struct hinic3_hwdev *hwdev = pf_to_mgmt->hwdev; 155 + const void *seg_data; 156 + __le64 msg_header; 157 + bool is_complete; 158 + u8 dir, msg_id; 159 + int err; 160 + 161 + msg_header = *(__force __le64 *)header; 162 + dir = MBOX_MSG_HEADER_GET(msg_header, DIRECTION); 163 + msg_id = MBOX_MSG_HEADER_GET(msg_header, MSG_ID); 164 + /* Don't need to get anything from hw when cmd is async */ 165 + if (dir == MBOX_MSG_RESP && (msg_id & MGMT_ASYNC_MSG_FLAG)) 166 + return; 167 + 168 + seg_data = header + sizeof(msg_header); 169 + err = hinic3_recv_msg_add_seg(recv_msg, msg_header, 170 + seg_data, &is_complete); 171 + if (err) { 172 + dev_err(hwdev->dev, "invalid receive segment\n"); 173 + /* set seq_id to invalid seq_id */ 174 + recv_msg->seq_id = MGMT_BOGUS_SEQ_ID; 175 + 176 + return; 177 + } 178 + 179 + if (!is_complete) 180 + return; 181 + 182 + recv_msg->cmd = MBOX_MSG_HEADER_GET(msg_header, CMD); 183 + recv_msg->mod = MBOX_MSG_HEADER_GET(msg_header, MODULE); 184 + recv_msg->async_mgmt_to_pf = MBOX_MSG_HEADER_GET(msg_header, NO_ACK); 185 + recv_msg->seq_id = MGMT_BOGUS_SEQ_ID; 186 + 187 + if (dir == MBOX_MSG_RESP) 188 + hinic3_mgmt_resp_msg_handler(pf_to_mgmt, recv_msg); 189 + else 190 + hinic3_init_mgmt_msg_work(pf_to_mgmt, recv_msg); 191 + } 192 + 193 + static int alloc_recv_msg(struct hinic3_recv_msg *recv_msg) 194 + { 195 + recv_msg->seq_id = MGMT_BOGUS_SEQ_ID; 196 + 197 + recv_msg->msg = kzalloc(MGMT_MAX_PF_BUF_SIZE, GFP_KERNEL); 198 + if (!recv_msg->msg) 199 + return -ENOMEM; 200 + 201 + return 0; 202 + } 203 + 204 + static void free_recv_msg(struct hinic3_recv_msg *recv_msg) 205 + { 206 + kfree(recv_msg->msg); 207 + } 208 + 209 + static int alloc_msg_buf(struct hinic3_msg_pf_to_mgmt *pf_to_mgmt) 210 + { 211 + struct device *dev = pf_to_mgmt->hwdev->dev; 212 + int err; 213 + 214 + err = alloc_recv_msg(&pf_to_mgmt->recv_msg_from_mgmt); 215 + if (err) { 216 + dev_err(dev, "Failed to allocate recv msg\n"); 217 + return err; 218 + } 219 + 220 + err = alloc_recv_msg(&pf_to_mgmt->recv_resp_msg_from_mgmt); 221 + if (err) { 222 + dev_err(dev, "Failed to allocate resp recv msg\n"); 223 + goto err_free_msg_from_mgmt; 224 + } 225 + 226 + pf_to_mgmt->mgmt_ack_buf = kzalloc(MGMT_MAX_PF_BUF_SIZE, GFP_KERNEL); 227 + if (!pf_to_mgmt->mgmt_ack_buf) { 228 + err = -ENOMEM; 229 + goto err_free_resp_msg_from_mgmt; 230 + } 231 + 232 + return 0; 233 + 234 + err_free_resp_msg_from_mgmt: 235 + free_recv_msg(&pf_to_mgmt->recv_resp_msg_from_mgmt); 236 + err_free_msg_from_mgmt: 237 + free_recv_msg(&pf_to_mgmt->recv_msg_from_mgmt); 238 + 239 + return err; 240 + } 241 + 242 + static void free_msg_buf(struct hinic3_msg_pf_to_mgmt *pf_to_mgmt) 243 + { 244 + kfree(pf_to_mgmt->mgmt_ack_buf); 245 + 246 + free_recv_msg(&pf_to_mgmt->recv_resp_msg_from_mgmt); 247 + free_recv_msg(&pf_to_mgmt->recv_msg_from_mgmt); 248 + } 249 + 250 + int hinic3_pf_to_mgmt_init(struct hinic3_hwdev *hwdev) 251 + { 252 + struct hinic3_msg_pf_to_mgmt *pf_to_mgmt; 253 + int err; 254 + 255 + pf_to_mgmt = kzalloc(sizeof(*pf_to_mgmt), GFP_KERNEL); 256 + if (!pf_to_mgmt) 257 + return -ENOMEM; 258 + 259 + hwdev->pf_to_mgmt = pf_to_mgmt; 260 + pf_to_mgmt->hwdev = hwdev; 261 + spin_lock_init(&pf_to_mgmt->sync_event_lock); 262 + pf_to_mgmt->workq = create_singlethread_workqueue(HINIC3_MGMT_WQ_NAME); 263 + if (!pf_to_mgmt->workq) { 264 + dev_err(hwdev->dev, "Failed to initialize MGMT workqueue\n"); 265 + err = -ENOMEM; 266 + goto err_free_pf_to_mgmt; 267 + } 268 + 269 + err = alloc_msg_buf(pf_to_mgmt); 270 + if (err) { 271 + dev_err(hwdev->dev, "Failed to allocate msg buffers\n"); 272 + goto err_destroy_workqueue; 273 + } 274 + 275 + return 0; 276 + 277 + err_destroy_workqueue: 278 + destroy_workqueue(pf_to_mgmt->workq); 279 + err_free_pf_to_mgmt: 280 + kfree(pf_to_mgmt); 281 + 282 + return err; 283 + } 284 + 285 + void hinic3_pf_to_mgmt_free(struct hinic3_hwdev *hwdev) 286 + { 287 + struct hinic3_msg_pf_to_mgmt *pf_to_mgmt = hwdev->pf_to_mgmt; 288 + 289 + /* destroy workqueue before free related pf_to_mgmt resources in case of 290 + * illegal resource access 291 + */ 292 + destroy_workqueue(pf_to_mgmt->workq); 293 + 294 + free_msg_buf(pf_to_mgmt); 295 + kfree(pf_to_mgmt); 296 + } 8 297 9 298 void hinic3_flush_mgmt_workq(struct hinic3_hwdev *hwdev) 10 299 { 11 300 if (hwdev->aeqs) 12 301 flush_workqueue(hwdev->aeqs->workq); 302 + 303 + if (HINIC3_IS_PF(hwdev) && hwdev->pf_to_mgmt) 304 + flush_workqueue(hwdev->pf_to_mgmt->workq); 13 305 } 14 306 15 307 void hinic3_mgmt_msg_aeqe_handler(struct hinic3_hwdev *hwdev, u8 *header, 16 308 u8 size) 17 309 { 310 + struct hinic3_msg_pf_to_mgmt *pf_to_mgmt; 311 + struct hinic3_recv_msg *recv_msg; 312 + __le64 msg_header; 313 + bool is_send_dir; 314 + 18 315 if (MBOX_MSG_HEADER_GET(*(__force __le64 *)header, SOURCE) == 19 - MBOX_MSG_FROM_MBOX) 316 + MBOX_MSG_FROM_MBOX) { 20 317 hinic3_mbox_func_aeqe_handler(hwdev, header, size); 318 + 319 + return; 320 + } 321 + 322 + pf_to_mgmt = hwdev->pf_to_mgmt; 323 + msg_header = *(__force __le64 *)header; 324 + 325 + is_send_dir = (MBOX_MSG_HEADER_GET(msg_header, DIRECTION) == 326 + MBOX_MSG_SEND) ? true : false; 327 + 328 + recv_msg = is_send_dir ? &pf_to_mgmt->recv_msg_from_mgmt : 329 + &pf_to_mgmt->recv_resp_msg_from_mgmt; 330 + 331 + hinic3_recv_mgmt_msg_handler(pf_to_mgmt, header, recv_msg); 21 332 }
+53
drivers/net/ethernet/huawei/hinic3/hinic3_mgmt.h
··· 6 6 7 7 #include <linux/types.h> 8 8 9 + #include "hinic3_mbox.h" 10 + #include "hinic3_hw_intf.h" 11 + 9 12 struct hinic3_hwdev; 10 13 14 + struct hinic3_recv_msg { 15 + /* Preallocated buffer of size MAX_PF_MGMT_BUF_SIZE that accumulates 16 + * receive message, segment-by-segment. 17 + */ 18 + void *msg; 19 + /* Message id for which segments are accumulated. */ 20 + u8 msg_id; 21 + /* Sequence id of last received segment of current message. */ 22 + u8 seq_id; 23 + u16 msg_len; 24 + int async_mgmt_to_pf; 25 + enum mgmt_mod_type mod; 26 + u16 cmd; 27 + struct completion recv_done; 28 + }; 29 + 30 + enum comm_pf_to_mgmt_event_state { 31 + COMM_SEND_EVENT_UNINIT, 32 + COMM_SEND_EVENT_START, 33 + COMM_SEND_EVENT_SUCCESS, 34 + COMM_SEND_EVENT_TIMEOUT, 35 + }; 36 + 37 + struct hinic3_msg_pf_to_mgmt { 38 + struct hinic3_hwdev *hwdev; 39 + struct workqueue_struct *workq; 40 + void *mgmt_ack_buf; 41 + struct hinic3_recv_msg recv_msg_from_mgmt; 42 + struct hinic3_recv_msg recv_resp_msg_from_mgmt; 43 + u16 async_msg_id; 44 + u16 sync_msg_id; 45 + void *async_msg_cb_data[MGMT_MOD_HW_MAX]; 46 + /* synchronizes message send with message receives via event queue */ 47 + spinlock_t sync_event_lock; 48 + enum comm_pf_to_mgmt_event_state event_flag; 49 + }; 50 + 51 + struct mgmt_msg_handle_work { 52 + struct work_struct work; 53 + struct hinic3_msg_pf_to_mgmt *pf_to_mgmt; 54 + void *msg; 55 + u16 msg_len; 56 + enum mgmt_mod_type mod; 57 + u16 cmd; 58 + u16 msg_id; 59 + int async_mgmt_to_pf; 60 + }; 61 + 62 + int hinic3_pf_to_mgmt_init(struct hinic3_hwdev *hwdev); 63 + void hinic3_pf_to_mgmt_free(struct hinic3_hwdev *hwdev); 11 64 void hinic3_flush_mgmt_workq(struct hinic3_hwdev *hwdev); 12 65 void hinic3_mgmt_msg_aeqe_handler(struct hinic3_hwdev *hwdev, 13 66 u8 *header, u8 size);
+69
drivers/net/ethernet/huawei/hinic3/hinic3_mgmt_interface.h
··· 56 56 u8 new_mac[ETH_ALEN]; 57 57 }; 58 58 59 + struct l2nic_cmd_vlan_config { 60 + struct mgmt_msg_head msg_head; 61 + u16 func_id; 62 + u8 opcode; 63 + u8 rsvd1; 64 + u16 vlan_id; 65 + u16 rsvd2; 66 + }; 67 + 68 + struct l2nic_cmd_vlan_offload { 69 + struct mgmt_msg_head msg_head; 70 + u16 func_id; 71 + u8 vlan_offload; 72 + u8 rsvd1[5]; 73 + }; 74 + 75 + /* set vlan filter */ 76 + struct l2nic_cmd_set_vlan_filter { 77 + struct mgmt_msg_head msg_head; 78 + u16 func_id; 79 + u8 rsvd[2]; 80 + /* bit0:vlan filter en; bit1:broadcast_filter_en */ 81 + u32 vlan_filter_ctrl; 82 + }; 83 + 59 84 struct l2nic_cmd_set_ci_attr { 60 85 struct mgmt_msg_head msg_head; 61 86 u16 func_idx; ··· 115 90 u8 rsvd2[3]; 116 91 }; 117 92 93 + /* * 94 + * Definition of the NIC receiving mode 95 + */ 96 + #define L2NIC_RX_MODE_UC 0x01 97 + #define L2NIC_RX_MODE_MC 0x02 98 + #define L2NIC_RX_MODE_BC 0x04 99 + #define L2NIC_RX_MODE_MC_ALL 0x08 100 + #define L2NIC_RX_MODE_PROMISC 0x10 101 + 102 + struct l2nic_rx_mode_config { 103 + struct mgmt_msg_head msg_head; 104 + u16 func_id; 105 + u16 rsvd1; 106 + u32 rx_mode; 107 + }; 108 + 118 109 struct l2nic_cmd_set_dcb_state { 119 110 struct mgmt_msg_head head; 120 111 u16 func_id; ··· 141 100 /* 0 - disable, 1 - enable dcb */ 142 101 u8 port_state; 143 102 u8 rsvd[7]; 103 + }; 104 + 105 + struct l2nic_cmd_lro_config { 106 + struct mgmt_msg_head msg_head; 107 + u16 func_id; 108 + u8 opcode; 109 + u8 rsvd1; 110 + u8 lro_ipv4_en; 111 + u8 lro_ipv6_en; 112 + /* unit is 1K */ 113 + u8 lro_max_pkt_len; 114 + u8 resv2[13]; 115 + }; 116 + 117 + struct l2nic_cmd_lro_timer { 118 + struct mgmt_msg_head msg_head; 119 + /* 1: set timer value, 0: get timer value */ 120 + u8 opcode; 121 + u8 rsvd[3]; 122 + u32 timer; 144 123 }; 145 124 146 125 #define L2NIC_RSS_TYPE_VALID_MASK BIT(23) ··· 221 160 /* FUNC CFG */ 222 161 L2NIC_CMD_SET_FUNC_TBL = 5, 223 162 L2NIC_CMD_SET_VPORT_ENABLE = 6, 163 + L2NIC_CMD_SET_RX_MODE = 7, 224 164 L2NIC_CMD_SET_SQ_CI_ATTR = 8, 225 165 L2NIC_CMD_CLEAR_QP_RESOURCE = 11, 166 + L2NIC_CMD_CFG_RX_LRO = 13, 167 + L2NIC_CMD_CFG_LRO_TIMER = 14, 226 168 L2NIC_CMD_FEATURE_NEGO = 15, 169 + L2NIC_CMD_GET_MAC = 20, 227 170 L2NIC_CMD_SET_MAC = 21, 228 171 L2NIC_CMD_DEL_MAC = 22, 229 172 L2NIC_CMD_UPDATE_MAC = 23, 173 + L2NIC_CMD_CFG_FUNC_VLAN = 25, 174 + L2NIC_CMD_SET_VLAN_FILTER_EN = 26, 175 + L2NIC_CMD_SET_RX_VLAN_OFFLOAD = 27, 230 176 L2NIC_CMD_CFG_RSS = 60, 231 177 L2NIC_CMD_CFG_RSS_HASH_KEY = 63, 232 178 L2NIC_CMD_CFG_RSS_HASH_ENGINE = 64, ··· 257 189 258 190 /* hilink mac group command */ 259 191 enum mag_cmd { 192 + MAG_CMD_SET_PORT_ENABLE = 6, 260 193 MAG_CMD_GET_LINK_STATUS = 7, 261 194 }; 262 195
+376 -1
drivers/net/ethernet/huawei/hinic3/hinic3_netdev_ops.c
··· 2 2 // Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved. 3 3 4 4 #include <linux/etherdevice.h> 5 + #include <linux/if_vlan.h> 5 6 #include <linux/netdevice.h> 7 + #include <net/vxlan.h> 6 8 7 9 #include "hinic3_hwif.h" 8 10 #include "hinic3_nic_cfg.h" ··· 13 11 #include "hinic3_rss.h" 14 12 #include "hinic3_rx.h" 15 13 #include "hinic3_tx.h" 14 + 15 + #define HINIC3_LRO_DEFAULT_COAL_PKT_SIZE 32 16 + #define HINIC3_LRO_DEFAULT_TIME_LIMIT 16 17 + 18 + #define VLAN_BITMAP_BITS_SIZE(nic_dev) (sizeof(*(nic_dev)->vlan_bitmap) * 8) 19 + #define VID_LINE(nic_dev, vid) \ 20 + ((vid) / VLAN_BITMAP_BITS_SIZE(nic_dev)) 21 + #define VID_COL(nic_dev, vid) \ 22 + ((vid) & (VLAN_BITMAP_BITS_SIZE(nic_dev) - 1)) 16 23 17 24 /* try to modify the number of irq to the target number, 18 25 * and return the actual number of irq. ··· 338 327 hinic3_free_qp_ctxts(nic_dev); 339 328 } 340 329 330 + static int hinic3_maybe_set_port_state(struct net_device *netdev, bool enable) 331 + { 332 + struct hinic3_nic_dev *nic_dev = netdev_priv(netdev); 333 + int err; 334 + 335 + mutex_lock(&nic_dev->port_state_mutex); 336 + err = hinic3_set_port_enable(nic_dev->hwdev, enable); 337 + mutex_unlock(&nic_dev->port_state_mutex); 338 + 339 + return err; 340 + } 341 + 342 + static void hinic3_print_link_message(struct net_device *netdev, 343 + bool link_status_up) 344 + { 345 + struct hinic3_nic_dev *nic_dev = netdev_priv(netdev); 346 + 347 + if (nic_dev->link_status_up == link_status_up) 348 + return; 349 + 350 + nic_dev->link_status_up = link_status_up; 351 + 352 + netdev_dbg(netdev, "Link is %s\n", str_up_down(link_status_up)); 353 + } 354 + 341 355 static int hinic3_vport_up(struct net_device *netdev) 342 356 { 343 357 struct hinic3_nic_dev *nic_dev = netdev_priv(netdev); ··· 377 341 goto err_flush_qps_res; 378 342 } 379 343 344 + err = hinic3_maybe_set_port_state(netdev, true); 345 + if (err) { 346 + netdev_err(netdev, "Failed to enable port\n"); 347 + goto err_disable_vport; 348 + } 349 + 380 350 err = netif_set_real_num_queues(netdev, nic_dev->q_params.num_qps, 381 351 nic_dev->q_params.num_qps); 382 352 if (err) { 383 353 netdev_err(netdev, "Failed to set real number of queues\n"); 384 - goto err_flush_qps_res; 354 + goto err_disable_vport; 385 355 } 386 356 netif_tx_start_all_queues(netdev); 387 357 ··· 395 353 if (!err && link_status_up) 396 354 netif_carrier_on(netdev); 397 355 356 + hinic3_print_link_message(netdev, link_status_up); 357 + 398 358 return 0; 399 359 360 + err_disable_vport: 361 + hinic3_set_vport_enable(nic_dev->hwdev, glb_func_id, false); 400 362 err_flush_qps_res: 401 363 hinic3_flush_qps_res(nic_dev->hwdev); 402 364 /* wait to guarantee that no packets will be sent to host */ ··· 432 386 struct hinic3_dyna_qp_params qp_params; 433 387 int err; 434 388 389 + if (test_bit(HINIC3_INTF_UP, &nic_dev->flags)) { 390 + netdev_dbg(netdev, "Netdev already open, do nothing\n"); 391 + return 0; 392 + } 393 + 435 394 err = hinic3_init_nicio_res(nic_dev); 436 395 if (err) { 437 396 netdev_err(netdev, "Failed to init nicio resources\n"); ··· 464 413 if (err) 465 414 goto err_close_channel; 466 415 416 + set_bit(HINIC3_INTF_UP, &nic_dev->flags); 417 + 467 418 return 0; 468 419 469 420 err_close_channel: ··· 486 433 struct hinic3_nic_dev *nic_dev = netdev_priv(netdev); 487 434 struct hinic3_dyna_qp_params qp_params; 488 435 436 + if (!test_and_clear_bit(HINIC3_INTF_UP, &nic_dev->flags)) { 437 + netdev_dbg(netdev, "Netdev already close, do nothing\n"); 438 + return 0; 439 + } 440 + 489 441 hinic3_vport_down(netdev); 490 442 hinic3_close_channel(netdev); 491 443 hinic3_uninit_qps(nic_dev, &qp_params); 492 444 hinic3_free_channel_resources(netdev, &qp_params, &nic_dev->q_params); 493 445 494 446 return 0; 447 + } 448 + 449 + #define SET_FEATURES_OP_STR(op) ((op) ? "Enable" : "Disable") 450 + 451 + static int hinic3_set_feature_rx_csum(struct net_device *netdev, 452 + netdev_features_t wanted_features, 453 + netdev_features_t features, 454 + netdev_features_t *failed_features) 455 + { 456 + netdev_features_t changed = wanted_features ^ features; 457 + struct hinic3_nic_dev *nic_dev = netdev_priv(netdev); 458 + struct hinic3_hwdev *hwdev = nic_dev->hwdev; 459 + 460 + if (changed & NETIF_F_RXCSUM) 461 + dev_dbg(hwdev->dev, "%s rx csum success\n", 462 + SET_FEATURES_OP_STR(wanted_features & NETIF_F_RXCSUM)); 463 + 464 + return 0; 465 + } 466 + 467 + static int hinic3_set_feature_tso(struct net_device *netdev, 468 + netdev_features_t wanted_features, 469 + netdev_features_t features, 470 + netdev_features_t *failed_features) 471 + { 472 + netdev_features_t changed = wanted_features ^ features; 473 + struct hinic3_nic_dev *nic_dev = netdev_priv(netdev); 474 + struct hinic3_hwdev *hwdev = nic_dev->hwdev; 475 + 476 + if (changed & NETIF_F_TSO) 477 + dev_dbg(hwdev->dev, "%s tso success\n", 478 + SET_FEATURES_OP_STR(wanted_features & NETIF_F_TSO)); 479 + 480 + return 0; 481 + } 482 + 483 + static int hinic3_set_feature_lro(struct net_device *netdev, 484 + netdev_features_t wanted_features, 485 + netdev_features_t features, 486 + netdev_features_t *failed_features) 487 + { 488 + netdev_features_t changed = wanted_features ^ features; 489 + struct hinic3_nic_dev *nic_dev = netdev_priv(netdev); 490 + struct hinic3_hwdev *hwdev = nic_dev->hwdev; 491 + bool en = !!(wanted_features & NETIF_F_LRO); 492 + int err; 493 + 494 + if (!(changed & NETIF_F_LRO)) 495 + return 0; 496 + 497 + err = hinic3_set_rx_lro_state(hwdev, en, 498 + HINIC3_LRO_DEFAULT_TIME_LIMIT, 499 + HINIC3_LRO_DEFAULT_COAL_PKT_SIZE); 500 + if (err) { 501 + dev_err(hwdev->dev, "%s lro failed\n", SET_FEATURES_OP_STR(en)); 502 + *failed_features |= NETIF_F_LRO; 503 + } 504 + 505 + return err; 506 + } 507 + 508 + static int hinic3_set_feature_rx_cvlan(struct net_device *netdev, 509 + netdev_features_t wanted_features, 510 + netdev_features_t features, 511 + netdev_features_t *failed_features) 512 + { 513 + bool en = !!(wanted_features & NETIF_F_HW_VLAN_CTAG_RX); 514 + netdev_features_t changed = wanted_features ^ features; 515 + struct hinic3_nic_dev *nic_dev = netdev_priv(netdev); 516 + struct hinic3_hwdev *hwdev = nic_dev->hwdev; 517 + int err; 518 + 519 + if (!(changed & NETIF_F_HW_VLAN_CTAG_RX)) 520 + return 0; 521 + 522 + err = hinic3_set_rx_vlan_offload(hwdev, en); 523 + if (err) { 524 + dev_err(hwdev->dev, "%s rx vlan offload failed\n", 525 + SET_FEATURES_OP_STR(en)); 526 + *failed_features |= NETIF_F_HW_VLAN_CTAG_RX; 527 + } 528 + 529 + return err; 530 + } 531 + 532 + static int hinic3_set_feature_vlan_filter(struct net_device *netdev, 533 + netdev_features_t wanted_features, 534 + netdev_features_t features, 535 + netdev_features_t *failed_features) 536 + { 537 + bool en = !!(wanted_features & NETIF_F_HW_VLAN_CTAG_FILTER); 538 + netdev_features_t changed = wanted_features ^ features; 539 + struct hinic3_nic_dev *nic_dev = netdev_priv(netdev); 540 + struct hinic3_hwdev *hwdev = nic_dev->hwdev; 541 + int err; 542 + 543 + if (!(changed & NETIF_F_HW_VLAN_CTAG_FILTER)) 544 + return 0; 545 + 546 + err = hinic3_set_vlan_filter(hwdev, en); 547 + if (err) { 548 + dev_err(hwdev->dev, "%s rx vlan filter failed\n", 549 + SET_FEATURES_OP_STR(en)); 550 + *failed_features |= NETIF_F_HW_VLAN_CTAG_FILTER; 551 + } 552 + 553 + return err; 554 + } 555 + 556 + static int hinic3_set_features(struct net_device *netdev, 557 + netdev_features_t curr, 558 + netdev_features_t wanted) 559 + { 560 + netdev_features_t failed = 0; 561 + int err; 562 + 563 + err = hinic3_set_feature_rx_csum(netdev, wanted, curr, &failed) | 564 + hinic3_set_feature_tso(netdev, wanted, curr, &failed) | 565 + hinic3_set_feature_lro(netdev, wanted, curr, &failed) | 566 + hinic3_set_feature_rx_cvlan(netdev, wanted, curr, &failed) | 567 + hinic3_set_feature_vlan_filter(netdev, wanted, curr, &failed); 568 + if (err) { 569 + netdev->features = wanted ^ failed; 570 + return err; 571 + } 572 + 573 + return 0; 574 + } 575 + 576 + static int hinic3_ndo_set_features(struct net_device *netdev, 577 + netdev_features_t features) 578 + { 579 + return hinic3_set_features(netdev, netdev->features, features); 580 + } 581 + 582 + static netdev_features_t hinic3_fix_features(struct net_device *netdev, 583 + netdev_features_t features) 584 + { 585 + netdev_features_t features_tmp = features; 586 + 587 + /* If Rx checksum is disabled, then LRO should also be disabled */ 588 + if (!(features_tmp & NETIF_F_RXCSUM)) 589 + features_tmp &= ~NETIF_F_LRO; 590 + 591 + return features_tmp; 592 + } 593 + 594 + static netdev_features_t hinic3_features_check(struct sk_buff *skb, 595 + struct net_device *dev, 596 + netdev_features_t features) 597 + { 598 + features = vlan_features_check(skb, features); 599 + features = vxlan_features_check(skb, features); 600 + 601 + return features; 602 + } 603 + 604 + int hinic3_set_hw_features(struct net_device *netdev) 605 + { 606 + netdev_features_t wanted, curr; 607 + 608 + wanted = netdev->features; 609 + /* fake current features so all wanted are enabled */ 610 + curr = ~wanted; 611 + 612 + return hinic3_set_features(netdev, curr, wanted); 495 613 } 496 614 497 615 static int hinic3_change_mtu(struct net_device *netdev, int new_mtu) ··· 706 482 return 0; 707 483 } 708 484 485 + static int hinic3_vlan_rx_add_vid(struct net_device *netdev, 486 + __be16 proto, u16 vid) 487 + { 488 + struct hinic3_nic_dev *nic_dev = netdev_priv(netdev); 489 + unsigned long *vlan_bitmap = nic_dev->vlan_bitmap; 490 + u32 column, row; 491 + u16 func_id; 492 + int err; 493 + 494 + column = VID_COL(nic_dev, vid); 495 + row = VID_LINE(nic_dev, vid); 496 + 497 + func_id = hinic3_global_func_id(nic_dev->hwdev); 498 + 499 + err = hinic3_add_vlan(nic_dev->hwdev, vid, func_id); 500 + if (err) { 501 + netdev_err(netdev, "Failed to add vlan %u\n", vid); 502 + goto out; 503 + } 504 + 505 + set_bit(column, &vlan_bitmap[row]); 506 + netdev_dbg(netdev, "Add vlan %u\n", vid); 507 + 508 + out: 509 + return err; 510 + } 511 + 512 + static int hinic3_vlan_rx_kill_vid(struct net_device *netdev, 513 + __be16 proto, u16 vid) 514 + { 515 + struct hinic3_nic_dev *nic_dev = netdev_priv(netdev); 516 + unsigned long *vlan_bitmap = nic_dev->vlan_bitmap; 517 + u32 column, row; 518 + u16 func_id; 519 + int err; 520 + 521 + column = VID_COL(nic_dev, vid); 522 + row = VID_LINE(nic_dev, vid); 523 + 524 + func_id = hinic3_global_func_id(nic_dev->hwdev); 525 + err = hinic3_del_vlan(nic_dev->hwdev, vid, func_id); 526 + if (err) { 527 + netdev_err(netdev, "Failed to delete vlan %u\n", vid); 528 + goto out; 529 + } 530 + 531 + clear_bit(column, &vlan_bitmap[row]); 532 + netdev_dbg(netdev, "Remove vlan %u\n", vid); 533 + 534 + out: 535 + return err; 536 + } 537 + 538 + static void hinic3_tx_timeout(struct net_device *netdev, unsigned int txqueue) 539 + { 540 + struct hinic3_nic_dev *nic_dev = netdev_priv(netdev); 541 + struct hinic3_io_queue *sq; 542 + u16 sw_pi, hw_ci; 543 + 544 + sq = nic_dev->txqs[txqueue].sq; 545 + sw_pi = hinic3_get_sq_local_pi(sq); 546 + hw_ci = hinic3_get_sq_hw_ci(sq); 547 + netdev_dbg(netdev, 548 + "txq%u: sw_pi: %u, hw_ci: %u, sw_ci: %u, napi->state: 0x%lx.\n", 549 + txqueue, sw_pi, hw_ci, hinic3_get_sq_local_ci(sq), 550 + nic_dev->q_params.irq_cfg[txqueue].napi.state); 551 + 552 + if (sw_pi != hw_ci) 553 + set_bit(HINIC3_EVENT_WORK_TX_TIMEOUT, &nic_dev->event_flag); 554 + } 555 + 556 + static void hinic3_get_stats64(struct net_device *netdev, 557 + struct rtnl_link_stats64 *stats) 558 + { 559 + struct hinic3_nic_dev *nic_dev = netdev_priv(netdev); 560 + u64 bytes, packets, dropped, errors; 561 + struct hinic3_txq_stats *txq_stats; 562 + struct hinic3_rxq_stats *rxq_stats; 563 + struct hinic3_txq *txq; 564 + struct hinic3_rxq *rxq; 565 + unsigned int start; 566 + int i; 567 + 568 + bytes = 0; 569 + packets = 0; 570 + dropped = 0; 571 + for (i = 0; i < nic_dev->max_qps; i++) { 572 + if (!nic_dev->txqs) 573 + break; 574 + 575 + txq = &nic_dev->txqs[i]; 576 + txq_stats = &txq->txq_stats; 577 + do { 578 + start = u64_stats_fetch_begin(&txq_stats->syncp); 579 + bytes += txq_stats->bytes; 580 + packets += txq_stats->packets; 581 + dropped += txq_stats->dropped; 582 + } while (u64_stats_fetch_retry(&txq_stats->syncp, start)); 583 + } 584 + stats->tx_packets = packets; 585 + stats->tx_bytes = bytes; 586 + stats->tx_dropped = dropped; 587 + 588 + bytes = 0; 589 + packets = 0; 590 + errors = 0; 591 + dropped = 0; 592 + for (i = 0; i < nic_dev->max_qps; i++) { 593 + if (!nic_dev->rxqs) 594 + break; 595 + 596 + rxq = &nic_dev->rxqs[i]; 597 + rxq_stats = &rxq->rxq_stats; 598 + do { 599 + start = u64_stats_fetch_begin(&rxq_stats->syncp); 600 + bytes += rxq_stats->bytes; 601 + packets += rxq_stats->packets; 602 + errors += rxq_stats->csum_errors + 603 + rxq_stats->other_errors; 604 + dropped += rxq_stats->dropped; 605 + } while (u64_stats_fetch_retry(&rxq_stats->syncp, start)); 606 + } 607 + stats->rx_packets = packets; 608 + stats->rx_bytes = bytes; 609 + stats->rx_errors = errors; 610 + stats->rx_dropped = dropped; 611 + } 612 + 613 + static void hinic3_nic_set_rx_mode(struct net_device *netdev) 614 + { 615 + struct hinic3_nic_dev *nic_dev = netdev_priv(netdev); 616 + 617 + if (netdev_uc_count(netdev) != nic_dev->netdev_uc_cnt || 618 + netdev_mc_count(netdev) != nic_dev->netdev_mc_cnt) { 619 + set_bit(HINIC3_UPDATE_MAC_FILTER, &nic_dev->flags); 620 + nic_dev->netdev_uc_cnt = netdev_uc_count(netdev); 621 + nic_dev->netdev_mc_cnt = netdev_mc_count(netdev); 622 + } 623 + 624 + queue_work(nic_dev->workq, &nic_dev->rx_mode_work); 625 + } 626 + 709 627 static const struct net_device_ops hinic3_netdev_ops = { 710 628 .ndo_open = hinic3_open, 711 629 .ndo_stop = hinic3_close, 630 + .ndo_set_features = hinic3_ndo_set_features, 631 + .ndo_fix_features = hinic3_fix_features, 632 + .ndo_features_check = hinic3_features_check, 712 633 .ndo_change_mtu = hinic3_change_mtu, 713 634 .ndo_set_mac_address = hinic3_set_mac_addr, 635 + .ndo_validate_addr = eth_validate_addr, 636 + .ndo_vlan_rx_add_vid = hinic3_vlan_rx_add_vid, 637 + .ndo_vlan_rx_kill_vid = hinic3_vlan_rx_kill_vid, 638 + .ndo_tx_timeout = hinic3_tx_timeout, 639 + .ndo_get_stats64 = hinic3_get_stats64, 640 + .ndo_set_rx_mode = hinic3_nic_set_rx_mode, 714 641 .ndo_start_xmit = hinic3_xmit_frame, 715 642 }; 716 643
+280 -4
drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.c
··· 10 10 #include "hinic3_nic_dev.h" 11 11 #include "hinic3_nic_io.h" 12 12 13 + #define MGMT_MSG_CMD_OP_ADD 1 14 + #define MGMT_MSG_CMD_OP_DEL 0 15 + 13 16 static int hinic3_feature_nego(struct hinic3_hwdev *hwdev, u8 opcode, 14 17 u64 *s_feature, u16 size) 15 18 { ··· 58 55 enum hinic3_nic_feature_cap feature_bits) 59 56 { 60 57 return (nic_dev->nic_io->feature_cap & feature_bits) == feature_bits; 58 + } 59 + 60 + static int hinic3_set_rx_lro(struct hinic3_hwdev *hwdev, u8 ipv4_en, u8 ipv6_en, 61 + u8 lro_max_pkt_len) 62 + { 63 + struct l2nic_cmd_lro_config lro_cfg = {}; 64 + struct mgmt_msg_params msg_params = {}; 65 + int err; 66 + 67 + lro_cfg.func_id = hinic3_global_func_id(hwdev); 68 + lro_cfg.opcode = MGMT_MSG_CMD_OP_SET; 69 + lro_cfg.lro_ipv4_en = ipv4_en; 70 + lro_cfg.lro_ipv6_en = ipv6_en; 71 + lro_cfg.lro_max_pkt_len = lro_max_pkt_len; 72 + 73 + mgmt_msg_params_init_default(&msg_params, &lro_cfg, 74 + sizeof(lro_cfg)); 75 + 76 + err = hinic3_send_mbox_to_mgmt(hwdev, MGMT_MOD_L2NIC, 77 + L2NIC_CMD_CFG_RX_LRO, 78 + &msg_params); 79 + 80 + if (err || lro_cfg.msg_head.status) { 81 + dev_err(hwdev->dev, "Failed to set lro offload, err: %d, status: 0x%x\n", 82 + err, lro_cfg.msg_head.status); 83 + return -EFAULT; 84 + } 85 + 86 + return 0; 87 + } 88 + 89 + static int hinic3_set_rx_lro_timer(struct hinic3_hwdev *hwdev, u32 timer_value) 90 + { 91 + struct l2nic_cmd_lro_timer lro_timer = {}; 92 + struct mgmt_msg_params msg_params = {}; 93 + int err; 94 + 95 + lro_timer.opcode = MGMT_MSG_CMD_OP_SET; 96 + lro_timer.timer = timer_value; 97 + 98 + mgmt_msg_params_init_default(&msg_params, &lro_timer, 99 + sizeof(lro_timer)); 100 + 101 + err = hinic3_send_mbox_to_mgmt(hwdev, MGMT_MOD_L2NIC, 102 + L2NIC_CMD_CFG_LRO_TIMER, 103 + &msg_params); 104 + 105 + if (err || lro_timer.msg_head.status) { 106 + dev_err(hwdev->dev, "Failed to set lro timer, err: %d, status: 0x%x\n", 107 + err, lro_timer.msg_head.status); 108 + 109 + return -EFAULT; 110 + } 111 + 112 + return 0; 113 + } 114 + 115 + int hinic3_set_rx_lro_state(struct hinic3_hwdev *hwdev, u8 lro_en, 116 + u32 lro_timer, u8 lro_max_pkt_len) 117 + { 118 + u8 ipv4_en, ipv6_en; 119 + int err; 120 + 121 + ipv4_en = lro_en ? 1 : 0; 122 + ipv6_en = lro_en ? 1 : 0; 123 + 124 + dev_dbg(hwdev->dev, "Set LRO max coalesce packet size to %uK\n", 125 + lro_max_pkt_len); 126 + 127 + err = hinic3_set_rx_lro(hwdev, ipv4_en, ipv6_en, lro_max_pkt_len); 128 + if (err) 129 + return err; 130 + 131 + /* we don't set LRO timer for VF */ 132 + if (HINIC3_IS_VF(hwdev)) 133 + return 0; 134 + 135 + dev_dbg(hwdev->dev, "Set LRO timer to %u\n", lro_timer); 136 + 137 + return hinic3_set_rx_lro_timer(hwdev, lro_timer); 138 + } 139 + 140 + int hinic3_set_rx_vlan_offload(struct hinic3_hwdev *hwdev, u8 en) 141 + { 142 + struct l2nic_cmd_vlan_offload vlan_cfg = {}; 143 + struct mgmt_msg_params msg_params = {}; 144 + int err; 145 + 146 + vlan_cfg.func_id = hinic3_global_func_id(hwdev); 147 + vlan_cfg.vlan_offload = en; 148 + 149 + mgmt_msg_params_init_default(&msg_params, &vlan_cfg, 150 + sizeof(vlan_cfg)); 151 + 152 + err = hinic3_send_mbox_to_mgmt(hwdev, MGMT_MOD_L2NIC, 153 + L2NIC_CMD_SET_RX_VLAN_OFFLOAD, 154 + &msg_params); 155 + 156 + if (err || vlan_cfg.msg_head.status) { 157 + dev_err(hwdev->dev, "Failed to set rx vlan offload, err: %d, status: 0x%x\n", 158 + err, vlan_cfg.msg_head.status); 159 + return -EFAULT; 160 + } 161 + 162 + return 0; 163 + } 164 + 165 + int hinic3_set_vlan_filter(struct hinic3_hwdev *hwdev, u32 vlan_filter_ctrl) 166 + { 167 + struct l2nic_cmd_set_vlan_filter vlan_filter = {}; 168 + struct mgmt_msg_params msg_params = {}; 169 + int err; 170 + 171 + vlan_filter.func_id = hinic3_global_func_id(hwdev); 172 + vlan_filter.vlan_filter_ctrl = vlan_filter_ctrl; 173 + 174 + mgmt_msg_params_init_default(&msg_params, &vlan_filter, 175 + sizeof(vlan_filter)); 176 + 177 + err = hinic3_send_mbox_to_mgmt(hwdev, MGMT_MOD_L2NIC, 178 + L2NIC_CMD_SET_VLAN_FILTER_EN, 179 + &msg_params); 180 + 181 + if (err || vlan_filter.msg_head.status) { 182 + dev_err(hwdev->dev, "Failed to set vlan filter, err: %d, status: 0x%x\n", 183 + err, vlan_filter.msg_head.status); 184 + return -EFAULT; 185 + } 186 + 187 + return 0; 61 188 } 62 189 63 190 void hinic3_update_nic_feature(struct hinic3_nic_dev *nic_dev, u64 feature_cap) ··· 250 117 &func_tbl_cfg); 251 118 } 252 119 120 + static bool hinic3_check_vf_set_by_pf(struct hinic3_hwdev *hwdev, 121 + u8 status) 122 + { 123 + return HINIC3_IS_VF(hwdev) && status == HINIC3_PF_SET_VF_ALREADY; 124 + } 125 + 253 126 static int hinic3_check_mac_info(struct hinic3_hwdev *hwdev, u8 status, 254 127 u16 vlan_id) 255 128 { 256 129 if ((status && status != MGMT_STATUS_EXIST) || 257 130 ((vlan_id & BIT(15)) && status == MGMT_STATUS_EXIST)) { 131 + if (hinic3_check_vf_set_by_pf(hwdev, status)) 132 + return 0; 133 + 258 134 return -EINVAL; 259 135 } 136 + 137 + return 0; 138 + } 139 + 140 + int hinic3_get_default_mac(struct hinic3_hwdev *hwdev, u8 *mac_addr) 141 + { 142 + struct l2nic_cmd_set_mac mac_info = {}; 143 + struct mgmt_msg_params msg_params = {}; 144 + int err; 145 + 146 + mac_info.func_id = hinic3_global_func_id(hwdev); 147 + 148 + mgmt_msg_params_init_default(&msg_params, &mac_info, sizeof(mac_info)); 149 + 150 + err = hinic3_send_mbox_to_mgmt(hwdev, MGMT_MOD_L2NIC, 151 + L2NIC_CMD_GET_MAC, 152 + &msg_params); 153 + 154 + if (err || mac_info.msg_head.status) { 155 + dev_err(hwdev->dev, 156 + "Failed to get mac, err: %d, status: 0x%x\n", 157 + err, mac_info.msg_head.status); 158 + return -EFAULT; 159 + } 160 + 161 + ether_addr_copy(mac_addr, mac_info.mac); 260 162 261 163 return 0; 262 164 } ··· 325 157 return -EIO; 326 158 } 327 159 328 - if (mac_info.msg_head.status == MGMT_STATUS_PF_SET_VF_ALREADY) { 160 + if (hinic3_check_vf_set_by_pf(hwdev, mac_info.msg_head.status)) { 329 161 dev_warn(hwdev->dev, "PF has already set VF mac, Ignore set operation\n"); 330 - return 0; 162 + return -EADDRINUSE; 331 163 } 332 164 333 165 if (mac_info.msg_head.status == MGMT_STATUS_EXIST) { ··· 359 191 360 192 err = hinic3_send_mbox_to_mgmt(hwdev, MGMT_MOD_L2NIC, 361 193 L2NIC_CMD_DEL_MAC, &msg_params); 362 - if (err) { 194 + if (err || 195 + (mac_info.msg_head.status && 196 + !hinic3_check_vf_set_by_pf(hwdev, mac_info.msg_head.status))) { 363 197 dev_err(hwdev->dev, 364 198 "Failed to delete MAC, err: %d, status: 0x%x\n", 365 199 err, mac_info.msg_head.status); 366 - return err; 200 + return -EFAULT; 201 + } 202 + 203 + if (hinic3_check_vf_set_by_pf(hwdev, mac_info.msg_head.status)) { 204 + dev_warn(hwdev->dev, "PF has already set VF mac, Ignore delete operation.\n"); 205 + return -EADDRINUSE; 367 206 } 368 207 369 208 return 0; ··· 404 229 "Failed to update MAC, err: %d, status: 0x%x\n", 405 230 err, mac_info.msg_head.status); 406 231 return -EIO; 232 + } 233 + 234 + if (hinic3_check_vf_set_by_pf(hwdev, mac_info.msg_head.status)) { 235 + dev_warn(hwdev->dev, "PF has already set VF MAC. Ignore update operation\n"); 236 + return -EADDRINUSE; 237 + } 238 + 239 + if (mac_info.msg_head.status == HINIC3_MGMT_STATUS_EXIST) { 240 + dev_warn(hwdev->dev, 241 + "MAC is repeated. Ignore update operation\n"); 242 + return 0; 407 243 } 408 244 409 245 return 0; ··· 497 311 } 498 312 499 313 return pkt_drop.msg_head.status; 314 + } 315 + 316 + int hinic3_set_rx_mode(struct hinic3_hwdev *hwdev, u32 rx_mode) 317 + { 318 + struct l2nic_rx_mode_config rx_mode_cfg = {}; 319 + struct mgmt_msg_params msg_params = {}; 320 + int err; 321 + 322 + rx_mode_cfg.func_id = hinic3_global_func_id(hwdev); 323 + rx_mode_cfg.rx_mode = rx_mode; 324 + 325 + mgmt_msg_params_init_default(&msg_params, &rx_mode_cfg, 326 + sizeof(rx_mode_cfg)); 327 + 328 + err = hinic3_send_mbox_to_mgmt(hwdev, MGMT_MOD_L2NIC, 329 + L2NIC_CMD_SET_RX_MODE, &msg_params); 330 + 331 + if (err || rx_mode_cfg.msg_head.status) { 332 + dev_err(hwdev->dev, "Failed to set rx mode, err: %d, status: 0x%x\n", 333 + err, rx_mode_cfg.msg_head.status); 334 + return -EFAULT; 335 + } 336 + 337 + return 0; 338 + } 339 + 340 + static int hinic3_config_vlan(struct hinic3_hwdev *hwdev, 341 + u8 opcode, u16 vlan_id, u16 func_id) 342 + { 343 + struct l2nic_cmd_vlan_config vlan_info = {}; 344 + struct mgmt_msg_params msg_params = {}; 345 + int err; 346 + 347 + vlan_info.opcode = opcode; 348 + vlan_info.func_id = func_id; 349 + vlan_info.vlan_id = vlan_id; 350 + 351 + mgmt_msg_params_init_default(&msg_params, &vlan_info, 352 + sizeof(vlan_info)); 353 + 354 + err = hinic3_send_mbox_to_mgmt(hwdev, MGMT_MOD_L2NIC, 355 + L2NIC_CMD_CFG_FUNC_VLAN, &msg_params); 356 + 357 + if (err || vlan_info.msg_head.status) { 358 + dev_err(hwdev->dev, 359 + "Failed to %s vlan, err: %d, status: 0x%x\n", 360 + opcode == MGMT_MSG_CMD_OP_ADD ? "add" : "delete", 361 + err, vlan_info.msg_head.status); 362 + return -EFAULT; 363 + } 364 + 365 + return 0; 366 + } 367 + 368 + int hinic3_add_vlan(struct hinic3_hwdev *hwdev, u16 vlan_id, u16 func_id) 369 + { 370 + return hinic3_config_vlan(hwdev, MGMT_MSG_CMD_OP_ADD, vlan_id, func_id); 371 + } 372 + 373 + int hinic3_del_vlan(struct hinic3_hwdev *hwdev, u16 vlan_id, u16 func_id) 374 + { 375 + return hinic3_config_vlan(hwdev, MGMT_MSG_CMD_OP_DEL, vlan_id, func_id); 376 + } 377 + 378 + int hinic3_set_port_enable(struct hinic3_hwdev *hwdev, bool enable) 379 + { 380 + struct mag_cmd_set_port_enable en_state = {}; 381 + struct mgmt_msg_params msg_params = {}; 382 + int err; 383 + 384 + if (HINIC3_IS_VF(hwdev)) 385 + return 0; 386 + 387 + en_state.function_id = hinic3_global_func_id(hwdev); 388 + en_state.state = enable ? MAG_CMD_TX_ENABLE | MAG_CMD_RX_ENABLE : 389 + MAG_CMD_PORT_DISABLE; 390 + 391 + mgmt_msg_params_init_default(&msg_params, &en_state, 392 + sizeof(en_state)); 393 + 394 + err = hinic3_send_mbox_to_mgmt(hwdev, MGMT_MOD_HILINK, 395 + MAG_CMD_SET_PORT_ENABLE, &msg_params); 396 + 397 + if (err || en_state.head.status) { 398 + dev_err(hwdev->dev, "Failed to set port state, err: %d, status: 0x%x\n", 399 + err, en_state.head.status); 400 + return -EFAULT; 401 + } 402 + 403 + return 0; 500 404 } 501 405 502 406 int hinic3_sync_dcb_state(struct hinic3_hwdev *hwdev, u8 op_code, u8 state)
+47
drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.h
··· 16 16 #define HINIC3_MAX_JUMBO_FRAME_SIZE 9600 17 17 18 18 #define HINIC3_VLAN_ID_MASK 0x7FFF 19 + #define HINIC3_PF_SET_VF_ALREADY 0x4 20 + #define HINIC3_MGMT_STATUS_EXIST 0x6 19 21 20 22 enum hinic3_nic_event_type { 21 23 HINIC3_NIC_EVENT_LINK_DOWN = 0, 22 24 HINIC3_NIC_EVENT_LINK_UP = 1, 25 + HINIC3_NIC_EVENT_PORT_MODULE_EVENT = 2, 23 26 }; 24 27 25 28 struct hinic3_sq_attr { ··· 35 32 u64 ci_dma_base; 36 33 }; 37 34 35 + #define MAG_CMD_PORT_DISABLE 0x0 36 + #define MAG_CMD_TX_ENABLE 0x1 37 + #define MAG_CMD_RX_ENABLE 0x2 38 + /* the physical port is disabled only when all pf of the port are set to down, 39 + * if any pf is enabled, the port is enabled 40 + */ 41 + struct mag_cmd_set_port_enable { 42 + struct mgmt_msg_head head; 43 + 44 + u16 function_id; 45 + u16 rsvd0; 46 + 47 + /* bitmap bit0:tx_en bit1:rx_en */ 48 + u8 state; 49 + u8 rsvd1[3]; 50 + }; 51 + 52 + enum link_err_type { 53 + LINK_ERR_MODULE_UNRECOGENIZED, 54 + LINK_ERR_NUM, 55 + }; 56 + 57 + enum port_module_event_type { 58 + HINIC3_PORT_MODULE_CABLE_PLUGGED, 59 + HINIC3_PORT_MODULE_CABLE_UNPLUGGED, 60 + HINIC3_PORT_MODULE_LINK_ERR, 61 + HINIC3_PORT_MODULE_MAX_EVENT, 62 + }; 63 + 64 + struct hinic3_port_module_event { 65 + enum port_module_event_type type; 66 + enum link_err_type err_type; 67 + }; 68 + 38 69 int hinic3_get_nic_feature_from_hw(struct hinic3_nic_dev *nic_dev); 39 70 int hinic3_set_nic_feature_to_hw(struct hinic3_nic_dev *nic_dev); 40 71 bool hinic3_test_support(struct hinic3_nic_dev *nic_dev, 41 72 enum hinic3_nic_feature_cap feature_bits); 42 73 void hinic3_update_nic_feature(struct hinic3_nic_dev *nic_dev, u64 feature_cap); 43 74 75 + int hinic3_set_rx_lro_state(struct hinic3_hwdev *hwdev, u8 lro_en, 76 + u32 lro_timer, u8 lro_max_pkt_len); 77 + int hinic3_set_rx_vlan_offload(struct hinic3_hwdev *hwdev, u8 en); 78 + int hinic3_set_vlan_filter(struct hinic3_hwdev *hwdev, u32 vlan_filter_ctrl); 79 + 44 80 int hinic3_init_function_table(struct hinic3_nic_dev *nic_dev); 45 81 int hinic3_set_port_mtu(struct net_device *netdev, u16 new_mtu); 46 82 83 + int hinic3_get_default_mac(struct hinic3_hwdev *hwdev, u8 *mac_addr); 47 84 int hinic3_set_mac(struct hinic3_hwdev *hwdev, const u8 *mac_addr, u16 vlan_id, 48 85 u16 func_id); 49 86 int hinic3_del_mac(struct hinic3_hwdev *hwdev, const u8 *mac_addr, u16 vlan_id, ··· 95 52 struct hinic3_sq_attr *attr); 96 53 int hinic3_flush_qps_res(struct hinic3_hwdev *hwdev); 97 54 int hinic3_force_drop_tx_pkt(struct hinic3_hwdev *hwdev); 55 + int hinic3_set_rx_mode(struct hinic3_hwdev *hwdev, u32 rx_mode); 98 56 99 57 int hinic3_sync_dcb_state(struct hinic3_hwdev *hwdev, u8 op_code, u8 state); 58 + int hinic3_set_port_enable(struct hinic3_hwdev *hwdev, bool enable); 100 59 int hinic3_get_link_status(struct hinic3_hwdev *hwdev, bool *link_status_up); 101 60 int hinic3_set_vport_enable(struct hinic3_hwdev *hwdev, u16 func_id, 102 61 bool enable); 62 + int hinic3_add_vlan(struct hinic3_hwdev *hwdev, u16 vlan_id, u16 func_id); 63 + int hinic3_del_vlan(struct hinic3_hwdev *hwdev, u16 vlan_id, u16 func_id); 103 64 104 65 #endif
+58
drivers/net/ethernet/huawei/hinic3/hinic3_nic_dev.h
··· 4 4 #ifndef _HINIC3_NIC_DEV_H_ 5 5 #define _HINIC3_NIC_DEV_H_ 6 6 7 + #include <linux/if_vlan.h> 7 8 #include <linux/netdevice.h> 8 9 9 10 #include "hinic3_hw_cfg.h" 11 + #include "hinic3_hwdev.h" 10 12 #include "hinic3_mgmt_interface.h" 11 13 14 + #define HINIC3_VLAN_BITMAP_BYTE_SIZE(nic_dev) (sizeof(*(nic_dev)->vlan_bitmap)) 15 + #define HINIC3_VLAN_BITMAP_SIZE(nic_dev) \ 16 + (VLAN_N_VID / HINIC3_VLAN_BITMAP_BYTE_SIZE(nic_dev)) 17 + 12 18 enum hinic3_flags { 19 + HINIC3_INTF_UP, 20 + HINIC3_MAC_FILTER_CHANGED, 13 21 HINIC3_RSS_ENABLE, 22 + HINIC3_UPDATE_MAC_FILTER, 23 + }; 24 + 25 + enum hinic3_event_work_flags { 26 + HINIC3_EVENT_WORK_TX_TIMEOUT, 27 + }; 28 + 29 + enum hinic3_rx_mode_state { 30 + HINIC3_HW_PROMISC_ON, 31 + HINIC3_HW_ALLMULTI_ON, 32 + HINIC3_PROMISC_FORCE_ON, 33 + HINIC3_ALLMULTI_FORCE_ON, 34 + }; 35 + 36 + enum hinic3_mac_filter_state { 37 + HINIC3_MAC_WAIT_HW_SYNC, 38 + HINIC3_MAC_HW_SYNCING, 39 + HINIC3_MAC_HW_SYNCED, 40 + HINIC3_MAC_WAIT_HW_UNSYNC, 41 + HINIC3_MAC_HW_UNSYNCED, 42 + }; 43 + 44 + struct hinic3_mac_filter { 45 + struct list_head list; 46 + u8 addr[ETH_ALEN]; 47 + unsigned long state; 14 48 }; 15 49 16 50 enum hinic3_rss_hash_type { ··· 73 39 cpumask_t affinity_mask; 74 40 struct hinic3_txq *txq; 75 41 struct hinic3_rxq *rxq; 42 + u16 total_events; 76 43 }; 77 44 78 45 struct hinic3_dyna_txrxq_params { ··· 90 55 u8 pending_limit; 91 56 u8 coalesce_timer_cfg; 92 57 u8 resend_timer_cfg; 58 + 59 + u8 rx_pending_limit_low; 60 + u8 rx_pending_limit_high; 93 61 }; 94 62 95 63 struct hinic3_nic_dev { ··· 104 66 u16 max_qps; 105 67 u16 rx_buf_len; 106 68 u32 lro_replenish_thld; 69 + unsigned long *vlan_bitmap; 107 70 unsigned long flags; 108 71 struct hinic3_nic_service_cap nic_svc_cap; 109 72 ··· 121 82 struct msix_entry *qps_msix_entries; 122 83 123 84 struct hinic3_intr_coal_info *intr_coalesce; 85 + u32 adaptive_rx_coal; 124 86 87 + struct workqueue_struct *workq; 88 + struct delayed_work periodic_work; 89 + struct work_struct rx_mode_work; 90 + /* lock for enable/disable port */ 91 + struct mutex port_state_mutex; 92 + 93 + struct list_head uc_filter_list; 94 + struct list_head mc_filter_list; 95 + unsigned long rx_mod_state; 96 + int netdev_uc_cnt; 97 + int netdev_mc_cnt; 98 + 99 + /* flag bits defined by hinic3_event_work_flags */ 100 + unsigned long event_flag; 125 101 bool link_status_up; 126 102 }; 127 103 128 104 void hinic3_set_netdev_ops(struct net_device *netdev); 105 + int hinic3_set_hw_features(struct net_device *netdev); 129 106 int hinic3_qps_irq_init(struct net_device *netdev); 130 107 void hinic3_qps_irq_uninit(struct net_device *netdev); 108 + 109 + void hinic3_set_rx_mode_work(struct work_struct *work); 110 + void hinic3_clean_mac_list_filter(struct net_device *netdev); 131 111 132 112 #endif
+27
drivers/net/ethernet/huawei/hinic3/hinic3_rx.c
··· 33 33 HINIC3_RX_IPV6_PKT ? HINIC3_LRO_PKT_HDR_LEN_IPV6 : \ 34 34 HINIC3_LRO_PKT_HDR_LEN_IPV4) 35 35 36 + static void hinic3_rxq_clean_stats(struct hinic3_rxq_stats *rxq_stats) 37 + { 38 + u64_stats_update_begin(&rxq_stats->syncp); 39 + rxq_stats->bytes = 0; 40 + rxq_stats->packets = 0; 41 + rxq_stats->errors = 0; 42 + rxq_stats->csum_errors = 0; 43 + rxq_stats->other_errors = 0; 44 + rxq_stats->dropped = 0; 45 + rxq_stats->rx_buf_empty = 0; 46 + 47 + rxq_stats->alloc_skb_err = 0; 48 + rxq_stats->alloc_rx_buf_err = 0; 49 + rxq_stats->restore_drop_sge = 0; 50 + u64_stats_update_end(&rxq_stats->syncp); 51 + } 52 + 53 + static void hinic3_rxq_stats_init(struct hinic3_rxq *rxq) 54 + { 55 + struct hinic3_rxq_stats *rxq_stats = &rxq->rxq_stats; 56 + 57 + u64_stats_init(&rxq_stats->syncp); 58 + hinic3_rxq_clean_stats(rxq_stats); 59 + } 60 + 36 61 int hinic3_alloc_rxqs(struct net_device *netdev) 37 62 { 38 63 struct hinic3_nic_dev *nic_dev = netdev_priv(netdev); ··· 79 54 rxq->buf_len_shift = ilog2(nic_dev->rx_buf_len); 80 55 rxq->q_depth = nic_dev->q_params.rq_depth; 81 56 rxq->q_mask = nic_dev->q_params.rq_depth - 1; 57 + 58 + hinic3_rxq_stats_init(rxq); 82 59 } 83 60 84 61 return 0;
+21
drivers/net/ethernet/huawei/hinic3/hinic3_rx.h
··· 5 5 #define _HINIC3_RX_H_ 6 6 7 7 #include <linux/bitfield.h> 8 + #include <linux/dim.h> 8 9 #include <linux/netdevice.h> 9 10 10 11 #define RQ_CQE_OFFOLAD_TYPE_PKT_TYPE_MASK GENMASK(4, 0) ··· 25 24 #define RQ_CQE_STATUS_RXDONE_MASK BIT(31) 26 25 #define RQ_CQE_STATUS_GET(val, member) \ 27 26 FIELD_GET(RQ_CQE_STATUS_##member##_MASK, val) 27 + 28 + struct hinic3_rxq_stats { 29 + u64 packets; 30 + u64 bytes; 31 + u64 errors; 32 + u64 csum_errors; 33 + u64 other_errors; 34 + u64 dropped; 35 + u64 rx_buf_empty; 36 + u64 alloc_skb_err; 37 + u64 alloc_rx_buf_err; 38 + u64 restore_drop_sge; 39 + struct u64_stats_sync syncp; 40 + }; 28 41 29 42 /* RX Completion information that is provided by HW for a specific RX WQE */ 30 43 struct hinic3_rq_cqe { ··· 74 59 u16 buf_len; 75 60 u32 buf_len_shift; 76 61 62 + struct hinic3_rxq_stats rxq_stats; 77 63 u32 cons_idx; 78 64 u32 delta; 79 65 ··· 96 80 struct device *dev; /* device for DMA mapping */ 97 81 98 82 dma_addr_t cqe_start_paddr; 83 + 84 + struct dim dim; 85 + 86 + u8 last_coalesc_timer_cfg; 87 + u8 last_pending_limit; 99 88 } ____cacheline_aligned; 100 89 101 90 struct hinic3_dyna_rxq_res {
+27
drivers/net/ethernet/huawei/hinic3/hinic3_tx.c
··· 16 16 17 17 #define MIN_SKB_LEN 32 18 18 19 + static void hinic3_txq_clean_stats(struct hinic3_txq_stats *txq_stats) 20 + { 21 + u64_stats_update_begin(&txq_stats->syncp); 22 + txq_stats->bytes = 0; 23 + txq_stats->packets = 0; 24 + txq_stats->busy = 0; 25 + txq_stats->dropped = 0; 26 + 27 + txq_stats->skb_pad_err = 0; 28 + txq_stats->frag_len_overflow = 0; 29 + txq_stats->offload_cow_skb_err = 0; 30 + txq_stats->map_frag_err = 0; 31 + txq_stats->unknown_tunnel_pkt = 0; 32 + txq_stats->frag_size_err = 0; 33 + u64_stats_update_end(&txq_stats->syncp); 34 + } 35 + 36 + static void hinic3_txq_stats_init(struct hinic3_txq *txq) 37 + { 38 + struct hinic3_txq_stats *txq_stats = &txq->txq_stats; 39 + 40 + u64_stats_init(&txq_stats->syncp); 41 + hinic3_txq_clean_stats(txq_stats); 42 + } 43 + 19 44 int hinic3_alloc_txqs(struct net_device *netdev) 20 45 { 21 46 struct hinic3_nic_dev *nic_dev = netdev_priv(netdev); ··· 65 40 txq->q_depth = nic_dev->q_params.sq_depth; 66 41 txq->q_mask = nic_dev->q_params.sq_depth - 1; 67 42 txq->dev = &pdev->dev; 43 + 44 + hinic3_txq_stats_init(txq); 68 45 } 69 46 70 47 return 0;
+16
drivers/net/ethernet/huawei/hinic3/hinic3_tx.h
··· 100 100 u32 task_type; 101 101 }; 102 102 103 + struct hinic3_txq_stats { 104 + u64 packets; 105 + u64 bytes; 106 + u64 busy; 107 + u64 dropped; 108 + u64 skb_pad_err; 109 + u64 frag_len_overflow; 110 + u64 offload_cow_skb_err; 111 + u64 map_frag_err; 112 + u64 unknown_tunnel_pkt; 113 + u64 frag_size_err; 114 + struct u64_stats_sync syncp; 115 + }; 116 + 103 117 struct hinic3_dma_info { 104 118 dma_addr_t dma; 105 119 u32 len; ··· 137 123 138 124 struct hinic3_tx_info *tx_info; 139 125 struct hinic3_io_queue *sq; 126 + 127 + struct hinic3_txq_stats txq_stats; 140 128 } ____cacheline_aligned; 141 129 142 130 struct hinic3_dyna_txq_res {