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

accel/qaic: Support MHI QAIC_TIMESYNC channel

Use QAIC_TIMESYNC MHI channel to send UTC time to device in SBL
environment. Remove support for QAIC_TIMESYNC MHI channel in AMSS
environment as it is not used in that environment.

Signed-off-by: Pranjal Ramajor Asha Kanojiya <quic_pkanojiy@quicinc.com>
Reviewed-by: Jeffrey Hugo <quic_jhugo@quicinc.com>
Reviewed-by: Carl Vanderlip <quic_carlv@quicinc.com>
Signed-off-by: Jeffrey Hugo <quic_jhugo@quicinc.com>
Reviewed-by: Stanislaw Gruszka <stanislaw.gruszka@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20231016170114.5446-3-quic_jhugo@quicinc.com

authored by

Pranjal Ramajor Asha Kanojiya and committed by
Jeffrey Hugo
41cfbaa4 6216fb03

+166 -5
+1 -1
Documentation/accel/qaic/aic100.rst
··· 221 221 +----------------+---------+----------+----------------------------------------+ 222 222 | QAIC_DEBUG | 18 & 19 | AMSS | Not used. | 223 223 +----------------+---------+----------+----------------------------------------+ 224 - | QAIC_TIMESYNC | 20 & 21 | SBL/AMSS | Used to synchronize timestamps in the | 224 + | QAIC_TIMESYNC | 20 & 21 | SBL | Used to synchronize timestamps in the | 225 225 | | | | device side logs with the host time | 226 226 | | | | source. | 227 227 +----------------+---------+----------+----------------------------------------+
+2 -2
drivers/accel/qaic/mhi_controller.c
··· 348 348 .local_elements = 0, 349 349 .event_ring = 0, 350 350 .dir = DMA_TO_DEVICE, 351 - .ee_mask = MHI_CH_EE_SBL | MHI_CH_EE_AMSS, 351 + .ee_mask = MHI_CH_EE_SBL, 352 352 .pollcfg = 0, 353 353 .doorbell = MHI_DB_BRST_DISABLE, 354 354 .lpm_notify = false, ··· 364 364 .local_elements = 0, 365 365 .event_ring = 0, 366 366 .dir = DMA_FROM_DEVICE, 367 - .ee_mask = MHI_CH_EE_SBL | MHI_CH_EE_AMSS, 367 + .ee_mask = MHI_CH_EE_SBL, 368 368 .pollcfg = 0, 369 369 .doorbell = MHI_DB_BRST_DISABLE, 370 370 .lpm_notify = false,
+4
drivers/accel/qaic/qaic.h
··· 139 139 u32 (*gen_crc)(void *msg); 140 140 /* Validate the CRC of a control message */ 141 141 bool (*valid_crc)(void *msg); 142 + /* MHI "QAIC_TIMESYNC" channel device */ 143 + struct mhi_device *qts_ch; 144 + /* Work queue for tasks related to MHI "QAIC_TIMESYNC" channel */ 145 + struct workqueue_struct *qts_wq; 142 146 }; 143 147 144 148 struct qaic_drm_device {
+7
drivers/accel/qaic/qaic_drv.c
··· 325 325 cleanup_srcu_struct(&qdev->dev_lock); 326 326 pci_set_drvdata(qdev->pdev, NULL); 327 327 destroy_workqueue(qdev->cntl_wq); 328 + destroy_workqueue(qdev->qts_wq); 328 329 } 329 330 330 331 static struct qaic_device *create_qdev(struct pci_dev *pdev, const struct pci_device_id *id) ··· 348 347 qdev->cntl_wq = alloc_workqueue("qaic_cntl", WQ_UNBOUND, 0); 349 348 if (!qdev->cntl_wq) 350 349 return NULL; 350 + 351 + qdev->qts_wq = alloc_workqueue("qaic_ts", WQ_UNBOUND, 0); 352 + if (!qdev->qts_wq) { 353 + destroy_workqueue(qdev->cntl_wq); 354 + return NULL; 355 + } 351 356 352 357 pci_set_drvdata(pdev, qdev); 353 358 qdev->pdev = pdev;
+152 -2
drivers/accel/qaic/qaic_timesync.c
··· 22 22 MODULE_PARM_DESC(timesync_delay_ms, "Delay in ms between two consecutive timesync operations"); 23 23 24 24 enum qts_msg_type { 25 - QAIC_TS_SYNC_REQ = 1, 25 + QAIC_TS_CMD_TO_HOST, 26 + QAIC_TS_SYNC_REQ, 26 27 QAIC_TS_ACK_TO_HOST, 27 28 QAIC_TS_MSG_TYPE_MAX 28 29 }; ··· 82 81 atomic_t buff_in_use; 83 82 struct device *dev; 84 83 struct qts_host_time_sync_msg_data *sync_msg; 84 + }; 85 + 86 + struct qts_resp_msg { 87 + struct qts_hdr hdr; 88 + } __packed; 89 + 90 + struct qts_resp { 91 + struct qts_resp_msg data; 92 + struct work_struct work; 93 + struct qaic_device *qdev; 85 94 }; 86 95 87 96 #ifdef readq ··· 245 234 }, 246 235 }; 247 236 237 + static void qaic_boot_timesync_worker(struct work_struct *work) 238 + { 239 + struct qts_resp *resp = container_of(work, struct qts_resp, work); 240 + struct qts_host_time_sync_msg_data *req; 241 + struct qts_resp_msg data = resp->data; 242 + struct qaic_device *qdev = resp->qdev; 243 + struct mhi_device *mhi_dev; 244 + struct timespec64 ts; 245 + int ret; 246 + 247 + mhi_dev = qdev->qts_ch; 248 + /* Queue the response message beforehand to avoid race conditions */ 249 + ret = mhi_queue_buf(mhi_dev, DMA_FROM_DEVICE, &resp->data, sizeof(resp->data), MHI_EOT); 250 + if (ret) { 251 + kfree(resp); 252 + dev_warn(&mhi_dev->dev, "Failed to re-queue response buffer %d\n", ret); 253 + return; 254 + } 255 + 256 + switch (data.hdr.msg_type) { 257 + case QAIC_TS_CMD_TO_HOST: 258 + req = kzalloc(sizeof(*req), GFP_KERNEL); 259 + if (!req) 260 + break; 261 + 262 + req->header = data.hdr; 263 + req->header.msg_type = QAIC_TS_SYNC_REQ; 264 + ktime_get_real_ts64(&ts); 265 + req->data.tv_sec = cpu_to_le64(ts.tv_sec); 266 + req->data.tv_usec = cpu_to_le64(div_u64(ts.tv_nsec, NSEC_PER_USEC)); 267 + 268 + ret = mhi_queue_buf(mhi_dev, DMA_TO_DEVICE, req, sizeof(*req), MHI_EOT); 269 + if (ret) { 270 + kfree(req); 271 + dev_dbg(&mhi_dev->dev, "Failed to send request message. Error %d\n", ret); 272 + } 273 + break; 274 + case QAIC_TS_ACK_TO_HOST: 275 + dev_dbg(&mhi_dev->dev, "ACK received from device\n"); 276 + break; 277 + default: 278 + dev_err(&mhi_dev->dev, "Invalid message type %u.\n", data.hdr.msg_type); 279 + } 280 + } 281 + 282 + static int qaic_boot_timesync_queue_resp(struct mhi_device *mhi_dev, struct qaic_device *qdev) 283 + { 284 + struct qts_resp *resp; 285 + int ret; 286 + 287 + resp = kzalloc(sizeof(*resp), GFP_KERNEL); 288 + if (!resp) 289 + return -ENOMEM; 290 + 291 + resp->qdev = qdev; 292 + INIT_WORK(&resp->work, qaic_boot_timesync_worker); 293 + 294 + ret = mhi_queue_buf(mhi_dev, DMA_FROM_DEVICE, &resp->data, sizeof(resp->data), MHI_EOT); 295 + if (ret) { 296 + kfree(resp); 297 + dev_warn(&mhi_dev->dev, "Failed to queue response buffer %d\n", ret); 298 + return ret; 299 + } 300 + 301 + return 0; 302 + } 303 + 304 + static void qaic_boot_timesync_remove(struct mhi_device *mhi_dev) 305 + { 306 + struct qaic_device *qdev; 307 + 308 + qdev = dev_get_drvdata(&mhi_dev->dev); 309 + mhi_unprepare_from_transfer(qdev->qts_ch); 310 + qdev->qts_ch = NULL; 311 + } 312 + 313 + static int qaic_boot_timesync_probe(struct mhi_device *mhi_dev, const struct mhi_device_id *id) 314 + { 315 + struct qaic_device *qdev = pci_get_drvdata(to_pci_dev(mhi_dev->mhi_cntrl->cntrl_dev)); 316 + int ret; 317 + 318 + ret = mhi_prepare_for_transfer(mhi_dev); 319 + if (ret) 320 + return ret; 321 + 322 + qdev->qts_ch = mhi_dev; 323 + dev_set_drvdata(&mhi_dev->dev, qdev); 324 + 325 + ret = qaic_boot_timesync_queue_resp(mhi_dev, qdev); 326 + if (ret) { 327 + dev_set_drvdata(&mhi_dev->dev, NULL); 328 + qdev->qts_ch = NULL; 329 + mhi_unprepare_from_transfer(mhi_dev); 330 + } 331 + 332 + return ret; 333 + } 334 + 335 + static void qaic_boot_timesync_ul_xfer_cb(struct mhi_device *mhi_dev, struct mhi_result *mhi_result) 336 + { 337 + kfree(mhi_result->buf_addr); 338 + } 339 + 340 + static void qaic_boot_timesync_dl_xfer_cb(struct mhi_device *mhi_dev, struct mhi_result *mhi_result) 341 + { 342 + struct qts_resp *resp = container_of(mhi_result->buf_addr, struct qts_resp, data); 343 + 344 + if (mhi_result->transaction_status || mhi_result->bytes_xferd != sizeof(resp->data)) { 345 + kfree(resp); 346 + return; 347 + } 348 + 349 + queue_work(resp->qdev->qts_wq, &resp->work); 350 + } 351 + 352 + static const struct mhi_device_id qaic_boot_timesync_match_table[] = { 353 + { .chan = "QAIC_TIMESYNC"}, 354 + {}, 355 + }; 356 + 357 + static struct mhi_driver qaic_boot_timesync_driver = { 358 + .id_table = qaic_boot_timesync_match_table, 359 + .remove = qaic_boot_timesync_remove, 360 + .probe = qaic_boot_timesync_probe, 361 + .ul_xfer_cb = qaic_boot_timesync_ul_xfer_cb, 362 + .dl_xfer_cb = qaic_boot_timesync_dl_xfer_cb, 363 + .driver = { 364 + .name = "qaic_timesync", 365 + }, 366 + }; 367 + 248 368 int qaic_timesync_init(void) 249 369 { 250 - return mhi_driver_register(&qaic_timesync_driver); 370 + int ret; 371 + 372 + ret = mhi_driver_register(&qaic_timesync_driver); 373 + if (ret) 374 + return ret; 375 + ret = mhi_driver_register(&qaic_boot_timesync_driver); 376 + 377 + return ret; 251 378 } 252 379 253 380 void qaic_timesync_deinit(void) 254 381 { 382 + mhi_driver_unregister(&qaic_boot_timesync_driver); 255 383 mhi_driver_unregister(&qaic_timesync_driver); 256 384 }