Print this page
    
Use #pragma pack() per Hans
Hans review comments, but no pragma packed yet.
Add virtio net feature bit order string
Reviewed by: Josef 'Jeff' Sipek <josef.sipek@nexenta.com>
Code review changes
    
      
        | Split | 
	Close | 
      
      | Expand all | 
      | Collapse all | 
    
    
          --- old/usr/src/uts/common/io/vioif/vioif.c
          +++ new/usr/src/uts/common/io/vioif/vioif.c
   1    1  /*
   2    2   * This file and its contents are supplied under the terms of the
   3    3   * Common Development and Distribution License ("CDDL"), version 1.0.
   4    4   * You may only use this file in accordance with the terms of version
   5    5   * 1.0 of the CDDL.
   6    6   *
   7    7   * A full copy of the text of the CDDL should have accompanied this
   8    8   * source.  A copy of the CDDL is also available via the Internet at
   9    9   * http://www.illumos.org/license/CDDL.
  10   10   */
  11   11  
  12   12  /*
  13   13   * Copyright 2013 Nexenta Inc.  All rights reserved.
  14   14   * Copyright (c) 2014, 2015 by Delphix. All rights reserved.
  15   15   */
  16   16  
  17   17  /* Based on the NetBSD virtio driver by Minoura Makoto. */
  18   18  /*
  19   19   * Copyright (c) 2010 Minoura Makoto.
  20   20   * All rights reserved.
  21   21   *
  22   22   * Redistribution and use in source and binary forms, with or without
  23   23   * modification, are permitted provided that the following conditions
  24   24   * are met:
  25   25   * 1. Redistributions of source code must retain the above copyright
  26   26   *    notice, this list of conditions and the following disclaimer.
  27   27   * 2. Redistributions in binary form must reproduce the above copyright
  28   28   *    notice, this list of conditions and the following disclaimer in the
  29   29   *    documentation and/or other materials provided with the distribution.
  30   30   *
  31   31   * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  32   32   * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  33   33   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  34   34   * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  35   35   * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  36   36   * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  37   37   * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  38   38   * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  39   39   * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  40   40   * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  41   41   */
  42   42  
  43   43  #include <sys/types.h>
  44   44  #include <sys/errno.h>
  45   45  #include <sys/param.h>
  46   46  #include <sys/stropts.h>
  47   47  #include <sys/stream.h>
  
    | 
      ↓ open down ↓ | 
    47 lines elided | 
    
      ↑ open up ↑ | 
  
  48   48  #include <sys/strsubr.h>
  49   49  #include <sys/kmem.h>
  50   50  #include <sys/conf.h>
  51   51  #include <sys/devops.h>
  52   52  #include <sys/ksynch.h>
  53   53  #include <sys/stat.h>
  54   54  #include <sys/modctl.h>
  55   55  #include <sys/debug.h>
  56   56  #include <sys/pci.h>
  57   57  #include <sys/ethernet.h>
       58 +#include <sys/vlan.h>
  58   59  
  59      -#define VLAN_TAGSZ 4
  60      -
  61   60  #include <sys/dlpi.h>
  62   61  #include <sys/taskq.h>
  63   62  #include <sys/cyclic.h>
  64   63  
  65   64  #include <sys/pattr.h>
  66   65  #include <sys/strsun.h>
  67   66  
  68   67  #include <sys/random.h>
  69   68  #include <sys/sysmacros.h>
  70   69  #include <sys/stream.h>
  71   70  
  72   71  #include <sys/mac.h>
  73   72  #include <sys/mac_provider.h>
  74   73  #include <sys/mac_ether.h>
  75   74  
  76   75  #include "virtiovar.h"
  77   76  #include "virtioreg.h"
  78   77  
  79      -#if !defined(__packed)
  80      -#define __packed __attribute__((packed))
  81      -#endif /* __packed */
  82      -
  83   78  /* Configuration registers */
  84   79  #define VIRTIO_NET_CONFIG_MAC           0 /* 8bit x 6byte */
  85   80  #define VIRTIO_NET_CONFIG_STATUS        6 /* 16bit */
  86   81  
  87   82  /* Feature bits */
  88   83  #define VIRTIO_NET_F_CSUM       (1 << 0) /* Host handles pkts w/ partial csum */
  89   84  #define VIRTIO_NET_F_GUEST_CSUM (1 << 1) /* Guest handles pkts w/ part csum */
  90   85  #define VIRTIO_NET_F_MAC        (1 << 5) /* Host has given MAC address. */
  91   86  #define VIRTIO_NET_F_GSO        (1 << 6) /* Host handles pkts w/ any GSO type */
  92   87  #define VIRTIO_NET_F_GUEST_TSO4 (1 << 7) /* Guest can handle TSOv4 in. */
  93   88  #define VIRTIO_NET_F_GUEST_TSO6 (1 << 8) /* Guest can handle TSOv6 in. */
  94   89  #define VIRTIO_NET_F_GUEST_ECN  (1 << 9) /* Guest can handle TSO[6] w/ ECN in */
  95   90  #define VIRTIO_NET_F_GUEST_UFO  (1 << 10) /* Guest can handle UFO in. */
  96   91  #define VIRTIO_NET_F_HOST_TSO4  (1 << 11) /* Host can handle TSOv4 in. */
  
    | 
      ↓ open down ↓ | 
    4 lines elided | 
    
      ↑ open up ↑ | 
  
  97   92  #define VIRTIO_NET_F_HOST_TSO6  (1 << 12) /* Host can handle TSOv6 in. */
  98   93  #define VIRTIO_NET_F_HOST_ECN   (1 << 13) /* Host can handle TSO[6] w/ ECN in */
  99   94  #define VIRTIO_NET_F_HOST_UFO   (1 << 14) /* Host can handle UFO in. */
 100   95  #define VIRTIO_NET_F_MRG_RXBUF  (1 << 15) /* Host can merge receive buffers. */
 101   96  #define VIRTIO_NET_F_STATUS     (1 << 16) /* Config.status available */
 102   97  #define VIRTIO_NET_F_CTRL_VQ    (1 << 17) /* Control channel available */
 103   98  #define VIRTIO_NET_F_CTRL_RX    (1 << 18) /* Control channel RX mode support */
 104   99  #define VIRTIO_NET_F_CTRL_VLAN  (1 << 19) /* Control channel VLAN filtering */
 105  100  #define VIRTIO_NET_F_CTRL_RX_EXTRA (1 << 20) /* Extra RX mode control support */
 106  101  
      102 +#define VIRTIO_NET_FEATURE_BITS \
      103 +        "\020" \
      104 +        "\1CSUM" \
      105 +        "\2GUEST_CSUM" \
      106 +        "\6MAC" \
      107 +        "\7GSO" \
      108 +        "\10GUEST_TSO4" \
      109 +        "\11GUEST_TSO6" \
      110 +        "\12GUEST_ECN" \
      111 +        "\13GUEST_UFO" \
      112 +        "\14HOST_TSO4" \
      113 +        "\15HOST_TSO6" \
      114 +        "\16HOST_ECN" \
      115 +        "\17HOST_UFO" \
      116 +        "\20MRG_RXBUF" \
      117 +        "\21STATUS" \
      118 +        "\22CTRL_VQ" \
      119 +        "\23CTRL_RX" \
      120 +        "\24CTRL_VLAN" \
      121 +        "\25CTRL_RX_EXTRA"
      122 +
 107  123  /* Status */
 108  124  #define VIRTIO_NET_S_LINK_UP    1
 109  125  
      126 +#pragma pack(1)
 110  127  /* Packet header structure */
 111  128  struct virtio_net_hdr {
 112  129          uint8_t         flags;
 113  130          uint8_t         gso_type;
 114  131          uint16_t        hdr_len;
 115  132          uint16_t        gso_size;
 116  133          uint16_t        csum_start;
 117  134          uint16_t        csum_offset;
 118  135  };
      136 +#pragma pack()
 119  137  
 120  138  #define VIRTIO_NET_HDR_F_NEEDS_CSUM     1 /* flags */
 121  139  #define VIRTIO_NET_HDR_GSO_NONE         0 /* gso_type */
 122  140  #define VIRTIO_NET_HDR_GSO_TCPV4        1 /* gso_type */
 123  141  #define VIRTIO_NET_HDR_GSO_UDP          3 /* gso_type */
 124  142  #define VIRTIO_NET_HDR_GSO_TCPV6        4 /* gso_type */
 125  143  #define VIRTIO_NET_HDR_GSO_ECN          0x80 /* gso_type, |'ed */
 126  144  
 127  145  
 128  146  /* Control virtqueue */
      147 +#pragma pack(1)
 129  148  struct virtio_net_ctrl_cmd {
 130  149          uint8_t class;
 131  150          uint8_t command;
 132      -} __packed;
      151 +};
      152 +#pragma pack()
 133  153  
 134  154  #define VIRTIO_NET_CTRL_RX              0
 135  155  #define VIRTIO_NET_CTRL_RX_PROMISC      0
 136  156  #define VIRTIO_NET_CTRL_RX_ALLMULTI     1
 137  157  
 138  158  #define VIRTIO_NET_CTRL_MAC             1
 139  159  #define VIRTIO_NET_CTRL_MAC_TABLE_SET   0
 140  160  
 141  161  #define VIRTIO_NET_CTRL_VLAN            2
 142  162  #define VIRTIO_NET_CTRL_VLAN_ADD        0
 143  163  #define VIRTIO_NET_CTRL_VLAN_DEL        1
 144  164  
      165 +#pragma pack(1)
 145  166  struct virtio_net_ctrl_status {
 146  167          uint8_t ack;
 147      -} __packed;
      168 +};
 148  169  
 149  170  struct virtio_net_ctrl_rx {
 150  171          uint8_t onoff;
 151      -} __packed;
      172 +};
 152  173  
 153  174  struct virtio_net_ctrl_mac_tbl {
 154  175          uint32_t nentries;
 155  176          uint8_t macs[][ETHERADDRL];
 156      -} __packed;
      177 +};
 157  178  
 158  179  struct virtio_net_ctrl_vlan {
 159  180          uint16_t id;
 160      -} __packed;
      181 +};
      182 +#pragma pack()
 161  183  
 162  184  static int vioif_quiesce(dev_info_t *);
 163  185  static int vioif_attach(dev_info_t *, ddi_attach_cmd_t);
 164  186  static int vioif_detach(dev_info_t *, ddi_detach_cmd_t);
 165  187  
 166  188  DDI_DEFINE_STREAM_OPS(vioif_ops,
 167  189          nulldev,                /* identify */
 168  190          nulldev,                /* probe */
 169  191          vioif_attach,           /* attach */
 170  192          vioif_detach,           /* detach */
 171  193          nodev,                  /* reset */
 172  194          NULL,                   /* cb_ops */
 173  195          D_MP,                   /* bus_ops */
 174  196          NULL,                   /* power */
 175  197          vioif_quiesce           /* quiesce */
 176  198  );
 177  199  
 178  200  static char vioif_ident[] = "VirtIO ethernet driver";
 179  201  
 180  202  /* Standard Module linkage initialization for a Streams driver */
 181  203  extern struct mod_ops mod_driverops;
 182  204  
 183  205  static struct modldrv modldrv = {
 184  206          &mod_driverops,         /* Type of module.  This one is a driver */
 185  207          vioif_ident,            /* short description */
 186  208          &vioif_ops              /* driver specific ops */
 187  209  };
 188  210  
 189  211  static struct modlinkage modlinkage = {
 190  212          MODREV_1,
 191  213          {
 192  214                  (void *)&modldrv,
 193  215                  NULL,
 194  216          },
 195  217  };
 196  218  
 197  219  ddi_device_acc_attr_t vioif_attr = {
 198  220          DDI_DEVICE_ATTR_V0,
 199  221          DDI_NEVERSWAP_ACC,      /* virtio is always native byte order */
 200  222          DDI_STORECACHING_OK_ACC,
 201  223          DDI_DEFAULT_ACC
 202  224  };
 203  225  
 204  226  /*
 205  227   * A mapping represents a binding for a single buffer that is contiguous in the
 206  228   * virtual address space.
 207  229   */
 208  230  struct vioif_buf_mapping {
 209  231          caddr_t                 vbm_buf;
 210  232          ddi_dma_handle_t        vbm_dmah;
 211  233          ddi_acc_handle_t        vbm_acch;
 212  234          ddi_dma_cookie_t        vbm_dmac;
 213  235          unsigned int            vbm_ncookies;
 214  236  };
 215  237  
 216  238  /*
 217  239   * Rx buffers can be loaned upstream, so the code has
 218  240   * to allocate them dynamically.
 219  241   */
 220  242  struct vioif_rx_buf {
 221  243          struct vioif_softc      *rb_sc;
 222  244          frtn_t                  rb_frtn;
 223  245  
 224  246          struct vioif_buf_mapping rb_mapping;
 225  247  };
 226  248  
 227  249  /*
 228  250   * Tx buffers have two mapping types. One, "inline", is pre-allocated and is
 229  251   * used to hold the virtio_net_header. Small packets also get copied there, as
 230  252   * it's faster then mapping them. Bigger packets get mapped using the "external"
 231  253   * mapping array. An array is used, because a packet may consist of muptiple
 232  254   * fragments, so each fragment gets bound to an entry. According to my
 233  255   * observations, the number of fragments does not exceed 2, but just in case,
 234  256   * a bigger, up to VIOIF_INDIRECT_MAX - 1 array is allocated. To save resources,
 235  257   * the dma handles are allocated lazily in the tx path.
 236  258   */
 237  259  struct vioif_tx_buf {
 238  260          mblk_t                  *tb_mp;
 239  261  
 240  262          /* inline buffer */
 241  263          struct vioif_buf_mapping tb_inline_mapping;
 242  264  
 243  265          /* External buffers */
 244  266          struct vioif_buf_mapping *tb_external_mapping;
 245  267          unsigned int            tb_external_num;
 246  268  };
 247  269  
 248  270  struct vioif_softc {
 249  271          dev_info_t              *sc_dev; /* mirrors virtio_softc->sc_dev */
 250  272          struct virtio_softc     sc_virtio;
 251  273  
 252  274          mac_handle_t sc_mac_handle;
 253  275          mac_register_t *sc_macp;
 254  276  
 255  277          struct virtqueue        *sc_rx_vq;
 256  278          struct virtqueue        *sc_tx_vq;
 257  279          struct virtqueue        *sc_ctrl_vq;
 258  280  
 259  281          unsigned int            sc_tx_stopped:1;
 260  282  
 261  283          /* Feature bits. */
 262  284          unsigned int            sc_rx_csum:1;
 263  285          unsigned int            sc_tx_csum:1;
 264  286          unsigned int            sc_tx_tso4:1;
 265  287  
 266  288          int                     sc_mtu;
 267  289          uint8_t                 sc_mac[ETHERADDRL];
 268  290          /*
 269  291           * For rx buffers, we keep a pointer array, because the buffers
 270  292           * can be loaned upstream, and we have to repopulate the array with
 271  293           * new members.
 272  294           */
 273  295          struct vioif_rx_buf     **sc_rxbufs;
 274  296  
 275  297          /*
 276  298           * For tx, we just allocate an array of buffers. The packet can
 277  299           * either be copied into the inline buffer, or the external mapping
 278  300           * could be used to map the packet
 279  301           */
 280  302          struct vioif_tx_buf     *sc_txbufs;
 281  303  
 282  304          kstat_t                 *sc_intrstat;
 283  305          /*
 284  306           * We "loan" rx buffers upstream and reuse them after they are
 285  307           * freed. This lets us avoid allocations in the hot path.
 286  308           */
 287  309          kmem_cache_t            *sc_rxbuf_cache;
 288  310          ulong_t                 sc_rxloan;
 289  311  
 290  312          /* Copying small packets turns out to be faster then mapping them. */
 291  313          unsigned long           sc_rxcopy_thresh;
 292  314          unsigned long           sc_txcopy_thresh;
 293  315          /* Some statistic coming here */
 294  316          uint64_t                sc_ipackets;
 295  317          uint64_t                sc_opackets;
 296  318          uint64_t                sc_rbytes;
 297  319          uint64_t                sc_obytes;
 298  320          uint64_t                sc_brdcstxmt;
 299  321          uint64_t                sc_brdcstrcv;
 300  322          uint64_t                sc_multixmt;
 301  323          uint64_t                sc_multircv;
 302  324          uint64_t                sc_norecvbuf;
 303  325          uint64_t                sc_notxbuf;
 304  326          uint64_t                sc_ierrors;
 305  327          uint64_t                sc_oerrors;
 306  328  };
 307  329  
 308  330  #define ETHER_HEADER_LEN                sizeof (struct ether_header)
 309  331  
 310  332  /* MTU + the ethernet header. */
 311  333  #define MAX_PAYLOAD     65535
 312  334  #define MAX_MTU         (MAX_PAYLOAD - ETHER_HEADER_LEN)
 313  335  #define DEFAULT_MTU     ETHERMTU
 314  336  
 315  337  /*
 316  338   * Yeah, we spend 8M per device. Turns out, there is no point
 317  339   * being smart and using merged rx buffers (VIRTIO_NET_F_MRG_RXBUF),
 318  340   * because vhost does not support them, and we expect to be used with
 319  341   * vhost in production environment.
 320  342   */
 321  343  /* The buffer keeps both the packet data and the virtio_net_header. */
 322  344  #define VIOIF_RX_SIZE (MAX_PAYLOAD + sizeof (struct virtio_net_hdr))
 323  345  
 324  346  /*
 325  347   * We win a bit on header alignment, but the host wins a lot
 326  348   * more on moving aligned buffers. Might need more thought.
 327  349   */
 328  350  #define VIOIF_IP_ALIGN 0
 329  351  
 330  352  /* Maximum number of indirect descriptors, somewhat arbitrary. */
 331  353  #define VIOIF_INDIRECT_MAX 128
 332  354  
 333  355  /*
 334  356   * We pre-allocate a reasonably large buffer to copy small packets
 335  357   * there. Bigger packets are mapped, packets with multiple
 336  358   * cookies are mapped as indirect buffers.
 337  359   */
 338  360  #define VIOIF_TX_INLINE_SIZE 2048
 339  361  
 340  362  /* Native queue size for all queues */
 341  363  #define VIOIF_RX_QLEN 0
 342  364  #define VIOIF_TX_QLEN 0
 343  365  #define VIOIF_CTRL_QLEN 0
 344  366  
 345  367  static uchar_t vioif_broadcast[ETHERADDRL] = {
 346  368          0xff, 0xff, 0xff, 0xff, 0xff, 0xff
 347  369  };
 348  370  
 349  371  #define VIOIF_TX_THRESH_MAX     640
 350  372  #define VIOIF_RX_THRESH_MAX     640
 351  373  
 352  374  #define CACHE_NAME_SIZE 32
 353  375  
 354  376  static char vioif_txcopy_thresh[] =
 355  377          "vioif_txcopy_thresh";
 356  378  static char vioif_rxcopy_thresh[] =
 357  379          "vioif_rxcopy_thresh";
 358  380  
 359  381  static char *vioif_priv_props[] = {
 360  382          vioif_txcopy_thresh,
 361  383          vioif_rxcopy_thresh,
 362  384          NULL
 363  385  };
 364  386  
 365  387  /* Add up to ddi? */
 366  388  static ddi_dma_cookie_t *
 367  389  vioif_dma_curr_cookie(ddi_dma_handle_t dmah)
 368  390  {
 369  391          ddi_dma_impl_t *dmah_impl = (void *) dmah;
 370  392          ASSERT(dmah_impl->dmai_cookie);
 371  393          return (dmah_impl->dmai_cookie);
 372  394  }
 373  395  
 374  396  static void
 375  397  vioif_dma_reset_cookie(ddi_dma_handle_t dmah, ddi_dma_cookie_t *dmac)
 376  398  {
 377  399          ddi_dma_impl_t *dmah_impl = (void *) dmah;
 378  400          dmah_impl->dmai_cookie = dmac;
 379  401  }
 380  402  
 381  403  static link_state_t
 382  404  vioif_link_state(struct vioif_softc *sc)
 383  405  {
 384  406          if (sc->sc_virtio.sc_features & VIRTIO_NET_F_STATUS) {
 385  407                  if (virtio_read_device_config_2(&sc->sc_virtio,
 386  408                      VIRTIO_NET_CONFIG_STATUS) & VIRTIO_NET_S_LINK_UP) {
 387  409                          return (LINK_STATE_UP);
 388  410                  } else {
 389  411                          return (LINK_STATE_DOWN);
 390  412                  }
 391  413          }
 392  414  
 393  415          return (LINK_STATE_UP);
 394  416  }
 395  417  
 396  418  static ddi_dma_attr_t vioif_inline_buf_dma_attr = {
 397  419          DMA_ATTR_V0,            /* Version number */
 398  420          0,                      /* low address */
 399  421          0xFFFFFFFFFFFFFFFF,     /* high address */
 400  422          0xFFFFFFFF,             /* counter register max */
 401  423          1,                      /* page alignment */
 402  424          1,                      /* burst sizes: 1 - 32 */
 403  425          1,                      /* minimum transfer size */
 404  426          0xFFFFFFFF,             /* max transfer size */
 405  427          0xFFFFFFFFFFFFFFF,      /* address register max */
 406  428          1,                      /* scatter-gather capacity */
 407  429          1,                      /* device operates on bytes */
 408  430          0,                      /* attr flag: set to 0 */
 409  431  };
 410  432  
 411  433  static ddi_dma_attr_t vioif_mapped_buf_dma_attr = {
 412  434          DMA_ATTR_V0,            /* Version number */
 413  435          0,                      /* low address */
 414  436          0xFFFFFFFFFFFFFFFF,     /* high address */
 415  437          0xFFFFFFFF,             /* counter register max */
 416  438          1,                      /* page alignment */
 417  439          1,                      /* burst sizes: 1 - 32 */
 418  440          1,                      /* minimum transfer size */
 419  441          0xFFFFFFFF,             /* max transfer size */
 420  442          0xFFFFFFFFFFFFFFF,      /* address register max */
 421  443  
 422  444          /* One entry is used for the virtio_net_hdr on the tx path */
 423  445          VIOIF_INDIRECT_MAX - 1, /* scatter-gather capacity */
 424  446          1,                      /* device operates on bytes */
 425  447          0,                      /* attr flag: set to 0 */
 426  448  };
 427  449  
 428  450  static ddi_device_acc_attr_t vioif_bufattr = {
 429  451          DDI_DEVICE_ATTR_V0,
 430  452          DDI_NEVERSWAP_ACC,
 431  453          DDI_STORECACHING_OK_ACC,
 432  454          DDI_DEFAULT_ACC
 433  455  };
 434  456  
 435  457  static void
 436  458  vioif_rx_free(caddr_t free_arg)
 437  459  {
 438  460          struct vioif_rx_buf *buf = (void *) free_arg;
 439  461          struct vioif_softc *sc = buf->rb_sc;
 440  462  
 441  463          kmem_cache_free(sc->sc_rxbuf_cache, buf);
 442  464          atomic_dec_ulong(&sc->sc_rxloan);
 443  465  }
 444  466  
 445  467  static int
 446  468  vioif_rx_construct(void *buffer, void *user_arg, int kmflags)
 447  469  {
 448  470          _NOTE(ARGUNUSED(kmflags));
 449  471          struct vioif_softc *sc = user_arg;
 450  472          struct vioif_rx_buf *buf = buffer;
 451  473          size_t len;
 452  474  
 453  475          if (ddi_dma_alloc_handle(sc->sc_dev, &vioif_mapped_buf_dma_attr,
 454  476              DDI_DMA_SLEEP, NULL, &buf->rb_mapping.vbm_dmah)) {
 455  477                  dev_err(sc->sc_dev, CE_WARN,
 456  478                      "Can't allocate dma handle for rx buffer");
 457  479                  goto exit_handle;
 458  480          }
 459  481  
 460  482          if (ddi_dma_mem_alloc(buf->rb_mapping.vbm_dmah,
 461  483              VIOIF_RX_SIZE + sizeof (struct virtio_net_hdr),
 462  484              &vioif_bufattr, DDI_DMA_STREAMING, DDI_DMA_SLEEP,
 463  485              NULL, &buf->rb_mapping.vbm_buf, &len, &buf->rb_mapping.vbm_acch)) {
 464  486                  dev_err(sc->sc_dev, CE_WARN,
 465  487                      "Can't allocate rx buffer");
 466  488                  goto exit_alloc;
 467  489          }
 468  490          ASSERT(len >= VIOIF_RX_SIZE);
 469  491  
 470  492          if (ddi_dma_addr_bind_handle(buf->rb_mapping.vbm_dmah, NULL,
 471  493              buf->rb_mapping.vbm_buf, len, DDI_DMA_READ | DDI_DMA_STREAMING,
 472  494              DDI_DMA_SLEEP, NULL, &buf->rb_mapping.vbm_dmac,
 473  495              &buf->rb_mapping.vbm_ncookies)) {
 474  496                  dev_err(sc->sc_dev, CE_WARN, "Can't bind tx buffer");
 475  497  
 476  498                  goto exit_bind;
 477  499          }
 478  500  
 479  501          ASSERT(buf->rb_mapping.vbm_ncookies <= VIOIF_INDIRECT_MAX);
 480  502  
 481  503          buf->rb_sc = sc;
 482  504          buf->rb_frtn.free_arg = (void *) buf;
 483  505          buf->rb_frtn.free_func = vioif_rx_free;
 484  506  
 485  507          return (0);
 486  508  exit_bind:
 487  509          ddi_dma_mem_free(&buf->rb_mapping.vbm_acch);
 488  510  exit_alloc:
 489  511          ddi_dma_free_handle(&buf->rb_mapping.vbm_dmah);
 490  512  exit_handle:
 491  513  
 492  514          return (ENOMEM);
 493  515  }
 494  516  
 495  517  static void
 496  518  vioif_rx_destruct(void *buffer, void *user_arg)
 497  519  {
 498  520          _NOTE(ARGUNUSED(user_arg));
 499  521          struct vioif_rx_buf *buf = buffer;
 500  522  
 501  523          ASSERT(buf->rb_mapping.vbm_acch);
 502  524          ASSERT(buf->rb_mapping.vbm_acch);
 503  525  
 504  526          (void) ddi_dma_unbind_handle(buf->rb_mapping.vbm_dmah);
 505  527          ddi_dma_mem_free(&buf->rb_mapping.vbm_acch);
 506  528          ddi_dma_free_handle(&buf->rb_mapping.vbm_dmah);
 507  529  }
 508  530  
 509  531  static void
 510  532  vioif_free_mems(struct vioif_softc *sc)
 511  533  {
 512  534          int i;
 513  535  
 514  536          for (i = 0; i < sc->sc_tx_vq->vq_num; i++) {
 515  537                  struct vioif_tx_buf *buf = &sc->sc_txbufs[i];
 516  538                  int j;
 517  539  
 518  540                  /* Tear down the internal mapping. */
 519  541  
 520  542                  ASSERT(buf->tb_inline_mapping.vbm_acch);
 521  543                  ASSERT(buf->tb_inline_mapping.vbm_dmah);
 522  544  
 523  545                  (void) ddi_dma_unbind_handle(buf->tb_inline_mapping.vbm_dmah);
 524  546                  ddi_dma_mem_free(&buf->tb_inline_mapping.vbm_acch);
 525  547                  ddi_dma_free_handle(&buf->tb_inline_mapping.vbm_dmah);
 526  548  
 527  549                  /* We should not see any in-flight buffers at this point. */
 528  550                  ASSERT(!buf->tb_mp);
 529  551  
 530  552                  /* Free all the dma hdnales we allocated lazily. */
 531  553                  for (j = 0; buf->tb_external_mapping[j].vbm_dmah; j++)
 532  554                          ddi_dma_free_handle(
 533  555                              &buf->tb_external_mapping[j].vbm_dmah);
 534  556                  /* Free the external mapping array. */
 535  557                  kmem_free(buf->tb_external_mapping,
 536  558                      sizeof (struct vioif_tx_buf) * VIOIF_INDIRECT_MAX - 1);
 537  559          }
 538  560  
 539  561          kmem_free(sc->sc_txbufs, sizeof (struct vioif_tx_buf) *
 540  562              sc->sc_tx_vq->vq_num);
 541  563  
 542  564          for (i = 0; i < sc->sc_rx_vq->vq_num; i++) {
 543  565                  struct vioif_rx_buf *buf = sc->sc_rxbufs[i];
 544  566  
 545  567                  if (buf)
 546  568                          kmem_cache_free(sc->sc_rxbuf_cache, buf);
 547  569          }
 548  570          kmem_free(sc->sc_rxbufs, sizeof (struct vioif_rx_buf *) *
 549  571              sc->sc_rx_vq->vq_num);
 550  572  }
 551  573  
 552  574  static int
 553  575  vioif_alloc_mems(struct vioif_softc *sc)
 554  576  {
 555  577          int i, txqsize, rxqsize;
 556  578          size_t len;
 557  579          unsigned int nsegments;
 558  580  
 559  581          txqsize = sc->sc_tx_vq->vq_num;
 560  582          rxqsize = sc->sc_rx_vq->vq_num;
 561  583  
 562  584          sc->sc_txbufs = kmem_zalloc(sizeof (struct vioif_tx_buf) * txqsize,
 563  585              KM_SLEEP);
 564  586          if (sc->sc_txbufs == NULL) {
 565  587                  dev_err(sc->sc_dev, CE_WARN,
 566  588                      "Failed to allocate the tx buffers array");
 567  589                  goto exit_txalloc;
 568  590          }
 569  591  
 570  592          /*
 571  593           * We don't allocate the rx vioif_bufs, just the pointers, as
 572  594           * rx vioif_bufs can be loaned upstream, and we don't know the
 573  595           * total number we need.
 574  596           */
 575  597          sc->sc_rxbufs = kmem_zalloc(sizeof (struct vioif_rx_buf *) * rxqsize,
 576  598              KM_SLEEP);
 577  599          if (sc->sc_rxbufs == NULL) {
 578  600                  dev_err(sc->sc_dev, CE_WARN,
 579  601                      "Failed to allocate the rx buffers pointer array");
 580  602                  goto exit_rxalloc;
 581  603          }
 582  604  
 583  605          for (i = 0; i < txqsize; i++) {
 584  606                  struct vioif_tx_buf *buf = &sc->sc_txbufs[i];
 585  607  
 586  608                  /* Allocate and bind an inline mapping. */
 587  609  
 588  610                  if (ddi_dma_alloc_handle(sc->sc_dev,
 589  611                      &vioif_inline_buf_dma_attr,
 590  612                      DDI_DMA_SLEEP, NULL, &buf->tb_inline_mapping.vbm_dmah)) {
 591  613  
 592  614                          dev_err(sc->sc_dev, CE_WARN,
 593  615                              "Can't allocate dma handle for tx buffer %d", i);
 594  616                          goto exit_tx;
 595  617                  }
 596  618  
 597  619                  if (ddi_dma_mem_alloc(buf->tb_inline_mapping.vbm_dmah,
 598  620                      VIOIF_TX_INLINE_SIZE, &vioif_bufattr, DDI_DMA_STREAMING,
 599  621                      DDI_DMA_SLEEP, NULL, &buf->tb_inline_mapping.vbm_buf,
 600  622                      &len, &buf->tb_inline_mapping.vbm_acch)) {
 601  623  
 602  624                          dev_err(sc->sc_dev, CE_WARN,
 603  625                              "Can't allocate tx buffer %d", i);
 604  626                          goto exit_tx;
 605  627                  }
 606  628                  ASSERT(len >= VIOIF_TX_INLINE_SIZE);
 607  629  
 608  630                  if (ddi_dma_addr_bind_handle(buf->tb_inline_mapping.vbm_dmah,
 609  631                      NULL, buf->tb_inline_mapping.vbm_buf, len,
 610  632                      DDI_DMA_WRITE | DDI_DMA_STREAMING, DDI_DMA_SLEEP, NULL,
 611  633                      &buf->tb_inline_mapping.vbm_dmac, &nsegments)) {
 612  634  
 613  635                          dev_err(sc->sc_dev, CE_WARN,
 614  636                              "Can't bind tx buffer %d", i);
 615  637                          goto exit_tx;
 616  638                  }
 617  639  
 618  640                  /* We asked for a single segment */
 619  641                  ASSERT(nsegments == 1);
 620  642  
 621  643                  /*
 622  644                   * We allow up to VIOIF_INDIRECT_MAX - 1 external mappings.
 623  645                   * In reality, I don't expect more then 2-3 used, but who
 624  646                   * knows.
 625  647                   */
 626  648                  buf->tb_external_mapping = kmem_zalloc(
 627  649                      sizeof (struct vioif_tx_buf) * VIOIF_INDIRECT_MAX - 1,
 628  650                      KM_SLEEP);
 629  651  
 630  652                  /*
 631  653                   * The external mapping's dma handles are allocate lazily,
 632  654                   * as we don't expect most of them to be used..
 633  655                   */
 634  656          }
 635  657  
 636  658          return (0);
 637  659  
 638  660  exit_tx:
 639  661          for (i = 0; i < txqsize; i++) {
 640  662                  struct vioif_tx_buf *buf = &sc->sc_txbufs[i];
 641  663  
 642  664                  if (buf->tb_inline_mapping.vbm_dmah)
 643  665                          (void) ddi_dma_unbind_handle(
 644  666                              buf->tb_inline_mapping.vbm_dmah);
 645  667  
 646  668                  if (buf->tb_inline_mapping.vbm_acch)
 647  669                          ddi_dma_mem_free(
 648  670                              &buf->tb_inline_mapping.vbm_acch);
 649  671  
 650  672                  if (buf->tb_inline_mapping.vbm_dmah)
 651  673                          ddi_dma_free_handle(
 652  674                              &buf->tb_inline_mapping.vbm_dmah);
 653  675  
 654  676                  if (buf->tb_external_mapping)
 655  677                          kmem_free(buf->tb_external_mapping,
 656  678                              sizeof (struct vioif_tx_buf) *
 657  679                              VIOIF_INDIRECT_MAX - 1);
 658  680          }
 659  681  
 660  682          kmem_free(sc->sc_rxbufs, sizeof (struct vioif_rx_buf) * rxqsize);
 661  683  
 662  684  exit_rxalloc:
 663  685          kmem_free(sc->sc_txbufs, sizeof (struct vioif_tx_buf) * txqsize);
 664  686  exit_txalloc:
 665  687          return (ENOMEM);
 666  688  }
 667  689  
 668  690  /* ARGSUSED */
 669  691  int
 670  692  vioif_multicst(void *arg, boolean_t add, const uint8_t *macaddr)
 671  693  {
 672  694          return (DDI_SUCCESS);
 673  695  }
 674  696  
 675  697  /* ARGSUSED */
 676  698  int
 677  699  vioif_promisc(void *arg, boolean_t on)
 678  700  {
 679  701          return (DDI_SUCCESS);
 680  702  }
 681  703  
 682  704  /* ARGSUSED */
 683  705  int
 684  706  vioif_unicst(void *arg, const uint8_t *macaddr)
 685  707  {
 686  708          return (DDI_FAILURE);
 687  709  }
 688  710  
 689  711  
 690  712  static int
 691  713  vioif_add_rx(struct vioif_softc *sc, int kmflag)
 692  714  {
 693  715          struct vq_entry *ve;
 694  716          struct vioif_rx_buf *buf;
 695  717  
 696  718          ve = vq_alloc_entry(sc->sc_rx_vq);
 697  719          if (!ve) {
 698  720                  /*
 699  721                   * Out of free descriptors - ring already full.
 700  722                   * It would be better to update sc_norxdescavail
 701  723                   * but MAC does not ask for this info, hence we
 702  724                   * update sc_norecvbuf.
 703  725                   */
 704  726                  sc->sc_norecvbuf++;
 705  727                  goto exit_vq;
 706  728          }
 707  729          buf = sc->sc_rxbufs[ve->qe_index];
 708  730  
 709  731          if (!buf) {
 710  732                  /* First run, allocate the buffer. */
 711  733                  buf = kmem_cache_alloc(sc->sc_rxbuf_cache, kmflag);
 712  734                  sc->sc_rxbufs[ve->qe_index] = buf;
 713  735          }
 714  736  
 715  737          /* Still nothing? Bye. */
 716  738          if (!buf) {
 717  739                  dev_err(sc->sc_dev, CE_WARN, "Can't allocate rx buffer");
 718  740                  sc->sc_norecvbuf++;
 719  741                  goto exit_buf;
 720  742          }
 721  743  
 722  744          ASSERT(buf->rb_mapping.vbm_ncookies >= 1);
 723  745  
 724  746          /*
 725  747           * For an unknown reason, the virtio_net_hdr must be placed
 726  748           * as a separate virtio queue entry.
 727  749           */
 728  750          virtio_ve_add_indirect_buf(ve, buf->rb_mapping.vbm_dmac.dmac_laddress,
 729  751              sizeof (struct virtio_net_hdr), B_FALSE);
 730  752  
 731  753          /* Add the rest of the first cookie. */
 732  754          virtio_ve_add_indirect_buf(ve,
 733  755              buf->rb_mapping.vbm_dmac.dmac_laddress +
 734  756              sizeof (struct virtio_net_hdr),
 735  757              buf->rb_mapping.vbm_dmac.dmac_size -
 736  758              sizeof (struct virtio_net_hdr), B_FALSE);
 737  759  
 738  760          /*
 739  761           * If the buffer consists of a single cookie (unlikely for a
 740  762           * 64-k buffer), we are done. Otherwise, add the rest of the cookies
 741  763           * using indirect entries.
 742  764           */
 743  765          if (buf->rb_mapping.vbm_ncookies > 1) {
 744  766                  ddi_dma_cookie_t *first_extra_dmac;
 745  767                  ddi_dma_cookie_t dmac;
 746  768                  first_extra_dmac =
 747  769                      vioif_dma_curr_cookie(buf->rb_mapping.vbm_dmah);
 748  770  
 749  771                  ddi_dma_nextcookie(buf->rb_mapping.vbm_dmah, &dmac);
 750  772                  virtio_ve_add_cookie(ve, buf->rb_mapping.vbm_dmah,
 751  773                      dmac, buf->rb_mapping.vbm_ncookies - 1, B_FALSE);
 752  774                  vioif_dma_reset_cookie(buf->rb_mapping.vbm_dmah,
 753  775                      first_extra_dmac);
 754  776          }
 755  777  
 756  778          virtio_push_chain(ve, B_FALSE);
 757  779  
 758  780          return (DDI_SUCCESS);
 759  781  
 760  782  exit_buf:
 761  783          vq_free_entry(sc->sc_rx_vq, ve);
 762  784  exit_vq:
 763  785          return (DDI_FAILURE);
 764  786  }
 765  787  
 766  788  static int
 767  789  vioif_populate_rx(struct vioif_softc *sc, int kmflag)
 768  790  {
 769  791          int i = 0;
 770  792          int ret;
 771  793  
 772  794          for (;;) {
 773  795                  ret = vioif_add_rx(sc, kmflag);
 774  796                  if (ret)
 775  797                          /*
 776  798                           * We could not allocate some memory. Try to work with
 777  799                           * what we've got.
 778  800                           */
 779  801                          break;
 780  802                  i++;
 781  803          }
 782  804  
 783  805          if (i)
 784  806                  virtio_sync_vq(sc->sc_rx_vq);
 785  807  
 786  808          return (i);
 787  809  }
 788  810  
 789  811  static int
 790  812  vioif_process_rx(struct vioif_softc *sc)
 791  813  {
 792  814          struct vq_entry *ve;
 793  815          struct vioif_rx_buf *buf;
 794  816          mblk_t *mp;
 795  817          uint32_t len;
 796  818          int i = 0;
 797  819  
 798  820          while ((ve = virtio_pull_chain(sc->sc_rx_vq, &len))) {
 799  821  
 800  822                  buf = sc->sc_rxbufs[ve->qe_index];
 801  823                  ASSERT(buf);
 802  824  
 803  825                  if (len < sizeof (struct virtio_net_hdr)) {
 804  826                          dev_err(sc->sc_dev, CE_WARN, "RX: Cnain too small: %u",
 805  827                              len - (uint32_t)sizeof (struct virtio_net_hdr));
 806  828                          sc->sc_ierrors++;
 807  829                          virtio_free_chain(ve);
 808  830                          continue;
 809  831                  }
 810  832  
 811  833                  len -= sizeof (struct virtio_net_hdr);
 812  834                  /*
 813  835                   * We copy small packets that happenned to fit into a single
 814  836                   * cookie and reuse the buffers. For bigger ones, we loan
 815  837                   * the buffers upstream.
 816  838                   */
 817  839                  if (len < sc->sc_rxcopy_thresh) {
 818  840                          mp = allocb(len, 0);
 819  841                          if (!mp) {
 820  842                                  sc->sc_norecvbuf++;
 821  843                                  sc->sc_ierrors++;
 822  844  
 823  845                                  virtio_free_chain(ve);
 824  846                                  break;
 825  847                          }
 826  848  
 827  849                          bcopy((char *)buf->rb_mapping.vbm_buf +
 828  850                              sizeof (struct virtio_net_hdr), mp->b_rptr, len);
 829  851                          mp->b_wptr = mp->b_rptr + len;
 830  852  
 831  853                  } else {
 832  854                          mp = desballoc((unsigned char *)
 833  855                              buf->rb_mapping.vbm_buf +
 834  856                              sizeof (struct virtio_net_hdr) +
 835  857                              VIOIF_IP_ALIGN, len, 0, &buf->rb_frtn);
 836  858                          if (!mp) {
  
    | 
      ↓ open down ↓ | 
    666 lines elided | 
    
      ↑ open up ↑ | 
  
 837  859                                  sc->sc_norecvbuf++;
 838  860                                  sc->sc_ierrors++;
 839  861  
 840  862                                  virtio_free_chain(ve);
 841  863                                  break;
 842  864                          }
 843  865                          mp->b_wptr = mp->b_rptr + len;
 844  866  
 845  867                          atomic_inc_ulong(&sc->sc_rxloan);
 846  868                          /*
 847      -                         * Buffer loaned, we will have to allocte a new one
      869 +                         * Buffer loaned, we will have to allocate a new one
 848  870                           * for this slot.
 849  871                           */
 850  872                          sc->sc_rxbufs[ve->qe_index] = NULL;
 851  873                  }
 852  874  
 853  875                  /*
 854  876                   * virtio-net does not tell us if this packet is multicast
 855  877                   * or broadcast, so we have to check it.
 856  878                   */
 857  879                  if (mp->b_rptr[0] & 0x1) {
 858  880                          if (bcmp(mp->b_rptr, vioif_broadcast, ETHERADDRL) != 0)
 859  881                                  sc->sc_multircv++;
 860  882                          else
 861  883                                  sc->sc_brdcstrcv++;
 862  884                  }
 863  885  
 864  886                  sc->sc_rbytes += len;
 865  887                  sc->sc_ipackets++;
 866  888  
 867  889                  virtio_free_chain(ve);
 868  890                  mac_rx(sc->sc_mac_handle, NULL, mp);
 869  891                  i++;
 870  892          }
 871  893  
 872  894          return (i);
 873  895  }
 874  896  
 875  897  static void
 876  898  vioif_reclaim_used_tx(struct vioif_softc *sc)
 877  899  {
 878  900          struct vq_entry *ve;
 879  901          struct vioif_tx_buf *buf;
 880  902          uint32_t len;
 881  903          mblk_t *mp;
 882  904          int i = 0;
 883  905  
 884  906          while ((ve = virtio_pull_chain(sc->sc_tx_vq, &len))) {
 885  907                  /* We don't chain descriptors for tx, so don't expect any. */
 886  908                  ASSERT(!ve->qe_next);
 887  909  
 888  910                  buf = &sc->sc_txbufs[ve->qe_index];
 889  911                  mp = buf->tb_mp;
 890  912                  buf->tb_mp = NULL;
 891  913  
 892  914                  if (mp) {
 893  915                          for (i = 0; i < buf->tb_external_num; i++)
 894  916                                  (void) ddi_dma_unbind_handle(
 895  917                                      buf->tb_external_mapping[i].vbm_dmah);
 896  918                  }
 897  919  
 898  920                  virtio_free_chain(ve);
 899  921  
 900  922                  /* External mapping used, mp was not freed in vioif_send() */
 901  923                  if (mp)
 902  924                          freemsg(mp);
 903  925                  i++;
 904  926          }
 905  927  
 906  928          if (sc->sc_tx_stopped && i) {
 907  929                  sc->sc_tx_stopped = 0;
 908  930                  mac_tx_update(sc->sc_mac_handle);
 909  931          }
 910  932  }
 911  933  
 912  934  /* sc will be used to update stat counters. */
 913  935  /* ARGSUSED */
 914  936  static inline void
 915  937  vioif_tx_inline(struct vioif_softc *sc, struct vq_entry *ve, mblk_t *mp,
 916  938      size_t msg_size)
 917  939  {
 918  940          struct vioif_tx_buf *buf;
 919  941          buf = &sc->sc_txbufs[ve->qe_index];
 920  942  
 921  943          ASSERT(buf);
 922  944  
 923  945          /* Frees mp */
 924  946          mcopymsg(mp, buf->tb_inline_mapping.vbm_buf +
 925  947              sizeof (struct virtio_net_hdr));
 926  948  
 927  949          virtio_ve_add_indirect_buf(ve,
 928  950              buf->tb_inline_mapping.vbm_dmac.dmac_laddress +
 929  951              sizeof (struct virtio_net_hdr), msg_size, B_TRUE);
 930  952  }
 931  953  
 932  954  static inline int
 933  955  vioif_tx_lazy_handle_alloc(struct vioif_softc *sc, struct vioif_tx_buf *buf,
 934  956      int i)
 935  957  {
 936  958          int ret = DDI_SUCCESS;
 937  959  
 938  960          if (!buf->tb_external_mapping[i].vbm_dmah) {
 939  961                  ret = ddi_dma_alloc_handle(sc->sc_dev,
 940  962                      &vioif_mapped_buf_dma_attr, DDI_DMA_SLEEP, NULL,
 941  963                      &buf->tb_external_mapping[i].vbm_dmah);
 942  964                  if (ret != DDI_SUCCESS) {
 943  965                          dev_err(sc->sc_dev, CE_WARN,
 944  966                              "Can't allocate dma handle for external tx buffer");
 945  967                  }
 946  968          }
 947  969  
 948  970          return (ret);
 949  971  }
 950  972  
 951  973  static inline int
 952  974  vioif_tx_external(struct vioif_softc *sc, struct vq_entry *ve, mblk_t *mp,
 953  975      size_t msg_size)
 954  976  {
 955  977          _NOTE(ARGUNUSED(msg_size));
 956  978  
 957  979          struct vioif_tx_buf *buf;
 958  980          mblk_t *nmp;
 959  981          int i, j;
 960  982          int ret = DDI_SUCCESS;
 961  983  
 962  984          buf = &sc->sc_txbufs[ve->qe_index];
 963  985  
 964  986          ASSERT(buf);
 965  987  
 966  988          buf->tb_external_num = 0;
 967  989          i = 0;
 968  990          nmp = mp;
 969  991  
 970  992          while (nmp) {
 971  993                  size_t len;
 972  994                  ddi_dma_cookie_t dmac;
 973  995                  unsigned int ncookies;
 974  996  
 975  997                  len = MBLKL(nmp);
 976  998                  /*
 977  999                   * For some reason, the network stack can
 978 1000                   * actually send us zero-length fragments.
 979 1001                   */
 980 1002                  if (len == 0) {
 981 1003                          nmp = nmp->b_cont;
 982 1004                          continue;
 983 1005                  }
 984 1006  
 985 1007                  ret = vioif_tx_lazy_handle_alloc(sc, buf, i);
 986 1008                  if (ret != DDI_SUCCESS) {
 987 1009                          sc->sc_notxbuf++;
 988 1010                          sc->sc_oerrors++;
 989 1011                          goto exit_lazy_alloc;
 990 1012                  }
 991 1013                  ret = ddi_dma_addr_bind_handle(
 992 1014                      buf->tb_external_mapping[i].vbm_dmah, NULL,
 993 1015                      (caddr_t)nmp->b_rptr, len,
 994 1016                      DDI_DMA_WRITE | DDI_DMA_STREAMING,
 995 1017                      DDI_DMA_SLEEP, NULL, &dmac, &ncookies);
 996 1018  
 997 1019                  if (ret != DDI_SUCCESS) {
 998 1020                          sc->sc_oerrors++;
 999 1021                          dev_err(sc->sc_dev, CE_NOTE,
1000 1022                              "TX: Failed to bind external handle");
1001 1023                          goto exit_bind;
1002 1024                  }
1003 1025  
1004 1026                  /* Check if we still fit into the indirect table. */
1005 1027                  if (virtio_ve_indirect_available(ve) < ncookies) {
1006 1028                          dev_err(sc->sc_dev, CE_NOTE,
1007 1029                              "TX: Indirect descriptor table limit reached."
1008 1030                              " It took %d fragments.", i);
1009 1031                          sc->sc_notxbuf++;
1010 1032                          sc->sc_oerrors++;
1011 1033  
1012 1034                          ret = DDI_FAILURE;
1013 1035                          goto exit_limit;
1014 1036                  }
1015 1037  
1016 1038                  virtio_ve_add_cookie(ve, buf->tb_external_mapping[i].vbm_dmah,
1017 1039                      dmac, ncookies, B_TRUE);
1018 1040  
1019 1041                  nmp = nmp->b_cont;
1020 1042                  i++;
1021 1043          }
1022 1044  
1023 1045          buf->tb_external_num = i;
1024 1046          /* Save the mp to free it when the packet is sent. */
1025 1047          buf->tb_mp = mp;
1026 1048  
1027 1049          return (DDI_SUCCESS);
1028 1050  
1029 1051  exit_limit:
1030 1052  exit_bind:
1031 1053  exit_lazy_alloc:
1032 1054  
1033 1055          for (j = 0; j < i; j++) {
1034 1056                  (void) ddi_dma_unbind_handle(
1035 1057                      buf->tb_external_mapping[j].vbm_dmah);
1036 1058          }
1037 1059  
1038 1060          return (ret);
1039 1061  }
1040 1062  
1041 1063  static boolean_t
1042 1064  vioif_send(struct vioif_softc *sc, mblk_t *mp)
1043 1065  {
1044 1066          struct vq_entry *ve;
1045 1067          struct vioif_tx_buf *buf;
1046 1068          struct virtio_net_hdr *net_header = NULL;
1047 1069          size_t msg_size = 0;
1048 1070          uint32_t csum_start;
1049 1071          uint32_t csum_stuff;
1050 1072          uint32_t csum_flags;
1051 1073          uint32_t lso_flags;
1052 1074          uint32_t lso_mss;
1053 1075          mblk_t *nmp;
1054 1076          int ret;
1055 1077          boolean_t lso_required = B_FALSE;
1056 1078  
1057 1079          for (nmp = mp; nmp; nmp = nmp->b_cont)
1058 1080                  msg_size += MBLKL(nmp);
1059 1081  
1060 1082          if (sc->sc_tx_tso4) {
1061 1083                  mac_lso_get(mp, &lso_mss, &lso_flags);
1062 1084                  lso_required = (lso_flags & HW_LSO);
1063 1085          }
1064 1086  
1065 1087          ve = vq_alloc_entry(sc->sc_tx_vq);
1066 1088  
1067 1089          if (!ve) {
  
    | 
      ↓ open down ↓ | 
    210 lines elided | 
    
      ↑ open up ↑ | 
  
1068 1090                  sc->sc_notxbuf++;
1069 1091                  /* Out of free descriptors - try later. */
1070 1092                  return (B_FALSE);
1071 1093          }
1072 1094          buf = &sc->sc_txbufs[ve->qe_index];
1073 1095  
1074 1096          /* Use the inline buffer of the first entry for the virtio_net_hdr. */
1075 1097          (void) memset(buf->tb_inline_mapping.vbm_buf, 0,
1076 1098              sizeof (struct virtio_net_hdr));
1077 1099  
1078      -        /* LINTED E_BAD_PTR_CAST_ALIGN */
1079      -        net_header = (struct virtio_net_hdr *)
1080      -            buf->tb_inline_mapping.vbm_buf;
     1100 +        net_header = (struct virtio_net_hdr *)buf->tb_inline_mapping.vbm_buf;
1081 1101  
1082 1102          mac_hcksum_get(mp, &csum_start, &csum_stuff, NULL,
1083 1103              NULL, &csum_flags);
1084 1104  
1085 1105          /* They want us to do the TCP/UDP csum calculation. */
1086 1106          if (csum_flags & HCK_PARTIALCKSUM) {
1087 1107                  struct ether_header *eth_header;
1088 1108                  int eth_hsize;
1089 1109  
1090 1110                  /* Did we ask for it? */
1091 1111                  ASSERT(sc->sc_tx_csum);
1092 1112  
1093 1113                  /* We only asked for partial csum packets. */
1094 1114                  ASSERT(!(csum_flags & HCK_IPV4_HDRCKSUM));
1095 1115                  ASSERT(!(csum_flags & HCK_FULLCKSUM));
1096 1116  
1097 1117                  eth_header = (void *) mp->b_rptr;
1098 1118                  if (eth_header->ether_type == htons(ETHERTYPE_VLAN)) {
1099 1119                          eth_hsize = sizeof (struct ether_vlan_header);
1100 1120                  } else {
1101 1121                          eth_hsize = sizeof (struct ether_header);
1102 1122                  }
1103 1123                  net_header->flags = VIRTIO_NET_HDR_F_NEEDS_CSUM;
1104 1124                  net_header->csum_start = eth_hsize + csum_start;
1105 1125                  net_header->csum_offset = csum_stuff - csum_start;
1106 1126          }
1107 1127  
1108 1128          /* setup LSO fields if required */
1109 1129          if (lso_required) {
1110 1130                  net_header->gso_type = VIRTIO_NET_HDR_GSO_TCPV4;
1111 1131                  net_header->gso_size = (uint16_t)lso_mss;
1112 1132          }
1113 1133  
1114 1134          virtio_ve_add_indirect_buf(ve,
1115 1135              buf->tb_inline_mapping.vbm_dmac.dmac_laddress,
1116 1136              sizeof (struct virtio_net_hdr), B_TRUE);
1117 1137  
1118 1138          /* meanwhile update the statistic */
1119 1139          if (mp->b_rptr[0] & 0x1) {
1120 1140                  if (bcmp(mp->b_rptr, vioif_broadcast, ETHERADDRL) != 0)
1121 1141                                  sc->sc_multixmt++;
1122 1142                          else
1123 1143                                  sc->sc_brdcstxmt++;
1124 1144          }
1125 1145  
1126 1146          /*
1127 1147           * We copy small packets into the inline buffer. The bigger ones
1128 1148           * get mapped using the mapped buffer.
1129 1149           */
1130 1150          if (msg_size < sc->sc_txcopy_thresh) {
1131 1151                  vioif_tx_inline(sc, ve, mp, msg_size);
1132 1152          } else {
1133 1153                  /* statistic gets updated by vioif_tx_external when fail */
1134 1154                  ret = vioif_tx_external(sc, ve, mp, msg_size);
1135 1155                  if (ret != DDI_SUCCESS)
1136 1156                          goto exit_tx_external;
1137 1157          }
1138 1158  
1139 1159          virtio_push_chain(ve, B_TRUE);
1140 1160  
1141 1161          sc->sc_opackets++;
1142 1162          sc->sc_obytes += msg_size;
1143 1163  
1144 1164          return (B_TRUE);
1145 1165  
1146 1166  exit_tx_external:
1147 1167  
1148 1168          vq_free_entry(sc->sc_tx_vq, ve);
1149 1169          /*
1150 1170           * vioif_tx_external can fail when the buffer does not fit into the
1151 1171           * indirect descriptor table. Free the mp. I don't expect this ever
1152 1172           * to happen.
1153 1173           */
1154 1174          freemsg(mp);
1155 1175  
1156 1176          return (B_TRUE);
1157 1177  }
1158 1178  
1159 1179  mblk_t *
1160 1180  vioif_tx(void *arg, mblk_t *mp)
1161 1181  {
1162 1182          struct vioif_softc *sc = arg;
1163 1183          mblk_t  *nmp;
1164 1184  
1165 1185          while (mp != NULL) {
1166 1186                  nmp = mp->b_next;
1167 1187                  mp->b_next = NULL;
1168 1188  
1169 1189                  if (!vioif_send(sc, mp)) {
1170 1190                          sc->sc_tx_stopped = 1;
1171 1191                          mp->b_next = nmp;
1172 1192                          break;
1173 1193                  }
1174 1194                  mp = nmp;
1175 1195          }
1176 1196  
1177 1197          return (mp);
1178 1198  }
1179 1199  
1180 1200  int
1181 1201  vioif_start(void *arg)
1182 1202  {
1183 1203          struct vioif_softc *sc = arg;
1184 1204  
1185 1205          mac_link_update(sc->sc_mac_handle,
1186 1206              vioif_link_state(sc));
1187 1207  
1188 1208          virtio_start_vq_intr(sc->sc_rx_vq);
1189 1209  
1190 1210          return (DDI_SUCCESS);
1191 1211  }
1192 1212  
1193 1213  void
1194 1214  vioif_stop(void *arg)
1195 1215  {
1196 1216          struct vioif_softc *sc = arg;
1197 1217  
1198 1218          virtio_stop_vq_intr(sc->sc_rx_vq);
1199 1219  }
1200 1220  
1201 1221  /* ARGSUSED */
1202 1222  static int
1203 1223  vioif_stat(void *arg, uint_t stat, uint64_t *val)
1204 1224  {
1205 1225          struct vioif_softc *sc = arg;
1206 1226  
1207 1227          switch (stat) {
1208 1228          case MAC_STAT_IERRORS:
1209 1229                  *val = sc->sc_ierrors;
1210 1230                  break;
1211 1231          case MAC_STAT_OERRORS:
1212 1232                  *val = sc->sc_oerrors;
1213 1233                  break;
1214 1234          case MAC_STAT_MULTIRCV:
1215 1235                  *val = sc->sc_multircv;
1216 1236                  break;
1217 1237          case MAC_STAT_BRDCSTRCV:
1218 1238                  *val = sc->sc_brdcstrcv;
1219 1239                  break;
1220 1240          case MAC_STAT_MULTIXMT:
1221 1241                  *val = sc->sc_multixmt;
1222 1242                  break;
1223 1243          case MAC_STAT_BRDCSTXMT:
1224 1244                  *val = sc->sc_brdcstxmt;
1225 1245                  break;
1226 1246          case MAC_STAT_IPACKETS:
1227 1247                  *val = sc->sc_ipackets;
1228 1248                  break;
1229 1249          case MAC_STAT_RBYTES:
1230 1250                  *val = sc->sc_rbytes;
1231 1251                  break;
1232 1252          case MAC_STAT_OPACKETS:
1233 1253                  *val = sc->sc_opackets;
1234 1254                  break;
1235 1255          case MAC_STAT_OBYTES:
1236 1256                  *val = sc->sc_obytes;
1237 1257                  break;
1238 1258          case MAC_STAT_NORCVBUF:
1239 1259                  *val = sc->sc_norecvbuf;
1240 1260                  break;
1241 1261          case MAC_STAT_NOXMTBUF:
1242 1262                  *val = sc->sc_notxbuf;
1243 1263                  break;
1244 1264          case MAC_STAT_IFSPEED:
1245 1265                  /* always 1 Gbit */
1246 1266                  *val = 1000000000ULL;
1247 1267                  break;
1248 1268          case ETHER_STAT_LINK_DUPLEX:
1249 1269                  /* virtual device, always full-duplex */
1250 1270                  *val = LINK_DUPLEX_FULL;
1251 1271                  break;
1252 1272  
1253 1273          default:
1254 1274                  return (ENOTSUP);
1255 1275          }
1256 1276  
1257 1277          return (DDI_SUCCESS);
1258 1278  }
1259 1279  
1260 1280  static int
1261 1281  vioif_set_prop_private(struct vioif_softc *sc, const char *pr_name,
1262 1282      uint_t pr_valsize, const void *pr_val)
1263 1283  {
1264 1284          _NOTE(ARGUNUSED(pr_valsize));
1265 1285  
1266 1286          long result;
1267 1287  
1268 1288          if (strcmp(pr_name, vioif_txcopy_thresh) == 0) {
1269 1289  
1270 1290                  if (pr_val == NULL)
1271 1291                          return (EINVAL);
1272 1292  
1273 1293                  (void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
1274 1294  
1275 1295                  if (result < 0 || result > VIOIF_TX_THRESH_MAX)
1276 1296                          return (EINVAL);
1277 1297                  sc->sc_txcopy_thresh = result;
1278 1298          }
1279 1299          if (strcmp(pr_name, vioif_rxcopy_thresh) == 0) {
1280 1300  
1281 1301                  if (pr_val == NULL)
1282 1302                          return (EINVAL);
1283 1303  
1284 1304                  (void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
1285 1305  
1286 1306                  if (result < 0 || result > VIOIF_RX_THRESH_MAX)
1287 1307                          return (EINVAL);
1288 1308                  sc->sc_rxcopy_thresh = result;
1289 1309          }
1290 1310          return (0);
1291 1311  }
1292 1312  
1293 1313  static int
1294 1314  vioif_setprop(void *arg, const char *pr_name, mac_prop_id_t pr_num,
1295 1315      uint_t pr_valsize, const void *pr_val)
1296 1316  {
1297 1317          struct vioif_softc *sc = arg;
1298 1318          const uint32_t *new_mtu;
1299 1319          int err;
1300 1320  
1301 1321          switch (pr_num) {
1302 1322          case MAC_PROP_MTU:
1303 1323                  new_mtu = pr_val;
1304 1324  
1305 1325                  if (*new_mtu > MAX_MTU) {
1306 1326                          return (EINVAL);
1307 1327                  }
1308 1328  
1309 1329                  err = mac_maxsdu_update(sc->sc_mac_handle, *new_mtu);
1310 1330                  if (err) {
1311 1331                          return (err);
1312 1332                  }
1313 1333                  break;
1314 1334          case MAC_PROP_PRIVATE:
1315 1335                  err = vioif_set_prop_private(sc, pr_name,
1316 1336                      pr_valsize, pr_val);
1317 1337                  if (err)
1318 1338                          return (err);
1319 1339                  break;
1320 1340          default:
1321 1341                  return (ENOTSUP);
1322 1342          }
1323 1343  
1324 1344          return (0);
1325 1345  }
1326 1346  
1327 1347  static int
1328 1348  vioif_get_prop_private(struct vioif_softc *sc, const char *pr_name,
1329 1349      uint_t pr_valsize, void *pr_val)
1330 1350  {
1331 1351          int err = ENOTSUP;
1332 1352          int value;
1333 1353  
1334 1354          if (strcmp(pr_name, vioif_txcopy_thresh) == 0) {
1335 1355  
1336 1356                  value = sc->sc_txcopy_thresh;
1337 1357                  err = 0;
1338 1358                  goto done;
1339 1359          }
1340 1360          if (strcmp(pr_name, vioif_rxcopy_thresh) == 0) {
1341 1361  
1342 1362                  value = sc->sc_rxcopy_thresh;
1343 1363                  err = 0;
1344 1364                  goto done;
1345 1365          }
1346 1366  done:
1347 1367          if (err == 0) {
1348 1368                  (void) snprintf(pr_val, pr_valsize, "%d", value);
1349 1369          }
1350 1370          return (err);
1351 1371  }
1352 1372  
1353 1373  static int
1354 1374  vioif_getprop(void *arg, const char *pr_name, mac_prop_id_t pr_num,
1355 1375      uint_t pr_valsize, void *pr_val)
1356 1376  {
1357 1377          struct vioif_softc *sc = arg;
1358 1378          int err = ENOTSUP;
1359 1379  
1360 1380          switch (pr_num) {
1361 1381          case MAC_PROP_PRIVATE:
1362 1382                  err = vioif_get_prop_private(sc, pr_name,
1363 1383                      pr_valsize, pr_val);
1364 1384                  break;
1365 1385          default:
1366 1386                  break;
1367 1387          }
1368 1388          return (err);
1369 1389  }
1370 1390  
1371 1391  static void
1372 1392  vioif_propinfo(void *arg, const char *pr_name, mac_prop_id_t pr_num,
1373 1393      mac_prop_info_handle_t prh)
1374 1394  {
1375 1395          struct vioif_softc *sc = arg;
1376 1396          char valstr[64];
1377 1397          int value;
1378 1398  
1379 1399          switch (pr_num) {
1380 1400          case MAC_PROP_MTU:
1381 1401                  mac_prop_info_set_range_uint32(prh, ETHERMIN, MAX_MTU);
1382 1402                  break;
1383 1403  
1384 1404          case MAC_PROP_PRIVATE:
1385 1405                  bzero(valstr, sizeof (valstr));
1386 1406                  if (strcmp(pr_name, vioif_txcopy_thresh) == 0) {
1387 1407  
1388 1408                          value = sc->sc_txcopy_thresh;
1389 1409                  } else  if (strcmp(pr_name,
1390 1410                      vioif_rxcopy_thresh) == 0) {
1391 1411                          value = sc->sc_rxcopy_thresh;
1392 1412                  } else {
1393 1413                          return;
1394 1414                  }
1395 1415                  (void) snprintf(valstr, sizeof (valstr), "%d", value);
1396 1416                  break;
1397 1417  
1398 1418          default:
1399 1419                  break;
1400 1420          }
1401 1421  }
1402 1422  
1403 1423  static boolean_t
1404 1424  vioif_getcapab(void *arg, mac_capab_t cap, void *cap_data)
1405 1425  {
1406 1426          struct vioif_softc *sc = arg;
1407 1427  
1408 1428          switch (cap) {
1409 1429          case MAC_CAPAB_HCKSUM:
1410 1430                  if (sc->sc_tx_csum) {
1411 1431                          uint32_t *txflags = cap_data;
1412 1432  
1413 1433                          *txflags = HCKSUM_INET_PARTIAL;
1414 1434                          return (B_TRUE);
1415 1435                  }
1416 1436                  return (B_FALSE);
1417 1437          case MAC_CAPAB_LSO:
1418 1438                  if (sc->sc_tx_tso4) {
1419 1439                          mac_capab_lso_t *cap_lso = cap_data;
1420 1440  
1421 1441                          cap_lso->lso_flags = LSO_TX_BASIC_TCP_IPV4;
1422 1442                          cap_lso->lso_basic_tcp_ipv4.lso_max = MAX_MTU;
1423 1443                          return (B_TRUE);
1424 1444                  }
1425 1445                  return (B_FALSE);
1426 1446          default:
1427 1447                  break;
1428 1448          }
1429 1449          return (B_FALSE);
1430 1450  }
1431 1451  
1432 1452  static mac_callbacks_t vioif_m_callbacks = {
1433 1453          .mc_callbacks   = (MC_GETCAPAB | MC_SETPROP | MC_GETPROP | MC_PROPINFO),
1434 1454          .mc_getstat     = vioif_stat,
1435 1455          .mc_start       = vioif_start,
1436 1456          .mc_stop        = vioif_stop,
1437 1457          .mc_setpromisc  = vioif_promisc,
1438 1458          .mc_multicst    = vioif_multicst,
1439 1459          .mc_unicst      = vioif_unicst,
1440 1460          .mc_tx          = vioif_tx,
1441 1461          /* Optional callbacks */
1442 1462          .mc_reserved    = NULL,         /* reserved */
1443 1463          .mc_ioctl       = NULL,         /* mc_ioctl */
1444 1464          .mc_getcapab    = vioif_getcapab,               /* mc_getcapab */
1445 1465          .mc_open        = NULL,         /* mc_open */
1446 1466          .mc_close       = NULL,         /* mc_close */
1447 1467          .mc_setprop     = vioif_setprop,
1448 1468          .mc_getprop     = vioif_getprop,
1449 1469          .mc_propinfo    = vioif_propinfo,
1450 1470  };
1451 1471  
  
    | 
      ↓ open down ↓ | 
    361 lines elided | 
    
      ↑ open up ↑ | 
  
1452 1472  static void
1453 1473  vioif_show_features(struct vioif_softc *sc, const char *prefix,
1454 1474      uint32_t features)
1455 1475  {
1456 1476          char buf[512];
1457 1477          char *bufp = buf;
1458 1478          char *bufend = buf + sizeof (buf);
1459 1479  
1460 1480          /* LINTED E_PTRDIFF_OVERFLOW */
1461 1481          bufp += snprintf(bufp, bufend - bufp, prefix);
1462      -
1463 1482          /* LINTED E_PTRDIFF_OVERFLOW */
1464 1483          bufp += virtio_show_features(features, bufp, bufend - bufp);
1465      -
1466      -        /* LINTED E_PTRDIFF_OVERFLOW */
1467      -        bufp += snprintf(bufp, bufend - bufp, "Vioif ( ");
1468      -
1469      -        if (features & VIRTIO_NET_F_CSUM)
1470      -                /* LINTED E_PTRDIFF_OVERFLOW */
1471      -                bufp += snprintf(bufp, bufend - bufp, "CSUM ");
1472      -        if (features & VIRTIO_NET_F_GUEST_CSUM)
1473      -                /* LINTED E_PTRDIFF_OVERFLOW */
1474      -                bufp += snprintf(bufp, bufend - bufp, "GUEST_CSUM ");
1475      -        if (features & VIRTIO_NET_F_MAC)
1476      -                /* LINTED E_PTRDIFF_OVERFLOW */
1477      -                bufp += snprintf(bufp, bufend - bufp, "MAC ");
1478      -        if (features & VIRTIO_NET_F_GSO)
1479      -                /* LINTED E_PTRDIFF_OVERFLOW */
1480      -                bufp += snprintf(bufp, bufend - bufp, "GSO ");
1481      -        if (features & VIRTIO_NET_F_GUEST_TSO4)
1482      -                /* LINTED E_PTRDIFF_OVERFLOW */
1483      -                bufp += snprintf(bufp, bufend - bufp, "GUEST_TSO4 ");
1484      -        if (features & VIRTIO_NET_F_GUEST_TSO6)
1485      -                /* LINTED E_PTRDIFF_OVERFLOW */
1486      -                bufp += snprintf(bufp, bufend - bufp, "GUEST_TSO6 ");
1487      -        if (features & VIRTIO_NET_F_GUEST_ECN)
1488      -                /* LINTED E_PTRDIFF_OVERFLOW */
1489      -                bufp += snprintf(bufp, bufend - bufp, "GUEST_ECN ");
1490      -        if (features & VIRTIO_NET_F_GUEST_UFO)
1491      -                /* LINTED E_PTRDIFF_OVERFLOW */
1492      -                bufp += snprintf(bufp, bufend - bufp, "GUEST_UFO ");
1493      -        if (features & VIRTIO_NET_F_HOST_TSO4)
1494      -                /* LINTED E_PTRDIFF_OVERFLOW */
1495      -                bufp += snprintf(bufp, bufend - bufp, "HOST_TSO4 ");
1496      -        if (features & VIRTIO_NET_F_HOST_TSO6)
1497      -                /* LINTED E_PTRDIFF_OVERFLOW */
1498      -                bufp += snprintf(bufp, bufend - bufp, "HOST_TSO6 ");
1499      -        if (features & VIRTIO_NET_F_HOST_ECN)
1500      -                /* LINTED E_PTRDIFF_OVERFLOW */
1501      -                bufp += snprintf(bufp, bufend - bufp, "HOST_ECN ");
1502      -        if (features & VIRTIO_NET_F_HOST_UFO)
1503      -                /* LINTED E_PTRDIFF_OVERFLOW */
1504      -                bufp += snprintf(bufp, bufend - bufp, "HOST_UFO ");
1505      -        if (features & VIRTIO_NET_F_MRG_RXBUF)
1506      -                /* LINTED E_PTRDIFF_OVERFLOW */
1507      -                bufp += snprintf(bufp, bufend - bufp, "MRG_RXBUF ");
1508      -        if (features & VIRTIO_NET_F_STATUS)
1509      -                /* LINTED E_PTRDIFF_OVERFLOW */
1510      -                bufp += snprintf(bufp, bufend - bufp, "STATUS ");
1511      -        if (features & VIRTIO_NET_F_CTRL_VQ)
1512      -                /* LINTED E_PTRDIFF_OVERFLOW */
1513      -                bufp += snprintf(bufp, bufend - bufp, "CTRL_VQ ");
1514      -        if (features & VIRTIO_NET_F_CTRL_RX)
1515      -                /* LINTED E_PTRDIFF_OVERFLOW */
1516      -                bufp += snprintf(bufp, bufend - bufp, "CTRL_RX ");
1517      -        if (features & VIRTIO_NET_F_CTRL_VLAN)
1518      -                /* LINTED E_PTRDIFF_OVERFLOW */
1519      -                bufp += snprintf(bufp, bufend - bufp, "CTRL_VLAN ");
1520      -        if (features & VIRTIO_NET_F_CTRL_RX_EXTRA)
1521      -                /* LINTED E_PTRDIFF_OVERFLOW */
1522      -                bufp += snprintf(bufp, bufend - bufp, "CTRL_RX_EXTRA ");
1523      -
1524      -        /* LINTED E_PTRDIFF_OVERFLOW */
1525      -        bufp += snprintf(bufp, bufend - bufp, ")");
1526 1484          *bufp = '\0';
1527 1485  
1528      -        dev_err(sc->sc_dev, CE_NOTE, "%s", buf);
     1486 +
     1487 +        /* Using '!' to only CE_NOTE this to the system log. */
     1488 +        dev_err(sc->sc_dev, CE_NOTE, "!%s Vioif (%b)", buf, features,
     1489 +            VIRTIO_NET_FEATURE_BITS);
1529 1490  }
1530 1491  
1531 1492  /*
1532 1493   * Find out which features are supported by the device and
1533 1494   * choose which ones we wish to use.
1534 1495   */
1535 1496  static int
1536 1497  vioif_dev_features(struct vioif_softc *sc)
1537 1498  {
1538 1499          uint32_t host_features;
1539 1500  
1540 1501          host_features = virtio_negotiate_features(&sc->sc_virtio,
1541 1502              VIRTIO_NET_F_CSUM |
1542 1503              VIRTIO_NET_F_HOST_TSO4 |
1543 1504              VIRTIO_NET_F_HOST_ECN |
1544 1505              VIRTIO_NET_F_MAC |
1545 1506              VIRTIO_NET_F_STATUS |
1546 1507              VIRTIO_F_RING_INDIRECT_DESC |
1547 1508              VIRTIO_F_NOTIFY_ON_EMPTY);
1548 1509  
1549 1510          vioif_show_features(sc, "Host features: ", host_features);
1550 1511          vioif_show_features(sc, "Negotiated features: ",
1551 1512              sc->sc_virtio.sc_features);
1552 1513  
1553 1514          if (!(sc->sc_virtio.sc_features & VIRTIO_F_RING_INDIRECT_DESC)) {
1554 1515                  dev_err(sc->sc_dev, CE_NOTE,
1555 1516                      "Host does not support RING_INDIRECT_DESC, bye.");
1556 1517                  return (DDI_FAILURE);
1557 1518          }
1558 1519  
1559 1520          return (DDI_SUCCESS);
1560 1521  }
1561 1522  
1562 1523  static int
1563 1524  vioif_has_feature(struct vioif_softc *sc, uint32_t feature)
1564 1525  {
1565 1526          return (virtio_has_feature(&sc->sc_virtio, feature));
1566 1527  }
1567 1528  
1568 1529  static void
1569 1530  vioif_set_mac(struct vioif_softc *sc)
1570 1531  {
1571 1532          int i;
1572 1533  
1573 1534          for (i = 0; i < ETHERADDRL; i++) {
1574 1535                  virtio_write_device_config_1(&sc->sc_virtio,
1575 1536                      VIRTIO_NET_CONFIG_MAC + i, sc->sc_mac[i]);
1576 1537          }
1577 1538  }
1578 1539  
1579 1540  /* Get the mac address out of the hardware, or make up one. */
1580 1541  static void
1581 1542  vioif_get_mac(struct vioif_softc *sc)
1582 1543  {
1583 1544          int i;
1584 1545          if (sc->sc_virtio.sc_features & VIRTIO_NET_F_MAC) {
1585 1546                  for (i = 0; i < ETHERADDRL; i++) {
1586 1547                          sc->sc_mac[i] = virtio_read_device_config_1(
1587 1548                              &sc->sc_virtio,
1588 1549                              VIRTIO_NET_CONFIG_MAC + i);
1589 1550                  }
1590 1551                  dev_err(sc->sc_dev, CE_NOTE, "Got MAC address from host: %s",
1591 1552                      ether_sprintf((struct ether_addr *)sc->sc_mac));
1592 1553          } else {
1593 1554                  /* Get a few random bytes */
1594 1555                  (void) random_get_pseudo_bytes(sc->sc_mac, ETHERADDRL);
1595 1556                  /* Make sure it's a unicast MAC */
1596 1557                  sc->sc_mac[0] &= ~1;
1597 1558                  /* Set the "locally administered" bit */
1598 1559                  sc->sc_mac[1] |= 2;
1599 1560  
1600 1561                  vioif_set_mac(sc);
1601 1562  
1602 1563                  dev_err(sc->sc_dev, CE_NOTE,
1603 1564                      "Generated a random MAC address: %s",
1604 1565                      ether_sprintf((struct ether_addr *)sc->sc_mac));
1605 1566          }
1606 1567  }
1607 1568  
1608 1569  /*
1609 1570   * Virtqueue interrupt handlers
1610 1571   */
1611 1572  /* ARGSUSED */
1612 1573  uint_t
1613 1574  vioif_rx_handler(caddr_t arg1, caddr_t arg2)
1614 1575  {
1615 1576          struct virtio_softc *vsc = (void *) arg1;
1616 1577          struct vioif_softc *sc = container_of(vsc,
1617 1578              struct vioif_softc, sc_virtio);
1618 1579  
1619 1580          (void) vioif_process_rx(sc);
1620 1581  
1621 1582          (void) vioif_populate_rx(sc, KM_NOSLEEP);
1622 1583  
1623 1584          return (DDI_INTR_CLAIMED);
1624 1585  }
1625 1586  
1626 1587  /* ARGSUSED */
1627 1588  uint_t
1628 1589  vioif_tx_handler(caddr_t arg1, caddr_t arg2)
1629 1590  {
1630 1591          struct virtio_softc *vsc = (void *)arg1;
1631 1592          struct vioif_softc *sc = container_of(vsc,
1632 1593              struct vioif_softc, sc_virtio);
1633 1594  
1634 1595          vioif_reclaim_used_tx(sc);
1635 1596          return (DDI_INTR_CLAIMED);
1636 1597  }
1637 1598  
1638 1599  static int
1639 1600  vioif_register_ints(struct vioif_softc *sc)
1640 1601  {
1641 1602          int ret;
1642 1603  
1643 1604          struct virtio_int_handler vioif_vq_h[] = {
1644 1605                  { vioif_rx_handler },
1645 1606                  { vioif_tx_handler },
1646 1607                  { NULL }
1647 1608          };
1648 1609  
1649 1610          ret = virtio_register_ints(&sc->sc_virtio, NULL, vioif_vq_h);
1650 1611  
1651 1612          return (ret);
1652 1613  }
1653 1614  
1654 1615  
1655 1616  static void
1656 1617  vioif_check_features(struct vioif_softc *sc)
1657 1618  {
1658 1619          if (vioif_has_feature(sc, VIRTIO_NET_F_CSUM)) {
1659 1620                  /* The GSO/GRO featured depend on CSUM, check them here. */
1660 1621                  sc->sc_tx_csum = 1;
1661 1622                  sc->sc_rx_csum = 1;
1662 1623  
1663 1624                  if (!vioif_has_feature(sc, VIRTIO_NET_F_GUEST_CSUM)) {
1664 1625                          sc->sc_rx_csum = 0;
1665 1626                  }
1666 1627                  cmn_err(CE_NOTE, "Csum enabled.");
1667 1628  
1668 1629                  if (vioif_has_feature(sc, VIRTIO_NET_F_HOST_TSO4)) {
1669 1630  
1670 1631                          sc->sc_tx_tso4 = 1;
1671 1632                          /*
1672 1633                           * We don't seem to have a way to ask the system
1673 1634                           * not to send us LSO packets with Explicit
1674 1635                           * Congestion Notification bit set, so we require
1675 1636                           * the device to support it in order to do
1676 1637                           * LSO.
1677 1638                           */
1678 1639                          if (!vioif_has_feature(sc, VIRTIO_NET_F_HOST_ECN)) {
1679 1640                                  dev_err(sc->sc_dev, CE_NOTE,
1680 1641                                      "TSO4 supported, but not ECN. "
1681 1642                                      "Not using LSO.");
1682 1643                                  sc->sc_tx_tso4 = 0;
1683 1644                          } else {
1684 1645                                  cmn_err(CE_NOTE, "LSO enabled");
1685 1646                          }
1686 1647                  }
1687 1648          }
1688 1649  }
1689 1650  
1690 1651  static int
1691 1652  vioif_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd)
1692 1653  {
1693 1654          int ret, instance;
1694 1655          struct vioif_softc *sc;
1695 1656          struct virtio_softc *vsc;
1696 1657          mac_register_t *macp;
  
    | 
      ↓ open down ↓ | 
    158 lines elided | 
    
      ↑ open up ↑ | 
  
1697 1658          char cache_name[CACHE_NAME_SIZE];
1698 1659  
1699 1660          instance = ddi_get_instance(devinfo);
1700 1661  
1701 1662          switch (cmd) {
1702 1663          case DDI_ATTACH:
1703 1664                  break;
1704 1665  
1705 1666          case DDI_RESUME:
1706 1667          case DDI_PM_RESUME:
1707      -                /* not supported yet */
     1668 +                /* We do not support suspend/resume for vioif. */
1708 1669                  goto exit;
1709 1670  
1710 1671          default:
1711      -                /* unrecognized command */
1712 1672                  goto exit;
1713 1673          }
1714 1674  
1715 1675          sc = kmem_zalloc(sizeof (struct vioif_softc), KM_SLEEP);
1716 1676          ddi_set_driver_private(devinfo, sc);
1717 1677  
1718 1678          vsc = &sc->sc_virtio;
1719 1679  
1720 1680          /* Duplicate for less typing */
1721 1681          sc->sc_dev = devinfo;
1722 1682          vsc->sc_dev = devinfo;
1723 1683  
1724 1684          /*
1725 1685           * Initialize interrupt kstat.
1726 1686           */
1727 1687          sc->sc_intrstat = kstat_create("vioif", instance, "intr", "controller",
1728 1688              KSTAT_TYPE_INTR, 1, 0);
1729 1689          if (sc->sc_intrstat == NULL) {
1730 1690                  dev_err(devinfo, CE_WARN, "kstat_create failed");
1731 1691                  goto exit_intrstat;
1732 1692          }
1733 1693          kstat_install(sc->sc_intrstat);
1734 1694  
1735 1695          /* map BAR 0 */
1736 1696          ret = ddi_regs_map_setup(devinfo, 1,
1737 1697              (caddr_t *)&sc->sc_virtio.sc_io_addr,
1738 1698              0, 0, &vioif_attr, &sc->sc_virtio.sc_ioh);
1739 1699          if (ret != DDI_SUCCESS) {
1740 1700                  dev_err(devinfo, CE_WARN, "unable to map bar 0: %d", ret);
1741 1701                  goto exit_map;
1742 1702          }
1743 1703  
1744 1704          virtio_device_reset(&sc->sc_virtio);
1745 1705          virtio_set_status(&sc->sc_virtio, VIRTIO_CONFIG_DEVICE_STATUS_ACK);
1746 1706          virtio_set_status(&sc->sc_virtio, VIRTIO_CONFIG_DEVICE_STATUS_DRIVER);
1747 1707  
1748 1708          ret = vioif_dev_features(sc);
1749 1709          if (ret)
1750 1710                  goto exit_features;
1751 1711  
1752 1712          vsc->sc_nvqs = vioif_has_feature(sc, VIRTIO_NET_F_CTRL_VQ) ? 3 : 2;
1753 1713  
1754 1714          (void) snprintf(cache_name, CACHE_NAME_SIZE, "vioif%d_rx", instance);
1755 1715          sc->sc_rxbuf_cache = kmem_cache_create(cache_name,
1756 1716              sizeof (struct vioif_rx_buf), 0, vioif_rx_construct,
1757 1717              vioif_rx_destruct, NULL, sc, NULL, KM_SLEEP);
1758 1718          if (sc->sc_rxbuf_cache == NULL) {
1759 1719                  dev_err(sc->sc_dev, CE_WARN, "Can't allocate the buffer cache");
1760 1720                  goto exit_cache;
1761 1721          }
1762 1722  
1763 1723          ret = vioif_register_ints(sc);
1764 1724          if (ret) {
1765 1725                  dev_err(sc->sc_dev, CE_WARN,
1766 1726                      "Failed to allocate interrupt(s)!");
1767 1727                  goto exit_ints;
1768 1728          }
1769 1729  
1770 1730          /*
1771 1731           * Register layout determined, can now access the
1772 1732           * device-specific bits
1773 1733           */
1774 1734          vioif_get_mac(sc);
1775 1735  
1776 1736          sc->sc_rx_vq = virtio_alloc_vq(&sc->sc_virtio, 0,
1777 1737              VIOIF_RX_QLEN, VIOIF_INDIRECT_MAX, "rx");
1778 1738          if (!sc->sc_rx_vq)
1779 1739                  goto exit_alloc1;
1780 1740          virtio_stop_vq_intr(sc->sc_rx_vq);
1781 1741  
1782 1742          sc->sc_tx_vq = virtio_alloc_vq(&sc->sc_virtio, 1,
1783 1743              VIOIF_TX_QLEN, VIOIF_INDIRECT_MAX, "tx");
1784 1744          if (!sc->sc_rx_vq)
1785 1745                  goto exit_alloc2;
1786 1746          virtio_stop_vq_intr(sc->sc_tx_vq);
1787 1747  
1788 1748          if (vioif_has_feature(sc, VIRTIO_NET_F_CTRL_VQ)) {
1789 1749                  sc->sc_ctrl_vq = virtio_alloc_vq(&sc->sc_virtio, 2,
1790 1750                      VIOIF_CTRL_QLEN, 0, "ctrl");
1791 1751                  if (!sc->sc_ctrl_vq) {
1792 1752                          goto exit_alloc3;
1793 1753                  }
1794 1754                  virtio_stop_vq_intr(sc->sc_ctrl_vq);
1795 1755          }
1796 1756  
1797 1757          virtio_set_status(&sc->sc_virtio,
1798 1758              VIRTIO_CONFIG_DEVICE_STATUS_DRIVER_OK);
1799 1759  
1800 1760          sc->sc_rxloan = 0;
1801 1761  
1802 1762          /* set some reasonable-small default values */
1803 1763          sc->sc_rxcopy_thresh = 300;
1804 1764          sc->sc_txcopy_thresh = 300;
1805 1765          sc->sc_mtu = ETHERMTU;
1806 1766  
1807 1767          vioif_check_features(sc);
1808 1768  
1809 1769          if (vioif_alloc_mems(sc))
1810 1770                  goto exit_alloc_mems;
1811 1771  
1812 1772          if ((macp = mac_alloc(MAC_VERSION)) == NULL) {
1813 1773                  dev_err(devinfo, CE_WARN, "Failed to allocate a mac_register");
1814 1774                  goto exit_macalloc;
1815 1775          }
1816 1776  
1817 1777          macp->m_type_ident = MAC_PLUGIN_IDENT_ETHER;
1818 1778          macp->m_driver = sc;
1819 1779          macp->m_dip = devinfo;
1820 1780          macp->m_src_addr = sc->sc_mac;
1821 1781          macp->m_callbacks = &vioif_m_callbacks;
1822 1782          macp->m_min_sdu = 0;
1823 1783          macp->m_max_sdu = sc->sc_mtu;
1824 1784          macp->m_margin = VLAN_TAGSZ;
1825 1785          macp->m_priv_props = vioif_priv_props;
1826 1786  
1827 1787          sc->sc_macp = macp;
1828 1788  
1829 1789          /* Pre-fill the rx ring. */
1830 1790          (void) vioif_populate_rx(sc, KM_SLEEP);
1831 1791  
1832 1792          ret = mac_register(macp, &sc->sc_mac_handle);
1833 1793          if (ret != 0) {
1834 1794                  dev_err(devinfo, CE_WARN, "vioif_attach: "
1835 1795                      "mac_register() failed, ret=%d", ret);
1836 1796                  goto exit_register;
1837 1797          }
1838 1798  
1839 1799          ret = virtio_enable_ints(&sc->sc_virtio);
1840 1800          if (ret) {
1841 1801                  dev_err(devinfo, CE_WARN, "Failed to enable interrupts");
1842 1802                  goto exit_enable_ints;
1843 1803          }
1844 1804  
1845 1805          mac_link_update(sc->sc_mac_handle, LINK_STATE_UP);
1846 1806          return (DDI_SUCCESS);
1847 1807  
1848 1808  exit_enable_ints:
1849 1809          (void) mac_unregister(sc->sc_mac_handle);
1850 1810  exit_register:
1851 1811          mac_free(macp);
1852 1812  exit_macalloc:
1853 1813          vioif_free_mems(sc);
1854 1814  exit_alloc_mems:
1855 1815          virtio_release_ints(&sc->sc_virtio);
1856 1816          if (sc->sc_ctrl_vq)
1857 1817                  virtio_free_vq(sc->sc_ctrl_vq);
1858 1818  exit_alloc3:
1859 1819          virtio_free_vq(sc->sc_tx_vq);
1860 1820  exit_alloc2:
1861 1821          virtio_free_vq(sc->sc_rx_vq);
1862 1822  exit_alloc1:
1863 1823  exit_ints:
1864 1824          kmem_cache_destroy(sc->sc_rxbuf_cache);
1865 1825  exit_cache:
1866 1826  exit_features:
1867 1827          virtio_set_status(&sc->sc_virtio, VIRTIO_CONFIG_DEVICE_STATUS_FAILED);
1868 1828          ddi_regs_map_free(&sc->sc_virtio.sc_ioh);
1869 1829  exit_intrstat:
1870 1830  exit_map:
1871 1831          kstat_delete(sc->sc_intrstat);
1872 1832          kmem_free(sc, sizeof (struct vioif_softc));
1873 1833  exit:
1874 1834          return (DDI_FAILURE);
1875 1835  }
1876 1836  
1877 1837  static int
1878 1838  vioif_detach(dev_info_t *devinfo, ddi_detach_cmd_t cmd)
1879 1839  {
  
    | 
      ↓ open down ↓ | 
    158 lines elided | 
    
      ↑ open up ↑ | 
  
1880 1840          struct vioif_softc *sc;
1881 1841  
1882 1842          if ((sc = ddi_get_driver_private(devinfo)) == NULL)
1883 1843                  return (DDI_FAILURE);
1884 1844  
1885 1845          switch (cmd) {
1886 1846          case DDI_DETACH:
1887 1847                  break;
1888 1848  
1889 1849          case DDI_PM_SUSPEND:
1890      -                /* not supported yet */
     1850 +                /* We do not support suspend/resume for vioif. */
1891 1851                  return (DDI_FAILURE);
1892 1852  
1893 1853          default:
1894      -                /* unrecognized command */
1895 1854                  return (DDI_FAILURE);
1896 1855          }
1897 1856  
1898 1857          if (sc->sc_rxloan) {
1899      -                cmn_err(CE_NOTE, "Some rx buffers are still upstream, "
1900      -                    "Not detaching");
     1858 +                dev_err(devinfo, CE_WARN, "!Some rx buffers are still upstream,"
     1859 +                    " not detaching.");
1901 1860                  return (DDI_FAILURE);
1902 1861          }
1903 1862  
1904 1863          virtio_stop_vq_intr(sc->sc_rx_vq);
1905 1864          virtio_stop_vq_intr(sc->sc_tx_vq);
1906 1865  
1907 1866          virtio_release_ints(&sc->sc_virtio);
1908 1867  
1909 1868          if (mac_unregister(sc->sc_mac_handle)) {
1910 1869                  return (DDI_FAILURE);
1911 1870          }
1912 1871  
1913 1872          mac_free(sc->sc_macp);
1914 1873  
1915 1874          vioif_free_mems(sc);
1916 1875          virtio_free_vq(sc->sc_rx_vq);
1917 1876          virtio_free_vq(sc->sc_tx_vq);
1918 1877  
1919 1878          virtio_device_reset(&sc->sc_virtio);
1920 1879  
1921 1880          ddi_regs_map_free(&sc->sc_virtio.sc_ioh);
1922 1881  
1923 1882          kmem_cache_destroy(sc->sc_rxbuf_cache);
1924 1883          kstat_delete(sc->sc_intrstat);
1925 1884          kmem_free(sc, sizeof (struct vioif_softc));
1926 1885  
1927 1886          return (DDI_SUCCESS);
1928 1887  }
1929 1888  
1930 1889  static int
1931 1890  vioif_quiesce(dev_info_t *devinfo)
1932 1891  {
1933 1892          struct vioif_softc *sc;
1934 1893  
1935 1894          if ((sc = ddi_get_driver_private(devinfo)) == NULL)
1936 1895                  return (DDI_FAILURE);
1937 1896  
1938 1897          virtio_stop_vq_intr(sc->sc_rx_vq);
1939 1898          virtio_stop_vq_intr(sc->sc_tx_vq);
1940 1899          virtio_device_reset(&sc->sc_virtio);
1941 1900  
1942 1901          return (DDI_SUCCESS);
1943 1902  }
1944 1903  
1945 1904  int
1946 1905  _init(void)
1947 1906  {
1948 1907          int ret = 0;
1949 1908  
1950 1909          mac_init_ops(&vioif_ops, "vioif");
1951 1910  
1952 1911          ret = mod_install(&modlinkage);
1953 1912          if (ret != DDI_SUCCESS) {
1954 1913                  mac_fini_ops(&vioif_ops);
1955 1914                  return (ret);
1956 1915          }
1957 1916  
1958 1917          return (0);
1959 1918  }
1960 1919  
1961 1920  int
1962 1921  _fini(void)
1963 1922  {
1964 1923          int ret;
1965 1924  
1966 1925          ret = mod_remove(&modlinkage);
1967 1926          if (ret == DDI_SUCCESS) {
1968 1927                  mac_fini_ops(&vioif_ops);
1969 1928          }
1970 1929  
1971 1930          return (ret);
1972 1931  }
1973 1932  
1974 1933  int
1975 1934  _info(struct modinfo *pModinfo)
1976 1935  {
1977 1936          return (mod_info(&modlinkage, pModinfo));
1978 1937  }
  
    | 
      ↓ open down ↓ | 
    68 lines elided | 
    
      ↑ open up ↑ | 
  
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX