]> Git Repo - linux.git/blobdiff - drivers/s390/cio/cio.c
[S390] ipl/dump on panic.
[linux.git] / drivers / s390 / cio / cio.c
index 5b20d8c9c0257eec01184b8de15eb4bd2167dd12..050963f158025d99e005392318ce0da0e4a7b8b5 100644 (file)
@@ -11,7 +11,6 @@
  */
 
 #include <linux/module.h>
-#include <linux/config.h>
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/device.h>
@@ -148,7 +147,7 @@ cio_tpi(void)
                sch->driver->irq(&sch->dev);
        spin_unlock(&sch->lock);
        irq_exit ();
-       __local_bh_enable();
+       _local_bh_enable();
        return 1;
 }
 
@@ -520,6 +519,7 @@ cio_validate_subchannel (struct subchannel *sch, struct subchannel_id schid)
        memset(sch, 0, sizeof(struct subchannel));
 
        spin_lock_init(&sch->lock);
+       mutex_init(&sch->reg_mutex);
 
        /* Set a name for the subchannel */
        snprintf (sch->dev.bus_id, BUS_ID_SIZE, "0.%x.%04x", schid.ssid,
@@ -798,7 +798,7 @@ struct subchannel *
 cio_get_console_subchannel(void)
 {
        if (!console_subchannel_in_use)
-               return 0;
+               return NULL;
        return &console_subchannel;
 }
 
@@ -841,14 +841,26 @@ __clear_subchannel_easy(struct subchannel_id schid)
        return -EBUSY;
 }
 
-extern void do_reipl(unsigned long devno);
-static int
-__shutdown_subchannel_easy(struct subchannel_id schid, void *data)
+struct sch_match_id {
+       struct subchannel_id schid;
+       struct ccw_dev_id devid;
+       int rc;
+};
+
+static int __shutdown_subchannel_easy_and_match(struct subchannel_id schid,
+       void *data)
 {
        struct schib schib;
+       struct sch_match_id *match_id = data;
 
        if (stsch_err(schid, &schib))
                return -ENXIO;
+       if (match_id && schib.pmcw.dnv &&
+               (schib.pmcw.dev == match_id->devid.devno) &&
+               (schid.ssid == match_id->devid.ssid)) {
+               match_id->schid = schid;
+               match_id->rc = 0;
+       }
        if (!schib.pmcw.ena)
                return 0;
        switch(__disable_subchannel_easy(schid, &schib)) {
@@ -864,17 +876,36 @@ __shutdown_subchannel_easy(struct subchannel_id schid, void *data)
        return 0;
 }
 
-void
-clear_all_subchannels(void)
+static int clear_all_subchannels_and_match(struct ccw_dev_id *devid,
+       struct subchannel_id *schid)
+{
+       struct sch_match_id match_id;
+
+       match_id.devid = *devid;
+       match_id.rc = -ENODEV;
+       local_irq_disable();
+       for_each_subchannel(__shutdown_subchannel_easy_and_match, &match_id);
+       if (match_id.rc == 0)
+               *schid = match_id.schid;
+       return match_id.rc;
+}
+
+
+void clear_all_subchannels(void)
 {
        local_irq_disable();
-       for_each_subchannel(__shutdown_subchannel_easy, NULL);
+       for_each_subchannel(__shutdown_subchannel_easy_and_match, NULL);
 }
 
+extern void do_reipl_asm(__u32 schid);
+
 /* Make sure all subchannels are quiet before we re-ipl an lpar. */
-void
-reipl(unsigned long devno)
+void reipl_ccw_dev(struct ccw_dev_id *devid)
 {
-       clear_all_subchannels();
-       do_reipl(devno);
+       struct subchannel_id schid;
+
+       if (clear_all_subchannels_and_match(devid, &schid))
+               panic("IPL Device not found\n");
+       cio_reset_channel_paths();
+       do_reipl_asm(*((__u32*)&schid));
 }
This page took 0.029547 seconds and 4 git commands to generate.