Print this page


   1 /*
   2  * This file and its contents are supplied under the terms of the
   3  * Common Development and Distribution License ("CDDL"), version 1.0.
   4  * You may only use this file in accordance with the terms of version
   5  * 1.0 of the CDDL.
   6  *
   7  * A full copy of the text of the CDDL should have accompanied this
   8  * source.  A copy of the CDDL is also available via the Internet at
   9  * http://www.illumos.org/license/CDDL.
  10  */
  11 
  12 /*
  13  * Copyright 2013 Nexenta Inc.  All rights reserved.
  14  * Copyright (c) 2014, 2015 by Delphix. All rights reserved.
  15  */
  16 
  17 /* Based on the NetBSD virtio driver by Minoura Makoto. */
  18 /*
  19  * Copyright (c) 2010 Minoura Makoto.
  20  * All rights reserved.
  21  *
  22  * Redistribution and use in source and binary forms, with or without
  23  * modification, are permitted provided that the following conditions
  24  * are met:
  25  * 1. Redistributions of source code must retain the above copyright
  26  *    notice, this list of conditions and the following disclaimer.
  27  * 2. Redistributions in binary form must reproduce the above copyright
  28  *    notice, this list of conditions and the following disclaimer in the
  29  *    documentation and/or other materials provided with the distribution.
  30  *
  31  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  32  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  33  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.


 367 vioif_dma_curr_cookie(ddi_dma_handle_t dmah)
 368 {
 369         ddi_dma_impl_t *dmah_impl = (void *) dmah;
 370         ASSERT(dmah_impl->dmai_cookie);
 371         return (dmah_impl->dmai_cookie);
 372 }
 373 
 374 static void
 375 vioif_dma_reset_cookie(ddi_dma_handle_t dmah, ddi_dma_cookie_t *dmac)
 376 {
 377         ddi_dma_impl_t *dmah_impl = (void *) dmah;
 378         dmah_impl->dmai_cookie = dmac;
 379 }
 380 
 381 static link_state_t
 382 vioif_link_state(struct vioif_softc *sc)
 383 {
 384         if (sc->sc_virtio.sc_features & VIRTIO_NET_F_STATUS) {
 385                 if (virtio_read_device_config_2(&sc->sc_virtio,
 386                     VIRTIO_NET_CONFIG_STATUS) & VIRTIO_NET_S_LINK_UP) {

 387                         return (LINK_STATE_UP);
 388                 } else {
 389                         return (LINK_STATE_DOWN);
 390                 }
 391         }
 392 
 393         return (LINK_STATE_UP);
 394 }
 395 
 396 static ddi_dma_attr_t vioif_inline_buf_dma_attr = {
 397         DMA_ATTR_V0,            /* Version number */
 398         0,                      /* low address */
 399         0xFFFFFFFFFFFFFFFF,     /* high address */
 400         0xFFFFFFFF,             /* counter register max */
 401         1,                      /* page alignment */
 402         1,                      /* burst sizes: 1 - 32 */
 403         1,                      /* minimum transfer size */
 404         0xFFFFFFFF,             /* max transfer size */
 405         0xFFFFFFFFFFFFFFF,      /* address register max */
 406         1,                      /* scatter-gather capacity */


 678 {
 679         return (DDI_SUCCESS);
 680 }
 681 
 682 /* ARGSUSED */
 683 int
 684 vioif_unicst(void *arg, const uint8_t *macaddr)
 685 {
 686         return (DDI_FAILURE);
 687 }
 688 
 689 
 690 static int
 691 vioif_add_rx(struct vioif_softc *sc, int kmflag)
 692 {
 693         struct vq_entry *ve;
 694         struct vioif_rx_buf *buf;
 695 
 696         ve = vq_alloc_entry(sc->sc_rx_vq);
 697         if (!ve) {
 698                 /*
 699                  * Out of free descriptors - ring already full.
 700                  * It would be better to update sc_norxdescavail
 701                  * but MAC does not ask for this info, hence we
 702                  * update sc_norecvbuf.
 703                  */
 704                 sc->sc_norecvbuf++;
 705                 goto exit_vq;
 706         }
 707         buf = sc->sc_rxbufs[ve->qe_index];
 708 
 709         if (!buf) {
 710                 /* First run, allocate the buffer. */
 711                 buf = kmem_cache_alloc(sc->sc_rxbuf_cache, kmflag);
 712                 sc->sc_rxbufs[ve->qe_index] = buf;
 713         }
 714 
 715         /* Still nothing? Bye. */
 716         if (!buf) {
 717                 dev_err(sc->sc_dev, CE_WARN, "Can't allocate rx buffer");
 718                 sc->sc_norecvbuf++;
 719                 goto exit_buf;
 720         }
 721 
 722         ASSERT(buf->rb_mapping.vbm_ncookies >= 1);


 827                         bcopy((char *)buf->rb_mapping.vbm_buf +
 828                             sizeof (struct virtio_net_hdr), mp->b_rptr, len);
 829                         mp->b_wptr = mp->b_rptr + len;
 830 
 831                 } else {
 832                         mp = desballoc((unsigned char *)
 833                             buf->rb_mapping.vbm_buf +
 834                             sizeof (struct virtio_net_hdr) +
 835                             VIOIF_IP_ALIGN, len, 0, &buf->rb_frtn);
 836                         if (!mp) {
 837                                 sc->sc_norecvbuf++;
 838                                 sc->sc_ierrors++;
 839 
 840                                 virtio_free_chain(ve);
 841                                 break;
 842                         }
 843                         mp->b_wptr = mp->b_rptr + len;
 844 
 845                         atomic_inc_ulong(&sc->sc_rxloan);
 846                         /*
 847                          * Buffer loaned, we will have to allocte a new one
 848                          * for this slot.
 849                          */
 850                         sc->sc_rxbufs[ve->qe_index] = NULL;
 851                 }
 852 
 853                 /*
 854                  * virtio-net does not tell us if this packet is multicast
 855                  * or broadcast, so we have to check it.
 856                  */
 857                 if (mp->b_rptr[0] & 0x1) {
 858                         if (bcmp(mp->b_rptr, vioif_broadcast, ETHERADDRL) != 0)
 859                                 sc->sc_multircv++;
 860                         else
 861                                 sc->sc_brdcstrcv++;
 862                 }
 863 
 864                 sc->sc_rbytes += len;
 865                 sc->sc_ipackets++;
 866 
 867                 virtio_free_chain(ve);
 868                 mac_rx(sc->sc_mac_handle, NULL, mp);
 869                 i++;
 870         }
 871 
 872         return (i);
 873 }
 874 
 875 static void


1299         int err;
1300 
1301         switch (pr_num) {
1302         case MAC_PROP_MTU:
1303                 new_mtu = pr_val;
1304 
1305                 if (*new_mtu > MAX_MTU) {
1306                         return (EINVAL);
1307                 }
1308 
1309                 err = mac_maxsdu_update(sc->sc_mac_handle, *new_mtu);
1310                 if (err) {
1311                         return (err);
1312                 }
1313                 break;
1314         case MAC_PROP_PRIVATE:
1315                 err = vioif_set_prop_private(sc, pr_name,
1316                     pr_valsize, pr_val);
1317                 if (err)
1318                         return (err);
1319                 break;
1320         default:
1321                 return (ENOTSUP);
1322         }
1323 
1324         return (0);
1325 }
1326 
1327 static int
1328 vioif_get_prop_private(struct vioif_softc *sc, const char *pr_name,
1329     uint_t pr_valsize, void *pr_val)
1330 {
1331         int err = ENOTSUP;
1332         int value;
1333 
1334         if (strcmp(pr_name, vioif_txcopy_thresh) == 0) {
1335 
1336                 value = sc->sc_txcopy_thresh;
1337                 err = 0;
1338                 goto done;
1339         }


1356 {
1357         struct vioif_softc *sc = arg;
1358         int err = ENOTSUP;
1359 
1360         switch (pr_num) {
1361         case MAC_PROP_PRIVATE:
1362                 err = vioif_get_prop_private(sc, pr_name,
1363                     pr_valsize, pr_val);
1364                 break;
1365         default:
1366                 break;
1367         }
1368         return (err);
1369 }
1370 
1371 static void
1372 vioif_propinfo(void *arg, const char *pr_name, mac_prop_id_t pr_num,
1373     mac_prop_info_handle_t prh)
1374 {
1375         struct vioif_softc *sc = arg;
1376         char valstr[64];
1377         int value;
1378 
1379         switch (pr_num) {
1380         case MAC_PROP_MTU:
1381                 mac_prop_info_set_range_uint32(prh, ETHERMIN, MAX_MTU);
1382                 break;
1383 
1384         case MAC_PROP_PRIVATE:



1385                 bzero(valstr, sizeof (valstr));
1386                 if (strcmp(pr_name, vioif_txcopy_thresh) == 0) {
1387 
1388                         value = sc->sc_txcopy_thresh;
1389                 } else  if (strcmp(pr_name,
1390                     vioif_rxcopy_thresh) == 0) {
1391                         value = sc->sc_rxcopy_thresh;
1392                 } else {
1393                         return;
1394                 }
1395                 (void) snprintf(valstr, sizeof (valstr), "%d", value);
1396                 break;
1397 
1398         default:
1399                 break;
1400         }
1401 }
1402 
1403 static boolean_t
1404 vioif_getcapab(void *arg, mac_capab_t cap, void *cap_data)
1405 {
1406         struct vioif_softc *sc = arg;
1407 
1408         switch (cap) {
1409         case MAC_CAPAB_HCKSUM:
1410                 if (sc->sc_tx_csum) {
1411                         uint32_t *txflags = cap_data;
1412 
1413                         *txflags = HCKSUM_INET_PARTIAL;
1414                         return (B_TRUE);
1415                 }
1416                 return (B_FALSE);
1417         case MAC_CAPAB_LSO:


1437         .mc_setpromisc  = vioif_promisc,
1438         .mc_multicst    = vioif_multicst,
1439         .mc_unicst      = vioif_unicst,
1440         .mc_tx          = vioif_tx,
1441         /* Optional callbacks */
1442         .mc_reserved    = NULL,         /* reserved */
1443         .mc_ioctl       = NULL,         /* mc_ioctl */
1444         .mc_getcapab    = vioif_getcapab,               /* mc_getcapab */
1445         .mc_open        = NULL,         /* mc_open */
1446         .mc_close       = NULL,         /* mc_close */
1447         .mc_setprop     = vioif_setprop,
1448         .mc_getprop     = vioif_getprop,
1449         .mc_propinfo    = vioif_propinfo,
1450 };
1451 
1452 static void
1453 vioif_show_features(struct vioif_softc *sc, const char *prefix,
1454     uint32_t features)
1455 {
1456         char buf[512];
1457         char *bufp = buf;
1458         char *bufend = buf + sizeof (buf);
1459 
1460         /* LINTED E_PTRDIFF_OVERFLOW */
1461         bufp += snprintf(bufp, bufend - bufp, prefix);
1462 
1463         /* LINTED E_PTRDIFF_OVERFLOW */
1464         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         *bufp = '\0';
1527 
1528         dev_err(sc->sc_dev, CE_NOTE, "%s", buf);
1529 }
1530 
1531 /*
1532  * Find out which features are supported by the device and
1533  * choose which ones we wish to use.
1534  */
1535 static int
1536 vioif_dev_features(struct vioif_softc *sc)
1537 {
1538         uint32_t host_features;
1539 
1540         host_features = virtio_negotiate_features(&sc->sc_virtio,
1541             VIRTIO_NET_F_CSUM |
1542             VIRTIO_NET_F_HOST_TSO4 |
1543             VIRTIO_NET_F_HOST_ECN |
1544             VIRTIO_NET_F_MAC |
1545             VIRTIO_NET_F_STATUS |
1546             VIRTIO_F_RING_INDIRECT_DESC |
1547             VIRTIO_F_NOTIFY_ON_EMPTY);
1548 
1549         vioif_show_features(sc, "Host features: ", host_features);
1550         vioif_show_features(sc, "Negotiated features: ",
1551             sc->sc_virtio.sc_features);
1552 
1553         if (!(sc->sc_virtio.sc_features & VIRTIO_F_RING_INDIRECT_DESC)) {
1554                 dev_err(sc->sc_dev, CE_NOTE,
1555                     "Host does not support RING_INDIRECT_DESC, bye.");
1556                 return (DDI_FAILURE);
1557         }
1558 
1559         return (DDI_SUCCESS);
1560 }
1561 
1562 static int
1563 vioif_has_feature(struct vioif_softc *sc, uint32_t feature)
1564 {
1565         return (virtio_has_feature(&sc->sc_virtio, feature));
1566 }
1567 
1568 static void
1569 vioif_set_mac(struct vioif_softc *sc)
1570 {


1687         }
1688 }
1689 
1690 static int
1691 vioif_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd)
1692 {
1693         int ret, instance;
1694         struct vioif_softc *sc;
1695         struct virtio_softc *vsc;
1696         mac_register_t *macp;
1697         char cache_name[CACHE_NAME_SIZE];
1698 
1699         instance = ddi_get_instance(devinfo);
1700 
1701         switch (cmd) {
1702         case DDI_ATTACH:
1703                 break;
1704 
1705         case DDI_RESUME:
1706         case DDI_PM_RESUME:
1707                 /* not supported yet */
1708                 goto exit;
1709 
1710         default:
1711                 /* unrecognized command */
1712                 goto exit;
1713         }
1714 
1715         sc = kmem_zalloc(sizeof (struct vioif_softc), KM_SLEEP);
1716         ddi_set_driver_private(devinfo, sc);
1717 
1718         vsc = &sc->sc_virtio;
1719 
1720         /* Duplicate for less typing */
1721         sc->sc_dev = devinfo;
1722         vsc->sc_dev = devinfo;
1723 
1724         /*
1725          * Initialize interrupt kstat.
1726          */
1727         sc->sc_intrstat = kstat_create("vioif", instance, "intr", "controller",
1728             KSTAT_TYPE_INTR, 1, 0);
1729         if (sc->sc_intrstat == NULL) {
1730                 dev_err(devinfo, CE_WARN, "kstat_create failed");
1731                 goto exit_intrstat;


1870 exit_map:
1871         kstat_delete(sc->sc_intrstat);
1872         kmem_free(sc, sizeof (struct vioif_softc));
1873 exit:
1874         return (DDI_FAILURE);
1875 }
1876 
1877 static int
1878 vioif_detach(dev_info_t *devinfo, ddi_detach_cmd_t cmd)
1879 {
1880         struct vioif_softc *sc;
1881 
1882         if ((sc = ddi_get_driver_private(devinfo)) == NULL)
1883                 return (DDI_FAILURE);
1884 
1885         switch (cmd) {
1886         case DDI_DETACH:
1887                 break;
1888 
1889         case DDI_PM_SUSPEND:
1890                 /* not supported yet */
1891                 return (DDI_FAILURE);
1892 
1893         default:
1894                 /* unrecognized command */
1895                 return (DDI_FAILURE);
1896         }
1897 
1898         if (sc->sc_rxloan) {
1899                 cmn_err(CE_NOTE, "Some rx buffers are still upstream, "
1900                     "Not detaching");
1901                 return (DDI_FAILURE);
1902         }
1903 
1904         virtio_stop_vq_intr(sc->sc_rx_vq);
1905         virtio_stop_vq_intr(sc->sc_tx_vq);
1906 
1907         virtio_release_ints(&sc->sc_virtio);
1908 
1909         if (mac_unregister(sc->sc_mac_handle)) {
1910                 return (DDI_FAILURE);
1911         }
1912 
1913         mac_free(sc->sc_macp);
1914 
1915         vioif_free_mems(sc);
1916         virtio_free_vq(sc->sc_rx_vq);
1917         virtio_free_vq(sc->sc_tx_vq);
1918 
1919         virtio_device_reset(&sc->sc_virtio);


1935         if ((sc = ddi_get_driver_private(devinfo)) == NULL)
1936                 return (DDI_FAILURE);
1937 
1938         virtio_stop_vq_intr(sc->sc_rx_vq);
1939         virtio_stop_vq_intr(sc->sc_tx_vq);
1940         virtio_device_reset(&sc->sc_virtio);
1941 
1942         return (DDI_SUCCESS);
1943 }
1944 
1945 int
1946 _init(void)
1947 {
1948         int ret = 0;
1949 
1950         mac_init_ops(&vioif_ops, "vioif");
1951 
1952         ret = mod_install(&modlinkage);
1953         if (ret != DDI_SUCCESS) {
1954                 mac_fini_ops(&vioif_ops);

1955                 return (ret);
1956         }
1957 
1958         return (0);
1959 }
1960 
1961 int
1962 _fini(void)
1963 {
1964         int ret;
1965 
1966         ret = mod_remove(&modlinkage);
1967         if (ret == DDI_SUCCESS) {
1968                 mac_fini_ops(&vioif_ops);
1969         }
1970 
1971         return (ret);
1972 }
1973 
1974 int
   1 /*
   2  * This file and its contents are supplied under the terms of the
   3  * Common Development and Distribution License ("CDDL"), version 1.0.
   4  * You may only use this file in accordance with the terms of version
   5  * 1.0 of the CDDL.
   6  *
   7  * A full copy of the text of the CDDL should have accompanied this
   8  * source.  A copy of the CDDL is also available via the Internet at
   9  * http://www.illumos.org/license/CDDL.
  10  */
  11 
  12 /*
  13  * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
  14  * Copyright (c) 2014, 2015 by Delphix. All rights reserved.
  15  */
  16 
  17 /* Based on the NetBSD virtio driver by Minoura Makoto. */
  18 /*
  19  * Copyright (c) 2010 Minoura Makoto.
  20  * All rights reserved.
  21  *
  22  * Redistribution and use in source and binary forms, with or without
  23  * modification, are permitted provided that the following conditions
  24  * are met:
  25  * 1. Redistributions of source code must retain the above copyright
  26  *    notice, this list of conditions and the following disclaimer.
  27  * 2. Redistributions in binary form must reproduce the above copyright
  28  *    notice, this list of conditions and the following disclaimer in the
  29  *    documentation and/or other materials provided with the distribution.
  30  *
  31  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  32  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  33  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.


 367 vioif_dma_curr_cookie(ddi_dma_handle_t dmah)
 368 {
 369         ddi_dma_impl_t *dmah_impl = (void *) dmah;
 370         ASSERT(dmah_impl->dmai_cookie);
 371         return (dmah_impl->dmai_cookie);
 372 }
 373 
 374 static void
 375 vioif_dma_reset_cookie(ddi_dma_handle_t dmah, ddi_dma_cookie_t *dmac)
 376 {
 377         ddi_dma_impl_t *dmah_impl = (void *) dmah;
 378         dmah_impl->dmai_cookie = dmac;
 379 }
 380 
 381 static link_state_t
 382 vioif_link_state(struct vioif_softc *sc)
 383 {
 384         if (sc->sc_virtio.sc_features & VIRTIO_NET_F_STATUS) {
 385                 if (virtio_read_device_config_2(&sc->sc_virtio,
 386                     VIRTIO_NET_CONFIG_STATUS) & VIRTIO_NET_S_LINK_UP) {
 387 
 388                         return (LINK_STATE_UP);
 389                 } else {
 390                         return (LINK_STATE_DOWN);
 391                 }
 392         }
 393 
 394         return (LINK_STATE_UP);
 395 }
 396 
 397 static ddi_dma_attr_t vioif_inline_buf_dma_attr = {
 398         DMA_ATTR_V0,            /* Version number */
 399         0,                      /* low address */
 400         0xFFFFFFFFFFFFFFFF,     /* high address */
 401         0xFFFFFFFF,             /* counter register max */
 402         1,                      /* page alignment */
 403         1,                      /* burst sizes: 1 - 32 */
 404         1,                      /* minimum transfer size */
 405         0xFFFFFFFF,             /* max transfer size */
 406         0xFFFFFFFFFFFFFFF,      /* address register max */
 407         1,                      /* scatter-gather capacity */


 679 {
 680         return (DDI_SUCCESS);
 681 }
 682 
 683 /* ARGSUSED */
 684 int
 685 vioif_unicst(void *arg, const uint8_t *macaddr)
 686 {
 687         return (DDI_FAILURE);
 688 }
 689 
 690 
 691 static int
 692 vioif_add_rx(struct vioif_softc *sc, int kmflag)
 693 {
 694         struct vq_entry *ve;
 695         struct vioif_rx_buf *buf;
 696 
 697         ve = vq_alloc_entry(sc->sc_rx_vq);
 698         if (!ve) {
 699                 /* Out of free descriptors - ring already full.
 700                  * would be better to update sc_norxdescavail
 701                  * but MAC does not ask for this info
 702                  * hence update sc_norecvbuf

 703                  */
 704                 sc->sc_norecvbuf++;
 705                 goto exit_vq;
 706         }
 707         buf = sc->sc_rxbufs[ve->qe_index];
 708 
 709         if (!buf) {
 710                 /* First run, allocate the buffer. */
 711                 buf = kmem_cache_alloc(sc->sc_rxbuf_cache, kmflag);
 712                 sc->sc_rxbufs[ve->qe_index] = buf;
 713         }
 714 
 715         /* Still nothing? Bye. */
 716         if (!buf) {
 717                 dev_err(sc->sc_dev, CE_WARN, "Can't allocate rx buffer");
 718                 sc->sc_norecvbuf++;
 719                 goto exit_buf;
 720         }
 721 
 722         ASSERT(buf->rb_mapping.vbm_ncookies >= 1);


 827                         bcopy((char *)buf->rb_mapping.vbm_buf +
 828                             sizeof (struct virtio_net_hdr), mp->b_rptr, len);
 829                         mp->b_wptr = mp->b_rptr + len;
 830 
 831                 } else {
 832                         mp = desballoc((unsigned char *)
 833                             buf->rb_mapping.vbm_buf +
 834                             sizeof (struct virtio_net_hdr) +
 835                             VIOIF_IP_ALIGN, len, 0, &buf->rb_frtn);
 836                         if (!mp) {
 837                                 sc->sc_norecvbuf++;
 838                                 sc->sc_ierrors++;
 839 
 840                                 virtio_free_chain(ve);
 841                                 break;
 842                         }
 843                         mp->b_wptr = mp->b_rptr + len;
 844 
 845                         atomic_inc_ulong(&sc->sc_rxloan);
 846                         /*
 847                          * Buffer loanded, we will have to allocate a new one
 848                          * for this slot.
 849                          */
 850                         sc->sc_rxbufs[ve->qe_index] = NULL;
 851                 }
 852                 /* virtio-net does not provide the info if this packet
 853                  * is multicast or broadcast. So we have to check it


 854                  */
 855                 if (mp->b_rptr[0] & 0x1) {
 856                         if (bcmp(mp->b_rptr, vioif_broadcast, ETHERADDRL) != 0)
 857                                 sc->sc_multircv++;
 858                         else
 859                                 sc->sc_brdcstrcv++;
 860                 }
 861 
 862                 sc->sc_rbytes += len;
 863                 sc->sc_ipackets++;
 864 
 865                 virtio_free_chain(ve);
 866                 mac_rx(sc->sc_mac_handle, NULL, mp);
 867                 i++;
 868         }
 869 
 870         return (i);
 871 }
 872 
 873 static void


1297         int err;
1298 
1299         switch (pr_num) {
1300         case MAC_PROP_MTU:
1301                 new_mtu = pr_val;
1302 
1303                 if (*new_mtu > MAX_MTU) {
1304                         return (EINVAL);
1305                 }
1306 
1307                 err = mac_maxsdu_update(sc->sc_mac_handle, *new_mtu);
1308                 if (err) {
1309                         return (err);
1310                 }
1311                 break;
1312         case MAC_PROP_PRIVATE:
1313                 err = vioif_set_prop_private(sc, pr_name,
1314                     pr_valsize, pr_val);
1315                 if (err)
1316                         return (err);

1317         default:
1318                 return (ENOTSUP);
1319         }
1320 
1321         return (0);
1322 }
1323 
1324 static int
1325 vioif_get_prop_private(struct vioif_softc *sc, const char *pr_name,
1326     uint_t pr_valsize, void *pr_val)
1327 {
1328         int err = ENOTSUP;
1329         int value;
1330 
1331         if (strcmp(pr_name, vioif_txcopy_thresh) == 0) {
1332 
1333                 value = sc->sc_txcopy_thresh;
1334                 err = 0;
1335                 goto done;
1336         }


1353 {
1354         struct vioif_softc *sc = arg;
1355         int err = ENOTSUP;
1356 
1357         switch (pr_num) {
1358         case MAC_PROP_PRIVATE:
1359                 err = vioif_get_prop_private(sc, pr_name,
1360                     pr_valsize, pr_val);
1361                 break;
1362         default:
1363                 break;
1364         }
1365         return (err);
1366 }
1367 
1368 static void
1369 vioif_propinfo(void *arg, const char *pr_name, mac_prop_id_t pr_num,
1370     mac_prop_info_handle_t prh)
1371 {
1372         struct vioif_softc *sc = arg;


1373 
1374         switch (pr_num) {
1375         case MAC_PROP_MTU:
1376                 mac_prop_info_set_range_uint32(prh, ETHERMIN, MAX_MTU);
1377                 break;
1378 
1379         case MAC_PROP_PRIVATE: {
1380                 char valstr[64];
1381                 int value;
1382 
1383                 bzero(valstr, sizeof (valstr));
1384                 if (strcmp(pr_name, vioif_txcopy_thresh) == 0) {
1385 
1386                         value = sc->sc_txcopy_thresh;
1387                 } else  if (strcmp(pr_name,
1388                     vioif_rxcopy_thresh) == 0) {
1389                         value = sc->sc_rxcopy_thresh;
1390                 } else {
1391                         return;
1392                 }
1393                 (void) snprintf(valstr, sizeof (valstr), "%d", value);
1394         }

1395         default:
1396                 break;
1397         }
1398 }
1399 
1400 static boolean_t
1401 vioif_getcapab(void *arg, mac_capab_t cap, void *cap_data)
1402 {
1403         struct vioif_softc *sc = arg;
1404 
1405         switch (cap) {
1406         case MAC_CAPAB_HCKSUM:
1407                 if (sc->sc_tx_csum) {
1408                         uint32_t *txflags = cap_data;
1409 
1410                         *txflags = HCKSUM_INET_PARTIAL;
1411                         return (B_TRUE);
1412                 }
1413                 return (B_FALSE);
1414         case MAC_CAPAB_LSO:


1434         .mc_setpromisc  = vioif_promisc,
1435         .mc_multicst    = vioif_multicst,
1436         .mc_unicst      = vioif_unicst,
1437         .mc_tx          = vioif_tx,
1438         /* Optional callbacks */
1439         .mc_reserved    = NULL,         /* reserved */
1440         .mc_ioctl       = NULL,         /* mc_ioctl */
1441         .mc_getcapab    = vioif_getcapab,               /* mc_getcapab */
1442         .mc_open        = NULL,         /* mc_open */
1443         .mc_close       = NULL,         /* mc_close */
1444         .mc_setprop     = vioif_setprop,
1445         .mc_getprop     = vioif_getprop,
1446         .mc_propinfo    = vioif_propinfo,
1447 };
1448 
1449 static void
1450 vioif_show_features(struct vioif_softc *sc, const char *prefix,
1451     uint32_t features)
1452 {
1453         char buf[512];


1454 
1455         dev_err(sc->sc_dev, CE_NOTE, "%s %s Vioif (%b)", prefix, virtio_show_features(...), features, "\020\1CSUM\2GUEST_CSUM\3MAC\4GSO\5GUEST_TSO4\5GUEST_TSO6\6GUEST_ECN\7GUEST_UFO\8HOST_TSO4\9HOST_TSO6\10HOST_ECN\11HOST_UFO\12MRG_RXBUF\13STATUS\14CTRL_VQ\15CTRL_RX\16CTRL_VLAN\17CTRL_RX_EXTRA", buf);




































































1456 }
1457 
1458 /*
1459  * Find out which features are supported by the device and
1460  * choose which ones we wish to use.
1461  */
1462 static int
1463 vioif_dev_features(struct vioif_softc *sc)
1464 {
1465         uint32_t host_features;
1466 
1467         host_features = virtio_negotiate_features(&sc->sc_virtio,
1468             VIRTIO_NET_F_CSUM |
1469             VIRTIO_NET_F_HOST_TSO4 |
1470             VIRTIO_NET_F_HOST_ECN |
1471             VIRTIO_NET_F_MAC |
1472             VIRTIO_NET_F_STATUS |
1473             VIRTIO_F_RING_INDIRECT_DESC |
1474             VIRTIO_F_NOTIFY_ON_EMPTY);
1475 
1476         vioif_show_features(sc, "Host features: ", host_features);
1477         vioif_show_features(sc,  ",
1478             sc->sc_virtio.sc_features);
1479 
1480         if (!(sc->sc_virtio.sc_features & VIRTIO_F_RING_INDIRECT_DESC)) {
1481                 dev_err(sc->sc_dev, CE_NOTE,
1482                     "Host does not support RING_INDIRECT_DESC, bye.");
1483                 return (DDI_FAILURE);
1484         }
1485 
1486         return (DDI_SUCCESS);
1487 }
1488 
1489 static int
1490 vioif_has_feature(struct vioif_softc *sc, uint32_t feature)
1491 {
1492         return (virtio_has_feature(&sc->sc_virtio, feature));
1493 }
1494 
1495 static void
1496 vioif_set_mac(struct vioif_softc *sc)
1497 {


1614         }
1615 }
1616 
1617 static int
1618 vioif_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd)
1619 {
1620         int ret, instance;
1621         struct vioif_softc *sc;
1622         struct virtio_softc *vsc;
1623         mac_register_t *macp;
1624         char cache_name[CACHE_NAME_SIZE];
1625 
1626         instance = ddi_get_instance(devinfo);
1627 
1628         switch (cmd) {
1629         case DDI_ATTACH:
1630                 break;
1631 
1632         case DDI_RESUME:
1633         case DDI_PM_RESUME:
1634                 dev_err(devinfo, CE_WARN, "resume not supported yet");
1635                 goto exit;
1636 
1637         default:
1638                 dev_err(devinfo, CE_WARN, "cmd 0x%x unrecognized", cmd);
1639                 goto exit;
1640         }
1641 
1642         sc = kmem_zalloc(sizeof (struct vioif_softc), KM_SLEEP);
1643         ddi_set_driver_private(devinfo, sc);
1644 
1645         vsc = &sc->sc_virtio;
1646 
1647         /* Duplicate for less typing */
1648         sc->sc_dev = devinfo;
1649         vsc->sc_dev = devinfo;
1650 
1651         /*
1652          * Initialize interrupt kstat.
1653          */
1654         sc->sc_intrstat = kstat_create("vioif", instance, "intr", "controller",
1655             KSTAT_TYPE_INTR, 1, 0);
1656         if (sc->sc_intrstat == NULL) {
1657                 dev_err(devinfo, CE_WARN, "kstat_create failed");
1658                 goto exit_intrstat;


1797 exit_map:
1798         kstat_delete(sc->sc_intrstat);
1799         kmem_free(sc, sizeof (struct vioif_softc));
1800 exit:
1801         return (DDI_FAILURE);
1802 }
1803 
1804 static int
1805 vioif_detach(dev_info_t *devinfo, ddi_detach_cmd_t cmd)
1806 {
1807         struct vioif_softc *sc;
1808 
1809         if ((sc = ddi_get_driver_private(devinfo)) == NULL)
1810                 return (DDI_FAILURE);
1811 
1812         switch (cmd) {
1813         case DDI_DETACH:
1814                 break;
1815 
1816         case DDI_PM_SUSPEND:
1817                 cmn_err(CE_WARN, "suspend not supported yet");
1818                 return (DDI_FAILURE);
1819 
1820         default:
1821                 cmn_err(CE_WARN, "cmd 0x%x unrecognized", cmd);
1822                 return (DDI_FAILURE);
1823         }
1824 
1825         if (sc->sc_rxloan) {
1826                 cmn_err(CE_WARN, "Some rx buffers are still upstream, "
1827                     "Not detaching");
1828                 return (DDI_FAILURE);
1829         }
1830 
1831         virtio_stop_vq_intr(sc->sc_rx_vq);
1832         virtio_stop_vq_intr(sc->sc_tx_vq);
1833 
1834         virtio_release_ints(&sc->sc_virtio);
1835 
1836         if (mac_unregister(sc->sc_mac_handle)) {
1837                 return (DDI_FAILURE);
1838         }
1839 
1840         mac_free(sc->sc_macp);
1841 
1842         vioif_free_mems(sc);
1843         virtio_free_vq(sc->sc_rx_vq);
1844         virtio_free_vq(sc->sc_tx_vq);
1845 
1846         virtio_device_reset(&sc->sc_virtio);


1862         if ((sc = ddi_get_driver_private(devinfo)) == NULL)
1863                 return (DDI_FAILURE);
1864 
1865         virtio_stop_vq_intr(sc->sc_rx_vq);
1866         virtio_stop_vq_intr(sc->sc_tx_vq);
1867         virtio_device_reset(&sc->sc_virtio);
1868 
1869         return (DDI_SUCCESS);
1870 }
1871 
1872 int
1873 _init(void)
1874 {
1875         int ret = 0;
1876 
1877         mac_init_ops(&vioif_ops, "vioif");
1878 
1879         ret = mod_install(&modlinkage);
1880         if (ret != DDI_SUCCESS) {
1881                 mac_fini_ops(&vioif_ops);
1882                 cmn_err(CE_WARN, "Unable to install the driver");
1883                 return (ret);
1884         }
1885 
1886         return (0);
1887 }
1888 
1889 int
1890 _fini(void)
1891 {
1892         int ret;
1893 
1894         ret = mod_remove(&modlinkage);
1895         if (ret == DDI_SUCCESS) {
1896                 mac_fini_ops(&vioif_ops);
1897         }
1898 
1899         return (ret);
1900 }
1901 
1902 int