RE: [PATCH v2 1/2] PCI: hv: Fix the PCI HyperV probe failure path to release resource properly
From: Wei Hu <hidden>
Date: 2020-05-06 05:36:55
Also in:
linux-pci, lkml
Hi Lorenzo, Thanks for your review. Please see my comments inline.
-----Original Message----- From: Lorenzo Pieralisi <redacted> Sent: Tuesday, May 5, 2020 11:03 PM To: Wei Hu <redacted> Cc: KY Srinivasan <kys@microsoft.com>; Haiyang Zhang [off-list ref]; Stephen Hemminger [off-list ref]; wei.liu@kernel.org; robh@kernel.org; bhelgaas@google.com; linux- hyperv@vger.kernel.org; linux-pci@vger.kernel.org; linux- kernel@vger.kernel.org; Dexuan Cui [off-list ref]; Michael Kelley [off-list ref] Subject: Re: [PATCH v2 1/2] PCI: hv: Fix the PCI HyperV probe failure path to release resource properly On Fri, May 01, 2020 at 01:36:17PM +0800, Wei Hu wrote:quoted
Some error cases in hv_pci_probe() were not handled. Fix these error paths to release the resourses and clean up the state properly.This patch does more than that. It adds a variable to store the number of slots actually allocated - I presume to free only allocated on slots on the exit path. Two patches required I am afraid.
Well, adding this variable is needed to make the call of "(void) hv_pci_bus_exit(hdev, true)" at the end to work and clean up the PCI state in the failure path. Just adding this variable would not make any changes. So I think it may be better to put them in single patch?
quoted
Signed-off-by: Wei Hu <redacted> --- drivers/pci/controller/pci-hyperv.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-)diff --git a/drivers/pci/controller/pci-hyperv.cb/drivers/pci/controller/pci-hyperv.c index e15022ff63e3..e6fac0187722 100644--- a/drivers/pci/controller/pci-hyperv.c +++ b/drivers/pci/controller/pci-hyperv.c@@ -480,6 +480,9 @@ struct hv_pcibus_device { struct workqueue_struct *wq; + /* Highest slot of child device with resources allocated */ + int wslot_res_allocated;I don't understand why you need an int rather than a u32. Furthermore, I think a bitmap is more appropriate for what this variable is used for.
So it can use a negative value (-1 in this case) to indicated none of any resources has been allocated. Currently value between 0-255 indicating some resources have been allocated. Of course I can use 0xffffffff to indicate that if it were u32. But it wouldn't make much difference, would it? It would take 32 bytes for total 256 child slots in bitmap, while it only takes 4 bytes using int. It is not in critical path so scanning from the location one by one is not a big deal.
quoted
+ /* hypercall arg, must not cross page boundary */ struct hv_retarget_device_interrupt retarget_msi_interrupt_params;@@ -2847,7 +2850,7 @@ static int hv_send_resources_allocated(structhv_device *hdev)quoted
struct hv_pci_dev *hpdev; struct pci_packet *pkt; size_t size_res; - u32 wslot; + int wslot; int ret; size_res = (hbus->protocol_version < PCI_PROTOCOL_VERSION_1_2)@@quoted
-2900,6 +2903,8 @@ static int hv_send_resources_allocated(struct hv_device*hdev)quoted
comp_pkt.completion_status); break; } + + hbus->wslot_res_allocated = wslot; } kfree(pkt);@@ -2918,10 +2923,10 @@ static int hv_send_resources_released(structhv_device *hdev)quoted
struct hv_pcibus_device *hbus = hv_get_drvdata(hdev); struct pci_child_message pkt; struct hv_pci_dev *hpdev; - u32 wslot; + int wslot; int ret; - for (wslot = 0; wslot < 256; wslot++) { + for (wslot = hbus->wslot_res_allocated; wslot >= 0; wslot--) { hpdev = get_pcichild_wslot(hbus, wslot); if (!hpdev) continue;@@ -2936,8 +2941,12 @@ static int hv_send_resources_released(structhv_device *hdev)quoted
VM_PKT_DATA_INBAND, 0); if (ret) return ret; + + hbus->wslot_res_allocated = wslot - 1;Do you really need to set it at every loop iteration ? Moreover, I think a bitmap is better suited for what you are doing, given that you may skip some loop indexes on !hpdev.
The value is set in the loop whenever a resource was successfully released. It could happen that it failed in the next iteration so the last one which had succeeded would be recorded in this variable. It is needed at the end of loop when this iteration succeeds. Once again since it is not in the critical path, just using an signed integer is straightforward, less error prone and a bit easier to maintain than bitmap in my opinion. 😊
quoted
} + hbus->wslot_res_allocated = -1; + return 0; }@@ -3037,6 +3046,7 @@ static int hv_pci_probe(struct hv_device *hdev, if (!hbus) return -ENOMEM; hbus->state = hv_pcibus_init; + hbus->wslot_res_allocated = -1; /* * The PCI bus "domain" is what is called "segment" in ACPI andother @@ -3136,7 +3146,7 @@ static int hv_pci_probe(struct hv_device *hdev, ret = hv_pci_allocate_bridge_windows(hbus); if (ret) - goto free_irq_domain; + goto exit_d0; ret = hv_send_resources_allocated(hdev); if (ret)@@ -3154,6 +3164,8 @@ static int hv_pci_probe(struct hv_device *hdev, free_windows: hv_pci_free_bridge_windows(hbus); +exit_d0: + (void) hv_pci_bus_exit(hdev, true);Remove the (void) cast.
Some tools (maybe lint?) could generate error/warning messages assuming the code fails to check the return value without such cast. Leaving the cast in place just indicates that the return value is deliberately ignored. Thanks, Wei