]> pilppa.com Git - linux-2.6-omap-h63xx.git/commitdiff
CRIS v10: Update kernel/io_interface_mux.c
authorJesper Nilsson <jesper.nilsson@axis.com>
Tue, 29 Jan 2008 10:27:19 +0000 (11:27 +0100)
committerJesper Nilsson <jesper.nilsson@axis.com>
Fri, 8 Feb 2008 10:06:32 +0000 (11:06 +0100)
Fixed a bug where two interfaces using pins in the same pin group could
not be allocated at the same time even if there where no pin collisions.

Change all restore and returns into goto exit pattern.

Also, remove useless CVS id and correct chapter reference for ETRAX100LX
Designer's Reference in comment.

arch/cris/arch-v10/kernel/io_interface_mux.c

index f3b327d4ed9cf912040a56310b69cad7063f7fd8..add98e0941b541970e3f1d4cb01cb00902a74aed 100644 (file)
@@ -1,10 +1,9 @@
 /* IO interface mux allocator for ETRAX100LX.
- * Copyright 2004, Axis Communications AB
- * $Id: io_interface_mux.c,v 1.2 2004/12/21 12:08:38 starvik Exp $
+ * Copyright 2004-2007, Axis Communications AB
  */
 
 
-/* C.f. ETRAX100LX Designer's Reference 20.9 */
+/* C.f. ETRAX100LX Designer's Reference chapter 19.9 */
 
 #include <linux/kernel.h>
 #include <linux/slab.h>
@@ -45,17 +44,39 @@ struct watcher
 struct if_group
 {
        enum io_if_group        group;
-       unsigned char           used;
-       enum cris_io_interface  owner;
+       /* name - the name of the group 'A' to 'F' */
+       char                   *name;
+       /* used - a bit mask of all pins in the group in the order listed
+        * in the tables in 19.9.1 to 19.9.6.  Note that no
+        * distinction is made between in, out and in/out pins. */
+       unsigned int            used;
 };
 
 
 struct interface
 {
        enum cris_io_interface   ioif;
+       /* name - the name of the interface */
+       char                    *name;
+       /* groups - OR'ed together io_if_group flags describing what pin groups
+        * the interface uses pins in. */
        unsigned char            groups;
+       /* used - set when the interface is allocated. */
        unsigned char            used;
        char                    *owner;
+       /* group_a through group_f - bit masks describing what pins in the
+        * pin groups the interface uses. */
+       unsigned int             group_a;
+       unsigned int             group_b;
+       unsigned int             group_c;
+       unsigned int             group_d;
+       unsigned int             group_e;
+       unsigned int             group_f;
+
+       /* gpio_g_in, gpio_g_out, gpio_b - bit masks telling what pins in the
+        * GPIO ports the interface uses.  This could be reconstucted using
+        * the group_X masks and a table of what pins the GPIO ports use,
+        * but that would be messy. */
        unsigned int             gpio_g_in;
        unsigned int             gpio_g_out;
        unsigned char            gpio_b;
@@ -64,26 +85,32 @@ struct interface
 static struct if_group if_groups[6] = {
        {
                .group = group_a,
+               .name = "A",
                .used = 0,
        },
        {
                .group = group_b,
+               .name = "B",
                .used = 0,
        },
        {
                .group = group_c,
+               .name = "C",
                .used = 0,
        },
        {
                .group = group_d,
+               .name = "D",
                .used = 0,
        },
        {
                .group = group_e,
+               .name = "E",
                .used = 0,
        },
        {
                .group = group_f,
+               .name = "F",
                .used = 0,
        }
 };
@@ -94,14 +121,32 @@ static struct interface interfaces[] = {
        /* Begin Non-multiplexed interfaces */
        {
                .ioif = if_eth,
+               .name = "ethernet",
                .groups = 0,
+
+               .group_a = 0,
+               .group_b = 0,
+               .group_c = 0,
+               .group_d = 0,
+               .group_e = 0,
+               .group_f = 0,
+
                .gpio_g_in = 0,
                .gpio_g_out = 0,
                .gpio_b = 0
        },
        {
                .ioif = if_serial_0,
+               .name = "serial_0",
                .groups = 0,
+
+               .group_a = 0,
+               .group_b = 0,
+               .group_c = 0,
+               .group_d = 0,
+               .group_e = 0,
+               .group_f = 0,
+
                .gpio_g_in = 0,
                .gpio_g_out = 0,
                .gpio_b = 0
@@ -109,172 +154,385 @@ static struct interface interfaces[] = {
        /* End Non-multiplexed interfaces */
        {
                .ioif = if_serial_1,
+               .name = "serial_1",
                .groups = group_e,
+
+               .group_a = 0,
+               .group_b = 0,
+               .group_c = 0,
+               .group_d = 0,
+               .group_e = 0x0f,
+               .group_f = 0,
+
                .gpio_g_in =  0x00000000,
                .gpio_g_out = 0x00000000,
                .gpio_b = 0x00
        },
        {
                .ioif = if_serial_2,
+               .name = "serial_2",
                .groups = group_b,
+
+               .group_a = 0,
+               .group_b = 0x0f,
+               .group_c = 0,
+               .group_d = 0,
+               .group_e = 0,
+               .group_f = 0,
+
                .gpio_g_in =  0x000000c0,
                .gpio_g_out = 0x000000c0,
                .gpio_b = 0x00
        },
        {
                .ioif = if_serial_3,
+               .name = "serial_3",
                .groups = group_c,
+
+               .group_a = 0,
+               .group_b = 0,
+               .group_c = 0x0f,
+               .group_d = 0,
+               .group_e = 0,
+               .group_f = 0,
+
                .gpio_g_in =  0xc0000000,
                .gpio_g_out = 0xc0000000,
                .gpio_b = 0x00
        },
        {
                .ioif = if_sync_serial_1,
-               .groups = group_e | group_f, /* if_sync_serial_1 and if_sync_serial_3
-                                              can be used simultaneously */
+               .name = "sync_serial_1",
+               .groups = group_e | group_f,
+
+               .group_a = 0,
+               .group_b = 0,
+               .group_c = 0,
+               .group_d = 0,
+               .group_e = 0x0f,
+               .group_f = 0x10,
+
                .gpio_g_in =  0x00000000,
                .gpio_g_out = 0x00000000,
                .gpio_b = 0x10
        },
        {
                .ioif = if_sync_serial_3,
+               .name = "sync_serial_3",
                .groups = group_c | group_f,
+
+               .group_a = 0,
+               .group_b = 0,
+               .group_c = 0x0f,
+               .group_d = 0,
+               .group_e = 0,
+               .group_f = 0x80,
+
                .gpio_g_in =  0xc0000000,
                .gpio_g_out = 0xc0000000,
                .gpio_b = 0x80
        },
        {
                .ioif = if_shared_ram,
+               .name = "shared_ram",
                .groups = group_a,
+
+               .group_a = 0x7f8ff,
+               .group_b = 0,
+               .group_c = 0,
+               .group_d = 0,
+               .group_e = 0,
+               .group_f = 0,
+
                .gpio_g_in =  0x0000ff3e,
                .gpio_g_out = 0x0000ff38,
                .gpio_b = 0x00
        },
        {
                .ioif = if_shared_ram_w,
+               .name = "shared_ram_w",
                .groups = group_a | group_d,
+
+               .group_a = 0x7f8ff,
+               .group_b = 0,
+               .group_c = 0,
+               .group_d = 0xff,
+               .group_e = 0,
+               .group_f = 0,
+
                .gpio_g_in =  0x00ffff3e,
                .gpio_g_out = 0x00ffff38,
                .gpio_b = 0x00
        },
        {
                .ioif = if_par_0,
+               .name = "par_0",
                .groups = group_a,
+
+               .group_a = 0x7fbff,
+               .group_b = 0,
+               .group_c = 0,
+               .group_d = 0,
+               .group_e = 0,
+               .group_f = 0,
+
                .gpio_g_in =  0x0000ff3e,
                .gpio_g_out = 0x0000ff3e,
                .gpio_b = 0x00
        },
        {
                .ioif = if_par_1,
+               .name = "par_1",
                .groups = group_d,
+
+               .group_a = 0,
+               .group_b = 0,
+               .group_c = 0,
+               .group_d = 0x7feff,
+               .group_e = 0,
+               .group_f = 0,
+
                .gpio_g_in =  0x3eff0000,
                .gpio_g_out = 0x3eff0000,
                .gpio_b = 0x00
        },
        {
                .ioif = if_par_w,
+               .name = "par_w",
                .groups = group_a | group_d,
+
+               .group_a = 0x7fbff,
+               .group_b = 0,
+               .group_c = 0,
+               .group_d = 0xff,
+               .group_e = 0,
+               .group_f = 0,
+
                .gpio_g_in =  0x00ffff3e,
                .gpio_g_out = 0x00ffff3e,
                .gpio_b = 0x00
        },
        {
                .ioif = if_scsi8_0,
-               .groups = group_a | group_b | group_f, /* if_scsi8_0 and if_scsi8_1
-                                                         can be used simultaneously */
+               .name = "scsi8_0",
+               .groups = group_a | group_b | group_f,
+
+               .group_a = 0x7ffff,
+               .group_b = 0x0f,
+               .group_c = 0,
+               .group_d = 0,
+               .group_e = 0,
+               .group_f = 0x10,
+
                .gpio_g_in =  0x0000ffff,
                .gpio_g_out = 0x0000ffff,
                .gpio_b = 0x10
        },
        {
                .ioif = if_scsi8_1,
-               .groups = group_c | group_d | group_f, /* if_scsi8_0 and if_scsi8_1
-                                                         can be used simultaneously */
+               .name = "scsi8_1",
+               .groups = group_c | group_d | group_f,
+
+               .group_a = 0,
+               .group_b = 0,
+               .group_c = 0x0f,
+               .group_d = 0x7ffff,
+               .group_e = 0,
+               .group_f = 0x80,
+
                .gpio_g_in =  0xffff0000,
                .gpio_g_out = 0xffff0000,
                .gpio_b = 0x80
        },
        {
                .ioif = if_scsi_w,
+               .name = "scsi_w",
                .groups = group_a | group_b | group_d | group_f,
+
+               .group_a = 0x7ffff,
+               .group_b = 0x0f,
+               .group_c = 0,
+               .group_d = 0x601ff,
+               .group_e = 0,
+               .group_f = 0x90,
+
                .gpio_g_in =  0x01ffffff,
                .gpio_g_out = 0x07ffffff,
                .gpio_b = 0x80
        },
        {
                .ioif = if_ata,
+               .name = "ata",
                .groups = group_a | group_b | group_c | group_d,
+
+               .group_a = 0x7ffff,
+               .group_b = 0x0f,
+               .group_c = 0x0f,
+               .group_d = 0x7cfff,
+               .group_e = 0,
+               .group_f = 0,
+
                .gpio_g_in =  0xf9ffffff,
                .gpio_g_out = 0xffffffff,
                .gpio_b = 0x80
        },
        {
                .ioif = if_csp,
-               .groups = group_f, /* if_csp and if_i2c can be used simultaneously */
+               .name = "csp",
+               .groups = group_f,
+
+               .group_a = 0,
+               .group_b = 0,
+               .group_c = 0,
+               .group_d = 0,
+               .group_e = 0,
+               .group_f = 0xfc,
+
                .gpio_g_in =  0x00000000,
                .gpio_g_out = 0x00000000,
                .gpio_b = 0xfc
        },
        {
                .ioif = if_i2c,
-               .groups = group_f, /* if_csp and if_i2c can be used simultaneously */
+               .name = "i2c",
+               .groups = group_f,
+
+               .group_a = 0,
+               .group_b = 0,
+               .group_c = 0,
+               .group_d = 0,
+               .group_e = 0,
+               .group_f = 0x03,
+
                .gpio_g_in =  0x00000000,
                .gpio_g_out = 0x00000000,
                .gpio_b = 0x03
        },
        {
                .ioif = if_usb_1,
+               .name = "usb_1",
                .groups = group_e | group_f,
+
+               .group_a = 0,
+               .group_b = 0,
+               .group_c = 0,
+               .group_d = 0,
+               .group_e = 0x0f,
+               .group_f = 0x2c,
+
                .gpio_g_in =  0x00000000,
                .gpio_g_out = 0x00000000,
                .gpio_b = 0x2c
        },
        {
                .ioif = if_usb_2,
+               .name = "usb_2",
                .groups = group_d,
-               .gpio_g_in =  0x0e000000,
-               .gpio_g_out = 0x3c000000,
+
+               .group_a = 0,
+               .group_b = 0,
+               .group_c = 0,
+               .group_d = 0,
+               .group_e = 0x33e00,
+               .group_f = 0,
+
+               .gpio_g_in =  0x3e000000,
+               .gpio_g_out = 0x0c000000,
                .gpio_b = 0x00
        },
        /* GPIO pins */
        {
                .ioif = if_gpio_grp_a,
+               .name = "gpio_a",
                .groups = group_a,
+
+               .group_a = 0,
+               .group_b = 0,
+               .group_c = 0,
+               .group_d = 0,
+               .group_e = 0,
+               .group_f = 0,
+
                .gpio_g_in =  0x0000ff3f,
                .gpio_g_out = 0x0000ff3f,
                .gpio_b = 0x00
        },
        {
                .ioif = if_gpio_grp_b,
+               .name = "gpio_b",
                .groups = group_b,
+
+               .group_a = 0,
+               .group_b = 0,
+               .group_c = 0,
+               .group_d = 0,
+               .group_e = 0,
+               .group_f = 0,
+
                .gpio_g_in =  0x000000c0,
                .gpio_g_out = 0x000000c0,
                .gpio_b = 0x00
        },
        {
                .ioif = if_gpio_grp_c,
+               .name = "gpio_c",
                .groups = group_c,
+
+               .group_a = 0,
+               .group_b = 0,
+               .group_c = 0,
+               .group_d = 0,
+               .group_e = 0,
+               .group_f = 0,
+
                .gpio_g_in =  0xc0000000,
                .gpio_g_out = 0xc0000000,
                .gpio_b = 0x00
        },
        {
                .ioif = if_gpio_grp_d,
+               .name = "gpio_d",
                .groups = group_d,
+
+               .group_a = 0,
+               .group_b = 0,
+               .group_c = 0,
+               .group_d = 0,
+               .group_e = 0,
+               .group_f = 0,
+
                .gpio_g_in =  0x3fff0000,
                .gpio_g_out = 0x3fff0000,
                .gpio_b = 0x00
        },
        {
                .ioif = if_gpio_grp_e,
+               .name = "gpio_e",
                .groups = group_e,
+
+               .group_a = 0,
+               .group_b = 0,
+               .group_c = 0,
+               .group_d = 0,
+               .group_e = 0,
+               .group_f = 0,
+
                .gpio_g_in =  0x00000000,
                .gpio_g_out = 0x00000000,
                .gpio_b = 0x00
        },
        {
                .ioif = if_gpio_grp_f,
+               .name = "gpio_f",
                .groups = group_f,
+
+               .group_a = 0,
+               .group_b = 0,
+               .group_c = 0,
+               .group_d = 0,
+               .group_e = 0,
+               .group_f = 0,
+
                .gpio_g_in =  0x00000000,
                .gpio_g_out = 0x00000000,
                .gpio_b = 0xff
@@ -284,11 +542,13 @@ static struct interface interfaces[] = {
 
 static struct watcher *watchers = NULL;
 
+/* The pins that are free to use in the GPIO ports. */
 static unsigned int gpio_in_pins =  0xffffffff;
 static unsigned int gpio_out_pins = 0xffffffff;
 static unsigned char gpio_pb_pins = 0xff;
 static unsigned char gpio_pa_pins = 0xff;
 
+/* Identifiers for the owners of the GPIO pins. */
 static enum cris_io_interface gpio_pa_owners[8];
 static enum cris_io_interface gpio_pb_owners[8];
 static enum cris_io_interface gpio_pg_owners[32];
@@ -338,13 +598,15 @@ int cris_request_io_interface(enum cris_io_interface ioif, const char *device_id
        struct if_group *grp;
        unsigned char group_set;
        unsigned long flags;
+       int res = 0;
 
        (void)cris_io_interface_init();
 
        DBG(printk("cris_request_io_interface(%d, \"%s\")\n", ioif, device_id));
 
        if ((ioif >= if_max_interfaces) || (ioif < 0)) {
-               printk(KERN_CRIT "cris_request_io_interface: Bad interface %u submitted for %s\n",
+               printk(KERN_CRIT "cris_request_io_interface: Bad interface "
+                       "%u submitted for %s\n",
                       ioif,
                       device_id);
                return -EINVAL;
@@ -353,59 +615,69 @@ int cris_request_io_interface(enum cris_io_interface ioif, const char *device_id
        local_irq_save(flags);
 
        if (interfaces[ioif].used) {
-               local_irq_restore(flags);
-               printk(KERN_CRIT "cris_io_interface: Cannot allocate interface for %s, in use by %s\n",
+               printk(KERN_CRIT "cris_io_interface: Cannot allocate interface "
+                       "%s for %s, in use by %s\n",
+                      interfaces[ioif].name,
                       device_id,
                       interfaces[ioif].owner);
-               return -EBUSY;
+               res = -EBUSY;
+               goto exit;
        }
 
-       /* Check that all required groups are free before allocating, */
+       /* Check that all required pins in the used groups are free
+        * before allocating. */
        group_set = interfaces[ioif].groups;
        while (NULL != (grp = get_group(group_set))) {
-               if (grp->used) {
-                       if (grp->group == group_f) {
-                               if ((if_sync_serial_1 ==  ioif) ||
-                                   (if_sync_serial_3 ==  ioif)) {
-                                       if ((grp->owner != if_sync_serial_1) &&
-                                           (grp->owner != if_sync_serial_3)) {
-                                               local_irq_restore(flags);
-                                               return -EBUSY;
-                                       }
-                               } else if ((if_scsi8_0 == ioif) ||
-                                          (if_scsi8_1 == ioif)) {
-                                       if ((grp->owner != if_scsi8_0) &&
-                                           (grp->owner != if_scsi8_1)) {
-                                               local_irq_restore(flags);
-                                               return -EBUSY;
-                                       }
-                               }
-                       } else {
-                               local_irq_restore(flags);
-                               return -EBUSY;
-                       }
+               unsigned int if_group_use = 0;
+
+               switch (grp->group) {
+               case group_a:
+                       if_group_use = interfaces[ioif].group_a;
+                       break;
+               case group_b:
+                       if_group_use = interfaces[ioif].group_b;
+                       break;
+               case group_c:
+                       if_group_use = interfaces[ioif].group_c;
+                       break;
+               case group_d:
+                       if_group_use = interfaces[ioif].group_d;
+                       break;
+               case group_e:
+                       if_group_use = interfaces[ioif].group_e;
+                       break;
+               case group_f:
+                       if_group_use = interfaces[ioif].group_f;
+                       break;
+               default:
+                       BUG_ON(1);
                }
+
+               if (if_group_use & grp->used) {
+                       printk(KERN_INFO "cris_request_io_interface: group "
+                               "%s needed by %s not available\n",
+                               grp->name, interfaces[ioif].name);
+                       res = -EBUSY;
+                       goto exit;
+               }
+
                group_set = clear_group_from_set(group_set, grp);
        }
 
        /* Are the required GPIO pins available too? */
-       if (((interfaces[ioif].gpio_g_in & gpio_in_pins) != interfaces[ioif].gpio_g_in) ||
-           ((interfaces[ioif].gpio_g_out & gpio_out_pins) != interfaces[ioif].gpio_g_out) ||
-           ((interfaces[ioif].gpio_b & gpio_pb_pins) != interfaces[ioif].gpio_b)) {
-               local_irq_restore(flags);
-               printk(KERN_CRIT "cris_request_io_interface: Could not get required pins for interface %u\n",
-                      ioif);
-               return -EBUSY;
-       }
-
-       /* All needed I/O pins and pin groups are free, allocate. */
-       group_set = interfaces[ioif].groups;
-       while (NULL != (grp = get_group(group_set))) {
-               grp->used = 1;
-               grp->owner = ioif;
-               group_set = clear_group_from_set(group_set, grp);
+       if (((interfaces[ioif].gpio_g_in & gpio_in_pins) !=
+                       interfaces[ioif].gpio_g_in) ||
+               ((interfaces[ioif].gpio_g_out & gpio_out_pins) !=
+                       interfaces[ioif].gpio_g_out) ||
+               ((interfaces[ioif].gpio_b & gpio_pb_pins) !=
+                       interfaces[ioif].gpio_b)) {
+               printk(KERN_CRIT "cris_request_io_interface: Could not get "
+                       "required pins for interface %u\n", ioif);
+               res = -EBUSY;
+               goto exit;
        }
 
+       /* Check which registers need to be reconfigured. */
        gens = genconfig_shadow;
        gens_ii = gen_config_ii_shadow;
 
@@ -495,9 +767,43 @@ int cris_request_io_interface(enum cris_io_interface ioif, const char *device_id
                set_gen_config = 0;
                break;
        default:
-               panic("cris_request_io_interface: Bad interface %u submitted for %s\n",
-                     ioif,
-                     device_id);
+               printk(KERN_INFO "cris_request_io_interface: Bad interface "
+                       "%u submitted for %s\n",
+                       ioif, device_id);
+               res = -EBUSY;
+               goto exit;
+       }
+
+       /* All needed I/O pins and pin groups are free, allocate. */
+       group_set = interfaces[ioif].groups;
+       while (NULL != (grp = get_group(group_set))) {
+               unsigned int if_group_use = 0;
+
+               switch (grp->group) {
+               case group_a:
+                       if_group_use = interfaces[ioif].group_a;
+                       break;
+               case group_b:
+                       if_group_use = interfaces[ioif].group_b;
+                       break;
+               case group_c:
+                       if_group_use = interfaces[ioif].group_c;
+                       break;
+               case group_d:
+                       if_group_use = interfaces[ioif].group_d;
+                       break;
+               case group_e:
+                       if_group_use = interfaces[ioif].group_e;
+                       break;
+               case group_f:
+                       if_group_use = interfaces[ioif].group_f;
+                       break;
+               default:
+                       BUG_ON(1);
+               }
+               grp->used |= if_group_use;
+
+               group_set = clear_group_from_set(group_set, grp);
        }
 
        interfaces[ioif].used = 1;
@@ -516,25 +822,28 @@ int cris_request_io_interface(enum cris_io_interface ioif, const char *device_id
                *R_GEN_CONFIG_II = gen_config_ii_shadow;
        }
 
-       DBG(printk("GPIO pins: available before: g_in=0x%08x g_out=0x%08x pb=0x%02x\n",
-                  gpio_in_pins, gpio_out_pins, gpio_pb_pins));
-       DBG(printk("grabbing pins: g_in=0x%08x g_out=0x%08x pb=0x%02x\n",
-                  interfaces[ioif].gpio_g_in,
-                  interfaces[ioif].gpio_g_out,
-                  interfaces[ioif].gpio_b));
+       DBG(printk(KERN_DEBUG "GPIO pins: available before: "
+               "g_in=0x%08x g_out=0x%08x pb=0x%02x\n",
+               gpio_in_pins, gpio_out_pins, gpio_pb_pins));
+       DBG(printk(KERN_DEBUG
+               "grabbing pins: g_in=0x%08x g_out=0x%08x pb=0x%02x\n",
+               interfaces[ioif].gpio_g_in,
+               interfaces[ioif].gpio_g_out,
+               interfaces[ioif].gpio_b));
 
        gpio_in_pins &= ~interfaces[ioif].gpio_g_in;
        gpio_out_pins &= ~interfaces[ioif].gpio_g_out;
        gpio_pb_pins &= ~interfaces[ioif].gpio_b;
 
-       DBG(printk("GPIO pins: available after: g_in=0x%08x g_out=0x%08x pb=0x%02x\n",
-                  gpio_in_pins, gpio_out_pins, gpio_pb_pins));
+       DBG(printk(KERN_DEBUG "GPIO pins: available after: "
+               "g_in=0x%08x g_out=0x%08x pb=0x%02x\n",
+               gpio_in_pins, gpio_out_pins, gpio_pb_pins));
 
+exit:
        local_irq_restore(flags);
-
-       notify_watchers();
-
-       return 0;
+       if (res == 0)
+               notify_watchers();
+       return res;
 }
 
 
@@ -560,43 +869,35 @@ void cris_free_io_interface(enum cris_io_interface ioif)
        }
        group_set = interfaces[ioif].groups;
        while (NULL != (grp = get_group(group_set))) {
-               if (grp->group == group_f) {
-                       switch (ioif)
-                       {
-                       case if_sync_serial_1:
-                               if ((grp->owner == if_sync_serial_1) &&
-                                   interfaces[if_sync_serial_3].used) {
-                                       grp->owner = if_sync_serial_3;
-                               } else
-                                       grp->used = 0;
-                               break;
-                       case if_sync_serial_3:
-                               if ((grp->owner == if_sync_serial_3) &&
-                                   interfaces[if_sync_serial_1].used) {
-                                       grp->owner = if_sync_serial_1;
-                               } else
-                                       grp->used = 0;
-                               break;
-                       case if_scsi8_0:
-                               if ((grp->owner == if_scsi8_0) &&
-                                   interfaces[if_scsi8_1].used) {
-                                       grp->owner = if_scsi8_1;
-                               } else
-                                       grp->used = 0;
-                               break;
-                       case if_scsi8_1:
-                               if ((grp->owner == if_scsi8_1) &&
-                                   interfaces[if_scsi8_0].used) {
-                                       grp->owner = if_scsi8_0;
-                               } else
-                                       grp->used = 0;
-                               break;
-                       default:
-                               grp->used = 0;
-                       }
-               } else {
-                       grp->used = 0;
+               unsigned int if_group_use = 0;
+
+               switch (grp->group) {
+               case group_a:
+                       if_group_use = interfaces[ioif].group_a;
+                       break;
+               case group_b:
+                       if_group_use = interfaces[ioif].group_b;
+                       break;
+               case group_c:
+                       if_group_use = interfaces[ioif].group_c;
+                       break;
+               case group_d:
+                       if_group_use = interfaces[ioif].group_d;
+                       break;
+               case group_e:
+                       if_group_use = interfaces[ioif].group_e;
+                       break;
+               case group_f:
+                       if_group_use = interfaces[ioif].group_f;
+                       break;
+               default:
+                       BUG_ON(1);
                }
+
+               if ((grp->used & if_group_use) != if_group_use)
+                       BUG_ON(1);
+               grp->used = grp->used & ~if_group_use;
+
                group_set = clear_group_from_set(group_set, grp);
        }
        interfaces[ioif].used = 0;