Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/drv/nic/virtio-net/virtio-net.c

    r1e472ee r417aaafb  
    6969        .driver_ops = &virtio_net_driver_ops
    7070};
     71
     72/** Allocate DMA buffers
     73 *
     74 * @param buffers[in]  Number of buffers to allocate.
     75 * @param size[in]     Size of each buffer.
     76 * @param write[in]    True if the buffers are writable by the driver, false
     77 *                     otherwise.
     78 * @param buf[out]     Output array holding virtual addresses of the allocated
     79 *                     buffers.
     80 * @param buf_p[out]   Output array holding physical addresses of the allocated
     81 *                     buffers.
     82 *
     83 * The buffers can be deallocated by virtio_net_teardown_bufs().
     84 *
     85 * @return  EOK on success or error code.
     86 */
     87static errno_t virtio_net_setup_bufs(unsigned int buffers, size_t size,
     88    bool write, void *buf[], uintptr_t buf_p[])
     89{
     90        /*
     91         * Allocate all buffers at once in one large chunk.
     92         */
     93        void *virt = AS_AREA_ANY;
     94        uintptr_t phys;
     95        errno_t rc = dmamem_map_anonymous(buffers * size, 0,
     96            write ? AS_AREA_WRITE : AS_AREA_READ, 0, &phys, &virt);
     97        if (rc != EOK)
     98                return rc;
     99
     100        ddf_msg(LVL_NOTE, "DMA buffers: %p-%p", virt, virt + buffers * size);
     101
     102        /*
     103         * Calculate addresses of the individual buffers for easy access.
     104         */
     105        for (unsigned i = 0; i < buffers; i++) {
     106                buf[i] = virt + i * size;
     107                buf_p[i] = phys + i * size;
     108        }
     109
     110        return EOK;
     111}
     112
     113/** Deallocate DMA buffers
     114 *
     115 * @param buf[in]  Array holding the virtual addresses of the DMA buffers
     116 *                 previously allocated by virtio_net_setup_bufs().
     117 */
     118static void virtio_net_teardown_bufs(void *buf[])
     119{
     120        if (buf[0]) {
     121                dmamem_unmap_anonymous(buf[0]);
     122                buf[0] = NULL;
     123        }
     124}
     125
     126/** Create free descriptor list from the unused VIRTIO descriptors
     127 *
     128 * @param vdev[in]   VIRTIO device for which the free list will be created.
     129 * @param num[in]    Index of the virtqueue for which the free list will be
     130 *                   created.
     131 * @param size[in]   Number of descriptors on the free list. The free list will
     132 *                   contain descriptors starting from 0 to \a size - 1.
     133 * @param head[out]  Variable that will hold the VIRTIO descriptor at the head
     134 *                   of the free list.
     135 */
     136static void virtio_net_create_desc_free_list(virtio_dev_t *vdev, uint16_t num,
     137    uint16_t size, uint16_t *head)
     138{
     139        for (unsigned i = 0; i < size; i++) {
     140                virtio_virtq_desc_set(vdev, num, i, 0, 0,
     141                    VIRTQ_DESC_F_NEXT, (i + 1 == size) ? -1U : i + 1);
     142        }
     143        *head = 0;
     144}
     145
     146/** Allocate a descriptor from the free list
     147 *
     148 * @param vdev[in]      VIRTIO device with the free list.
     149 * @param num[in]       Index of the virtqueue with free list.
     150 * @param head[in,out]  Head of the free list.
     151 *
     152 * @return  Allocated descriptor or 0xFFFF if the list is empty.
     153 */
     154static uint16_t virtio_net_alloc_desc(virtio_dev_t *vdev, uint16_t num,
     155    uint16_t *head)
     156{
     157        virtq_t *q = &vdev->queues[num];
     158        fibril_mutex_lock(&q->lock);
     159        uint16_t descno = *head;
     160        if (descno != (uint16_t) -1U)
     161                *head = virtio_virtq_desc_get_next(vdev, num, descno);
     162        fibril_mutex_unlock(&q->lock);
     163        return descno;
     164}
     165
     166/** Free a descriptor into the free list
     167 *
     168 * @param vdev[in]      VIRTIO device with the free list.
     169 * @param num[in]       Index of the virtqueue with free list.
     170 * @param head[in,out]  Head of the free list.
     171 * @param descno[in]    The freed descriptor.
     172 */
     173static void virtio_net_free_desc(virtio_dev_t *vdev, uint16_t num,
     174    uint16_t *head, uint16_t descno)
     175{
     176        virtq_t *q = &vdev->queues[num];
     177        fibril_mutex_lock(&q->lock);
     178        virtio_virtq_desc_set(vdev, num, descno, 0, 0, VIRTQ_DESC_F_NEXT,
     179            *head);
     180        *head = descno;
     181        fibril_mutex_unlock(&q->lock);
     182}
    71183
    72184static void virtio_net_irq_handler(ipc_call_t *icall, ddf_dev_t *dev)
     
    102214
    103215        while (virtio_virtq_consume_used(vdev, TX_QUEUE_1, &descno, &len)) {
    104                 virtio_free_desc(vdev, TX_QUEUE_1, &virtio_net->tx_free_head,
    105                     descno);
     216                virtio_net_free_desc(vdev, TX_QUEUE_1,
     217                    &virtio_net->tx_free_head, descno);
    106218        }
    107219        while (virtio_virtq_consume_used(vdev, CT_QUEUE_1, &descno, &len)) {
    108                 virtio_free_desc(vdev, CT_QUEUE_1, &virtio_net->ct_free_head,
    109                     descno);
     220                virtio_net_free_desc(vdev, CT_QUEUE_1,
     221                    &virtio_net->ct_free_head, descno);
    110222        }
    111223}
     
    233345         * Setup DMA buffers
    234346         */
    235         rc = virtio_setup_dma_bufs(RX_BUFFERS, RX_BUF_SIZE, false,
     347        rc = virtio_net_setup_bufs(RX_BUFFERS, RX_BUF_SIZE, false,
    236348            virtio_net->rx_buf, virtio_net->rx_buf_p);
    237349        if (rc != EOK)
    238350                goto fail;
    239         rc = virtio_setup_dma_bufs(TX_BUFFERS, TX_BUF_SIZE, true,
     351        rc = virtio_net_setup_bufs(TX_BUFFERS, TX_BUF_SIZE, true,
    240352            virtio_net->tx_buf, virtio_net->tx_buf_p);
    241353        if (rc != EOK)
    242354                goto fail;
    243         rc = virtio_setup_dma_bufs(CT_BUFFERS, CT_BUF_SIZE, true,
     355        rc = virtio_net_setup_bufs(CT_BUFFERS, CT_BUF_SIZE, true,
    244356            virtio_net->ct_buf, virtio_net->ct_buf_p);
    245357        if (rc != EOK)
     
    267379         * Put all TX and CT buffers on a free list
    268380         */
    269         virtio_create_desc_free_list(vdev, TX_QUEUE_1, TX_BUFFERS,
     381        virtio_net_create_desc_free_list(vdev, TX_QUEUE_1, TX_BUFFERS,
    270382            &virtio_net->tx_free_head);
    271         virtio_create_desc_free_list(vdev, CT_QUEUE_1, CT_BUFFERS,
     383        virtio_net_create_desc_free_list(vdev, CT_QUEUE_1, CT_BUFFERS,
    272384            &virtio_net->ct_free_head);
    273385
     
    302414
    303415fail:
    304         virtio_teardown_dma_bufs(virtio_net->rx_buf);
    305         virtio_teardown_dma_bufs(virtio_net->tx_buf);
    306         virtio_teardown_dma_bufs(virtio_net->ct_buf);
     416        virtio_net_teardown_bufs(virtio_net->rx_buf);
     417        virtio_net_teardown_bufs(virtio_net->tx_buf);
     418        virtio_net_teardown_bufs(virtio_net->ct_buf);
    307419
    308420        virtio_device_setup_fail(vdev);
     
    316428        virtio_net_t *virtio_net = (virtio_net_t *) nic_get_specific(nic);
    317429
    318         virtio_teardown_dma_bufs(virtio_net->rx_buf);
    319         virtio_teardown_dma_bufs(virtio_net->tx_buf);
    320         virtio_teardown_dma_bufs(virtio_net->ct_buf);
     430        virtio_net_teardown_bufs(virtio_net->rx_buf);
     431        virtio_net_teardown_bufs(virtio_net->tx_buf);
     432        virtio_net_teardown_bufs(virtio_net->ct_buf);
    321433
    322434        virtio_device_setup_fail(&virtio_net->virtio_dev);
     
    334446        }
    335447
    336         uint16_t descno = virtio_alloc_desc(vdev, TX_QUEUE_1,
     448        uint16_t descno = virtio_net_alloc_desc(vdev, TX_QUEUE_1,
    337449            &virtio_net->tx_free_head);
    338450        if (descno == (uint16_t) -1U) {
Note: See TracChangeset for help on using the changeset viewer.