Patch "PCI: endpoint: Use a separate lock for protecting epc->pci_epf list" has been added to the 6.1-stable tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This is a note to let you know that I've just added the patch titled

    PCI: endpoint: Use a separate lock for protecting epc->pci_epf list

to the 6.1-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     pci-endpoint-use-a-separate-lock-for-protecting-epc-.patch
and it can be found in the queue-6.1 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@xxxxxxxxxxxxxxx> know about it.



commit 56121f3580a0240030f74947b95bebd37adddf0e
Author: Manivannan Sadhasivam <manivannan.sadhasivam@xxxxxxxxxx>
Date:   Tue Jan 24 12:41:56 2023 +0530

    PCI: endpoint: Use a separate lock for protecting epc->pci_epf list
    
    [ Upstream commit d6dd5bafaabf98a99a76227ab8dc9a89e76a198f ]
    
    The EPC controller maintains a list of EPF drivers added to it. For
    protecting this list against the concurrent accesses, the epc->lock
    (used for protecting epc_ops) has been used so far. Since there were
    no users trying to use epc_ops and modify the pci_epf list simultaneously,
    this was not an issue.
    
    But with the addition of callback mechanism for passing the events, this
    will be a problem. Because the pci_epf list needs to be iterated first
    for getting hold of the EPF driver and then the relevant event specific
    callback needs to be called for the driver.
    
    If the same epc->lock is used, then it will result in a deadlock scenario.
    
    For instance,
    
    ...
            mutex_lock(&epc->lock);
            list_for_each_entry(epf, &epc->pci_epf, list) {
                    epf->event_ops->core_init(epf);
                    |
                    |-> pci_epc_set_bar();
                            |
                            |-> mutex_lock(&epc->lock) # DEADLOCK
    ...
    
    So to fix this issue, use a separate lock called "list_lock" for
    protecting the pci_epf list against the concurrent accesses. This lock
    will also be used by the callback mechanism.
    
    Link: https://lore.kernel.org/linux-pci/20230124071158.5503-4-manivannan.sadhasivam@xxxxxxxxxx
    Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@xxxxxxxxxx>
    Signed-off-by: Krzysztof Wilczyński <kwilczynski@xxxxxxxxxx>
    Acked-by: Kishon Vijay Abraham I <kishon@xxxxxx>
    Stable-dep-of: 688d2eb4c6fc ("PCI: endpoint: Clear secondary (not primary) EPC in pci_epc_remove_epf()")
    Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>

diff --git a/drivers/pci/endpoint/pci-epc-core.c b/drivers/pci/endpoint/pci-epc-core.c
index 3bc9273d0a082..6cce430d431b1 100644
--- a/drivers/pci/endpoint/pci-epc-core.c
+++ b/drivers/pci/endpoint/pci-epc-core.c
@@ -613,7 +613,7 @@ int pci_epc_add_epf(struct pci_epc *epc, struct pci_epf *epf,
 	if (type == SECONDARY_INTERFACE && epf->sec_epc)
 		return -EBUSY;
 
-	mutex_lock(&epc->lock);
+	mutex_lock(&epc->list_lock);
 	func_no = find_first_zero_bit(&epc->function_num_map,
 				      BITS_PER_LONG);
 	if (func_no >= BITS_PER_LONG) {
@@ -640,7 +640,7 @@ int pci_epc_add_epf(struct pci_epc *epc, struct pci_epf *epf,
 
 	list_add_tail(list, &epc->pci_epf);
 ret:
-	mutex_unlock(&epc->lock);
+	mutex_unlock(&epc->list_lock);
 
 	return ret;
 }
@@ -672,11 +672,11 @@ void pci_epc_remove_epf(struct pci_epc *epc, struct pci_epf *epf,
 		list = &epf->sec_epc_list;
 	}
 
-	mutex_lock(&epc->lock);
+	mutex_lock(&epc->list_lock);
 	clear_bit(func_no, &epc->function_num_map);
 	list_del(list);
 	epf->epc = NULL;
-	mutex_unlock(&epc->lock);
+	mutex_unlock(&epc->list_lock);
 }
 EXPORT_SYMBOL_GPL(pci_epc_remove_epf);
 
@@ -773,6 +773,7 @@ __pci_epc_create(struct device *dev, const struct pci_epc_ops *ops,
 	}
 
 	mutex_init(&epc->lock);
+	mutex_init(&epc->list_lock);
 	INIT_LIST_HEAD(&epc->pci_epf);
 	ATOMIC_INIT_NOTIFIER_HEAD(&epc->notifier);
 
diff --git a/include/linux/pci-epc.h b/include/linux/pci-epc.h
index a48778e1a4ee3..fe729dfe509b8 100644
--- a/include/linux/pci-epc.h
+++ b/include/linux/pci-epc.h
@@ -122,6 +122,7 @@ struct pci_epc_mem {
  * struct pci_epc - represents the PCI EPC device
  * @dev: PCI EPC device
  * @pci_epf: list of endpoint functions present in this EPC device
+ * list_lock: Mutex for protecting pci_epf list
  * @ops: function pointers for performing endpoint operations
  * @windows: array of address space of the endpoint controller
  * @mem: first window of the endpoint controller, which corresponds to
@@ -139,6 +140,7 @@ struct pci_epc_mem {
 struct pci_epc {
 	struct device			dev;
 	struct list_head		pci_epf;
+	struct mutex			list_lock;
 	const struct pci_epc_ops	*ops;
 	struct pci_epc_mem		**windows;
 	struct pci_epc_mem		*mem;




[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux