957 ASSERT(ddp->dd_tref == 0 && ddp->dd_prop_taskid == NULL);
958 }
959
960 if (ddp->dd_linkid != DATALINK_INVALID_LINKID)
961 dls_devnet_stat_destroy(ddp, ddp->dd_owner_zid);
962
963 ddp->dd_prop_loaded = B_FALSE;
964 ddp->dd_linkid = DATALINK_INVALID_LINKID;
965 ddp->dd_flags = 0;
966 mutex_exit(&ddp->dd_mutex);
967 kmem_cache_free(i_dls_devnet_cachep, ddp);
968
969 return (0);
970 }
971
972 static int
973 dls_devnet_hold_common(datalink_id_t linkid, dls_devnet_t **ddpp,
974 boolean_t tmp_hold)
975 {
976 dls_devnet_t *ddp;
977 dev_t phydev = 0;
978 dls_dev_handle_t ddh = NULL;
979 int err;
980
981 /*
982 * Hold this link to prevent it being detached in case of a
983 * physical link.
984 */
985 if (dls_mgmt_get_phydev(linkid, &phydev) == 0)
986 (void) softmac_hold_device(phydev, &ddh);
987
988 rw_enter(&i_dls_devnet_lock, RW_READER);
989 if ((err = mod_hash_find(i_dls_devnet_id_hash,
990 (mod_hash_key_t)(uintptr_t)linkid, (mod_hash_val_t *)&ddp)) != 0) {
991 ASSERT(err == MH_ERR_NOTFOUND);
992 rw_exit(&i_dls_devnet_lock);
993 softmac_rele_device(ddh);
994 return (ENOENT);
995 }
996
997 mutex_enter(&ddp->dd_mutex);
998 ASSERT(ddp->dd_ref > 0);
999 if (ddp->dd_flags & DD_CONDEMNED) {
1000 mutex_exit(&ddp->dd_mutex);
1001 rw_exit(&i_dls_devnet_lock);
1002 softmac_rele_device(ddh);
1003 return (ENOENT);
1004 }
1005 if (tmp_hold)
1006 ddp->dd_tref++;
1007 else
1008 ddp->dd_ref++;
1009 mutex_exit(&ddp->dd_mutex);
1010 rw_exit(&i_dls_devnet_lock);
1011
1012 softmac_rele_device(ddh);
1013
1014 *ddpp = ddp;
1015 return (0);
1016 }
1017
1018 int
1019 dls_devnet_hold(datalink_id_t linkid, dls_devnet_t **ddpp)
1020 {
1021 return (dls_devnet_hold_common(linkid, ddpp, B_FALSE));
1022 }
1023
1024 /*
1025 * Hold the vanity naming structure (dls_devnet_t) temporarily. The request to
1026 * delete the dls_devnet_t will wait until the temporary reference is released.
1027 */
1028 int
1029 dls_devnet_hold_tmp(datalink_id_t linkid, dls_devnet_t **ddpp)
1030 {
1031 return (dls_devnet_hold_common(linkid, ddpp, B_TRUE));
1032 }
1033
1034 /*
1035 * This funtion is called when a DLS client tries to open a device node.
1036 * This dev_t could a result of a /dev/net node access (returned by
1037 * devnet_create_rvp->dls_devnet_open()) or a direct /dev node access.
1038 * In both cases, this function bumps up the reference count of the
1039 * dls_devnet_t structure. The reference is held as long as the device node
1040 * is open. In the case of /dev/net while it is true that the initial reference
1041 * is held when the devnet_create_rvp->dls_devnet_open call happens, this
1042 * initial reference is released immediately in devnet_inactive_callback ->
1043 * dls_devnet_close(). (Note that devnet_inactive_callback() is called right
1044 * after dld_open completes, not when the /dev/net node is being closed).
1045 * To undo this function, call dls_devnet_rele()
1046 */
1047 int
1048 dls_devnet_hold_by_dev(dev_t dev, dls_dl_handle_t *ddhp)
1049 {
1050 char name[MAXNAMELEN];
1051 char *drv;
1052 dls_dev_handle_t ddh = NULL;
1053 dls_devnet_t *ddp;
1054 int err;
1055
1056 if ((drv = ddi_major_to_name(getmajor(dev))) == NULL)
1057 return (EINVAL);
1058
1059 (void) snprintf(name, sizeof (name), "%s%d", drv,
1060 DLS_MINOR2INST(getminor(dev)));
1061
1062 /*
1063 * Hold this link to prevent it being detached in case of a
1064 * GLDv3 physical link.
1065 */
1066 if (DLS_MINOR2INST(getminor(dev)) <= DLS_MAX_PPA)
1067 (void) softmac_hold_device(dev, &ddh);
1068
1069 rw_enter(&i_dls_devnet_lock, RW_READER);
1070 if ((err = mod_hash_find(i_dls_devnet_hash,
1071 (mod_hash_key_t)name, (mod_hash_val_t *)&ddp)) != 0) {
1072 ASSERT(err == MH_ERR_NOTFOUND);
1073 rw_exit(&i_dls_devnet_lock);
1074 softmac_rele_device(ddh);
1075 return (ENOENT);
1076 }
1077 mutex_enter(&ddp->dd_mutex);
1078 ASSERT(ddp->dd_ref > 0);
1079 if (ddp->dd_flags & DD_CONDEMNED) {
1080 mutex_exit(&ddp->dd_mutex);
1081 rw_exit(&i_dls_devnet_lock);
1082 softmac_rele_device(ddh);
1083 return (ENOENT);
1084 }
1085 ddp->dd_ref++;
1086 mutex_exit(&ddp->dd_mutex);
1087 rw_exit(&i_dls_devnet_lock);
1088
1089 softmac_rele_device(ddh);
1090
1091 *ddhp = ddp;
1092 return (0);
1093 }
1094
1095 void
1096 dls_devnet_rele(dls_devnet_t *ddp)
1097 {
1098 mutex_enter(&ddp->dd_mutex);
1099 ASSERT(ddp->dd_ref > 1);
1100 ddp->dd_ref--;
1101 if ((ddp->dd_flags & DD_IMPLICIT_IPTUN) && ddp->dd_ref == 1) {
1102 mutex_exit(&ddp->dd_mutex);
1103 if (i_dls_devnet_destroy_iptun(ddp->dd_linkid) != 0)
1104 ddp->dd_flags |= DD_IMPLICIT_IPTUN;
1105 return;
1106 }
1107 mutex_exit(&ddp->dd_mutex);
1108 }
1109
1110 static int
1115 major_t major;
1116 dev_t phy_dev, tmp_dev;
1117 datalink_id_t linkid;
1118 dls_dev_handle_t ddh;
1119 int err;
1120
1121 if ((err = dls_mgmt_get_linkid(link, &linkid)) == 0)
1122 return (dls_devnet_hold(linkid, ddpp));
1123
1124 /*
1125 * If we failed to get the link's linkid because the dlmgmtd daemon
1126 * has not been started, return ENOENT so that the application can
1127 * fallback to open the /dev node.
1128 */
1129 if (err == EBADF)
1130 return (ENOENT);
1131
1132 if (err != ENOENT)
1133 return (err);
1134
1135 if (ddi_parse(link, drv, &ppa) != DDI_SUCCESS)
1136 return (ENOENT);
1137
1138 if (IS_IPTUN_LINK(drv)) {
1139 if ((err = i_dls_devnet_create_iptun(link, drv, &linkid)) != 0)
1140 return (err);
1141 /*
1142 * At this point, an IP tunnel MAC has registered, which
1143 * resulted in a link being created.
1144 */
1145 err = dls_devnet_hold(linkid, ddpp);
1146 ASSERT(err == 0);
1147 if (err != 0) {
1148 VERIFY(i_dls_devnet_destroy_iptun(linkid) == 0);
1149 return (err);
1150 }
1151 /*
1152 * dls_devnet_rele() will know to destroy the implicit IP
1153 * tunnel on last reference release if DD_IMPLICIT_IPTUN is
1154 * set.
1155 */
1156 (*ddpp)->dd_flags |= DD_IMPLICIT_IPTUN;
1157 return (0);
1158 }
1159
1160 /*
1161 * If this link:
1162 * (a) is a physical device, (b) this is the first boot, (c) the MAC
1163 * is not registered yet, and (d) we cannot find its linkid, then the
1164 * linkname is the same as the devname.
1165 *
1166 * First filter out invalid names.
|
957 ASSERT(ddp->dd_tref == 0 && ddp->dd_prop_taskid == NULL);
958 }
959
960 if (ddp->dd_linkid != DATALINK_INVALID_LINKID)
961 dls_devnet_stat_destroy(ddp, ddp->dd_owner_zid);
962
963 ddp->dd_prop_loaded = B_FALSE;
964 ddp->dd_linkid = DATALINK_INVALID_LINKID;
965 ddp->dd_flags = 0;
966 mutex_exit(&ddp->dd_mutex);
967 kmem_cache_free(i_dls_devnet_cachep, ddp);
968
969 return (0);
970 }
971
972 static int
973 dls_devnet_hold_common(datalink_id_t linkid, dls_devnet_t **ddpp,
974 boolean_t tmp_hold)
975 {
976 dls_devnet_t *ddp;
977 int err;
978
979 rw_enter(&i_dls_devnet_lock, RW_READER);
980 if ((err = mod_hash_find(i_dls_devnet_id_hash,
981 (mod_hash_key_t)(uintptr_t)linkid, (mod_hash_val_t *)&ddp)) != 0) {
982 ASSERT(err == MH_ERR_NOTFOUND);
983 rw_exit(&i_dls_devnet_lock);
984 return (ENOENT);
985 }
986
987 mutex_enter(&ddp->dd_mutex);
988 ASSERT(ddp->dd_ref > 0);
989 if (ddp->dd_flags & DD_CONDEMNED) {
990 mutex_exit(&ddp->dd_mutex);
991 rw_exit(&i_dls_devnet_lock);
992 return (ENOENT);
993 }
994 if (tmp_hold)
995 ddp->dd_tref++;
996 else
997 ddp->dd_ref++;
998 mutex_exit(&ddp->dd_mutex);
999 rw_exit(&i_dls_devnet_lock);
1000
1001 *ddpp = ddp;
1002 return (0);
1003 }
1004
1005 int
1006 dls_devnet_hold(datalink_id_t linkid, dls_devnet_t **ddpp)
1007 {
1008 return (dls_devnet_hold_common(linkid, ddpp, B_FALSE));
1009 }
1010
1011 /*
1012 * Hold the vanity naming structure (dls_devnet_t) temporarily. The request to
1013 * delete the dls_devnet_t will wait until the temporary reference is released.
1014 */
1015 int
1016 dls_devnet_hold_tmp(datalink_id_t linkid, dls_devnet_t **ddpp)
1017 {
1018 return (dls_devnet_hold_common(linkid, ddpp, B_TRUE));
1019 }
1020
1021 /*
1022 * This funtion is called when a DLS client tries to open a device node.
1023 * This dev_t could be a result of a /dev/net node access (returned by
1024 * devnet_create_rvp->dls_devnet_open()) or a direct /dev node access.
1025 * In both cases, this function bumps up the reference count of the
1026 * dls_devnet_t structure. The reference is held as long as the device node
1027 * is open. In the case of /dev/net while it is true that the initial reference
1028 * is held when the devnet_create_rvp->dls_devnet_open call happens, this
1029 * initial reference is released immediately in devnet_inactive_callback ->
1030 * dls_devnet_close(). (Note that devnet_inactive_callback() is called right
1031 * after dld_open completes, not when the /dev/net node is being closed).
1032 * To undo this function, call dls_devnet_rele()
1033 */
1034 int
1035 dls_devnet_hold_by_dev(dev_t dev, dls_dl_handle_t *ddhp)
1036 {
1037 char name[MAXNAMELEN];
1038 char *drv;
1039 dls_devnet_t *ddp;
1040 int err;
1041
1042 if ((drv = ddi_major_to_name(getmajor(dev))) == NULL)
1043 return (EINVAL);
1044
1045 (void) snprintf(name, sizeof (name), "%s%d", drv,
1046 DLS_MINOR2INST(getminor(dev)));
1047
1048 rw_enter(&i_dls_devnet_lock, RW_READER);
1049 if ((err = mod_hash_find(i_dls_devnet_hash,
1050 (mod_hash_key_t)name, (mod_hash_val_t *)&ddp)) != 0) {
1051 ASSERT(err == MH_ERR_NOTFOUND);
1052 rw_exit(&i_dls_devnet_lock);
1053 return (ENOENT);
1054 }
1055 mutex_enter(&ddp->dd_mutex);
1056 ASSERT(ddp->dd_ref > 0);
1057 if (ddp->dd_flags & DD_CONDEMNED) {
1058 mutex_exit(&ddp->dd_mutex);
1059 rw_exit(&i_dls_devnet_lock);
1060 return (ENOENT);
1061 }
1062 ddp->dd_ref++;
1063 mutex_exit(&ddp->dd_mutex);
1064 rw_exit(&i_dls_devnet_lock);
1065
1066 *ddhp = ddp;
1067 return (0);
1068 }
1069
1070 void
1071 dls_devnet_rele(dls_devnet_t *ddp)
1072 {
1073 mutex_enter(&ddp->dd_mutex);
1074 ASSERT(ddp->dd_ref > 1);
1075 ddp->dd_ref--;
1076 if ((ddp->dd_flags & DD_IMPLICIT_IPTUN) && ddp->dd_ref == 1) {
1077 mutex_exit(&ddp->dd_mutex);
1078 if (i_dls_devnet_destroy_iptun(ddp->dd_linkid) != 0)
1079 ddp->dd_flags |= DD_IMPLICIT_IPTUN;
1080 return;
1081 }
1082 mutex_exit(&ddp->dd_mutex);
1083 }
1084
1085 static int
1090 major_t major;
1091 dev_t phy_dev, tmp_dev;
1092 datalink_id_t linkid;
1093 dls_dev_handle_t ddh;
1094 int err;
1095
1096 if ((err = dls_mgmt_get_linkid(link, &linkid)) == 0)
1097 return (dls_devnet_hold(linkid, ddpp));
1098
1099 /*
1100 * If we failed to get the link's linkid because the dlmgmtd daemon
1101 * has not been started, return ENOENT so that the application can
1102 * fallback to open the /dev node.
1103 */
1104 if (err == EBADF)
1105 return (ENOENT);
1106
1107 if (err != ENOENT)
1108 return (err);
1109
1110 /*
1111 * If we reach this point it means dlmgmtd is up but has no
1112 * mapping for the link name.
1113 */
1114 if (ddi_parse(link, drv, &ppa) != DDI_SUCCESS)
1115 return (ENOENT);
1116
1117 if (IS_IPTUN_LINK(drv)) {
1118 if ((err = i_dls_devnet_create_iptun(link, drv, &linkid)) != 0)
1119 return (err);
1120 /*
1121 * At this point, an IP tunnel MAC has registered, which
1122 * resulted in a link being created.
1123 */
1124 err = dls_devnet_hold(linkid, ddpp);
1125 if (err != 0) {
1126 VERIFY(i_dls_devnet_destroy_iptun(linkid) == 0);
1127 return (err);
1128 }
1129 /*
1130 * dls_devnet_rele() will know to destroy the implicit IP
1131 * tunnel on last reference release if DD_IMPLICIT_IPTUN is
1132 * set.
1133 */
1134 (*ddpp)->dd_flags |= DD_IMPLICIT_IPTUN;
1135 return (0);
1136 }
1137
1138 /*
1139 * If this link:
1140 * (a) is a physical device, (b) this is the first boot, (c) the MAC
1141 * is not registered yet, and (d) we cannot find its linkid, then the
1142 * linkname is the same as the devname.
1143 *
1144 * First filter out invalid names.
|