~ubuntu-branches/ubuntu/quantal/open-vm-tools/quantal-201210021442

« back to all changes in this revision

Viewing changes to modules/solaris/vmxnet3/vmxnet3_main.c

  • Committer: Bazaar Package Importer
  • Author(s): Serge Hallyn
  • Date: 2011-03-31 14:20:05 UTC
  • mfrom: (1.4.3 upstream)
  • Revision ID: james.westby@ubuntu.com-20110331142005-3n9red91p7ogkweo
Tags: 2011.03.28-387002-0ubuntu1
* Merge latest upstream git tag.  This has the unlocked_ioctl change
  needed to fix dkms build failures (LP: #727342)
* Changes in debian/rules:
  - work around a bug in toolbox/Makefile, where install-exec-hook is
    not happening.  This needs to get fixed the right way.
  - don't install 'vmware-user' which seems to no longer exist
  - move /etc/xdg into open-vm-toolbox (which should be done using .install)
* debian/open-vm-tools.init: add 'modprobe [-r] vmblock'. (LP: #332323)
* debian/rules and debian/open-vm-toolbox.lintian-overrides:
  - Make vmware-user-suid-wrapper suid-root (LP: #332323)

Show diffs side-by-side

added added

removed removed

Lines of Context:
31
31
static int       vmxnet3_start(void *);
32
32
static void      vmxnet3_stop(void *);
33
33
static int       vmxnet3_setpromisc(void *, boolean_t);
 
34
static void      vmxnet3_ioctl(void *arg, queue_t *wq, mblk_t *mp);
34
35
static int       vmxnet3_multicst(void *, boolean_t, const uint8_t *);
35
36
static int       vmxnet3_unicst(void *, const uint8_t *);
36
37
static boolean_t vmxnet3_getcapab(void *, mac_capab_t, void *);
37
38
 
38
39
/* MAC callbacks */
39
40
static mac_callbacks_t vmxnet3_mac_callbacks = {
40
 
   MC_GETCAPAB,        /* mc_callbacks */
41
 
   vmxnet3_getstat,    /* mc_getstat */
42
 
   vmxnet3_start,      /* mc_start */
43
 
   vmxnet3_stop,       /* mc_stop */
44
 
   vmxnet3_setpromisc, /* mc_setpromisc */
45
 
   vmxnet3_multicst,   /* mc_multicst */
46
 
   vmxnet3_unicst,     /* mc_unicst */
47
 
   vmxnet3_tx,         /* mc_tx */
 
41
   .mc_callbacks = MC_GETCAPAB | MC_IOCTL,
 
42
   .mc_getstat = vmxnet3_getstat,
 
43
   .mc_start = vmxnet3_start,
 
44
   .mc_stop = vmxnet3_stop,
 
45
   .mc_setpromisc = vmxnet3_setpromisc,
 
46
   .mc_multicst = vmxnet3_multicst,
 
47
   .mc_unicst = vmxnet3_unicst,
 
48
   .mc_tx = vmxnet3_tx,
48
49
#ifndef OPEN_SOLARIS
49
 
   NULL,               /* mc_resources */
 
50
   .mc_resources = NULL,
50
51
#endif
51
 
   NULL,               /* mc_ioctl */
52
 
   vmxnet3_getcapab    /* mc_getcapab */
 
52
   .mc_ioctl = vmxnet3_ioctl,
 
53
   .mc_getcapab = *vmxnet3_getcapab,
53
54
};
54
55
 
55
56
/* Tx DMA engine description */
250
251
   ds->devRead.misc.driverInfo.uptVerSpt = 1;
251
252
 
252
253
   ds->devRead.misc.uptFeatures = UPT1_F_RXCSUM;
253
 
   ds->devRead.misc.mtu = ETHERMTU;
 
254
   ds->devRead.misc.mtu = dp->cur_mtu;
 
255
 
254
256
   // XXX: ds->devRead.misc.maxNumRxSG
255
257
   ds->devRead.misc.numTxQueues = 1;
256
258
   ds->devRead.misc.numRxQueues = 1;
651
653
    */
652
654
   rxQueueSize = vmxnet3_getprop(dp, "RxRingSize", 32, 4096,
653
655
                                 VMXNET3_DEF_RX_RING_SIZE);
654
 
   if (!(txQueueSize & VMXNET3_RING_SIZE_MASK)) {
 
656
   if (!(rxQueueSize & VMXNET3_RING_SIZE_MASK)) {
655
657
      dp->rxQueue.cmdRing.size = rxQueueSize;
656
658
      dp->rxQueue.compRing.size = rxQueueSize;
657
659
      dp->rxQueue.sharedCtrl = &rqdesc->ctrl;
938
940
   return DDI_SUCCESS;
939
941
}
940
942
 
 
943
 
 
944
/*
 
945
 *---------------------------------------------------------------------------
 
946
 *
 
947
 * vmxnet3_change_mtu --
 
948
 *
 
949
 *    Change the MTU as seen by the driver. Reset the device and tx/rx queues
 
950
 *    so that buffers of right size are posted in rx queues.
 
951
 *
 
952
 * Results:
 
953
 *    EINVAL for invalid MTUs or other failures. 0 for success.
 
954
 *
 
955
 * Side effects:
 
956
 *    None.
 
957
 *
 
958
 *---------------------------------------------------------------------------
 
959
 */
 
960
 
 
961
static int
 
962
vmxnet3_change_mtu(vmxnet3_softc_t *dp, uint32_t new_mtu)
 
963
{
 
964
   int ret = 0, do_reset = 0;
 
965
   ASSERT(dp);
 
966
   if (new_mtu == dp->cur_mtu) {
 
967
      VMXNET3_WARN(dp, "New MTU is same as old mtu : %d.\n", new_mtu);
 
968
      return 0;
 
969
   }
 
970
 
 
971
   if (new_mtu < VMXNET3_MIN_MTU || new_mtu > VMXNET3_MAX_MTU) {
 
972
      VMXNET3_WARN(dp, "New MTU not in valid range [%d, %d].\n",
 
973
                   VMXNET3_MIN_MTU, VMXNET3_MAX_MTU);
 
974
      return EINVAL;
 
975
   }
 
976
 
 
977
   if (dp->devEnabled) {
 
978
      do_reset = 1;
 
979
      vmxnet3_stop(dp);
 
980
      VMXNET3_BAR1_PUT32(dp, VMXNET3_REG_CMD, VMXNET3_CMD_RESET_DEV);
 
981
   }
 
982
 
 
983
   dp->cur_mtu = new_mtu;
 
984
 
 
985
   if (do_reset)
 
986
      ret = vmxnet3_start(dp);
 
987
 
 
988
   return ret;
 
989
}
 
990
 
 
991
 
 
992
/*
 
993
 *---------------------------------------------------------------------------
 
994
 *
 
995
 * vmxnet3_ioctl --
 
996
 *
 
997
 *    DDI/DDK callback to handle IOCTL in driver. Currently it only handles
 
998
 *    ND_SET ioctl. Rest all are ignored. The ND_SET is used to set/reset
 
999
 *    accept-jumbo ndd parameted for the interface.
 
1000
 *
 
1001
 * Results:
 
1002
 *    Nothing is returned directly. An ACK or NACK is conveyed to the calling
 
1003
 *    function from the mblk which was used to call this function.
 
1004
 *
 
1005
 * Side effects:
 
1006
 *    MTU can be changed and device can be reset.
 
1007
 *
 
1008
 *---------------------------------------------------------------------------
 
1009
 */
 
1010
 
 
1011
static void
 
1012
vmxnet3_ioctl(void *arg, queue_t *wq, mblk_t *mp)
 
1013
{
 
1014
   vmxnet3_softc_t *dp = arg;
 
1015
   int             ret = EINVAL;
 
1016
   IOCP            iocp;
 
1017
   mblk_t          *mp1;
 
1018
   char            *valp, *param;
 
1019
   int             data;
 
1020
 
 
1021
   iocp = (void *)mp->b_rptr;
 
1022
   iocp->ioc_error = 0;
 
1023
 
 
1024
   switch (iocp->ioc_cmd) {
 
1025
   case ND_SET:
 
1026
 
 
1027
      /* the mblk in continuation would contain the ndd parameter name
 
1028
       * and data value to be set
 
1029
       */
 
1030
      mp1 = mp->b_cont;
 
1031
      if (!mp1) {
 
1032
         VMXNET3_WARN(dp, "Error locating parameter name.\n");
 
1033
         ret = EINVAL;
 
1034
         break;
 
1035
      }
 
1036
 
 
1037
      mp1->b_datap->db_lim[-1] = '\0';  /* Force null termination */
 
1038
 
 
1039
      /*
 
1040
       * From /usr/src/uts/common/inet/nd.c : nd_getset()
 
1041
       * "logic throughout nd_xxx assumes single data block for ioctl.
 
1042
       *  However, existing code sends in some big buffers."
 
1043
       */
 
1044
      if (mp1->b_cont) {
 
1045
         freemsg(mp1->b_cont);
 
1046
         mp1->b_cont = NULL;
 
1047
      }
 
1048
 
 
1049
      valp = (char *)mp1->b_rptr;       /* Points to param name*/
 
1050
      ASSERT(valp);
 
1051
      param = valp;
 
1052
      VMXNET3_DEBUG(dp, 3, "ND Set ioctl for %s\n", param);
 
1053
 
 
1054
      /* Go past the end of this null terminated string to get the data value.*/
 
1055
      while (*valp && valp <= (char *)mp1->b_wptr)
 
1056
         valp++;
 
1057
 
 
1058
      if (valp > (char *)mp1->b_wptr) {
 
1059
         /* We are already beyond the readable area of mblk and still havent
 
1060
          * found the end of param string.
 
1061
          */
 
1062
         VMXNET3_WARN(dp, "No data value found to be set to param.\n");
 
1063
         data = -1;
 
1064
      } else {
 
1065
         valp++;                        /* Now this points to data string */
 
1066
         data = (int)*valp - (int)'0';  /* Get numeric value of first letter */
 
1067
      }
 
1068
 
 
1069
      if (strcmp("accept-jumbo", param) == 0) {
 
1070
         if (data == 1) {
 
1071
            VMXNET3_DEBUG(dp, 2, "Accepting jumbo frames\n");
 
1072
            ret = vmxnet3_change_mtu(dp, VMXNET3_MAX_MTU);
 
1073
         } else if (data == 0) {
 
1074
            VMXNET3_DEBUG(dp, 2, "Rejecting jumbo frames\n");
 
1075
            ret = vmxnet3_change_mtu(dp, ETHERMTU);
 
1076
         } else {
 
1077
            VMXNET3_WARN(dp, "Invalid data value to be set, use 1 or 0.\n");
 
1078
            ret = -1;
 
1079
         }
 
1080
      }
 
1081
      freemsg(mp1);
 
1082
      mp->b_cont = NULL;
 
1083
      break;
 
1084
 
 
1085
   default:
 
1086
      if (mp->b_cont) {
 
1087
         freemsg(mp->b_cont);
 
1088
         mp->b_cont = NULL;
 
1089
      }
 
1090
      ret = -1;
 
1091
      break;
 
1092
   }
 
1093
 
 
1094
   if (ret == 0)
 
1095
      miocack(wq, mp, 0, 0);
 
1096
   else
 
1097
      miocnak(wq, mp, 0, EINVAL);
 
1098
}
 
1099
 
 
1100
 
941
1101
/*
942
1102
 *---------------------------------------------------------------------------
943
1103
 *
1128
1288
   return DDI_INTR_UNCLAIMED;
1129
1289
}
1130
1290
 
 
1291
 
1131
1292
/*
1132
1293
 *---------------------------------------------------------------------------
1133
1294
 *
1150
1311
   mac_register_t *macr;
1151
1312
   uint16_t vendorId, devId, ret16;
1152
1313
   uint32_t ret32;
1153
 
   int ret;
 
1314
   int ret, err;
1154
1315
   uint_t uret;
1155
1316
 
1156
1317
   if (cmd != DDI_ATTACH) {
1165
1326
 
1166
1327
   dp->dip = dip;
1167
1328
   dp->instance = ddi_get_instance(dip);
 
1329
   dp->cur_mtu = ETHERMTU;
1168
1330
 
1169
1331
   VMXNET3_DEBUG(dp, 1, "attach()\n");
1170
1332
 
1252
1414
   macr->m_src_addr = dp->macaddr;
1253
1415
   macr->m_dst_addr = NULL;
1254
1416
   macr->m_callbacks = &vmxnet3_mac_callbacks;
1255
 
   macr->m_min_sdu = 0;
1256
 
   macr->m_max_sdu = ETHERMTU;
 
1417
   macr->m_min_sdu = VMXNET3_MIN_MTU;
 
1418
   macr->m_max_sdu = VMXNET3_MAX_MTU;
1257
1419
   macr->m_pdata = NULL;
1258
1420
   macr->m_pdata_size = 0;
1259
1421
 
1274
1436
      case VMXNET3_IT_AUTO:
1275
1437
      case VMXNET3_IT_MSIX:
1276
1438
         dp->intrType = DDI_INTR_TYPE_MSIX;
1277
 
         if (ddi_intr_alloc(dip, &dp->intrHandle, dp->intrType, 0, 1,
1278
 
                            &ret, DDI_INTR_ALLOC_STRICT) == DDI_SUCCESS) {
 
1439
         err = ddi_intr_alloc(dip, &dp->intrHandle, dp->intrType, 0, 1,
 
1440
                              &ret, DDI_INTR_ALLOC_STRICT);
 
1441
         if (err == DDI_SUCCESS)
1279
1442
            break;
1280
 
         }
1281
 
         VMXNET3_DEBUG(dp, 2, "DDI_INTR_TYPE_MSIX failed\n");
 
1443
         VMXNET3_DEBUG(dp, 2, "DDI_INTR_TYPE_MSIX failed, err:%d\n", err);
1282
1444
      case VMXNET3_IT_MSI:
1283
1445
         dp->intrType = DDI_INTR_TYPE_MSI;
1284
1446
         if (ddi_intr_alloc(dip, &dp->intrHandle, dp->intrType, 0, 1,
1285
 
                            &ret, DDI_INTR_ALLOC_STRICT) == DDI_SUCCESS) {
 
1447
                            &ret, DDI_INTR_ALLOC_STRICT) == DDI_SUCCESS)
1286
1448
            break;
1287
 
         }
1288
1449
         VMXNET3_DEBUG(dp, 2, "DDI_INTR_TYPE_MSI failed\n");
1289
1450
      case VMXNET3_IT_INTX:
1290
1451
         dp->intrType = DDI_INTR_TYPE_FIXED;
1335
1496
      goto error_mutexes;
1336
1497
   }
1337
1498
 
1338
 
   if (ddi_intr_enable(dp->intrHandle) != DDI_SUCCESS) {
1339
 
      VMXNET3_WARN(dp, "ddi_intr_enable() failed\n");
 
1499
   err = ddi_intr_get_cap(dp->intrHandle, &dp->intrCap);
 
1500
   if (err != DDI_SUCCESS) {
 
1501
      VMXNET3_WARN(dp, "ddi_intr_get_cap() failed %d", err);
1340
1502
      goto error_intr_handler;
1341
1503
   }
1342
1504
 
 
1505
   if (dp->intrCap & DDI_INTR_FLAG_BLOCK) {
 
1506
      err = ddi_intr_block_enable(&dp->intrHandle, 1);
 
1507
      if (err != DDI_SUCCESS) {
 
1508
         VMXNET3_WARN(dp, "ddi_intr_block_enable() failed, err:%d\n", err);
 
1509
         goto error_intr_handler;
 
1510
      }
 
1511
   } else {
 
1512
      err = ddi_intr_enable(dp->intrHandle);
 
1513
      if ((err != DDI_SUCCESS)) {
 
1514
         VMXNET3_WARN(dp, "ddi_intr_enable() failed, err:%d\n", err);
 
1515
         goto error_intr_handler;
 
1516
      }
 
1517
   }
 
1518
 
1343
1519
   return DDI_SUCCESS;
1344
1520
 
1345
1521
error_intr_handler:
1403
1579
      }
1404
1580
   }
1405
1581
 
1406
 
   ddi_intr_disable(dp->intrHandle);
 
1582
   if (dp->intrCap & DDI_INTR_FLAG_BLOCK) {
 
1583
      ddi_intr_block_disable(&dp->intrHandle, 1);
 
1584
   } else {
 
1585
      ddi_intr_disable(dp->intrHandle);
 
1586
   }
1407
1587
   ddi_intr_remove_handler(dp->intrHandle);
1408
1588
   ddi_intr_free(dp->intrHandle);
1409
1589