aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/pci/pci.c
diff options
context:
space:
mode:
authorNiklas Schnelle <schnelle@linux.ibm.com>2020-07-22 16:53:54 +0200
committerVasily Gorbik <gor@linux.ibm.com>2021-02-09 15:57:04 +0100
commitba764dd703feacb5a9c410d191af1b6cfbe96845 (patch)
tree29917ca3bfc6464f27ca2a6824e07881e7e5d2d2 /arch/s390/pci/pci.c
parents390/qdio: track time of last data IRQ for each device (diff)
downloadlinux-dev-ba764dd703feacb5a9c410d191af1b6cfbe96845.tar.xz
linux-dev-ba764dd703feacb5a9c410d191af1b6cfbe96845.zip
s390/pci: refactor zpci_create_device()
Currently zpci_create_device() is only called in clp_add_pci_device() which allocates the memory for the struct zpci_dev being created. There is little separation of concerns as only both functions together can create a zpci_dev and the only CLP specific code in clp_add_pci_device() is a call to clp_query_pci_fn(). Improve this by removing clp_add_pci_device() and refactor zpci_create_device() such that it alone creates and initializes the zpci_dev given the FID and Function Handle. For this we need to make clp_query_pci_fn() non-static. While at it remove the function handle parameter since we can just take that from the zpci_dev. Also move adding to the zpci_list to after the zdev has been fully created which eliminates a window where a partially initialized zdev can be found by get_zdev_by_fid(). Acked-by: Pierre Morel <pmorel@linux.ibm.com> Signed-off-by: Niklas Schnelle <schnelle@linux.ibm.com> Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>
Diffstat (limited to 'arch/s390/pci/pci.c')
-rw-r--r--arch/s390/pci/pci.c57
1 files changed, 41 insertions, 16 deletions
diff --git a/arch/s390/pci/pci.c b/arch/s390/pci/pci.c
index 41df8fcfddde..600881d894dd 100644
--- a/arch/s390/pci/pci.c
+++ b/arch/s390/pci/pci.c
@@ -695,43 +695,68 @@ void zpci_remove_device(struct zpci_dev *zdev)
}
}
-int zpci_create_device(struct zpci_dev *zdev)
+/**
+ * zpci_create_device() - Create a new zpci_dev and add it to the zbus
+ * @fid: Function ID of the device to be created
+ * @fh: Current Function Handle of the device to be created
+ * @state: Initial state after creation either Standby or Configured
+ *
+ * Creates a new zpci device and adds it to its, possibly newly created, zbus
+ * as well as zpci_list.
+ *
+ * Returns: 0 on success, an error value otherwise
+ */
+int zpci_create_device(u32 fid, u32 fh, enum zpci_state state)
{
+ struct zpci_dev *zdev;
int rc;
- kref_init(&zdev->kref);
+ zpci_dbg(3, "add fid:%x, fh:%x, c:%d\n", fid, fh, state);
+ zdev = kzalloc(sizeof(*zdev), GFP_KERNEL);
+ if (!zdev)
+ return -ENOMEM;
- spin_lock(&zpci_list_lock);
- list_add_tail(&zdev->entry, &zpci_list);
- spin_unlock(&zpci_list_lock);
+ /* FID and Function Handle are the static/dynamic identifiers */
+ zdev->fid = fid;
+ zdev->fh = fh;
- rc = zpci_init_iommu(zdev);
+ /* Query function properties and update zdev */
+ rc = clp_query_pci_fn(zdev);
if (rc)
- goto out;
+ goto error;
+ zdev->state = state;
+ kref_init(&zdev->kref);
mutex_init(&zdev->lock);
+
+ rc = zpci_init_iommu(zdev);
+ if (rc)
+ goto error;
+
if (zdev->state == ZPCI_FN_STATE_CONFIGURED) {
rc = zpci_enable_device(zdev);
if (rc)
- goto out_destroy_iommu;
+ goto error_destroy_iommu;
}
rc = zpci_bus_device_register(zdev, &pci_root_ops);
if (rc)
- goto out_disable;
+ goto error_disable;
+
+ spin_lock(&zpci_list_lock);
+ list_add_tail(&zdev->entry, &zpci_list);
+ spin_unlock(&zpci_list_lock);
return 0;
-out_disable:
+error_disable:
if (zdev->state == ZPCI_FN_STATE_ONLINE)
zpci_disable_device(zdev);
-
-out_destroy_iommu:
+error_destroy_iommu:
zpci_destroy_iommu(zdev);
-out:
- spin_lock(&zpci_list_lock);
- list_del(&zdev->entry);
- spin_unlock(&zpci_list_lock);
+error:
+ zpci_dbg(0, "add fid:%x, rc:%d\n", fid, rc);
+ kfree(zdev);
return rc;
}