Fix find_first_zero_bit() usage
Subsystems (2)
v2 cover Fix find_first_zero_bit() usage
From: Niklas Cassel <[email protected]>
find_first_zero_bit()'s parameter 'size' is defined in bits, not in bytes.
Calling find_first_zero_bit() with the wrong size unit will lead to insidious bugs.
Fix all uses of find_first_zero_bit() called withsizeof() as size argument in drivers/pci.
Niklas Cassel (2):
PCI: designware-ep: Fix find_first_zero_bit() usage
PCI: endpoint: Fix find_first_zero_bit() usage
drivers/pci/dwc/pcie-designware-ep.c | 6 ++---- drivers/pci/endpoint/pci-ep-cfs.c | 3 +-- 2 files changed, 3 insertions(+), 6 deletions(-)
Signature · 1 line
2.14.2
PATCH v2 1/2 PCI: designware-ep: Fix find_first_zero_bit() usage
find_first_zero_bit()'s parameter 'size' is defined in bits, not in bytes.
find_first_zero_bit() was called with size in bytes rather than bits, which thus defined a too low upper limit, causing dw_pcie_ep_inbound_atu() to assign iatu index #4 to both bar 4 and bar 5, which made bar 5 overwrite the settings set by bar 4.
Fix this by using replacing find_first_zero_bit() with ffz(), since ffz() only works on a single 'unsigned long' and therefore does not need a size argument.
--- drivers/pci/dwc/pcie-designware-ep.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-)
drivers/pci/dwc/pcie-designware-ep.c +2 -4
@@ -70,8 +70,7 @@ static int dw_pcie_ep_inbound_atu(struct dw_pcie_ep *ep, enum pci_barno bar,u32 free_win;struct dw_pcie *pci =to_dw_pcie_from_ep (ep); - free_win =find_first_zero_bit (&ep->ib_window_map, -sizeof (ep->ib_window_map)); + free_win =ffz (ep->ib_window_map);if (free_win >= ep->num_ib_windows) {dev_err (pci->dev,"no free inbound window\n" );return -EINVAL ;
@@ -96,8 +95,7 @@ static int dw_pcie_ep_outbound_atu(struct dw_pcie_ep *ep, phys_addr_t phys_addr,u32 free_win;struct dw_pcie *pci =to_dw_pcie_from_ep (ep); - free_win =find_first_zero_bit (&ep->ob_window_map, -sizeof (ep->ob_window_map)); + free_win =ffz (ep->ob_window_map);if (free_win >= ep->num_ob_windows) {dev_err (pci->dev,"no free outbound window\n" );return -EINVAL ;
Signature · 1 line
2.14.2
Re: [PATCH v2 1/2] PCI: designware-ep: Fix find_first_zero_bit() usage
[+Kishon - please CC him next time]
Quoted 23 lines · Niklas Cassel
find_first_zero_bit()'s parameter 'size' is defined in bits, not in bytes.
find_first_zero_bit()was called with size in bytes rather than bits, which thus defined a too low upper limit, causingdw_pcie_ep_inbound_atu()to assign iatu index #4 to both bar 4 and bar 5, which made bar 5 overwrite the settings set by bar 4.Fix this by using replacing
find_first_zero_bit()withffz(), sinceffz()only works on a single 'unsigned long' and therefore does not need a size argument.Fixes f8aed6ec624f ("PCI: dwc: designware: Add EP mode support")Signed-off-by Niklas Cassel <[email protected]>--- drivers/pci/dwc/pcie-designware-ep.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-)drivers/pci/dwc/pcie-designware-ep.c +0
-0
drivers/pci/dwc/pcie-designware-ep.c static int dw_pcie_ep_inbound_atu(struct dw_pcie_ep *ep, enum pci_barno bar, · line 73
Quoted 6 lines
drivers/pci/dwc/pcie-designware-ep.c +1
-2@@ -70,8 +70,7 @@ static int dw_pcie_ep_inbound_atu(struct dw_pcie_ep *ep, enum pci_barno bar,u32 free_win;struct dw_pcie *pci =to_dw_pcie_from_ep (ep); - free_win =find_first_zero_bit (&ep->ib_window_map, -sizeof (ep->ib_window_map)); + free_win =ffz (ep->ib_window_map);
You fix the bug at hand but code suffers from the same issue since we should be checking the value against ~0UL first ie if size in bits < num_ib_windows (that I think it is unlikely anyway but while at it let's think if we can improve this).
@Kishon: maybe we should add a static upper size and declare a static bitmap accordingly (and still use find_first_zero_bit()) ?
I think the check against ~0UL should be added anyway, let's get Kishon's opinion before a v3 (if any).
Thanks,
Lorenzo
Quoted 16 lines
drivers/pci/dwc/pcie-designware-ep.c +1
-2if (free_win >= ep->num_ib_windows) {dev_err (pci->dev,"no free inbound window\n" );return -EINVAL ;@@ -96,8 +95,7 @@ static int dw_pcie_ep_outbound_atu(struct dw_pcie_ep *ep, phys_addr_t phys_addr,u32 free_win;struct dw_pcie *pci =to_dw_pcie_from_ep (ep); - free_win =find_first_zero_bit (&ep->ob_window_map, -sizeof (ep->ob_window_map)); + free_win =ffz (ep->ob_window_map);if (free_win >= ep->num_ob_windows) {dev_err (pci->dev,"no free outbound window\n" );return -EINVAL ;Signature · 1 line
2.14.2
Re: [PATCH v2 1/2] PCI: designware-ep: Fix find_first_zero_bit() usage
Hi Lorenzo,
Quoted 38 lines · Lorenzo Pieralisi
[+Kishon - please CC him next time]
Quoted 23 lines · Niklas Cassel
find_first_zero_bit()'s parameter 'size' is defined in bits, not in bytes.
find_first_zero_bit()was called with size in bytes rather than bits, which thus defined a too low upper limit, causingdw_pcie_ep_inbound_atu()to assign iatu index #4 to both bar 4 and bar 5, which made bar 5 overwrite the settings set by bar 4.Fix this by using replacing
find_first_zero_bit()withffz(), sinceffz()only works on a single 'unsigned long' and therefore does not need a size argument.Fixes f8aed6ec624f ("PCI: dwc: designware: Add EP mode support")Signed-off-by Niklas Cassel <[email protected]>--- drivers/pci/dwc/pcie-designware-ep.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-)drivers/pci/dwc/pcie-designware-ep.c +0
-0drivers/pci/dwc/pcie-designware-ep.c static int dw_pcie_ep_inbound_atu(struct dw_pcie_ep *ep, enum pci_barno bar, · line 73
Quoted 6 lines
drivers/pci/dwc/pcie-designware-ep.c +1
-2@@ -70,8 +70,7 @@ static int dw_pcie_ep_inbound_atu(struct dw_pcie_ep *ep, enum pci_barno bar,u32 free_win;struct dw_pcie *pci =to_dw_pcie_from_ep (ep); - free_win =find_first_zero_bit (&ep->ib_window_map, -sizeof (ep->ib_window_map)); + free_win =ffz (ep->ib_window_map);You fix the bug at hand but code suffers from the same issue since we should be checking the value against ~0UL first ie if size in bits <
num_ib_windows(that I think it is unlikely anyway but while at it let's think if we can improve this).
Quoted 5 lines
@Kishon: maybe we should add a static upper size and declare a static bitmap accordingly (and still use
find_first_zero_bit()) ?I think the check against ~0UL should be added anyway, let's get Kishon's opinion before a v3 (if any).
Yeah, for both ffz and find_first_zero_bit, the results are undefined if no zero exists.
I'm thinking if we should just use find_first_zero_bit(&ep->ib_window_map, ep->num_ib_windows) after checking if there are some '0' bits left.
Thanks
Kishon
Re: [PATCH v2 1/2] PCI: designware-ep: Fix find_first_zero_bit() usage
Quoted 47 lines · Kishon Vijay Abraham I
Hi Lorenzo,
Quoted 38 lines · Lorenzo Pieralisi
[+Kishon - please CC him next time]
Quoted 23 lines · Niklas Cassel
find_first_zero_bit()'s parameter 'size' is defined in bits, not in bytes.
find_first_zero_bit()was called with size in bytes rather than bits, which thus defined a too low upper limit, causingdw_pcie_ep_inbound_atu()to assign iatu index #4 to both bar 4 and bar 5, which made bar 5 overwrite the settings set by bar 4.Fix this by using replacing
find_first_zero_bit()withffz(), sinceffz()only works on a single 'unsigned long' and therefore does not need a size argument.Fixes f8aed6ec624f ("PCI: dwc: designware: Add EP mode support")Signed-off-by Niklas Cassel <[email protected]>--- drivers/pci/dwc/pcie-designware-ep.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-)drivers/pci/dwc/pcie-designware-ep.c +0
-0drivers/pci/dwc/pcie-designware-ep.c static int dw_pcie_ep_inbound_atu(struct dw_pcie_ep *ep, enum pci_barno bar, · line 73
Quoted 6 lines
drivers/pci/dwc/pcie-designware-ep.c +1
-2@@ -70,8 +70,7 @@ static int dw_pcie_ep_inbound_atu(struct dw_pcie_ep *ep, enum pci_barno bar,u32 free_win;struct dw_pcie *pci =to_dw_pcie_from_ep (ep); - free_win =find_first_zero_bit (&ep->ib_window_map, -sizeof (ep->ib_window_map)); + free_win =ffz (ep->ib_window_map);You fix the bug at hand but code suffers from the same issue since we should be checking the value against ~0UL first ie if size in bits <
num_ib_windows(that I think it is unlikely anyway but while at it let's think if we can improve this).Quoted 5 lines
@Kishon: maybe we should add a static upper size and declare a static bitmap accordingly (and still use
find_first_zero_bit()) ?I think the check against ~0UL should be added anyway, let's get Kishon's opinion before a v3 (if any).
Quoted 6 lines
Yeah, for both ffz and
find_first_zero_bit, the results are undefined if no zero exists.I'm thinking if we should just use
find_first_zero_bit(&ep->ib_window_map, ep->num_ib_windows)after checking if there are some '0' bits left.
Well yes but first the &ep->ib_window_map must be sized accordingly.
Lorenzo
PATCH v2 2/2 PCI: endpoint: Fix find_first_zero_bit() usage
In reply to Niklas Casselfind_first_zero_bit()'s parameter 'size' is defined in bits, not in bytes.
Calling find_first_zero_bit() with the wrong size unit will lead to insidious bugs.
Fix this by using replacing find_first_zero_bit() with ffz(), since ffz() only works on a single 'unsigned long' and therefore does not need a size argument.
--- drivers/pci/endpoint/pci-ep-cfs.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
drivers/pci/endpoint/pci-ep-cfs.c +1 -2
@@ -108,8 +108,7 @@ static int pci_epc_epf_link(struct config_item *epc_item,if (ret) goto err_add_epf; - func_no =find_first_zero_bit (&epc_group->function_num_map, -sizeof (epc_group->function_num_map)); + func_no =ffz (epc_group->function_num_map);set_bit (func_no, &epc_group->function_num_map); epf->func_no = func_no;
Signature · 1 line
2.14.2