FILE
hinic3_eqs.c
File preview with syntax highlighting.
linux-6.19.14/drivers/net/ethernet/huawei/hinic3/hinic3_eqs.c
1// SPDX-License-Identifier: GPL-2.0 2// Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved. 3 4#include <linux/delay.h> 5 6#include "hinic3_csr.h" 7#include "hinic3_eqs.h" 8#include "hinic3_hwdev.h" 9#include "hinic3_hwif.h" 10#include "hinic3_mbox.h" 11 12#define AEQ_CTRL_0_INTR_IDX_MASK GENMASK(9, 0) 13#define AEQ_CTRL_0_DMA_ATTR_MASK GENMASK(17, 12) 14#define AEQ_CTRL_0_PCI_INTF_IDX_MASK GENMASK(22, 20) 15#define AEQ_CTRL_0_INTR_MODE_MASK BIT(31) 16#define AEQ_CTRL_0_SET(val, member) \ 17 FIELD_PREP(AEQ_CTRL_0_##member##_MASK, val) 18 19#define AEQ_CTRL_1_LEN_MASK GENMASK(20, 0) 20#define AEQ_CTRL_1_ELEM_SIZE_MASK GENMASK(25, 24) 21#define AEQ_CTRL_1_PAGE_SIZE_MASK GENMASK(31, 28) 22#define AEQ_CTRL_1_SET(val, member) \ 23 FIELD_PREP(AEQ_CTRL_1_##member##_MASK, val) 24 25#define CEQ_CTRL_0_INTR_IDX_MASK GENMASK(9, 0) 26#define CEQ_CTRL_0_DMA_ATTR_MASK GENMASK(17, 12) 27#define CEQ_CTRL_0_LIMIT_KICK_MASK GENMASK(23, 20) 28#define CEQ_CTRL_0_PCI_INTF_IDX_MASK GENMASK(25, 24) 29#define CEQ_CTRL_0_PAGE_SIZE_MASK GENMASK(30, 27) 30#define CEQ_CTRL_0_INTR_MODE_MASK BIT(31) 31#define CEQ_CTRL_0_SET(val, member) \ 32 FIELD_PREP(CEQ_CTRL_0_##member##_MASK, val) 33 34#define CEQ_CTRL_1_LEN_MASK GENMASK(19, 0) 35#define CEQ_CTRL_1_SET(val, member) \ 36 FIELD_PREP(CEQ_CTRL_1_##member##_MASK, val) 37 38#define CEQE_TYPE_MASK GENMASK(25, 23) 39#define CEQE_TYPE(type) \ 40 FIELD_GET(CEQE_TYPE_MASK, le32_to_cpu(type)) 41 42#define CEQE_DATA_MASK GENMASK(25, 0) 43#define CEQE_DATA(data) ((data) & cpu_to_le32(CEQE_DATA_MASK)) 44 45#define EQ_ELEM_DESC_TYPE_MASK GENMASK(6, 0) 46#define EQ_ELEM_DESC_SRC_MASK BIT(7) 47#define EQ_ELEM_DESC_SIZE_MASK GENMASK(15, 8) 48#define EQ_ELEM_DESC_WRAPPED_MASK BIT(31) 49#define EQ_ELEM_DESC_GET(val, member) \ 50 FIELD_GET(EQ_ELEM_DESC_##member##_MASK, le32_to_cpu(val)) 51 52#define EQ_CI_SIMPLE_INDIR_CI_MASK GENMASK(20, 0) 53#define EQ_CI_SIMPLE_INDIR_ARMED_MASK BIT(21) 54#define EQ_CI_SIMPLE_INDIR_AEQ_IDX_MASK GENMASK(31, 30) 55#define EQ_CI_SIMPLE_INDIR_CEQ_IDX_MASK GENMASK(31, 24) 56#define EQ_CI_SIMPLE_INDIR_SET(val, member) \ 57 FIELD_PREP(EQ_CI_SIMPLE_INDIR_##member##_MASK, val) 58 59#define EQ_CI_SIMPLE_INDIR_REG_ADDR(eq) \ 60 (((eq)->type == HINIC3_AEQ) ? \ 61 HINIC3_CSR_AEQ_CI_SIMPLE_INDIR_ADDR : \ 62 HINIC3_CSR_CEQ_CI_SIMPLE_INDIR_ADDR) 63 64#define EQ_PROD_IDX_REG_ADDR(eq) \ 65 (((eq)->type == HINIC3_AEQ) ? \ 66 HINIC3_CSR_AEQ_PROD_IDX_ADDR : HINIC3_CSR_CEQ_PROD_IDX_ADDR) 67 68#define EQ_HI_PHYS_ADDR_REG(type, pg_num) \ 69 (((type) == HINIC3_AEQ) ? \ 70 HINIC3_AEQ_HI_PHYS_ADDR_REG(pg_num) : \ 71 HINIC3_CEQ_HI_PHYS_ADDR_REG(pg_num)) 72 73#define EQ_LO_PHYS_ADDR_REG(type, pg_num) \ 74 (((type) == HINIC3_AEQ) ? \ 75 HINIC3_AEQ_LO_PHYS_ADDR_REG(pg_num) : \ 76 HINIC3_CEQ_LO_PHYS_ADDR_REG(pg_num)) 77 78#define EQ_MSIX_RESEND_TIMER_CLEAR 1 79 80#define HINIC3_EQ_MAX_PAGES(eq) \ 81 ((eq)->type == HINIC3_AEQ ? \ 82 HINIC3_AEQ_MAX_PAGES : HINIC3_CEQ_MAX_PAGES) 83 84#define HINIC3_TASK_PROCESS_EQE_LIMIT 1024 85#define HINIC3_EQ_UPDATE_CI_STEP 64 86#define HINIC3_EQS_WQ_NAME "hinic3_eqs" 87 88#define HINIC3_EQ_VALID_SHIFT 31 89#define HINIC3_EQ_WRAPPED(eq) \ 90 ((eq)->wrapped << HINIC3_EQ_VALID_SHIFT) 91 92#define HINIC3_EQ_WRAPPED_SHIFT 20 93#define HINIC3_EQ_CONS_IDX(eq) \ 94 ((eq)->cons_idx | ((eq)->wrapped << HINIC3_EQ_WRAPPED_SHIFT)) 95 96static const struct hinic3_aeq_elem *get_curr_aeq_elem(const struct hinic3_eq *eq) 97{ 98 return get_q_element(&eq->qpages, eq->cons_idx, NULL); 99} 100 101static const __be32 *get_curr_ceq_elem(const struct hinic3_eq *eq) 102{ 103 return get_q_element(&eq->qpages, eq->cons_idx, NULL); 104} 105 106int hinic3_aeq_register_cb(struct hinic3_hwdev *hwdev, 107 enum hinic3_aeq_type event, 108 hinic3_aeq_event_cb hwe_cb) 109{ 110 struct hinic3_aeqs *aeqs; 111 112 aeqs = hwdev->aeqs; 113 aeqs->aeq_cb[event] = hwe_cb; 114 spin_lock_init(&aeqs->aeq_lock); 115 116 return 0; 117} 118 119void hinic3_aeq_unregister_cb(struct hinic3_hwdev *hwdev, 120 enum hinic3_aeq_type event) 121{ 122 struct hinic3_aeqs *aeqs; 123 124 aeqs = hwdev->aeqs; 125 126 spin_lock_bh(&aeqs->aeq_lock); 127 aeqs->aeq_cb[event] = NULL; 128 spin_unlock_bh(&aeqs->aeq_lock); 129} 130 131int hinic3_ceq_register_cb(struct hinic3_hwdev *hwdev, 132 enum hinic3_ceq_event event, 133 hinic3_ceq_event_cb callback) 134{ 135 struct hinic3_ceqs *ceqs; 136 137 ceqs = hwdev->ceqs; 138 ceqs->ceq_cb[event] = callback; 139 spin_lock_init(&ceqs->ceq_lock); 140 141 return 0; 142} 143 144void hinic3_ceq_unregister_cb(struct hinic3_hwdev *hwdev, 145 enum hinic3_ceq_event event) 146{ 147 struct hinic3_ceqs *ceqs; 148 149 ceqs = hwdev->ceqs; 150 151 spin_lock_bh(&ceqs->ceq_lock); 152 ceqs->ceq_cb[event] = NULL; 153 spin_unlock_bh(&ceqs->ceq_lock); 154} 155 156/* Set consumer index in the hw. */ 157static void set_eq_cons_idx(struct hinic3_eq *eq, u32 arm_state) 158{ 159 u32 addr = EQ_CI_SIMPLE_INDIR_REG_ADDR(eq); 160 u32 eq_wrap_ci, val; 161 162 eq_wrap_ci = HINIC3_EQ_CONS_IDX(eq); 163 val = EQ_CI_SIMPLE_INDIR_SET(arm_state, ARMED); 164 if (eq->type == HINIC3_AEQ) { 165 val = val | 166 EQ_CI_SIMPLE_INDIR_SET(eq_wrap_ci, CI) | 167 EQ_CI_SIMPLE_INDIR_SET(eq->q_id, AEQ_IDX); 168 } else { 169 val = val | 170 EQ_CI_SIMPLE_INDIR_SET(eq_wrap_ci, CI) | 171 EQ_CI_SIMPLE_INDIR_SET(eq->q_id, CEQ_IDX); 172 } 173 174 hinic3_hwif_write_reg(eq->hwdev->hwif, addr, val); 175} 176 177static struct hinic3_ceqs *ceq_to_ceqs(const struct hinic3_eq *eq) 178{ 179 return container_of(eq, struct hinic3_ceqs, ceq[eq->q_id]); 180} 181 182static void ceq_event_handler(struct hinic3_ceqs *ceqs, __le32 ceqe) 183{ 184 enum hinic3_ceq_event event = CEQE_TYPE(ceqe); 185 struct hinic3_hwdev *hwdev = ceqs->hwdev; 186 __le32 ceqe_data = CEQE_DATA(ceqe); 187 188 if (event >= HINIC3_MAX_CEQ_EVENTS) { 189 dev_warn(hwdev->dev, "Ceq unknown event:%d, ceqe data: 0x%x\n", 190 event, ceqe_data); 191 return; 192 } 193 194 spin_lock_bh(&ceqs->ceq_lock); 195 if (ceqs->ceq_cb[event]) 196 ceqs->ceq_cb[event](hwdev, ceqe_data); 197 198 spin_unlock_bh(&ceqs->ceq_lock); 199} 200 201static struct hinic3_aeqs *aeq_to_aeqs(const struct hinic3_eq *eq) 202{ 203 return container_of(eq, struct hinic3_aeqs, aeq[eq->q_id]); 204} 205 206static void aeq_event_handler(struct hinic3_aeqs *aeqs, __le32 aeqe, 207 const struct hinic3_aeq_elem *aeqe_pos) 208{ 209 struct hinic3_hwdev *hwdev = aeqs->hwdev; 210 u8 data[HINIC3_AEQE_DATA_SIZE], size; 211 enum hinic3_aeq_type event; 212 hinic3_aeq_event_cb hwe_cb; 213 214 if (EQ_ELEM_DESC_GET(aeqe, SRC)) 215 return; 216 217 event = EQ_ELEM_DESC_GET(aeqe, TYPE); 218 if (event >= HINIC3_MAX_AEQ_EVENTS) { 219 dev_warn(hwdev->dev, "Aeq unknown event:%d\n", event); 220 return; 221 } 222 223 memcpy(data, aeqe_pos->aeqe_data, HINIC3_AEQE_DATA_SIZE); 224 swab32_array((u32 *)data, HINIC3_AEQE_DATA_SIZE / sizeof(u32)); 225 size = EQ_ELEM_DESC_GET(aeqe, SIZE); 226 227 spin_lock_bh(&aeqs->aeq_lock); 228 hwe_cb = aeqs->aeq_cb[event]; 229 if (hwe_cb) 230 hwe_cb(aeqs->hwdev, data, size); 231 spin_unlock_bh(&aeqs->aeq_lock); 232} 233 234static int aeq_irq_handler(struct hinic3_eq *eq) 235{ 236 const struct hinic3_aeq_elem *aeqe_pos; 237 struct hinic3_aeqs *aeqs; 238 u32 i, eqe_cnt = 0; 239 __le32 aeqe; 240 241 aeqs = aeq_to_aeqs(eq); 242 for (i = 0; i < HINIC3_TASK_PROCESS_EQE_LIMIT; i++) { 243 aeqe_pos = get_curr_aeq_elem(eq); 244 aeqe = (__force __le32)swab32((__force __u32)aeqe_pos->desc); 245 /* HW updates wrapped bit, when it adds eq element event */ 246 if (EQ_ELEM_DESC_GET(aeqe, WRAPPED) == eq->wrapped) 247 return 0; 248 249 /* Prevent speculative reads from element */ 250 dma_rmb(); 251 aeq_event_handler(aeqs, aeqe, aeqe_pos); 252 eq->cons_idx++; 253 if (eq->cons_idx == eq->eq_len) { 254 eq->cons_idx = 0; 255 eq->wrapped = !eq->wrapped; 256 } 257 258 if (++eqe_cnt >= HINIC3_EQ_UPDATE_CI_STEP) { 259 eqe_cnt = 0; 260 set_eq_cons_idx(eq, HINIC3_EQ_NOT_ARMED); 261 } 262 } 263 264 return -EAGAIN; 265} 266 267static int ceq_irq_handler(struct hinic3_eq *eq) 268{ 269 struct hinic3_ceqs *ceqs; 270 u32 eqe_cnt = 0; 271 __be32 ceqe_raw; 272 __le32 ceqe; 273 u32 i; 274 275 ceqs = ceq_to_ceqs(eq); 276 for (i = 0; i < HINIC3_TASK_PROCESS_EQE_LIMIT; i++) { 277 ceqe_raw = *get_curr_ceq_elem(eq); 278 ceqe = (__force __le32)swab32((__force __u32)ceqe_raw); 279 280 /* HW updates wrapped bit, when it adds eq element event */ 281 if (EQ_ELEM_DESC_GET(ceqe, WRAPPED) == eq->wrapped) 282 return 0; 283 284 ceq_event_handler(ceqs, ceqe); 285 eq->cons_idx++; 286 if (eq->cons_idx == eq->eq_len) { 287 eq->cons_idx = 0; 288 eq->wrapped = !eq->wrapped; 289 } 290 291 if (++eqe_cnt >= HINIC3_EQ_UPDATE_CI_STEP) { 292 eqe_cnt = 0; 293 set_eq_cons_idx(eq, HINIC3_EQ_NOT_ARMED); 294 } 295 } 296 297 return -EAGAIN; 298} 299 300static void reschedule_aeq_handler(struct hinic3_eq *eq) 301{ 302 struct hinic3_aeqs *aeqs = aeq_to_aeqs(eq); 303 304 queue_work(aeqs->workq, &eq->aeq_work); 305} 306 307static int eq_irq_handler(struct hinic3_eq *eq) 308{ 309 int err; 310 311 if (eq->type == HINIC3_AEQ) 312 err = aeq_irq_handler(eq); 313 else 314 err = ceq_irq_handler(eq); 315 316 set_eq_cons_idx(eq, err ? HINIC3_EQ_NOT_ARMED : 317 HINIC3_EQ_ARMED); 318 319 return err; 320} 321 322static void aeq_irq_work(struct work_struct *work) 323{ 324 struct hinic3_eq *eq = container_of(work, struct hinic3_eq, aeq_work); 325 int err; 326 327 err = eq_irq_handler(eq); 328 if (err) 329 reschedule_aeq_handler(eq); 330} 331 332static irqreturn_t aeq_interrupt(int irq, void *data) 333{ 334 struct workqueue_struct *workq; 335 struct hinic3_eq *aeq = data; 336 struct hinic3_hwdev *hwdev; 337 struct hinic3_aeqs *aeqs; 338 339 aeqs = aeq_to_aeqs(aeq); 340 hwdev = aeq->hwdev; 341 342 /* clear resend timer cnt register */ 343 workq = aeqs->workq; 344 hinic3_msix_intr_clear_resend_bit(hwdev, aeq->msix_entry_idx, 345 EQ_MSIX_RESEND_TIMER_CLEAR); 346 queue_work(workq, &aeq->aeq_work); 347 348 return IRQ_HANDLED; 349} 350 351static irqreturn_t ceq_interrupt(int irq, void *data) 352{ 353 struct hinic3_eq *ceq = data; 354 int err; 355 356 /* clear resend timer counters */ 357 hinic3_msix_intr_clear_resend_bit(ceq->hwdev, ceq->msix_entry_idx, 358 EQ_MSIX_RESEND_TIMER_CLEAR); 359 err = eq_irq_handler(ceq); 360 if (err) 361 return IRQ_NONE; 362 363 return IRQ_HANDLED; 364} 365 366static int hinic3_set_ceq_ctrl_reg(struct hinic3_hwdev *hwdev, u16 q_id, 367 u32 ctrl0, u32 ctrl1) 368{ 369 struct comm_cmd_set_ceq_ctrl_reg ceq_ctrl = {}; 370 struct mgmt_msg_params msg_params = {}; 371 int err; 372 373 ceq_ctrl.func_id = hinic3_global_func_id(hwdev); 374 ceq_ctrl.q_id = q_id; 375 ceq_ctrl.ctrl0 = ctrl0; 376 ceq_ctrl.ctrl1 = ctrl1; 377 378 mgmt_msg_params_init_default(&msg_params, &ceq_ctrl, sizeof(ceq_ctrl)); 379 380 err = hinic3_send_mbox_to_mgmt(hwdev, MGMT_MOD_COMM, 381 COMM_CMD_SET_CEQ_CTRL_REG, &msg_params); 382 if (err || ceq_ctrl.head.status) { 383 dev_err(hwdev->dev, "Failed to set ceq %u ctrl reg, err: %d status: 0x%x\n", 384 q_id, err, ceq_ctrl.head.status); 385 return -EFAULT; 386 } 387 388 return 0; 389} 390 391static int set_eq_ctrls(struct hinic3_eq *eq) 392{ 393 struct hinic3_hwif *hwif = eq->hwdev->hwif; 394 struct hinic3_queue_pages *qpages; 395 u8 pci_intf_idx, elem_size; 396 u32 mask, ctrl0, ctrl1; 397 u32 page_size_val; 398 int err; 399 400 qpages = &eq->qpages; 401 page_size_val = ilog2(qpages->page_size / HINIC3_MIN_PAGE_SIZE); 402 pci_intf_idx = hwif->attr.pci_intf_idx; 403 404 if (eq->type == HINIC3_AEQ) { 405 /* set ctrl0 using read-modify-write */ 406 mask = AEQ_CTRL_0_INTR_IDX_MASK | 407 AEQ_CTRL_0_DMA_ATTR_MASK | 408 AEQ_CTRL_0_PCI_INTF_IDX_MASK | 409 AEQ_CTRL_0_INTR_MODE_MASK; 410 ctrl0 = hinic3_hwif_read_reg(hwif, HINIC3_CSR_AEQ_CTRL_0_ADDR); 411 ctrl0 = (ctrl0 & ~mask) | 412 AEQ_CTRL_0_SET(eq->msix_entry_idx, INTR_IDX) | 413 AEQ_CTRL_0_SET(0, DMA_ATTR) | 414 AEQ_CTRL_0_SET(pci_intf_idx, PCI_INTF_IDX) | 415 AEQ_CTRL_0_SET(HINIC3_INTR_MODE_ARMED, INTR_MODE); 416 hinic3_hwif_write_reg(hwif, HINIC3_CSR_AEQ_CTRL_0_ADDR, ctrl0); 417 418 /* HW expects log2(number of 32 byte units). */ 419 elem_size = qpages->elem_size_shift - 5; 420 ctrl1 = AEQ_CTRL_1_SET(eq->eq_len, LEN) | 421 AEQ_CTRL_1_SET(elem_size, ELEM_SIZE) | 422 AEQ_CTRL_1_SET(page_size_val, PAGE_SIZE); 423 hinic3_hwif_write_reg(hwif, HINIC3_CSR_AEQ_CTRL_1_ADDR, ctrl1); 424 } else { 425 ctrl0 = CEQ_CTRL_0_SET(eq->msix_entry_idx, INTR_IDX) | 426 CEQ_CTRL_0_SET(0, DMA_ATTR) | 427 CEQ_CTRL_0_SET(0, LIMIT_KICK) | 428 CEQ_CTRL_0_SET(pci_intf_idx, PCI_INTF_IDX) | 429 CEQ_CTRL_0_SET(page_size_val, PAGE_SIZE) | 430 CEQ_CTRL_0_SET(HINIC3_INTR_MODE_ARMED, INTR_MODE); 431 432 ctrl1 = CEQ_CTRL_1_SET(eq->eq_len, LEN); 433 434 /* set ceq ctrl reg through mgmt cpu */ 435 err = hinic3_set_ceq_ctrl_reg(eq->hwdev, eq->q_id, ctrl0, 436 ctrl1); 437 if (err) 438 return err; 439 } 440 441 return 0; 442} 443 444static void ceq_elements_init(struct hinic3_eq *eq, u32 init_val) 445{ 446 __be32 *ceqe; 447 u32 i; 448 449 for (i = 0; i < eq->eq_len; i++) { 450 ceqe = get_q_element(&eq->qpages, i, NULL); 451 *ceqe = cpu_to_be32(init_val); 452 } 453 454 wmb(); /* Clear ceq elements bit */ 455} 456 457static void aeq_elements_init(struct hinic3_eq *eq, u32 init_val) 458{ 459 struct hinic3_aeq_elem *aeqe; 460 u32 i; 461 462 for (i = 0; i < eq->eq_len; i++) { 463 aeqe = get_q_element(&eq->qpages, i, NULL); 464 aeqe->desc = cpu_to_be32(init_val); 465 } 466 467 wmb(); /* Clear aeq elements bit */ 468} 469 470static void eq_elements_init(struct hinic3_eq *eq, u32 init_val) 471{ 472 if (eq->type == HINIC3_AEQ) 473 aeq_elements_init(eq, init_val); 474 else 475 ceq_elements_init(eq, init_val); 476} 477 478static int alloc_eq_pages(struct hinic3_eq *eq) 479{ 480 struct hinic3_hwif *hwif = eq->hwdev->hwif; 481 struct hinic3_queue_pages *qpages; 482 dma_addr_t page_paddr; 483 u32 reg, init_val; 484 u16 pg_idx; 485 int err; 486 487 qpages = &eq->qpages; 488 err = hinic3_queue_pages_alloc(eq->hwdev, qpages, HINIC3_MIN_PAGE_SIZE); 489 if (err) 490 return err; 491 492 for (pg_idx = 0; pg_idx < qpages->num_pages; pg_idx++) { 493 page_paddr = qpages->pages[pg_idx].align_paddr; 494 reg = EQ_HI_PHYS_ADDR_REG(eq->type, pg_idx); 495 hinic3_hwif_write_reg(hwif, reg, upper_32_bits(page_paddr)); 496 reg = EQ_LO_PHYS_ADDR_REG(eq->type, pg_idx); 497 hinic3_hwif_write_reg(hwif, reg, lower_32_bits(page_paddr)); 498 } 499 500 init_val = HINIC3_EQ_WRAPPED(eq); 501 eq_elements_init(eq, init_val); 502 503 return 0; 504} 505 506static void eq_calc_page_size_and_num(struct hinic3_eq *eq, u32 elem_size) 507{ 508 u32 max_pages, min_page_size, page_size, total_size; 509 510 /* No need for complicated arithmetic. All values must be power of 2. 511 * Multiplications give power of 2 and divisions give power of 2 without 512 * remainder. 513 */ 514 max_pages = HINIC3_EQ_MAX_PAGES(eq); 515 min_page_size = HINIC3_MIN_PAGE_SIZE; 516 total_size = eq->eq_len * elem_size; 517 518 if (total_size <= max_pages * min_page_size) 519 page_size = min_page_size; 520 else 521 page_size = total_size / max_pages; 522 523 hinic3_queue_pages_init(&eq->qpages, eq->eq_len, page_size, elem_size); 524} 525 526static int request_eq_irq(struct hinic3_eq *eq) 527{ 528 int err; 529 530 if (eq->type == HINIC3_AEQ) { 531 INIT_WORK(&eq->aeq_work, aeq_irq_work); 532 snprintf(eq->irq_name, sizeof(eq->irq_name), 533 "hinic3_aeq%u@pci:%s", eq->q_id, 534 pci_name(eq->hwdev->pdev)); 535 err = request_irq(eq->irq_id, aeq_interrupt, 0, 536 eq->irq_name, eq); 537 } else { 538 snprintf(eq->irq_name, sizeof(eq->irq_name), 539 "hinic3_ceq%u@pci:%s", eq->q_id, 540 pci_name(eq->hwdev->pdev)); 541 err = request_threaded_irq(eq->irq_id, NULL, ceq_interrupt, 542 IRQF_ONESHOT, eq->irq_name, eq); 543 } 544 545 return err; 546} 547 548static void reset_eq(struct hinic3_eq *eq) 549{ 550 /* clear eq_len to force eqe drop in hardware */ 551 if (eq->type == HINIC3_AEQ) 552 hinic3_hwif_write_reg(eq->hwdev->hwif, 553 HINIC3_CSR_AEQ_CTRL_1_ADDR, 0); 554 else 555 hinic3_set_ceq_ctrl_reg(eq->hwdev, eq->q_id, 0, 0); 556 557 hinic3_hwif_write_reg(eq->hwdev->hwif, EQ_PROD_IDX_REG_ADDR(eq), 0); 558} 559 560static int init_eq(struct hinic3_eq *eq, struct hinic3_hwdev *hwdev, u16 q_id, 561 u32 q_len, enum hinic3_eq_type type, 562 struct msix_entry *msix_entry) 563{ 564 u32 elem_size; 565 int err; 566 567 eq->hwdev = hwdev; 568 eq->q_id = q_id; 569 eq->type = type; 570 eq->eq_len = q_len; 571 572 /* Indirect access should set q_id first */ 573 hinic3_hwif_write_reg(hwdev->hwif, HINIC3_EQ_INDIR_IDX_ADDR(eq->type), 574 eq->q_id); 575 576 reset_eq(eq); 577 578 eq->cons_idx = 0; 579 eq->wrapped = 0; 580 581 elem_size = (type == HINIC3_AEQ) ? HINIC3_AEQE_SIZE : HINIC3_CEQE_SIZE; 582 eq_calc_page_size_and_num(eq, elem_size); 583 584 err = alloc_eq_pages(eq); 585 if (err) { 586 dev_err(hwdev->dev, "Failed to allocate pages for eq\n"); 587 return err; 588 } 589 590 eq->msix_entry_idx = msix_entry->entry; 591 eq->irq_id = msix_entry->vector; 592 593 err = set_eq_ctrls(eq); 594 if (err) { 595 dev_err(hwdev->dev, "Failed to set ctrls for eq\n"); 596 goto err_free_queue_pages; 597 } 598 599 set_eq_cons_idx(eq, HINIC3_EQ_ARMED); 600 601 err = request_eq_irq(eq); 602 if (err) { 603 dev_err(hwdev->dev, 604 "Failed to request irq for the eq, err: %d\n", err); 605 goto err_free_queue_pages; 606 } 607 608 hinic3_set_msix_state(hwdev, eq->msix_entry_idx, HINIC3_MSIX_DISABLE); 609 610 return 0; 611 612err_free_queue_pages: 613 hinic3_queue_pages_free(hwdev, &eq->qpages); 614 615 return err; 616} 617 618static void remove_eq(struct hinic3_eq *eq) 619{ 620 hinic3_set_msix_state(eq->hwdev, eq->msix_entry_idx, 621 HINIC3_MSIX_DISABLE); 622 free_irq(eq->irq_id, eq); 623 /* Indirect access should set q_id first */ 624 hinic3_hwif_write_reg(eq->hwdev->hwif, 625 HINIC3_EQ_INDIR_IDX_ADDR(eq->type), 626 eq->q_id); 627 628 if (eq->type == HINIC3_AEQ) { 629 disable_work_sync(&eq->aeq_work); 630 /* clear eq_len to avoid hw access host memory */ 631 hinic3_hwif_write_reg(eq->hwdev->hwif, 632 HINIC3_CSR_AEQ_CTRL_1_ADDR, 0); 633 } else { 634 hinic3_set_ceq_ctrl_reg(eq->hwdev, eq->q_id, 0, 0); 635 } 636 637 /* update consumer index to avoid invalid interrupt */ 638 eq->cons_idx = hinic3_hwif_read_reg(eq->hwdev->hwif, 639 EQ_PROD_IDX_REG_ADDR(eq)); 640 set_eq_cons_idx(eq, HINIC3_EQ_NOT_ARMED); 641 hinic3_queue_pages_free(eq->hwdev, &eq->qpages); 642} 643 644int hinic3_aeqs_init(struct hinic3_hwdev *hwdev, u16 num_aeqs, 645 struct msix_entry *msix_entries) 646{ 647 struct hinic3_aeqs *aeqs; 648 u16 q_id; 649 int err; 650 651 aeqs = kzalloc(sizeof(*aeqs), GFP_KERNEL); 652 if (!aeqs) 653 return -ENOMEM; 654 655 hwdev->aeqs = aeqs; 656 aeqs->hwdev = hwdev; 657 aeqs->num_aeqs = num_aeqs; 658 aeqs->workq = alloc_workqueue(HINIC3_EQS_WQ_NAME, WQ_MEM_RECLAIM, 659 HINIC3_MAX_AEQS); 660 if (!aeqs->workq) { 661 dev_err(hwdev->dev, "Failed to initialize aeq workqueue\n"); 662 err = -ENOMEM; 663 goto err_free_aeqs; 664 } 665 666 for (q_id = 0; q_id < num_aeqs; q_id++) { 667 err = init_eq(&aeqs->aeq[q_id], hwdev, q_id, 668 HINIC3_DEFAULT_AEQ_LEN, HINIC3_AEQ, 669 &msix_entries[q_id]); 670 if (err) { 671 dev_err(hwdev->dev, "Failed to init aeq %u\n", 672 q_id); 673 goto err_remove_eqs; 674 } 675 } 676 for (q_id = 0; q_id < num_aeqs; q_id++) 677 hinic3_set_msix_state(hwdev, aeqs->aeq[q_id].msix_entry_idx, 678 HINIC3_MSIX_ENABLE); 679 680 return 0; 681 682err_remove_eqs: 683 while (q_id > 0) { 684 q_id--; 685 remove_eq(&aeqs->aeq[q_id]); 686 } 687 688 destroy_workqueue(aeqs->workq); 689 690err_free_aeqs: 691 kfree(aeqs); 692 693 return err; 694} 695 696void hinic3_aeqs_free(struct hinic3_hwdev *hwdev) 697{ 698 struct hinic3_aeqs *aeqs = hwdev->aeqs; 699 enum hinic3_aeq_type aeq_event; 700 struct hinic3_eq *eq; 701 u16 q_id; 702 703 for (q_id = 0; q_id < aeqs->num_aeqs; q_id++) { 704 eq = aeqs->aeq + q_id; 705 remove_eq(eq); 706 hinic3_free_irq(hwdev, eq->irq_id); 707 } 708 709 for (aeq_event = 0; aeq_event < HINIC3_MAX_AEQ_EVENTS; aeq_event++) 710 hinic3_aeq_unregister_cb(hwdev, aeq_event); 711 712 destroy_workqueue(aeqs->workq); 713 714 kfree(aeqs); 715} 716 717int hinic3_ceqs_init(struct hinic3_hwdev *hwdev, u16 num_ceqs, 718 struct msix_entry *msix_entries) 719{ 720 struct hinic3_ceqs *ceqs; 721 u16 q_id; 722 int err; 723 724 ceqs = kzalloc(sizeof(*ceqs), GFP_KERNEL); 725 if (!ceqs) 726 return -ENOMEM; 727 728 hwdev->ceqs = ceqs; 729 ceqs->hwdev = hwdev; 730 ceqs->num_ceqs = num_ceqs; 731 732 for (q_id = 0; q_id < num_ceqs; q_id++) { 733 err = init_eq(&ceqs->ceq[q_id], hwdev, q_id, 734 HINIC3_DEFAULT_CEQ_LEN, HINIC3_CEQ, 735 &msix_entries[q_id]); 736 if (err) { 737 dev_err(hwdev->dev, "Failed to init ceq %u\n", 738 q_id); 739 goto err_free_ceqs; 740 } 741 } 742 for (q_id = 0; q_id < num_ceqs; q_id++) 743 hinic3_set_msix_state(hwdev, ceqs->ceq[q_id].msix_entry_idx, 744 HINIC3_MSIX_ENABLE); 745 746 return 0; 747 748err_free_ceqs: 749 while (q_id > 0) { 750 q_id--; 751 remove_eq(&ceqs->ceq[q_id]); 752 } 753 754 kfree(ceqs); 755 756 return err; 757} 758 759void hinic3_ceqs_free(struct hinic3_hwdev *hwdev) 760{ 761 struct hinic3_ceqs *ceqs = hwdev->ceqs; 762 enum hinic3_ceq_event ceq_event; 763 struct hinic3_eq *eq; 764 u16 q_id; 765 766 for (q_id = 0; q_id < ceqs->num_ceqs; q_id++) { 767 eq = ceqs->ceq + q_id; 768 remove_eq(eq); 769 hinic3_free_irq(hwdev, eq->irq_id); 770 } 771 772 for (ceq_event = 0; ceq_event < HINIC3_MAX_CEQ_EVENTS; ceq_event++) 773 hinic3_ceq_unregister_cb(hwdev, ceq_event); 774 775 kfree(ceqs); 776}
~/
Read-only file preview.