qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Anthony Liguori <anthony@codemonkey.ws>
To: Frediano Ziglio <freddy77@gmail.com>
Cc: qemu-devel@nongnu.org
Subject: Re: [Qemu-devel] [PATCH] rewrote timer implementation for rtl8139.
Date: Sat, 20 Feb 2010 11:13:15 -0600	[thread overview]
Message-ID: <4B80182B.6040200@codemonkey.ws> (raw)
In-Reply-To: <1266681995-12315-1-git-send-email-freddy77@gmail.com>

On 02/20/2010 10:06 AM, Frediano Ziglio wrote:
> Add a QEMU timer only when needed (timeout status not set, timeout
> irq wanted and timer set).
>
> This patch is required for Darwin. Patch has been tested under
> FreeBSD, Darwin and Linux.
>    

This is missing a Signed-off-by.

Regards,

Anthony Liguori

> ---
>   hw/rtl8139.c |  139 +++++++++++++++++++++++++++++++++++-----------------------
>   1 files changed, 84 insertions(+), 55 deletions(-)
>
> diff --git a/hw/rtl8139.c b/hw/rtl8139.c
> index f04dd54..72e2242 100644
> --- a/hw/rtl8139.c
> +++ b/hw/rtl8139.c
> @@ -41,6 +41,10 @@
>    *                                  segmentation offloading
>    *                                  Removed slirp.h dependency
>    *                                  Added rx/tx buffer reset when enabling rx/tx operation
> + *
> + *  2010-Feb-04  Frediano Ziglio:   Rewrote timer support using QEMU timer only
> + *                                  when strictly needed (required for for
> + *                                  Darwin)
>    */
>
>   #include "hw.h"
> @@ -60,9 +64,6 @@
>   /* Calculate CRCs properly on Rx packets */
>   #define RTL8139_CALCULATE_RXCRC 1
>
> -/* Uncomment to enable on-board timer interrupts */
> -//#define RTL8139_ONBOARD_TIMER 1
> -
>   #if defined(RTL8139_CALCULATE_RXCRC)
>   /* For crc32 */
>   #include<zlib.h>
> @@ -491,9 +492,12 @@ typedef struct RTL8139State {
>
>       /* PCI interrupt timer */
>       QEMUTimer *timer;
> +    int64_t TimerExpire;
>
>   } RTL8139State;
>
> +static void rtl8139_set_next_tctr_time(RTL8139State *s, int64_t current_time);
> +
>   static void prom9346_decode_command(EEprom9346 *eeprom, uint8_t command)
>   {
>       DEBUG_PRINT(("RTL8139: eeprom command 0x%02x\n", command));
> @@ -2522,7 +2526,9 @@ static void rtl8139_IntrMask_write(RTL8139State *s, uint32_t val)
>
>       s->IntrMask = val;
>
> +    rtl8139_set_next_tctr_time(s, qemu_get_clock(vm_clock));
>       rtl8139_update_irq(s);
> +
>   }
>
>   static uint32_t rtl8139_IntrMask_read(RTL8139State *s)
> @@ -2555,12 +2561,22 @@ static void rtl8139_IntrStatus_write(RTL8139State *s, uint32_t val)
>       rtl8139_update_irq(s);
>
>       s->IntrStatus = newStatus;
> +    /*
> +     * Computing if we miss an interrupt here is not that correct but
> +     * considered that we should have had already an interrupt
> +     * and probably emulated is slower is better to assume this resetting was
> +     * done before testing on previous rtl8139_update_irq lead to IRQ loosing
> +     */
> +    rtl8139_set_next_tctr_time(s, qemu_get_clock(vm_clock));
>       rtl8139_update_irq(s);
> +
>   #endif
>   }
>
>   static uint32_t rtl8139_IntrStatus_read(RTL8139State *s)
>   {
> +    rtl8139_set_next_tctr_time(s, qemu_get_clock(vm_clock));
> +
>       uint32_t ret = s->IntrStatus;
>
>       DEBUG_PRINT(("RTL8139: IntrStatus read(w) val=0x%04x\n", ret));
> @@ -2739,6 +2755,46 @@ static void rtl8139_io_writew(void *opaque, uint8_t addr, uint32_t val)
>       }
>   }
>
> +static void rtl8139_set_next_tctr_time(RTL8139State *s, int64_t current_time)
> +{
> +    int64_t pci_time, next_time;
> +    uint32_t low_pci;
> +
> +    DEBUG_PRINT(("RTL8139: entered rtl8139_set_next_tctr_time\n"));
> +
> +    if (s->TimerExpire&&  current_time>= s->TimerExpire) {
> +        s->IntrStatus |= PCSTimeout;
> +        rtl8139_update_irq(s);
> +    }
> +
> +    /* Set QEMU timer only if needed that is
> +     * - TimerInt<>  0 (we have a timer)
> +     * - mask = 1 (we want an interrupt timer)
> +     * - irq = 0  (irq is not already active)
> +     * If any of above change we need to compute timer again
> +     * Also we must check if timer is passed without QEMU timer
> +     */
> +    s->TimerExpire = 0;
> +    if (!s->TimerInt) {
> +        return;
> +    }
> +
> +    pci_time = muldiv64(current_time - s->TCTR_base, PCI_FREQUENCY,
> +                                get_ticks_per_sec());
> +    low_pci = pci_time&  0xffffffff;
> +    pci_time = pci_time - low_pci + s->TimerInt;
> +    if (low_pci>= s->TimerInt) {
> +        pci_time += 0x100000000LL;
> +    }
> +    next_time = s->TCTR_base + muldiv64(pci_time, get_ticks_per_sec(),
> +                                                PCI_FREQUENCY);
> +    s->TimerExpire = next_time;
> +
> +    if ((s->IntrMask&  PCSTimeout) != 0&&  (s->IntrStatus&  PCSTimeout) == 0) {
> +        qemu_mod_timer(s->timer, next_time);
> +    }
> +}
> +
>   static void rtl8139_io_writel(void *opaque, uint8_t addr, uint32_t val)
>   {
>       RTL8139State *s = opaque;
> @@ -2784,13 +2840,16 @@ static void rtl8139_io_writel(void *opaque, uint8_t addr, uint32_t val)
>
>           case Timer:
>               DEBUG_PRINT(("RTL8139: TCTR Timer reset on write\n"));
> -            s->TCTR = 0;
>               s->TCTR_base = qemu_get_clock(vm_clock);
> +            rtl8139_set_next_tctr_time(s, s->TCTR_base);
>               break;
>
>           case FlashReg:
>               DEBUG_PRINT(("RTL8139: FlashReg TimerInt write val=0x%08x\n", val));
> -            s->TimerInt = val;
> +            if (s->TimerInt != val) {
> +                s->TimerInt = val;
> +                rtl8139_set_next_tctr_time(s, qemu_get_clock(vm_clock));
> +            }
>               break;
>
>           default:
> @@ -3000,7 +3059,8 @@ static uint32_t rtl8139_io_readl(void *opaque, uint8_t addr)
>               break;
>
>           case Timer:
> -            ret = s->TCTR;
> +            ret = muldiv64(qemu_get_clock(vm_clock) - s->TCTR_base,
> +                           PCI_FREQUENCY, get_ticks_per_sec());
>               DEBUG_PRINT(("RTL8139: TCTR Timer read val=0x%08x\n", ret));
>               break;
>
> @@ -3105,6 +3165,7 @@ static uint32_t rtl8139_mmio_readl(void *opaque, target_phys_addr_t addr)
>   static int rtl8139_post_load(void *opaque, int version_id)
>   {
>       RTL8139State* s = opaque;
> +    rtl8139_set_next_tctr_time(s, qemu_get_clock(vm_clock));
>       if (version_id<  4) {
>           s->cplus_enabled = s->CpCmd != 0;
>       }
> @@ -3112,12 +3173,24 @@ static int rtl8139_post_load(void *opaque, int version_id)
>       return 0;
>   }
>
> +static void rtl8139_pre_save(void *opaque)
> +{
> +    RTL8139State* s = opaque;
> +    int64_t current_time = qemu_get_clock(vm_clock);
> +
> +    /* set IntrStatus correctly */
> +    rtl8139_set_next_tctr_time(s, current_time);
> +    s->TCTR = muldiv64(current_time - s->TCTR_base, PCI_FREQUENCY,
> +                       get_ticks_per_sec());
> +}
> +
>   static const VMStateDescription vmstate_rtl8139 = {
>       .name = "rtl8139",
>       .version_id = 4,
>       .minimum_version_id = 3,
>       .minimum_version_id_old = 3,
>       .post_load = rtl8139_post_load,
> +    .pre_save  = rtl8139_pre_save,
>       .fields      = (VMStateField []) {
>           VMSTATE_PCI_DEVICE(dev, RTL8139State),
>           VMSTATE_PARTIAL_BUFFER(phys, RTL8139State, 6),
> @@ -3231,59 +3304,20 @@ static CPUWriteMemoryFunc * const rtl8139_mmio_write[3] = {
>       rtl8139_mmio_writel,
>   };
>
> -static inline int64_t rtl8139_get_next_tctr_time(RTL8139State *s, int64_t current_time)
> -{
> -    int64_t next_time = current_time +
> -        muldiv64(1, get_ticks_per_sec(), PCI_FREQUENCY);
> -    if (next_time<= current_time)
> -        next_time = current_time + 1;
> -    return next_time;
> -}
> -
> -#ifdef RTL8139_ONBOARD_TIMER
>   static void rtl8139_timer(void *opaque)
>   {
>       RTL8139State *s = opaque;
>
> -    int is_timeout = 0;
> -
> -    int64_t  curr_time;
> -    uint32_t curr_tick;
> -
>       if (!s->clock_enabled)
>       {
>           DEBUG_PRINT(("RTL8139:>>>  timer: clock is not running\n"));
>           return;
>       }
>
> -    curr_time = qemu_get_clock(vm_clock);
> -
> -    curr_tick = muldiv64(curr_time - s->TCTR_base, PCI_FREQUENCY,
> -                         get_ticks_per_sec());
> -
> -    if (s->TimerInt&&  curr_tick>= s->TimerInt)
> -    {
> -        if (s->TCTR<  s->TimerInt || curr_tick<  s->TCTR)
> -        {
> -            is_timeout = 1;
> -        }
> -    }
> -
> -    s->TCTR = curr_tick;
> -
> -//  DEBUG_PRINT(("RTL8139:>>>  timer: tick=%08u\n", s->TCTR));
> -
> -    if (is_timeout)
> -    {
> -        DEBUG_PRINT(("RTL8139:>>>  timer: timeout tick=%08u\n", s->TCTR));
> -        s->IntrStatus |= PCSTimeout;
> -        rtl8139_update_irq(s);
> -    }
> -
> -    qemu_mod_timer(s->timer,
> -        rtl8139_get_next_tctr_time(s,curr_time));
> +    s->IntrStatus |= PCSTimeout;
> +    rtl8139_update_irq(s);
> +    rtl8139_set_next_tctr_time(s, qemu_get_clock(vm_clock));
>   }
> -#endif /* RTL8139_ONBOARD_TIMER */
>
>   static void rtl8139_cleanup(VLANClientState *nc)
>   {
> @@ -3301,10 +3335,8 @@ static int pci_rtl8139_uninit(PCIDevice *dev)
>           qemu_free(s->cplus_txbuffer);
>           s->cplus_txbuffer = NULL;
>       }
> -#ifdef RTL8139_ONBOARD_TIMER
>       qemu_del_timer(s->timer);
>       qemu_free_timer(s->timer);
> -#endif
>       qemu_del_vlan_client(&s->nic->nc);
>       return 0;
>   }
> @@ -3356,12 +3388,9 @@ static int pci_rtl8139_init(PCIDevice *dev)
>       s->cplus_txbuffer_len = 0;
>       s->cplus_txbuffer_offset = 0;
>
> -#ifdef RTL8139_ONBOARD_TIMER
> +    s->TimerExpire = 0;
>       s->timer = qemu_new_timer(vm_clock, rtl8139_timer, s);
> -
> -    qemu_mod_timer(s->timer,
> -        rtl8139_get_next_tctr_time(s,qemu_get_clock(vm_clock)));
> -#endif /* RTL8139_ONBOARD_TIMER */
> +    rtl8139_set_next_tctr_time(s, qemu_get_clock(vm_clock));
>       return 0;
>   }
>
>    

  reply	other threads:[~2010-02-20 17:13 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-02-16  8:35 [Qemu-devel] [PATCH] rewrote timer implementation for rtl8139 Frediano Ziglio
2010-02-19 21:50 ` Anthony Liguori
2010-02-19 22:22   ` Alexander Graf
2010-02-19 23:26     ` Anthony Liguori
2010-02-20  5:52       ` Igor Kovalenko
2010-02-20 16:14         ` Frediano Ziglio
2010-02-20 16:06       ` Frediano Ziglio
2010-02-20 17:13         ` Anthony Liguori [this message]
2010-02-20 17:27       ` Frediano Ziglio
2010-02-25 14:24         ` Paul Brook
2010-02-20 17:50       ` Frediano Ziglio
2010-02-19 23:24 ` Anthony Liguori

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4B80182B.6040200@codemonkey.ws \
    --to=anthony@codemonkey.ws \
    --cc=freddy77@gmail.com \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).