blob: e52097a58954675bba3e49d6f3e88270429b0593 [file] [log] [blame]
// Copyright 2016 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef MSD_VSI_CONNECTION_H
#define MSD_VSI_CONNECTION_H
#include <lib/fit/thread_safety.h>
#include <lib/magma/util/short_macros.h>
#include <lib/magma_service/msd.h>
#include <memory>
#include "address_space.h"
#include "mapped_batch.h"
#include "ringbuffer.h"
class MsdVsiConnection {
public:
class Owner {
public:
virtual Ringbuffer* GetRingbuffer() = 0;
// If |do_flush| is true, a flush TLB command will be queued before the batch commands.
virtual magma::Status SubmitBatch(std::unique_ptr<MappedBatch> batch, bool do_flush) = 0;
};
explicit MsdVsiConnection(Owner* owner, std::shared_ptr<AddressSpace> address_space,
msd::msd_client_id_t client_id)
: owner_(owner), address_space_(std::move(address_space)), client_id_(client_id) {}
magma::Status MapBufferGpu(std::shared_ptr<MsdVsiBuffer> buffer, uint64_t gpu_va,
uint64_t page_offset, uint64_t page_count);
Ringbuffer* GetRingbuffer() { return owner_->GetRingbuffer(); }
magma::Status SubmitBatch(std::unique_ptr<MappedBatch> mapped_batch, bool do_flush = false) {
do_flush |= address_space_dirty_;
address_space_dirty_ = false;
return owner_->SubmitBatch(std::move(mapped_batch), do_flush);
}
bool address_space_dirty() { return address_space_dirty_; }
void SetNotificationCallback(msd::NotificationHandler* notification_handler) {
notifications_.Set(notification_handler);
}
void SendContextKilled() { notifications_.SendContextKilled(); }
bool ReleaseMapping(magma::PlatformBuffer* buffer, uint64_t gpu_va);
void ReleaseBuffer(magma::PlatformBuffer* buffer);
// Submit pending release mappings on the given context
bool SubmitPendingReleaseMappings(std::shared_ptr<MsdVsiContext> context);
msd::msd_client_id_t client_id() { return client_id_; }
std::shared_ptr<AddressSpace> address_space() { return address_space_; }
private:
// Saves the released bus mappings to |mappings_to_release_|, to be transferred to the next
// created |MappingReleaseBatch|.
// Sends a ContextKilled notification if a mapping is still in use.
void QueueReleasedMappings(std::vector<std::shared_ptr<GpuMapping>> mappings);
const std::vector<std::unique_ptr<magma::PlatformBusMapper::BusMapping>>& mappings_to_release()
const {
return mappings_to_release_;
}
Owner* owner_;
std::shared_ptr<AddressSpace> address_space_;
msd::msd_client_id_t client_id_;
std::vector<std::unique_ptr<magma::PlatformBusMapper::BusMapping>> mappings_to_release_;
bool address_space_dirty_ = false;
class Notifications {
public:
void SendContextKilled() {
std::lock_guard<std::mutex> lock(mutex_);
if (notification_handler_) {
notification_handler_->ContextKilled();
}
}
void Set(msd::NotificationHandler* notification_handler) {
std::lock_guard<std::mutex> lock(mutex_);
notification_handler_ = notification_handler;
}
private:
FIT_GUARDED(mutex_) msd::NotificationHandler* notification_handler_ {};
std::mutex mutex_;
};
Notifications notifications_;
friend class TestMsdVsiConnection_ReleaseMapping_Test;
friend class TestMsdVsiConnection_ReleaseBuffer_Test;
friend class TestMsdVsiConnection_ReleaseBufferWhileMapped_Test;
};
class MsdVsiAbiConnection : public msd::Connection {
public:
explicit MsdVsiAbiConnection(std::shared_ptr<MsdVsiConnection> ptr)
: ptr_(std::move(ptr)), magic_(kMagic) {}
static MsdVsiAbiConnection* cast(msd::Connection* conn) {
DASSERT(conn);
auto connection = static_cast<MsdVsiAbiConnection*>(conn);
DASSERT(connection->magic_ == kMagic);
return connection;
}
magma_status_t MapBuffer(msd::Buffer& buffer, uint64_t gpu_va, uint64_t offset, uint64_t length,
uint64_t flags) override;
void ReleaseBuffer(msd::Buffer& buffer) override;
magma_status_t UnmapBuffer(msd::Buffer& buffer, uint64_t gpu_va) override;
magma_status_t BufferRangeOp(msd::Buffer& buffer, uint32_t options, uint64_t start_offset,
uint64_t length) override {
return MAGMA_STATUS_INVALID_ARGS;
}
void SetNotificationCallback(msd::NotificationHandler* handler) override;
std::unique_ptr<msd::Context> CreateContext() override;
std::shared_ptr<MsdVsiConnection> ptr() { return ptr_; }
private:
std::shared_ptr<MsdVsiConnection> ptr_;
static const uint32_t kMagic = 0x636f6e6e; // "conn" (Connection)
const uint32_t magic_;
};
#endif // MSD_VSI_CONNECTION_H