nfp: fail probe if serial or interface id is missing
authorJakub Kicinski <jakub.kicinski@netronome.com>
Sat, 30 Jun 2018 00:04:35 +0000 (17:04 -0700)
committerDavid S. Miller <davem@davemloft.net>
Sat, 30 Jun 2018 12:31:56 +0000 (21:31 +0900)
On some platforms with broken ACPI tables we may not have access
to the Serial Number PCIe capability.  This capability is crucial
for us for switchdev operation as we use serial number as switch ID,
and for communication with management FW where interface ID is used.

If we can't determine the Serial Number we have to fail device probe.

Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/netronome/nfp/nfpcore/nfp6000_pcie.c
drivers/net/ethernet/netronome/nfp/nfpcore/nfp_cpp.h
drivers/net/ethernet/netronome/nfp/nfpcore/nfp_cppcore.c

index 749655c329b240021a34e99612412626c26e8855..c8d0b1016a6463e8df585e3359c137379f5faea2 100644 (file)
@@ -1248,7 +1248,7 @@ static void nfp6000_free(struct nfp_cpp *cpp)
        kfree(nfp);
 }
 
-static void nfp6000_read_serial(struct device *dev, u8 *serial)
+static int nfp6000_read_serial(struct device *dev, u8 *serial)
 {
        struct pci_dev *pdev = to_pci_dev(dev);
        int pos;
@@ -1256,25 +1256,29 @@ static void nfp6000_read_serial(struct device *dev, u8 *serial)
 
        pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_DSN);
        if (!pos) {
-               memset(serial, 0, NFP_SERIAL_LEN);
-               return;
+               dev_err(dev, "can't find PCIe Serial Number Capability\n");
+               return -EINVAL;
        }
 
        pci_read_config_dword(pdev, pos + 4, &reg);
        put_unaligned_be16(reg >> 16, serial + 4);
        pci_read_config_dword(pdev, pos + 8, &reg);
        put_unaligned_be32(reg, serial);
+
+       return 0;
 }
 
-static u16 nfp6000_get_interface(struct device *dev)
+static int nfp6000_get_interface(struct device *dev)
 {
        struct pci_dev *pdev = to_pci_dev(dev);
        int pos;
        u32 reg;
 
        pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_DSN);
-       if (!pos)
-               return NFP_CPP_INTERFACE(NFP_CPP_INTERFACE_TYPE_PCI, 0, 0xff);
+       if (!pos) {
+               dev_err(dev, "can't find PCIe Serial Number Capability\n");
+               return -EINVAL;
+       }
 
        pci_read_config_dword(pdev, pos + 4, &reg);
 
index b0da3d4368505eef63a992ce4a652eaabba9e5a6..c338d539fa96738076146cacd104e2e6030b6cf6 100644 (file)
@@ -364,8 +364,8 @@ struct nfp_cpp_operations {
        int (*init)(struct nfp_cpp *cpp);
        void (*free)(struct nfp_cpp *cpp);
 
-       void (*read_serial)(struct device *dev, u8 *serial);
-       u16 (*get_interface)(struct device *dev);
+       int (*read_serial)(struct device *dev, u8 *serial);
+       int (*get_interface)(struct device *dev);
 
        int (*area_init)(struct nfp_cpp_area *area,
                         u32 dest, unsigned long long address,
index ef30597aa31963715676d9c4c8fb4a4ebe03ec10..73de57a09800d7d0c482e64d22995a3aa6c06613 100644 (file)
@@ -1163,10 +1163,10 @@ nfp_cpp_from_operations(const struct nfp_cpp_operations *ops,
 {
        const u32 arm = NFP_CPP_ID(NFP_CPP_TARGET_ARM, NFP_CPP_ACTION_RW, 0);
        struct nfp_cpp *cpp;
+       int ifc, err;
        u32 mask[2];
        u32 xpbaddr;
        size_t tgt;
-       int err;
 
        cpp = kzalloc(sizeof(*cpp), GFP_KERNEL);
        if (!cpp) {
@@ -1176,9 +1176,19 @@ nfp_cpp_from_operations(const struct nfp_cpp_operations *ops,
 
        cpp->op = ops;
        cpp->priv = priv;
-       cpp->interface = ops->get_interface(parent);
-       if (ops->read_serial)
-               ops->read_serial(parent, cpp->serial);
+
+       ifc = ops->get_interface(parent);
+       if (ifc < 0) {
+               err = ifc;
+               goto err_free_cpp;
+       }
+       cpp->interface = ifc;
+       if (ops->read_serial) {
+               err = ops->read_serial(parent, cpp->serial);
+               if (err)
+                       goto err_free_cpp;
+       }
+
        rwlock_init(&cpp->resource_lock);
        init_waitqueue_head(&cpp->waitq);
        lockdep_set_class(&cpp->resource_lock, &nfp_cpp_resource_lock_key);
@@ -1191,7 +1201,7 @@ nfp_cpp_from_operations(const struct nfp_cpp_operations *ops,
        err = device_register(&cpp->dev);
        if (err < 0) {
                put_device(&cpp->dev);
-               goto err_dev;
+               goto err_free_cpp;
        }
 
        dev_set_drvdata(&cpp->dev, cpp);
@@ -1238,7 +1248,7 @@ nfp_cpp_from_operations(const struct nfp_cpp_operations *ops,
 
 err_out:
        device_unregister(&cpp->dev);
-err_dev:
+err_free_cpp:
        kfree(cpp);
 err_malloc:
        return ERR_PTR(err);