1 // SPDX-License-Identifier: GPL-2.0-only 2 /* Copyright (C) 2025 Intel Corporation */ 3 4 #include "ixd.h" 5 #include "ixd_ctlq.h" 6 #include "ixd_devlink.h" 7 #include "ixd_virtchnl.h" 8 9 #define IXD_DFLT_MBX_Q_LEN 64 10 11 /** 12 * ixd_init_ctlq_create_info - Initialize control queue info for creation 13 * @info: destination 14 * @type: type of the queue to create 15 * @ctlq_reg: register assigned to the control queue 16 */ 17 static void ixd_init_ctlq_create_info(struct libie_ctlq_create_info *info, 18 enum libie_ctlq_type type, 19 const struct libie_ctlq_reg *ctlq_reg) 20 { 21 *info = (struct libie_ctlq_create_info) { 22 .type = type, 23 .id = -1, 24 .reg = *ctlq_reg, 25 .len = IXD_DFLT_MBX_Q_LEN, 26 }; 27 } 28 29 /** 30 * ixd_init_libie_xn_params - Initialize xn transaction manager creation info 31 * @params: destination 32 * @adapter: adapter info struct 33 * @ctlqs: list of the managed queues to create 34 * @num_queues: length of the queue list 35 */ 36 static void ixd_init_libie_xn_params(struct libie_ctlq_xn_init_params *params, 37 struct ixd_adapter *adapter, 38 struct libie_ctlq_create_info *ctlqs, 39 uint num_queues) 40 { 41 *params = (struct libie_ctlq_xn_init_params){ 42 .cctlq_info = ctlqs, 43 .ctx = &adapter->cp_ctx, 44 .num_qs = num_queues, 45 }; 46 } 47 48 /** 49 * ixd_adapter_fill_dflt_ctlqs - Find default control queues and store them 50 * @adapter: adapter info struct 51 */ 52 static void ixd_adapter_fill_dflt_ctlqs(struct ixd_adapter *adapter) 53 { 54 adapter->arq = libie_find_ctlq(&adapter->cp_ctx, LIBIE_CTLQ_TYPE_RX, 55 LIBIE_CTLQ_MBX_ID); 56 adapter->asq = libie_find_ctlq(&adapter->cp_ctx, LIBIE_CTLQ_TYPE_TX, 57 LIBIE_CTLQ_MBX_ID); 58 } 59 60 /** 61 * ixd_deinit_dflt_mbx - Deinitialize default mailbox 62 * @adapter: adapter info struct 63 */ 64 void ixd_deinit_dflt_mbx(struct ixd_adapter *adapter) 65 { 66 cancel_delayed_work_sync(&adapter->mbx_task); 67 68 if (adapter->xnm) 69 libie_ctlq_xn_shutdown(adapter->xnm); 70 71 if (adapter->asq) 72 ixd_ctlq_clean_sq(adapter, true); 73 74 if (adapter->xnm) 75 libie_ctlq_xn_deinit(adapter->xnm, &adapter->cp_ctx); 76 77 adapter->arq = NULL; 78 adapter->asq = NULL; 79 adapter->xnm = NULL; 80 } 81 82 /** 83 * ixd_init_dflt_mbx - Setup default mailbox parameters and make request 84 * @adapter: adapter info struct 85 * 86 * Return: %0 on success, negative errno code on failure 87 */ 88 int ixd_init_dflt_mbx(struct ixd_adapter *adapter) 89 { 90 struct libie_ctlq_create_info ctlqs_info[2]; 91 struct libie_ctlq_xn_init_params xn_params; 92 struct libie_ctlq_reg ctlq_reg_tx; 93 struct libie_ctlq_reg ctlq_reg_rx; 94 int err; 95 96 ixd_ctlq_reg_init(adapter, &ctlq_reg_tx, &ctlq_reg_rx); 97 ixd_init_ctlq_create_info(&ctlqs_info[0], LIBIE_CTLQ_TYPE_TX, 98 &ctlq_reg_tx); 99 ixd_init_ctlq_create_info(&ctlqs_info[1], LIBIE_CTLQ_TYPE_RX, 100 &ctlq_reg_rx); 101 ixd_init_libie_xn_params(&xn_params, adapter, ctlqs_info, 102 ARRAY_SIZE(ctlqs_info)); 103 err = libie_ctlq_xn_init(&xn_params); 104 if (err) 105 return err; 106 adapter->xnm = xn_params.xnm; 107 108 ixd_adapter_fill_dflt_ctlqs(adapter); 109 110 if (!adapter->asq || !adapter->arq) { 111 ixd_deinit_dflt_mbx(adapter); 112 return -ENOENT; 113 } 114 115 queue_delayed_work(system_dfl_wq, &adapter->mbx_task, 0); 116 117 return 0; 118 } 119 120 /** 121 * ixd_init_task - Initialize after reset 122 * @work: init work struct 123 */ 124 void ixd_init_task(struct work_struct *work) 125 { 126 struct ixd_adapter *adapter; 127 int err; 128 129 adapter = container_of(work, struct ixd_adapter, 130 init_task.init_work.work); 131 132 if (!ixd_check_reset_complete(adapter)) { 133 if (++adapter->init_task.reset_retries < 10) 134 queue_delayed_work(system_dfl_wq, 135 &adapter->init_task.init_work, 136 IXD_INIT_TASK_DELAY_JIFFIES); 137 else 138 dev_err(ixd_to_dev(adapter), 139 "Device reset failed. The driver was unable to contact the device's firmware. Check that the FW is running.\n"); 140 return; 141 } 142 143 adapter->init_task.reset_retries = 0; 144 err = ixd_init_dflt_mbx(adapter); 145 if (err) { 146 dev_err(ixd_to_dev(adapter), 147 "Failed to initialize the default mailbox: %pe\n", 148 ERR_PTR(err)); 149 return; 150 } 151 152 err = ixd_vc_dev_init(adapter); 153 if (!err) { 154 adapter->init_task.vc_retries = 0; 155 adapter->init_task.success = true; 156 ixd_devlink_register(adapter); 157 return; 158 } 159 160 libie_ctlq_xn_shutdown(adapter->xnm); 161 ixd_trigger_reset(adapter); 162 ixd_deinit_dflt_mbx(adapter); 163 if (++adapter->init_task.vc_retries > 5 || 164 (err != -ETIMEDOUT && err != -EAGAIN && err != -EBUSY)) { 165 dev_err(ixd_to_dev(adapter), 166 "Failed to establish mailbox communication with the hardware: %pe\n", 167 ERR_PTR(err)); 168 return; 169 } 170 171 queue_delayed_work(system_dfl_wq, &adapter->init_task.init_work, 172 IXD_INIT_TASK_DELAY_JIFFIES); 173 } 174