param.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * Copyright (c) 2016 Mellanox Technologies. All rights reserved.
  4. * Copyright (c) 2016 Jiri Pirko <jiri@mellanox.com>
  5. */
  6. #include "devl_internal.h"
  7. static const struct devlink_param devlink_param_generic[] = {
  8. {
  9. .id = DEVLINK_PARAM_GENERIC_ID_INT_ERR_RESET,
  10. .name = DEVLINK_PARAM_GENERIC_INT_ERR_RESET_NAME,
  11. .type = DEVLINK_PARAM_GENERIC_INT_ERR_RESET_TYPE,
  12. },
  13. {
  14. .id = DEVLINK_PARAM_GENERIC_ID_MAX_MACS,
  15. .name = DEVLINK_PARAM_GENERIC_MAX_MACS_NAME,
  16. .type = DEVLINK_PARAM_GENERIC_MAX_MACS_TYPE,
  17. },
  18. {
  19. .id = DEVLINK_PARAM_GENERIC_ID_ENABLE_SRIOV,
  20. .name = DEVLINK_PARAM_GENERIC_ENABLE_SRIOV_NAME,
  21. .type = DEVLINK_PARAM_GENERIC_ENABLE_SRIOV_TYPE,
  22. },
  23. {
  24. .id = DEVLINK_PARAM_GENERIC_ID_REGION_SNAPSHOT,
  25. .name = DEVLINK_PARAM_GENERIC_REGION_SNAPSHOT_NAME,
  26. .type = DEVLINK_PARAM_GENERIC_REGION_SNAPSHOT_TYPE,
  27. },
  28. {
  29. .id = DEVLINK_PARAM_GENERIC_ID_IGNORE_ARI,
  30. .name = DEVLINK_PARAM_GENERIC_IGNORE_ARI_NAME,
  31. .type = DEVLINK_PARAM_GENERIC_IGNORE_ARI_TYPE,
  32. },
  33. {
  34. .id = DEVLINK_PARAM_GENERIC_ID_MSIX_VEC_PER_PF_MAX,
  35. .name = DEVLINK_PARAM_GENERIC_MSIX_VEC_PER_PF_MAX_NAME,
  36. .type = DEVLINK_PARAM_GENERIC_MSIX_VEC_PER_PF_MAX_TYPE,
  37. },
  38. {
  39. .id = DEVLINK_PARAM_GENERIC_ID_MSIX_VEC_PER_PF_MIN,
  40. .name = DEVLINK_PARAM_GENERIC_MSIX_VEC_PER_PF_MIN_NAME,
  41. .type = DEVLINK_PARAM_GENERIC_MSIX_VEC_PER_PF_MIN_TYPE,
  42. },
  43. {
  44. .id = DEVLINK_PARAM_GENERIC_ID_FW_LOAD_POLICY,
  45. .name = DEVLINK_PARAM_GENERIC_FW_LOAD_POLICY_NAME,
  46. .type = DEVLINK_PARAM_GENERIC_FW_LOAD_POLICY_TYPE,
  47. },
  48. {
  49. .id = DEVLINK_PARAM_GENERIC_ID_RESET_DEV_ON_DRV_PROBE,
  50. .name = DEVLINK_PARAM_GENERIC_RESET_DEV_ON_DRV_PROBE_NAME,
  51. .type = DEVLINK_PARAM_GENERIC_RESET_DEV_ON_DRV_PROBE_TYPE,
  52. },
  53. {
  54. .id = DEVLINK_PARAM_GENERIC_ID_ENABLE_ROCE,
  55. .name = DEVLINK_PARAM_GENERIC_ENABLE_ROCE_NAME,
  56. .type = DEVLINK_PARAM_GENERIC_ENABLE_ROCE_TYPE,
  57. },
  58. {
  59. .id = DEVLINK_PARAM_GENERIC_ID_ENABLE_REMOTE_DEV_RESET,
  60. .name = DEVLINK_PARAM_GENERIC_ENABLE_REMOTE_DEV_RESET_NAME,
  61. .type = DEVLINK_PARAM_GENERIC_ENABLE_REMOTE_DEV_RESET_TYPE,
  62. },
  63. {
  64. .id = DEVLINK_PARAM_GENERIC_ID_ENABLE_ETH,
  65. .name = DEVLINK_PARAM_GENERIC_ENABLE_ETH_NAME,
  66. .type = DEVLINK_PARAM_GENERIC_ENABLE_ETH_TYPE,
  67. },
  68. {
  69. .id = DEVLINK_PARAM_GENERIC_ID_ENABLE_RDMA,
  70. .name = DEVLINK_PARAM_GENERIC_ENABLE_RDMA_NAME,
  71. .type = DEVLINK_PARAM_GENERIC_ENABLE_RDMA_TYPE,
  72. },
  73. {
  74. .id = DEVLINK_PARAM_GENERIC_ID_ENABLE_VNET,
  75. .name = DEVLINK_PARAM_GENERIC_ENABLE_VNET_NAME,
  76. .type = DEVLINK_PARAM_GENERIC_ENABLE_VNET_TYPE,
  77. },
  78. {
  79. .id = DEVLINK_PARAM_GENERIC_ID_ENABLE_IWARP,
  80. .name = DEVLINK_PARAM_GENERIC_ENABLE_IWARP_NAME,
  81. .type = DEVLINK_PARAM_GENERIC_ENABLE_IWARP_TYPE,
  82. },
  83. {
  84. .id = DEVLINK_PARAM_GENERIC_ID_IO_EQ_SIZE,
  85. .name = DEVLINK_PARAM_GENERIC_IO_EQ_SIZE_NAME,
  86. .type = DEVLINK_PARAM_GENERIC_IO_EQ_SIZE_TYPE,
  87. },
  88. {
  89. .id = DEVLINK_PARAM_GENERIC_ID_EVENT_EQ_SIZE,
  90. .name = DEVLINK_PARAM_GENERIC_EVENT_EQ_SIZE_NAME,
  91. .type = DEVLINK_PARAM_GENERIC_EVENT_EQ_SIZE_TYPE,
  92. },
  93. {
  94. .id = DEVLINK_PARAM_GENERIC_ID_ENABLE_PHC,
  95. .name = DEVLINK_PARAM_GENERIC_ENABLE_PHC_NAME,
  96. .type = DEVLINK_PARAM_GENERIC_ENABLE_PHC_TYPE,
  97. },
  98. {
  99. .id = DEVLINK_PARAM_GENERIC_ID_CLOCK_ID,
  100. .name = DEVLINK_PARAM_GENERIC_CLOCK_ID_NAME,
  101. .type = DEVLINK_PARAM_GENERIC_CLOCK_ID_TYPE,
  102. },
  103. {
  104. .id = DEVLINK_PARAM_GENERIC_ID_TOTAL_VFS,
  105. .name = DEVLINK_PARAM_GENERIC_TOTAL_VFS_NAME,
  106. .type = DEVLINK_PARAM_GENERIC_TOTAL_VFS_TYPE,
  107. },
  108. {
  109. .id = DEVLINK_PARAM_GENERIC_ID_NUM_DOORBELLS,
  110. .name = DEVLINK_PARAM_GENERIC_NUM_DOORBELLS_NAME,
  111. .type = DEVLINK_PARAM_GENERIC_NUM_DOORBELLS_TYPE,
  112. },
  113. {
  114. .id = DEVLINK_PARAM_GENERIC_ID_MAX_MAC_PER_VF,
  115. .name = DEVLINK_PARAM_GENERIC_MAX_MAC_PER_VF_NAME,
  116. .type = DEVLINK_PARAM_GENERIC_MAX_MAC_PER_VF_TYPE,
  117. },
  118. };
  119. static int devlink_param_generic_verify(const struct devlink_param *param)
  120. {
  121. /* verify it match generic parameter by id and name */
  122. if (param->id > DEVLINK_PARAM_GENERIC_ID_MAX)
  123. return -EINVAL;
  124. if (strcmp(param->name, devlink_param_generic[param->id].name))
  125. return -ENOENT;
  126. WARN_ON(param->type != devlink_param_generic[param->id].type);
  127. return 0;
  128. }
  129. static int devlink_param_driver_verify(const struct devlink_param *param)
  130. {
  131. int i;
  132. if (param->id <= DEVLINK_PARAM_GENERIC_ID_MAX)
  133. return -EINVAL;
  134. /* verify no such name in generic params */
  135. for (i = 0; i <= DEVLINK_PARAM_GENERIC_ID_MAX; i++)
  136. if (!strcmp(param->name, devlink_param_generic[i].name))
  137. return -EEXIST;
  138. return 0;
  139. }
  140. static struct devlink_param_item *
  141. devlink_param_find_by_name(struct xarray *params, const char *param_name)
  142. {
  143. struct devlink_param_item *param_item;
  144. unsigned long param_id;
  145. xa_for_each(params, param_id, param_item) {
  146. if (!strcmp(param_item->param->name, param_name))
  147. return param_item;
  148. }
  149. return NULL;
  150. }
  151. static struct devlink_param_item *
  152. devlink_param_find_by_id(struct xarray *params, u32 param_id)
  153. {
  154. return xa_load(params, param_id);
  155. }
  156. static bool
  157. devlink_param_cmode_is_supported(const struct devlink_param *param,
  158. enum devlink_param_cmode cmode)
  159. {
  160. return test_bit(cmode, &param->supported_cmodes);
  161. }
  162. static int devlink_param_get(struct devlink *devlink,
  163. const struct devlink_param *param,
  164. struct devlink_param_gset_ctx *ctx,
  165. struct netlink_ext_ack *extack)
  166. {
  167. if (!param->get)
  168. return -EOPNOTSUPP;
  169. return param->get(devlink, param->id, ctx, extack);
  170. }
  171. static int devlink_param_set(struct devlink *devlink,
  172. const struct devlink_param *param,
  173. struct devlink_param_gset_ctx *ctx,
  174. struct netlink_ext_ack *extack)
  175. {
  176. if (!param->set)
  177. return -EOPNOTSUPP;
  178. return param->set(devlink, param->id, ctx, extack);
  179. }
  180. static int devlink_param_get_default(struct devlink *devlink,
  181. const struct devlink_param *param,
  182. struct devlink_param_gset_ctx *ctx,
  183. struct netlink_ext_ack *extack)
  184. {
  185. if (!param->get_default)
  186. return -EOPNOTSUPP;
  187. return param->get_default(devlink, param->id, ctx, extack);
  188. }
  189. static int devlink_param_reset_default(struct devlink *devlink,
  190. const struct devlink_param *param,
  191. enum devlink_param_cmode cmode,
  192. struct netlink_ext_ack *extack)
  193. {
  194. if (!param->reset_default)
  195. return -EOPNOTSUPP;
  196. return param->reset_default(devlink, param->id, cmode, extack);
  197. }
  198. static int
  199. devlink_nl_param_value_put(struct sk_buff *msg, enum devlink_param_type type,
  200. int nla_type, union devlink_param_value val,
  201. bool flag_as_u8)
  202. {
  203. switch (type) {
  204. case DEVLINK_PARAM_TYPE_U8:
  205. if (nla_put_u8(msg, nla_type, val.vu8))
  206. return -EMSGSIZE;
  207. break;
  208. case DEVLINK_PARAM_TYPE_U16:
  209. if (nla_put_u16(msg, nla_type, val.vu16))
  210. return -EMSGSIZE;
  211. break;
  212. case DEVLINK_PARAM_TYPE_U32:
  213. if (nla_put_u32(msg, nla_type, val.vu32))
  214. return -EMSGSIZE;
  215. break;
  216. case DEVLINK_PARAM_TYPE_U64:
  217. if (devlink_nl_put_u64(msg, nla_type, val.vu64))
  218. return -EMSGSIZE;
  219. break;
  220. case DEVLINK_PARAM_TYPE_STRING:
  221. if (nla_put_string(msg, nla_type, val.vstr))
  222. return -EMSGSIZE;
  223. break;
  224. case DEVLINK_PARAM_TYPE_BOOL:
  225. /* default values of type bool are encoded with u8, so that
  226. * false can be distinguished from not present
  227. */
  228. if (flag_as_u8) {
  229. if (nla_put_u8(msg, nla_type, val.vbool))
  230. return -EMSGSIZE;
  231. } else {
  232. if (val.vbool && nla_put_flag(msg, nla_type))
  233. return -EMSGSIZE;
  234. }
  235. break;
  236. }
  237. return 0;
  238. }
  239. static int
  240. devlink_nl_param_value_fill_one(struct sk_buff *msg,
  241. enum devlink_param_type type,
  242. enum devlink_param_cmode cmode,
  243. union devlink_param_value val,
  244. union devlink_param_value default_val,
  245. bool has_default)
  246. {
  247. struct nlattr *param_value_attr;
  248. int err = -EMSGSIZE;
  249. param_value_attr = nla_nest_start_noflag(msg,
  250. DEVLINK_ATTR_PARAM_VALUE);
  251. if (!param_value_attr)
  252. return -EMSGSIZE;
  253. if (nla_put_u8(msg, DEVLINK_ATTR_PARAM_VALUE_CMODE, cmode))
  254. goto value_nest_cancel;
  255. err = devlink_nl_param_value_put(msg, type,
  256. DEVLINK_ATTR_PARAM_VALUE_DATA,
  257. val, false);
  258. if (err)
  259. goto value_nest_cancel;
  260. if (has_default) {
  261. err = devlink_nl_param_value_put(msg, type,
  262. DEVLINK_ATTR_PARAM_VALUE_DEFAULT,
  263. default_val, true);
  264. if (err)
  265. goto value_nest_cancel;
  266. }
  267. nla_nest_end(msg, param_value_attr);
  268. return 0;
  269. value_nest_cancel:
  270. nla_nest_cancel(msg, param_value_attr);
  271. return err;
  272. }
  273. static int devlink_nl_param_fill(struct sk_buff *msg, struct devlink *devlink,
  274. unsigned int port_index,
  275. struct devlink_param_item *param_item,
  276. enum devlink_command cmd,
  277. u32 portid, u32 seq, int flags,
  278. struct netlink_ext_ack *extack)
  279. {
  280. union devlink_param_value default_value[DEVLINK_PARAM_CMODE_MAX + 1];
  281. union devlink_param_value param_value[DEVLINK_PARAM_CMODE_MAX + 1];
  282. bool default_value_set[DEVLINK_PARAM_CMODE_MAX + 1] = {};
  283. bool param_value_set[DEVLINK_PARAM_CMODE_MAX + 1] = {};
  284. const struct devlink_param *param = param_item->param;
  285. struct devlink_param_gset_ctx ctx;
  286. struct nlattr *param_values_list;
  287. struct nlattr *param_attr;
  288. void *hdr;
  289. int err;
  290. int i;
  291. /* Get value from driver part to driverinit configuration mode */
  292. for (i = 0; i <= DEVLINK_PARAM_CMODE_MAX; i++) {
  293. if (!devlink_param_cmode_is_supported(param, i))
  294. continue;
  295. if (i == DEVLINK_PARAM_CMODE_DRIVERINIT) {
  296. if (param_item->driverinit_value_new_valid)
  297. param_value[i] = param_item->driverinit_value_new;
  298. else if (param_item->driverinit_value_valid)
  299. param_value[i] = param_item->driverinit_value;
  300. else
  301. return -EOPNOTSUPP;
  302. if (param_item->driverinit_value_valid) {
  303. default_value[i] = param_item->driverinit_default;
  304. default_value_set[i] = true;
  305. }
  306. } else {
  307. ctx.cmode = i;
  308. err = devlink_param_get(devlink, param, &ctx, extack);
  309. if (err)
  310. return err;
  311. param_value[i] = ctx.val;
  312. err = devlink_param_get_default(devlink, param, &ctx,
  313. extack);
  314. if (!err) {
  315. default_value[i] = ctx.val;
  316. default_value_set[i] = true;
  317. } else if (err != -EOPNOTSUPP) {
  318. return err;
  319. }
  320. }
  321. param_value_set[i] = true;
  322. }
  323. hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
  324. if (!hdr)
  325. return -EMSGSIZE;
  326. if (devlink_nl_put_handle(msg, devlink))
  327. goto genlmsg_cancel;
  328. if (cmd == DEVLINK_CMD_PORT_PARAM_GET ||
  329. cmd == DEVLINK_CMD_PORT_PARAM_NEW ||
  330. cmd == DEVLINK_CMD_PORT_PARAM_DEL)
  331. if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX, port_index))
  332. goto genlmsg_cancel;
  333. param_attr = nla_nest_start_noflag(msg, DEVLINK_ATTR_PARAM);
  334. if (!param_attr)
  335. goto genlmsg_cancel;
  336. if (nla_put_string(msg, DEVLINK_ATTR_PARAM_NAME, param->name))
  337. goto param_nest_cancel;
  338. if (param->generic && nla_put_flag(msg, DEVLINK_ATTR_PARAM_GENERIC))
  339. goto param_nest_cancel;
  340. if (nla_put_u8(msg, DEVLINK_ATTR_PARAM_TYPE, param->type))
  341. goto param_nest_cancel;
  342. param_values_list = nla_nest_start_noflag(msg,
  343. DEVLINK_ATTR_PARAM_VALUES_LIST);
  344. if (!param_values_list)
  345. goto param_nest_cancel;
  346. for (i = 0; i <= DEVLINK_PARAM_CMODE_MAX; i++) {
  347. if (!param_value_set[i])
  348. continue;
  349. err = devlink_nl_param_value_fill_one(msg, param->type,
  350. i, param_value[i],
  351. default_value[i],
  352. default_value_set[i]);
  353. if (err)
  354. goto values_list_nest_cancel;
  355. }
  356. nla_nest_end(msg, param_values_list);
  357. nla_nest_end(msg, param_attr);
  358. genlmsg_end(msg, hdr);
  359. return 0;
  360. values_list_nest_cancel:
  361. nla_nest_end(msg, param_values_list);
  362. param_nest_cancel:
  363. nla_nest_cancel(msg, param_attr);
  364. genlmsg_cancel:
  365. genlmsg_cancel(msg, hdr);
  366. return -EMSGSIZE;
  367. }
  368. static void devlink_param_notify(struct devlink *devlink,
  369. unsigned int port_index,
  370. struct devlink_param_item *param_item,
  371. enum devlink_command cmd)
  372. {
  373. struct sk_buff *msg;
  374. int err;
  375. WARN_ON(cmd != DEVLINK_CMD_PARAM_NEW && cmd != DEVLINK_CMD_PARAM_DEL &&
  376. cmd != DEVLINK_CMD_PORT_PARAM_NEW &&
  377. cmd != DEVLINK_CMD_PORT_PARAM_DEL);
  378. /* devlink_notify_register() / devlink_notify_unregister()
  379. * will replay the notifications if the params are added/removed
  380. * outside of the lifetime of the instance.
  381. */
  382. if (!devl_is_registered(devlink) || !devlink_nl_notify_need(devlink))
  383. return;
  384. msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
  385. if (!msg)
  386. return;
  387. err = devlink_nl_param_fill(msg, devlink, port_index, param_item, cmd,
  388. 0, 0, 0, NULL);
  389. if (err) {
  390. nlmsg_free(msg);
  391. return;
  392. }
  393. devlink_nl_notify_send(devlink, msg);
  394. }
  395. static void devlink_params_notify(struct devlink *devlink,
  396. enum devlink_command cmd)
  397. {
  398. struct devlink_param_item *param_item;
  399. unsigned long param_id;
  400. xa_for_each(&devlink->params, param_id, param_item)
  401. devlink_param_notify(devlink, 0, param_item, cmd);
  402. }
  403. void devlink_params_notify_register(struct devlink *devlink)
  404. {
  405. devlink_params_notify(devlink, DEVLINK_CMD_PARAM_NEW);
  406. }
  407. void devlink_params_notify_unregister(struct devlink *devlink)
  408. {
  409. devlink_params_notify(devlink, DEVLINK_CMD_PARAM_DEL);
  410. }
  411. static int devlink_nl_param_get_dump_one(struct sk_buff *msg,
  412. struct devlink *devlink,
  413. struct netlink_callback *cb,
  414. int flags)
  415. {
  416. struct devlink_nl_dump_state *state = devlink_dump_state(cb);
  417. struct devlink_param_item *param_item;
  418. unsigned long param_id;
  419. int err = 0;
  420. xa_for_each_start(&devlink->params, param_id, param_item, state->idx) {
  421. err = devlink_nl_param_fill(msg, devlink, 0, param_item,
  422. DEVLINK_CMD_PARAM_GET,
  423. NETLINK_CB(cb->skb).portid,
  424. cb->nlh->nlmsg_seq, flags,
  425. cb->extack);
  426. if (err == -EOPNOTSUPP) {
  427. err = 0;
  428. } else if (err) {
  429. state->idx = param_id;
  430. break;
  431. }
  432. }
  433. return err;
  434. }
  435. int devlink_nl_param_get_dumpit(struct sk_buff *skb,
  436. struct netlink_callback *cb)
  437. {
  438. return devlink_nl_dumpit(skb, cb, devlink_nl_param_get_dump_one);
  439. }
  440. static int
  441. devlink_param_type_get_from_info(struct genl_info *info,
  442. enum devlink_param_type *param_type)
  443. {
  444. if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_PARAM_TYPE))
  445. return -EINVAL;
  446. *param_type = nla_get_u8(info->attrs[DEVLINK_ATTR_PARAM_TYPE]);
  447. return 0;
  448. }
  449. static int
  450. devlink_param_value_get_from_info(const struct devlink_param *param,
  451. struct genl_info *info,
  452. union devlink_param_value *value)
  453. {
  454. struct nlattr *param_data;
  455. int len;
  456. param_data = info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA];
  457. if (param->type != DEVLINK_PARAM_TYPE_BOOL && !param_data)
  458. return -EINVAL;
  459. switch (param->type) {
  460. case DEVLINK_PARAM_TYPE_U8:
  461. if (nla_len(param_data) != sizeof(u8))
  462. return -EINVAL;
  463. value->vu8 = nla_get_u8(param_data);
  464. break;
  465. case DEVLINK_PARAM_TYPE_U16:
  466. if (nla_len(param_data) != sizeof(u16))
  467. return -EINVAL;
  468. value->vu16 = nla_get_u16(param_data);
  469. break;
  470. case DEVLINK_PARAM_TYPE_U32:
  471. if (nla_len(param_data) != sizeof(u32))
  472. return -EINVAL;
  473. value->vu32 = nla_get_u32(param_data);
  474. break;
  475. case DEVLINK_PARAM_TYPE_U64:
  476. if (nla_len(param_data) != sizeof(u64))
  477. return -EINVAL;
  478. value->vu64 = nla_get_u64(param_data);
  479. break;
  480. case DEVLINK_PARAM_TYPE_STRING:
  481. len = strnlen(nla_data(param_data), nla_len(param_data));
  482. if (len == nla_len(param_data) ||
  483. len >= __DEVLINK_PARAM_MAX_STRING_VALUE)
  484. return -EINVAL;
  485. strcpy(value->vstr, nla_data(param_data));
  486. break;
  487. case DEVLINK_PARAM_TYPE_BOOL:
  488. if (param_data && nla_len(param_data))
  489. return -EINVAL;
  490. value->vbool = nla_get_flag(param_data);
  491. break;
  492. }
  493. return 0;
  494. }
  495. static struct devlink_param_item *
  496. devlink_param_get_from_info(struct xarray *params, struct genl_info *info)
  497. {
  498. char *param_name;
  499. if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_PARAM_NAME))
  500. return NULL;
  501. param_name = nla_data(info->attrs[DEVLINK_ATTR_PARAM_NAME]);
  502. return devlink_param_find_by_name(params, param_name);
  503. }
  504. int devlink_nl_param_get_doit(struct sk_buff *skb,
  505. struct genl_info *info)
  506. {
  507. struct devlink *devlink = info->user_ptr[0];
  508. struct devlink_param_item *param_item;
  509. struct sk_buff *msg;
  510. int err;
  511. param_item = devlink_param_get_from_info(&devlink->params, info);
  512. if (!param_item)
  513. return -EINVAL;
  514. msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
  515. if (!msg)
  516. return -ENOMEM;
  517. err = devlink_nl_param_fill(msg, devlink, 0, param_item,
  518. DEVLINK_CMD_PARAM_GET, info->snd_portid,
  519. info->snd_seq, 0, info->extack);
  520. if (err) {
  521. nlmsg_free(msg);
  522. return err;
  523. }
  524. return genlmsg_reply(msg, info);
  525. }
  526. static int __devlink_nl_cmd_param_set_doit(struct devlink *devlink,
  527. unsigned int port_index,
  528. struct xarray *params,
  529. struct genl_info *info,
  530. enum devlink_command cmd)
  531. {
  532. enum devlink_param_type param_type;
  533. struct devlink_param_gset_ctx ctx;
  534. enum devlink_param_cmode cmode;
  535. struct devlink_param_item *param_item;
  536. const struct devlink_param *param;
  537. union devlink_param_value value;
  538. bool reset_default;
  539. int err = 0;
  540. param_item = devlink_param_get_from_info(params, info);
  541. if (!param_item)
  542. return -EINVAL;
  543. param = param_item->param;
  544. err = devlink_param_type_get_from_info(info, &param_type);
  545. if (err)
  546. return err;
  547. if (param_type != param->type)
  548. return -EINVAL;
  549. reset_default = info->attrs[DEVLINK_ATTR_PARAM_RESET_DEFAULT];
  550. if (!reset_default) {
  551. err = devlink_param_value_get_from_info(param, info, &value);
  552. if (err)
  553. return err;
  554. if (param->validate) {
  555. err = param->validate(devlink, param->id, value,
  556. info->extack);
  557. if (err)
  558. return err;
  559. }
  560. }
  561. if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_PARAM_VALUE_CMODE))
  562. return -EINVAL;
  563. cmode = nla_get_u8(info->attrs[DEVLINK_ATTR_PARAM_VALUE_CMODE]);
  564. if (!devlink_param_cmode_is_supported(param, cmode))
  565. return -EOPNOTSUPP;
  566. if (cmode == DEVLINK_PARAM_CMODE_DRIVERINIT) {
  567. if (reset_default) {
  568. if (!param_item->driverinit_value_valid) {
  569. NL_SET_ERR_MSG(info->extack,
  570. "Default value not available");
  571. return -EOPNOTSUPP;
  572. }
  573. value = param_item->driverinit_default;
  574. }
  575. param_item->driverinit_value_new = value;
  576. param_item->driverinit_value_new_valid = true;
  577. } else {
  578. if (!param->set)
  579. return -EOPNOTSUPP;
  580. ctx.val = value;
  581. ctx.cmode = cmode;
  582. if (reset_default)
  583. err = devlink_param_reset_default(devlink, param, cmode,
  584. info->extack);
  585. else
  586. err = devlink_param_set(devlink, param, &ctx,
  587. info->extack);
  588. if (err)
  589. return err;
  590. }
  591. devlink_param_notify(devlink, port_index, param_item, cmd);
  592. return 0;
  593. }
  594. int devlink_nl_param_set_doit(struct sk_buff *skb, struct genl_info *info)
  595. {
  596. struct devlink *devlink = info->user_ptr[0];
  597. return __devlink_nl_cmd_param_set_doit(devlink, 0, &devlink->params,
  598. info, DEVLINK_CMD_PARAM_NEW);
  599. }
  600. int devlink_nl_port_param_get_dumpit(struct sk_buff *msg,
  601. struct netlink_callback *cb)
  602. {
  603. NL_SET_ERR_MSG(cb->extack, "Port params are not supported");
  604. return msg->len;
  605. }
  606. int devlink_nl_port_param_get_doit(struct sk_buff *skb,
  607. struct genl_info *info)
  608. {
  609. NL_SET_ERR_MSG(info->extack, "Port params are not supported");
  610. return -EINVAL;
  611. }
  612. int devlink_nl_port_param_set_doit(struct sk_buff *skb,
  613. struct genl_info *info)
  614. {
  615. NL_SET_ERR_MSG(info->extack, "Port params are not supported");
  616. return -EINVAL;
  617. }
  618. static int devlink_param_verify(const struct devlink_param *param)
  619. {
  620. if (!param || !param->name || !param->supported_cmodes)
  621. return -EINVAL;
  622. if (param->generic)
  623. return devlink_param_generic_verify(param);
  624. else
  625. return devlink_param_driver_verify(param);
  626. }
  627. static int devlink_param_register(struct devlink *devlink,
  628. const struct devlink_param *param)
  629. {
  630. struct devlink_param_item *param_item;
  631. int err;
  632. WARN_ON(devlink_param_verify(param));
  633. WARN_ON(devlink_param_find_by_name(&devlink->params, param->name));
  634. if (param->supported_cmodes == BIT(DEVLINK_PARAM_CMODE_DRIVERINIT))
  635. WARN_ON(param->get || param->set);
  636. else
  637. WARN_ON(!param->get || !param->set);
  638. param_item = kzalloc_obj(*param_item);
  639. if (!param_item)
  640. return -ENOMEM;
  641. param_item->param = param;
  642. err = xa_insert(&devlink->params, param->id, param_item, GFP_KERNEL);
  643. if (err)
  644. goto err_xa_insert;
  645. devlink_param_notify(devlink, 0, param_item, DEVLINK_CMD_PARAM_NEW);
  646. return 0;
  647. err_xa_insert:
  648. kfree(param_item);
  649. return err;
  650. }
  651. static void devlink_param_unregister(struct devlink *devlink,
  652. const struct devlink_param *param)
  653. {
  654. struct devlink_param_item *param_item;
  655. param_item = devlink_param_find_by_id(&devlink->params, param->id);
  656. if (WARN_ON(!param_item))
  657. return;
  658. devlink_param_notify(devlink, 0, param_item, DEVLINK_CMD_PARAM_DEL);
  659. xa_erase(&devlink->params, param->id);
  660. kfree(param_item);
  661. }
  662. /**
  663. * devl_params_register - register configuration parameters
  664. *
  665. * @devlink: devlink
  666. * @params: configuration parameters array
  667. * @params_count: number of parameters provided
  668. *
  669. * Register the configuration parameters supported by the driver.
  670. */
  671. int devl_params_register(struct devlink *devlink,
  672. const struct devlink_param *params,
  673. size_t params_count)
  674. {
  675. const struct devlink_param *param = params;
  676. int i, err;
  677. lockdep_assert_held(&devlink->lock);
  678. for (i = 0; i < params_count; i++, param++) {
  679. err = devlink_param_register(devlink, param);
  680. if (err)
  681. goto rollback;
  682. }
  683. return 0;
  684. rollback:
  685. if (!i)
  686. return err;
  687. for (param--; i > 0; i--, param--)
  688. devlink_param_unregister(devlink, param);
  689. return err;
  690. }
  691. EXPORT_SYMBOL_GPL(devl_params_register);
  692. int devlink_params_register(struct devlink *devlink,
  693. const struct devlink_param *params,
  694. size_t params_count)
  695. {
  696. int err;
  697. devl_lock(devlink);
  698. err = devl_params_register(devlink, params, params_count);
  699. devl_unlock(devlink);
  700. return err;
  701. }
  702. EXPORT_SYMBOL_GPL(devlink_params_register);
  703. /**
  704. * devl_params_unregister - unregister configuration parameters
  705. * @devlink: devlink
  706. * @params: configuration parameters to unregister
  707. * @params_count: number of parameters provided
  708. */
  709. void devl_params_unregister(struct devlink *devlink,
  710. const struct devlink_param *params,
  711. size_t params_count)
  712. {
  713. const struct devlink_param *param = params;
  714. int i;
  715. lockdep_assert_held(&devlink->lock);
  716. for (i = 0; i < params_count; i++, param++)
  717. devlink_param_unregister(devlink, param);
  718. }
  719. EXPORT_SYMBOL_GPL(devl_params_unregister);
  720. void devlink_params_unregister(struct devlink *devlink,
  721. const struct devlink_param *params,
  722. size_t params_count)
  723. {
  724. devl_lock(devlink);
  725. devl_params_unregister(devlink, params, params_count);
  726. devl_unlock(devlink);
  727. }
  728. EXPORT_SYMBOL_GPL(devlink_params_unregister);
  729. /**
  730. * devl_param_driverinit_value_get - get configuration parameter
  731. * value for driver initializing
  732. *
  733. * @devlink: devlink
  734. * @param_id: parameter ID
  735. * @val: pointer to store the value of parameter in driverinit
  736. * configuration mode
  737. *
  738. * This function should be used by the driver to get driverinit
  739. * configuration for initialization after reload command.
  740. *
  741. * Note that lockless call of this function relies on the
  742. * driver to maintain following basic sane behavior:
  743. * 1) Driver ensures a call to this function cannot race with
  744. * registering/unregistering the parameter with the same parameter ID.
  745. * 2) Driver ensures a call to this function cannot race with
  746. * devl_param_driverinit_value_set() call with the same parameter ID.
  747. * 3) Driver ensures a call to this function cannot race with
  748. * reload operation.
  749. * If the driver is not able to comply, it has to take the devlink->lock
  750. * while calling this.
  751. */
  752. int devl_param_driverinit_value_get(struct devlink *devlink, u32 param_id,
  753. union devlink_param_value *val)
  754. {
  755. struct devlink_param_item *param_item;
  756. if (WARN_ON(!devlink_reload_supported(devlink->ops)))
  757. return -EOPNOTSUPP;
  758. param_item = devlink_param_find_by_id(&devlink->params, param_id);
  759. if (!param_item)
  760. return -EINVAL;
  761. if (!param_item->driverinit_value_valid)
  762. return -EOPNOTSUPP;
  763. if (WARN_ON(!devlink_param_cmode_is_supported(param_item->param,
  764. DEVLINK_PARAM_CMODE_DRIVERINIT)))
  765. return -EOPNOTSUPP;
  766. *val = param_item->driverinit_value;
  767. return 0;
  768. }
  769. EXPORT_SYMBOL_GPL(devl_param_driverinit_value_get);
  770. /**
  771. * devl_param_driverinit_value_set - set value of configuration
  772. * parameter for driverinit
  773. * configuration mode
  774. *
  775. * @devlink: devlink
  776. * @param_id: parameter ID
  777. * @init_val: value of parameter to set for driverinit configuration mode
  778. *
  779. * This function should be used by the driver to set driverinit
  780. * configuration mode default value.
  781. */
  782. void devl_param_driverinit_value_set(struct devlink *devlink, u32 param_id,
  783. union devlink_param_value init_val)
  784. {
  785. struct devlink_param_item *param_item;
  786. devl_assert_locked(devlink);
  787. param_item = devlink_param_find_by_id(&devlink->params, param_id);
  788. if (WARN_ON(!param_item))
  789. return;
  790. if (WARN_ON(!devlink_param_cmode_is_supported(param_item->param,
  791. DEVLINK_PARAM_CMODE_DRIVERINIT)))
  792. return;
  793. param_item->driverinit_value = init_val;
  794. param_item->driverinit_value_valid = true;
  795. param_item->driverinit_default = init_val;
  796. devlink_param_notify(devlink, 0, param_item, DEVLINK_CMD_PARAM_NEW);
  797. }
  798. EXPORT_SYMBOL_GPL(devl_param_driverinit_value_set);
  799. void devlink_params_driverinit_load_new(struct devlink *devlink)
  800. {
  801. struct devlink_param_item *param_item;
  802. unsigned long param_id;
  803. xa_for_each(&devlink->params, param_id, param_item) {
  804. if (!devlink_param_cmode_is_supported(param_item->param,
  805. DEVLINK_PARAM_CMODE_DRIVERINIT) ||
  806. !param_item->driverinit_value_new_valid)
  807. continue;
  808. param_item->driverinit_value = param_item->driverinit_value_new;
  809. param_item->driverinit_value_valid = true;
  810. param_item->driverinit_value_new_valid = false;
  811. }
  812. }
  813. /**
  814. * devl_param_value_changed - notify devlink on a parameter's value
  815. * change. Should be called by the driver
  816. * right after the change.
  817. *
  818. * @devlink: devlink
  819. * @param_id: parameter ID
  820. *
  821. * This function should be used by the driver to notify devlink on value
  822. * change, excluding driverinit configuration mode.
  823. * For driverinit configuration mode driver should use the function
  824. */
  825. void devl_param_value_changed(struct devlink *devlink, u32 param_id)
  826. {
  827. struct devlink_param_item *param_item;
  828. param_item = devlink_param_find_by_id(&devlink->params, param_id);
  829. WARN_ON(!param_item);
  830. devlink_param_notify(devlink, 0, param_item, DEVLINK_CMD_PARAM_NEW);
  831. }
  832. EXPORT_SYMBOL_GPL(devl_param_value_changed);