Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 18aa5b18 authored by Jakub Kicinski's avatar Jakub Kicinski Committed by David S. Miller
Browse files

nfp: fail probe if serial or interface id is missing



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: default avatarJakub Kicinski <jakub.kicinski@netronome.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent f055a9df
Loading
Loading
Loading
Loading
+10 −6
Original line number Diff line number Diff line
@@ -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);

+2 −2
Original line number Diff line number Diff line
@@ -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,
+16 −6
Original line number Diff line number Diff line
@@ -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);