mirror of
https://github.com/arehnman/yttrium-virtio-gpu.git
synced 2026-10-31 02:05:04 +00:00
https://issues.redhat.com/browse/RHEL-68725 https://github.com/virtio-win/kvm-guest-drivers-windows/issues/1197 In such case we do not have any other option than request to unload the driver. This can happen in 2 flows: power up (during fast startup) or reset, both with driver verifier that simulates low resources. In reset flow we need to request driver unload explicitly. Power up flow works in SET_POWER, so it will do it automatically. Signed-off-by: Yuri Benditovich <[email protected]>
157 lines
3.5 KiB
C++
157 lines
3.5 KiB
C++
#pragma once
|
|
#include "ParaNdis-VirtQueue.h"
|
|
#include "Parandis_DesignPatterns.h"
|
|
|
|
class CParaNdisAbstractPath
|
|
{
|
|
public:
|
|
#if NDIS_SUPPORT_NDIS620
|
|
CParaNdisAbstractPath()
|
|
{
|
|
memset(&DPCAffinity, 0, sizeof(DPCAffinity));
|
|
}
|
|
#else
|
|
CParaNdisAbstractPath() : DPCTargetProcessor(0) {}
|
|
#endif
|
|
|
|
bool WasInterruptReported()
|
|
{
|
|
return m_interruptReported;
|
|
}
|
|
|
|
void ClearInterruptReport()
|
|
{
|
|
m_interruptReported = false;
|
|
}
|
|
|
|
void ReportInterrupt() {
|
|
m_interruptReported = true;
|
|
}
|
|
|
|
UINT getMessageIndex() {
|
|
return m_messageIndex;
|
|
}
|
|
|
|
UINT getQueueIndex() {
|
|
return m_queueIndex;
|
|
}
|
|
|
|
virtual NDIS_STATUS SetupMessageIndex(u16 vector);
|
|
|
|
/* TODO - Path classes should inherit from CVirtQueue*/
|
|
virtual void DisableInterrupts()
|
|
{
|
|
m_pVirtQueue->DisableInterrupts();
|
|
}
|
|
|
|
void EnableInterrupts()
|
|
{
|
|
m_pVirtQueue->EnableInterrupts();
|
|
}
|
|
|
|
bool Renew()
|
|
{
|
|
m_pVirtQueue->Renew();
|
|
return m_pVirtQueue->IsValid();
|
|
}
|
|
|
|
ULONG getCPUIndex();
|
|
|
|
VOID SetLastInterruptTimestamp(LARGE_INTEGER timestamp)
|
|
{
|
|
m_LastInterruptTimeStamp = timestamp;
|
|
}
|
|
|
|
#if NDIS_SUPPORT_NDIS620
|
|
GROUP_AFFINITY DPCAffinity;
|
|
#else
|
|
KAFFINITY DPCTargetProcessor = 0;
|
|
#endif
|
|
|
|
virtual bool FireDPC(ULONG messageId) = 0;
|
|
|
|
protected:
|
|
PPARANDIS_ADAPTER m_Context;
|
|
CVirtQueue *m_pVirtQueue;
|
|
LARGE_INTEGER m_LastInterruptTimeStamp;
|
|
|
|
u16 m_messageIndex = (u16)-1;
|
|
u16 m_queueIndex = (u16)-1;
|
|
bool m_interruptReported;
|
|
};
|
|
|
|
|
|
template <class VQ> class CParaNdisTemplatePath : public CParaNdisAbstractPath, public CObserver<SMNotifications>{
|
|
public:
|
|
CParaNdisTemplatePath() : m_ObserverAdded(false) {
|
|
m_pVirtQueue = &m_VirtQueue;
|
|
}
|
|
|
|
bool CreatePath()
|
|
{
|
|
m_ObserverAdded = m_Context->m_StateMachine.Add(this) > 0;
|
|
return true;
|
|
}
|
|
|
|
~CParaNdisTemplatePath() {
|
|
if (m_ObserverAdded)
|
|
{
|
|
m_Context->m_StateMachine.Remove(this);
|
|
}
|
|
}
|
|
|
|
void Shutdown()
|
|
{
|
|
TPassiveSpinLocker LockedContext(m_Lock);
|
|
m_VirtQueue.Shutdown();
|
|
}
|
|
|
|
static BOOLEAN _Function_class_(MINIPORT_SYNCHRONIZE_INTERRUPT)
|
|
RestartQueueSynchronously(PVOID ctx)
|
|
{
|
|
auto This = static_cast<CParaNdisTemplatePath<VQ>*>(ctx);
|
|
return !This->m_VirtQueue.Restart();
|
|
}
|
|
|
|
/* We get notified by the state machine on suprise removal or when the
|
|
device needs a reset*/
|
|
void Notify(SMNotifications message) override
|
|
{
|
|
if (message == SMNotifications::SupriseRemoved || message == SMNotifications::NeedsReset)
|
|
{
|
|
m_VirtQueue.DoNotTouchHardware();
|
|
}
|
|
else if (message == SMNotifications::PoweredOn)
|
|
{
|
|
m_VirtQueue.AllowTouchHardware();
|
|
}
|
|
}
|
|
|
|
// this default implementation is for RX/TX queues
|
|
// CX queue shall redefine it
|
|
bool FireDPC(ULONG messageId) override
|
|
{
|
|
#if PARANDIS_SUPPORT_POLL
|
|
if (m_Context->bPollModeEnabled)
|
|
{
|
|
//rx index is 2*n, tx index is 2*n+1
|
|
ParaNdisPollNotify(m_Context, m_queueIndex / 2, (m_queueIndex % 2) ? "TX" : "RX");
|
|
return TRUE;
|
|
}
|
|
#endif
|
|
|
|
#if NDIS_SUPPORT_NDIS620
|
|
if (DPCAffinity.Mask)
|
|
{
|
|
NdisMQueueDpcEx(m_Context->InterruptHandle, messageId, &DPCAffinity, NULL);
|
|
return TRUE;
|
|
}
|
|
#endif
|
|
return FALSE;
|
|
}
|
|
protected:
|
|
CNdisSpinLock m_Lock;
|
|
bool m_ObserverAdded;
|
|
VQ m_VirtQueue;
|
|
};
|