|
@@ -875,6 +875,56 @@ static void print_version(void)
|
|
|
printk(KERN_INFO "%s", version);
|
|
|
}
|
|
|
|
|
|
+struct vdc_check_port_data {
|
|
|
+ int dev_no;
|
|
|
+ char *type;
|
|
|
+};
|
|
|
+
|
|
|
+static int vdc_device_probed(struct device *dev, void *arg)
|
|
|
+{
|
|
|
+ struct vio_dev *vdev = to_vio_dev(dev);
|
|
|
+ struct vdc_check_port_data *port_data;
|
|
|
+
|
|
|
+ port_data = (struct vdc_check_port_data *)arg;
|
|
|
+
|
|
|
+ if ((vdev->dev_no == port_data->dev_no) &&
|
|
|
+ (!(strcmp((char *)&vdev->type, port_data->type))) &&
|
|
|
+ dev_get_drvdata(dev)) {
|
|
|
+ /* This device has already been configured
|
|
|
+ * by vdc_port_probe()
|
|
|
+ */
|
|
|
+ return 1;
|
|
|
+ } else {
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/* Determine whether the VIO device is part of an mpgroup
|
|
|
+ * by locating all the virtual-device-port nodes associated
|
|
|
+ * with the parent virtual-device node for the VIO device
|
|
|
+ * and checking whether any of these nodes are vdc-ports
|
|
|
+ * which have already been configured.
|
|
|
+ *
|
|
|
+ * Returns true if this device is part of an mpgroup and has
|
|
|
+ * already been probed.
|
|
|
+ */
|
|
|
+static bool vdc_port_mpgroup_check(struct vio_dev *vdev)
|
|
|
+{
|
|
|
+ struct vdc_check_port_data port_data;
|
|
|
+ struct device *dev;
|
|
|
+
|
|
|
+ port_data.dev_no = vdev->dev_no;
|
|
|
+ port_data.type = (char *)&vdev->type;
|
|
|
+
|
|
|
+ dev = device_find_child(vdev->dev.parent, &port_data,
|
|
|
+ vdc_device_probed);
|
|
|
+
|
|
|
+ if (dev)
|
|
|
+ return true;
|
|
|
+
|
|
|
+ return false;
|
|
|
+}
|
|
|
+
|
|
|
static int vdc_port_probe(struct vio_dev *vdev, const struct vio_device_id *id)
|
|
|
{
|
|
|
struct mdesc_handle *hp;
|
|
@@ -893,6 +943,14 @@ static int vdc_port_probe(struct vio_dev *vdev, const struct vio_device_id *id)
|
|
|
goto err_out_release_mdesc;
|
|
|
}
|
|
|
|
|
|
+ /* Check if this device is part of an mpgroup */
|
|
|
+ if (vdc_port_mpgroup_check(vdev)) {
|
|
|
+ printk(KERN_WARNING
|
|
|
+ "VIO: Ignoring extra vdisk port %s",
|
|
|
+ dev_name(&vdev->dev));
|
|
|
+ goto err_out_release_mdesc;
|
|
|
+ }
|
|
|
+
|
|
|
port = kzalloc(sizeof(*port), GFP_KERNEL);
|
|
|
err = -ENOMEM;
|
|
|
if (!port) {
|
|
@@ -943,6 +1001,9 @@ static int vdc_port_probe(struct vio_dev *vdev, const struct vio_device_id *id)
|
|
|
if (err)
|
|
|
goto err_out_free_tx_ring;
|
|
|
|
|
|
+ /* Note that the device driver_data is used to determine
|
|
|
+ * whether the port has been probed.
|
|
|
+ */
|
|
|
dev_set_drvdata(&vdev->dev, port);
|
|
|
|
|
|
mdesc_release(hp);
|