]> err.no Git - linux-2.6/commitdiff
[S390] cio: Repair chpid event handling.
authorCornelia Huck <cornelia.huck@de.ibm.com>
Mon, 14 Jul 2008 07:59:02 +0000 (09:59 +0200)
committerHeiko Carstens <heiko.carstens@de.ibm.com>
Mon, 14 Jul 2008 08:02:11 +0000 (10:02 +0200)
Passing the affected chpid in chp_event() worked only by
chance since chpid is the first element in res_acc_data.
Make it work properly by generalizing res_acc_data as
chp_link and always passing around a properly filled out
chp_link structure in chp_event().

Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
drivers/s390/cio/chp.c
drivers/s390/cio/chp.h
drivers/s390/cio/chsc.c
drivers/s390/cio/css.h
drivers/s390/cio/device.c

index 62df43b2124c59cf8b1264b28c46b201d9ff9209..19078d5288536a63b375c219a256ef877f27611c 100644 (file)
@@ -525,7 +525,7 @@ static void chp_process_crw(struct crw *crw0, struct crw *crw1,
        }
 }
 
-int chp_ssd_get_mask(struct chsc_ssd_info *ssd, struct res_acc_data *data)
+int chp_ssd_get_mask(struct chsc_ssd_info *ssd, struct chp_link *link)
 {
        int i;
        int mask;
@@ -534,10 +534,10 @@ int chp_ssd_get_mask(struct chsc_ssd_info *ssd, struct res_acc_data *data)
                mask = 0x80 >> i;
                if (!(ssd->path_mask & mask))
                        continue;
-               if (!chp_id_is_equal(&ssd->chpid[i], &data->chpid))
+               if (!chp_id_is_equal(&ssd->chpid[i], &link->chpid))
                        continue;
                if ((ssd->fla_valid_mask & mask) &&
-                   ((ssd->fla[i] & data->fla_mask) != data->fla))
+                   ((ssd->fla[i] & link->fla_mask) != link->fla))
                        continue;
                return mask;
        }
index dffe2771ddacded5d8b0dd886589255d1767c617..26c3d22461764b56630958bbbfa6cb9714b166b0 100644 (file)
@@ -24,7 +24,7 @@
 #define CHP_VARY_ON 2
 #define CHP_VARY_OFF 3
 
-struct res_acc_data {
+struct chp_link {
        struct chp_id chpid;
        u32 fla_mask;
        u16 fla;
@@ -60,5 +60,5 @@ int chp_new(struct chp_id chpid);
 void chp_cfg_schedule(struct chp_id chpid, int configure);
 void chp_cfg_cancel_deconfigure(struct chp_id chpid);
 int chp_info_get_status(struct chp_id chpid);
-int chp_ssd_get_mask(struct chsc_ssd_info *, struct res_acc_data *);
+int chp_ssd_get_mask(struct chsc_ssd_info *, struct chp_link *);
 #endif /* S390_CHP_H */
index 62b0b16fe3d3e60405fef99f5c28acfbfaaa7a10..e23c3806972a018921f94f20e85bd4017fab808e 100644 (file)
@@ -146,15 +146,18 @@ out_unreg:
 void chsc_chp_offline(struct chp_id chpid)
 {
        char dbf_txt[15];
+       struct chp_link link;
 
        sprintf(dbf_txt, "chpr%x.%02x", chpid.cssid, chpid.id);
        CIO_TRACE_EVENT(2, dbf_txt);
 
        if (chp_get_status(chpid) <= 0)
                return;
+       memset(&link, 0, sizeof(struct chp_link));
+       link.chpid = chpid;
        /* Wait until previous actions have settled. */
        css_wait_for_slow_path();
-       for_each_subchannel_staged(s390_subchannel_remove_chpid, NULL, &chpid);
+       for_each_subchannel_staged(s390_subchannel_remove_chpid, NULL, &link);
 }
 
 static int s390_process_res_acc_new_sch(struct subchannel_id schid, void *data)
@@ -187,15 +190,15 @@ static int __s390_process_res_acc(struct subchannel *sch, void *data)
        return 0;
 }
 
-static void s390_process_res_acc (struct res_acc_data *res_data)
+static void s390_process_res_acc(struct chp_link *link)
 {
        char dbf_txt[15];
 
-       sprintf(dbf_txt, "accpr%x.%02x", res_data->chpid.cssid,
-               res_data->chpid.id);
+       sprintf(dbf_txt, "accpr%x.%02x", link->chpid.cssid,
+               link->chpid.id);
        CIO_TRACE_EVENT( 2, dbf_txt);
-       if (res_data->fla != 0) {
-               sprintf(dbf_txt, "fla%x", res_data->fla);
+       if (link->fla != 0) {
+               sprintf(dbf_txt, "fla%x", link->fla);
                CIO_TRACE_EVENT( 2, dbf_txt);
        }
        /* Wait until previous actions have settled. */
@@ -208,7 +211,7 @@ static void s390_process_res_acc (struct res_acc_data *res_data)
         * will we have to do.
         */
        for_each_subchannel_staged(__s390_process_res_acc,
-                                  s390_process_res_acc_new_sch, res_data);
+                                  s390_process_res_acc_new_sch, link);
 }
 
 static int
@@ -281,7 +284,7 @@ static void chsc_process_sei_link_incident(struct chsc_sei_area *sei_area)
 
 static void chsc_process_sei_res_acc(struct chsc_sei_area *sei_area)
 {
-       struct res_acc_data res_data;
+       struct chp_link link;
        struct chp_id chpid;
        int status;
 
@@ -297,18 +300,18 @@ static void chsc_process_sei_res_acc(struct chsc_sei_area *sei_area)
                chp_new(chpid);
        else if (!status)
                return;
-       memset(&res_data, 0, sizeof(struct res_acc_data));
-       res_data.chpid = chpid;
+       memset(&link, 0, sizeof(struct chp_link));
+       link.chpid = chpid;
        if ((sei_area->vf & 0xc0) != 0) {
-               res_data.fla = sei_area->fla;
+               link.fla = sei_area->fla;
                if ((sei_area->vf & 0xc0) == 0xc0)
                        /* full link address */
-                       res_data.fla_mask = 0xffff;
+                       link.fla_mask = 0xffff;
                else
                        /* link address */
-                       res_data.fla_mask = 0xff00;
+                       link.fla_mask = 0xff00;
        }
-       s390_process_res_acc(&res_data);
+       s390_process_res_acc(&link);
 }
 
 struct chp_config_data {
@@ -413,18 +416,18 @@ static void chsc_process_crw(struct crw *crw0, struct crw *crw1, int overflow)
 void chsc_chp_online(struct chp_id chpid)
 {
        char dbf_txt[15];
-       struct res_acc_data res_data;
+       struct chp_link link;
 
        sprintf(dbf_txt, "cadd%x.%02x", chpid.cssid, chpid.id);
        CIO_TRACE_EVENT(2, dbf_txt);
 
        if (chp_get_status(chpid) != 0) {
-               memset(&res_data, 0, sizeof(struct res_acc_data));
-               res_data.chpid = chpid;
+               memset(&link, 0, sizeof(struct chp_link));
+               link.chpid = chpid;
                /* Wait until previous actions have settled. */
                css_wait_for_slow_path();
                for_each_subchannel_staged(__s390_process_res_acc, NULL,
-                                          &res_data);
+                                          &link);
        }
 }
 
@@ -432,13 +435,13 @@ static void __s390_subchannel_vary_chpid(struct subchannel *sch,
                                         struct chp_id chpid, int on)
 {
        unsigned long flags;
-       struct res_acc_data res_data;
+       struct chp_link link;
 
-       memset(&res_data, 0, sizeof(struct res_acc_data));
-       res_data.chpid = chpid;
+       memset(&link, 0, sizeof(struct chp_link));
+       link.chpid = chpid;
        spin_lock_irqsave(sch->lock, flags);
        if (sch->driver && sch->driver->chp_event)
-               sch->driver->chp_event(sch, &res_data,
+               sch->driver->chp_event(sch, &link,
                                       on ? CHP_VARY_ON : CHP_VARY_OFF);
        spin_unlock_irqrestore(sch->lock, flags);
 }
@@ -479,6 +482,10 @@ __s390_vary_chpid_on(struct subchannel_id schid, void *data)
  */
 int chsc_chp_vary(struct chp_id chpid, int on)
 {
+       struct chp_link link;
+
+       memset(&link, 0, sizeof(struct chp_link));
+       link.chpid = chpid;
        /* Wait until previous actions have settled. */
        css_wait_for_slow_path();
        /*
@@ -487,10 +494,10 @@ int chsc_chp_vary(struct chp_id chpid, int on)
 
        if (on)
                for_each_subchannel_staged(s390_subchannel_vary_chpid_on,
-                                          __s390_vary_chpid_on, &chpid);
+                                          __s390_vary_chpid_on, &link);
        else
                for_each_subchannel_staged(s390_subchannel_vary_chpid_off,
-                                          NULL, &chpid);
+                                          NULL, &link);
 
        return 0;
 }
index 3ec3dc5a1e5edd2a3e7030d2a37983ea33cc272a..38bf9ddb8412da9a9e7205458861fec2873f42c6 100644 (file)
@@ -59,6 +59,7 @@ struct pgid {
 } __attribute__ ((packed));
 
 struct subchannel;
+struct chp_link;
 /**
  * struct css_driver - device driver for subchannels
  * @owner: owning module
@@ -77,7 +78,7 @@ struct css_driver {
        unsigned int subchannel_type;
        struct device_driver drv;
        void (*irq)(struct subchannel *);
-       int (*chp_event)(struct subchannel *, void *, int);
+       int (*chp_event)(struct subchannel *, struct chp_link *, int);
        int (*sch_event)(struct subchannel *, int);
        int (*probe)(struct subchannel *);
        int (*remove)(struct subchannel *);
index 67e7a31239549e4a16c205f5f6a473f096f7e470..522d47afc950d567f9338d963b91fc8da6530adc 100644 (file)
@@ -128,7 +128,8 @@ static int io_subchannel_probe(struct subchannel *);
 static int io_subchannel_remove(struct subchannel *);
 static void io_subchannel_shutdown(struct subchannel *);
 static int io_subchannel_sch_event(struct subchannel *, int);
-static int io_subchannel_chp_event(struct subchannel *, void *, int);
+static int io_subchannel_chp_event(struct subchannel *, struct chp_link *,
+                                  int);
 
 static struct css_driver io_subchannel_driver = {
        .owner = THIS_MODULE,
@@ -1329,14 +1330,12 @@ static void io_subchannel_terminate_path(struct subchannel *sch, u8 mask)
 
 }
 
-static int io_subchannel_chp_event(struct subchannel *sch, void *data,
-                                  int event)
+static int io_subchannel_chp_event(struct subchannel *sch,
+                                  struct chp_link *link, int event)
 {
        int mask;
-       struct res_acc_data *res_data;
 
-       res_data = data;
-       mask = chp_ssd_get_mask(&sch->ssd_info, res_data);
+       mask = chp_ssd_get_mask(&sch->ssd_info, link);
        if (!mask)
                return 0;
        switch (event) {