Commit ae0b63eb authored by Nathan Fontenot's avatar Nathan Fontenot Committed by Greg Kroah-Hartman

ibmvnic: Initialize completion variables before starting work


[ Upstream commit db5d0b59 ]

Initialize condition variables prior to invoking any work that can
mark them complete. This resolves a race in the ibmvnic driver where
the driver faults trying to complete an uninitialized condition
variable.
Signed-off-by: default avatarNathan Fontenot <nfont@linux.vnet.ibm.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
Signed-off-by: default avatarSasha Levin <alexander.levin@verizon.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 4544ba31
...@@ -189,9 +189,10 @@ static int alloc_long_term_buff(struct ibmvnic_adapter *adapter, ...@@ -189,9 +189,10 @@ static int alloc_long_term_buff(struct ibmvnic_adapter *adapter,
} }
ltb->map_id = adapter->map_id; ltb->map_id = adapter->map_id;
adapter->map_id++; adapter->map_id++;
init_completion(&adapter->fw_done);
send_request_map(adapter, ltb->addr, send_request_map(adapter, ltb->addr,
ltb->size, ltb->map_id); ltb->size, ltb->map_id);
init_completion(&adapter->fw_done);
wait_for_completion(&adapter->fw_done); wait_for_completion(&adapter->fw_done);
return 0; return 0;
} }
...@@ -1133,10 +1134,10 @@ static void ibmvnic_get_ethtool_stats(struct net_device *dev, ...@@ -1133,10 +1134,10 @@ static void ibmvnic_get_ethtool_stats(struct net_device *dev,
crq.request_statistics.ioba = cpu_to_be32(adapter->stats_token); crq.request_statistics.ioba = cpu_to_be32(adapter->stats_token);
crq.request_statistics.len = crq.request_statistics.len =
cpu_to_be32(sizeof(struct ibmvnic_statistics)); cpu_to_be32(sizeof(struct ibmvnic_statistics));
ibmvnic_send_crq(adapter, &crq);
/* Wait for data to be written */ /* Wait for data to be written */
init_completion(&adapter->stats_done); init_completion(&adapter->stats_done);
ibmvnic_send_crq(adapter, &crq);
wait_for_completion(&adapter->stats_done); wait_for_completion(&adapter->stats_done);
for (i = 0; i < ARRAY_SIZE(ibmvnic_stats); i++) for (i = 0; i < ARRAY_SIZE(ibmvnic_stats); i++)
...@@ -2809,9 +2810,9 @@ static ssize_t trace_read(struct file *file, char __user *user_buf, size_t len, ...@@ -2809,9 +2810,9 @@ static ssize_t trace_read(struct file *file, char __user *user_buf, size_t len,
crq.collect_fw_trace.correlator = adapter->ras_comps[num].correlator; crq.collect_fw_trace.correlator = adapter->ras_comps[num].correlator;
crq.collect_fw_trace.ioba = cpu_to_be32(trace_tok); crq.collect_fw_trace.ioba = cpu_to_be32(trace_tok);
crq.collect_fw_trace.len = adapter->ras_comps[num].trace_buff_size; crq.collect_fw_trace.len = adapter->ras_comps[num].trace_buff_size;
ibmvnic_send_crq(adapter, &crq);
init_completion(&adapter->fw_done); init_completion(&adapter->fw_done);
ibmvnic_send_crq(adapter, &crq);
wait_for_completion(&adapter->fw_done); wait_for_completion(&adapter->fw_done);
if (*ppos + len > be32_to_cpu(adapter->ras_comps[num].trace_buff_size)) if (*ppos + len > be32_to_cpu(adapter->ras_comps[num].trace_buff_size))
...@@ -3591,9 +3592,9 @@ static int ibmvnic_dump_show(struct seq_file *seq, void *v) ...@@ -3591,9 +3592,9 @@ static int ibmvnic_dump_show(struct seq_file *seq, void *v)
memset(&crq, 0, sizeof(crq)); memset(&crq, 0, sizeof(crq));
crq.request_dump_size.first = IBMVNIC_CRQ_CMD; crq.request_dump_size.first = IBMVNIC_CRQ_CMD;
crq.request_dump_size.cmd = REQUEST_DUMP_SIZE; crq.request_dump_size.cmd = REQUEST_DUMP_SIZE;
ibmvnic_send_crq(adapter, &crq);
init_completion(&adapter->fw_done); init_completion(&adapter->fw_done);
ibmvnic_send_crq(adapter, &crq);
wait_for_completion(&adapter->fw_done); wait_for_completion(&adapter->fw_done);
seq_write(seq, adapter->dump_data, adapter->dump_data_size); seq_write(seq, adapter->dump_data, adapter->dump_data_size);
...@@ -3639,8 +3640,8 @@ static void handle_crq_init_rsp(struct work_struct *work) ...@@ -3639,8 +3640,8 @@ static void handle_crq_init_rsp(struct work_struct *work)
} }
} }
send_version_xchg(adapter);
reinit_completion(&adapter->init_done); reinit_completion(&adapter->init_done);
send_version_xchg(adapter);
if (!wait_for_completion_timeout(&adapter->init_done, timeout)) { if (!wait_for_completion_timeout(&adapter->init_done, timeout)) {
dev_err(dev, "Passive init timeout\n"); dev_err(dev, "Passive init timeout\n");
goto task_failed; goto task_failed;
...@@ -3650,9 +3651,9 @@ static void handle_crq_init_rsp(struct work_struct *work) ...@@ -3650,9 +3651,9 @@ static void handle_crq_init_rsp(struct work_struct *work)
if (adapter->renegotiate) { if (adapter->renegotiate) {
adapter->renegotiate = false; adapter->renegotiate = false;
release_sub_crqs_no_irqs(adapter); release_sub_crqs_no_irqs(adapter);
send_cap_queries(adapter);
reinit_completion(&adapter->init_done); reinit_completion(&adapter->init_done);
send_cap_queries(adapter);
if (!wait_for_completion_timeout(&adapter->init_done, if (!wait_for_completion_timeout(&adapter->init_done,
timeout)) { timeout)) {
dev_err(dev, "Passive init timeout\n"); dev_err(dev, "Passive init timeout\n");
...@@ -3780,9 +3781,9 @@ static int ibmvnic_probe(struct vio_dev *dev, const struct vio_device_id *id) ...@@ -3780,9 +3781,9 @@ static int ibmvnic_probe(struct vio_dev *dev, const struct vio_device_id *id)
adapter->debugfs_dump = ent; adapter->debugfs_dump = ent;
} }
} }
ibmvnic_send_crq_init(adapter);
init_completion(&adapter->init_done); init_completion(&adapter->init_done);
ibmvnic_send_crq_init(adapter);
if (!wait_for_completion_timeout(&adapter->init_done, timeout)) if (!wait_for_completion_timeout(&adapter->init_done, timeout))
return 0; return 0;
...@@ -3790,9 +3791,9 @@ static int ibmvnic_probe(struct vio_dev *dev, const struct vio_device_id *id) ...@@ -3790,9 +3791,9 @@ static int ibmvnic_probe(struct vio_dev *dev, const struct vio_device_id *id)
if (adapter->renegotiate) { if (adapter->renegotiate) {
adapter->renegotiate = false; adapter->renegotiate = false;
release_sub_crqs_no_irqs(adapter); release_sub_crqs_no_irqs(adapter);
send_cap_queries(adapter);
reinit_completion(&adapter->init_done); reinit_completion(&adapter->init_done);
send_cap_queries(adapter);
if (!wait_for_completion_timeout(&adapter->init_done, if (!wait_for_completion_timeout(&adapter->init_done,
timeout)) timeout))
return 0; return 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment