Skip to content

Commit

Permalink
Adding helper functions for switching of devtree backend in the same …
Browse files Browse the repository at this point in the history
…process

Context: It is now required that the devtree backend in BMC systems should be
able to switch in the same process on runtime e.g.; from KERNEL to
SBEFIFO or vice-versa. This is to support running extract SBE RC hardware procedure.
This commit introduces the necessary changes in order to achieve that.

Solution: It basically introduces few functions which
will clear the pdbg_dt_root and its associated children subsequently
if the pdbg_targets_init function is called more than once now
(earlier it was not allowed to call pdbg_targets_init function twice
in the same process)

Test-1: The switching of the backend in the same process was tested
through a standalone application which runs in a loop for multiple times
and each time it sets the intial backend to SBEFIFO first and then
switched it to KERNEL. Trace log is attached along with the PR

Test-2: While booting BMC up injected a clock error dueing IPL in
between istep0 to istep2 and call the SBR RC extract procedure
to get the error code after switching the backend from SBEFIFO to
KERNEL. Once the extraction is done switched back to SBEFIFO for
further processing. Journal log is attached with the PR.

Signed-off-by: swarnendu.roy.chowdhury@ibm.com
  • Loading branch information
Swarnendu-R-C committed May 30, 2023
1 parent 49d08f7 commit 4579008
Show file tree
Hide file tree
Showing 5 changed files with 112 additions and 2 deletions.
67 changes: 67 additions & 0 deletions libpdbg/device.c
Original file line number Diff line number Diff line change
Expand Up @@ -701,6 +701,73 @@ static void pdbg_targets_init_virtual(struct pdbg_target *node, struct pdbg_targ
}
}

/**
* @brief It releases/deletes a target from its target_class list.
* Each pdbg_target object (except the virtuals one) has an
* associated target class linked via it's class_link. This
* function deletes/removes a target form the list of associated
* pdbg_target_class object. For internal use only.
*
* @param target The pdbg_target object which will be removed from it's associated
* pdbg_target_class list
*
* @see pdbg_release_target for more details
*/
static void pdbg_del_target_from_target_class_list(struct pdbg_target* target)
{
if (!target)
return;

struct pdbg_target_class* target_class = get_target_class(target);
if (target_class)
list_del_from(&target_class->targets, &target->class_link);
}

/**
* @brief A function to delete/release an existing pdbg_target object along
* with its children from the node list/dev tree. Should be only called
* internally. Recursive in nature. For internal use only.
*
* @param target The target node for which the children and then the node itself
* will be released/freed
*
* @see pdbg_release_dt_root for more details
*/
static void pdbg_release_target(struct pdbg_target* target)
{
if (!target)
return;

struct pdbg_target *childTarget, *next = NULL;
list_for_each_safe(&target->children, childTarget, next, list)
pdbg_release_target(childTarget);

if (target->class)
pdbg_del_target_from_target_class_list(target);

struct pdbg_target* parentTarget = target->parent;
if (parentTarget)
list_del_from(&parentTarget->children, &target->list);

if (target)
free(target);
target = NULL;
}

void pdbg_release_dt_root()
{
if (pdbg_dt_root)
{
pdbg_release_target(pdbg_dt_root);
if (pdbg_dt_root)
pdbg_dt_root = NULL;
//Reset the phandle count to zero
last_phandle = 0;
//Clear the existing target classes
clear_target_classes();
}
}

bool pdbg_targets_init(void *fdt)
{
struct pdbg_dtb *dtb;
Expand Down
11 changes: 9 additions & 2 deletions libpdbg/dtb.c
Original file line number Diff line number Diff line change
Expand Up @@ -412,8 +412,15 @@ static void mmap_dtb(const char *file, bool readonly, struct pdbg_mfile *mfile)

bool pdbg_set_backend(enum pdbg_backend backend, const char *backend_option)
{
if (pdbg_target_root()) {
pdbg_log(PDBG_ERROR, "pdbg_set_backend() must be called before pdbg_targets_init()\n");
if (pdbg_target_root())
{
pdbg_log(PDBG_ERROR, "pdbg_set_backend() must be called before pdbg_targets_init() or after calling pdbg_release_dt_root() if a dev tree is already set\n");
return false;
}

if (pdbg_backend == backend)
{
pdbg_log(PDBG_ERROR, "New backend is same as the current backend. Not proceeding further\n");
return false;
}

Expand Down
12 changes: 12 additions & 0 deletions libpdbg/libpdbg.h
Original file line number Diff line number Diff line change
Expand Up @@ -1452,6 +1452,18 @@ void pdbg_log(int loglevel, const char *fmt, ...);
*/
bool pdbg_context_short(void);

/**
* @brief Clears/Releases the existing device tree and it's root node
*
* This function needs to be called if for some very good reason we are
* switching the backend in the same process. It clears/releases the
* existing dev tree (if any) children by children along with the root node.
*
* Call this function very judiciously before ##pdbg_set_backend() if there is a
* dev tree already is in place and we are switching the backend
*/
void pdbg_release_dt_root();

#ifdef __cplusplus
}
#endif
Expand Down
12 changes: 12 additions & 0 deletions libpdbg/target.c
Original file line number Diff line number Diff line change
Expand Up @@ -638,3 +638,15 @@ struct pdbg_target *target_to_virtual(struct pdbg_target *target, bool strict)

return target;
}

void clear_target_classes()
{
struct pdbg_target_class *child, *next = NULL;
list_for_each_safe(&target_classes, child, next, class_head_link)
{
list_del_from(&target_classes, &child->class_head_link);
if (child)
free(child);
child = NULL;
}
}
12 changes: 12 additions & 0 deletions libpdbg/target.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,18 @@ struct pdbg_target_class *require_target_class(const char *name);
struct pdbg_target_class *get_target_class(struct pdbg_target *target);
bool pdbg_target_is_class(struct pdbg_target *target, const char *class);

/**
* @brief Clears the list of target classes
* It clears the list of target classes
* from the global static list target_classes
* once the device tree is cleared and associated
* all pdbg_target objects are destroyed
*
* @see pdbg_release_dt_root() for more details
*
*/
void clear_target_classes();

extern struct list_head empty_list;
extern struct list_head target_classes;

Expand Down

0 comments on commit 4579008

Please sign in to comment.