Patch for orabug 12394831

This patch merged 3 upstream patches:

commit ea4078ca1a7a3a198e519c2a7a2ed6126e40b130
Author: Matthew Garrett <mjg@redhat.com>
Date:   Wed May 26 14:43:48 2010 -0700

    ipmi: reduce polling when interrupts are available
    
    If we're not currently in the middle of a transaction, and if we have
    interrupts, there's no real reason to poll the controller more frequently
    than the core IPMI code does.  Set the interrupt_disabled flag
    appropriately as the interrupt state changes, and make the timeout code
    reset itself only if the transaction is incomplete or we have no
    interrupts.

commit 3326f4f2276791561af1fd5f2020be0186459813
Author: Matthew Garrett <mjg@redhat.com>
Date:   Wed May 26 14:43:49 2010 -0700

    ipmi: reduce polling
    
    We can reasonably alter the poll rate depending on whether we're
    performing a transaction or merely waiting for an event.

commit 4c418ba9695a24917a1fcfa48f7db3fd76337eb7
Author: Doe, YiCheng <yicheng.doe@hp.com>
Date:   Thu Mar 10 14:00:21 2011 -0600

    ipmi: Fix IPMI errors due to timing problems
    
    This patch fixes an issue in OpenIPMI module where sometimes an ABORT command
    is sent after sending an IPMI request to BMC causing the IPMI request to fail.
    
diff -up linux-2.6.18.i686/drivers/char/ipmi/ipmi_si_intf.c.orig linux-2.6.18.i686/drivers/char/ipmi/ipmi_si_intf.c
--- linux-2.6.18.i686/drivers/char/ipmi/ipmi_si_intf.c.orig	2011-06-14 12:45:25.000000000 +0800
+++ linux-2.6.18.i686/drivers/char/ipmi/ipmi_si_intf.c	2011-06-14 13:07:48.000000000 +0800
@@ -380,6 +380,9 @@ static inline void disable_si_irq(struct
 	if ((smi_info->irq) && (!smi_info->interrupt_disabled)) {
 		start_disable_irq(smi_info);
 		smi_info->interrupt_disabled = 1;
+		if (!atomic_read(&smi_info->stop_operation))
+			mod_timer(&smi_info->si_timer,
+				  jiffies + SI_TIMEOUT_JIFFIES);
 	}
 }
 
@@ -628,6 +631,8 @@ static void handle_transaction_done(stru
 			printk(KERN_WARNING
 			       "ipmi_si: Could not enable interrupts"
 			       ", failed set, using polled mode.\n");
+		} else {
+			smi_info->interrupt_disabled = 0;
 		}
 		smi_info->si_state = SI_NORMAL;
 		break;
@@ -810,6 +815,19 @@ static void sender(void                *
 	printk("**Enqueue: %d.%9.9d\n", t.tv_sec, t.tv_usec);
 #endif
 
+	/*
+	 * last_timeout_jiffies is updated here to avoid
+	 * smi_timeout() handler passing very large time_diff
+	 * value to smi_event_handler() that causes
+	 * the send command to abort.
+	 */
+	smi_info->last_timeout_jiffies = jiffies;
+
+	mod_timer(&smi_info->si_timer, jiffies + SI_TIMEOUT_JIFFIES);
+
+	if (smi_info->thread)
+		wake_up_process(smi_info->thread);
+
 	if (smi_info->run_to_completion) {
 		/* If we are running to completion, then throw it in
 		   the list and run transactions until everything is
@@ -884,6 +902,8 @@ static int ipmi_thread(void *data)
 		}
 		else if (smi_result == SI_SM_CALL_WITH_DELAY)
 			schedule();
+		else if (smi_result == SI_SM_IDLE)
+			schedule_timeout_interruptible(100);
 		else
 			schedule_timeout_interruptible(1);
 	}
@@ -922,6 +942,7 @@ static void smi_timeout(unsigned long da
 	unsigned long     flags;
 	unsigned long     jiffies_now;
 	long              time_diff;
+	long		  timeout;
 #ifdef DEBUG_TIMING
 	struct timeval    t;
 #endif
@@ -942,11 +963,11 @@ static void smi_timeout(unsigned long da
 
 	if ((smi_info->irq) && (!smi_info->interrupt_disabled)) {
 		/* Running with interrupts, only do long timeouts. */
-		smi_info->si_timer.expires = jiffies + SI_TIMEOUT_JIFFIES;
+		timeout = jiffies + SI_TIMEOUT_JIFFIES;
 		spin_lock_irqsave(&smi_info->count_lock, flags);
 		smi_info->long_timeouts++;
 		spin_unlock_irqrestore(&smi_info->count_lock, flags);
-		goto do_add_timer;
+		goto do_mod_timer;
 	}
 
 	/* If the state machine asks for a short delay, then shorten
@@ -955,16 +976,17 @@ static void smi_timeout(unsigned long da
 		spin_lock_irqsave(&smi_info->count_lock, flags);
 		smi_info->short_timeouts++;
 		spin_unlock_irqrestore(&smi_info->count_lock, flags);
-		smi_info->si_timer.expires = jiffies + 1;
+		timeout = jiffies + 1;
 	} else {
 		spin_lock_irqsave(&smi_info->count_lock, flags);
 		smi_info->long_timeouts++;
 		spin_unlock_irqrestore(&smi_info->count_lock, flags);
-		smi_info->si_timer.expires = jiffies + SI_TIMEOUT_JIFFIES;
+		timeout = jiffies + SI_TIMEOUT_JIFFIES;
 	}
 
- do_add_timer:
-	add_timer(&(smi_info->si_timer));
+ do_mod_timer:
+	if (smi_result != SI_SM_IDLE)
+		mod_timer(&(smi_info->si_timer), timeout);
 }
 
 static irqreturn_t si_irq_handler(int irq, void *data, struct pt_regs *regs)
@@ -2776,7 +2798,7 @@ static int try_smi_init(struct smi_info 
 	atomic_set(&new_smi->req_events, 0);
 	new_smi->run_to_completion = 0;
 
-	new_smi->interrupt_disabled = 0;
+	new_smi->interrupt_disabled = 1;
 	atomic_set(&new_smi->stop_operation, 0);
 	new_smi->intf_num = smi_num;
 	smi_num++;
