Lines Matching full:fifo
38 /* Virtual devices sharing the TM FIFO. */
76 * @fifo: pointer to the tmfifo structure
95 struct mlxbf_tmfifo *fifo; member
134 * @tx_buf: tx buffer used to buffer data before writing into the FIFO
150 * @fifo: pointer to the tmfifo structure
155 struct mlxbf_tmfifo *fifo; member
180 * @rx_fifo_size: number of entries of the Rx FIFO
181 * @tx_fifo_size: number of entries of the Tx FIFO
211 * @len: payload length in network byte order. Messages sent into the FIFO
245 /* Free vrings of the FIFO device. */
246 static void mlxbf_tmfifo_free_vrings(struct mlxbf_tmfifo *fifo, in mlxbf_tmfifo_free_vrings() argument
267 /* Allocate vrings for the FIFO. */
268 static int mlxbf_tmfifo_alloc_vrings(struct mlxbf_tmfifo *fifo, in mlxbf_tmfifo_alloc_vrings() argument
279 vring->fifo = fifo; in mlxbf_tmfifo_alloc_vrings()
291 mlxbf_tmfifo_free_vrings(fifo, tm_vdev); in mlxbf_tmfifo_alloc_vrings()
303 /* Disable interrupts of the FIFO device. */
304 static void mlxbf_tmfifo_disable_irqs(struct mlxbf_tmfifo *fifo) in mlxbf_tmfifo_disable_irqs() argument
309 irq = fifo->irq_info[i].irq; in mlxbf_tmfifo_disable_irqs()
310 fifo->irq_info[i].irq = 0; in mlxbf_tmfifo_disable_irqs()
320 if (!test_and_set_bit(irq_info->index, &irq_info->fifo->pend_events)) in mlxbf_tmfifo_irq_handler()
321 schedule_work(&irq_info->fifo->work); in mlxbf_tmfifo_irq_handler()
441 struct mlxbf_tmfifo *fifo = container_of(t, struct mlxbf_tmfifo, timer); in mlxbf_tmfifo_timer() local
444 rx = !test_and_set_bit(MLXBF_TM_RX_HWM_IRQ, &fifo->pend_events); in mlxbf_tmfifo_timer()
445 tx = !test_and_set_bit(MLXBF_TM_TX_LWM_IRQ, &fifo->pend_events); in mlxbf_tmfifo_timer()
448 schedule_work(&fifo->work); in mlxbf_tmfifo_timer()
450 mod_timer(&fifo->timer, jiffies + MLXBF_TMFIFO_TIMER_INTERVAL); in mlxbf_tmfifo_timer()
510 /* Get the number of available words in Rx FIFO for receiving. */
511 static int mlxbf_tmfifo_get_rx_avail(struct mlxbf_tmfifo *fifo) in mlxbf_tmfifo_get_rx_avail() argument
515 sts = readq(fifo->rx.sts); in mlxbf_tmfifo_get_rx_avail()
520 static int mlxbf_tmfifo_get_tx_avail(struct mlxbf_tmfifo *fifo, int vdev_id) in mlxbf_tmfifo_get_tx_avail() argument
526 /* Reserve some room in FIFO for console messages. */ in mlxbf_tmfifo_get_tx_avail()
528 tx_reserve = fifo->tx_fifo_size / MLXBF_TMFIFO_RESERVE_RATIO; in mlxbf_tmfifo_get_tx_avail()
532 sts = readq(fifo->tx.sts); in mlxbf_tmfifo_get_tx_avail()
534 return fifo->tx_fifo_size - tx_reserve - count; in mlxbf_tmfifo_get_tx_avail()
538 static void mlxbf_tmfifo_console_tx(struct mlxbf_tmfifo *fifo, int avail) in mlxbf_tmfifo_console_tx() argument
551 cons = fifo->vdev[VIRTIO_ID_CONSOLE]; in mlxbf_tmfifo_console_tx()
568 writeq(*(u64 *)&hdr, fifo->tx.data); in mlxbf_tmfifo_console_tx()
571 spin_lock_irqsave(&fifo->spin_lock[0], flags); in mlxbf_tmfifo_console_tx()
585 writeq(data, fifo->tx.data); in mlxbf_tmfifo_console_tx()
598 spin_unlock_irqrestore(&fifo->spin_lock[0], flags); in mlxbf_tmfifo_console_tx()
607 struct mlxbf_tmfifo *fifo = vring->fifo; in mlxbf_tmfifo_rxtx_word() local
614 /* Read a word from FIFO for Rx. */ in mlxbf_tmfifo_rxtx_word()
616 data = readq(fifo->rx.data); in mlxbf_tmfifo_rxtx_word()
643 /* Write the word into FIFO for Tx. */ in mlxbf_tmfifo_rxtx_word()
645 writeq(data, fifo->tx.data); in mlxbf_tmfifo_rxtx_word()
659 struct mlxbf_tmfifo *fifo = vring->fifo; in mlxbf_tmfifo_rxtx_header() local
667 /* Drain one word from the FIFO. */ in mlxbf_tmfifo_rxtx_header()
668 *(u64 *)&hdr = readq(fifo->rx.data); in mlxbf_tmfifo_rxtx_header()
678 config = &fifo->vdev[vdev_id]->config.net; in mlxbf_tmfifo_rxtx_header()
695 struct mlxbf_tmfifo_vdev *tm_dev2 = fifo->vdev[vdev_id]; in mlxbf_tmfifo_rxtx_header()
721 writeq(*(u64 *)&hdr, fifo->tx.data); in mlxbf_tmfifo_rxtx_header()
726 fifo->vring[is_rx] = vring; in mlxbf_tmfifo_rxtx_header()
738 struct mlxbf_tmfifo *fifo = vring->fifo; in mlxbf_tmfifo_rxtx_one_desc() local
745 vdev = &fifo->vdev[vring->vdev_id]->vdev; in mlxbf_tmfifo_rxtx_one_desc()
801 fifo->vring[is_rx] = NULL; in mlxbf_tmfifo_rxtx_one_desc()
818 spin_lock_irqsave(&fifo->spin_lock[is_rx], flags); in mlxbf_tmfifo_rxtx_one_desc()
820 spin_unlock_irqrestore(&fifo->spin_lock[is_rx], flags); in mlxbf_tmfifo_rxtx_one_desc()
860 vring->fifo->vring[0] = NULL; in mlxbf_tmfifo_check_tx_timeout()
869 spin_lock_irqsave(&vring->fifo->spin_lock[0], flags); in mlxbf_tmfifo_check_tx_timeout()
871 spin_unlock_irqrestore(&vring->fifo->spin_lock[0], flags); in mlxbf_tmfifo_check_tx_timeout()
878 struct mlxbf_tmfifo *fifo; in mlxbf_tmfifo_rxtx() local
881 fifo = vring->fifo; in mlxbf_tmfifo_rxtx()
884 if (!fifo || !fifo->vdev[devid]) in mlxbf_tmfifo_rxtx()
888 if (fifo->vring[is_rx] && fifo->vring[is_rx] != vring) in mlxbf_tmfifo_rxtx()
897 /* Get available FIFO space. */ in mlxbf_tmfifo_rxtx()
900 avail = mlxbf_tmfifo_get_rx_avail(fifo); in mlxbf_tmfifo_rxtx()
902 avail = mlxbf_tmfifo_get_tx_avail(fifo, devid); in mlxbf_tmfifo_rxtx()
911 writeq(0, vring->fifo->tx.data); in mlxbf_tmfifo_rxtx()
920 mlxbf_tmfifo_console_tx(fifo, avail); in mlxbf_tmfifo_rxtx()
934 static void mlxbf_tmfifo_work_rxtx(struct mlxbf_tmfifo *fifo, int queue_id, in mlxbf_tmfifo_work_rxtx() argument
941 if (!test_and_clear_bit(irq_id, &fifo->pend_events) || in mlxbf_tmfifo_work_rxtx()
942 !fifo->irq_info[irq_id].irq) in mlxbf_tmfifo_work_rxtx()
946 tm_vdev = fifo->vdev[i]; in mlxbf_tmfifo_work_rxtx()
958 struct mlxbf_tmfifo *fifo; in mlxbf_tmfifo_work_handler() local
960 fifo = container_of(work, struct mlxbf_tmfifo, work); in mlxbf_tmfifo_work_handler()
961 if (!fifo->is_ready) in mlxbf_tmfifo_work_handler()
964 mutex_lock(&fifo->lock); in mlxbf_tmfifo_work_handler()
967 mlxbf_tmfifo_work_rxtx(fifo, MLXBF_TMFIFO_VRING_TX, in mlxbf_tmfifo_work_handler()
971 mlxbf_tmfifo_work_rxtx(fifo, MLXBF_TMFIFO_VRING_RX, in mlxbf_tmfifo_work_handler()
974 mutex_unlock(&fifo->lock); in mlxbf_tmfifo_work_handler()
982 struct mlxbf_tmfifo *fifo; in mlxbf_tmfifo_virtio_notify() local
985 fifo = vring->fifo; in mlxbf_tmfifo_virtio_notify()
999 spin_lock_irqsave(&fifo->spin_lock[0], flags); in mlxbf_tmfifo_virtio_notify()
1000 tm_vdev = fifo->vdev[VIRTIO_ID_CONSOLE]; in mlxbf_tmfifo_virtio_notify()
1002 spin_unlock_irqrestore(&fifo->spin_lock[0], flags); in mlxbf_tmfifo_virtio_notify()
1003 set_bit(MLXBF_TM_TX_LWM_IRQ, &fifo->pend_events); in mlxbf_tmfifo_virtio_notify()
1005 &fifo->pend_events)) { in mlxbf_tmfifo_virtio_notify()
1009 if (test_and_set_bit(MLXBF_TM_RX_HWM_IRQ, &fifo->pend_events)) in mlxbf_tmfifo_virtio_notify()
1013 schedule_work(&fifo->work); in mlxbf_tmfifo_virtio_notify()
1188 /* Create vdev for the FIFO. */
1190 struct mlxbf_tmfifo *fifo, in mlxbf_tmfifo_create_vdev() argument
1197 mutex_lock(&fifo->lock); in mlxbf_tmfifo_create_vdev()
1199 tm_vdev = fifo->vdev[vdev_id]; in mlxbf_tmfifo_create_vdev()
1220 if (mlxbf_tmfifo_alloc_vrings(fifo, tm_vdev)) { in mlxbf_tmfifo_create_vdev()
1231 fifo->vdev[vdev_id] = tm_vdev; in mlxbf_tmfifo_create_vdev()
1241 mutex_unlock(&fifo->lock); in mlxbf_tmfifo_create_vdev()
1245 mlxbf_tmfifo_free_vrings(fifo, tm_vdev); in mlxbf_tmfifo_create_vdev()
1246 fifo->vdev[vdev_id] = NULL; in mlxbf_tmfifo_create_vdev()
1252 mutex_unlock(&fifo->lock); in mlxbf_tmfifo_create_vdev()
1256 /* Delete vdev for the FIFO. */
1257 static int mlxbf_tmfifo_delete_vdev(struct mlxbf_tmfifo *fifo, int vdev_id) in mlxbf_tmfifo_delete_vdev() argument
1261 mutex_lock(&fifo->lock); in mlxbf_tmfifo_delete_vdev()
1264 tm_vdev = fifo->vdev[vdev_id]; in mlxbf_tmfifo_delete_vdev()
1267 mlxbf_tmfifo_free_vrings(fifo, tm_vdev); in mlxbf_tmfifo_delete_vdev()
1268 fifo->vdev[vdev_id] = NULL; in mlxbf_tmfifo_delete_vdev()
1271 mutex_unlock(&fifo->lock); in mlxbf_tmfifo_delete_vdev()
1292 static void mlxbf_tmfifo_set_threshold(struct mlxbf_tmfifo *fifo) in mlxbf_tmfifo_set_threshold() argument
1296 /* Get Tx FIFO size and set the low/high watermark. */ in mlxbf_tmfifo_set_threshold()
1297 ctl = readq(fifo->tx.ctl); in mlxbf_tmfifo_set_threshold()
1298 fifo->tx_fifo_size = in mlxbf_tmfifo_set_threshold()
1302 fifo->tx_fifo_size / 2); in mlxbf_tmfifo_set_threshold()
1305 fifo->tx_fifo_size - 1); in mlxbf_tmfifo_set_threshold()
1306 writeq(ctl, fifo->tx.ctl); in mlxbf_tmfifo_set_threshold()
1308 /* Get Rx FIFO size and set the low/high watermark. */ in mlxbf_tmfifo_set_threshold()
1309 ctl = readq(fifo->rx.ctl); in mlxbf_tmfifo_set_threshold()
1310 fifo->rx_fifo_size = in mlxbf_tmfifo_set_threshold()
1316 writeq(ctl, fifo->rx.ctl); in mlxbf_tmfifo_set_threshold()
1319 static void mlxbf_tmfifo_cleanup(struct mlxbf_tmfifo *fifo) in mlxbf_tmfifo_cleanup() argument
1323 fifo->is_ready = false; in mlxbf_tmfifo_cleanup()
1324 timer_delete_sync(&fifo->timer); in mlxbf_tmfifo_cleanup()
1325 mlxbf_tmfifo_disable_irqs(fifo); in mlxbf_tmfifo_cleanup()
1326 cancel_work_sync(&fifo->work); in mlxbf_tmfifo_cleanup()
1328 mlxbf_tmfifo_delete_vdev(fifo, i); in mlxbf_tmfifo_cleanup()
1336 struct mlxbf_tmfifo *fifo; in mlxbf_tmfifo_probe() local
1346 fifo = devm_kzalloc(dev, sizeof(*fifo), GFP_KERNEL); in mlxbf_tmfifo_probe()
1347 if (!fifo) in mlxbf_tmfifo_probe()
1350 spin_lock_init(&fifo->spin_lock[0]); in mlxbf_tmfifo_probe()
1351 spin_lock_init(&fifo->spin_lock[1]); in mlxbf_tmfifo_probe()
1352 INIT_WORK(&fifo->work, mlxbf_tmfifo_work_handler); in mlxbf_tmfifo_probe()
1353 mutex_init(&fifo->lock); in mlxbf_tmfifo_probe()
1355 /* Get the resource of the Rx FIFO. */ in mlxbf_tmfifo_probe()
1356 fifo->res0 = devm_platform_ioremap_resource(pdev, 0); in mlxbf_tmfifo_probe()
1357 if (IS_ERR(fifo->res0)) in mlxbf_tmfifo_probe()
1358 return PTR_ERR(fifo->res0); in mlxbf_tmfifo_probe()
1360 /* Get the resource of the Tx FIFO. */ in mlxbf_tmfifo_probe()
1361 fifo->res1 = devm_platform_ioremap_resource(pdev, 1); in mlxbf_tmfifo_probe()
1362 if (IS_ERR(fifo->res1)) in mlxbf_tmfifo_probe()
1363 return PTR_ERR(fifo->res1); in mlxbf_tmfifo_probe()
1366 fifo->rx.ctl = fifo->res1 + MLXBF_TMFIFO_RX_CTL_BF3; in mlxbf_tmfifo_probe()
1367 fifo->rx.sts = fifo->res1 + MLXBF_TMFIFO_RX_STS_BF3; in mlxbf_tmfifo_probe()
1368 fifo->rx.data = fifo->res0 + MLXBF_TMFIFO_RX_DATA_BF3; in mlxbf_tmfifo_probe()
1369 fifo->tx.ctl = fifo->res1 + MLXBF_TMFIFO_TX_CTL_BF3; in mlxbf_tmfifo_probe()
1370 fifo->tx.sts = fifo->res1 + MLXBF_TMFIFO_TX_STS_BF3; in mlxbf_tmfifo_probe()
1371 fifo->tx.data = fifo->res0 + MLXBF_TMFIFO_TX_DATA_BF3; in mlxbf_tmfifo_probe()
1373 fifo->rx.ctl = fifo->res0 + MLXBF_TMFIFO_RX_CTL; in mlxbf_tmfifo_probe()
1374 fifo->rx.sts = fifo->res0 + MLXBF_TMFIFO_RX_STS; in mlxbf_tmfifo_probe()
1375 fifo->rx.data = fifo->res0 + MLXBF_TMFIFO_RX_DATA; in mlxbf_tmfifo_probe()
1376 fifo->tx.ctl = fifo->res1 + MLXBF_TMFIFO_TX_CTL; in mlxbf_tmfifo_probe()
1377 fifo->tx.sts = fifo->res1 + MLXBF_TMFIFO_TX_STS; in mlxbf_tmfifo_probe()
1378 fifo->tx.data = fifo->res1 + MLXBF_TMFIFO_TX_DATA; in mlxbf_tmfifo_probe()
1381 platform_set_drvdata(pdev, fifo); in mlxbf_tmfifo_probe()
1383 timer_setup(&fifo->timer, mlxbf_tmfifo_timer, 0); in mlxbf_tmfifo_probe()
1386 fifo->irq_info[i].index = i; in mlxbf_tmfifo_probe()
1387 fifo->irq_info[i].fifo = fifo; in mlxbf_tmfifo_probe()
1388 fifo->irq_info[i].irq = platform_get_irq(pdev, i); in mlxbf_tmfifo_probe()
1389 rc = devm_request_irq(dev, fifo->irq_info[i].irq, in mlxbf_tmfifo_probe()
1391 "tmfifo", &fifo->irq_info[i]); in mlxbf_tmfifo_probe()
1394 fifo->irq_info[i].irq = 0; in mlxbf_tmfifo_probe()
1399 mlxbf_tmfifo_set_threshold(fifo); in mlxbf_tmfifo_probe()
1402 rc = mlxbf_tmfifo_create_vdev(dev, fifo, VIRTIO_ID_CONSOLE, 0, NULL, 0); in mlxbf_tmfifo_probe()
1415 rc = mlxbf_tmfifo_create_vdev(dev, fifo, VIRTIO_ID_NET, in mlxbf_tmfifo_probe()
1421 mod_timer(&fifo->timer, jiffies + MLXBF_TMFIFO_TIMER_INTERVAL); in mlxbf_tmfifo_probe()
1426 fifo->is_ready = true; in mlxbf_tmfifo_probe()
1430 mlxbf_tmfifo_cleanup(fifo); in mlxbf_tmfifo_probe()
1437 struct mlxbf_tmfifo *fifo = platform_get_drvdata(pdev); in mlxbf_tmfifo_remove() local
1439 mlxbf_tmfifo_cleanup(fifo); in mlxbf_tmfifo_remove()