param.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865
  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. static int devlink_param_generic_verify(const struct devlink_param *param)
  95. {
  96. /* verify it match generic parameter by id and name */
  97. if (param->id > DEVLINK_PARAM_GENERIC_ID_MAX)
  98. return -EINVAL;
  99. if (strcmp(param->name, devlink_param_generic[param->id].name))
  100. return -ENOENT;
  101. WARN_ON(param->type != devlink_param_generic[param->id].type);
  102. return 0;
  103. }
  104. static int devlink_param_driver_verify(const struct devlink_param *param)
  105. {
  106. int i;
  107. if (param->id <= DEVLINK_PARAM_GENERIC_ID_MAX)
  108. return -EINVAL;
  109. /* verify no such name in generic params */
  110. for (i = 0; i <= DEVLINK_PARAM_GENERIC_ID_MAX; i++)
  111. if (!strcmp(param->name, devlink_param_generic[i].name))
  112. return -EEXIST;
  113. return 0;
  114. }
  115. static struct devlink_param_item *
  116. devlink_param_find_by_name(struct xarray *params, const char *param_name)
  117. {
  118. struct devlink_param_item *param_item;
  119. unsigned long param_id;
  120. xa_for_each(params, param_id, param_item) {
  121. if (!strcmp(param_item->param->name, param_name))
  122. return param_item;
  123. }
  124. return NULL;
  125. }
  126. static struct devlink_param_item *
  127. devlink_param_find_by_id(struct xarray *params, u32 param_id)
  128. {
  129. return xa_load(params, param_id);
  130. }
  131. static bool
  132. devlink_param_cmode_is_supported(const struct devlink_param *param,
  133. enum devlink_param_cmode cmode)
  134. {
  135. return test_bit(cmode, &param->supported_cmodes);
  136. }
  137. static int devlink_param_get(struct devlink *devlink,
  138. const struct devlink_param *param,
  139. struct devlink_param_gset_ctx *ctx)
  140. {
  141. if (!param->get)
  142. return -EOPNOTSUPP;
  143. return param->get(devlink, param->id, ctx);
  144. }
  145. static int devlink_param_set(struct devlink *devlink,
  146. const struct devlink_param *param,
  147. struct devlink_param_gset_ctx *ctx,
  148. struct netlink_ext_ack *extack)
  149. {
  150. if (!param->set)
  151. return -EOPNOTSUPP;
  152. return param->set(devlink, param->id, ctx, extack);
  153. }
  154. static int
  155. devlink_param_type_to_nla_type(enum devlink_param_type param_type)
  156. {
  157. switch (param_type) {
  158. case DEVLINK_PARAM_TYPE_U8:
  159. return NLA_U8;
  160. case DEVLINK_PARAM_TYPE_U16:
  161. return NLA_U16;
  162. case DEVLINK_PARAM_TYPE_U32:
  163. return NLA_U32;
  164. case DEVLINK_PARAM_TYPE_STRING:
  165. return NLA_STRING;
  166. case DEVLINK_PARAM_TYPE_BOOL:
  167. return NLA_FLAG;
  168. default:
  169. return -EINVAL;
  170. }
  171. }
  172. static int
  173. devlink_nl_param_value_fill_one(struct sk_buff *msg,
  174. enum devlink_param_type type,
  175. enum devlink_param_cmode cmode,
  176. union devlink_param_value val)
  177. {
  178. struct nlattr *param_value_attr;
  179. param_value_attr = nla_nest_start_noflag(msg,
  180. DEVLINK_ATTR_PARAM_VALUE);
  181. if (!param_value_attr)
  182. goto nla_put_failure;
  183. if (nla_put_u8(msg, DEVLINK_ATTR_PARAM_VALUE_CMODE, cmode))
  184. goto value_nest_cancel;
  185. switch (type) {
  186. case DEVLINK_PARAM_TYPE_U8:
  187. if (nla_put_u8(msg, DEVLINK_ATTR_PARAM_VALUE_DATA, val.vu8))
  188. goto value_nest_cancel;
  189. break;
  190. case DEVLINK_PARAM_TYPE_U16:
  191. if (nla_put_u16(msg, DEVLINK_ATTR_PARAM_VALUE_DATA, val.vu16))
  192. goto value_nest_cancel;
  193. break;
  194. case DEVLINK_PARAM_TYPE_U32:
  195. if (nla_put_u32(msg, DEVLINK_ATTR_PARAM_VALUE_DATA, val.vu32))
  196. goto value_nest_cancel;
  197. break;
  198. case DEVLINK_PARAM_TYPE_STRING:
  199. if (nla_put_string(msg, DEVLINK_ATTR_PARAM_VALUE_DATA,
  200. val.vstr))
  201. goto value_nest_cancel;
  202. break;
  203. case DEVLINK_PARAM_TYPE_BOOL:
  204. if (val.vbool &&
  205. nla_put_flag(msg, DEVLINK_ATTR_PARAM_VALUE_DATA))
  206. goto value_nest_cancel;
  207. break;
  208. }
  209. nla_nest_end(msg, param_value_attr);
  210. return 0;
  211. value_nest_cancel:
  212. nla_nest_cancel(msg, param_value_attr);
  213. nla_put_failure:
  214. return -EMSGSIZE;
  215. }
  216. static int devlink_nl_param_fill(struct sk_buff *msg, struct devlink *devlink,
  217. unsigned int port_index,
  218. struct devlink_param_item *param_item,
  219. enum devlink_command cmd,
  220. u32 portid, u32 seq, int flags)
  221. {
  222. union devlink_param_value param_value[DEVLINK_PARAM_CMODE_MAX + 1];
  223. bool param_value_set[DEVLINK_PARAM_CMODE_MAX + 1] = {};
  224. const struct devlink_param *param = param_item->param;
  225. struct devlink_param_gset_ctx ctx;
  226. struct nlattr *param_values_list;
  227. struct nlattr *param_attr;
  228. int nla_type;
  229. void *hdr;
  230. int err;
  231. int i;
  232. /* Get value from driver part to driverinit configuration mode */
  233. for (i = 0; i <= DEVLINK_PARAM_CMODE_MAX; i++) {
  234. if (!devlink_param_cmode_is_supported(param, i))
  235. continue;
  236. if (i == DEVLINK_PARAM_CMODE_DRIVERINIT) {
  237. if (param_item->driverinit_value_new_valid)
  238. param_value[i] = param_item->driverinit_value_new;
  239. else if (param_item->driverinit_value_valid)
  240. param_value[i] = param_item->driverinit_value;
  241. else
  242. return -EOPNOTSUPP;
  243. } else {
  244. ctx.cmode = i;
  245. err = devlink_param_get(devlink, param, &ctx);
  246. if (err)
  247. return err;
  248. param_value[i] = ctx.val;
  249. }
  250. param_value_set[i] = true;
  251. }
  252. hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
  253. if (!hdr)
  254. return -EMSGSIZE;
  255. if (devlink_nl_put_handle(msg, devlink))
  256. goto genlmsg_cancel;
  257. if (cmd == DEVLINK_CMD_PORT_PARAM_GET ||
  258. cmd == DEVLINK_CMD_PORT_PARAM_NEW ||
  259. cmd == DEVLINK_CMD_PORT_PARAM_DEL)
  260. if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX, port_index))
  261. goto genlmsg_cancel;
  262. param_attr = nla_nest_start_noflag(msg, DEVLINK_ATTR_PARAM);
  263. if (!param_attr)
  264. goto genlmsg_cancel;
  265. if (nla_put_string(msg, DEVLINK_ATTR_PARAM_NAME, param->name))
  266. goto param_nest_cancel;
  267. if (param->generic && nla_put_flag(msg, DEVLINK_ATTR_PARAM_GENERIC))
  268. goto param_nest_cancel;
  269. nla_type = devlink_param_type_to_nla_type(param->type);
  270. if (nla_type < 0)
  271. goto param_nest_cancel;
  272. if (nla_put_u8(msg, DEVLINK_ATTR_PARAM_TYPE, nla_type))
  273. goto param_nest_cancel;
  274. param_values_list = nla_nest_start_noflag(msg,
  275. DEVLINK_ATTR_PARAM_VALUES_LIST);
  276. if (!param_values_list)
  277. goto param_nest_cancel;
  278. for (i = 0; i <= DEVLINK_PARAM_CMODE_MAX; i++) {
  279. if (!param_value_set[i])
  280. continue;
  281. err = devlink_nl_param_value_fill_one(msg, param->type,
  282. i, param_value[i]);
  283. if (err)
  284. goto values_list_nest_cancel;
  285. }
  286. nla_nest_end(msg, param_values_list);
  287. nla_nest_end(msg, param_attr);
  288. genlmsg_end(msg, hdr);
  289. return 0;
  290. values_list_nest_cancel:
  291. nla_nest_end(msg, param_values_list);
  292. param_nest_cancel:
  293. nla_nest_cancel(msg, param_attr);
  294. genlmsg_cancel:
  295. genlmsg_cancel(msg, hdr);
  296. return -EMSGSIZE;
  297. }
  298. static void devlink_param_notify(struct devlink *devlink,
  299. unsigned int port_index,
  300. struct devlink_param_item *param_item,
  301. enum devlink_command cmd)
  302. {
  303. struct sk_buff *msg;
  304. int err;
  305. WARN_ON(cmd != DEVLINK_CMD_PARAM_NEW && cmd != DEVLINK_CMD_PARAM_DEL &&
  306. cmd != DEVLINK_CMD_PORT_PARAM_NEW &&
  307. cmd != DEVLINK_CMD_PORT_PARAM_DEL);
  308. /* devlink_notify_register() / devlink_notify_unregister()
  309. * will replay the notifications if the params are added/removed
  310. * outside of the lifetime of the instance.
  311. */
  312. if (!devl_is_registered(devlink) || !devlink_nl_notify_need(devlink))
  313. return;
  314. msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
  315. if (!msg)
  316. return;
  317. err = devlink_nl_param_fill(msg, devlink, port_index, param_item, cmd,
  318. 0, 0, 0);
  319. if (err) {
  320. nlmsg_free(msg);
  321. return;
  322. }
  323. devlink_nl_notify_send(devlink, msg);
  324. }
  325. static void devlink_params_notify(struct devlink *devlink,
  326. enum devlink_command cmd)
  327. {
  328. struct devlink_param_item *param_item;
  329. unsigned long param_id;
  330. xa_for_each(&devlink->params, param_id, param_item)
  331. devlink_param_notify(devlink, 0, param_item, cmd);
  332. }
  333. void devlink_params_notify_register(struct devlink *devlink)
  334. {
  335. devlink_params_notify(devlink, DEVLINK_CMD_PARAM_NEW);
  336. }
  337. void devlink_params_notify_unregister(struct devlink *devlink)
  338. {
  339. devlink_params_notify(devlink, DEVLINK_CMD_PARAM_DEL);
  340. }
  341. static int devlink_nl_param_get_dump_one(struct sk_buff *msg,
  342. struct devlink *devlink,
  343. struct netlink_callback *cb,
  344. int flags)
  345. {
  346. struct devlink_nl_dump_state *state = devlink_dump_state(cb);
  347. struct devlink_param_item *param_item;
  348. unsigned long param_id;
  349. int err = 0;
  350. xa_for_each_start(&devlink->params, param_id, param_item, state->idx) {
  351. err = devlink_nl_param_fill(msg, devlink, 0, param_item,
  352. DEVLINK_CMD_PARAM_GET,
  353. NETLINK_CB(cb->skb).portid,
  354. cb->nlh->nlmsg_seq, flags);
  355. if (err == -EOPNOTSUPP) {
  356. err = 0;
  357. } else if (err) {
  358. state->idx = param_id;
  359. break;
  360. }
  361. }
  362. return err;
  363. }
  364. int devlink_nl_param_get_dumpit(struct sk_buff *skb,
  365. struct netlink_callback *cb)
  366. {
  367. return devlink_nl_dumpit(skb, cb, devlink_nl_param_get_dump_one);
  368. }
  369. static int
  370. devlink_param_type_get_from_info(struct genl_info *info,
  371. enum devlink_param_type *param_type)
  372. {
  373. if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_PARAM_TYPE))
  374. return -EINVAL;
  375. switch (nla_get_u8(info->attrs[DEVLINK_ATTR_PARAM_TYPE])) {
  376. case NLA_U8:
  377. *param_type = DEVLINK_PARAM_TYPE_U8;
  378. break;
  379. case NLA_U16:
  380. *param_type = DEVLINK_PARAM_TYPE_U16;
  381. break;
  382. case NLA_U32:
  383. *param_type = DEVLINK_PARAM_TYPE_U32;
  384. break;
  385. case NLA_STRING:
  386. *param_type = DEVLINK_PARAM_TYPE_STRING;
  387. break;
  388. case NLA_FLAG:
  389. *param_type = DEVLINK_PARAM_TYPE_BOOL;
  390. break;
  391. default:
  392. return -EINVAL;
  393. }
  394. return 0;
  395. }
  396. static int
  397. devlink_param_value_get_from_info(const struct devlink_param *param,
  398. struct genl_info *info,
  399. union devlink_param_value *value)
  400. {
  401. struct nlattr *param_data;
  402. int len;
  403. param_data = info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA];
  404. if (param->type != DEVLINK_PARAM_TYPE_BOOL && !param_data)
  405. return -EINVAL;
  406. switch (param->type) {
  407. case DEVLINK_PARAM_TYPE_U8:
  408. if (nla_len(param_data) != sizeof(u8))
  409. return -EINVAL;
  410. value->vu8 = nla_get_u8(param_data);
  411. break;
  412. case DEVLINK_PARAM_TYPE_U16:
  413. if (nla_len(param_data) != sizeof(u16))
  414. return -EINVAL;
  415. value->vu16 = nla_get_u16(param_data);
  416. break;
  417. case DEVLINK_PARAM_TYPE_U32:
  418. if (nla_len(param_data) != sizeof(u32))
  419. return -EINVAL;
  420. value->vu32 = nla_get_u32(param_data);
  421. break;
  422. case DEVLINK_PARAM_TYPE_STRING:
  423. len = strnlen(nla_data(param_data), nla_len(param_data));
  424. if (len == nla_len(param_data) ||
  425. len >= __DEVLINK_PARAM_MAX_STRING_VALUE)
  426. return -EINVAL;
  427. strcpy(value->vstr, nla_data(param_data));
  428. break;
  429. case DEVLINK_PARAM_TYPE_BOOL:
  430. if (param_data && nla_len(param_data))
  431. return -EINVAL;
  432. value->vbool = nla_get_flag(param_data);
  433. break;
  434. }
  435. return 0;
  436. }
  437. static struct devlink_param_item *
  438. devlink_param_get_from_info(struct xarray *params, struct genl_info *info)
  439. {
  440. char *param_name;
  441. if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_PARAM_NAME))
  442. return NULL;
  443. param_name = nla_data(info->attrs[DEVLINK_ATTR_PARAM_NAME]);
  444. return devlink_param_find_by_name(params, param_name);
  445. }
  446. int devlink_nl_param_get_doit(struct sk_buff *skb,
  447. struct genl_info *info)
  448. {
  449. struct devlink *devlink = info->user_ptr[0];
  450. struct devlink_param_item *param_item;
  451. struct sk_buff *msg;
  452. int err;
  453. param_item = devlink_param_get_from_info(&devlink->params, info);
  454. if (!param_item)
  455. return -EINVAL;
  456. msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
  457. if (!msg)
  458. return -ENOMEM;
  459. err = devlink_nl_param_fill(msg, devlink, 0, param_item,
  460. DEVLINK_CMD_PARAM_GET,
  461. info->snd_portid, info->snd_seq, 0);
  462. if (err) {
  463. nlmsg_free(msg);
  464. return err;
  465. }
  466. return genlmsg_reply(msg, info);
  467. }
  468. static int __devlink_nl_cmd_param_set_doit(struct devlink *devlink,
  469. unsigned int port_index,
  470. struct xarray *params,
  471. struct genl_info *info,
  472. enum devlink_command cmd)
  473. {
  474. enum devlink_param_type param_type;
  475. struct devlink_param_gset_ctx ctx;
  476. enum devlink_param_cmode cmode;
  477. struct devlink_param_item *param_item;
  478. const struct devlink_param *param;
  479. union devlink_param_value value;
  480. int err = 0;
  481. param_item = devlink_param_get_from_info(params, info);
  482. if (!param_item)
  483. return -EINVAL;
  484. param = param_item->param;
  485. err = devlink_param_type_get_from_info(info, &param_type);
  486. if (err)
  487. return err;
  488. if (param_type != param->type)
  489. return -EINVAL;
  490. err = devlink_param_value_get_from_info(param, info, &value);
  491. if (err)
  492. return err;
  493. if (param->validate) {
  494. err = param->validate(devlink, param->id, value, info->extack);
  495. if (err)
  496. return err;
  497. }
  498. if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_PARAM_VALUE_CMODE))
  499. return -EINVAL;
  500. cmode = nla_get_u8(info->attrs[DEVLINK_ATTR_PARAM_VALUE_CMODE]);
  501. if (!devlink_param_cmode_is_supported(param, cmode))
  502. return -EOPNOTSUPP;
  503. if (cmode == DEVLINK_PARAM_CMODE_DRIVERINIT) {
  504. param_item->driverinit_value_new = value;
  505. param_item->driverinit_value_new_valid = true;
  506. } else {
  507. if (!param->set)
  508. return -EOPNOTSUPP;
  509. ctx.val = value;
  510. ctx.cmode = cmode;
  511. err = devlink_param_set(devlink, param, &ctx, info->extack);
  512. if (err)
  513. return err;
  514. }
  515. devlink_param_notify(devlink, port_index, param_item, cmd);
  516. return 0;
  517. }
  518. int devlink_nl_param_set_doit(struct sk_buff *skb, struct genl_info *info)
  519. {
  520. struct devlink *devlink = info->user_ptr[0];
  521. return __devlink_nl_cmd_param_set_doit(devlink, 0, &devlink->params,
  522. info, DEVLINK_CMD_PARAM_NEW);
  523. }
  524. int devlink_nl_port_param_get_dumpit(struct sk_buff *msg,
  525. struct netlink_callback *cb)
  526. {
  527. NL_SET_ERR_MSG(cb->extack, "Port params are not supported");
  528. return msg->len;
  529. }
  530. int devlink_nl_port_param_get_doit(struct sk_buff *skb,
  531. struct genl_info *info)
  532. {
  533. NL_SET_ERR_MSG(info->extack, "Port params are not supported");
  534. return -EINVAL;
  535. }
  536. int devlink_nl_port_param_set_doit(struct sk_buff *skb,
  537. struct genl_info *info)
  538. {
  539. NL_SET_ERR_MSG(info->extack, "Port params are not supported");
  540. return -EINVAL;
  541. }
  542. static int devlink_param_verify(const struct devlink_param *param)
  543. {
  544. if (!param || !param->name || !param->supported_cmodes)
  545. return -EINVAL;
  546. if (param->generic)
  547. return devlink_param_generic_verify(param);
  548. else
  549. return devlink_param_driver_verify(param);
  550. }
  551. static int devlink_param_register(struct devlink *devlink,
  552. const struct devlink_param *param)
  553. {
  554. struct devlink_param_item *param_item;
  555. int err;
  556. WARN_ON(devlink_param_verify(param));
  557. WARN_ON(devlink_param_find_by_name(&devlink->params, param->name));
  558. if (param->supported_cmodes == BIT(DEVLINK_PARAM_CMODE_DRIVERINIT))
  559. WARN_ON(param->get || param->set);
  560. else
  561. WARN_ON(!param->get || !param->set);
  562. param_item = kzalloc(sizeof(*param_item), GFP_KERNEL);
  563. if (!param_item)
  564. return -ENOMEM;
  565. param_item->param = param;
  566. err = xa_insert(&devlink->params, param->id, param_item, GFP_KERNEL);
  567. if (err)
  568. goto err_xa_insert;
  569. devlink_param_notify(devlink, 0, param_item, DEVLINK_CMD_PARAM_NEW);
  570. return 0;
  571. err_xa_insert:
  572. kfree(param_item);
  573. return err;
  574. }
  575. static void devlink_param_unregister(struct devlink *devlink,
  576. const struct devlink_param *param)
  577. {
  578. struct devlink_param_item *param_item;
  579. param_item = devlink_param_find_by_id(&devlink->params, param->id);
  580. if (WARN_ON(!param_item))
  581. return;
  582. devlink_param_notify(devlink, 0, param_item, DEVLINK_CMD_PARAM_DEL);
  583. xa_erase(&devlink->params, param->id);
  584. kfree(param_item);
  585. }
  586. /**
  587. * devl_params_register - register configuration parameters
  588. *
  589. * @devlink: devlink
  590. * @params: configuration parameters array
  591. * @params_count: number of parameters provided
  592. *
  593. * Register the configuration parameters supported by the driver.
  594. */
  595. int devl_params_register(struct devlink *devlink,
  596. const struct devlink_param *params,
  597. size_t params_count)
  598. {
  599. const struct devlink_param *param = params;
  600. int i, err;
  601. lockdep_assert_held(&devlink->lock);
  602. for (i = 0; i < params_count; i++, param++) {
  603. err = devlink_param_register(devlink, param);
  604. if (err)
  605. goto rollback;
  606. }
  607. return 0;
  608. rollback:
  609. if (!i)
  610. return err;
  611. for (param--; i > 0; i--, param--)
  612. devlink_param_unregister(devlink, param);
  613. return err;
  614. }
  615. EXPORT_SYMBOL_GPL(devl_params_register);
  616. int devlink_params_register(struct devlink *devlink,
  617. const struct devlink_param *params,
  618. size_t params_count)
  619. {
  620. int err;
  621. devl_lock(devlink);
  622. err = devl_params_register(devlink, params, params_count);
  623. devl_unlock(devlink);
  624. return err;
  625. }
  626. EXPORT_SYMBOL_GPL(devlink_params_register);
  627. /**
  628. * devl_params_unregister - unregister configuration parameters
  629. * @devlink: devlink
  630. * @params: configuration parameters to unregister
  631. * @params_count: number of parameters provided
  632. */
  633. void devl_params_unregister(struct devlink *devlink,
  634. const struct devlink_param *params,
  635. size_t params_count)
  636. {
  637. const struct devlink_param *param = params;
  638. int i;
  639. lockdep_assert_held(&devlink->lock);
  640. for (i = 0; i < params_count; i++, param++)
  641. devlink_param_unregister(devlink, param);
  642. }
  643. EXPORT_SYMBOL_GPL(devl_params_unregister);
  644. void devlink_params_unregister(struct devlink *devlink,
  645. const struct devlink_param *params,
  646. size_t params_count)
  647. {
  648. devl_lock(devlink);
  649. devl_params_unregister(devlink, params, params_count);
  650. devl_unlock(devlink);
  651. }
  652. EXPORT_SYMBOL_GPL(devlink_params_unregister);
  653. /**
  654. * devl_param_driverinit_value_get - get configuration parameter
  655. * value for driver initializing
  656. *
  657. * @devlink: devlink
  658. * @param_id: parameter ID
  659. * @val: pointer to store the value of parameter in driverinit
  660. * configuration mode
  661. *
  662. * This function should be used by the driver to get driverinit
  663. * configuration for initialization after reload command.
  664. *
  665. * Note that lockless call of this function relies on the
  666. * driver to maintain following basic sane behavior:
  667. * 1) Driver ensures a call to this function cannot race with
  668. * registering/unregistering the parameter with the same parameter ID.
  669. * 2) Driver ensures a call to this function cannot race with
  670. * devl_param_driverinit_value_set() call with the same parameter ID.
  671. * 3) Driver ensures a call to this function cannot race with
  672. * reload operation.
  673. * If the driver is not able to comply, it has to take the devlink->lock
  674. * while calling this.
  675. */
  676. int devl_param_driverinit_value_get(struct devlink *devlink, u32 param_id,
  677. union devlink_param_value *val)
  678. {
  679. struct devlink_param_item *param_item;
  680. if (WARN_ON(!devlink_reload_supported(devlink->ops)))
  681. return -EOPNOTSUPP;
  682. param_item = devlink_param_find_by_id(&devlink->params, param_id);
  683. if (!param_item)
  684. return -EINVAL;
  685. if (!param_item->driverinit_value_valid)
  686. return -EOPNOTSUPP;
  687. if (WARN_ON(!devlink_param_cmode_is_supported(param_item->param,
  688. DEVLINK_PARAM_CMODE_DRIVERINIT)))
  689. return -EOPNOTSUPP;
  690. *val = param_item->driverinit_value;
  691. return 0;
  692. }
  693. EXPORT_SYMBOL_GPL(devl_param_driverinit_value_get);
  694. /**
  695. * devl_param_driverinit_value_set - set value of configuration
  696. * parameter for driverinit
  697. * configuration mode
  698. *
  699. * @devlink: devlink
  700. * @param_id: parameter ID
  701. * @init_val: value of parameter to set for driverinit configuration mode
  702. *
  703. * This function should be used by the driver to set driverinit
  704. * configuration mode default value.
  705. */
  706. void devl_param_driverinit_value_set(struct devlink *devlink, u32 param_id,
  707. union devlink_param_value init_val)
  708. {
  709. struct devlink_param_item *param_item;
  710. devl_assert_locked(devlink);
  711. param_item = devlink_param_find_by_id(&devlink->params, param_id);
  712. if (WARN_ON(!param_item))
  713. return;
  714. if (WARN_ON(!devlink_param_cmode_is_supported(param_item->param,
  715. DEVLINK_PARAM_CMODE_DRIVERINIT)))
  716. return;
  717. param_item->driverinit_value = init_val;
  718. param_item->driverinit_value_valid = true;
  719. devlink_param_notify(devlink, 0, param_item, DEVLINK_CMD_PARAM_NEW);
  720. }
  721. EXPORT_SYMBOL_GPL(devl_param_driverinit_value_set);
  722. void devlink_params_driverinit_load_new(struct devlink *devlink)
  723. {
  724. struct devlink_param_item *param_item;
  725. unsigned long param_id;
  726. xa_for_each(&devlink->params, param_id, param_item) {
  727. if (!devlink_param_cmode_is_supported(param_item->param,
  728. DEVLINK_PARAM_CMODE_DRIVERINIT) ||
  729. !param_item->driverinit_value_new_valid)
  730. continue;
  731. param_item->driverinit_value = param_item->driverinit_value_new;
  732. param_item->driverinit_value_valid = true;
  733. param_item->driverinit_value_new_valid = false;
  734. }
  735. }
  736. /**
  737. * devl_param_value_changed - notify devlink on a parameter's value
  738. * change. Should be called by the driver
  739. * right after the change.
  740. *
  741. * @devlink: devlink
  742. * @param_id: parameter ID
  743. *
  744. * This function should be used by the driver to notify devlink on value
  745. * change, excluding driverinit configuration mode.
  746. * For driverinit configuration mode driver should use the function
  747. */
  748. void devl_param_value_changed(struct devlink *devlink, u32 param_id)
  749. {
  750. struct devlink_param_item *param_item;
  751. param_item = devlink_param_find_by_id(&devlink->params, param_id);
  752. WARN_ON(!param_item);
  753. devlink_param_notify(devlink, 0, param_item, DEVLINK_CMD_PARAM_NEW);
  754. }
  755. EXPORT_SYMBOL_GPL(devl_param_value_changed);