Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ibmvnic: Make CRQ interrupt tasklet wait for all capabilities crqs

After sending device capability queries and requests to the vNIC Server,
an interrupt is triggered and the responses are written to the driver's
CRQ response buffer. Since the interrupt can be triggered before all
responses are written and visible to the partition, there is a danger
that the interrupt handler or tasklet can terminate before all responses
are read, resulting in a failure to initialize the device.

To avoid this scenario, when capability commands are sent, we set
a flag that will be checked in the following interrupt tasklet that
will handle the capability responses from the server. Once all
responses have been handled, the flag is disabled; and the tasklet
is allowed to terminate.

Signed-off-by: Thomas Falcon <tlfalcon@linux.vnet.ibm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Thomas Falcon and committed by
David S. Miller
249168ad 901e040a

+15 -2
+14 -2
drivers/net/ethernet/ibm/ibmvnic.c
··· 2418 2418 struct ibmvnic_query_ip_offload_buffer *ip_offload_buf = 2419 2419 &adapter->ip_offload_buf; 2420 2420 2421 + adapter->wait_capability = false; 2421 2422 adapter->ip_offload_tok = dma_map_single(dev, ip_offload_buf, 2422 2423 buf_sz, 2423 2424 DMA_FROM_DEVICE); ··· 2714 2713 } 2715 2714 2716 2715 out: 2717 - if (atomic_read(&adapter->running_cap_crqs) == 0) 2716 + if (atomic_read(&adapter->running_cap_crqs) == 0) { 2717 + adapter->wait_capability = false; 2718 2718 init_sub_crqs(adapter, 0); 2719 2719 /* We're done querying the capabilities, initialize sub-crqs */ 2720 + } 2720 2721 } 2721 2722 2722 2723 static void handle_control_ras_rsp(union ibmvnic_crq *crq, ··· 3461 3458 ibmvnic_handle_crq(crq, adapter); 3462 3459 crq->generic.first = 0; 3463 3460 } else { 3464 - done = true; 3461 + /* remain in tasklet until all 3462 + * capabilities responses are received 3463 + */ 3464 + if (!adapter->wait_capability) 3465 + done = true; 3465 3466 } 3466 3467 } 3468 + /* if capabilities CRQ's were sent in this tasklet, the following 3469 + * tasklet must wait until all responses are received 3470 + */ 3471 + if (atomic_read(&adapter->running_cap_crqs) != 0) 3472 + adapter->wait_capability = true; 3467 3473 spin_unlock_irqrestore(&queue->lock, flags); 3468 3474 } 3469 3475
+1
drivers/net/ethernet/ibm/ibmvnic.h
··· 977 977 int login_rsp_buf_sz; 978 978 979 979 atomic_t running_cap_crqs; 980 + bool wait_capability; 980 981 981 982 struct ibmvnic_sub_crq_queue **tx_scrq; 982 983 struct ibmvnic_sub_crq_queue **rx_scrq;