PageRenderTime 42ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 0ms

/sys/contrib/octeon-sdk/cvmx-error.c

https://bitbucket.org/freebsd/freebsd-head/
C | 643 lines | 383 code | 37 blank | 223 comment | 117 complexity | 1a583c6d4644be81e75f9246c606d900 MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception, BSD-3-Clause, LGPL-2.0, LGPL-2.1, BSD-2-Clause, 0BSD, JSON, AGPL-1.0, GPL-2.0
  1. /***********************license start***************
  2. * Copyright (c) 2003-2010 Cavium Networks (support@cavium.com). All rights
  3. * reserved.
  4. *
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions are
  8. * met:
  9. *
  10. * * Redistributions of source code must retain the above copyright
  11. * notice, this list of conditions and the following disclaimer.
  12. *
  13. * * Redistributions in binary form must reproduce the above
  14. * copyright notice, this list of conditions and the following
  15. * disclaimer in the documentation and/or other materials provided
  16. * with the distribution.
  17. * * Neither the name of Cavium Networks nor the names of
  18. * its contributors may be used to endorse or promote products
  19. * derived from this software without specific prior written
  20. * permission.
  21. * This Software, including technical data, may be subject to U.S. export control
  22. * laws, including the U.S. Export Administration Act and its associated
  23. * regulations, and may be subject to export or import regulations in other
  24. * countries.
  25. * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
  26. * AND WITH ALL FAULTS AND CAVIUM NETWORKS MAKES NO PROMISES, REPRESENTATIONS OR
  27. * WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO
  28. * THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION OR
  29. * DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM
  30. * SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE,
  31. * MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF
  32. * VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR
  33. * CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT OF USE OR
  34. * PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
  35. ***********************license end**************************************/
  36. /**
  37. * @file
  38. *
  39. * Interface to the Octeon extended error status.
  40. *
  41. * <hr>$Revision: 44252 $<hr>
  42. */
  43. #ifdef CVMX_BUILD_FOR_LINUX_KERNEL
  44. #include <asm/octeon/cvmx.h>
  45. #include <asm/octeon/cvmx-error.h>
  46. #include <asm/octeon/cvmx-error-custom.h>
  47. #include <asm/octeon/cvmx-pcie.h>
  48. #include <asm/octeon/cvmx-srio.h>
  49. #include <asm/octeon/cvmx-pexp-defs.h>
  50. #else
  51. #include "cvmx.h"
  52. #include "cvmx-error.h"
  53. #include "cvmx-error-custom.h"
  54. #include "cvmx-pcie.h"
  55. #include "cvmx-srio.h"
  56. #include "cvmx-interrupt.h"
  57. #endif
  58. #define MAX_TABLE_SIZE 1024 /* Max number of error status bits we can support */
  59. extern int cvmx_error_initialize_cn63xx(void);
  60. extern int cvmx_error_initialize_cn63xxp1(void);
  61. extern int cvmx_error_initialize_cn58xxp1(void);
  62. extern int cvmx_error_initialize_cn58xx(void);
  63. extern int cvmx_error_initialize_cn56xxp1(void);
  64. extern int cvmx_error_initialize_cn56xx(void);
  65. extern int cvmx_error_initialize_cn50xx(void);
  66. extern int cvmx_error_initialize_cn52xxp1(void);
  67. extern int cvmx_error_initialize_cn52xx(void);
  68. extern int cvmx_error_initialize_cn38xxp2(void);
  69. extern int cvmx_error_initialize_cn38xx(void);
  70. extern int cvmx_error_initialize_cn31xx(void);
  71. extern int cvmx_error_initialize_cn30xx(void);
  72. /* Each entry in this array represents a status bit function or chain */
  73. static CVMX_SHARED cvmx_error_info_t __cvmx_error_table[MAX_TABLE_SIZE];
  74. static CVMX_SHARED int __cvmx_error_table_size = 0;
  75. static CVMX_SHARED cvmx_error_flags_t __cvmx_error_flags;
  76. #define REG_MATCH(h, reg_type, status_addr, status_mask) \
  77. ((h->reg_type == reg_type) && (h->status_addr == status_addr) && (h->status_mask == status_mask))
  78. /**
  79. * @INTERNAL
  80. * Read a status or enable register from the hardware
  81. *
  82. * @param reg_type Register type to read
  83. * @param addr Address to read
  84. *
  85. * @return Result of the read
  86. */
  87. static uint64_t __cvmx_error_read_hw(cvmx_error_register_t reg_type, uint64_t addr)
  88. {
  89. switch (reg_type)
  90. {
  91. case __CVMX_ERROR_REGISTER_NONE:
  92. return 0;
  93. case CVMX_ERROR_REGISTER_IO64:
  94. return cvmx_read_csr(addr);
  95. case CVMX_ERROR_REGISTER_IO32:
  96. return cvmx_read64_uint32(addr ^ 4);
  97. case CVMX_ERROR_REGISTER_PCICONFIG:
  98. return cvmx_pcie_cfgx_read(addr>>32, addr&0xffffffffull);
  99. case CVMX_ERROR_REGISTER_SRIOMAINT:
  100. {
  101. uint32_t r;
  102. if (cvmx_srio_config_read32(addr>>32, 0, -1, 0, 0, addr&0xffffffffull, &r))
  103. return 0;
  104. else
  105. return r;
  106. }
  107. }
  108. return 0;
  109. }
  110. /**
  111. * @INTERNAL
  112. * Write a status or enable register to the hardware
  113. *
  114. * @param reg_type Register type to write
  115. * @param addr Address to write
  116. * @param value Value to write
  117. */
  118. static void __cvmx_error_write_hw(cvmx_error_register_t reg_type, uint64_t addr, uint64_t value)
  119. {
  120. switch (reg_type)
  121. {
  122. case __CVMX_ERROR_REGISTER_NONE:
  123. return;
  124. case CVMX_ERROR_REGISTER_IO64:
  125. cvmx_write_csr(addr, value);
  126. return;
  127. case CVMX_ERROR_REGISTER_IO32:
  128. cvmx_write64_uint32(addr ^ 4, value);
  129. return;
  130. case CVMX_ERROR_REGISTER_PCICONFIG:
  131. cvmx_pcie_cfgx_write(addr>>32, addr&0xffffffffull, value);
  132. return;
  133. case CVMX_ERROR_REGISTER_SRIOMAINT:
  134. {
  135. cvmx_srio_config_write32(addr>>32, 0, -1, 0, 0, addr&0xffffffffull, value);
  136. return;
  137. }
  138. }
  139. }
  140. /**
  141. * @INTERNAL
  142. * Function for processing non leaf error status registers. This function
  143. * calls all handlers for this passed register and all children linked
  144. * to it.
  145. *
  146. * @param info Error register to check
  147. *
  148. * @return Number of error status bits found or zero if no bits were set.
  149. */
  150. int __cvmx_error_decode(const cvmx_error_info_t *info)
  151. {
  152. uint64_t status;
  153. uint64_t enable;
  154. int i;
  155. int handled = 0;
  156. /* Read the status and enable state */
  157. status = __cvmx_error_read_hw(info->reg_type, info->status_addr);
  158. if (info->enable_addr)
  159. enable = __cvmx_error_read_hw(info->reg_type, info->enable_addr);
  160. else
  161. enable = 0;
  162. for (i = 0; i < __cvmx_error_table_size; i++)
  163. {
  164. const cvmx_error_info_t *h = &__cvmx_error_table[i];
  165. uint64_t masked_status = status;
  166. /* If this is a child of the current register then recurse and process
  167. the child */
  168. if ((h->parent.reg_type == info->reg_type) &&
  169. (h->parent.status_addr == info->status_addr) &&
  170. (status & h->parent.status_mask))
  171. handled += __cvmx_error_decode(h);
  172. if ((h->reg_type != info->reg_type) || (h->status_addr != info->status_addr))
  173. continue;
  174. /* If the corresponding enable bit is not set then we have nothing to do */
  175. if (h->enable_addr && h->enable_mask)
  176. {
  177. if (!(enable & h->enable_mask))
  178. continue;
  179. }
  180. /* Apply the mask to eliminate irrelevant bits */
  181. if (h->status_mask)
  182. masked_status &= h->status_mask;
  183. /* Finally call the handler function unless it is this function */
  184. if (masked_status && h->func && (h->func != __cvmx_error_decode))
  185. handled += h->func(h);
  186. }
  187. /* Ths should be the total errors found */
  188. return handled;
  189. }
  190. /**
  191. * @INTERNAL
  192. * This error bit handler simply prints a message and clears the status bit
  193. *
  194. * @param info Error register to check
  195. *
  196. * @return
  197. */
  198. int __cvmx_error_display(const cvmx_error_info_t *info)
  199. {
  200. const char *message = (const char *)(long)info->user_info;
  201. /* This assumes that all bits in the status register are RO or R/W1C */
  202. __cvmx_error_write_hw(info->reg_type, info->status_addr, info->status_mask);
  203. cvmx_safe_printf("%s", message);
  204. return 1;
  205. }
  206. /**
  207. * Initalize the error status system. This should be called once
  208. * before any other functions are called. This function adds default
  209. * handlers for most all error events but does not enable them. Later
  210. * calls to cvmx_error_enable() are needed.
  211. *
  212. * @param flags Optional flags.
  213. *
  214. * @return Zero on success, negative on failure.
  215. */
  216. int cvmx_error_initialize(cvmx_error_flags_t flags)
  217. {
  218. __cvmx_error_flags = flags;
  219. if (OCTEON_IS_MODEL(OCTEON_CN63XX_PASS2_X))
  220. {
  221. if (cvmx_error_initialize_cn63xx())
  222. return -1;
  223. }
  224. else if (OCTEON_IS_MODEL(OCTEON_CN63XX_PASS1_X))
  225. {
  226. if (cvmx_error_initialize_cn63xxp1())
  227. return -1;
  228. }
  229. else if (OCTEON_IS_MODEL(OCTEON_CN58XX_PASS1_X))
  230. {
  231. if (cvmx_error_initialize_cn58xxp1())
  232. return -1;
  233. }
  234. else if (OCTEON_IS_MODEL(OCTEON_CN58XX))
  235. {
  236. if (cvmx_error_initialize_cn58xx())
  237. return -1;
  238. }
  239. else if (OCTEON_IS_MODEL(OCTEON_CN56XX_PASS1_X))
  240. {
  241. if (cvmx_error_initialize_cn56xxp1())
  242. return -1;
  243. }
  244. else if (OCTEON_IS_MODEL(OCTEON_CN56XX))
  245. {
  246. if (cvmx_error_initialize_cn56xx())
  247. return -1;
  248. }
  249. else if (OCTEON_IS_MODEL(OCTEON_CN50XX))
  250. {
  251. if (cvmx_error_initialize_cn50xx())
  252. return -1;
  253. }
  254. else if (OCTEON_IS_MODEL(OCTEON_CN52XX_PASS1_X))
  255. {
  256. if (cvmx_error_initialize_cn52xxp1())
  257. return -1;
  258. }
  259. else if (OCTEON_IS_MODEL(OCTEON_CN52XX))
  260. {
  261. if (cvmx_error_initialize_cn52xx())
  262. return -1;
  263. }
  264. else if (OCTEON_IS_MODEL(OCTEON_CN38XX_PASS2))
  265. {
  266. if (cvmx_error_initialize_cn38xxp2())
  267. return -1;
  268. }
  269. else if (OCTEON_IS_MODEL(OCTEON_CN38XX))
  270. {
  271. if (cvmx_error_initialize_cn38xx())
  272. return -1;
  273. }
  274. else if (OCTEON_IS_MODEL(OCTEON_CN31XX))
  275. {
  276. if (cvmx_error_initialize_cn31xx())
  277. return -1;
  278. }
  279. else if (OCTEON_IS_MODEL(OCTEON_CN30XX))
  280. {
  281. if (cvmx_error_initialize_cn30xx())
  282. return -1;
  283. }
  284. else
  285. {
  286. cvmx_warn("cvmx_error_initialize() needs update for this Octeon model\n");
  287. return -1;
  288. }
  289. if (__cvmx_error_custom_initialize())
  290. return -1;
  291. /* Enable all of the purely internal error sources by default */
  292. cvmx_error_enable_group(CVMX_ERROR_GROUP_INTERNAL, 0);
  293. /* Enable DDR error reporting based on the memory controllers */
  294. if (OCTEON_IS_MODEL(OCTEON_CN56XX))
  295. {
  296. cvmx_l2c_cfg_t l2c_cfg;
  297. l2c_cfg.u64 = cvmx_read_csr(CVMX_L2C_CFG);
  298. if (l2c_cfg.s.dpres0)
  299. cvmx_error_enable_group(CVMX_ERROR_GROUP_LMC, 0);
  300. if (l2c_cfg.s.dpres1)
  301. cvmx_error_enable_group(CVMX_ERROR_GROUP_LMC, 1);
  302. }
  303. else
  304. cvmx_error_enable_group(CVMX_ERROR_GROUP_LMC, 0);
  305. /* Old PCI parts don't have a common PCI init, so enable error
  306. reporting if the bootloader told us we are a PCI host. PCIe
  307. is handled when cvmx_pcie_rc_initialize is called */
  308. if (!octeon_has_feature(OCTEON_FEATURE_PCIE) &&
  309. (cvmx_sysinfo_get()->bootloader_config_flags & CVMX_BOOTINFO_CFG_FLAG_PCI_HOST))
  310. cvmx_error_enable_group(CVMX_ERROR_GROUP_PCI, 0);
  311. /* FIXME: Why is this needed for CN63XX? */
  312. if (OCTEON_IS_MODEL(OCTEON_CN63XX))
  313. cvmx_write_csr(CVMX_PEXP_SLI_INT_SUM, 1);
  314. return 0;
  315. }
  316. /**
  317. * Poll the error status registers and call the appropriate error
  318. * handlers. This should be called in the RSL interrupt handler
  319. * for your application or operating system.
  320. *
  321. * @return Number of error handlers called. Zero means this call
  322. * found no errors and was spurious.
  323. */
  324. int cvmx_error_poll(void)
  325. {
  326. int i;
  327. int count = 0;
  328. /* Call all handlers that don't have a parent */
  329. for (i = 0; i < __cvmx_error_table_size; i++)
  330. if (__cvmx_error_table[i].parent.reg_type == __CVMX_ERROR_REGISTER_NONE)
  331. count += __cvmx_error_decode(&__cvmx_error_table[i]);
  332. return count;
  333. }
  334. /**
  335. * Register to be called when an error status bit is set. Most users
  336. * will not need to call this function as cvmx_error_initialize()
  337. * registers default handlers for most error conditions. This function
  338. * is normally used to add more handlers without changing the existing
  339. * handlers.
  340. *
  341. * @param new_info Information about the handler for a error register. The
  342. * structure passed is copied and can be destroyed after the
  343. * call. All members of the structure must be populated, even the
  344. * parent information.
  345. *
  346. * @return Zero on success, negative on failure.
  347. */
  348. int cvmx_error_add(const cvmx_error_info_t *new_info)
  349. {
  350. if (__cvmx_error_table_size >= MAX_TABLE_SIZE)
  351. {
  352. cvmx_warn("cvmx-error table full\n");
  353. return -1;
  354. }
  355. __cvmx_error_table[__cvmx_error_table_size] = *new_info;
  356. __cvmx_error_table_size++;
  357. return 0;
  358. }
  359. /**
  360. * Remove all handlers for a status register and mask. Normally
  361. * this function should not be called. Instead a new handler should be
  362. * installed to replace the existing handler. In the even that all
  363. * reporting of a error bit should be removed, then use this
  364. * function.
  365. *
  366. * @param reg_type Type of the status register to remove
  367. * @param status_addr
  368. * Status register to remove.
  369. * @param status_mask
  370. * All handlers for this status register with this mask will be
  371. * removed.
  372. * @param old_info If not NULL, this is filled with information about the handler
  373. * that was removed.
  374. *
  375. * @return Zero on success, negative on failure (not found).
  376. */
  377. int cvmx_error_remove(cvmx_error_register_t reg_type,
  378. uint64_t status_addr, uint64_t status_mask,
  379. cvmx_error_info_t *old_info)
  380. {
  381. int found = 0;
  382. int i;
  383. for (i = 0; i < __cvmx_error_table_size; i++)
  384. {
  385. cvmx_error_info_t *h = &__cvmx_error_table[i];
  386. if (!REG_MATCH(h, reg_type, status_addr, status_mask))
  387. continue;
  388. if (old_info)
  389. *old_info = *h;
  390. memset(h, 0, sizeof(*h));
  391. found = 1;
  392. }
  393. if (found)
  394. return 0;
  395. else
  396. {
  397. cvmx_warn("cvmx-error remove couldn't find requested register\n");
  398. return -1;
  399. }
  400. }
  401. /**
  402. * Change the function and user_info for an existing error status
  403. * register. This function should be used to replace the default
  404. * handler with an application specific version as needed.
  405. *
  406. * @param reg_type Type of the status register to change
  407. * @param status_addr
  408. * Status register to change.
  409. * @param status_mask
  410. * All handlers for this status register with this mask will be
  411. * changed.
  412. * @param new_func New function to use to handle the error status
  413. * @param new_user_info
  414. * New user info parameter for the function
  415. * @param old_func If not NULL, the old function is returned. Useful for restoring
  416. * the old handler.
  417. * @param old_user_info
  418. * If not NULL, the old user info parameter.
  419. *
  420. * @return Zero on success, negative on failure
  421. */
  422. int cvmx_error_change_handler(cvmx_error_register_t reg_type,
  423. uint64_t status_addr, uint64_t status_mask,
  424. cvmx_error_func_t new_func, uint64_t new_user_info,
  425. cvmx_error_func_t *old_func, uint64_t *old_user_info)
  426. {
  427. int found = 0;
  428. int i;
  429. for (i = 0; i < __cvmx_error_table_size; i++)
  430. {
  431. cvmx_error_info_t *h = &__cvmx_error_table[i];
  432. if (!REG_MATCH(h, reg_type, status_addr, status_mask))
  433. continue;
  434. if (old_func)
  435. *old_func = h->func;
  436. if (old_user_info)
  437. *old_user_info = h->user_info;
  438. h->func = new_func;
  439. h->user_info = new_user_info;
  440. found = 1;
  441. }
  442. if (found)
  443. return 0;
  444. else
  445. {
  446. cvmx_warn("cvmx-error change couldn't find requested register\n");
  447. return -1;
  448. }
  449. }
  450. /**
  451. * Enable all error registers for a logical group. This should be
  452. * called whenever a logical group is brought online.
  453. *
  454. * @param group Logical group to enable
  455. * @param group_index
  456. * Index for the group as defined in the cvmx_error_group_t
  457. * comments.
  458. *
  459. * @return Zero on success, negative on failure.
  460. */
  461. int cvmx_error_enable_group(cvmx_error_group_t group, int group_index)
  462. {
  463. int i;
  464. uint64_t enable;
  465. if (cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_SIM)
  466. return 0;
  467. for (i = 0; i < __cvmx_error_table_size; i++)
  468. {
  469. const cvmx_error_info_t *h = &__cvmx_error_table[i];
  470. /* Skip entries that have a different group or group index. We
  471. also skip entries that don't have an enable */
  472. if ((h->group != group) || (h->group_index != group_index) || (!h->enable_addr))
  473. continue;
  474. /* Skip entries that have flags that don't match the user's
  475. selected flags */
  476. if (h->flags && (h->flags != (h->flags & __cvmx_error_flags)))
  477. continue;
  478. /* Update the enables for this entry */
  479. enable = __cvmx_error_read_hw(h->reg_type, h->enable_addr);
  480. if (h->reg_type == CVMX_ERROR_REGISTER_PCICONFIG)
  481. enable &= ~h->enable_mask; /* PCI bits have reversed polarity */
  482. else
  483. enable |= h->enable_mask;
  484. __cvmx_error_write_hw(h->reg_type, h->enable_addr, enable);
  485. }
  486. return 0;
  487. }
  488. /**
  489. * Disable all error registers for a logical group. This should be
  490. * called whenever a logical group is brought offline. Many blocks
  491. * will report spurious errors when offline unless this function
  492. * is called.
  493. *
  494. * @param group Logical group to disable
  495. * @param group_index
  496. * Index for the group as defined in the cvmx_error_group_t
  497. * comments.
  498. *
  499. * @return Zero on success, negative on failure.
  500. */
  501. int cvmx_error_disable_group(cvmx_error_group_t group, int group_index)
  502. {
  503. int i;
  504. uint64_t enable;
  505. if (cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_SIM)
  506. return 0;
  507. for (i = 0; i < __cvmx_error_table_size; i++)
  508. {
  509. const cvmx_error_info_t *h = &__cvmx_error_table[i];
  510. /* Skip entries that have a different group or group index. We
  511. also skip entries that don't have an enable */
  512. if ((h->group != group) || (h->group_index != group_index) || (!h->enable_addr))
  513. continue;
  514. /* Update the enables for this entry */
  515. enable = __cvmx_error_read_hw(h->reg_type, h->enable_addr);
  516. if (h->reg_type == CVMX_ERROR_REGISTER_PCICONFIG)
  517. enable |= h->enable_mask; /* PCI bits have reversed polarity */
  518. else
  519. enable &= ~h->enable_mask;
  520. __cvmx_error_write_hw(h->reg_type, h->enable_addr, enable);
  521. }
  522. return 0;
  523. }
  524. /**
  525. * Enable all handlers for a specific status register mask.
  526. *
  527. * @param reg_type Type of the status register
  528. * @param status_addr
  529. * Status register address
  530. * @param status_mask
  531. * All handlers for this status register with this mask will be
  532. * enabled.
  533. *
  534. * @return Zero on success, negative on failure.
  535. */
  536. int cvmx_error_enable(cvmx_error_register_t reg_type,
  537. uint64_t status_addr, uint64_t status_mask)
  538. {
  539. int found = 0;
  540. int i;
  541. uint64_t enable;
  542. for (i = 0; i < __cvmx_error_table_size; i++)
  543. {
  544. cvmx_error_info_t *h = &__cvmx_error_table[i];
  545. if (!REG_MATCH(h, reg_type, status_addr, status_mask) || !h->enable_addr)
  546. continue;
  547. enable = __cvmx_error_read_hw(h->reg_type, h->enable_addr);
  548. if (h->reg_type == CVMX_ERROR_REGISTER_PCICONFIG)
  549. enable &= ~h->enable_mask; /* PCI bits have reversed polarity */
  550. else
  551. enable |= h->enable_mask;
  552. __cvmx_error_write_hw(h->reg_type, h->enable_addr, enable);
  553. h->flags &= ~CVMX_ERROR_FLAGS_DISABLED;
  554. found = 1;
  555. }
  556. if (found)
  557. return 0;
  558. else
  559. {
  560. cvmx_warn("cvmx-error enable couldn't find requested register\n");
  561. return -1;
  562. }
  563. }
  564. /**
  565. * Disable all handlers for a specific status register and mask.
  566. *
  567. * @param reg_type Type of the status register
  568. * @param status_addr
  569. * Status register address
  570. * @param status_mask
  571. * All handlers for this status register with this mask will be
  572. * disabled.
  573. *
  574. * @return Zero on success, negative on failure.
  575. */
  576. int cvmx_error_disable(cvmx_error_register_t reg_type,
  577. uint64_t status_addr, uint64_t status_mask)
  578. {
  579. int found = 0;
  580. int i;
  581. uint64_t enable;
  582. for (i = 0; i < __cvmx_error_table_size; i++)
  583. {
  584. cvmx_error_info_t *h = &__cvmx_error_table[i];
  585. if (!REG_MATCH(h, reg_type, status_addr, status_mask) || !h->enable_addr)
  586. continue;
  587. enable = __cvmx_error_read_hw(h->reg_type, h->enable_addr);
  588. if (h->reg_type == CVMX_ERROR_REGISTER_PCICONFIG)
  589. enable |= h->enable_mask; /* PCI bits have reversed polarity */
  590. else
  591. enable &= ~h->enable_mask;
  592. __cvmx_error_write_hw(h->reg_type, h->enable_addr, enable);
  593. h->flags |= CVMX_ERROR_FLAGS_DISABLED;
  594. found = 1;
  595. }
  596. if (found)
  597. return 0;
  598. else
  599. {
  600. cvmx_warn("cvmx-error disable couldn't find requested register\n");
  601. return -1;
  602. }
  603. }