mfd: vexpress: Handle pending config transactions
authorPawel Moll <pawel.moll@arm.com>
Thu, 25 Apr 2013 17:14:51 +0000 (18:14 +0100)
committerSamuel Ortiz <sameo@linux.intel.com>
Fri, 26 Apr 2013 14:10:03 +0000 (16:10 +0200)
The config transactions "scheduler" was hopelessly broken,
repeating completed transaction instead of picking up
next pending one.

Fixed now. Also improved debug messages.

Signed-off-by: Pawel Moll <pawel.moll@arm.com>
Reviewed-by: Jon Medhurst <tixy@linaro.org>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
drivers/mfd/vexpress-config.c

index 3c1723aa62250c28c61aab4b3f83442e28770dc8..84ce6b9daa3dea13b2adf8d07d907fb128d1175c 100644 (file)
@@ -184,13 +184,14 @@ static int vexpress_config_schedule(struct vexpress_config_trans *trans)
 
        spin_lock_irqsave(&bridge->transactions_lock, flags);
 
-       vexpress_config_dump_trans("Executing", trans);
-
-       if (list_empty(&bridge->transactions))
+       if (list_empty(&bridge->transactions)) {
+               vexpress_config_dump_trans("Executing", trans);
                status = bridge->info->func_exec(trans->func->func,
                                trans->offset, trans->write, trans->data);
-       else
+       } else {
+               vexpress_config_dump_trans("Queuing", trans);
                status = VEXPRESS_CONFIG_STATUS_WAIT;
+       }
 
        switch (status) {
        case VEXPRESS_CONFIG_STATUS_DONE:
@@ -212,25 +213,31 @@ void vexpress_config_complete(struct vexpress_config_bridge *bridge,
 {
        struct vexpress_config_trans *trans;
        unsigned long flags;
+       const char *message = "Completed";
 
        spin_lock_irqsave(&bridge->transactions_lock, flags);
 
        trans = list_first_entry(&bridge->transactions,
                        struct vexpress_config_trans, list);
-       vexpress_config_dump_trans("Completed", trans);
-
        trans->status = status;
-       list_del(&trans->list);
 
-       if (!list_empty(&bridge->transactions)) {
-               vexpress_config_dump_trans("Pending", trans);
+       do {
+               vexpress_config_dump_trans(message, trans);
+               list_del(&trans->list);
+               complete(&trans->completion);
 
-               bridge->info->func_exec(trans->func->func, trans->offset,
-                               trans->write, trans->data);
-       }
-       spin_unlock_irqrestore(&bridge->transactions_lock, flags);
+               if (list_empty(&bridge->transactions))
+                       break;
+
+               trans = list_first_entry(&bridge->transactions,
+                               struct vexpress_config_trans, list);
+               vexpress_config_dump_trans("Executing pending", trans);
+               trans->status = bridge->info->func_exec(trans->func->func,
+                               trans->offset, trans->write, trans->data);
+               message = "Finished pending";
+       } while (trans->status == VEXPRESS_CONFIG_STATUS_DONE);
 
-       complete(&trans->completion);
+       spin_unlock_irqrestore(&bridge->transactions_lock, flags);
 }
 EXPORT_SYMBOL(vexpress_config_complete);