1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright 2022-2025 NXP 4 * Copyright 2024 Furong Xu <0x1207@gmail.com> 5 */ 6 #include "common.h" 7 #include "netlink.h" 8 9 struct mm_req_info { 10 struct ethnl_req_info base; 11 }; 12 13 struct mm_reply_data { 14 struct ethnl_reply_data base; 15 struct ethtool_mm_state state; 16 struct ethtool_mm_stats stats; 17 }; 18 19 #define MM_REPDATA(__reply_base) \ 20 container_of(__reply_base, struct mm_reply_data, base) 21 22 #define ETHTOOL_MM_STAT_CNT \ 23 (__ETHTOOL_A_MM_STAT_CNT - (ETHTOOL_A_MM_STAT_PAD + 1)) 24 25 const struct nla_policy ethnl_mm_get_policy[ETHTOOL_A_MM_HEADER + 1] = { 26 [ETHTOOL_A_MM_HEADER] = NLA_POLICY_NESTED(ethnl_header_policy_stats), 27 }; 28 29 static int mm_prepare_data(const struct ethnl_req_info *req_base, 30 struct ethnl_reply_data *reply_base, 31 const struct genl_info *info) 32 { 33 struct mm_reply_data *data = MM_REPDATA(reply_base); 34 struct net_device *dev = reply_base->dev; 35 const struct ethtool_ops *ops; 36 int ret; 37 38 ops = dev->ethtool_ops; 39 40 if (!ops->get_mm) 41 return -EOPNOTSUPP; 42 43 ethtool_stats_init((u64 *)&data->stats, 44 sizeof(data->stats) / sizeof(u64)); 45 46 ret = ethnl_ops_begin(dev); 47 if (ret < 0) 48 return ret; 49 50 ret = ops->get_mm(dev, &data->state); 51 if (ret) 52 goto out_complete; 53 54 if (ops->get_mm_stats && (req_base->flags & ETHTOOL_FLAG_STATS)) 55 ops->get_mm_stats(dev, &data->stats); 56 57 out_complete: 58 ethnl_ops_complete(dev); 59 60 return ret; 61 } 62 63 static int mm_reply_size(const struct ethnl_req_info *req_base, 64 const struct ethnl_reply_data *reply_base) 65 { 66 int len = 0; 67 68 len += nla_total_size(sizeof(u8)); /* _MM_PMAC_ENABLED */ 69 len += nla_total_size(sizeof(u8)); /* _MM_TX_ENABLED */ 70 len += nla_total_size(sizeof(u8)); /* _MM_TX_ACTIVE */ 71 len += nla_total_size(sizeof(u8)); /* _MM_VERIFY_ENABLED */ 72 len += nla_total_size(sizeof(u8)); /* _MM_VERIFY_STATUS */ 73 len += nla_total_size(sizeof(u32)); /* _MM_VERIFY_TIME */ 74 len += nla_total_size(sizeof(u32)); /* _MM_MAX_VERIFY_TIME */ 75 len += nla_total_size(sizeof(u32)); /* _MM_TX_MIN_FRAG_SIZE */ 76 len += nla_total_size(sizeof(u32)); /* _MM_RX_MIN_FRAG_SIZE */ 77 78 if (req_base->flags & ETHTOOL_FLAG_STATS) 79 len += nla_total_size(0) + /* _MM_STATS */ 80 nla_total_size_64bit(sizeof(u64)) * ETHTOOL_MM_STAT_CNT; 81 82 return len; 83 } 84 85 static int mm_put_stat(struct sk_buff *skb, u64 val, u16 attrtype) 86 { 87 if (val == ETHTOOL_STAT_NOT_SET) 88 return 0; 89 if (nla_put_u64_64bit(skb, attrtype, val, ETHTOOL_A_MM_STAT_PAD)) 90 return -EMSGSIZE; 91 return 0; 92 } 93 94 static int mm_put_stats(struct sk_buff *skb, 95 const struct ethtool_mm_stats *stats) 96 { 97 struct nlattr *nest; 98 99 nest = nla_nest_start(skb, ETHTOOL_A_MM_STATS); 100 if (!nest) 101 return -EMSGSIZE; 102 103 if (mm_put_stat(skb, stats->MACMergeFrameAssErrorCount, 104 ETHTOOL_A_MM_STAT_REASSEMBLY_ERRORS) || 105 mm_put_stat(skb, stats->MACMergeFrameSmdErrorCount, 106 ETHTOOL_A_MM_STAT_SMD_ERRORS) || 107 mm_put_stat(skb, stats->MACMergeFrameAssOkCount, 108 ETHTOOL_A_MM_STAT_REASSEMBLY_OK) || 109 mm_put_stat(skb, stats->MACMergeFragCountRx, 110 ETHTOOL_A_MM_STAT_RX_FRAG_COUNT) || 111 mm_put_stat(skb, stats->MACMergeFragCountTx, 112 ETHTOOL_A_MM_STAT_TX_FRAG_COUNT) || 113 mm_put_stat(skb, stats->MACMergeHoldCount, 114 ETHTOOL_A_MM_STAT_HOLD_COUNT)) 115 goto err_cancel; 116 117 nla_nest_end(skb, nest); 118 return 0; 119 120 err_cancel: 121 nla_nest_cancel(skb, nest); 122 return -EMSGSIZE; 123 } 124 125 static int mm_fill_reply(struct sk_buff *skb, 126 const struct ethnl_req_info *req_base, 127 const struct ethnl_reply_data *reply_base) 128 { 129 const struct mm_reply_data *data = MM_REPDATA(reply_base); 130 const struct ethtool_mm_state *state = &data->state; 131 132 if (nla_put_u8(skb, ETHTOOL_A_MM_TX_ENABLED, state->tx_enabled) || 133 nla_put_u8(skb, ETHTOOL_A_MM_TX_ACTIVE, state->tx_active) || 134 nla_put_u8(skb, ETHTOOL_A_MM_PMAC_ENABLED, state->pmac_enabled) || 135 nla_put_u8(skb, ETHTOOL_A_MM_VERIFY_ENABLED, state->verify_enabled) || 136 nla_put_u8(skb, ETHTOOL_A_MM_VERIFY_STATUS, state->verify_status) || 137 nla_put_u32(skb, ETHTOOL_A_MM_VERIFY_TIME, state->verify_time) || 138 nla_put_u32(skb, ETHTOOL_A_MM_MAX_VERIFY_TIME, state->max_verify_time) || 139 nla_put_u32(skb, ETHTOOL_A_MM_TX_MIN_FRAG_SIZE, state->tx_min_frag_size) || 140 nla_put_u32(skb, ETHTOOL_A_MM_RX_MIN_FRAG_SIZE, state->rx_min_frag_size)) 141 return -EMSGSIZE; 142 143 if (req_base->flags & ETHTOOL_FLAG_STATS && 144 mm_put_stats(skb, &data->stats)) 145 return -EMSGSIZE; 146 147 return 0; 148 } 149 150 const struct nla_policy ethnl_mm_set_policy[ETHTOOL_A_MM_MAX + 1] = { 151 [ETHTOOL_A_MM_HEADER] = NLA_POLICY_NESTED(ethnl_header_policy), 152 [ETHTOOL_A_MM_VERIFY_ENABLED] = NLA_POLICY_MAX(NLA_U8, 1), 153 [ETHTOOL_A_MM_VERIFY_TIME] = NLA_POLICY_RANGE(NLA_U32, 1, 128), 154 [ETHTOOL_A_MM_TX_ENABLED] = NLA_POLICY_MAX(NLA_U8, 1), 155 [ETHTOOL_A_MM_PMAC_ENABLED] = NLA_POLICY_MAX(NLA_U8, 1), 156 [ETHTOOL_A_MM_TX_MIN_FRAG_SIZE] = NLA_POLICY_RANGE(NLA_U32, 60, 252), 157 }; 158 159 static void mm_state_to_cfg(const struct ethtool_mm_state *state, 160 struct ethtool_mm_cfg *cfg) 161 { 162 /* We could also compare state->verify_status against 163 * ETHTOOL_MM_VERIFY_STATUS_DISABLED, but state->verify_enabled 164 * is more like an administrative state which should be seen in 165 * ETHTOOL_MSG_MM_GET replies. For example, a port with verification 166 * disabled might be in the ETHTOOL_MM_VERIFY_STATUS_INITIAL 167 * if it's down. 168 */ 169 cfg->verify_enabled = state->verify_enabled; 170 cfg->verify_time = state->verify_time; 171 cfg->tx_enabled = state->tx_enabled; 172 cfg->pmac_enabled = state->pmac_enabled; 173 cfg->tx_min_frag_size = state->tx_min_frag_size; 174 } 175 176 static int 177 ethnl_set_mm_validate(struct ethnl_req_info *req_info, struct genl_info *info) 178 { 179 const struct ethtool_ops *ops = req_info->dev->ethtool_ops; 180 181 return ops->get_mm && ops->set_mm ? 1 : -EOPNOTSUPP; 182 } 183 184 static int ethnl_set_mm(struct ethnl_req_info *req_info, struct genl_info *info) 185 { 186 struct netlink_ext_ack *extack = info->extack; 187 struct net_device *dev = req_info->dev; 188 struct ethtool_mm_state state = {}; 189 struct nlattr **tb = info->attrs; 190 struct ethtool_mm_cfg cfg = {}; 191 bool mod = false; 192 int ret; 193 194 ret = dev->ethtool_ops->get_mm(dev, &state); 195 if (ret) 196 return ret; 197 198 mm_state_to_cfg(&state, &cfg); 199 200 ethnl_update_bool(&cfg.verify_enabled, tb[ETHTOOL_A_MM_VERIFY_ENABLED], 201 &mod); 202 ethnl_update_u32(&cfg.verify_time, tb[ETHTOOL_A_MM_VERIFY_TIME], &mod); 203 ethnl_update_bool(&cfg.tx_enabled, tb[ETHTOOL_A_MM_TX_ENABLED], &mod); 204 ethnl_update_bool(&cfg.pmac_enabled, tb[ETHTOOL_A_MM_PMAC_ENABLED], 205 &mod); 206 ethnl_update_u32(&cfg.tx_min_frag_size, 207 tb[ETHTOOL_A_MM_TX_MIN_FRAG_SIZE], &mod); 208 209 if (!mod) 210 return 0; 211 212 if (cfg.verify_time > state.max_verify_time) { 213 NL_SET_ERR_MSG_ATTR(extack, tb[ETHTOOL_A_MM_VERIFY_TIME], 214 "verifyTime exceeds device maximum"); 215 return -ERANGE; 216 } 217 218 if (cfg.verify_enabled && !cfg.tx_enabled) { 219 NL_SET_ERR_MSG(extack, "Verification requires TX enabled"); 220 return -EINVAL; 221 } 222 223 if (cfg.tx_enabled && !cfg.pmac_enabled) { 224 NL_SET_ERR_MSG(extack, "TX enabled requires pMAC enabled"); 225 return -EINVAL; 226 } 227 228 ret = dev->ethtool_ops->set_mm(dev, &cfg, extack); 229 return ret < 0 ? ret : 1; 230 } 231 232 const struct ethnl_request_ops ethnl_mm_request_ops = { 233 .request_cmd = ETHTOOL_MSG_MM_GET, 234 .reply_cmd = ETHTOOL_MSG_MM_GET_REPLY, 235 .hdr_attr = ETHTOOL_A_MM_HEADER, 236 .req_info_size = sizeof(struct mm_req_info), 237 .reply_data_size = sizeof(struct mm_reply_data), 238 239 .prepare_data = mm_prepare_data, 240 .reply_size = mm_reply_size, 241 .fill_reply = mm_fill_reply, 242 243 .set_validate = ethnl_set_mm_validate, 244 .set = ethnl_set_mm, 245 .set_ntf_cmd = ETHTOOL_MSG_MM_NTF, 246 }; 247 248 /* Returns whether a given device supports the MAC merge layer 249 * (has an eMAC and a pMAC). Must be called under whichever lock 250 * netdev_assert_locked_ops_compat() accepts (rtnl for traditional drivers, 251 * the netdev instance lock for ops-locked ones) and ethnl_ops_begin(). 252 */ 253 bool __ethtool_dev_mm_supported(struct net_device *dev) 254 { 255 const struct ethtool_ops *ops = dev->ethtool_ops; 256 struct ethtool_mm_state state = {}; 257 int ret = -EOPNOTSUPP; 258 259 if (ops && ops->get_mm) 260 ret = ops->get_mm(dev, &state); 261 262 return !ret; 263 } 264 265 bool ethtool_dev_mm_supported(struct net_device *dev) 266 { 267 const struct ethtool_ops *ops = dev->ethtool_ops; 268 bool supported; 269 int ret; 270 271 ASSERT_RTNL(); 272 273 if (!ops) 274 return false; 275 276 ret = ethnl_ops_begin(dev); 277 if (ret < 0) 278 return false; 279 280 supported = __ethtool_dev_mm_supported(dev); 281 282 ethnl_ops_complete(dev); 283 284 return supported; 285 } 286 EXPORT_SYMBOL_GPL(ethtool_dev_mm_supported); 287 288 static void ethtool_mmsv_configure_tx(struct ethtool_mmsv *mmsv, 289 bool tx_active) 290 { 291 if (mmsv->ops->configure_tx) 292 mmsv->ops->configure_tx(mmsv, tx_active); 293 } 294 295 static void ethtool_mmsv_configure_pmac(struct ethtool_mmsv *mmsv, 296 bool pmac_enabled) 297 { 298 if (mmsv->ops->configure_pmac) 299 mmsv->ops->configure_pmac(mmsv, pmac_enabled); 300 } 301 302 static void ethtool_mmsv_send_mpacket(struct ethtool_mmsv *mmsv, 303 enum ethtool_mpacket mpacket) 304 { 305 if (mmsv->ops->send_mpacket) 306 mmsv->ops->send_mpacket(mmsv, mpacket); 307 } 308 309 /** 310 * ethtool_mmsv_verify_timer - Timer for MAC Merge verification 311 * @t: timer_list struct containing private info 312 * 313 * Verify the MAC Merge capability in the local TX direction, by 314 * transmitting Verify mPackets up to 3 times. Wait until link 315 * partner responds with a Response mPacket, otherwise fail. 316 */ 317 static void ethtool_mmsv_verify_timer(struct timer_list *t) 318 { 319 struct ethtool_mmsv *mmsv = timer_container_of(mmsv, t, verify_timer); 320 unsigned long flags; 321 bool rearm = false; 322 323 spin_lock_irqsave(&mmsv->lock, flags); 324 325 switch (mmsv->status) { 326 case ETHTOOL_MM_VERIFY_STATUS_INITIAL: 327 case ETHTOOL_MM_VERIFY_STATUS_VERIFYING: 328 if (mmsv->verify_retries != 0) { 329 ethtool_mmsv_send_mpacket(mmsv, ETHTOOL_MPACKET_VERIFY); 330 rearm = true; 331 } else { 332 mmsv->status = ETHTOOL_MM_VERIFY_STATUS_FAILED; 333 } 334 335 mmsv->verify_retries--; 336 break; 337 338 case ETHTOOL_MM_VERIFY_STATUS_SUCCEEDED: 339 ethtool_mmsv_configure_tx(mmsv, true); 340 break; 341 342 default: 343 break; 344 } 345 346 if (rearm) { 347 mod_timer(&mmsv->verify_timer, 348 jiffies + msecs_to_jiffies(mmsv->verify_time)); 349 } 350 351 spin_unlock_irqrestore(&mmsv->lock, flags); 352 } 353 354 static void ethtool_mmsv_verify_timer_arm(struct ethtool_mmsv *mmsv) 355 { 356 if (mmsv->pmac_enabled && mmsv->tx_enabled && mmsv->verify_enabled && 357 mmsv->status != ETHTOOL_MM_VERIFY_STATUS_FAILED && 358 mmsv->status != ETHTOOL_MM_VERIFY_STATUS_SUCCEEDED) { 359 timer_setup(&mmsv->verify_timer, ethtool_mmsv_verify_timer, 0); 360 mod_timer(&mmsv->verify_timer, jiffies); 361 } 362 } 363 364 static void ethtool_mmsv_apply(struct ethtool_mmsv *mmsv) 365 { 366 /* If verification is disabled, configure FPE right away. 367 * Otherwise let the timer code do it. 368 */ 369 if (!mmsv->verify_enabled) { 370 ethtool_mmsv_configure_pmac(mmsv, mmsv->pmac_enabled); 371 ethtool_mmsv_configure_tx(mmsv, mmsv->tx_enabled); 372 } else { 373 mmsv->status = ETHTOOL_MM_VERIFY_STATUS_INITIAL; 374 mmsv->verify_retries = ETHTOOL_MM_MAX_VERIFY_RETRIES; 375 376 if (netif_running(mmsv->dev)) 377 ethtool_mmsv_verify_timer_arm(mmsv); 378 } 379 } 380 381 /** 382 * ethtool_mmsv_stop() - Stop MAC Merge Software Verification 383 * @mmsv: MAC Merge Software Verification state 384 * 385 * Drivers should call this method in a state where the hardware is 386 * about to lose state, like ndo_stop() or suspend(), and turning off 387 * MAC Merge features would be superfluous. Otherwise, prefer 388 * ethtool_mmsv_link_state_handle() with up=false. 389 */ 390 void ethtool_mmsv_stop(struct ethtool_mmsv *mmsv) 391 { 392 timer_shutdown_sync(&mmsv->verify_timer); 393 } 394 EXPORT_SYMBOL_GPL(ethtool_mmsv_stop); 395 396 /** 397 * ethtool_mmsv_link_state_handle() - Inform MAC Merge Software Verification 398 * of link state changes 399 * @mmsv: MAC Merge Software Verification state 400 * @up: True if device carrier is up and able to pass verification packets 401 * 402 * Calling context is expected to be from a task, interrupts enabled. 403 */ 404 void ethtool_mmsv_link_state_handle(struct ethtool_mmsv *mmsv, bool up) 405 { 406 unsigned long flags; 407 408 ethtool_mmsv_stop(mmsv); 409 410 spin_lock_irqsave(&mmsv->lock, flags); 411 412 if (up && mmsv->pmac_enabled) { 413 /* VERIFY process requires pMAC enabled when NIC comes up */ 414 ethtool_mmsv_configure_pmac(mmsv, true); 415 416 /* New link => maybe new partner => new verification process */ 417 ethtool_mmsv_apply(mmsv); 418 } else { 419 /* Reset the reported verification state while the link is down */ 420 if (mmsv->verify_enabled) 421 mmsv->status = ETHTOOL_MM_VERIFY_STATUS_INITIAL; 422 423 /* No link or pMAC not enabled */ 424 ethtool_mmsv_configure_pmac(mmsv, false); 425 ethtool_mmsv_configure_tx(mmsv, false); 426 } 427 428 spin_unlock_irqrestore(&mmsv->lock, flags); 429 } 430 EXPORT_SYMBOL_GPL(ethtool_mmsv_link_state_handle); 431 432 /** 433 * ethtool_mmsv_event_handle() - Inform MAC Merge Software Verification 434 * of interrupt-based events 435 * @mmsv: MAC Merge Software Verification state 436 * @event: Event which took place (packet transmission or reception) 437 * 438 * Calling context expects to have interrupts disabled. 439 */ 440 void ethtool_mmsv_event_handle(struct ethtool_mmsv *mmsv, 441 enum ethtool_mmsv_event event) 442 { 443 /* This is interrupt context, just spin_lock() */ 444 spin_lock(&mmsv->lock); 445 446 if (!mmsv->pmac_enabled) 447 goto unlock; 448 449 switch (event) { 450 case ETHTOOL_MMSV_LP_SENT_VERIFY_MPACKET: 451 /* Link partner has sent verify mPacket */ 452 ethtool_mmsv_send_mpacket(mmsv, ETHTOOL_MPACKET_RESPONSE); 453 break; 454 case ETHTOOL_MMSV_LD_SENT_VERIFY_MPACKET: 455 /* Local device has sent verify mPacket */ 456 if (mmsv->status != ETHTOOL_MM_VERIFY_STATUS_SUCCEEDED) 457 mmsv->status = ETHTOOL_MM_VERIFY_STATUS_VERIFYING; 458 break; 459 case ETHTOOL_MMSV_LP_SENT_RESPONSE_MPACKET: 460 /* Link partner has sent response mPacket */ 461 if (mmsv->status == ETHTOOL_MM_VERIFY_STATUS_VERIFYING) 462 mmsv->status = ETHTOOL_MM_VERIFY_STATUS_SUCCEEDED; 463 break; 464 } 465 466 unlock: 467 spin_unlock(&mmsv->lock); 468 } 469 EXPORT_SYMBOL_GPL(ethtool_mmsv_event_handle); 470 471 static bool ethtool_mmsv_is_tx_active(struct ethtool_mmsv *mmsv) 472 { 473 /* TX is active if administratively enabled, and verification either 474 * succeeded, or was administratively disabled. 475 */ 476 return mmsv->tx_enabled && 477 (mmsv->status == ETHTOOL_MM_VERIFY_STATUS_SUCCEEDED || 478 mmsv->status == ETHTOOL_MM_VERIFY_STATUS_DISABLED); 479 } 480 481 /** 482 * ethtool_mmsv_get_mm() - get_mm() hook for MAC Merge Software Verification 483 * @mmsv: MAC Merge Software Verification state 484 * @state: see struct ethtool_mm_state 485 * 486 * Drivers are expected to call this from their ethtool_ops :: get_mm() 487 * method. 488 */ 489 void ethtool_mmsv_get_mm(struct ethtool_mmsv *mmsv, 490 struct ethtool_mm_state *state) 491 { 492 unsigned long flags; 493 494 spin_lock_irqsave(&mmsv->lock, flags); 495 496 state->max_verify_time = ETHTOOL_MM_MAX_VERIFY_TIME_MS; 497 state->verify_enabled = mmsv->verify_enabled; 498 state->pmac_enabled = mmsv->pmac_enabled; 499 state->verify_time = mmsv->verify_time; 500 state->tx_enabled = mmsv->tx_enabled; 501 state->verify_status = mmsv->status; 502 state->tx_active = ethtool_mmsv_is_tx_active(mmsv); 503 504 spin_unlock_irqrestore(&mmsv->lock, flags); 505 } 506 EXPORT_SYMBOL_GPL(ethtool_mmsv_get_mm); 507 508 /** 509 * ethtool_mmsv_set_mm() - set_mm() hook for MAC Merge Software Verification 510 * @mmsv: MAC Merge Software Verification state 511 * @cfg: see struct ethtool_mm_cfg 512 * 513 * Drivers are expected to call this from their ethtool_ops :: set_mm() 514 * method. 515 */ 516 void ethtool_mmsv_set_mm(struct ethtool_mmsv *mmsv, struct ethtool_mm_cfg *cfg) 517 { 518 unsigned long flags; 519 520 /* Wait for the verification that's currently in progress to finish */ 521 ethtool_mmsv_stop(mmsv); 522 523 spin_lock_irqsave(&mmsv->lock, flags); 524 525 mmsv->verify_enabled = cfg->verify_enabled; 526 mmsv->pmac_enabled = cfg->pmac_enabled; 527 mmsv->verify_time = cfg->verify_time; 528 mmsv->tx_enabled = cfg->tx_enabled; 529 530 if (!cfg->verify_enabled) 531 mmsv->status = ETHTOOL_MM_VERIFY_STATUS_DISABLED; 532 533 ethtool_mmsv_apply(mmsv); 534 535 spin_unlock_irqrestore(&mmsv->lock, flags); 536 } 537 EXPORT_SYMBOL_GPL(ethtool_mmsv_set_mm); 538 539 /** 540 * ethtool_mmsv_init() - Initialize MAC Merge Software Verification state 541 * @mmsv: MAC Merge Software Verification state 542 * @dev: Pointer to network interface 543 * @ops: Methods for implementing the generic functionality 544 * 545 * The MAC Merge Software Verification is a timer- and event-based state 546 * machine intended for network interfaces which lack a hardware-based 547 * TX verification process (as per IEEE 802.3 clause 99.4.3). The timer 548 * is managed by the core code, whereas events are supplied by the 549 * driver explicitly calling one of the other API functions. 550 */ 551 void ethtool_mmsv_init(struct ethtool_mmsv *mmsv, struct net_device *dev, 552 const struct ethtool_mmsv_ops *ops) 553 { 554 mmsv->ops = ops; 555 mmsv->dev = dev; 556 mmsv->verify_retries = ETHTOOL_MM_MAX_VERIFY_RETRIES; 557 mmsv->verify_time = ETHTOOL_MM_MAX_VERIFY_TIME_MS; 558 mmsv->status = ETHTOOL_MM_VERIFY_STATUS_DISABLED; 559 timer_setup(&mmsv->verify_timer, ethtool_mmsv_verify_timer, 0); 560 spin_lock_init(&mmsv->lock); 561 } 562 EXPORT_SYMBOL_GPL(ethtool_mmsv_init); 563