mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-10 14:19:09 -04:00
msm: pci: Release spinlock before notifying client
Release spinlock before notifying client driver and acquire spinlock once done because once host notifies client driver with an event, client can schedule an recovery in same context before returning and expects an new event which could cause an race condition if spinlock is acquired. Also use list_for_each_entry_safe() while travesing the list of registered clients for notification. Change-Id: I6ae55032acdb1a5b14f473eadacb7a009a8df753 Signed-off-by: Vivek Pernamitta <vpernami@codeaurora.org>
This commit is contained in:
parent
8bbe418836
commit
130b3b8d8f
1 changed files with 17 additions and 4 deletions
|
|
@ -5031,13 +5031,13 @@ EXPORT_SYMBOL(msm_pcie_enumerate);
|
|||
static void msm_pcie_notify_client(struct msm_pcie_dev_t *dev,
|
||||
enum msm_pcie_event event)
|
||||
{
|
||||
struct msm_pcie_register_event *reg_itr;
|
||||
struct msm_pcie_register_event *reg_itr, *temp;
|
||||
struct msm_pcie_notify *notify;
|
||||
struct msm_pcie_notify client_notify;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&dev->evt_reg_list_lock, flags);
|
||||
list_for_each_entry(reg_itr, &dev->event_reg_list, node) {
|
||||
list_for_each_entry_safe(reg_itr, temp, &dev->event_reg_list, node) {
|
||||
if ((reg_itr->events & event) && reg_itr->callback) {
|
||||
notify = ®_itr->notify;
|
||||
client_notify.event = event;
|
||||
|
|
@ -5046,8 +5046,19 @@ static void msm_pcie_notify_client(struct msm_pcie_dev_t *dev,
|
|||
client_notify.options = notify->options;
|
||||
PCIE_DUMP(dev, "PCIe: callback RC%d for event %d\n",
|
||||
dev->rc_idx, event);
|
||||
|
||||
/* Release spinlock before notifying client driver
|
||||
* and acquire it once done because once host notifies
|
||||
* client driver with an event, client can schedule an
|
||||
* recovery in same context before returning and
|
||||
* expects an new event which could cause an race
|
||||
* condition if spinlock is acquired.
|
||||
*/
|
||||
spin_unlock_irqrestore(&dev->evt_reg_list_lock, flags);
|
||||
|
||||
reg_itr->callback(&client_notify);
|
||||
|
||||
spin_lock_irqsave(&dev->evt_reg_list_lock, flags);
|
||||
if ((reg_itr->options & MSM_PCIE_CONFIG_NO_RECOVERY) &&
|
||||
(event == MSM_PCIE_EVENT_LINKDOWN)) {
|
||||
dev->user_suspend = true;
|
||||
|
|
@ -8050,7 +8061,7 @@ int msm_pcie_register_event(struct msm_pcie_register_event *reg)
|
|||
{
|
||||
int ret = 0;
|
||||
struct msm_pcie_dev_t *pcie_dev;
|
||||
struct msm_pcie_register_event *reg_itr;
|
||||
struct msm_pcie_register_event *reg_itr, *temp;
|
||||
struct pci_dev *pcidev;
|
||||
unsigned long flags;
|
||||
|
||||
|
|
@ -8074,7 +8085,9 @@ int msm_pcie_register_event(struct msm_pcie_register_event *reg)
|
|||
pcidev = (struct pci_dev *)reg->user;
|
||||
|
||||
spin_lock_irqsave(&pcie_dev->evt_reg_list_lock, flags);
|
||||
list_for_each_entry(reg_itr, &pcie_dev->event_reg_list, node) {
|
||||
list_for_each_entry_safe(reg_itr, temp,
|
||||
&pcie_dev->event_reg_list, node) {
|
||||
|
||||
if (reg_itr->user == reg->user) {
|
||||
PCIE_ERR(pcie_dev,
|
||||
"PCIe: RC%d: EP BDF 0x%4x already registered\n",
|
||||
|
|
|
|||
Loading…
Reference in a new issue