ibmvnic: Introduce active CRQ state
authorThomas Falcon <tlfalcon@linux.vnet.ibm.com>
Wed, 23 May 2018 18:37:56 +0000 (13:37 -0500)
committerDavid S. Miller <davem@davemloft.net>
Fri, 25 May 2018 02:19:25 +0000 (22:19 -0400)
Introduce an "active" state for a IBM vNIC Command-Response Queue. A CRQ
is considered active once it has initialized or linked with its partner by
sending an initialization request and getting a successful response back
from the management partition.  Until this has happened, do not allow CRQ
commands to be sent other than the initialization request.

This change will avoid a protocol error in case of a device transport
event occurring during a initialization. When the driver receives a
transport event notification indicating that the backing hardware
has changed and needs reinitialization, any further commands other
than the initialization handshake with the VIOS management partition
will result in an invalid state error. Instead of sending a command
that will be returned with an error, print a warning and return an
error that will be handled by the caller.

Signed-off-by: Thomas Falcon <tlfalcon@linux.vnet.ibm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/ibm/ibmvnic.c
drivers/net/ethernet/ibm/ibmvnic.h

index eabc1e445137aeb4a73a16b906e38f531184bde7..e6a081c13661a9cf05731fcda28903b96ceeda57 100644 (file)
@@ -3147,6 +3147,12 @@ static int ibmvnic_send_crq(struct ibmvnic_adapter *adapter,
                   (unsigned long int)cpu_to_be64(u64_crq[0]),
                   (unsigned long int)cpu_to_be64(u64_crq[1]));
 
+       if (!adapter->crq.active &&
+           crq->generic.first != IBMVNIC_CRQ_INIT_CMD) {
+               dev_warn(dev, "Invalid request detected while CRQ is inactive, possible device state change during reset\n");
+               return -EINVAL;
+       }
+
        /* Make sure the hypervisor sees the complete request */
        mb();
 
@@ -4225,6 +4231,7 @@ static void ibmvnic_handle_crq(union ibmvnic_crq *crq,
                        break;
                case IBMVNIC_CRQ_INIT_COMPLETE:
                        dev_info(dev, "Partner initialization complete\n");
+                       adapter->crq.active = true;
                        send_version_xchg(adapter);
                        break;
                default:
@@ -4233,6 +4240,7 @@ static void ibmvnic_handle_crq(union ibmvnic_crq *crq,
                return;
        case IBMVNIC_CRQ_XPORT_EVENT:
                netif_carrier_off(netdev);
+               adapter->crq.active = false;
                if (gen_crq->cmd == IBMVNIC_PARTITION_MIGRATED) {
                        dev_info(dev, "Migrated, re-enabling adapter\n");
                        ibmvnic_reset(adapter, VNIC_RESET_MOBILITY);
@@ -4420,6 +4428,7 @@ static int ibmvnic_reset_crq(struct ibmvnic_adapter *adapter)
        /* Clean out the queue */
        memset(crq->msgs, 0, PAGE_SIZE);
        crq->cur = 0;
+       crq->active = false;
 
        /* And re-open it again */
        rc = plpar_hcall_norets(H_REG_CRQ, vdev->unit_address,
@@ -4454,6 +4463,7 @@ static void release_crq_queue(struct ibmvnic_adapter *adapter)
                         DMA_BIDIRECTIONAL);
        free_page((unsigned long)crq->msgs);
        crq->msgs = NULL;
+       crq->active = false;
 }
 
 static int init_crq_queue(struct ibmvnic_adapter *adapter)
index 22391e8805f6ffe6abcba00666bdf0231dfbf54f..edfc312d3523598b60c5e4b4656fc15aca289b94 100644 (file)
@@ -865,6 +865,7 @@ struct ibmvnic_crq_queue {
        int size, cur;
        dma_addr_t msg_token;
        spinlock_t lock;
+       bool active;
 };
 
 union sub_crq {