[dwmac] split dwmac into two devices
Bug:73278
Test:vim3 check for panic
device-enumeration-test
Change-Id: I89424effc8462f9faec6b7dcc864da9d156c5c16
Reviewed-on: https://fuchsia-review.googlesource.com/c/fuchsia/+/512776
Fuchsia-Auto-Submit: Ruby Zhuang <rdzhuang@google.com>
Reviewed-by: James Robinson <jamesr@google.com>
Reviewed-by: Alex Legg <alexlegg@google.com>
Reviewed-by: Adrian Danis <adanis@google.com>
Reviewed-by: Suraj Malhotra <surajmalhotra@google.com>
Commit-Queue: Ruby Zhuang <rdzhuang@google.com>
diff --git a/boards/kernel_cmdline/BUILD.gn b/boards/kernel_cmdline/BUILD.gn
index b04867d..9d877d4 100644
--- a/boards/kernel_cmdline/BUILD.gn
+++ b/boards/kernel_cmdline/BUILD.gn
@@ -76,6 +76,6 @@
kernel_cmdline("vim3") {
args = [
# Prefer using the built-in NIC to the CDC-ether interface.
- "netsvc.interface=/dev/dwmac/Designware-MAC/ethernet",
+ "netsvc.interface=/dev/dwmac/dwmac/Designware-MAC/ethernet",
]
}
diff --git a/src/connectivity/ethernet/drivers/dwmac/dwmac.cc b/src/connectivity/ethernet/drivers/dwmac/dwmac.cc
index 34f9465..8bbbf5e 100644
--- a/src/connectivity/ethernet/drivers/dwmac/dwmac.cc
+++ b/src/connectivity/ethernet/drivers/dwmac/dwmac.cc
@@ -92,13 +92,21 @@
int ret = thrd_create_with_name(&thread_, thunk, this, "mac-thread");
ZX_DEBUG_ASSERT(ret == thrd_success);
- zx_status_t status = DdkAdd("Designware-MAC");
+ fbl::AllocChecker ac;
+ std::unique_ptr<EthPhyFunction> phy_function(new (&ac) EthPhyFunction(zxdev(), this));
+ if (!ac.check()) {
+ DdkAsyncRemove();
+ return ZX_ERR_NO_MEMORY;
+ }
+ auto status = phy_function->DdkAdd("Designware-MAC");
if (status != ZX_OK) {
zxlogf(ERROR, "dwmac: Could not create eth device: %d", status);
+ DdkAsyncRemove();
return status;
} else {
zxlogf(INFO, "dwmac: Added dwMac device");
}
+ phy_function_ = phy_function.release();
return status;
}
@@ -207,6 +215,12 @@
sync_completion_reset(&mac_device->cb_registered_signal_);
+ status = mac_device->DdkAdd("dwmac", DEVICE_ADD_NON_BINDABLE);
+ if (status != ZX_OK) {
+ zxlogf(ERROR, "DWMac DdkAdd failed %d", status);
+ return status;
+ }
+
// Populate board specific information
eth_dev_metadata_t phy_info;
size_t actual;
@@ -223,25 +237,20 @@
{BIND_PLATFORM_DEV_DID, 0, phy_info.did},
};
- device_add_args_t phy_device_args = {};
- phy_device_args.version = DEVICE_ADD_ARGS_VERSION;
- phy_device_args.name = "eth_phy";
- phy_device_args.ops = &mac_device->ddk_device_proto_,
- phy_device_args.proto_id = ZX_PROTOCOL_ETH_MAC;
- phy_device_args.props = props;
- phy_device_args.prop_count = countof(props);
- phy_device_args.ctx = mac_device.get();
- phy_device_args.proto_ops = &mac_device->eth_mac_protocol_ops_;
-
+ fbl::AllocChecker ac;
+ std::unique_ptr<EthMacFunction> mac_function(
+ new (&ac) EthMacFunction(mac_device->zxdev(), mac_device.get()));
+ if (!ac.check()) {
+ return ZX_ERR_NO_MEMORY;
+ }
// TODO(braval): use proper device pointer, depending on how
// many PHY devices we have to load, from the metadata.
- zx_device_t* dev;
- status = device_add(device, &phy_device_args, &dev);
+ status = mac_function->DdkAdd(ddk::DeviceAddArgs("eth_phy").set_props(props));
if (status != ZX_OK) {
- zxlogf(ERROR, "dwmac: Could not create phy device: %d", status);
-
+ zxlogf(ERROR, "DdkAdd for Eth Mac Function failed %d", status);
return status;
}
+ mac_device->mac_function_ = mac_function.release();
auto worker_thunk = [](void* arg) -> int {
return reinterpret_cast<DWMacDevice*>(arg)->WorkerThread();
@@ -354,7 +363,9 @@
}
DWMacDevice::DWMacDevice(zx_device_t* device, ddk::PDev pdev, ddk::EthBoardProtocolClient eth_board)
- : ddk::Device<DWMacDevice, ddk::Unbindable>(device), pdev_(pdev), eth_board_(eth_board) {}
+ : ddk::Device<DWMacDevice, ddk::Unbindable, ddk::Suspendable>(device),
+ pdev_(pdev),
+ eth_board_(eth_board) {}
void DWMacDevice::ReleaseBuffers() {
// Unpin the memory used for the dma buffers
@@ -368,6 +379,8 @@
void DWMacDevice::DdkRelease() {
zxlogf(INFO, "Ethernet release...");
+ ZX_ASSERT(phy_function_ == nullptr);
+ ZX_ASSERT(mac_function_ == nullptr);
delete this;
}
@@ -377,6 +390,13 @@
txn.Reply();
}
+void DWMacDevice::DdkSuspend(ddk::SuspendTxn txn) {
+ zxlogf(INFO, "Ethernet DdkSuspend");
+ // We do not distinguish between states, just completely shutdown.
+ ShutDown();
+ txn.Reply(ZX_OK, txn.requested_state());
+}
+
zx_status_t DWMacDevice::ShutDown() {
if (running_.load()) {
running_.store(false);
diff --git a/src/connectivity/ethernet/drivers/dwmac/dwmac.h b/src/connectivity/ethernet/drivers/dwmac/dwmac.h
index e3b530a..385ae82 100644
--- a/src/connectivity/ethernet/drivers/dwmac/dwmac.h
+++ b/src/connectivity/ethernet/drivers/dwmac/dwmac.h
@@ -92,9 +92,10 @@
namespace eth {
-class DWMacDevice : public ddk::Device<DWMacDevice, ddk::Unbindable>,
- public ddk::EthernetImplProtocol<DWMacDevice, ddk::base_protocol>,
- public ddk::EthMacProtocol<DWMacDevice> {
+class EthPhyFunction;
+class EthMacFunction;
+
+class DWMacDevice : public ddk::Device<DWMacDevice, ddk::Unbindable, ddk::Suspendable> {
public:
DWMacDevice(zx_device_t* device, ddk::PDev pdev, ddk::EthBoardProtocolClient eth_board);
@@ -102,6 +103,7 @@
void DdkRelease();
void DdkUnbind(ddk::UnbindTxn txn);
+ void DdkSuspend(ddk::SuspendTxn txn);
// ZX_PROTOCOL_ETHERNET_IMPL ops.
zx_status_t EthernetImplQuery(uint32_t options, ethernet_info_t* info);
@@ -120,6 +122,9 @@
zx_status_t EthMacRegisterCallbacks(const eth_mac_callbacks_t* callbacks);
private:
+ friend class EthMacFunction;
+ friend class EthPhyFunction;
+
zx_status_t InitBuffers();
zx_status_t InitDevice();
zx_status_t DeInitDevice() __TA_REQUIRES(lock_);
@@ -194,6 +199,90 @@
// Callbacks registered signal.
sync_completion_t cb_registered_signal_;
+
+ EthPhyFunction* phy_function_;
+ EthMacFunction* mac_function_;
+};
+
+using EthPhyFunctionType = ddk::Device<EthPhyFunction, ddk::Unbindable, ddk::Suspendable>;
+class EthPhyFunction : public EthPhyFunctionType,
+ public ddk::EthernetImplProtocol<EthPhyFunction, ddk::base_protocol> {
+ public:
+ explicit EthPhyFunction(zx_device_t* device, DWMacDevice* peripheral)
+ : EthPhyFunctionType(device), device_(peripheral) {}
+
+ void DdkUnbind(ddk::UnbindTxn txn) {
+ device_->phy_function_ = nullptr;
+ device_ = nullptr;
+ txn.Reply();
+ }
+ void DdkSuspend(ddk::SuspendTxn txn) {
+ device_->phy_function_ = nullptr;
+ device_ = nullptr;
+ txn.Reply(ZX_OK, txn.requested_state());
+ }
+ void DdkRelease() {
+ ZX_ASSERT(device_ == nullptr);
+ delete this;
+ }
+
+ // ZX_PROTOCOL_ETHERNET_IMPL ops.
+ zx_status_t EthernetImplQuery(uint32_t options, ethernet_info_t* info) {
+ return device_->EthernetImplQuery(options, info);
+ }
+ void EthernetImplStop() { device_->EthernetImplStop(); }
+ zx_status_t EthernetImplStart(const ethernet_ifc_protocol_t* ifc) {
+ return device_->EthernetImplStart(ifc);
+ }
+ void EthernetImplQueueTx(uint32_t options, ethernet_netbuf_t* netbuf,
+ ethernet_impl_queue_tx_callback completion_cb, void* cookie) {
+ device_->EthernetImplQueueTx(options, netbuf, completion_cb, cookie);
+ }
+ zx_status_t EthernetImplSetParam(uint32_t param, int32_t value, const uint8_t* data,
+ size_t data_size) {
+ return device_->EthernetImplSetParam(param, value, data, data_size);
+ }
+ void EthernetImplGetBti(zx::bti* bti) { device_->EthernetImplGetBti(bti); }
+
+ private:
+ DWMacDevice* device_;
+};
+
+using EthMacFunctionType = ddk::Device<EthMacFunction, ddk::Unbindable, ddk::Suspendable>;
+class EthMacFunction : public EthMacFunctionType,
+ public ddk::EthMacProtocol<EthMacFunction, ddk::base_protocol> {
+ public:
+ explicit EthMacFunction(zx_device_t* device, DWMacDevice* peripheral)
+ : EthMacFunctionType(device), device_(peripheral) {}
+
+ void DdkUnbind(ddk::UnbindTxn txn) {
+ device_->mac_function_ = nullptr;
+ device_ = nullptr;
+ txn.Reply();
+ }
+ void DdkSuspend(ddk::SuspendTxn txn) {
+ device_->mac_function_ = nullptr;
+ device_ = nullptr;
+ txn.Reply(ZX_OK, txn.requested_state());
+ }
+ void DdkRelease() {
+ ZX_ASSERT(device_ == nullptr);
+ delete this;
+ }
+
+ // ZX_PROTOCOL_ETH_MAC ops.
+ zx_status_t EthMacMdioWrite(uint32_t reg, uint32_t val) {
+ return device_->EthMacMdioWrite(reg, val);
+ }
+ zx_status_t EthMacMdioRead(uint32_t reg, uint32_t* val) {
+ return device_->EthMacMdioRead(reg, val);
+ }
+ zx_status_t EthMacRegisterCallbacks(const eth_mac_callbacks_t* callbacks) {
+ return device_->EthMacRegisterCallbacks(callbacks);
+ }
+
+ private:
+ DWMacDevice* device_;
};
} // namespace eth
diff --git a/zircon/system/utest/device-enumeration/main.cc b/zircon/system/utest/device-enumeration/main.cc
index 37b73b2..ffcf287 100644
--- a/zircon/system/utest/device-enumeration/main.cc
+++ b/zircon/system/utest/device-enumeration/main.cc
@@ -174,7 +174,7 @@
"aml_emmc/aml-sd-emmc/sdmmc/sdmmc-mmc/user/block/part-006/block",
// "sys/platform/05:00:3/aml-uart/serial/bt-transport-uart/bcm-hci",
"sys/platform/05:00:2/aml-i2c/i2c/i2c-1-81/rtc", "sys/platform/00:00:2/xhci/usb-bus",
- "mali/aml-gpu", "dwmac/eth_phy/phy_null_device", "dwmac/Designware-MAC/ethernet",
+ "mali/aml-gpu", "dwmac/dwmac/eth_phy/phy_null_device", "dwmac/dwmac/Designware-MAC/ethernet",
"display/vim2-display/display-controller", "vim-thermal/vim-thermal", "gpio-light/gpio-light",
"wifi/brcmfmac-wlanphy", "aml-sdio/aml-sd-emmc/sdmmc",
"aml-sdio/aml-sd-emmc/sdmmc/sdmmc-sdio", "aml-sdio/aml-sd-emmc/sdmmc/sdmmc-sdio/sdmmc-sdio-1",
@@ -194,8 +194,8 @@
"sys/platform/05:00:14/clocks",
"sys/platform/05:00:2/aml-i2c",
"sys/platform/05:00:2/aml-i2c/i2c/i2c-0-81/rtc",
- "dwmac/eth_phy/phy_null_device",
- "dwmac/Designware-MAC/ethernet",
+ "dwmac/dwmac/eth_phy/phy_null_device",
+ "dwmac/dwmac/Designware-MAC/ethernet",
"aml_sd/aml-sd-emmc",
"aml_sdio/aml-sd-emmc/sdmmc/sdmmc-sdio/sdmmc-sdio-1",
"aml_sdio/aml-sd-emmc/sdmmc/sdmmc-sdio/sdmmc-sdio-2",
@@ -311,9 +311,15 @@
TEST_F(DeviceEnumerationTest, NelsonTest) {
static const char* kDevicePaths[] = {
- "sys/platform/nelson", "sys/platform/05:03:1/aml-axg-gpio", "nelson-buttons/hid-buttons",
- "class/bt-transport/000", "class/bt-hci/000", "sys/platform/05:00:2/aml-i2c", "mali/aml-gpu",
- "sys/platform/05:0a:21/nelson-usb-phy", "nelson-audio-i2s-out",
+ "sys/platform/nelson",
+ "sys/platform/05:03:1/aml-axg-gpio",
+ "nelson-buttons/hid-buttons",
+ "class/bt-transport/000",
+ "class/bt-hci/000",
+ "sys/platform/05:00:2/aml-i2c",
+ "mali/aml-gpu",
+ "sys/platform/05:0a:21/nelson-usb-phy",
+ "nelson-audio-i2s-out",
"sys/platform/05:05:13/nelson-audio-pdm-in",
"sys/platform/00:00:29", // registers device
@@ -324,8 +330,11 @@
// so we can't just test that one of them is bound. That is why the
// following test is disabled.
// "sys/platform/03:03:5/gt92xx HidDevice/hid-device-000",
- "backlight/ti-lp8556", "sys/platform/05:00:10/aml-canvas", "tee/optee",
- "sys/platform/00:00:f/fallback-rtc", "nelson-emmc/aml-sd-emmc/sdmmc/sdmmc-mmc/boot1/block",
+ "backlight/ti-lp8556",
+ "sys/platform/05:00:10/aml-canvas",
+ "tee/optee",
+ "sys/platform/00:00:f/fallback-rtc",
+ "nelson-emmc/aml-sd-emmc/sdmmc/sdmmc-mmc/boot1/block",
"nelson-emmc/aml-sd-emmc/sdmmc/sdmmc-mmc/boot2/block",
"nelson-emmc/aml-sd-emmc/sdmmc/sdmmc-mmc/rpmb",
"nelson-emmc/aml-sd-emmc/sdmmc/sdmmc-mmc/user/block/part-000/block",
@@ -346,20 +355,38 @@
"nelson-emmc/aml-sd-emmc/sdmmc/sdmmc-mmc/user/block/part-015/block",
"nelson-emmc/aml-sd-emmc/sdmmc/sdmmc-mmc/user/block/part-016/block",
"nelson-emmc/aml-sd-emmc/sdmmc/sdmmc-mmc/user/block/part-017/block",
- "tcs3400-light/tcs-3400/hid-device-000", "aml-nna", "sys/platform/05:05:22/clocks",
- "aml-thermal-pll/thermal", "class/thermal/000",
+ "tcs3400-light/tcs-3400/hid-device-000",
+ "aml-nna",
+ "sys/platform/05:05:22/clocks",
+ "aml-thermal-pll/thermal",
+ "class/thermal/000",
// "sys/platform/05:03:1e/cpu",
- "aml-secure-mem/aml-securemem", "class/pwm/000", "class/pwm/001", "class/pwm/002",
- "class/pwm/003", "class/pwm/004", "class/pwm/005", "class/pwm/006", "class/pwm/007",
- "class/pwm/008", "class/pwm/009", "aml-sdio/aml-sd-emmc/sdmmc",
- "aml-sdio/aml-sd-emmc/sdmmc/sdmmc-sdio", "aml-sdio/aml-sd-emmc/sdmmc/sdmmc-sdio/sdmmc-sdio-1",
- "aml-sdio/aml-sd-emmc/sdmmc/sdmmc-sdio/sdmmc-sdio-2", "sys/platform/00:00:1e/dw-dsi",
- "display/amlogic-display/display-controller", "class/dsi-base/000", "ti-ina231-mlb/ti-ina231",
- "ti-ina231-speakers/ti-ina231", "sys/platform/05:00:2/aml-i2c/i2c/i2c-0-112/shtv3",
+ "aml-secure-mem/aml-securemem",
+ "class/pwm/000",
+ "class/pwm/001",
+ "class/pwm/002",
+ "class/pwm/003",
+ "class/pwm/004",
+ "class/pwm/005",
+ "class/pwm/006",
+ "class/pwm/007",
+ "class/pwm/008",
+ "class/pwm/009",
+ "aml-sdio/aml-sd-emmc/sdmmc",
+ "aml-sdio/aml-sd-emmc/sdmmc/sdmmc-sdio",
+ "aml-sdio/aml-sd-emmc/sdmmc/sdmmc-sdio/sdmmc-sdio-1",
+ "aml-sdio/aml-sd-emmc/sdmmc/sdmmc-sdio/sdmmc-sdio-2",
+ "sys/platform/00:00:1e/dw-dsi",
+ "display/amlogic-display/display-controller",
+ "class/dsi-base/000",
+ "ti-ina231-mlb/ti-ina231",
+ "ti-ina231-speakers/ti-ina231",
+ "sys/platform/05:00:2/aml-i2c/i2c/i2c-0-112/shtv3",
"gt6853-touch/gt6853",
// Amber LED.
- "gpio-light", "class/light/000",
+ "gpio-light",
+ "class/light/000",
"spi/aml-spi-1/spi/spi-1-0",
"selina/selina",