Both priority inheritance and priority ceiling protocols are used to minimise the consequences of a race condition. They both dynamically change the priority of tasks that hold a resource, needed for execution of a higher-priority task, which "unstucks" it.
What I cannot find in any literature is:
The difference between them lies in the exact time when the priority of a low-priority task that holds a shared resource, is raised.
Priority ceiling raises it immediately to the highest priority, which lead to a worse average-case performance time—even if the resource is uncontested, the algorithm still triggers. But triggers only once, contributing to its good worst-case performance. Priority ceiling is completely deadlock-safe.
Priority inheritance is only doing it each time a high-priority task tries to contest the shared resource, taken by a low-priority task. Is not beneficial, if a lot of tasks contest the resource, for the algorithm is triggered every time. In FreeRTOS, it is implemented by default when using mutexes to secure a critical section.