]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/s390/cio/cio.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6
[linux-2.6-omap-h63xx.git] / drivers / s390 / cio / cio.c
index 326f4cc7f92c932578870443f1421488501c25c0..3db2c386546f13733f122b6e0d6ef7410416548c 100644 (file)
@@ -114,6 +114,7 @@ cio_tpi(void)
        struct tpi_info *tpi_info;
        struct subchannel *sch;
        struct irb *irb;
+       int irq_context;
 
        tpi_info = (struct tpi_info *) __LC_SUBCHANNEL_ID;
        if (tpi (NULL) != 1)
@@ -126,7 +127,9 @@ cio_tpi(void)
        sch = (struct subchannel *)(unsigned long)tpi_info->intparm;
        if (!sch)
                return 1;
-       local_bh_disable();
+       irq_context = in_interrupt();
+       if (!irq_context)
+               local_bh_disable();
        irq_enter ();
        spin_lock(sch->lock);
        memcpy(&sch->schib.scsw, &irb->scsw, sizeof(union scsw));
@@ -134,7 +137,8 @@ cio_tpi(void)
                sch->driver->irq(sch);
        spin_unlock(sch->lock);
        irq_exit ();
-       _local_bh_enable();
+       if (!irq_context)
+               _local_bh_enable();
        return 1;
 }
 
@@ -153,7 +157,7 @@ cio_start_handle_notoper(struct subchannel *sch, __u8 lpm)
        CIO_MSG_EVENT(2, "cio_start: 'not oper' status for "
                      "subchannel 0.%x.%04x!\n", sch->schid.ssid,
                      sch->schid.sch_no);
-       sprintf(dbf_text, "no%s", sch->dev.bus_id);
+       sprintf(dbf_text, "no%s", dev_name(&sch->dev));
        CIO_TRACE_EVENT(0, dbf_text);
        CIO_HEX_EVENT(0, &sch->schib, sizeof (struct schib));
 
@@ -171,7 +175,7 @@ cio_start_key (struct subchannel *sch,      /* subchannel structure */
        union orb *orb;
 
        CIO_TRACE_EVENT(4, "stIO");
-       CIO_TRACE_EVENT(4, sch->dev.bus_id);
+       CIO_TRACE_EVENT(4, dev_name(&sch->dev));
 
        orb = &to_io_private(sch)->orb;
        memset(orb, 0, sizeof(union orb));
@@ -232,7 +236,7 @@ cio_resume (struct subchannel *sch)
        int ccode;
 
        CIO_TRACE_EVENT (4, "resIO");
-       CIO_TRACE_EVENT (4, sch->dev.bus_id);
+       CIO_TRACE_EVENT(4, dev_name(&sch->dev));
 
        ccode = rsch (sch->schid);
 
@@ -269,7 +273,7 @@ cio_halt(struct subchannel *sch)
                return -ENODEV;
 
        CIO_TRACE_EVENT (2, "haltIO");
-       CIO_TRACE_EVENT (2, sch->dev.bus_id);
+       CIO_TRACE_EVENT(2, dev_name(&sch->dev));
 
        /*
         * Issue "Halt subchannel" and process condition code
@@ -304,7 +308,7 @@ cio_clear(struct subchannel *sch)
                return -ENODEV;
 
        CIO_TRACE_EVENT (2, "clearIO");
-       CIO_TRACE_EVENT (2, sch->dev.bus_id);
+       CIO_TRACE_EVENT(2, dev_name(&sch->dev));
 
        /*
         * Issue "Clear subchannel" and process condition code
@@ -340,7 +344,7 @@ cio_cancel (struct subchannel *sch)
                return -ENODEV;
 
        CIO_TRACE_EVENT (2, "cancelIO");
-       CIO_TRACE_EVENT (2, sch->dev.bus_id);
+       CIO_TRACE_EVENT(2, dev_name(&sch->dev));
 
        ccode = xsch (sch->schid);
 
@@ -404,7 +408,7 @@ int cio_enable_subchannel(struct subchannel *sch, u32 intparm)
        int ret;
 
        CIO_TRACE_EVENT (2, "ensch");
-       CIO_TRACE_EVENT (2, sch->dev.bus_id);
+       CIO_TRACE_EVENT(2, dev_name(&sch->dev));
 
        if (sch_is_pseudo_sch(sch))
                return -EINVAL;
@@ -454,7 +458,7 @@ int cio_disable_subchannel(struct subchannel *sch)
        int ret;
 
        CIO_TRACE_EVENT (2, "dissch");
-       CIO_TRACE_EVENT (2, sch->dev.bus_id);
+       CIO_TRACE_EVENT(2, dev_name(&sch->dev));
 
        if (sch_is_pseudo_sch(sch))
                return 0;
@@ -571,8 +575,10 @@ int cio_validate_subchannel(struct subchannel *sch, struct subchannel_id schid)
        }
        mutex_init(&sch->reg_mutex);
        /* Set a name for the subchannel */
-       snprintf (sch->dev.bus_id, BUS_ID_SIZE, "0.%x.%04x", schid.ssid,
-                 schid.sch_no);
+       if (cio_is_console(schid))
+               sch->dev.init_name = cio_get_console_sch_name(schid);
+       else
+               dev_set_name(&sch->dev, "0.%x.%04x", schid.ssid, schid.sch_no);
 
        /*
         * The first subchannel that is not-operational (ccode==3)
@@ -677,6 +683,7 @@ do_IRQ (struct pt_regs *regs)
 
 #ifdef CONFIG_CCW_CONSOLE
 static struct subchannel console_subchannel;
+static char console_sch_name[10] = "0.x.xxxx";
 static struct io_subchannel_private console_priv;
 static int console_subchannel_in_use;
 
@@ -827,6 +834,12 @@ cio_get_console_subchannel(void)
        return &console_subchannel;
 }
 
+const char *cio_get_console_sch_name(struct subchannel_id schid)
+{
+       snprintf(console_sch_name, 10, "0.%x.%04x", schid.ssid, schid.sch_no);
+       return (const char *)console_sch_name;
+}
+
 #endif
 static int
 __disable_subchannel_easy(struct subchannel_id schid, struct schib *schib)
@@ -846,19 +859,6 @@ __disable_subchannel_easy(struct subchannel_id schid, struct schib *schib)
        return -EBUSY; /* uhm... */
 }
 
-/* we can't use the normal udelay here, since it enables external interrupts */
-
-static void udelay_reset(unsigned long usecs)
-{
-       uint64_t start_cc, end_cc;
-
-       asm volatile ("STCK %0" : "=m" (start_cc));
-       do {
-               cpu_relax();
-               asm volatile ("STCK %0" : "=m" (end_cc));
-       } while (((end_cc - start_cc)/4096) < usecs);
-}
-
 static int
 __clear_io_subchannel_easy(struct subchannel_id schid)
 {
@@ -874,7 +874,7 @@ __clear_io_subchannel_easy(struct subchannel_id schid)
                        if (schid_equal(&ti.schid, &schid))
                                return 0;
                }
-               udelay_reset(100);
+               udelay_simple(100);
        }
        return -EBUSY;
 }
@@ -882,7 +882,7 @@ __clear_io_subchannel_easy(struct subchannel_id schid)
 static void __clear_chsc_subchannel_easy(void)
 {
        /* It seems we can only wait for a bit here :/ */
-       udelay_reset(100);
+       udelay_simple(100);
 }
 
 static int pgm_check_occured;
@@ -892,7 +892,7 @@ static void cio_reset_pgm_check_handler(void)
        pgm_check_occured = 1;
 }
 
-static int stsch_reset(struct subchannel_id schid, volatile struct schib *addr)
+static int stsch_reset(struct subchannel_id schid, struct schib *addr)
 {
        int rc;