psgen.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864
  1. /*====================================================================*
  2. *
  3. * Copyright (c) 2013 Qualcomm Atheros, Inc.
  4. *
  5. * All rights reserved.
  6. *
  7. *====================================================================*/
  8. /*====================================================================*
  9. *
  10. * psgen.c - generate prescaler values based on trace results;
  11. *
  12. * Contributor(s):
  13. * Nathaniel Houghton <nhoughto@qca.qualcomm.com>
  14. * Charles Maier <cmaier@qca.qualcomm.com>
  15. *
  16. *--------------------------------------------------------------------*/
  17. /*====================================================================*
  18. * system header files;
  19. *--------------------------------------------------------------------*/
  20. #include <math.h>
  21. #include <stdio.h>
  22. #include <stdlib.h>
  23. #include <unistd.h>
  24. #include <string.h>
  25. #include <stdint.h>
  26. #include <ctype.h>
  27. /*====================================================================*
  28. * custom header files;
  29. *--------------------------------------------------------------------*/
  30. #include "../tools/error.h"
  31. #include "../tools/flags.h"
  32. #include "../tools/getoptv.h"
  33. #include "../tools/putoptv.h"
  34. #include "../tools/symbol.h"
  35. #include "../tools/types.h"
  36. #include "../tools/version.h"
  37. #include "../nda/psgen.h"
  38. /*====================================================================*
  39. * custom source files;
  40. *--------------------------------------------------------------------*/
  41. #ifndef MAKEFILE
  42. #include "../tools/getoptv.c"
  43. #include "../tools/putoptv.c"
  44. #include "../tools/version.c"
  45. #include "../tools/error.c"
  46. #include "../tools/lookup.c"
  47. #include "../tools/todigit.c"
  48. #include "../tools/fdchecksum32.c"
  49. #endif
  50. #ifndef MAKEFILE
  51. #include "../pib/pibscalers.c"
  52. #include "../pib/lightning_pib_file.c"
  53. #include "../pib/lightning_pib_lock.c"
  54. #endif
  55. #ifndef MAKEFILE
  56. #include "../nda/psgen_util.c"
  57. #endif
  58. /*====================================================================*
  59. * program constants;
  60. *--------------------------------------------------------------------*/
  61. #define PSGEN_SILENCE (1 << 0)
  62. #define PSGEN_VERBOSE (1 << 1)
  63. #define PSGEN_FLATTEN (1 << 2)
  64. /*====================================================================*
  65. * USA notches;
  66. *--------------------------------------------------------------------*/
  67. struct notch usa_notches [] =
  68. {
  69. {
  70. 1806636.000000,
  71. 2099604.000000
  72. },
  73. {
  74. 3417960.000000,
  75. 4101552.000000
  76. },
  77. {
  78. 5249010.000000,
  79. 5517564.000000
  80. },
  81. {
  82. 6909162.000000,
  83. 7397442.000000
  84. },
  85. {
  86. 10009740.000000,
  87. 10253880.000000
  88. },
  89. {
  90. 13915980.000000,
  91. 14453088.000000
  92. },
  93. {
  94. 17993118.000000,
  95. 18286086.000000
  96. },
  97. {
  98. 20922798.000000,
  99. 21557562.000000
  100. },
  101. {
  102. 24804624.000000,
  103. 25097592.000000
  104. },
  105. {
  106. 27929616.000000,
  107. 30004806.000000
  108. }
  109. };
  110. /*--------------------------------------------------------------------*
  111. * Japan notches;
  112. *--------------------------------------------------------------------*/
  113. struct notch japan_notches [] =
  114. {
  115. {
  116. 1806636.000000,
  117. 2124018.000000
  118. },
  119. {
  120. 3417960.000000,
  121. 4125966.000000
  122. },
  123. {
  124. 5249010.000000,
  125. 5517564.000000
  126. },
  127. {
  128. 5932602.000000,
  129. 6249984.000000
  130. },
  131. {
  132. 6884748.000000,
  133. 7446270.000000
  134. },
  135. {
  136. 9472632.000000,
  137. 9887670.000000
  138. },
  139. {
  140. 9985326.000000,
  141. 10302708.000000
  142. },
  143. {
  144. 13891566.000000,
  145. 14477502.000000
  146. },
  147. {
  148. 17993118.000000,
  149. 18286086.000000
  150. },
  151. {
  152. 20922798.000000,
  153. 21557562.000000
  154. },
  155. {
  156. 24804624.000000,
  157. 25097592.000000
  158. },
  159. {
  160. 27929616.000000,
  161. 30004806.000000
  162. }
  163. };
  164. /*--------------------------------------------------------------------*
  165. * Permanent EN50561 Notches;
  166. *--------------------------------------------------------------------*/
  167. struct notch permanent_en50561_notches [] =
  168. {
  169. {
  170. 1800000.000000,
  171. 2000000.000000
  172. },
  173. {
  174. 2850000.000000,
  175. 3025000.000000
  176. },
  177. {
  178. 3400000.000000,
  179. 4000000.000000
  180. },
  181. {
  182. 4650000.000000,
  183. 4700000.000000
  184. },
  185. {
  186. 5250000.000000,
  187. 5450000.000000
  188. },
  189. {
  190. 5480000.000000,
  191. 5680000.000000
  192. },
  193. {
  194. 6525000.000000,
  195. 6685000.000000
  196. },
  197. {
  198. 7000000.000000,
  199. 7300000.000000
  200. },
  201. {
  202. 8815000.000000,
  203. 8965000.000000
  204. },
  205. {
  206. 10005000.000000,
  207. 10150000.000000
  208. },
  209. {
  210. 11275000.000000,
  211. 11400000.000000
  212. },
  213. {
  214. 13260000.000000,
  215. 13360000.000000
  216. },
  217. {
  218. 14000000.000000,
  219. 14350000.000000
  220. },
  221. {
  222. 17900000.000000,
  223. 17970000.000000
  224. },
  225. {
  226. 18068000.000000,
  227. 18168000.000000
  228. },
  229. {
  230. 21000000.000000,
  231. 21450000.000000
  232. },
  233. {
  234. 21924000.000000,
  235. 22000000.000000
  236. },
  237. {
  238. 24890000.000000,
  239. 24990000.000000
  240. },
  241. {
  242. 26960000.000000,
  243. 27410000.000000
  244. },
  245. {
  246. 28000000.000000,
  247. 29700000.000000
  248. }
  249. };
  250. /*--------------------------------------------------------------------*
  251. * Dynamic EN50561 Notches;
  252. *--------------------------------------------------------------------*/
  253. struct notch dynamic_en50561_notches [] =
  254. {
  255. {
  256. 2300000.000000,
  257. 2498000.000000
  258. },
  259. {
  260. 3200000.000000,
  261. 3400000.000000
  262. },
  263. {
  264. 3900000.000000,
  265. 4050000.000000
  266. },
  267. {
  268. 4750000.000000,
  269. 5110000.000000
  270. },
  271. {
  272. 5750000.000000,
  273. 6200000.000000
  274. },
  275. {
  276. 7200000.000000,
  277. 7700000.000000
  278. },
  279. {
  280. 9300000.000000,
  281. 9950000.000000
  282. },
  283. {
  284. 11550000.000000,
  285. 12100000.000000
  286. },
  287. {
  288. 13550000.000000,
  289. 13900000.000000
  290. },
  291. {
  292. 15050000.000000,
  293. 15850000.000000
  294. },
  295. {
  296. 17400000.000000,
  297. 17900000.000000
  298. },
  299. {
  300. 18900000.000000,
  301. 19020000.000000
  302. },
  303. {
  304. 21450000.000000,
  305. 21850000.000000
  306. },
  307. {
  308. 25650000.000000,
  309. 26100000.000000
  310. }
  311. };
  312. /*--------------------------------------------------------------------*
  313. * All EN50561 Notches;
  314. *--------------------------------------------------------------------*/
  315. struct notch all_en50561_notches [] =
  316. {
  317. {
  318. 1806640.625000,
  319. 2514648.438000
  320. },
  321. {
  322. 2832031.250000,
  323. 4077148.438000
  324. },
  325. {
  326. 4638671.875000,
  327. 6225585.938000
  328. },
  329. {
  330. 6494140.625000,
  331. 6713867.188000
  332. },
  333. {
  334. 6982421.875000,
  335. 7739257.812500
  336. },
  337. {
  338. 8789062.500000,
  339. 9008789.062500
  340. },
  341. {
  342. 9277343.750000,
  343. 10180664.062500
  344. },
  345. {
  346. 11230468.750000,
  347. 12133789.062500
  348. },
  349. {
  350. 13232421.875000,
  351. 14379882.812500
  352. },
  353. {
  354. 15039062.500000,
  355. 15893554.687500
  356. },
  357. {
  358. 17382812.500000,
  359. 18188476.562500
  360. },
  361. {
  362. 18896484.375000,
  363. 19067382.812500
  364. },
  365. {
  366. 20996093.750000,
  367. 22045898.437500
  368. },
  369. {
  370. 24853515.625000,
  371. 25024414.062500
  372. },
  373. {
  374. 25634765.625000,
  375. 26147460.937500
  376. },
  377. {
  378. 26953125.000000,
  379. 27416992.187500
  380. },
  381. {
  382. 27978515.625000,
  383. 29760742.187500
  384. },
  385. };
  386. /*--------------------------------------------------------------------*
  387. * notch sets;
  388. *--------------------------------------------------------------------*/
  389. #define NOTCH_SET_NONE 0
  390. #define NOTCH_SET_USA 1
  391. #define NOTCH_SET_JAPAN 2
  392. #define NOTCH_SET_EN50561_PERM 3
  393. #define NOTCH_SET_EN50561_ALL 4
  394. #define NOTCH_SETS 5
  395. struct _code_ notch_set_names [NOTCH_SETS] =
  396. {
  397. {
  398. NOTCH_SET_NONE,
  399. "none"
  400. },
  401. {
  402. NOTCH_SET_USA,
  403. "usa"
  404. },
  405. {
  406. NOTCH_SET_JAPAN,
  407. "japan"
  408. },
  409. {
  410. NOTCH_SET_EN50561_PERM,
  411. "en50561_perm"
  412. },
  413. {
  414. NOTCH_SET_EN50561_ALL,
  415. "en50561_all"
  416. }
  417. };
  418. /*--------------------------------------------------------------------*
  419. *
  420. *--------------------------------------------------------------------*/
  421. struct notch_set notch_sets [NOTCH_SETS] =
  422. {
  423. {
  424. 0,
  425. 0,
  426. NULL
  427. },
  428. {
  429. SIZEOF (usa_notches),
  430. -1000,
  431. usa_notches
  432. },
  433. {
  434. SIZEOF (japan_notches),
  435. -1000,
  436. japan_notches
  437. },
  438. {
  439. SIZEOF (permanent_en50561_notches),
  440. -1000,
  441. permanent_en50561_notches
  442. },
  443. {
  444. SIZEOF (all_en50561_notches),
  445. -1000,
  446. all_en50561_notches
  447. }
  448. };
  449. /*--------------------------------------------------------------------*
  450. *
  451. *--------------------------------------------------------------------*/
  452. #define DEVICE_SPEC_AR6400 0
  453. #define DEVICE_SPEC_AR7400 1
  454. #define DEVICE_SPEC_QCA6410 2
  455. #define DEVICE_SPEC_QCA7420 3
  456. #define DEVICE_SPEC_QCA7500 4
  457. #define DEVICE_SPECS 5
  458. #define AR7400_NAME "ar7400"
  459. #define AR6400_NAME "ar6400"
  460. #define QCA7420_NAME "ar7420"
  461. #define QCA6410_NAME "qca6410"
  462. #define QCA7500_NAME "qca7500"
  463. struct _code_ device_spec_name [DEVICE_SPECS] =
  464. {
  465. {
  466. DEVICE_SPEC_AR6400,
  467. AR6400_NAME
  468. },
  469. {
  470. DEVICE_SPEC_AR7400,
  471. AR7400_NAME
  472. },
  473. {
  474. DEVICE_SPEC_QCA6410,
  475. QCA6410_NAME
  476. },
  477. {
  478. DEVICE_SPEC_QCA7420,
  479. QCA7420_NAME
  480. },
  481. {
  482. DEVICE_SPEC_QCA7500,
  483. QCA7500_NAME
  484. }
  485. };
  486. struct device_spec device_spec [DEVICE_SPECS] =
  487. {
  488. {
  489. AR6400_NAME,
  490. 1155,
  491. 256,
  492. 511,
  493. 1,
  494. 1070,
  495. update_pib,
  496. set_tx_gain_6400,
  497. check_tx_gain_6400
  498. },
  499. {
  500. AR7400_NAME,
  501. 2880,
  502. 512,
  503. 1023,
  504. 1,
  505. 2690,
  506. update_pib,
  507. NULL,
  508. NULL
  509. },
  510. {
  511. QCA6410_NAME,
  512. 578,
  513. 128,
  514. 255,
  515. 2,
  516. -1,
  517. NULL,
  518. NULL,
  519. NULL
  520. },
  521. {
  522. QCA7420_NAME,
  523. 1345,
  524. 128,
  525. 255,
  526. 2,
  527. -1,
  528. NULL,
  529. NULL,
  530. NULL
  531. },
  532. {
  533. QCA7500_NAME,
  534. 1345,
  535. 128,
  536. 255,
  537. 2,
  538. -1,
  539. NULL,
  540. NULL,
  541. NULL
  542. }
  543. };
  544. /*--------------------------------------------------------------------*
  545. * define program defaults;
  546. *--------------------------------------------------------------------*/
  547. #define DEFAULT_DEVICE_NAME "ar6400"
  548. #define DEFAULT_NOTCH_SET "usa"
  549. #define DEFAULT_INPUT_FORMAT "rs"
  550. #define DEFAULT_CARRIER_REPLACE_WIDTH 0
  551. #define DEFAULT_GAIN_ADJUST 0
  552. /*====================================================================*
  553. *
  554. *--------------------------------------------------------------------*/
  555. int main (int argc, const char * argv [])
  556. {
  557. static const char * optv [] =
  558. {
  559. "d:F:G:i:N:n:P:p:r:T:v",
  560. "input_file [> output file]",
  561. "Prescaler Generator",
  562. "d s\tTarget device is (s) [" LITERAL (DEFAULT_DEVICE_NAME) "] (ar6400, ar7400, qca6410, ar7420)",
  563. "F n\tFlatten trace to level (n) (units match units of spectrum analyzer trace)",
  564. "G n\tOutput power level gain adjustment is (n) dB [" LITERAL (DEFAULT_GAIN_ADJUST) "]",
  565. "i s\tInput format is (s) [" LITERAL (DEFAULT_INPUT_FORMAT) "]",
  566. "N s\tNotch to match regulatory requirements for (s) [" LITERAL (NOTCH_SET_DEFAULT) "] (none, usa, japan, en50561_perm, en50561_all)",
  567. "n x\tReplace (x) carriers around notches [" LITERAL (DEFAULT_CARRIER_REPLACE_WIDTH) "]",
  568. "P f\tSave prescalers and gain to pib file (f)",
  569. "p f\tLoad prescaler values used during spectrum analyzer capture from prescaler file (f) (otherwise unity is assumed)",
  570. "r x-y\tModify prescalers in frequency range [x,y] (eg. 0-30M is 0Hz to 30MHz)",
  571. "T sf,ef,sd,ed\tTweak prescalers from sf to ef (start freq, end freq) by sd (start delta) at sf, linearly changing to ed (end delta) at ef",
  572. "v\tverbose messages",
  573. (const char *) (0)
  574. };
  575. unsigned scale = 2;
  576. double flatten;
  577. signed gain_adj = DEFAULT_GAIN_ADJUST;
  578. char * notch_type = DEFAULT_NOTCH_SET;
  579. signed notch_set;
  580. char * target_device = DEFAULT_DEVICE_NAME;
  581. int device_type;
  582. char * input_format = DEFAULT_INPUT_FORMAT;
  583. char * pib_path = NULL;
  584. char * input_prescaler_path = NULL;
  585. struct rs_file rs_file;
  586. struct trace trace;
  587. struct trace orig_trace;
  588. struct trace shaped_trace;
  589. struct tweak * tweak = NULL;
  590. struct tweak * tweak_tail = NULL;
  591. struct dev_config * dconf;
  592. struct device_spec * dspec;
  593. uint32_t carrier_replace_width = DEFAULT_CARRIER_REPLACE_WIDTH;
  594. double start_freq = -1;
  595. double end_freq = -1;
  596. const char * p;
  597. struct tweak * t = (struct tweak *) (0);
  598. struct prescalers * input_ps;
  599. signed index;
  600. flag_t flags = (flag_t) (0);
  601. signed c;
  602. optind = 1;
  603. while (~ (c = getoptv (argc, argv, optv)))
  604. {
  605. switch (c)
  606. {
  607. case 'd':
  608. target_device = optarg;
  609. break;
  610. case 'F':
  611. _setbits (flags, PSGEN_FLATTEN);
  612. p = strtodouble (optarg, & flatten);
  613. if (* p != '\0')
  614. {
  615. error (1, 0, "invalid value provided to option -F: %s", optarg);
  616. }
  617. break;
  618. case 'G':
  619. gain_adj = atoi (optarg);
  620. break;
  621. case 'i':
  622. input_format = optarg;
  623. break;
  624. case 'N':
  625. notch_type = optarg;
  626. break;
  627. case 'n':
  628. carrier_replace_width = atoi (optarg);
  629. break;
  630. case 'P':
  631. pib_path = optarg;
  632. break;
  633. case 'p':
  634. input_prescaler_path = optarg;
  635. break;
  636. case 'r':
  637. if (parse_range (optarg, & start_freq, & end_freq) == -1)
  638. {
  639. error (1, 0, "invalid value provided to option -r: %s", optarg);
  640. }
  641. if (start_freq < 0 || end_freq < 0 || start_freq > end_freq)
  642. {
  643. error (1, 0, "invalid value provided to option -r: %s", optarg);
  644. }
  645. break;
  646. case 'T':
  647. {
  648. struct tweak * new_tweak;
  649. new_tweak = malloc (sizeof (* new_tweak));
  650. if (new_tweak == NULL)
  651. {
  652. error (1, errno, "out of memory");
  653. }
  654. memset (new_tweak, 0, sizeof (* new_tweak));
  655. if (parse_tweak (new_tweak, optarg) == -1)
  656. {
  657. error (1, 0, "invalid tweak provided to option -T: %s", optarg);
  658. }
  659. if (tweak_tail != NULL)
  660. {
  661. tweak_tail->next = new_tweak;
  662. }
  663. if (tweak == NULL)
  664. {
  665. tweak = new_tweak;
  666. }
  667. tweak_tail = new_tweak;
  668. }
  669. break;
  670. default:
  671. break;
  672. }
  673. }
  674. argc -= optind;
  675. argv += optind;
  676. if (argc != 1)
  677. {
  678. putoptv (optv);
  679. exit (1);
  680. }
  681. device_type = lookup (target_device, device_spec_name, DEVICE_SPECS);
  682. if (device_type == -1)
  683. {
  684. error (1, 0, "unknown device type \"%s\"", target_device);
  685. }
  686. dspec = & device_spec [device_type];
  687. notch_set = lookup (notch_type, notch_set_names, NOTCH_SETS);
  688. if (notch_set == -1)
  689. {
  690. error (1, 0, "unknown notch set \"%s\"", notch_type);
  691. }
  692. if (strcasecmp (input_format, DEFAULT_INPUT_FORMAT))
  693. {
  694. error (1, 0, "only input format rs is currently supported");
  695. }
  696. if (gain_adj != 0)
  697. {
  698. if (dspec->check_tx_gain == NULL)
  699. {
  700. error (1, 0, "gain adjustment is not (yet) supported for device type %s", target_device);
  701. }
  702. if (dspec->check_tx_gain (gain_adj) == -1)
  703. {
  704. error (1, 0, "invalid gain adjustment provided");
  705. }
  706. }
  707. if (load_rs_file (argv [0], & rs_file) == -1)
  708. {
  709. error (1, 0, "failed to load %s", argv [0]);
  710. }
  711. if (create_trace_rs (& rs_file, & orig_trace) == -1)
  712. {
  713. error (1, 0, "could not convert input file into internal format");
  714. }
  715. free_rs_file (& rs_file);
  716. if (reshape_trace (& shaped_trace, & orig_trace, dspec, start_freq, end_freq) == -1)
  717. {
  718. error (1, 0, "could not reshape trace to match prescalers");
  719. }
  720. free_trace_data (& orig_trace);
  721. /* make copy of shaped trace */
  722. if (create_trace_copy (& trace, & shaped_trace) == -1)
  723. {
  724. error (1, 0, "could not copy trace");
  725. }
  726. /* flatten trace */
  727. if (_anyset (flags, PSGEN_FLATTEN))
  728. {
  729. for (index = 0; index < trace.count; ++ index)
  730. {
  731. trace.value [index] = flatten;
  732. }
  733. }
  734. /* apply tweaks */
  735. for (t = tweak; t != NULL; t = t->next)
  736. {
  737. apply_tweak (& trace, t, TWEAK_RELATIVE);
  738. }
  739. /* apply notching */
  740. if (notch_set != NOTCH_SET_NONE)
  741. {
  742. for (index = 0; index < notch_sets [notch_set].count; ++ index)
  743. {
  744. struct tweak tw;
  745. tw.sf = notch_sets [notch_set].notch [index].sf;
  746. tw.ef = notch_sets [notch_set].notch [index].ef;
  747. tw.ev = tw.sv = notch_sets [notch_set].depth;
  748. apply_tweak (& trace, & tw, TWEAK_ABSOLUTE);
  749. }
  750. /* remove the tail (if any) */
  751. if (dspec->tail_start != -1)
  752. {
  753. for (index = dspec->tail_start; index < trace.count; ++ index)
  754. {
  755. trace.value [index] = notch_sets [notch_set].depth;
  756. }
  757. }
  758. }
  759. /* load input prescalers (or generate default set if NULL is specified for input file) */
  760. input_ps = load_prescalers (input_prescaler_path, dspec);
  761. if (input_ps == NULL)
  762. {
  763. error (1, 0, "failed to load/generate input prescaler file");
  764. }
  765. /* generate prescalers based on device spec, two traces, and gain adjustment */
  766. dconf = generate_config (& shaped_trace, & trace, dspec, gain_adj, input_ps, start_freq, end_freq);
  767. if (dconf == NULL)
  768. {
  769. error (1, 0, "could not generate device configuration");
  770. }
  771. show_prescalers (dconf->ps, scale);
  772. /* post process -- adjust config around the notches */
  773. if (carrier_replace_width)
  774. {
  775. if (replace_prescalers_around_notches (dconf->ps, carrier_replace_width) == -1)
  776. {
  777. error (1, 0, "could not replace prescaler data around notches");
  778. }
  779. }
  780. if (pib_path == NULL)
  781. {
  782. print_config_stats (dconf, stdout);
  783. print_config (dconf, stdout);
  784. }
  785. else
  786. {
  787. if (dspec->update_pib == NULL)
  788. {
  789. error (1, 0, "a PIB is not yet supported for device type %s", dspec->name);
  790. }
  791. if (dspec->update_pib (pib_path, dconf) == -1)
  792. {
  793. error (1, 0, "could not save configuration to PIB");
  794. }
  795. }
  796. print_config_stats (dconf, stderr);
  797. free_trace_data (& trace);
  798. free_trace_data (& shaped_trace);
  799. free_dev_config (dconf);
  800. free_tweaks (tweak);
  801. return (0);
  802. }