1 /*****************************************************************************
3 (c) Cambridge Silicon Radio Limited 2012
4 All rights reserved and confidential information of CSR
6 Refer to LICENSE.txt included with this source for details
9 *****************************************************************************/
12 * ---------------------------------------------------------------------------
13 * FILE: csr_wifi_hip_dump.c
16 * Routines for retrieving and buffering core status from the UniFi
18 * ---------------------------------------------------------------------------
20 #include <linux/slab.h>
21 #include "csr_wifi_hip_unifi.h"
22 #include "csr_wifi_hip_unifiversion.h"
23 #include "csr_wifi_hip_card.h"
25 /* Locations to capture in dump (XAP words) */
26 #define HIP_CDUMP_FIRST_CPUREG (0xFFE0) /* First CPU register */
27 #define HIP_CDUMP_FIRST_LO (0) /* Start of low address range */
28 #define HIP_CDUMP_FIRST_HI_MAC (0x3C00) /* Start of MAC high area */
29 #define HIP_CDUMP_FIRST_HI_PHY (0x1C00) /* Start of PHY high area */
30 #define HIP_CDUMP_FIRST_SH (0) /* Start of shared memory area */
32 #define HIP_CDUMP_NCPUREGS (10) /* No. of 16-bit XAP registers */
33 #define HIP_CDUMP_NWORDS_LO (0x0100) /* Low area size in 16-bit words */
34 #define HIP_CDUMP_NWORDS_HI (0x0400) /* High area size in 16-bit words */
35 #define HIP_CDUMP_NWORDS_SH (0x0500) /* Shared memory area size, 16-bit words */
37 #define HIP_CDUMP_NUM_ZONES 7 /* Number of UniFi memory areas to capture */
39 /* Mini-coredump state */
40 typedef struct coredump_buf
42 u16 count
; /* serial number of dump */
43 u32 timestamp
; /* host's system time at capture */
44 s16 requestor
; /* request: 0=auto dump, 1=manual */
47 u16
*zone
[HIP_CDUMP_NUM_ZONES
];
49 struct coredump_buf
*next
; /* circular list */
50 struct coredump_buf
*prev
; /* circular list */
53 /* Structure used to describe a zone of chip memory captured by mini-coredump */
56 unifi_coredump_space_t space
; /* XAP memory space this zone covers */
57 enum unifi_dbg_processors_select cpu
; /* XAP CPU core selector */
58 u32 gp
; /* Generic Pointer to memory zone on XAP */
59 u16 offset
; /* 16-bit XAP word offset of zone in memory space */
60 u16 length
; /* Length of zone in XAP words */
63 static CsrResult
unifi_coredump_from_sdio(card_t
*card
, coredump_buffer
*dump_buf
);
64 static CsrResult
unifi_coredump_read_zones(card_t
*card
, coredump_buffer
*dump_buf
);
65 static CsrResult
unifi_coredump_read_zone(card_t
*card
, u16
*zone
,
66 const struct coredump_zone
*def
);
67 static s32
get_value_from_coredump(const coredump_buffer
*dump
,
68 const unifi_coredump_space_t space
, const u16 offset
);
70 /* Table of chip memory zones we capture on mini-coredump */
71 static const struct coredump_zone zonedef_table
[HIP_CDUMP_NUM_ZONES
] = {
72 { UNIFI_COREDUMP_MAC_REG
, UNIFI_PROC_MAC
, UNIFI_MAKE_GP(REGISTERS
, HIP_CDUMP_FIRST_CPUREG
* 2), HIP_CDUMP_FIRST_CPUREG
, HIP_CDUMP_NCPUREGS
},
73 { UNIFI_COREDUMP_PHY_REG
, UNIFI_PROC_PHY
, UNIFI_MAKE_GP(REGISTERS
, HIP_CDUMP_FIRST_CPUREG
* 2), HIP_CDUMP_FIRST_CPUREG
, HIP_CDUMP_NCPUREGS
},
74 { UNIFI_COREDUMP_SH_DMEM
, UNIFI_PROC_INVALID
, UNIFI_MAKE_GP(SH_DMEM
, HIP_CDUMP_FIRST_SH
* 2), HIP_CDUMP_FIRST_SH
, HIP_CDUMP_NWORDS_SH
},
75 { UNIFI_COREDUMP_MAC_DMEM
, UNIFI_PROC_MAC
, UNIFI_MAKE_GP(MAC_DMEM
, HIP_CDUMP_FIRST_LO
* 2), HIP_CDUMP_FIRST_LO
, HIP_CDUMP_NWORDS_LO
},
76 { UNIFI_COREDUMP_MAC_DMEM
, UNIFI_PROC_MAC
, UNIFI_MAKE_GP(MAC_DMEM
, HIP_CDUMP_FIRST_HI_MAC
* 2), HIP_CDUMP_FIRST_HI_MAC
, HIP_CDUMP_NWORDS_HI
},
77 { UNIFI_COREDUMP_PHY_DMEM
, UNIFI_PROC_PHY
, UNIFI_MAKE_GP(PHY_DMEM
, HIP_CDUMP_FIRST_LO
* 2), HIP_CDUMP_FIRST_LO
, HIP_CDUMP_NWORDS_LO
},
78 { UNIFI_COREDUMP_PHY_DMEM
, UNIFI_PROC_PHY
, UNIFI_MAKE_GP(PHY_DMEM
, HIP_CDUMP_FIRST_HI_PHY
* 2), HIP_CDUMP_FIRST_HI_PHY
, HIP_CDUMP_NWORDS_HI
},
82 * ---------------------------------------------------------------------------
83 * unifi_coredump_request_at_next_reset
85 * Request that a mini-coredump is performed when the driver has
86 * completed resetting the UniFi device.
89 * card Pointer to card struct
90 * enable If non-zero, sets the request.
91 * If zero, cancels any pending request.
94 * CSR_RESULT_SUCCESS or CSR HIP error code
97 * This function is typically called once the driver has detected that
98 * the UniFi device has become unresponsive due to crash, or internal
99 * watchdog reset. The driver must reset it to regain communication and,
100 * immediately after that, the mini-coredump can be captured.
101 * ---------------------------------------------------------------------------
103 CsrResult
unifi_coredump_request_at_next_reset(card_t
*card
, s8 enable
)
109 unifi_trace(card
->ospriv
, UDBG2
, "Mini-coredump requested after reset\n");
114 r
= CSR_WIFI_HIP_RESULT_INVALID_VALUE
;
118 card
->request_coredump_on_reset
= enable
?1 : 0;
119 r
= CSR_RESULT_SUCCESS
;
127 * ---------------------------------------------------------------------------
128 * unifi_coredump_handle_request
130 * Performs a coredump now, if one was requested, and clears the request.
133 * card Pointer to card struct
136 * CSR_RESULT_SUCCESS or CSR HIP error code
139 * ---------------------------------------------------------------------------
141 CsrResult
unifi_coredump_handle_request(card_t
*card
)
143 CsrResult r
= CSR_RESULT_SUCCESS
;
147 r
= CSR_WIFI_HIP_RESULT_INVALID_VALUE
;
151 if (card
->request_coredump_on_reset
== 1)
153 card
->request_coredump_on_reset
= 0;
154 r
= unifi_coredump_capture(card
, NULL
);
163 * ---------------------------------------------------------------------------
164 * unifi_coredump_capture
166 * Capture the current status of the UniFi device.
167 * Various registers are buffered for future offline inspection.
170 * card Pointer to card struct
171 * req Pointer to request struct, or NULL:
172 * A coredump requested manually by the user app
173 * will have a request struct pointer, an automatic
174 * coredump will have a NULL pointer.
176 * CSR_RESULT_SUCCESS on success,
177 * CSR_RESULT_FAILURE SDIO error
178 * CSR_WIFI_HIP_RESULT_INVALID_VALUE Initialisation not complete
181 * The result is a filled entry in the circular buffer of core dumps,
182 * values from which can be extracted to userland via an ioctl.
183 * ---------------------------------------------------------------------------
185 CsrResult
unifi_coredump_capture(card_t
*card
, struct unifi_coredump_req
*req
)
187 CsrResult r
= CSR_RESULT_SUCCESS
;
188 static u16 dump_seq_no
= 1;
191 if (card
->dump_next_write
== NULL
)
193 r
= CSR_RESULT_SUCCESS
;
197 /* Reject forced capture before initialisation has happened */
198 if (card
->helper
== NULL
)
200 r
= CSR_WIFI_HIP_RESULT_INVALID_VALUE
;
206 * Force a mini-coredump capture right now
208 time_of_capture
= CsrTimeGet(NULL
);
209 unifi_info(card
->ospriv
, "Mini-coredump capture at t=%u\n", time_of_capture
);
211 /* Wake up the processors so we can talk to them */
212 r
= unifi_set_host_state(card
, UNIFI_HOST_STATE_AWAKE
);
213 if (r
!= CSR_RESULT_SUCCESS
)
215 unifi_error(card
->ospriv
, "Failed to wake UniFi\n");
221 unifi_trace(card
->ospriv
, UDBG4
, "Stopping XAPs for coredump capture\n");
222 r
= unifi_card_stop_processor(card
, UNIFI_PROC_BOTH
);
223 if (r
!= CSR_RESULT_SUCCESS
)
225 unifi_error(card
->ospriv
, "Failed to stop UniFi XAPs\n");
229 /* Dump core into the next available slot in the circular list */
230 r
= unifi_coredump_from_sdio(card
, card
->dump_next_write
);
231 if (r
== CSR_RESULT_SUCCESS
)
233 /* Record whether the dump was manual or automatic */
234 card
->dump_next_write
->requestor
= (req
?1 : 0);
235 card
->dump_next_write
->timestamp
= time_of_capture
;
236 /* Advance to the next buffer */
237 card
->dump_next_write
->count
= dump_seq_no
++;
238 card
->dump_cur_read
= card
->dump_next_write
;
239 card
->dump_next_write
= card
->dump_next_write
->next
;
241 /* Sequence no. of zero indicates slot not in use, so handle wrap */
242 if (dump_seq_no
== 0)
247 unifi_trace(card
->ospriv
, UDBG3
,
248 "Coredump (%p), SeqNo=%d, cur_read=%p, next_write=%p\n",
250 card
->dump_cur_read
->count
,
251 card
->dump_cur_read
, card
->dump_next_write
);
254 /* Start both XAPs */
255 unifi_trace(card
->ospriv
, UDBG4
, "Restart XAPs after coredump\n");
256 r
= card_start_processor(card
, UNIFI_PROC_BOTH
);
257 if (r
!= CSR_RESULT_SUCCESS
)
259 unifi_error(card
->ospriv
, "Failed to start UniFi XAPs\n");
265 } /* unifi_coredump_capture() */
269 * ---------------------------------------------------------------------------
270 * get_value_from_coredump
275 * dump Pointer to buffered coredump data
276 * offset_in_space XAP memory space to retrieve from the buffer (there
277 * may be more than one zone covering the same memory
278 * space, but starting from different offsets).
279 * offset Offset within the XAP memory space to be retrieved
282 * >=0 Register value on success
283 * <0 Register out of range of any captured zones
286 * ---------------------------------------------------------------------------
288 static s32
get_value_from_coredump(const coredump_buffer
*coreDump
,
289 const unifi_coredump_space_t space
,
290 const u16 offset_in_space
)
296 const struct coredump_zone
*def
= &zonedef_table
[0];
298 /* Search zone def table for a match with the requested memory space */
299 for (i
= 0; i
< HIP_CDUMP_NUM_ZONES
; i
++, def
++)
301 if (space
== def
->space
)
303 zone_end_offset
= def
->offset
+ def
->length
;
305 /* Is the space offset contained in this zone? */
306 if (offset_in_space
< zone_end_offset
&&
307 offset_in_space
>= def
->offset
)
309 /* Calculate the offset of data within the zone buffer */
310 offset_in_zone
= offset_in_space
- def
->offset
;
311 r
= (s32
) * (coreDump
->zone
[i
] + offset_in_zone
);
313 unifi_trace(NULL
, UDBG6
,
314 "sp %d, offs 0x%04x = 0x%04x (in z%d 0x%04x->0x%04x)\n",
315 space
, offset_in_space
, r
,
316 i
, def
->offset
, zone_end_offset
- 1);
326 * ---------------------------------------------------------------------------
327 * unifi_coredump_get_value
329 * Retrieve the value of a register buffered from a previous core dump,
330 * so that it may be reported back to application code.
333 * card Pointer to card struct
334 * req_reg Pointer to request parameter partially filled. This
335 * function puts in the values retrieved from the dump.
338 * CSR_RESULT_SUCCESS on success, or:
339 * CSR_WIFI_HIP_RESULT_INVALID_VALUE Null parameter error
340 * CSR_WIFI_HIP_RESULT_RANGE Register out of range
341 * CSR_WIFI_HIP_RESULT_NOT_FOUND Dump index not (yet) captured
344 * ---------------------------------------------------------------------------
346 CsrResult
unifi_coredump_get_value(card_t
*card
, struct unifi_coredump_req
*req
)
350 coredump_buffer
*find_dump
= NULL
;
352 if (req
== NULL
|| card
== NULL
)
354 r
= CSR_WIFI_HIP_RESULT_INVALID_VALUE
;
358 if (card
->dump_buf
== NULL
)
360 unifi_trace(card
->ospriv
, UDBG2
, "No coredump buffers\n");
361 r
= CSR_WIFI_HIP_RESULT_NOT_FOUND
; /* Coredumping disabled */
364 if (card
->dump_cur_read
== NULL
)
366 unifi_trace(card
->ospriv
, UDBG4
, "No coredumps captured\n");
367 r
= CSR_WIFI_HIP_RESULT_NOT_FOUND
; /* No coredump yet captured */
371 /* Find the requested dump buffer */
375 find_dump
= card
->dump_cur_read
;
377 case -1: /* Oldest: The next used slot forward */
378 for (find_dump
= card
->dump_cur_read
->next
;
379 (find_dump
->count
== 0) && (find_dump
!= card
->dump_cur_read
);
380 find_dump
= card
->dump_cur_read
->next
)
384 default: /* Number of steps back from current read position */
385 for (i
= 0, find_dump
= card
->dump_cur_read
;
387 i
++, find_dump
= find_dump
->prev
)
389 /* Walk the list for the index'th entry, but
390 * stop when about to wrap. */
391 unifi_trace(card
->ospriv
, UDBG6
,
392 "%d: %d, @%p, p=%p, n=%p, cr=%p, h=%p\n",
393 i
, find_dump
->count
, find_dump
, find_dump
->prev
,
394 find_dump
->next
, card
->dump_cur_read
, card
->dump_buf
);
395 if (find_dump
->prev
== card
->dump_cur_read
)
397 /* Wrapped but still not found, index out of range */
400 unifi_trace(card
->ospriv
, UDBG6
,
401 "Dump index %d not found %d\n", req
->index
, i
);
402 r
= CSR_WIFI_HIP_RESULT_NOT_FOUND
;
411 /* Check if the slot is actually filled with a core dump */
412 if (find_dump
->count
== 0)
414 unifi_trace(card
->ospriv
, UDBG4
, "Not captured %d\n", req
->index
);
415 r
= CSR_WIFI_HIP_RESULT_NOT_FOUND
;
419 unifi_trace(card
->ospriv
, UDBG6
, "Req index %d, found seq %d at step %d\n",
420 req
->index
, find_dump
->count
, i
);
422 /* Find the appropriate entry in the buffer */
423 req
->value
= get_value_from_coredump(find_dump
, req
->space
, (u16
)req
->offset
);
426 r
= CSR_WIFI_HIP_RESULT_RANGE
; /* Un-captured register */
427 unifi_trace(card
->ospriv
, UDBG4
,
428 "Can't read space %d, reg 0x%x from coredump buffer %d\n",
429 req
->space
, req
->offset
, req
->index
);
433 r
= CSR_RESULT_SUCCESS
;
436 /* Update the private request structure with the found values */
437 req
->chip_ver
= find_dump
->chip_ver
;
438 req
->fw_ver
= find_dump
->fw_ver
;
439 req
->timestamp
= find_dump
->timestamp
;
440 req
->requestor
= find_dump
->requestor
;
441 req
->serial
= find_dump
->count
;
445 } /* unifi_coredump_get_value() */
449 * ---------------------------------------------------------------------------
450 * unifi_coredump_read_zone
452 * Captures a UniFi memory zone into a buffer on the host
455 * card Pointer to card struct
456 * zonebuf Pointer to on-host buffer to dump the memory zone into
457 * def Pointer to description of the memory zone to read from UniFi.
460 * CSR_RESULT_SUCCESS on success, or:
461 * CSR_RESULT_FAILURE SDIO error
462 * CSR_WIFI_HIP_RESULT_INVALID_VALUE Parameter error
465 * It is assumed that the caller has already stopped the XAPs
466 * ---------------------------------------------------------------------------
468 static CsrResult
unifi_coredump_read_zone(card_t
*card
, u16
*zonebuf
, const struct coredump_zone
*def
)
472 if (zonebuf
== NULL
|| def
== NULL
)
474 r
= CSR_WIFI_HIP_RESULT_INVALID_VALUE
;
478 /* Select XAP CPU if necessary */
479 if (def
->cpu
!= UNIFI_PROC_INVALID
)
481 if (def
->cpu
!= UNIFI_PROC_MAC
&& def
->cpu
!= UNIFI_PROC_PHY
)
483 r
= CSR_WIFI_HIP_RESULT_INVALID_VALUE
;
486 r
= unifi_set_proc_select(card
, def
->cpu
);
487 if (r
!= CSR_RESULT_SUCCESS
)
493 unifi_trace(card
->ospriv
, UDBG4
,
494 "Dump sp %d, offs 0x%04x, 0x%04x words @GP=%08x CPU %d\n",
495 def
->space
, def
->offset
, def
->length
, def
->gp
, def
->cpu
);
497 /* Read on-chip RAM (byte-wise) */
498 r
= unifi_card_readn(card
, def
->gp
, zonebuf
, (u16
)(def
->length
* 2));
499 if (r
== CSR_WIFI_HIP_RESULT_NO_DEVICE
)
503 if (r
!= CSR_RESULT_SUCCESS
)
505 unifi_error(card
->ospriv
, "Can't read UniFi shared data area\n");
515 * ---------------------------------------------------------------------------
516 * unifi_coredump_read_zones
518 * Walks through the table of on-chip memory zones defined in zonedef_table,
519 * and reads each of them from the UniFi chip
522 * card Pointer to card struct
523 * dump_buf Buffer into which register values will be dumped
526 * CSR_RESULT_SUCCESS on success, or:
527 * CSR_RESULT_FAILURE SDIO error
528 * CSR_WIFI_HIP_RESULT_INVALID_VALUE Parameter error
531 * It is assumed that the caller has already stopped the XAPs
532 * ---------------------------------------------------------------------------
534 static CsrResult
unifi_coredump_read_zones(card_t
*card
, coredump_buffer
*dump_buf
)
536 CsrResult r
= CSR_RESULT_SUCCESS
;
539 /* Walk the table of coredump zone definitions and read them from the chip */
541 (i
< HIP_CDUMP_NUM_ZONES
) && (r
== 0);
544 r
= unifi_coredump_read_zone(card
, dump_buf
->zone
[i
], &zonedef_table
[i
]);
552 * ---------------------------------------------------------------------------
553 * unifi_coredump_from_sdio
555 * Capture the status of the UniFi processors, over SDIO
558 * card Pointer to card struct
559 * reg_buffer Buffer into which register values will be dumped
562 * CSR_RESULT_SUCCESS on success, or:
563 * CSR_RESULT_FAILURE SDIO error
564 * CSR_WIFI_HIP_RESULT_INVALID_VALUE Parameter error
567 * ---------------------------------------------------------------------------
569 static CsrResult
unifi_coredump_from_sdio(card_t
*card
, coredump_buffer
*dump_buf
)
575 if (dump_buf
== NULL
)
577 r
= CSR_WIFI_HIP_RESULT_INVALID_VALUE
;
582 /* Chip and firmware version */
583 unifi_trace(card
->ospriv
, UDBG4
, "Get chip version\n");
584 sdio_addr
= 2 * ChipHelper_GBL_CHIP_VERSION(card
->helper
);
587 r
= unifi_read_direct16(card
, sdio_addr
, &val
);
588 if (r
== CSR_WIFI_HIP_RESULT_NO_DEVICE
)
592 if (r
!= CSR_RESULT_SUCCESS
)
594 unifi_error(card
->ospriv
, "Can't read GBL_CHIP_VERSION\n");
598 dump_buf
->chip_ver
= val
;
599 dump_buf
->fw_ver
= card
->build_id
;
601 unifi_trace(card
->ospriv
, UDBG4
, "chip_ver 0x%04x, fw_ver %u\n",
602 dump_buf
->chip_ver
, dump_buf
->fw_ver
);
604 /* Capture the memory zones required from UniFi */
605 r
= unifi_coredump_read_zones(card
, dump_buf
);
606 if (r
== CSR_WIFI_HIP_RESULT_NO_DEVICE
)
610 if (r
!= CSR_RESULT_SUCCESS
)
612 unifi_error(card
->ospriv
, "Can't read UniFi memory areas\n");
618 } /* unifi_coredump_from_sdio() */
621 #ifndef UNIFI_DISABLE_COREDUMP
623 * ---------------------------------------------------------------------------
626 * Allocates a coredump linked-list node, and links it to the previous.
630 * prevnode Previous node to link into
633 * Pointer to valid coredump_buffer on success
634 * NULL on memory allocation failure
637 * Allocates "all or nothing"
638 * ---------------------------------------------------------------------------
641 coredump_buffer
* new_coredump_node(void *ospriv
, coredump_buffer
*prevnode
)
643 coredump_buffer
*newnode
= NULL
;
648 /* Allocate node header */
649 newnode
= kzalloc(sizeof(coredump_buffer
), GFP_KERNEL
);
655 /* Allocate chip memory zone capture buffers */
656 for (i
= 0; i
< HIP_CDUMP_NUM_ZONES
; i
++)
658 zone_size
= sizeof(u16
) * zonedef_table
[i
].length
;
659 newzone
= kzalloc(zone_size
, GFP_KERNEL
);
660 newnode
->zone
[i
] = newzone
;
663 unifi_error(ospriv
, "Out of memory on coredump zone %d (%d words)\n",
664 i
, zonedef_table
[i
].length
);
669 /* Clean up if any zone alloc failed */
672 for (i
= 0; newnode
->zone
[i
] != NULL
; i
++)
674 kfree(newnode
->zone
[i
]);
675 newnode
->zone
[i
] = NULL
;
679 /* Link to previous node */
680 newnode
->prev
= prevnode
;
683 prevnode
->next
= newnode
;
685 newnode
->next
= NULL
;
691 #endif /* UNIFI_DISABLE_COREDUMP */
694 * ---------------------------------------------------------------------------
695 * unifi_coredump_init
697 * Allocates buffers for the automatic SDIO core dump
700 * card Pointer to card struct
701 * num_dump_buffers Number of buffers to reserve for coredumps
704 * CSR_RESULT_SUCCESS on success, or:
705 * CSR_WIFI_HIP_RESULT_NO_MEMORY memory allocation failed
708 * Allocates space in advance, to be used for the last n coredump buffers
709 * the intention being that the size is sufficient for at least one dump,
711 * It's probably advisable to have at least 2 coredump buffers to allow
712 * one to be enquired with the unifi_coredump tool, while leaving another
713 * free for capturing.
714 * ---------------------------------------------------------------------------
716 CsrResult
unifi_coredump_init(card_t
*card
, u16 num_dump_buffers
)
718 #ifndef UNIFI_DISABLE_COREDUMP
719 void *ospriv
= card
->ospriv
;
720 coredump_buffer
*prev
= NULL
;
721 coredump_buffer
*newnode
= NULL
;
725 card
->request_coredump_on_reset
= 0;
726 card
->dump_next_write
= NULL
;
727 card
->dump_cur_read
= NULL
;
728 card
->dump_buf
= NULL
;
730 #ifndef UNIFI_DISABLE_COREDUMP
731 unifi_trace(ospriv
, UDBG1
,
732 "Allocate buffers for %d core dumps\n", num_dump_buffers
);
733 if (num_dump_buffers
== 0)
739 card
->dump_buf
= new_coredump_node(ospriv
, NULL
);
740 if (card
->dump_buf
== NULL
)
744 prev
= card
->dump_buf
;
745 newnode
= card
->dump_buf
;
747 /* Add each subsequent node at tail */
748 for (i
= 1; i
< num_dump_buffers
; i
++)
750 newnode
= new_coredump_node(ospriv
, prev
);
758 /* Link the first and last nodes to make the list circular */
759 card
->dump_buf
->prev
= newnode
;
760 newnode
->next
= card
->dump_buf
;
762 /* Set initial r/w access pointers */
763 card
->dump_next_write
= card
->dump_buf
;
764 card
->dump_cur_read
= NULL
;
766 unifi_trace(ospriv
, UDBG2
, "Core dump configured (%d dumps max)\n", i
);
770 return CSR_RESULT_SUCCESS
;
772 #ifndef UNIFI_DISABLE_COREDUMP
774 /* Unwind what we allocated so far */
775 unifi_error(ospriv
, "Out of memory allocating core dump node %d\n", i
);
776 unifi_coredump_free(card
);
777 return CSR_WIFI_HIP_RESULT_NO_MEMORY
;
779 } /* unifi_coreump_init() */
783 * ---------------------------------------------------------------------------
784 * unifi_coredump_free
786 * Free all memory dynamically allocated for core dump
789 * card Pointer to card struct
795 * ---------------------------------------------------------------------------
797 void unifi_coredump_free(card_t
*card
)
799 void *ospriv
= card
->ospriv
;
800 coredump_buffer
*node
, *del_node
;
804 unifi_trace(ospriv
, UDBG2
, "Core dump de-configured\n");
806 if (card
->dump_buf
== NULL
)
811 node
= card
->dump_buf
;
814 /* Free payload zones */
815 for (j
= 0; j
< HIP_CDUMP_NUM_ZONES
; j
++)
817 kfree(node
->zone
[j
]);
818 node
->zone
[j
] = NULL
;
828 } while ((node
!= NULL
) && (node
!= card
->dump_buf
));
830 unifi_trace(ospriv
, UDBG3
, "Freed %d coredump buffers\n", i
);
832 card
->dump_buf
= NULL
;
833 card
->dump_next_write
= NULL
;
834 card
->dump_cur_read
= NULL
;
835 } /* unifi_coredump_free() */