macintosh/via-macii: Simplify locking
authorFinn Thain <fthain@telegraphics.com.au>
Wed, 12 Sep 2018 00:18:44 +0000 (20:18 -0400)
committerMichael Ellerman <mpe@ellerman.id.au>
Mon, 8 Oct 2018 11:53:10 +0000 (22:53 +1100)
Modifying the request queue or changing the current state requires
mutual exclusion. Use local_irq_disable() consistently for this
rather than disabling the ADB interrupt. This simplifies the locking
scheme and brings via-macii into line with the other ADB drivers.

Tested-by: Stan Johnson <userm57@yahoo.com>
Signed-off-by: Finn Thain <fthain@telegraphics.com.au>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
drivers/macintosh/via-macii.c

index 7e0e32f..6ed9ac9 100644 (file)
@@ -216,22 +216,23 @@ static void macii_queue_poll(void)
 static int macii_send_request(struct adb_request *req, int sync)
 {
        int err;
-       unsigned long flags;
 
-       local_irq_save(flags);
        err = macii_write(req);
-       local_irq_restore(flags);
+       if (err)
+               return err;
 
-       if (!err && sync)
+       if (sync)
                while (!req->complete)
                        macii_poll();
 
-       return err;
+       return 0;
 }
 
 /* Send an ADB request (append to request queue) */
 static int macii_write(struct adb_request *req)
 {
+       unsigned long flags;
+
        if (req->nbytes < 2 || req->data[0] != ADB_PACKET || req->nbytes > 15) {
                req->complete = 1;
                return -EINVAL;
@@ -242,6 +243,8 @@ static int macii_write(struct adb_request *req)
        req->complete = 0;
        req->reply_len = 0;
 
+       local_irq_save(flags);
+
        if (current_req != NULL) {
                last_req->next = req;
                last_req = req;
@@ -250,6 +253,9 @@ static int macii_write(struct adb_request *req)
                last_req = req;
                if (macii_state == idle) macii_start();
        }
+
+       local_irq_restore(flags);
+
        return 0;
 }
 
@@ -293,9 +299,7 @@ static inline int need_autopoll(void) {
 /* Prod the chip without interrupts */
 static void macii_poll(void)
 {
-       disable_irq(IRQ_MAC_ADB);
        macii_interrupt(0, NULL);
-       enable_irq(IRQ_MAC_ADB);
 }
 
 /* Reset the bus */
@@ -358,13 +362,18 @@ static irqreturn_t macii_interrupt(int irq, void *arg)
 {
        int x;
        struct adb_request *req;
+       unsigned long flags;
+
+       local_irq_save(flags);
 
        if (!arg) {
                /* Clear the SR IRQ flag when polling. */
                if (via[IFR] & SR_INT)
                        via[IFR] = SR_INT;
-               else
+               else {
+                       local_irq_restore(flags);
                        return IRQ_NONE;
+               }
        }
 
        last_status = status;
@@ -512,5 +521,6 @@ static irqreturn_t macii_interrupt(int irq, void *arg)
                break;
        }
 
+       local_irq_restore(flags);
        return IRQ_HANDLED;
 }