Skip to content

Commit 27158c7

Browse files
Yang Yinglianggregkh
authored andcommitted
ocxl: fix pci device refcount leak when calling get_function_0()
get_function_0() calls pci_get_domain_bus_and_slot(), as comment says, it returns a pci device with refcount increment, so after using it, pci_dev_put() needs be called. Get the device reference when get_function_0() is not called, so pci_dev_put() can be called in the error path and callers unconditionally. And add comment above get_dvsec_vendor0() to tell callers to call pci_dev_put(). Fixes: 87db757 ("ocxl: control via sysfs whether the FPGA is reloaded on a link reset") Suggested-by: Andrew Donnellan <[email protected]> Signed-off-by: Yang Yingliang <[email protected]> Acked-by: Andrew Donnellan <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent a4cb100 commit 27158c7

File tree

1 file changed

+19
-1
lines changed

1 file changed

+19
-1
lines changed

drivers/misc/ocxl/config.c

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,18 @@ static int read_dvsec_vendor(struct pci_dev *dev)
193193
return 0;
194194
}
195195

196+
/**
197+
* get_dvsec_vendor0() - Find a related PCI device (function 0)
198+
* @dev: PCI device to match
199+
* @dev0: The PCI device (function 0) found
200+
* @out_pos: The position of PCI device (function 0)
201+
*
202+
* Returns 0 on success, negative on failure.
203+
*
204+
* NOTE: If it's successful, the reference of dev0 is increased,
205+
* so after using it, the callers must call pci_dev_put() to give
206+
* up the reference.
207+
*/
196208
static int get_dvsec_vendor0(struct pci_dev *dev, struct pci_dev **dev0,
197209
int *out_pos)
198210
{
@@ -202,10 +214,14 @@ static int get_dvsec_vendor0(struct pci_dev *dev, struct pci_dev **dev0,
202214
dev = get_function_0(dev);
203215
if (!dev)
204216
return -1;
217+
} else {
218+
dev = pci_dev_get(dev);
205219
}
206220
pos = find_dvsec(dev, OCXL_DVSEC_VENDOR_ID);
207-
if (!pos)
221+
if (!pos) {
222+
pci_dev_put(dev);
208223
return -1;
224+
}
209225
*dev0 = dev;
210226
*out_pos = pos;
211227
return 0;
@@ -222,6 +238,7 @@ int ocxl_config_get_reset_reload(struct pci_dev *dev, int *val)
222238

223239
pci_read_config_dword(dev0, pos + OCXL_DVSEC_VENDOR_RESET_RELOAD,
224240
&reset_reload);
241+
pci_dev_put(dev0);
225242
*val = !!(reset_reload & BIT(0));
226243
return 0;
227244
}
@@ -243,6 +260,7 @@ int ocxl_config_set_reset_reload(struct pci_dev *dev, int val)
243260
reset_reload &= ~BIT(0);
244261
pci_write_config_dword(dev0, pos + OCXL_DVSEC_VENDOR_RESET_RELOAD,
245262
reset_reload);
263+
pci_dev_put(dev0);
246264
return 0;
247265
}
248266

0 commit comments

Comments
 (0)