diff options
author | Scott Wood <scottwood@freescale.com> | 2014-05-14 18:11:24 (GMT) |
---|---|---|
committer | Scott Wood <scottwood@freescale.com> | 2014-05-14 18:12:24 (GMT) |
commit | ffb069a30665ec06c05916355bc3252e33fc863b (patch) | |
tree | ba7b82696000c0f2983672d22966b83112da874e /drivers/char | |
parent | 8d5cd1658cb0c97d5429124f9fb5caa88c460186 (diff) | |
parent | 3756888c2a2da9c7291d39cacd1184171111b49d (diff) | |
download | linux-fsl-qoriq-ffb069a30665ec06c05916355bc3252e33fc863b.tar.xz |
Merge remote-tracking branch 'stable/linux-3.12.y' into sdk-v1.6.x
Signed-off-by: Scott Wood <scottwood@freescale.com>
Conflicts:
arch/sparc/Kconfig
drivers/tty/tty_buffer.c
Diffstat (limited to 'drivers/char')
-rw-r--r-- | drivers/char/ipmi/ipmi_bt_sm.c | 2 | ||||
-rw-r--r-- | drivers/char/ipmi/ipmi_si_intf.c | 46 | ||||
-rw-r--r-- | drivers/char/mem.c | 6 |
3 files changed, 35 insertions, 19 deletions
diff --git a/drivers/char/ipmi/ipmi_bt_sm.c b/drivers/char/ipmi/ipmi_bt_sm.c index a22a7a5..8156caf 100644 --- a/drivers/char/ipmi/ipmi_bt_sm.c +++ b/drivers/char/ipmi/ipmi_bt_sm.c @@ -352,7 +352,7 @@ static inline void write_all_bytes(struct si_sm_data *bt) static inline int read_all_bytes(struct si_sm_data *bt) { - unsigned char i; + unsigned int i; /* * length is "framing info", minimum = 4: NetFn, Seq, Cmd, cCode. diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index 15e4a60..e5bdd1a 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c @@ -249,6 +249,9 @@ struct smi_info { /* The timer for this si. */ struct timer_list si_timer; + /* This flag is set, if the timer is running (timer_pending() isn't enough) */ + bool timer_running; + /* The time (in jiffies) the last timeout occurred at. */ unsigned long last_timeout_jiffies; @@ -435,6 +438,13 @@ static void start_clear_flags(struct smi_info *smi_info) smi_info->si_state = SI_CLEARING_FLAGS; } +static void smi_mod_timer(struct smi_info *smi_info, unsigned long new_val) +{ + smi_info->last_timeout_jiffies = jiffies; + mod_timer(&smi_info->si_timer, new_val); + smi_info->timer_running = true; +} + /* * When we have a situtaion where we run out of memory and cannot * allocate messages, we just leave them in the BMC and run the system @@ -447,8 +457,7 @@ static inline void disable_si_irq(struct smi_info *smi_info) 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); + smi_mod_timer(smi_info, jiffies + SI_TIMEOUT_JIFFIES); } } @@ -908,15 +917,7 @@ static void sender(void *send_info, list_add_tail(&msg->link, &smi_info->xmit_msgs); if (smi_info->si_state == SI_NORMAL && smi_info->curr_msg == NULL) { - /* - * 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); + smi_mod_timer(smi_info, jiffies + SI_TIMEOUT_JIFFIES); if (smi_info->thread) wake_up_process(smi_info->thread); @@ -1005,6 +1006,17 @@ static int ipmi_thread(void *data) spin_lock_irqsave(&(smi_info->si_lock), flags); smi_result = smi_event_handler(smi_info, 0); + + /* + * If the driver is doing something, there is a possible + * race with the timer. If the timer handler see idle, + * and the thread here sees something else, the timer + * handler won't restart the timer even though it is + * required. So start it here if necessary. + */ + if (smi_result != SI_SM_IDLE && !smi_info->timer_running) + smi_mod_timer(smi_info, jiffies + SI_TIMEOUT_JIFFIES); + spin_unlock_irqrestore(&(smi_info->si_lock), flags); busy_wait = ipmi_thread_busy_wait(smi_result, smi_info, &busy_until); @@ -1074,10 +1086,6 @@ static void smi_timeout(unsigned long data) * SI_USEC_PER_JIFFY); smi_result = smi_event_handler(smi_info, time_diff); - spin_unlock_irqrestore(&(smi_info->si_lock), flags); - - smi_info->last_timeout_jiffies = jiffies_now; - if ((smi_info->irq) && (!smi_info->interrupt_disabled)) { /* Running with interrupts, only do long timeouts. */ timeout = jiffies + SI_TIMEOUT_JIFFIES; @@ -1099,7 +1107,10 @@ static void smi_timeout(unsigned long data) do_mod_timer: if (smi_result != SI_SM_IDLE) - mod_timer(&(smi_info->si_timer), timeout); + smi_mod_timer(smi_info, timeout); + else + smi_info->timer_running = false; + spin_unlock_irqrestore(&(smi_info->si_lock), flags); } static irqreturn_t si_irq_handler(int irq, void *data) @@ -1147,8 +1158,7 @@ static int smi_start_processing(void *send_info, /* Set up the timer that drives the interface. */ setup_timer(&new_smi->si_timer, smi_timeout, (long)new_smi); - new_smi->last_timeout_jiffies = jiffies; - mod_timer(&new_smi->si_timer, jiffies + SI_TIMEOUT_JIFFIES); + smi_mod_timer(new_smi, jiffies + SI_TIMEOUT_JIFFIES); /* * Check if the user forcefully enabled the daemon. diff --git a/drivers/char/mem.c b/drivers/char/mem.c index f895a8c..d1f4675 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c @@ -100,6 +100,9 @@ static ssize_t read_mem(struct file *file, char __user *buf, ssize_t read, sz; char *ptr; + if (p != *ppos) + return 0; + if (!valid_phys_addr_range(p, count)) return -EFAULT; read = 0; @@ -158,6 +161,9 @@ static ssize_t write_mem(struct file *file, const char __user *buf, unsigned long copied; void *ptr; + if (p != *ppos) + return -EFBIG; + if (!valid_phys_addr_range(p, count)) return -EFAULT; |