diff options
author | Arnd Bergmann <arnd@arndb.de> | 2016-06-01 09:29:13 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2016-06-02 01:04:54 -0400 |
commit | 14b84e8654c89ed59f433654e6bb64c886d095cd (patch) | |
tree | 133468288259491c2cc894f757f51d5a3a763b8b | |
parent | bfa49cfc526201119623de6593d284c96563bede (diff) |
qed: fix qed_fill_link() error handling
gcc warns about qed_fill_link possibly accessing uninitialized data:
drivers/net/ethernet/qlogic/qed/qed_main.c: In function 'qed_fill_link':
drivers/net/ethernet/qlogic/qed/qed_main.c:1170:35: error: 'link_caps' may be used uninitialized in this function [-Werror=maybe-uninitialized]
While this warning is only about the specific case of CONFIG_QED_SRIOV
being disabled but the function getting called for a VF (which should
never happen), another possibility is that qed_mcp_get_*() fails without
returning data.
This rearranges the code so we bail out in either of the two cases
and print a warning instead of accessing the uninitialized data.
The qed_link_output structure remains untouched in this case, but
all callers first call memset() on it, so at least we are not leaking
stack data then.
As discussed, we also use a compile-time check to ensure we never
use any of the VF code if CONFIG_QED_SRIOV is disabled, and the
PCI device table is updated to no longer bind to virtual functions
in that configuration.
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Acked-by: Yuval Mintz <Yuval.Mintz@qlogic.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/ethernet/qlogic/qed/qed_main.c | 45 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/qed/qed_sriov.h | 4 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/qede/qede_main.c | 2 |
3 files changed, 41 insertions, 10 deletions
diff --git a/drivers/net/ethernet/qlogic/qed/qed_main.c b/drivers/net/ethernet/qlogic/qed/qed_main.c index 753064679bde..61cc6869fa65 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_main.c +++ b/drivers/net/ethernet/qlogic/qed/qed_main.c | |||
@@ -1105,6 +1105,39 @@ static int qed_get_port_type(u32 media_type) | |||
1105 | return port_type; | 1105 | return port_type; |
1106 | } | 1106 | } |
1107 | 1107 | ||
1108 | static int qed_get_link_data(struct qed_hwfn *hwfn, | ||
1109 | struct qed_mcp_link_params *params, | ||
1110 | struct qed_mcp_link_state *link, | ||
1111 | struct qed_mcp_link_capabilities *link_caps) | ||
1112 | { | ||
1113 | void *p; | ||
1114 | |||
1115 | if (!IS_PF(hwfn->cdev)) { | ||
1116 | qed_vf_get_link_params(hwfn, params); | ||
1117 | qed_vf_get_link_state(hwfn, link); | ||
1118 | qed_vf_get_link_caps(hwfn, link_caps); | ||
1119 | |||
1120 | return 0; | ||
1121 | } | ||
1122 | |||
1123 | p = qed_mcp_get_link_params(hwfn); | ||
1124 | if (!p) | ||
1125 | return -ENXIO; | ||
1126 | memcpy(params, p, sizeof(*params)); | ||
1127 | |||
1128 | p = qed_mcp_get_link_state(hwfn); | ||
1129 | if (!p) | ||
1130 | return -ENXIO; | ||
1131 | memcpy(link, p, sizeof(*link)); | ||
1132 | |||
1133 | p = qed_mcp_get_link_capabilities(hwfn); | ||
1134 | if (!p) | ||
1135 | return -ENXIO; | ||
1136 | memcpy(link_caps, p, sizeof(*link_caps)); | ||
1137 | |||
1138 | return 0; | ||
1139 | } | ||
1140 | |||
1108 | static void qed_fill_link(struct qed_hwfn *hwfn, | 1141 | static void qed_fill_link(struct qed_hwfn *hwfn, |
1109 | struct qed_link_output *if_link) | 1142 | struct qed_link_output *if_link) |
1110 | { | 1143 | { |
@@ -1116,15 +1149,9 @@ static void qed_fill_link(struct qed_hwfn *hwfn, | |||
1116 | memset(if_link, 0, sizeof(*if_link)); | 1149 | memset(if_link, 0, sizeof(*if_link)); |
1117 | 1150 | ||
1118 | /* Prepare source inputs */ | 1151 | /* Prepare source inputs */ |
1119 | if (IS_PF(hwfn->cdev)) { | 1152 | if (qed_get_link_data(hwfn, ¶ms, &link, &link_caps)) { |
1120 | memcpy(¶ms, qed_mcp_get_link_params(hwfn), sizeof(params)); | 1153 | dev_warn(&hwfn->cdev->pdev->dev, "no link data available\n"); |
1121 | memcpy(&link, qed_mcp_get_link_state(hwfn), sizeof(link)); | 1154 | return; |
1122 | memcpy(&link_caps, qed_mcp_get_link_capabilities(hwfn), | ||
1123 | sizeof(link_caps)); | ||
1124 | } else { | ||
1125 | qed_vf_get_link_params(hwfn, ¶ms); | ||
1126 | qed_vf_get_link_state(hwfn, &link); | ||
1127 | qed_vf_get_link_caps(hwfn, &link_caps); | ||
1128 | } | 1155 | } |
1129 | 1156 | ||
1130 | /* Set the link parameters to pass to protocol driver */ | 1157 | /* Set the link parameters to pass to protocol driver */ |
diff --git a/drivers/net/ethernet/qlogic/qed/qed_sriov.h b/drivers/net/ethernet/qlogic/qed/qed_sriov.h index c8667c65e685..c90b2b6ad969 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_sriov.h +++ b/drivers/net/ethernet/qlogic/qed/qed_sriov.h | |||
@@ -12,11 +12,13 @@ | |||
12 | #include "qed_vf.h" | 12 | #include "qed_vf.h" |
13 | #define QED_VF_ARRAY_LENGTH (3) | 13 | #define QED_VF_ARRAY_LENGTH (3) |
14 | 14 | ||
15 | #ifdef CONFIG_QED_SRIOV | ||
15 | #define IS_VF(cdev) ((cdev)->b_is_vf) | 16 | #define IS_VF(cdev) ((cdev)->b_is_vf) |
16 | #define IS_PF(cdev) (!((cdev)->b_is_vf)) | 17 | #define IS_PF(cdev) (!((cdev)->b_is_vf)) |
17 | #ifdef CONFIG_QED_SRIOV | ||
18 | #define IS_PF_SRIOV(p_hwfn) (!!((p_hwfn)->cdev->p_iov_info)) | 18 | #define IS_PF_SRIOV(p_hwfn) (!!((p_hwfn)->cdev->p_iov_info)) |
19 | #else | 19 | #else |
20 | #define IS_VF(cdev) (0) | ||
21 | #define IS_PF(cdev) (1) | ||
20 | #define IS_PF_SRIOV(p_hwfn) (0) | 22 | #define IS_PF_SRIOV(p_hwfn) (0) |
21 | #endif | 23 | #endif |
22 | #define IS_PF_SRIOV_ALLOC(p_hwfn) (!!((p_hwfn)->pf_iov_info)) | 24 | #define IS_PF_SRIOV_ALLOC(p_hwfn) (!!((p_hwfn)->pf_iov_info)) |
diff --git a/drivers/net/ethernet/qlogic/qede/qede_main.c b/drivers/net/ethernet/qlogic/qede/qede_main.c index 5d00d1404bfc..5733d1888223 100644 --- a/drivers/net/ethernet/qlogic/qede/qede_main.c +++ b/drivers/net/ethernet/qlogic/qede/qede_main.c | |||
@@ -87,7 +87,9 @@ static const struct pci_device_id qede_pci_tbl[] = { | |||
87 | {PCI_VDEVICE(QLOGIC, PCI_DEVICE_ID_57980S_100), QEDE_PRIVATE_PF}, | 87 | {PCI_VDEVICE(QLOGIC, PCI_DEVICE_ID_57980S_100), QEDE_PRIVATE_PF}, |
88 | {PCI_VDEVICE(QLOGIC, PCI_DEVICE_ID_57980S_50), QEDE_PRIVATE_PF}, | 88 | {PCI_VDEVICE(QLOGIC, PCI_DEVICE_ID_57980S_50), QEDE_PRIVATE_PF}, |
89 | {PCI_VDEVICE(QLOGIC, PCI_DEVICE_ID_57980S_25), QEDE_PRIVATE_PF}, | 89 | {PCI_VDEVICE(QLOGIC, PCI_DEVICE_ID_57980S_25), QEDE_PRIVATE_PF}, |
90 | #ifdef CONFIG_QED_SRIOV | ||
90 | {PCI_VDEVICE(QLOGIC, PCI_DEVICE_ID_57980S_IOV), QEDE_PRIVATE_VF}, | 91 | {PCI_VDEVICE(QLOGIC, PCI_DEVICE_ID_57980S_IOV), QEDE_PRIVATE_VF}, |
92 | #endif | ||
91 | { 0 } | 93 | { 0 } |
92 | }; | 94 | }; |
93 | 95 | ||