18077c727SJoshua Hay // SPDX-License-Identifier: GPL-2.0-only 28077c727SJoshua Hay /* Copyright (C) 2023 Intel Corporation */ 38077c727SJoshua Hay 48077c727SJoshua Hay #include "idpf.h" 58077c727SJoshua Hay 6*4930fbf4SPavan Kumar Linga const char * const idpf_vport_vc_state_str[] = { 7*4930fbf4SPavan Kumar Linga IDPF_FOREACH_VPORT_VC_STATE(IDPF_GEN_STRING) 8*4930fbf4SPavan Kumar Linga }; 9*4930fbf4SPavan Kumar Linga 10*4930fbf4SPavan Kumar Linga /** 11*4930fbf4SPavan Kumar Linga * idpf_init_vector_stack - Fill the MSIX vector stack with vector index 12*4930fbf4SPavan Kumar Linga * @adapter: private data struct 13*4930fbf4SPavan Kumar Linga * 14*4930fbf4SPavan Kumar Linga * Return 0 on success, error on failure 15*4930fbf4SPavan Kumar Linga */ 16*4930fbf4SPavan Kumar Linga static int idpf_init_vector_stack(struct idpf_adapter *adapter) 17*4930fbf4SPavan Kumar Linga { 18*4930fbf4SPavan Kumar Linga struct idpf_vector_lifo *stack; 19*4930fbf4SPavan Kumar Linga u16 min_vec; 20*4930fbf4SPavan Kumar Linga u32 i; 21*4930fbf4SPavan Kumar Linga 22*4930fbf4SPavan Kumar Linga mutex_lock(&adapter->vector_lock); 23*4930fbf4SPavan Kumar Linga min_vec = adapter->num_msix_entries - adapter->num_avail_msix; 24*4930fbf4SPavan Kumar Linga stack = &adapter->vector_stack; 25*4930fbf4SPavan Kumar Linga stack->size = adapter->num_msix_entries; 26*4930fbf4SPavan Kumar Linga /* set the base and top to point at start of the 'free pool' to 27*4930fbf4SPavan Kumar Linga * distribute the unused vectors on-demand basis 28*4930fbf4SPavan Kumar Linga */ 29*4930fbf4SPavan Kumar Linga stack->base = min_vec; 30*4930fbf4SPavan Kumar Linga stack->top = min_vec; 31*4930fbf4SPavan Kumar Linga 32*4930fbf4SPavan Kumar Linga stack->vec_idx = kcalloc(stack->size, sizeof(u16), GFP_KERNEL); 33*4930fbf4SPavan Kumar Linga if (!stack->vec_idx) { 34*4930fbf4SPavan Kumar Linga mutex_unlock(&adapter->vector_lock); 35*4930fbf4SPavan Kumar Linga 36*4930fbf4SPavan Kumar Linga return -ENOMEM; 37*4930fbf4SPavan Kumar Linga } 38*4930fbf4SPavan Kumar Linga 39*4930fbf4SPavan Kumar Linga for (i = 0; i < stack->size; i++) 40*4930fbf4SPavan Kumar Linga stack->vec_idx[i] = i; 41*4930fbf4SPavan Kumar Linga 42*4930fbf4SPavan Kumar Linga mutex_unlock(&adapter->vector_lock); 43*4930fbf4SPavan Kumar Linga 44*4930fbf4SPavan Kumar Linga return 0; 45*4930fbf4SPavan Kumar Linga } 46*4930fbf4SPavan Kumar Linga 47*4930fbf4SPavan Kumar Linga /** 48*4930fbf4SPavan Kumar Linga * idpf_deinit_vector_stack - zero out the MSIX vector stack 49*4930fbf4SPavan Kumar Linga * @adapter: private data struct 50*4930fbf4SPavan Kumar Linga */ 51*4930fbf4SPavan Kumar Linga static void idpf_deinit_vector_stack(struct idpf_adapter *adapter) 52*4930fbf4SPavan Kumar Linga { 53*4930fbf4SPavan Kumar Linga struct idpf_vector_lifo *stack; 54*4930fbf4SPavan Kumar Linga 55*4930fbf4SPavan Kumar Linga mutex_lock(&adapter->vector_lock); 56*4930fbf4SPavan Kumar Linga stack = &adapter->vector_stack; 57*4930fbf4SPavan Kumar Linga kfree(stack->vec_idx); 58*4930fbf4SPavan Kumar Linga stack->vec_idx = NULL; 59*4930fbf4SPavan Kumar Linga mutex_unlock(&adapter->vector_lock); 60*4930fbf4SPavan Kumar Linga } 61*4930fbf4SPavan Kumar Linga 62*4930fbf4SPavan Kumar Linga /** 63*4930fbf4SPavan Kumar Linga * idpf_mb_intr_rel_irq - Free the IRQ association with the OS 64*4930fbf4SPavan Kumar Linga * @adapter: adapter structure 65*4930fbf4SPavan Kumar Linga * 66*4930fbf4SPavan Kumar Linga * This will also disable interrupt mode and queue up mailbox task. Mailbox 67*4930fbf4SPavan Kumar Linga * task will reschedule itself if not in interrupt mode. 68*4930fbf4SPavan Kumar Linga */ 69*4930fbf4SPavan Kumar Linga static void idpf_mb_intr_rel_irq(struct idpf_adapter *adapter) 70*4930fbf4SPavan Kumar Linga { 71*4930fbf4SPavan Kumar Linga clear_bit(IDPF_MB_INTR_MODE, adapter->flags); 72*4930fbf4SPavan Kumar Linga free_irq(adapter->msix_entries[0].vector, adapter); 73*4930fbf4SPavan Kumar Linga queue_delayed_work(adapter->mbx_wq, &adapter->mbx_task, 0); 74*4930fbf4SPavan Kumar Linga } 75*4930fbf4SPavan Kumar Linga 76*4930fbf4SPavan Kumar Linga /** 77*4930fbf4SPavan Kumar Linga * idpf_intr_rel - Release interrupt capabilities and free memory 78*4930fbf4SPavan Kumar Linga * @adapter: adapter to disable interrupts on 79*4930fbf4SPavan Kumar Linga */ 80*4930fbf4SPavan Kumar Linga void idpf_intr_rel(struct idpf_adapter *adapter) 81*4930fbf4SPavan Kumar Linga { 82*4930fbf4SPavan Kumar Linga int err; 83*4930fbf4SPavan Kumar Linga 84*4930fbf4SPavan Kumar Linga if (!adapter->msix_entries) 85*4930fbf4SPavan Kumar Linga return; 86*4930fbf4SPavan Kumar Linga 87*4930fbf4SPavan Kumar Linga idpf_mb_intr_rel_irq(adapter); 88*4930fbf4SPavan Kumar Linga pci_free_irq_vectors(adapter->pdev); 89*4930fbf4SPavan Kumar Linga 90*4930fbf4SPavan Kumar Linga err = idpf_send_dealloc_vectors_msg(adapter); 91*4930fbf4SPavan Kumar Linga if (err) 92*4930fbf4SPavan Kumar Linga dev_err(&adapter->pdev->dev, 93*4930fbf4SPavan Kumar Linga "Failed to deallocate vectors: %d\n", err); 94*4930fbf4SPavan Kumar Linga 95*4930fbf4SPavan Kumar Linga idpf_deinit_vector_stack(adapter); 96*4930fbf4SPavan Kumar Linga kfree(adapter->msix_entries); 97*4930fbf4SPavan Kumar Linga adapter->msix_entries = NULL; 98*4930fbf4SPavan Kumar Linga } 99*4930fbf4SPavan Kumar Linga 100*4930fbf4SPavan Kumar Linga /** 101*4930fbf4SPavan Kumar Linga * idpf_mb_intr_clean - Interrupt handler for the mailbox 102*4930fbf4SPavan Kumar Linga * @irq: interrupt number 103*4930fbf4SPavan Kumar Linga * @data: pointer to the adapter structure 104*4930fbf4SPavan Kumar Linga */ 105*4930fbf4SPavan Kumar Linga static irqreturn_t idpf_mb_intr_clean(int __always_unused irq, void *data) 106*4930fbf4SPavan Kumar Linga { 107*4930fbf4SPavan Kumar Linga struct idpf_adapter *adapter = (struct idpf_adapter *)data; 108*4930fbf4SPavan Kumar Linga 109*4930fbf4SPavan Kumar Linga queue_delayed_work(adapter->mbx_wq, &adapter->mbx_task, 0); 110*4930fbf4SPavan Kumar Linga 111*4930fbf4SPavan Kumar Linga return IRQ_HANDLED; 112*4930fbf4SPavan Kumar Linga } 113*4930fbf4SPavan Kumar Linga 114*4930fbf4SPavan Kumar Linga /** 115*4930fbf4SPavan Kumar Linga * idpf_mb_irq_enable - Enable MSIX interrupt for the mailbox 116*4930fbf4SPavan Kumar Linga * @adapter: adapter to get the hardware address for register write 117*4930fbf4SPavan Kumar Linga */ 118*4930fbf4SPavan Kumar Linga static void idpf_mb_irq_enable(struct idpf_adapter *adapter) 119*4930fbf4SPavan Kumar Linga { 120*4930fbf4SPavan Kumar Linga struct idpf_intr_reg *intr = &adapter->mb_vector.intr_reg; 121*4930fbf4SPavan Kumar Linga u32 val; 122*4930fbf4SPavan Kumar Linga 123*4930fbf4SPavan Kumar Linga val = intr->dyn_ctl_intena_m | intr->dyn_ctl_itridx_m; 124*4930fbf4SPavan Kumar Linga writel(val, intr->dyn_ctl); 125*4930fbf4SPavan Kumar Linga writel(intr->icr_ena_ctlq_m, intr->icr_ena); 126*4930fbf4SPavan Kumar Linga } 127*4930fbf4SPavan Kumar Linga 128*4930fbf4SPavan Kumar Linga /** 129*4930fbf4SPavan Kumar Linga * idpf_mb_intr_req_irq - Request irq for the mailbox interrupt 130*4930fbf4SPavan Kumar Linga * @adapter: adapter structure to pass to the mailbox irq handler 131*4930fbf4SPavan Kumar Linga */ 132*4930fbf4SPavan Kumar Linga static int idpf_mb_intr_req_irq(struct idpf_adapter *adapter) 133*4930fbf4SPavan Kumar Linga { 134*4930fbf4SPavan Kumar Linga struct idpf_q_vector *mb_vector = &adapter->mb_vector; 135*4930fbf4SPavan Kumar Linga int irq_num, mb_vidx = 0, err; 136*4930fbf4SPavan Kumar Linga 137*4930fbf4SPavan Kumar Linga irq_num = adapter->msix_entries[mb_vidx].vector; 138*4930fbf4SPavan Kumar Linga mb_vector->name = kasprintf(GFP_KERNEL, "%s-%s-%d", 139*4930fbf4SPavan Kumar Linga dev_driver_string(&adapter->pdev->dev), 140*4930fbf4SPavan Kumar Linga "Mailbox", mb_vidx); 141*4930fbf4SPavan Kumar Linga err = request_irq(irq_num, adapter->irq_mb_handler, 0, 142*4930fbf4SPavan Kumar Linga mb_vector->name, adapter); 143*4930fbf4SPavan Kumar Linga if (err) { 144*4930fbf4SPavan Kumar Linga dev_err(&adapter->pdev->dev, 145*4930fbf4SPavan Kumar Linga "IRQ request for mailbox failed, error: %d\n", err); 146*4930fbf4SPavan Kumar Linga 147*4930fbf4SPavan Kumar Linga return err; 148*4930fbf4SPavan Kumar Linga } 149*4930fbf4SPavan Kumar Linga 150*4930fbf4SPavan Kumar Linga set_bit(IDPF_MB_INTR_MODE, adapter->flags); 151*4930fbf4SPavan Kumar Linga 152*4930fbf4SPavan Kumar Linga return 0; 153*4930fbf4SPavan Kumar Linga } 154*4930fbf4SPavan Kumar Linga 155*4930fbf4SPavan Kumar Linga /** 156*4930fbf4SPavan Kumar Linga * idpf_set_mb_vec_id - Set vector index for mailbox 157*4930fbf4SPavan Kumar Linga * @adapter: adapter structure to access the vector chunks 158*4930fbf4SPavan Kumar Linga * 159*4930fbf4SPavan Kumar Linga * The first vector id in the requested vector chunks from the CP is for 160*4930fbf4SPavan Kumar Linga * the mailbox 161*4930fbf4SPavan Kumar Linga */ 162*4930fbf4SPavan Kumar Linga static void idpf_set_mb_vec_id(struct idpf_adapter *adapter) 163*4930fbf4SPavan Kumar Linga { 164*4930fbf4SPavan Kumar Linga if (adapter->req_vec_chunks) 165*4930fbf4SPavan Kumar Linga adapter->mb_vector.v_idx = 166*4930fbf4SPavan Kumar Linga le16_to_cpu(adapter->caps.mailbox_vector_id); 167*4930fbf4SPavan Kumar Linga else 168*4930fbf4SPavan Kumar Linga adapter->mb_vector.v_idx = 0; 169*4930fbf4SPavan Kumar Linga } 170*4930fbf4SPavan Kumar Linga 171*4930fbf4SPavan Kumar Linga /** 172*4930fbf4SPavan Kumar Linga * idpf_mb_intr_init - Initialize the mailbox interrupt 173*4930fbf4SPavan Kumar Linga * @adapter: adapter structure to store the mailbox vector 174*4930fbf4SPavan Kumar Linga */ 175*4930fbf4SPavan Kumar Linga static int idpf_mb_intr_init(struct idpf_adapter *adapter) 176*4930fbf4SPavan Kumar Linga { 177*4930fbf4SPavan Kumar Linga adapter->dev_ops.reg_ops.mb_intr_reg_init(adapter); 178*4930fbf4SPavan Kumar Linga adapter->irq_mb_handler = idpf_mb_intr_clean; 179*4930fbf4SPavan Kumar Linga 180*4930fbf4SPavan Kumar Linga return idpf_mb_intr_req_irq(adapter); 181*4930fbf4SPavan Kumar Linga } 182*4930fbf4SPavan Kumar Linga 183*4930fbf4SPavan Kumar Linga /** 184*4930fbf4SPavan Kumar Linga * idpf_intr_req - Request interrupt capabilities 185*4930fbf4SPavan Kumar Linga * @adapter: adapter to enable interrupts on 186*4930fbf4SPavan Kumar Linga * 187*4930fbf4SPavan Kumar Linga * Returns 0 on success, negative on failure 188*4930fbf4SPavan Kumar Linga */ 189*4930fbf4SPavan Kumar Linga int idpf_intr_req(struct idpf_adapter *adapter) 190*4930fbf4SPavan Kumar Linga { 191*4930fbf4SPavan Kumar Linga u16 default_vports = idpf_get_default_vports(adapter); 192*4930fbf4SPavan Kumar Linga int num_q_vecs, total_vecs, num_vec_ids; 193*4930fbf4SPavan Kumar Linga int min_vectors, v_actual, err; 194*4930fbf4SPavan Kumar Linga unsigned int vector; 195*4930fbf4SPavan Kumar Linga u16 *vecids; 196*4930fbf4SPavan Kumar Linga 197*4930fbf4SPavan Kumar Linga total_vecs = idpf_get_reserved_vecs(adapter); 198*4930fbf4SPavan Kumar Linga num_q_vecs = total_vecs - IDPF_MBX_Q_VEC; 199*4930fbf4SPavan Kumar Linga 200*4930fbf4SPavan Kumar Linga err = idpf_send_alloc_vectors_msg(adapter, num_q_vecs); 201*4930fbf4SPavan Kumar Linga if (err) { 202*4930fbf4SPavan Kumar Linga dev_err(&adapter->pdev->dev, 203*4930fbf4SPavan Kumar Linga "Failed to allocate %d vectors: %d\n", num_q_vecs, err); 204*4930fbf4SPavan Kumar Linga 205*4930fbf4SPavan Kumar Linga return -EAGAIN; 206*4930fbf4SPavan Kumar Linga } 207*4930fbf4SPavan Kumar Linga 208*4930fbf4SPavan Kumar Linga min_vectors = IDPF_MBX_Q_VEC + IDPF_MIN_Q_VEC * default_vports; 209*4930fbf4SPavan Kumar Linga v_actual = pci_alloc_irq_vectors(adapter->pdev, min_vectors, 210*4930fbf4SPavan Kumar Linga total_vecs, PCI_IRQ_MSIX); 211*4930fbf4SPavan Kumar Linga if (v_actual < min_vectors) { 212*4930fbf4SPavan Kumar Linga dev_err(&adapter->pdev->dev, "Failed to allocate MSIX vectors: %d\n", 213*4930fbf4SPavan Kumar Linga v_actual); 214*4930fbf4SPavan Kumar Linga err = -EAGAIN; 215*4930fbf4SPavan Kumar Linga goto send_dealloc_vecs; 216*4930fbf4SPavan Kumar Linga } 217*4930fbf4SPavan Kumar Linga 218*4930fbf4SPavan Kumar Linga adapter->msix_entries = kcalloc(v_actual, sizeof(struct msix_entry), 219*4930fbf4SPavan Kumar Linga GFP_KERNEL); 220*4930fbf4SPavan Kumar Linga 221*4930fbf4SPavan Kumar Linga if (!adapter->msix_entries) { 222*4930fbf4SPavan Kumar Linga err = -ENOMEM; 223*4930fbf4SPavan Kumar Linga goto free_irq; 224*4930fbf4SPavan Kumar Linga } 225*4930fbf4SPavan Kumar Linga 226*4930fbf4SPavan Kumar Linga idpf_set_mb_vec_id(adapter); 227*4930fbf4SPavan Kumar Linga 228*4930fbf4SPavan Kumar Linga vecids = kcalloc(total_vecs, sizeof(u16), GFP_KERNEL); 229*4930fbf4SPavan Kumar Linga if (!vecids) { 230*4930fbf4SPavan Kumar Linga err = -ENOMEM; 231*4930fbf4SPavan Kumar Linga goto free_msix; 232*4930fbf4SPavan Kumar Linga } 233*4930fbf4SPavan Kumar Linga 234*4930fbf4SPavan Kumar Linga if (adapter->req_vec_chunks) { 235*4930fbf4SPavan Kumar Linga struct virtchnl2_vector_chunks *vchunks; 236*4930fbf4SPavan Kumar Linga struct virtchnl2_alloc_vectors *ac; 237*4930fbf4SPavan Kumar Linga 238*4930fbf4SPavan Kumar Linga ac = adapter->req_vec_chunks; 239*4930fbf4SPavan Kumar Linga vchunks = &ac->vchunks; 240*4930fbf4SPavan Kumar Linga 241*4930fbf4SPavan Kumar Linga num_vec_ids = idpf_get_vec_ids(adapter, vecids, total_vecs, 242*4930fbf4SPavan Kumar Linga vchunks); 243*4930fbf4SPavan Kumar Linga if (num_vec_ids < v_actual) { 244*4930fbf4SPavan Kumar Linga err = -EINVAL; 245*4930fbf4SPavan Kumar Linga goto free_vecids; 246*4930fbf4SPavan Kumar Linga } 247*4930fbf4SPavan Kumar Linga } else { 248*4930fbf4SPavan Kumar Linga int i; 249*4930fbf4SPavan Kumar Linga 250*4930fbf4SPavan Kumar Linga for (i = 0; i < v_actual; i++) 251*4930fbf4SPavan Kumar Linga vecids[i] = i; 252*4930fbf4SPavan Kumar Linga } 253*4930fbf4SPavan Kumar Linga 254*4930fbf4SPavan Kumar Linga for (vector = 0; vector < v_actual; vector++) { 255*4930fbf4SPavan Kumar Linga adapter->msix_entries[vector].entry = vecids[vector]; 256*4930fbf4SPavan Kumar Linga adapter->msix_entries[vector].vector = 257*4930fbf4SPavan Kumar Linga pci_irq_vector(adapter->pdev, vector); 258*4930fbf4SPavan Kumar Linga } 259*4930fbf4SPavan Kumar Linga 260*4930fbf4SPavan Kumar Linga adapter->num_req_msix = total_vecs; 261*4930fbf4SPavan Kumar Linga adapter->num_msix_entries = v_actual; 262*4930fbf4SPavan Kumar Linga /* 'num_avail_msix' is used to distribute excess vectors to the vports 263*4930fbf4SPavan Kumar Linga * after considering the minimum vectors required per each default 264*4930fbf4SPavan Kumar Linga * vport 265*4930fbf4SPavan Kumar Linga */ 266*4930fbf4SPavan Kumar Linga adapter->num_avail_msix = v_actual - min_vectors; 267*4930fbf4SPavan Kumar Linga 268*4930fbf4SPavan Kumar Linga /* Fill MSIX vector lifo stack with vector indexes */ 269*4930fbf4SPavan Kumar Linga err = idpf_init_vector_stack(adapter); 270*4930fbf4SPavan Kumar Linga if (err) 271*4930fbf4SPavan Kumar Linga goto free_vecids; 272*4930fbf4SPavan Kumar Linga 273*4930fbf4SPavan Kumar Linga err = idpf_mb_intr_init(adapter); 274*4930fbf4SPavan Kumar Linga if (err) 275*4930fbf4SPavan Kumar Linga goto deinit_vec_stack; 276*4930fbf4SPavan Kumar Linga idpf_mb_irq_enable(adapter); 277*4930fbf4SPavan Kumar Linga kfree(vecids); 278*4930fbf4SPavan Kumar Linga 279*4930fbf4SPavan Kumar Linga return 0; 280*4930fbf4SPavan Kumar Linga 281*4930fbf4SPavan Kumar Linga deinit_vec_stack: 282*4930fbf4SPavan Kumar Linga idpf_deinit_vector_stack(adapter); 283*4930fbf4SPavan Kumar Linga free_vecids: 284*4930fbf4SPavan Kumar Linga kfree(vecids); 285*4930fbf4SPavan Kumar Linga free_msix: 286*4930fbf4SPavan Kumar Linga kfree(adapter->msix_entries); 287*4930fbf4SPavan Kumar Linga adapter->msix_entries = NULL; 288*4930fbf4SPavan Kumar Linga free_irq: 289*4930fbf4SPavan Kumar Linga pci_free_irq_vectors(adapter->pdev); 290*4930fbf4SPavan Kumar Linga send_dealloc_vecs: 291*4930fbf4SPavan Kumar Linga idpf_send_dealloc_vectors_msg(adapter); 292*4930fbf4SPavan Kumar Linga 293*4930fbf4SPavan Kumar Linga return err; 294*4930fbf4SPavan Kumar Linga } 295*4930fbf4SPavan Kumar Linga 296*4930fbf4SPavan Kumar Linga /** 297*4930fbf4SPavan Kumar Linga * idpf_mbx_task - Delayed task to handle mailbox responses 298*4930fbf4SPavan Kumar Linga * @work: work_struct handle 299*4930fbf4SPavan Kumar Linga */ 300*4930fbf4SPavan Kumar Linga void idpf_mbx_task(struct work_struct *work) 301*4930fbf4SPavan Kumar Linga { 302*4930fbf4SPavan Kumar Linga struct idpf_adapter *adapter; 303*4930fbf4SPavan Kumar Linga 304*4930fbf4SPavan Kumar Linga adapter = container_of(work, struct idpf_adapter, mbx_task.work); 305*4930fbf4SPavan Kumar Linga 306*4930fbf4SPavan Kumar Linga if (test_bit(IDPF_MB_INTR_MODE, adapter->flags)) 307*4930fbf4SPavan Kumar Linga idpf_mb_irq_enable(adapter); 308*4930fbf4SPavan Kumar Linga else 309*4930fbf4SPavan Kumar Linga queue_delayed_work(adapter->mbx_wq, &adapter->mbx_task, 310*4930fbf4SPavan Kumar Linga msecs_to_jiffies(300)); 311*4930fbf4SPavan Kumar Linga 312*4930fbf4SPavan Kumar Linga idpf_recv_mb_msg(adapter, VIRTCHNL2_OP_UNKNOWN, NULL, 0); 313*4930fbf4SPavan Kumar Linga } 314*4930fbf4SPavan Kumar Linga 315*4930fbf4SPavan Kumar Linga /** 316*4930fbf4SPavan Kumar Linga * idpf_service_task - Delayed task for handling mailbox responses 317*4930fbf4SPavan Kumar Linga * @work: work_struct handle to our data 318*4930fbf4SPavan Kumar Linga * 319*4930fbf4SPavan Kumar Linga */ 320*4930fbf4SPavan Kumar Linga void idpf_service_task(struct work_struct *work) 321*4930fbf4SPavan Kumar Linga { 322*4930fbf4SPavan Kumar Linga struct idpf_adapter *adapter; 323*4930fbf4SPavan Kumar Linga 324*4930fbf4SPavan Kumar Linga adapter = container_of(work, struct idpf_adapter, serv_task.work); 325*4930fbf4SPavan Kumar Linga 326*4930fbf4SPavan Kumar Linga if (idpf_is_reset_detected(adapter) && 327*4930fbf4SPavan Kumar Linga !idpf_is_reset_in_prog(adapter) && 328*4930fbf4SPavan Kumar Linga !test_bit(IDPF_REMOVE_IN_PROG, adapter->flags)) { 329*4930fbf4SPavan Kumar Linga dev_info(&adapter->pdev->dev, "HW reset detected\n"); 330*4930fbf4SPavan Kumar Linga set_bit(IDPF_HR_FUNC_RESET, adapter->flags); 331*4930fbf4SPavan Kumar Linga queue_delayed_work(adapter->vc_event_wq, 332*4930fbf4SPavan Kumar Linga &adapter->vc_event_task, 333*4930fbf4SPavan Kumar Linga msecs_to_jiffies(10)); 334*4930fbf4SPavan Kumar Linga } 335*4930fbf4SPavan Kumar Linga 336*4930fbf4SPavan Kumar Linga queue_delayed_work(adapter->serv_wq, &adapter->serv_task, 337*4930fbf4SPavan Kumar Linga msecs_to_jiffies(300)); 338*4930fbf4SPavan Kumar Linga } 339*4930fbf4SPavan Kumar Linga 3408077c727SJoshua Hay /** 3418077c727SJoshua Hay * idpf_check_reset_complete - check that reset is complete 3428077c727SJoshua Hay * @hw: pointer to hw struct 3438077c727SJoshua Hay * @reset_reg: struct with reset registers 3448077c727SJoshua Hay * 3458077c727SJoshua Hay * Returns 0 if device is ready to use, or -EBUSY if it's in reset. 3468077c727SJoshua Hay **/ 3478077c727SJoshua Hay static int idpf_check_reset_complete(struct idpf_hw *hw, 3488077c727SJoshua Hay struct idpf_reset_reg *reset_reg) 3498077c727SJoshua Hay { 3508077c727SJoshua Hay struct idpf_adapter *adapter = hw->back; 3518077c727SJoshua Hay int i; 3528077c727SJoshua Hay 3538077c727SJoshua Hay for (i = 0; i < 2000; i++) { 3548077c727SJoshua Hay u32 reg_val = readl(reset_reg->rstat); 3558077c727SJoshua Hay 3568077c727SJoshua Hay /* 0xFFFFFFFF might be read if other side hasn't cleared the 3578077c727SJoshua Hay * register for us yet and 0xFFFFFFFF is not a valid value for 3588077c727SJoshua Hay * the register, so treat that as invalid. 3598077c727SJoshua Hay */ 3608077c727SJoshua Hay if (reg_val != 0xFFFFFFFF && (reg_val & reset_reg->rstat_m)) 3618077c727SJoshua Hay return 0; 3628077c727SJoshua Hay 3638077c727SJoshua Hay usleep_range(5000, 10000); 3648077c727SJoshua Hay } 3658077c727SJoshua Hay 3668077c727SJoshua Hay dev_warn(&adapter->pdev->dev, "Device reset timeout!\n"); 3678077c727SJoshua Hay /* Clear the reset flag unconditionally here since the reset 3688077c727SJoshua Hay * technically isn't in progress anymore from the driver's perspective 3698077c727SJoshua Hay */ 3708077c727SJoshua Hay clear_bit(IDPF_HR_RESET_IN_PROG, adapter->flags); 3718077c727SJoshua Hay 3728077c727SJoshua Hay return -EBUSY; 3738077c727SJoshua Hay } 3748077c727SJoshua Hay 3758077c727SJoshua Hay /** 3768077c727SJoshua Hay * idpf_init_hard_reset - Initiate a hardware reset 3778077c727SJoshua Hay * @adapter: Driver specific private structure 3788077c727SJoshua Hay * 3798077c727SJoshua Hay * Deallocate the vports and all the resources associated with them and 3808077c727SJoshua Hay * reallocate. Also reinitialize the mailbox. Return 0 on success, 3818077c727SJoshua Hay * negative on failure. 3828077c727SJoshua Hay */ 3838077c727SJoshua Hay static int idpf_init_hard_reset(struct idpf_adapter *adapter) 3848077c727SJoshua Hay { 3858077c727SJoshua Hay struct idpf_reg_ops *reg_ops = &adapter->dev_ops.reg_ops; 3868077c727SJoshua Hay struct device *dev = &adapter->pdev->dev; 3878077c727SJoshua Hay int err; 3888077c727SJoshua Hay 3898077c727SJoshua Hay mutex_lock(&adapter->vport_ctrl_lock); 3908077c727SJoshua Hay 3918077c727SJoshua Hay dev_info(dev, "Device HW Reset initiated\n"); 3928077c727SJoshua Hay /* Prepare for reset */ 3938077c727SJoshua Hay if (test_and_clear_bit(IDPF_HR_DRV_LOAD, adapter->flags)) { 3948077c727SJoshua Hay reg_ops->trigger_reset(adapter, IDPF_HR_DRV_LOAD); 3958077c727SJoshua Hay } else if (test_and_clear_bit(IDPF_HR_FUNC_RESET, adapter->flags)) { 3968077c727SJoshua Hay bool is_reset = idpf_is_reset_detected(adapter); 3978077c727SJoshua Hay 398*4930fbf4SPavan Kumar Linga idpf_vc_core_deinit(adapter); 3998077c727SJoshua Hay if (!is_reset) 4008077c727SJoshua Hay reg_ops->trigger_reset(adapter, IDPF_HR_FUNC_RESET); 4018077c727SJoshua Hay idpf_deinit_dflt_mbx(adapter); 4028077c727SJoshua Hay } else { 4038077c727SJoshua Hay dev_err(dev, "Unhandled hard reset cause\n"); 4048077c727SJoshua Hay err = -EBADRQC; 4058077c727SJoshua Hay goto unlock_mutex; 4068077c727SJoshua Hay } 4078077c727SJoshua Hay 4088077c727SJoshua Hay /* Wait for reset to complete */ 4098077c727SJoshua Hay err = idpf_check_reset_complete(&adapter->hw, &adapter->reset_reg); 4108077c727SJoshua Hay if (err) { 4118077c727SJoshua Hay dev_err(dev, "The driver was unable to contact the device's firmware. Check that the FW is running. Driver state= 0x%x\n", 4128077c727SJoshua Hay adapter->state); 4138077c727SJoshua Hay goto unlock_mutex; 4148077c727SJoshua Hay } 4158077c727SJoshua Hay 4168077c727SJoshua Hay /* Reset is complete and so start building the driver resources again */ 4178077c727SJoshua Hay err = idpf_init_dflt_mbx(adapter); 418*4930fbf4SPavan Kumar Linga if (err) { 4198077c727SJoshua Hay dev_err(dev, "Failed to initialize default mailbox: %d\n", err); 420*4930fbf4SPavan Kumar Linga goto unlock_mutex; 421*4930fbf4SPavan Kumar Linga } 422*4930fbf4SPavan Kumar Linga 423*4930fbf4SPavan Kumar Linga /* Initialize the state machine, also allocate memory and request 424*4930fbf4SPavan Kumar Linga * resources 425*4930fbf4SPavan Kumar Linga */ 426*4930fbf4SPavan Kumar Linga err = idpf_vc_core_init(adapter); 427*4930fbf4SPavan Kumar Linga if (err) { 428*4930fbf4SPavan Kumar Linga idpf_deinit_dflt_mbx(adapter); 429*4930fbf4SPavan Kumar Linga goto unlock_mutex; 430*4930fbf4SPavan Kumar Linga } 4318077c727SJoshua Hay 4328077c727SJoshua Hay unlock_mutex: 4338077c727SJoshua Hay mutex_unlock(&adapter->vport_ctrl_lock); 4348077c727SJoshua Hay 4358077c727SJoshua Hay return err; 4368077c727SJoshua Hay } 4378077c727SJoshua Hay 4388077c727SJoshua Hay /** 4398077c727SJoshua Hay * idpf_vc_event_task - Handle virtchannel event logic 4408077c727SJoshua Hay * @work: work queue struct 4418077c727SJoshua Hay */ 4428077c727SJoshua Hay void idpf_vc_event_task(struct work_struct *work) 4438077c727SJoshua Hay { 4448077c727SJoshua Hay struct idpf_adapter *adapter; 4458077c727SJoshua Hay 4468077c727SJoshua Hay adapter = container_of(work, struct idpf_adapter, vc_event_task.work); 4478077c727SJoshua Hay 4488077c727SJoshua Hay if (test_bit(IDPF_REMOVE_IN_PROG, adapter->flags)) 4498077c727SJoshua Hay return; 4508077c727SJoshua Hay 4518077c727SJoshua Hay if (test_bit(IDPF_HR_FUNC_RESET, adapter->flags) || 4528077c727SJoshua Hay test_bit(IDPF_HR_DRV_LOAD, adapter->flags)) { 4538077c727SJoshua Hay set_bit(IDPF_HR_RESET_IN_PROG, adapter->flags); 4548077c727SJoshua Hay idpf_init_hard_reset(adapter); 4558077c727SJoshua Hay } 4568077c727SJoshua Hay } 4578077c727SJoshua Hay 4588077c727SJoshua Hay /** 4598077c727SJoshua Hay * idpf_alloc_dma_mem - Allocate dma memory 4608077c727SJoshua Hay * @hw: pointer to hw struct 4618077c727SJoshua Hay * @mem: pointer to dma_mem struct 4628077c727SJoshua Hay * @size: size of the memory to allocate 4638077c727SJoshua Hay */ 4648077c727SJoshua Hay void *idpf_alloc_dma_mem(struct idpf_hw *hw, struct idpf_dma_mem *mem, u64 size) 4658077c727SJoshua Hay { 4668077c727SJoshua Hay struct idpf_adapter *adapter = hw->back; 4678077c727SJoshua Hay size_t sz = ALIGN(size, 4096); 4688077c727SJoshua Hay 4698077c727SJoshua Hay mem->va = dma_alloc_coherent(&adapter->pdev->dev, sz, 4708077c727SJoshua Hay &mem->pa, GFP_KERNEL); 4718077c727SJoshua Hay mem->size = sz; 4728077c727SJoshua Hay 4738077c727SJoshua Hay return mem->va; 4748077c727SJoshua Hay } 4758077c727SJoshua Hay 4768077c727SJoshua Hay /** 4778077c727SJoshua Hay * idpf_free_dma_mem - Free the allocated dma memory 4788077c727SJoshua Hay * @hw: pointer to hw struct 4798077c727SJoshua Hay * @mem: pointer to dma_mem struct 4808077c727SJoshua Hay */ 4818077c727SJoshua Hay void idpf_free_dma_mem(struct idpf_hw *hw, struct idpf_dma_mem *mem) 4828077c727SJoshua Hay { 4838077c727SJoshua Hay struct idpf_adapter *adapter = hw->back; 4848077c727SJoshua Hay 4858077c727SJoshua Hay dma_free_coherent(&adapter->pdev->dev, mem->size, 4868077c727SJoshua Hay mem->va, mem->pa); 4878077c727SJoshua Hay mem->size = 0; 4888077c727SJoshua Hay mem->va = NULL; 4898077c727SJoshua Hay mem->pa = 0; 4908077c727SJoshua Hay } 491