Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changeset cbcb34c in mainline


Ignore:
Timestamp:
2018-05-22T19:06:50Z (3 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master
Children:
341df5f
Parents:
1c53d93
git-author:
Jakub Jermar <jakub@…> (2018-05-05 14:43:51)
git-committer:
Jakub Jermar <jakub@…> (2018-05-22 19:06:50)
Message:

Configure the virtqueues

Location:
uspace
Files:
4 edited

Legend:

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

    r1c53d93 rcbcb34c  
    4343#define NAME    "virtio-net"
    4444
     45#define VIRTIO_NET_NUM_QUEUES   3
     46
     47#define RECVQ1          0
     48#define TRANSQ1         1
     49#define CTRLQ1          2
     50
     51#define RECVQ_SIZE      8
     52#define TRANSQ_SIZE     8
     53#define CTRLQ_SIZE      4
     54
    4555static errno_t virtio_net_initialize(ddf_dev_t *dev)
    4656{
     
    6171                return rc;
    6272
     73        virtio_dev_t *vdev = &virtio_net->virtio_dev;
    6374        virtio_pci_common_cfg_t *cfg = virtio_net->virtio_dev.common_cfg;
    6475        virtio_net_cfg_t *netcfg = virtio_net->virtio_dev.device_cfg;
     
    8697
    8798        ddf_msg(LVL_NOTE, "offered features %x", features);
    88         features &= (1U << VIRTIO_NET_F_MAC);
     99        features &= (1U << VIRTIO_NET_F_MAC) | (1U << VIRTIO_NET_F_CTRL_VQ);
    89100
    90101        if (!features) {
     
    96107        pio_write_32(&cfg->driver_feature_select, VIRTIO_NET_F_SELECT_PAGE_0);
    97108        pio_write_32(&cfg->driver_feature, features);
     109
     110        ddf_msg(LVL_NOTE, "accepted features %x", features);
    98111
    99112        /* 5. Set FEATURES_OK */
     
    109122
    110123        /* 7. Perform device-specific setup */
     124
     125        /*
     126         * Discover and configure the virtqueues
     127         */
     128        uint16_t num_queues = pio_read_16(&cfg->num_queues);
     129        if (num_queues != VIRTIO_NET_NUM_QUEUES) {
     130                ddf_msg(LVL_NOTE, "Unsupported number of virtqueues: %u",
     131                    num_queues);
     132                goto fail;
     133        }
     134
     135        vdev->queues = calloc(sizeof(virtq_t), num_queues);
     136        if (!vdev->queues) {
     137                rc = ENOMEM;
     138                goto fail;
     139        }
     140
     141        rc = virtio_virtq_setup(vdev, RECVQ1, RECVQ_SIZE, 1500,
     142            VIRTQ_DESC_F_WRITE);
     143        if (rc != EOK)
     144                goto fail;
     145        rc = virtio_virtq_setup(vdev, TRANSQ1, TRANSQ_SIZE, 1500, 0);
     146        if (rc != EOK)
     147                goto fail;
     148        rc = virtio_virtq_setup(vdev, CTRLQ1, CTRLQ_SIZE, 512, 0);
     149        if (rc != EOK)
     150                goto fail;
     151
     152        /*
     153         * Read the MAC address
     154         */
    111155        nic_address_t nic_addr;
    112156        for (unsigned i = 0; i < 6; i++)
    113                 nic_addr.address[i] = netcfg->mac[i];
     157                nic_addr.address[i] = pio_read_8(&netcfg->mac[i]);
    114158        rc = nic_report_address(nic_data, &nic_addr);
    115159        if (rc != EOK)
  • uspace/drv/nic/virtio-net/virtio-net.h

    r1c53d93 rcbcb34c  
    4040/** Device has given MAC address. */
    4141#define VIRTIO_NET_F_MAC                5
     42/** Control channel is available */
     43#define VIRTIO_NET_F_CTRL_VQ            17
    4244
    4345typedef struct {
  • uspace/lib/virtio/virtio-pci.c

    r1c53d93 rcbcb34c  
    3232#include "virtio-pci.h"
    3333
     34#include <as.h>
     35#include <align.h>
     36#include <macros.h>
     37
    3438#include <ddf/driver.h>
    3539#include <ddf/log.h>
     
    173177
    174178        return EOK;
     179}
     180
     181errno_t virtio_virtq_setup(virtio_dev_t *vdev, uint16_t num, uint16_t size,
     182    size_t buf_size, uint16_t buf_flags)
     183{
     184        virtq_t *q = &vdev->queues[num];
     185        virtio_pci_common_cfg_t *cfg = vdev->common_cfg;
     186
     187        /* Program the queue of our interest */
     188        pio_write_16(&cfg->queue_select, num);
     189
     190        /* Trim the size of the queue as needed */
     191        size = min(pio_read_16(&cfg->queue_size), size);
     192        pio_write_16(&cfg->queue_size, size);
     193        ddf_msg(LVL_NOTE, "Virtq %u: %u buffers", num, (unsigned) size);
     194
     195        /* Allocate array to hold virtual addresses of DMA buffers */
     196        void **buffers = calloc(sizeof(void *), size);
     197        if (!buffers)
     198                return ENOMEM;
     199
     200        size_t avail_offset = 0;
     201        size_t used_offset = 0;
     202        size_t buffers_offset = 0;
     203
     204        /*
     205         * Compute the size of the needed DMA memory and also the offsets of
     206         * the individual components
     207         */
     208        size_t mem_size = sizeof(virtq_desc_t[size]);
     209        mem_size = ALIGN_UP(mem_size, _Alignof(virtq_avail_t));
     210        avail_offset = mem_size;
     211        mem_size += sizeof(virtq_avail_t) + sizeof(ioport16_t[size]) +
     212            sizeof(ioport16_t);
     213        mem_size = ALIGN_UP(mem_size, _Alignof(virtq_used_t));
     214        used_offset = mem_size;
     215        mem_size += sizeof(virtq_used_t) + sizeof(virtq_used_elem_t[size]) +
     216            sizeof(ioport16_t);
     217        buffers_offset = mem_size;
     218        mem_size += size * buf_size;
     219
     220        /*
     221         * Allocate DMA memory for the virtqueues and the buffers
     222         */
     223        q->virt = AS_AREA_ANY;
     224        errno_t rc = dmamem_map_anonymous(mem_size, DMAMEM_4GiB,
     225            AS_AREA_READ | AS_AREA_WRITE, 0, &q->phys, &q->virt);
     226        if (rc != EOK) {
     227                free(buffers);
     228                q->virt = NULL;
     229                return rc;
     230        }
     231
     232        q->size = mem_size;
     233        q->queue_size = size;
     234        q->desc = q->virt;
     235        q->avail = q->virt + avail_offset;
     236        q->used = q->virt + used_offset;
     237        q->buffers = buffers;
     238
     239        memset(q->virt, 0, q->size);
     240
     241        /*
     242         * Initialize the descriptor table and the buffers array
     243         */
     244        for (unsigned i = 0; i < size; i++) {
     245                q->desc[i].addr = q->phys + buffers_offset + i * buf_size;
     246                q->desc[i].len = buf_size;
     247                q->desc[i].flags = buf_flags;
     248
     249                q->buffers[i] = q->virt + buffers_offset + i * buf_size;
     250        }
     251
     252        /*
     253         * Write the configured addresses to device's common config
     254         */
     255        pio_write_64(&cfg->queue_desc, q->phys);
     256        pio_write_64(&cfg->queue_avail, q->phys + avail_offset);
     257        pio_write_64(&cfg->queue_used, q->phys + used_offset);
     258
     259        ddf_msg(LVL_NOTE, "DMA memory for virtq %d: virt=%p, phys=%p, size=%zu",
     260            num, q->virt, (void *) q->phys, q->size);
     261
     262        return rc;
     263}
     264
     265void virtio_virtq_teardown(virtio_dev_t *vdev, uint16_t num)
     266{
     267        virtq_t *q = &vdev->queues[num];
     268        if (q->size)
     269                dmamem_unmap_anonymous(q->virt);
     270        if (q->buffers)
     271                free(q->buffers);
    175272}
    176273
     
    279376errno_t virtio_pci_dev_cleanup(virtio_dev_t *vdev)
    280377{
     378        if (vdev->queues) {
     379                for (unsigned i = 0;
     380                    i < pio_read_16(&vdev->common_cfg->num_queues); i++)
     381                        virtio_virtq_teardown(vdev, i);
     382                free(vdev->queues);
     383        }
    281384        return disable_resources(vdev);
    282385}
  • uspace/lib/virtio/virtio-pci.h

    r1c53d93 rcbcb34c  
    124124} virtq_used_t;
    125125
     126typedef struct {
     127        void *virt;
     128        uintptr_t phys;
     129        size_t size;
     130
     131        /**
     132         * Size of the queue which determines the number of descriptors and
     133         * DMA buffers.
     134         */
     135        size_t queue_size;
     136
     137        /** Virtual address of queue size virtq descriptors */
     138        virtq_desc_t *desc;
     139        /** Virtual address of the available ring */
     140        virtq_avail_t *avail;
     141        /** Virtual address of the used ring */
     142        virtq_used_t *used;
     143
     144        /**
     145         * Queue-size-sized array of virtual addresses of the atcual DMA
     146         * buffers.
     147         */
     148        void **buffers;
     149} virtq_t;
     150
    126151/** VIRTIO-device specific data associated with the NIC framework nic_t */
    127152typedef struct {
     
    145170        /** Device-specific configuration */
    146171        void *device_cfg;
     172
     173        /** Virtqueues */
     174        virtq_t *queues;
    147175} virtio_dev_t;
     176
     177extern errno_t virtio_virtq_setup(virtio_dev_t *, uint16_t, uint16_t, size_t,
     178    uint16_t);
     179extern void virtio_virtq_teardown(virtio_dev_t *, uint16_t);
    148180
    149181extern errno_t virtio_pci_dev_initialize(ddf_dev_t *, virtio_dev_t *);
Note: See TracChangeset for help on using the changeset viewer.