* [PATCH net-next v2 2/7] net: ethernet: mediatek: add mtk_hw_deinit call as the opposite to mtk_hw_init call
From: sean.wang @ 2016-09-14 15:13 UTC (permalink / raw)
To: john, davem; +Cc: nbd, netdev, linux-mediatek, keyhaede, objelf, Sean Wang
In-Reply-To: <1473866001-9805-1-git-send-email-sean.wang@mediatek.com>
From: Sean Wang <sean.wang@mediatek.com>
grouping things related to the deinitialization of what
mtk_hw_init call does that help to be reused by the reset
process and the error path handling.
Signed-off-by: Sean Wang <sean.wang@mediatek.com>
---
drivers/net/ethernet/mediatek/mtk_eth_soc.c | 15 +++++++++++----
1 file changed, 11 insertions(+), 4 deletions(-)
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index ca46e82..c71b0b3 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -1477,6 +1477,16 @@ static int __init mtk_hw_init(struct mtk_eth *eth)
return 0;
}
+static int mtk_hw_deinit(struct mtk_eth *eth)
+{
+ clk_disable_unprepare(eth->clks[MTK_CLK_GP2]);
+ clk_disable_unprepare(eth->clks[MTK_CLK_GP1]);
+ clk_disable_unprepare(eth->clks[MTK_CLK_ESW]);
+ clk_disable_unprepare(eth->clks[MTK_CLK_ETHIF]);
+
+ return 0;
+}
+
static int __init mtk_init(struct net_device *dev)
{
struct mtk_mac *mac = netdev_priv(dev);
@@ -1923,10 +1933,7 @@ static int mtk_remove(struct platform_device *pdev)
mtk_stop(eth->netdev[i]);
}
- clk_disable_unprepare(eth->clks[MTK_CLK_ETHIF]);
- clk_disable_unprepare(eth->clks[MTK_CLK_ESW]);
- clk_disable_unprepare(eth->clks[MTK_CLK_GP1]);
- clk_disable_unprepare(eth->clks[MTK_CLK_GP2]);
+ mtk_hw_deinit(eth);
netif_napi_del(ð->tx_napi);
netif_napi_del(ð->rx_napi);
--
1.9.1
^ permalink raw reply related
* [PATCH net-next v2 1/7] net: ethernet: mediatek: refactoring mtk_hw_init to be reused
From: sean.wang @ 2016-09-14 15:13 UTC (permalink / raw)
To: john, davem; +Cc: nbd, netdev, linux-mediatek, keyhaede, objelf, Sean Wang
In-Reply-To: <1473866001-9805-1-git-send-email-sean.wang@mediatek.com>
From: Sean Wang <sean.wang@mediatek.com>
the existing mtk_hw_init includes hardware and software
initialization inside so that it is slightly hard to reuse
them for the process of the reset recovery, so some splitting
is made here for keeping hardware initializing relevant thing
and the else such as IRQ registration and MDIO initialization
what are all about to the interface of core driver moved to the
other proper place because they have no needs to register IRQ and
re-initialize structure again during the reset process.
Signed-off-by: Sean Wang <sean.wang@mediatek.com>
---
drivers/net/ethernet/mediatek/mtk_eth_soc.c | 62 ++++++++++++++++-------------
1 file changed, 34 insertions(+), 28 deletions(-)
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index 66fd45a..ca46e82 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -1415,7 +1415,12 @@ static int mtk_stop(struct net_device *dev)
static int __init mtk_hw_init(struct mtk_eth *eth)
{
- int err, i;
+ int i;
+
+ clk_prepare_enable(eth->clks[MTK_CLK_ETHIF]);
+ clk_prepare_enable(eth->clks[MTK_CLK_ESW]);
+ clk_prepare_enable(eth->clks[MTK_CLK_GP1]);
+ clk_prepare_enable(eth->clks[MTK_CLK_GP2]);
/* reset the frame engine */
reset_control_assert(eth->rstc);
@@ -1441,19 +1446,6 @@ static int __init mtk_hw_init(struct mtk_eth *eth)
/* Enable RX VLan Offloading */
mtk_w32(eth, 1, MTK_CDMP_EG_CTRL);
- err = devm_request_irq(eth->dev, eth->irq[1], mtk_handle_irq_tx, 0,
- dev_name(eth->dev), eth);
- if (err)
- return err;
- err = devm_request_irq(eth->dev, eth->irq[2], mtk_handle_irq_rx, 0,
- dev_name(eth->dev), eth);
- if (err)
- return err;
-
- err = mtk_mdio_init(eth);
- if (err)
- return err;
-
/* disable delay and normal interrupt */
mtk_w32(eth, 0, MTK_QDMA_DELAY_INT);
mtk_w32(eth, 0, MTK_PDMA_DELAY_INT);
@@ -1783,16 +1775,7 @@ static int mtk_add_mac(struct mtk_eth *eth, struct device_node *np)
eth->netdev[id]->features |= MTK_HW_FEATURES;
eth->netdev[id]->ethtool_ops = &mtk_ethtool_ops;
- err = register_netdev(eth->netdev[id]);
- if (err) {
- dev_err(eth->dev, "error bringing up device\n");
- goto free_netdev;
- }
eth->netdev[id]->irq = eth->irq[0];
- netif_info(eth, probe, eth->netdev[id],
- "mediatek frame engine at 0x%08lx, irq %d\n",
- eth->netdev[id]->base_addr, eth->irq[0]);
-
return 0;
free_netdev:
@@ -1862,11 +1845,6 @@ static int mtk_probe(struct platform_device *pdev)
}
}
- clk_prepare_enable(eth->clks[MTK_CLK_ETHIF]);
- clk_prepare_enable(eth->clks[MTK_CLK_ESW]);
- clk_prepare_enable(eth->clks[MTK_CLK_GP1]);
- clk_prepare_enable(eth->clks[MTK_CLK_GP2]);
-
eth->msg_enable = netif_msg_init(mtk_msg_level, MTK_DEFAULT_MSG_ENABLE);
INIT_WORK(ð->pending_work, mtk_pending_work);
@@ -1887,6 +1865,34 @@ static int mtk_probe(struct platform_device *pdev)
goto err_free_dev;
}
+ err = devm_request_irq(eth->dev, eth->irq[1], mtk_handle_irq_tx, 0,
+ dev_name(eth->dev), eth);
+ if (err)
+ goto err_free_dev;
+
+ err = devm_request_irq(eth->dev, eth->irq[2], mtk_handle_irq_rx, 0,
+ dev_name(eth->dev), eth);
+ if (err)
+ goto err_free_dev;
+
+ err = mtk_mdio_init(eth);
+ if (err)
+ goto err_free_dev;
+
+ for (i = 0; i < MTK_MAX_DEVS; i++) {
+ if (!eth->netdev[i])
+ continue;
+
+ err = register_netdev(eth->netdev[i]);
+ if (err) {
+ dev_err(eth->dev, "error bringing up device\n");
+ goto err_free_dev;
+ } else
+ netif_info(eth, probe, eth->netdev[i],
+ "mediatek frame engine at 0x%08lx, irq %d\n",
+ eth->netdev[i]->base_addr, eth->irq[0]);
+ }
+
/* we run 2 devices on the same DMA ring so we need a dummy device
* for NAPI to work
*/
--
1.9.1
^ permalink raw reply related
* [PATCH net-next v2 0/7] add enhancement into the existing reset flow
From: sean.wang @ 2016-09-14 15:13 UTC (permalink / raw)
To: john, davem; +Cc: nbd, netdev, linux-mediatek, keyhaede, objelf, Sean Wang
From: Sean Wang <sean.wang@mediatek.com>
Current driver only resets DMA used by descriptor rings which
can't guarantee it can recover all various kinds of fatal
errors, so the patch
1) tries to reset the underlying hardware resource from scratch on
Mediatek SoC required for ethernet running.
2) refactors code in order to the reusability of existing code.
3) considers handling for race condition between the reset flow and
callbacks registered into core driver called about hardware accessing.
4) introduces power domain usage to hardware setup which leads to have
cleanly and completely restore to the state as the initial.
Changes since v1:
- fix the build error with module built causing undefined symbol for
pinctrl_bind_pins, so using pinctrl_select_state instead accomplishes
the pin mux setup during the reset process.
Sean Wang (7):
net: ethernet: mediatek: refactoring mtk_hw_init to be reused
net: ethernet: mediatek: add mtk_hw_deinit call as the opposite to
mtk_hw_init call
net: ethernet: mediatek: cleanup error path inside mtk_hw_init
net: ethernet: mediatek: add controlling power domain the ethernet
belongs to
net: ethernet: mediatek: add the whole ethernet reset into the reset
process
net: ethernet: mediatek: add more resets for internal ethernet circuit
block
net: ethernet: mediatek: avoid race condition during the reset process
drivers/net/ethernet/mediatek/mtk_eth_soc.c | 226 +++++++++++++++++++++-------
drivers/net/ethernet/mediatek/mtk_eth_soc.h | 15 +-
2 files changed, 186 insertions(+), 55 deletions(-)
--
1.9.1
^ permalink raw reply
* [PATCH net] net: ethernet: mediatek: fix module loading automatically based on MODULE_DEVICE_TABLE
From: sean.wang @ 2016-09-14 13:29 UTC (permalink / raw)
To: john, davem; +Cc: nbd, netdev, linux-mediatek, keyhaede, objelf, Sean Wang
From: Sean Wang <sean.wang@mediatek.com>
The device table is required to load modules based on
modaliases. After adding MODULE_DEVICE_TABLE, below entries
for example will be added to modules.alias:
alias of:N*T*Cmediatek,mt7623-ethC* mtk_eth_soc
Signed-off-by: Sean Wang <sean.wang@mediatek.com>
---
drivers/net/ethernet/mediatek/mtk_eth_soc.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index a6a9a2f..b44ff3c 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -2053,6 +2053,7 @@ const struct of_device_id of_mtk_match[] = {
{ .compatible = "mediatek,mt7623-eth" },
{},
};
+MODULE_DEVICE_TABLE(of, of_mtk_match);
static struct platform_driver mtk_driver = {
.probe = mtk_probe,
--
1.9.1
^ permalink raw reply related
* Re: [PATCH v6 0/6] Add MT8173 MDP Driver
From: Hans Verkuil @ 2016-09-14 12:43 UTC (permalink / raw)
To: Minghsiu Tsai, Hans Verkuil, daniel.thompson, Rob Herring,
Mauro Carvalho Chehab, Matthias Brugger, Daniel Kurtz,
Pawel Osciak
Cc: srv_heupstream, Eddie Huang, Yingjoe Chen, devicetree,
linux-kernel, linux-arm-kernel, linux-media, linux-mediatek
In-Reply-To: <1473340146-6598-1-git-send-email-minghsiu.tsai@mediatek.com>
Hi Minghsiu,
v6 looks good, but I get these warnings when compiling it for i686:
linux-git-i686: WARNINGS
/home/hans/work/build/media-git/drivers/media/platform/mtk-mdp/mtk_mdp_vpu.c: In function 'mtk_mdp_vpu_handle_init_ack':
/home/hans/work/build/media-git/drivers/media/platform/mtk-mdp/mtk_mdp_vpu.c:28:28: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
struct mtk_mdp_vpu *vpu = (struct mtk_mdp_vpu *)msg->ap_inst;
^
/home/hans/work/build/media-git/drivers/media/platform/mtk-mdp/mtk_mdp_vpu.c: In function 'mtk_mdp_vpu_ipi_handler':
/home/hans/work/build/media-git/drivers/media/platform/mtk-mdp/mtk_mdp_vpu.c:40:28: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
struct mtk_mdp_vpu *vpu = (struct mtk_mdp_vpu *)msg->ap_inst;
^
/home/hans/work/build/media-git/drivers/media/platform/mtk-mdp/mtk_mdp_vpu.c: In function 'mtk_mdp_vpu_send_ap_ipi':
/home/hans/work/build/media-git/drivers/media/platform/mtk-mdp/mtk_mdp_vpu.c:111:16: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
msg.ap_inst = (uint64_t)vpu;
^
/home/hans/work/build/media-git/drivers/media/platform/mtk-mdp/mtk_mdp_vpu.c: In function 'mtk_mdp_vpu_init':
/home/hans/work/build/media-git/drivers/media/platform/mtk-mdp/mtk_mdp_vpu.c:129:16: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
msg.ap_inst = (uint64_t)vpu;
^
This is not blocking, but if you can post a follow-up patch for this, then that
would be helpful.
Regards,
Hans
On 09/08/2016 03:09 PM, Minghsiu Tsai wrote:
> Changes in v6:
> - s_selection() can't set the _DEFAULT and _BOUNDS targets
> - Add Maintainers entry
>
> Changes in v5:
> - Add ack in the comment of dts patch
> - Fix s/g_selection()
> - Separate format V4L2_PIX_FMT_MT21C into new patch
>
> Changes in v4:
> - Add "depends on HAS_DMA" in Kconfig.
> - Fix s/g_selection()
> - Replace struct v4l2_crop with u32 and struct v4l2_rect
> - Remove VB2_USERPTR
> - Move mutex lock after ctx allocation in mtk_mdp_m2m_open()
> - Add new format V4L2_PIX_FMT_YVU420 to support software on Android platform.
> - Only width/height of image in format V4L2_PIX_FMT_MT21 is aligned to 16/16,
> other ones are aligned to 2/2 by default
>
> Changes in v3:
> - Modify device ndoe as structured one.
> - Fix conflict in dts on Linux 4.8-rc1
>
> Changes in v2:
> - Add section to describe blocks function in dts-bindings
> - Remove the assignment of device_caps in querycap()
> - Remove format's name assignment
> - Copy colorspace-related parameters from OUTPUT to CAPTURE
> - Use m2m helper functions
> - Fix DMA allocation failure
> - Initialize lazily vpu instance in streamon()
>
> ==============
> Introduction
> ==============
>
> The purpose of this series is to add the driver for Media Data Path HW embedded in the Mediatek's MT8173 SoC.
> MDP is used for scaling and color space conversion.
>
> It could convert V4L2_PIX_FMT_MT21 to V4L2_PIX_FMT_NV12M or V4L2_PIX_FMT_YUV420M.
>
> NV12M/YUV420M/MT21 -> MDP -> NV12M/YUV420M
>
> This patch series rely on MTK VPU driver in patch series "Add MT8173 Video Encoder Driver and VPU Driver"[1] and "Add MT8173 Video Decoder Driver"[2].
> MDP driver rely on VPU driver to load, communicate with VPU.
>
> Internally the driver uses videobuf2 framework and MTK IOMMU and MTK SMI both have been merged in v4.6-rc1.
>
> [1]https://patchwork.kernel.org/patch/9002171/
> [2]https://patchwork.kernel.org/patch/9141245/
>
> ==================
> Device interface
> ==================
>
> In principle the driver bases on v4l2 memory-to-memory framework:
> it provides a single video node and each opened file handle gets its own private context with separate buffer queues. Each context consist of 2 buffer queues: OUTPUT (for source buffers) and CAPTURE (for destination buffers).
> OUTPUT and CAPTURE buffer could be MMAP or DMABUF memory type.
>
> v4l2-compliance test output:
> v4l2-compliance SHA : abc1453dfe89f244dccd3460d8e1a2e3091cbadb
>
> Driver Info:
> Driver name : mtk-mdp
> Card type : soc:mdp
> Bus info : platform:mt8173
> Driver version: 4.8.0
> Capabilities : 0x84204000
> Video Memory-to-Memory Multiplanar
> Streaming
> Extended Pix Format
> Device Capabilities
> Device Caps : 0x04204000
> Video Memory-to-Memory Multiplanar
> Streaming
> Extended Pix Format
>
> Compliance test for device /dev/image-proc0 (not using libv4l2):
>
> Required ioctls:
> test VIDIOC_QUERYCAP: OK
>
> Allow for multiple opens:
> test second video open: OK
> test VIDIOC_QUERYCAP: OK
> test VIDIOC_G/S_PRIORITY: OK
> test for unlimited opens: OK
>
> Debug ioctls:
> test VIDIOC_DBG_G/S_REGISTER: OK (Not Supported)
> test VIDIOC_LOG_STATUS: OK (Not Supported)
>
> Input ioctls:
> test VIDIOC_G/S_TUNER/ENUM_FREQ_BANDS: OK (Not Supported)
> test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
> test VIDIOC_S_HW_FREQ_SEEK: OK (Not Supported)
> test VIDIOC_ENUMAUDIO: OK (Not Supported)
> test VIDIOC_G/S/ENUMINPUT: OK (Not Supported)
> test VIDIOC_G/S_AUDIO: OK (Not Supported)
> Inputs: 0 Audio Inputs: 0 Tuners: 0
>
> Output ioctls:
> test VIDIOC_G/S_MODULATOR: OK (Not Supported)
> test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
> test VIDIOC_ENUMAUDOUT: OK (Not Supported)
> test VIDIOC_G/S/ENUMOUTPUT: OK (Not Supported)
> test VIDIOC_G/S_AUDOUT: OK (Not Supported)
> Outputs: 0 Audio Outputs: 0 Modulators: 0
>
> Input/Output configuration ioctls:
> test VIDIOC_ENUM/G/S/QUERY_STD: OK (Not Supported)
> test VIDIOC_ENUM/G/S/QUERY_DV_TIMINGS: OK (Not Supported)
> test VIDIOC_DV_TIMINGS_CAP: OK (Not Supported)
> test VIDIOC_G/S_EDID: OK (Not Supported)
>
> Control ioctls:
> test VIDIOC_QUERY_EXT_CTRL/QUERYMENU: OK
> test VIDIOC_QUERYCTRL: OK
> test VIDIOC_G/S_CTRL: OK
> test VIDIOC_G/S/TRY_EXT_CTRLS: OK
> test VIDIOC_(UN)SUBSCRIBE_EVENT/DQEVENT: OK
> test VIDIOC_G/S_JPEGCOMP: OK (Not Supported)
> Standard Controls: 5 Private Controls: 0
>
> Format ioctls:
> test VIDIOC_ENUM_FMT/FRAMESIZES/FRAMEINTERVALS: OK
> test VIDIOC_G/S_PARM: OK (Not Supported)
> test VIDIOC_G_FBUF: OK (Not Supported)
> test VIDIOC_G_FMT: OK
> test VIDIOC_TRY_FMT: OK
> test VIDIOC_S_FMT: OK
> test VIDIOC_G_SLICED_VBI_CAP: OK (Not Supported)
> test Cropping: OK
> test Composing: OK
> test Scaling: OK
>
> Codec ioctls:
> test VIDIOC_(TRY_)ENCODER_CMD: OK (Not Supported)
> test VIDIOC_G_ENC_INDEX: OK (Not Supported)
> test VIDIOC_(TRY_)DECODER_CMD: OK (Not Supported)
>
> Buffer ioctls:
> test VIDIOC_REQBUFS/CREATE_BUFS/QUERYBUF: OK
> test VIDIOC_EXPBUF: OK
>
> Test input 0:
>
>
> Total: 43, Succeeded: 43, Failed: 0, Warnings: 0
>
> Minghsiu Tsai (6):
> VPU: mediatek: Add mdp support
> dt-bindings: Add a binding for Mediatek MDP
> media: Add Mediatek MDP Driver
> arm64: dts: mediatek: Add MDP for MT8173
> media: mtk-mdp: support pixelformat V4L2_PIX_FMT_MT21C
> media: mtk-mdp: add Maintainers entry for Mediatek MDP driver
>
> .../devicetree/bindings/media/mediatek-mdp.txt | 109 ++
> MAINTAINERS | 9 +
> arch/arm64/boot/dts/mediatek/mt8173.dtsi | 84 ++
> drivers/media/platform/Kconfig | 17 +
> drivers/media/platform/Makefile | 2 +
> drivers/media/platform/mtk-mdp/Makefile | 9 +
> drivers/media/platform/mtk-mdp/mtk_mdp_comp.c | 159 +++
> drivers/media/platform/mtk-mdp/mtk_mdp_comp.h | 72 ++
> drivers/media/platform/mtk-mdp/mtk_mdp_core.c | 294 +++++
> drivers/media/platform/mtk-mdp/mtk_mdp_core.h | 260 ++++
> drivers/media/platform/mtk-mdp/mtk_mdp_ipi.h | 126 ++
> drivers/media/platform/mtk-mdp/mtk_mdp_m2m.c | 1278 ++++++++++++++++++++
> drivers/media/platform/mtk-mdp/mtk_mdp_m2m.h | 22 +
> drivers/media/platform/mtk-mdp/mtk_mdp_regs.c | 156 +++
> drivers/media/platform/mtk-mdp/mtk_mdp_regs.h | 31 +
> drivers/media/platform/mtk-mdp/mtk_mdp_vpu.c | 145 +++
> drivers/media/platform/mtk-mdp/mtk_mdp_vpu.h | 41 +
> drivers/media/platform/mtk-vpu/mtk_vpu.h | 5 +
> 18 files changed, 2819 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/media/mediatek-mdp.txt
> create mode 100644 drivers/media/platform/mtk-mdp/Makefile
> create mode 100644 drivers/media/platform/mtk-mdp/mtk_mdp_comp.c
> create mode 100644 drivers/media/platform/mtk-mdp/mtk_mdp_comp.h
> create mode 100644 drivers/media/platform/mtk-mdp/mtk_mdp_core.c
> create mode 100644 drivers/media/platform/mtk-mdp/mtk_mdp_core.h
> create mode 100644 drivers/media/platform/mtk-mdp/mtk_mdp_ipi.h
> create mode 100644 drivers/media/platform/mtk-mdp/mtk_mdp_m2m.c
> create mode 100644 drivers/media/platform/mtk-mdp/mtk_mdp_m2m.h
> create mode 100644 drivers/media/platform/mtk-mdp/mtk_mdp_regs.c
> create mode 100644 drivers/media/platform/mtk-mdp/mtk_mdp_regs.h
> create mode 100644 drivers/media/platform/mtk-mdp/mtk_mdp_vpu.c
> create mode 100644 drivers/media/platform/mtk-mdp/mtk_mdp_vpu.h
>
^ permalink raw reply
* Re: [PATCH v2 2/4] docs-rst: Add compressed video formats used on MT8173 codec driver
From: Hans Verkuil @ 2016-09-14 11:51 UTC (permalink / raw)
To: Tiffany Lin, Hans Verkuil, Laurent Pinchart,
Mauro Carvalho Chehab, Matthias Brugger, Daniel Kurtz,
Pawel Osciak
Cc: Eddie Huang, Yingjoe Chen, linux-kernel, linux-media,
linux-mediatek
In-Reply-To: <1473436087-21943-3-git-send-email-tiffany.lin@mediatek.com>
Hi Tiffany,
On 09/09/2016 05:48 PM, Tiffany Lin wrote:
> Add V4L2_PIX_FMT_MT21C documentation
>
> Signed-off-by: Tiffany Lin <tiffany.lin@mediatek.com>
> ---
> Documentation/media/uapi/v4l/pixfmt-reserved.rst | 10 ++++++++++
> 1 file changed, 10 insertions(+)
>
> diff --git a/Documentation/media/uapi/v4l/pixfmt-reserved.rst b/Documentation/media/uapi/v4l/pixfmt-reserved.rst
> index 0dd2f7f..0989e99 100644
> --- a/Documentation/media/uapi/v4l/pixfmt-reserved.rst
> +++ b/Documentation/media/uapi/v4l/pixfmt-reserved.rst
> @@ -339,7 +339,17 @@ please make a proposal on the linux-media mailing list.
> array. Anything what's in between the UYVY lines is JPEG data and
> should be concatenated to form the JPEG stream.
>
> + - .. _V4L2-PIX-FMT-MT21C:
>
> + - ``V4L2_PIX_FMT_MT21C``
> +
> + - 'MT21C'
> +
> + - Compressed two-planar YVU420 format used by Mediatek MT8173.
> + The compression is lossless.
> + It is an opaque intermediate format, and MDP HW could convert
Is it OK if I change this to:
" and the MDP hardware must be used to convert"
> + V4L2_PIX_FMT_MT21C to V4L2_PIX_FMT_NV12M,
> + V4L2_PIX_FMT_YUV420M and V4L2_PIX_FMT_YVU420.
and here "and" should be replaced by "or".
Regards,
Hans
>
> .. tabularcolumns:: |p{6.6cm}|p{2.2cm}|p{8.7cm}|
>
>
^ permalink raw reply
* Re: [PATCH v7 7/9] drm/mediatek: add dsi transfer function
From: CK Hu @ 2016-09-14 7:34 UTC (permalink / raw)
To: YT Shen
Cc: Daniel Vetter, Jie Qiu, Mao Huang, yingjoe.chen, Dan Carpenter,
Jitao Shi, Sascha Hauer, linux-mediatek, dri-devel,
Matthias Brugger, shaoming chen, linux-arm-kernel, srv_heupstream,
emil.l.velikov, linux-kernel, Maxime Ripard
In-Reply-To: <1473837742.24354.28.camel@mtksdaap41>
Hi, YT:
On Wed, 2016-09-14 at 15:22 +0800, YT Shen wrote:
> Hi CK,
>
> On Wed, 2016-09-14 at 14:39 +0800, CK Hu wrote:
> > Hi, YT:
> >
> > On Wed, 2016-09-14 at 14:19 +0800, YT Shen wrote:
> > > Hi CK,
> > >
> > > On Tue, 2016-09-13 at 17:25 +0800, CK Hu wrote:
> > > > Hi, YT:
> > > >
> > > > On Mon, 2016-09-12 at 18:16 +0800, YT Shen wrote:
> > > > > Hi CK,
> > > > >
> > > > > On Wed, 2016-09-07 at 10:33 +0800, CK Hu wrote:
> > > > > > Hi, YT:
> > > > > >
> > > > > > On Fri, 2016-09-02 at 19:24 +0800, YT Shen wrote:
> > > > > > > From: shaoming chen <shaoming.chen@mediatek.com>
> > > > > > >
> > > > > > > add dsi read/write commands for transfer function
> > > > > > >
> > > > > > > Signed-off-by: shaoming chen <shaoming.chen@mediatek.com>
> > > > > > > ---
> > > > > > > drivers/gpu/drm/mediatek/mtk_dsi.c | 188 +++++++++++++++++++++++++++++++++++++
> > > > > > > 1 file changed, 188 insertions(+)
> > > > > > >
> > > > > >
> > > > > > [snip...]
> > > > > >
> > > > > > >
> > > > > > > +static void mtk_dsi_irq_data_clear(struct mtk_dsi *dsi, u32 irq_bit)
> > > > > > > +{
> > > > > > > + dsi->irq_data &= ~irq_bit;
> > > > > > > +}
> > > > > > > +
> > > > > >
> > > > > > [snip...]
> > > > > >
> > > > > > > +
> > > > > > > +static s32 mtk_dsi_wait_for_irq_done(struct mtk_dsi *dsi, u32 irq_flag,
> > > > > > > + unsigned int timeout)
> > > > > > > +{
> > > > > > > + s32 ret = 0;
> > > > > > > + unsigned long jiffies = msecs_to_jiffies(timeout);
> > > > > > > +
> > > > > > > + ret = wait_event_interruptible_timeout(_dsi_irq_wait_queue,
> > > > > > > + dsi->irq_data & irq_flag,
> > > > > > > + jiffies);
> > > > > > > + if (ret == 0) {
> > > > > > > + dev_info(dsi->dev, "Wait DSI IRQ(0x%08x) Timeout\n", irq_flag);
> > > > > > > +
> > > > > > > + mtk_dsi_enable(dsi);
> > > > > > > + mtk_dsi_reset_engine(dsi);
> > > > > > > + }
> > > > > > > +
> > > > > > > + return ret;
> > > > > > > +}
> > > > > >
> > > > > > I think mtk_dsi_irq_data_clear() and mtk_dsi_wait_for_irq_done() should
> > > > > > be moved to the 6th patch [1] of this series because these two functions
> > > > > > deal the irq control.
> > > > > We will move mtk_dsi_irq_data_clear() to patch "drm/mediatek: add dsi
> > > > > interrupt control" and put mtk_dsi_wait_for_irq_done() here, because it
> > > > > is used in the transfer function.
> > > >
> > > > mtk_dsi_irq_data_clear() is also only used in transfer function now. I
> > > > think both function could be used for other application rather than
> > > > transfer function, so these two function are general function for irq
> > > > control.
> > > We will rollback the changes here. Move mtk_dsi_irq_data_clear() to
> > > original place.
> > >
> > > Add new functions could be used in the future will have problems.
> > > warning: 'mtk_dsi_wait_for_irq_done' defined but not used
> > > [-Wunused-function]
> > > static s32 mtk_dsi_wait_for_irq_done(struct mtk_dsi *dsi, u32 irq_flag,
> > > warning: 'mtk_dsi_irq_data_clear' defined but not used
> > > [-Wunused-function]
> > > static void mtk_dsi_irq_data_clear(struct mtk_dsi *dsi, u32 irq_bit)
> >
> > Please refer to [1], '__maybe_unused' can fix your problem.
> >
> > [1]
> > http://lxr.free-electrons.com/source/drivers/gpu/drm/panel/panel-sharp-lq101r1sx01.c#L76
> Add __maybe_unused just let GCC not produce a warning for this function.
> So you want add patch like this?
>
> [PATCH v7 6/9] drm/mediatek: add dsi interrupt control
> +static __maybe_unused s32 mtk_dsi_wait_for_irq_done(struct mtk_dsi
> *dsi, u32 irq_flag,
>
> +static __maybe_unused void mtk_dsi_irq_data_set(struct mtk_dsi *dsi,
> u32 irq_bit)
>
> [PATCH v7 7/9] drm/mediatek: add dsi transfer function
> -static __maybe_unused s32 mtk_dsi_wait_for_irq_done(struct mtk_dsi
> *dsi, u32 irq_flag,
> +static s32 mtk_dsi_wait_for_irq_done(struct mtk_dsi *dsi, u32 irq_flag,
>
> -static __maybe_unused void mtk_dsi_irq_data_clear(struct mtk_dsi *dsi,
> u32 irq_bit)
> +static void mtk_dsi_irq_data_clear(struct mtk_dsi *dsi, u32 irq_bit)
>
> Put the static function earlier and add __maybe_unused annotations.
> Then remove _maybe_unused annotations later. Or you want to keep
> __maybe_unused annotations inside? Sounds unnecessary, it is different
> from your reference sharp_panel_read().
Removing '__maybe_unused' in later patch looks good to me.
Regards,
CK
>
> >
> > Regards,
> > CK
> >
> > >
> > > > Regards,
> > > > CK
> > > >
> > > > >
> > > > > Regards,
> > > > > yt.shen
> > > > > >
> > > > > >
> > > > > > [1] https://patchwork.kernel.org/patch/9310819/
> > > > > >
> > > > > >
> > > > > > Regards,
> > > > > > CK
> > > > > >
> > > > >
> > > > >
> > > >
> > > >
> > >
> > >
> >
> >
>
>
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel
^ permalink raw reply
* Re: [PATCH v7 7/9] drm/mediatek: add dsi transfer function
From: YT Shen @ 2016-09-14 7:22 UTC (permalink / raw)
To: CK Hu
Cc: dri-devel, Philipp Zabel, David Airlie, Matthias Brugger,
Daniel Kurtz, Mao Huang, Bibby Hsieh, Daniel Vetter,
Thierry Reding, Jie Qiu, Maxime Ripard, Chris Wilson,
shaoming chen, Jitao Shi, Boris Brezillon, Dan Carpenter,
linux-arm-kernel, linux-mediatek, linux-kernel
In-Reply-To: <1473835151.10216.2.camel@mtksdaap41>
Hi CK,
On Wed, 2016-09-14 at 14:39 +0800, CK Hu wrote:
> Hi, YT:
>
> On Wed, 2016-09-14 at 14:19 +0800, YT Shen wrote:
> > Hi CK,
> >
> > On Tue, 2016-09-13 at 17:25 +0800, CK Hu wrote:
> > > Hi, YT:
> > >
> > > On Mon, 2016-09-12 at 18:16 +0800, YT Shen wrote:
> > > > Hi CK,
> > > >
> > > > On Wed, 2016-09-07 at 10:33 +0800, CK Hu wrote:
> > > > > Hi, YT:
> > > > >
> > > > > On Fri, 2016-09-02 at 19:24 +0800, YT Shen wrote:
> > > > > > From: shaoming chen <shaoming.chen@mediatek.com>
> > > > > >
> > > > > > add dsi read/write commands for transfer function
> > > > > >
> > > > > > Signed-off-by: shaoming chen <shaoming.chen@mediatek.com>
> > > > > > ---
> > > > > > drivers/gpu/drm/mediatek/mtk_dsi.c | 188 +++++++++++++++++++++++++++++++++++++
> > > > > > 1 file changed, 188 insertions(+)
> > > > > >
> > > > >
> > > > > [snip...]
> > > > >
> > > > > >
> > > > > > +static void mtk_dsi_irq_data_clear(struct mtk_dsi *dsi, u32 irq_bit)
> > > > > > +{
> > > > > > + dsi->irq_data &= ~irq_bit;
> > > > > > +}
> > > > > > +
> > > > >
> > > > > [snip...]
> > > > >
> > > > > > +
> > > > > > +static s32 mtk_dsi_wait_for_irq_done(struct mtk_dsi *dsi, u32 irq_flag,
> > > > > > + unsigned int timeout)
> > > > > > +{
> > > > > > + s32 ret = 0;
> > > > > > + unsigned long jiffies = msecs_to_jiffies(timeout);
> > > > > > +
> > > > > > + ret = wait_event_interruptible_timeout(_dsi_irq_wait_queue,
> > > > > > + dsi->irq_data & irq_flag,
> > > > > > + jiffies);
> > > > > > + if (ret == 0) {
> > > > > > + dev_info(dsi->dev, "Wait DSI IRQ(0x%08x) Timeout\n", irq_flag);
> > > > > > +
> > > > > > + mtk_dsi_enable(dsi);
> > > > > > + mtk_dsi_reset_engine(dsi);
> > > > > > + }
> > > > > > +
> > > > > > + return ret;
> > > > > > +}
> > > > >
> > > > > I think mtk_dsi_irq_data_clear() and mtk_dsi_wait_for_irq_done() should
> > > > > be moved to the 6th patch [1] of this series because these two functions
> > > > > deal the irq control.
> > > > We will move mtk_dsi_irq_data_clear() to patch "drm/mediatek: add dsi
> > > > interrupt control" and put mtk_dsi_wait_for_irq_done() here, because it
> > > > is used in the transfer function.
> > >
> > > mtk_dsi_irq_data_clear() is also only used in transfer function now. I
> > > think both function could be used for other application rather than
> > > transfer function, so these two function are general function for irq
> > > control.
> > We will rollback the changes here. Move mtk_dsi_irq_data_clear() to
> > original place.
> >
> > Add new functions could be used in the future will have problems.
> > warning: 'mtk_dsi_wait_for_irq_done' defined but not used
> > [-Wunused-function]
> > static s32 mtk_dsi_wait_for_irq_done(struct mtk_dsi *dsi, u32 irq_flag,
> > warning: 'mtk_dsi_irq_data_clear' defined but not used
> > [-Wunused-function]
> > static void mtk_dsi_irq_data_clear(struct mtk_dsi *dsi, u32 irq_bit)
>
> Please refer to [1], '__maybe_unused' can fix your problem.
>
> [1]
> http://lxr.free-electrons.com/source/drivers/gpu/drm/panel/panel-sharp-lq101r1sx01.c#L76
Add __maybe_unused just let GCC not produce a warning for this function.
So you want add patch like this?
[PATCH v7 6/9] drm/mediatek: add dsi interrupt control
+static __maybe_unused s32 mtk_dsi_wait_for_irq_done(struct mtk_dsi
*dsi, u32 irq_flag,
+static __maybe_unused void mtk_dsi_irq_data_set(struct mtk_dsi *dsi,
u32 irq_bit)
[PATCH v7 7/9] drm/mediatek: add dsi transfer function
-static __maybe_unused s32 mtk_dsi_wait_for_irq_done(struct mtk_dsi
*dsi, u32 irq_flag,
+static s32 mtk_dsi_wait_for_irq_done(struct mtk_dsi *dsi, u32 irq_flag,
-static __maybe_unused void mtk_dsi_irq_data_clear(struct mtk_dsi *dsi,
u32 irq_bit)
+static void mtk_dsi_irq_data_clear(struct mtk_dsi *dsi, u32 irq_bit)
Put the static function earlier and add __maybe_unused annotations.
Then remove _maybe_unused annotations later. Or you want to keep
__maybe_unused annotations inside? Sounds unnecessary, it is different
from your reference sharp_panel_read().
>
> Regards,
> CK
>
> >
> > > Regards,
> > > CK
> > >
> > > >
> > > > Regards,
> > > > yt.shen
> > > > >
> > > > >
> > > > > [1] https://patchwork.kernel.org/patch/9310819/
> > > > >
> > > > >
> > > > > Regards,
> > > > > CK
> > > > >
> > > >
> > > >
> > >
> > >
> >
> >
>
>
^ permalink raw reply
* Re: [PATCH v7 7/9] drm/mediatek: add dsi transfer function
From: CK Hu @ 2016-09-14 6:39 UTC (permalink / raw)
To: YT Shen
Cc: dri-devel, Philipp Zabel, David Airlie, Matthias Brugger,
Daniel Kurtz, Mao Huang, Bibby Hsieh, Daniel Vetter,
Thierry Reding, Jie Qiu, Maxime Ripard, Chris Wilson,
shaoming chen, Jitao Shi, Boris Brezillon, Dan Carpenter,
linux-arm-kernel, linux-mediatek, linux-kernel
In-Reply-To: <1473833946.24354.8.camel@mtksdaap41>
Hi, YT:
On Wed, 2016-09-14 at 14:19 +0800, YT Shen wrote:
> Hi CK,
>
> On Tue, 2016-09-13 at 17:25 +0800, CK Hu wrote:
> > Hi, YT:
> >
> > On Mon, 2016-09-12 at 18:16 +0800, YT Shen wrote:
> > > Hi CK,
> > >
> > > On Wed, 2016-09-07 at 10:33 +0800, CK Hu wrote:
> > > > Hi, YT:
> > > >
> > > > On Fri, 2016-09-02 at 19:24 +0800, YT Shen wrote:
> > > > > From: shaoming chen <shaoming.chen@mediatek.com>
> > > > >
> > > > > add dsi read/write commands for transfer function
> > > > >
> > > > > Signed-off-by: shaoming chen <shaoming.chen@mediatek.com>
> > > > > ---
> > > > > drivers/gpu/drm/mediatek/mtk_dsi.c | 188 +++++++++++++++++++++++++++++++++++++
> > > > > 1 file changed, 188 insertions(+)
> > > > >
> > > >
> > > > [snip...]
> > > >
> > > > >
> > > > > +static void mtk_dsi_irq_data_clear(struct mtk_dsi *dsi, u32 irq_bit)
> > > > > +{
> > > > > + dsi->irq_data &= ~irq_bit;
> > > > > +}
> > > > > +
> > > >
> > > > [snip...]
> > > >
> > > > > +
> > > > > +static s32 mtk_dsi_wait_for_irq_done(struct mtk_dsi *dsi, u32 irq_flag,
> > > > > + unsigned int timeout)
> > > > > +{
> > > > > + s32 ret = 0;
> > > > > + unsigned long jiffies = msecs_to_jiffies(timeout);
> > > > > +
> > > > > + ret = wait_event_interruptible_timeout(_dsi_irq_wait_queue,
> > > > > + dsi->irq_data & irq_flag,
> > > > > + jiffies);
> > > > > + if (ret == 0) {
> > > > > + dev_info(dsi->dev, "Wait DSI IRQ(0x%08x) Timeout\n", irq_flag);
> > > > > +
> > > > > + mtk_dsi_enable(dsi);
> > > > > + mtk_dsi_reset_engine(dsi);
> > > > > + }
> > > > > +
> > > > > + return ret;
> > > > > +}
> > > >
> > > > I think mtk_dsi_irq_data_clear() and mtk_dsi_wait_for_irq_done() should
> > > > be moved to the 6th patch [1] of this series because these two functions
> > > > deal the irq control.
> > > We will move mtk_dsi_irq_data_clear() to patch "drm/mediatek: add dsi
> > > interrupt control" and put mtk_dsi_wait_for_irq_done() here, because it
> > > is used in the transfer function.
> >
> > mtk_dsi_irq_data_clear() is also only used in transfer function now. I
> > think both function could be used for other application rather than
> > transfer function, so these two function are general function for irq
> > control.
> We will rollback the changes here. Move mtk_dsi_irq_data_clear() to
> original place.
>
> Add new functions could be used in the future will have problems.
> warning: 'mtk_dsi_wait_for_irq_done' defined but not used
> [-Wunused-function]
> static s32 mtk_dsi_wait_for_irq_done(struct mtk_dsi *dsi, u32 irq_flag,
> warning: 'mtk_dsi_irq_data_clear' defined but not used
> [-Wunused-function]
> static void mtk_dsi_irq_data_clear(struct mtk_dsi *dsi, u32 irq_bit)
Please refer to [1], '__maybe_unused' can fix your problem.
[1]
http://lxr.free-electrons.com/source/drivers/gpu/drm/panel/panel-sharp-lq101r1sx01.c#L76
Regards,
CK
>
> > Regards,
> > CK
> >
> > >
> > > Regards,
> > > yt.shen
> > > >
> > > >
> > > > [1] https://patchwork.kernel.org/patch/9310819/
> > > >
> > > >
> > > > Regards,
> > > > CK
> > > >
> > >
> > >
> >
> >
>
>
^ permalink raw reply
* Re: [PATCH v7 7/9] drm/mediatek: add dsi transfer function
From: YT Shen @ 2016-09-14 6:19 UTC (permalink / raw)
To: CK Hu
Cc: dri-devel, Philipp Zabel, David Airlie, Matthias Brugger,
Daniel Kurtz, Mao Huang, Bibby Hsieh, Daniel Vetter,
Thierry Reding, Jie Qiu, Maxime Ripard, Chris Wilson,
shaoming chen, Jitao Shi, Boris Brezillon, Dan Carpenter,
linux-arm-kernel, linux-mediatek, linux-kernel
In-Reply-To: <1473758754.28437.40.camel@mtksdaap41>
Hi CK,
On Tue, 2016-09-13 at 17:25 +0800, CK Hu wrote:
> Hi, YT:
>
> On Mon, 2016-09-12 at 18:16 +0800, YT Shen wrote:
> > Hi CK,
> >
> > On Wed, 2016-09-07 at 10:33 +0800, CK Hu wrote:
> > > Hi, YT:
> > >
> > > On Fri, 2016-09-02 at 19:24 +0800, YT Shen wrote:
> > > > From: shaoming chen <shaoming.chen@mediatek.com>
> > > >
> > > > add dsi read/write commands for transfer function
> > > >
> > > > Signed-off-by: shaoming chen <shaoming.chen@mediatek.com>
> > > > ---
> > > > drivers/gpu/drm/mediatek/mtk_dsi.c | 188 +++++++++++++++++++++++++++++++++++++
> > > > 1 file changed, 188 insertions(+)
> > > >
> > >
> > > [snip...]
> > >
> > > >
> > > > +static void mtk_dsi_irq_data_clear(struct mtk_dsi *dsi, u32 irq_bit)
> > > > +{
> > > > + dsi->irq_data &= ~irq_bit;
> > > > +}
> > > > +
> > >
> > > [snip...]
> > >
> > > > +
> > > > +static s32 mtk_dsi_wait_for_irq_done(struct mtk_dsi *dsi, u32 irq_flag,
> > > > + unsigned int timeout)
> > > > +{
> > > > + s32 ret = 0;
> > > > + unsigned long jiffies = msecs_to_jiffies(timeout);
> > > > +
> > > > + ret = wait_event_interruptible_timeout(_dsi_irq_wait_queue,
> > > > + dsi->irq_data & irq_flag,
> > > > + jiffies);
> > > > + if (ret == 0) {
> > > > + dev_info(dsi->dev, "Wait DSI IRQ(0x%08x) Timeout\n", irq_flag);
> > > > +
> > > > + mtk_dsi_enable(dsi);
> > > > + mtk_dsi_reset_engine(dsi);
> > > > + }
> > > > +
> > > > + return ret;
> > > > +}
> > >
> > > I think mtk_dsi_irq_data_clear() and mtk_dsi_wait_for_irq_done() should
> > > be moved to the 6th patch [1] of this series because these two functions
> > > deal the irq control.
> > We will move mtk_dsi_irq_data_clear() to patch "drm/mediatek: add dsi
> > interrupt control" and put mtk_dsi_wait_for_irq_done() here, because it
> > is used in the transfer function.
>
> mtk_dsi_irq_data_clear() is also only used in transfer function now. I
> think both function could be used for other application rather than
> transfer function, so these two function are general function for irq
> control.
We will rollback the changes here. Move mtk_dsi_irq_data_clear() to
original place.
Add new functions could be used in the future will have problems.
warning: 'mtk_dsi_wait_for_irq_done' defined but not used
[-Wunused-function]
static s32 mtk_dsi_wait_for_irq_done(struct mtk_dsi *dsi, u32 irq_flag,
warning: 'mtk_dsi_irq_data_clear' defined but not used
[-Wunused-function]
static void mtk_dsi_irq_data_clear(struct mtk_dsi *dsi, u32 irq_bit)
> Regards,
> CK
>
> >
> > Regards,
> > yt.shen
> > >
> > >
> > > [1] https://patchwork.kernel.org/patch/9310819/
> > >
> > >
> > > Regards,
> > > CK
> > >
> >
> >
>
>
^ permalink raw reply
* [PATCH net-next v2 3/3] net: ethernet: mediatek: add the dts property to set if the HW supports LRO
From: Nelson Chang @ 2016-09-14 5:58 UTC (permalink / raw)
To: john, davem, f.fainelli
Cc: nbd, netdev, linux-mediatek, nelsonch.tw, Nelson Chang
In-Reply-To: <1473832739-4983-1-git-send-email-nelson.chang@mediatek.com>
Add the dts property for the capability if the hardware supports LRO.
Signed-off-by: Nelson Chang <nelson.chang@mediatek.com>
---
Documentation/devicetree/bindings/net/mediatek-net.txt | 2 ++
1 file changed, 2 insertions(+)
diff --git a/Documentation/devicetree/bindings/net/mediatek-net.txt b/Documentation/devicetree/bindings/net/mediatek-net.txt
index 32eaaca..ea09a7f 100644
--- a/Documentation/devicetree/bindings/net/mediatek-net.txt
+++ b/Documentation/devicetree/bindings/net/mediatek-net.txt
@@ -20,6 +20,7 @@ Required properties:
- mediatek,ethsys: phandle to the syscon node that handles the port setup
- mediatek,pctl: phandle to the syscon node that handles the ports slew rate
and driver current
+- mediatek,hwlro: the capability if the hardware supports LRO functions
Optional properties:
- interrupt-parent: Should be the phandle for the interrupt controller
@@ -51,6 +52,7 @@ eth: ethernet@1b100000 {
reset-names = "eth";
mediatek,ethsys = <ðsys>;
mediatek,pctl = <&syscfg_pctl_a>;
+ mediatek,hwlro;
#address-cells = <1>;
#size-cells = <0>;
--
1.9.1
^ permalink raw reply related
* [PATCH net-next v2 2/3] net: ethernet: mediatek: add ethtool functions to configure RX flows of HW LRO
From: Nelson Chang @ 2016-09-14 5:58 UTC (permalink / raw)
To: john, davem, f.fainelli
Cc: nbd, netdev, linux-mediatek, nelsonch.tw, Nelson Chang
In-Reply-To: <1473832739-4983-1-git-send-email-nelson.chang@mediatek.com>
The codes add ethtool functions to set RX flows for HW LRO. Because the
HW LRO hardware can only recognize the destination IP of TCP/IP RX flows,
the ethtool command to add HW LRO flow is as below:
ethtool -N [devname] flow-type tcp4 dst-ip [ip_addr] loc [0~1]
Otherwise, cause the hardware can set total four destination IPs, each
GMAC (GMAC1/GMAC2) can set two IPs separately at most.
Signed-off-by: Nelson Chang <nelson.chang@mediatek.com>
---
drivers/net/ethernet/mediatek/mtk_eth_soc.c | 236 ++++++++++++++++++++++++++++
1 file changed, 236 insertions(+)
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index ed35e0f..5f5ff17 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -1344,6 +1344,182 @@ static void mtk_hwlro_rx_uninit(struct mtk_eth *eth)
mtk_w32(eth, 0, MTK_PDMA_LRO_CTRL_DW0);
}
+static void mtk_hwlro_val_ipaddr(struct mtk_eth *eth, int idx, __be32 ip)
+{
+ u32 reg_val;
+
+ reg_val = mtk_r32(eth, MTK_LRO_CTRL_DW2_CFG(idx));
+
+ /* invalidate the IP setting */
+ mtk_w32(eth, (reg_val & ~MTK_RING_MYIP_VLD), MTK_LRO_CTRL_DW2_CFG(idx));
+
+ mtk_w32(eth, ip, MTK_LRO_DIP_DW0_CFG(idx));
+
+ /* validate the IP setting */
+ mtk_w32(eth, (reg_val | MTK_RING_MYIP_VLD), MTK_LRO_CTRL_DW2_CFG(idx));
+}
+
+static void mtk_hwlro_inval_ipaddr(struct mtk_eth *eth, int idx)
+{
+ u32 reg_val;
+
+ reg_val = mtk_r32(eth, MTK_LRO_CTRL_DW2_CFG(idx));
+
+ /* invalidate the IP setting */
+ mtk_w32(eth, (reg_val & ~MTK_RING_MYIP_VLD), MTK_LRO_CTRL_DW2_CFG(idx));
+
+ mtk_w32(eth, 0, MTK_LRO_DIP_DW0_CFG(idx));
+}
+
+static int mtk_hwlro_get_ip_cnt(struct mtk_mac *mac)
+{
+ int cnt = 0;
+ int i;
+
+ for (i = 0; i < MTK_MAX_LRO_IP_CNT; i++) {
+ if (mac->hwlro_ip[i])
+ cnt++;
+ }
+
+ return cnt;
+}
+
+static int mtk_hwlro_add_ipaddr(struct net_device *dev,
+ struct ethtool_rxnfc *cmd)
+{
+ struct ethtool_rx_flow_spec *fsp =
+ (struct ethtool_rx_flow_spec *)&cmd->fs;
+ struct mtk_mac *mac = netdev_priv(dev);
+ struct mtk_eth *eth = mac->hw;
+ int hwlro_idx;
+
+ if ((fsp->flow_type != TCP_V4_FLOW) ||
+ (!fsp->h_u.tcp_ip4_spec.ip4dst) ||
+ (fsp->location > 1))
+ return -EINVAL;
+
+ mac->hwlro_ip[fsp->location] = htonl(fsp->h_u.tcp_ip4_spec.ip4dst);
+ hwlro_idx = (mac->id * MTK_MAX_LRO_IP_CNT) + fsp->location;
+
+ mac->hwlro_ip_cnt = mtk_hwlro_get_ip_cnt(mac);
+
+ mtk_hwlro_val_ipaddr(eth, hwlro_idx, mac->hwlro_ip[fsp->location]);
+
+ return 0;
+}
+
+static int mtk_hwlro_del_ipaddr(struct net_device *dev,
+ struct ethtool_rxnfc *cmd)
+{
+ struct ethtool_rx_flow_spec *fsp =
+ (struct ethtool_rx_flow_spec *)&cmd->fs;
+ struct mtk_mac *mac = netdev_priv(dev);
+ struct mtk_eth *eth = mac->hw;
+ int hwlro_idx;
+
+ if (fsp->location > 1)
+ return -EINVAL;
+
+ mac->hwlro_ip[fsp->location] = 0;
+ hwlro_idx = (mac->id * MTK_MAX_LRO_IP_CNT) + fsp->location;
+
+ mac->hwlro_ip_cnt = mtk_hwlro_get_ip_cnt(mac);
+
+ mtk_hwlro_inval_ipaddr(eth, hwlro_idx);
+
+ return 0;
+}
+
+static void mtk_hwlro_netdev_disable(struct net_device *dev)
+{
+ struct mtk_mac *mac = netdev_priv(dev);
+ struct mtk_eth *eth = mac->hw;
+ int i, hwlro_idx;
+
+ for (i = 0; i < MTK_MAX_LRO_IP_CNT; i++) {
+ mac->hwlro_ip[i] = 0;
+ hwlro_idx = (mac->id * MTK_MAX_LRO_IP_CNT) + i;
+
+ mtk_hwlro_inval_ipaddr(eth, hwlro_idx);
+ }
+
+ mac->hwlro_ip_cnt = 0;
+}
+
+static int mtk_hwlro_get_fdir_entry(struct net_device *dev,
+ struct ethtool_rxnfc *cmd)
+{
+ struct mtk_mac *mac = netdev_priv(dev);
+ struct ethtool_rx_flow_spec *fsp =
+ (struct ethtool_rx_flow_spec *)&cmd->fs;
+
+ /* only tcp dst ipv4 is meaningful, others are meaningless */
+ fsp->flow_type = TCP_V4_FLOW;
+ fsp->h_u.tcp_ip4_spec.ip4dst = ntohl(mac->hwlro_ip[fsp->location]);
+ fsp->m_u.tcp_ip4_spec.ip4dst = 0;
+
+ fsp->h_u.tcp_ip4_spec.ip4src = 0;
+ fsp->m_u.tcp_ip4_spec.ip4src = 0xffffffff;
+ fsp->h_u.tcp_ip4_spec.psrc = 0;
+ fsp->m_u.tcp_ip4_spec.psrc = 0xffff;
+ fsp->h_u.tcp_ip4_spec.pdst = 0;
+ fsp->m_u.tcp_ip4_spec.pdst = 0xffff;
+ fsp->h_u.tcp_ip4_spec.tos = 0;
+ fsp->m_u.tcp_ip4_spec.tos = 0xff;
+
+ return 0;
+}
+
+static int mtk_hwlro_get_fdir_all(struct net_device *dev,
+ struct ethtool_rxnfc *cmd,
+ u32 *rule_locs)
+{
+ struct mtk_mac *mac = netdev_priv(dev);
+ int cnt = 0;
+ int i;
+
+ for (i = 0; i < MTK_MAX_LRO_IP_CNT; i++) {
+ if (mac->hwlro_ip[i]) {
+ rule_locs[cnt] = i;
+ cnt++;
+ }
+ }
+
+ cmd->rule_cnt = cnt;
+
+ return 0;
+}
+
+static netdev_features_t mtk_fix_features(struct net_device *dev,
+ netdev_features_t features)
+{
+ if (!(features & NETIF_F_LRO)) {
+ struct mtk_mac *mac = netdev_priv(dev);
+ int ip_cnt = mtk_hwlro_get_ip_cnt(mac);
+
+ if (ip_cnt) {
+ netdev_info(dev, "RX flow is programmed, LRO should keep on\n");
+
+ features |= NETIF_F_LRO;
+ }
+ }
+
+ return features;
+}
+
+static int mtk_set_features(struct net_device *dev, netdev_features_t features)
+{
+ int err = 0;
+
+ if (!((dev->features ^ features) & NETIF_F_LRO))
+ return 0;
+
+ if (!(features & NETIF_F_LRO))
+ mtk_hwlro_netdev_disable(dev);
+
+ return err;
+}
+
/* wait for DMA to finish whatever it is doing before we start using it again */
static int mtk_dma_busy_wait(struct mtk_eth *eth)
{
@@ -1863,6 +2039,62 @@ static void mtk_get_ethtool_stats(struct net_device *dev,
} while (u64_stats_fetch_retry_irq(&hwstats->syncp, start));
}
+static int mtk_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd,
+ u32 *rule_locs)
+{
+ int ret = -EOPNOTSUPP;
+
+ switch (cmd->cmd) {
+ case ETHTOOL_GRXRINGS:
+ if (dev->features & NETIF_F_LRO) {
+ cmd->data = MTK_MAX_RX_RING_NUM;
+ ret = 0;
+ }
+ break;
+ case ETHTOOL_GRXCLSRLCNT:
+ if (dev->features & NETIF_F_LRO) {
+ struct mtk_mac *mac = netdev_priv(dev);
+
+ cmd->rule_cnt = mac->hwlro_ip_cnt;
+ ret = 0;
+ }
+ break;
+ case ETHTOOL_GRXCLSRULE:
+ if (dev->features & NETIF_F_LRO)
+ ret = mtk_hwlro_get_fdir_entry(dev, cmd);
+ break;
+ case ETHTOOL_GRXCLSRLALL:
+ if (dev->features & NETIF_F_LRO)
+ ret = mtk_hwlro_get_fdir_all(dev, cmd,
+ rule_locs);
+ break;
+ default:
+ break;
+ }
+
+ return ret;
+}
+
+static int mtk_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd)
+{
+ int ret = -EOPNOTSUPP;
+
+ switch (cmd->cmd) {
+ case ETHTOOL_SRXCLSRLINS:
+ if (dev->features & NETIF_F_LRO)
+ ret = mtk_hwlro_add_ipaddr(dev, cmd);
+ break;
+ case ETHTOOL_SRXCLSRLDEL:
+ if (dev->features & NETIF_F_LRO)
+ ret = mtk_hwlro_del_ipaddr(dev, cmd);
+ break;
+ default:
+ break;
+ }
+
+ return ret;
+}
+
static const struct ethtool_ops mtk_ethtool_ops = {
.get_settings = mtk_get_settings,
.set_settings = mtk_set_settings,
@@ -1874,6 +2106,8 @@ static const struct ethtool_ops mtk_ethtool_ops = {
.get_strings = mtk_get_strings,
.get_sset_count = mtk_get_sset_count,
.get_ethtool_stats = mtk_get_ethtool_stats,
+ .get_rxnfc = mtk_get_rxnfc,
+ .set_rxnfc = mtk_set_rxnfc,
};
static const struct net_device_ops mtk_netdev_ops = {
@@ -1888,6 +2122,8 @@ static const struct net_device_ops mtk_netdev_ops = {
.ndo_change_mtu = eth_change_mtu,
.ndo_tx_timeout = mtk_tx_timeout,
.ndo_get_stats64 = mtk_get_stats64,
+ .ndo_fix_features = mtk_fix_features,
+ .ndo_set_features = mtk_set_features,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = mtk_poll_controller,
#endif
--
1.9.1
^ permalink raw reply related
* [PATCH net-next v2 1/3] net: ethernet: mediatek: add HW LRO functions of PDMA RX rings
From: Nelson Chang @ 2016-09-14 5:58 UTC (permalink / raw)
To: john, davem, f.fainelli
Cc: nbd, netdev, linux-mediatek, nelsonch.tw, Nelson Chang
In-Reply-To: <1473832739-4983-1-git-send-email-nelson.chang@mediatek.com>
The codes add the large receive offload (LRO) functions by hardware as below:
1) PDMA has total four RX rings that one is the normal ring, and others can
be configured as LRO rings.
2) Only TCP/IP RX flows can be offloaded. The hardware can set four IP
addresses at most, if the destination IP of the RX flow matches one of
them, it has the chance to be offloaded.
3) There three RX flows can be offloaded at most, and one flow is mapped to
one RX ring.
4) If there are more than three candidate RX flows, the hardware can
choose three of them by throughput comparison results.
Signed-off-by: Nelson Chang <nelson.chang@mediatek.com>
---
drivers/net/ethernet/mediatek/mtk_eth_soc.c | 215 +++++++++++++++++++++++++---
drivers/net/ethernet/mediatek/mtk_eth_soc.h | 75 +++++++++-
2 files changed, 265 insertions(+), 25 deletions(-)
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index 6e01f1f..ed35e0f 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -810,11 +810,51 @@ drop:
return NETDEV_TX_OK;
}
+static struct mtk_rx_ring *mtk_get_rx_ring(struct mtk_eth *eth)
+{
+ int i;
+ struct mtk_rx_ring *ring;
+ int idx;
+
+ if (!eth->hwlro)
+ return ð->rx_ring[0];
+
+ for (i = 0; i < MTK_MAX_RX_RING_NUM; i++) {
+ ring = ð->rx_ring[i];
+ idx = NEXT_RX_DESP_IDX(ring->calc_idx, ring->dma_size);
+ if (ring->dma[idx].rxd2 & RX_DMA_DONE) {
+ ring->calc_idx_update = true;
+ return ring;
+ }
+ }
+
+ return NULL;
+}
+
+static void mtk_update_rx_cpu_idx(struct mtk_eth *eth)
+{
+ struct mtk_rx_ring *ring;
+ int i;
+
+ if (!eth->hwlro) {
+ ring = ð->rx_ring[0];
+ mtk_w32(eth, ring->calc_idx, ring->crx_idx_reg);
+ } else {
+ for (i = 0; i < MTK_MAX_RX_RING_NUM; i++) {
+ ring = ð->rx_ring[i];
+ if (ring->calc_idx_update) {
+ ring->calc_idx_update = false;
+ mtk_w32(eth, ring->calc_idx, ring->crx_idx_reg);
+ }
+ }
+ }
+}
+
static int mtk_poll_rx(struct napi_struct *napi, int budget,
struct mtk_eth *eth)
{
- struct mtk_rx_ring *ring = ð->rx_ring;
- int idx = ring->calc_idx;
+ struct mtk_rx_ring *ring;
+ int idx;
struct sk_buff *skb;
u8 *data, *new_data;
struct mtk_rx_dma *rxd, trxd;
@@ -826,7 +866,11 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget,
dma_addr_t dma_addr;
int mac = 0;
- idx = NEXT_RX_DESP_IDX(idx);
+ ring = mtk_get_rx_ring(eth);
+ if (unlikely(!ring))
+ goto rx_done;
+
+ idx = NEXT_RX_DESP_IDX(ring->calc_idx, ring->dma_size);
rxd = &ring->dma[idx];
data = ring->data[idx];
@@ -894,12 +938,13 @@ release_desc:
done++;
}
+rx_done:
if (done) {
/* make sure that all changes to the dma ring are flushed before
* we continue
*/
wmb();
- mtk_w32(eth, ring->calc_idx, MTK_PRX_CRX_IDX0);
+ mtk_update_rx_cpu_idx(eth);
}
return done;
@@ -1122,32 +1167,41 @@ static void mtk_tx_clean(struct mtk_eth *eth)
}
}
-static int mtk_rx_alloc(struct mtk_eth *eth)
+static int mtk_rx_alloc(struct mtk_eth *eth, int ring_no, int rx_flag)
{
- struct mtk_rx_ring *ring = ð->rx_ring;
+ struct mtk_rx_ring *ring = ð->rx_ring[ring_no];
+ int rx_data_len, rx_dma_size;
int i;
- ring->frag_size = mtk_max_frag_size(ETH_DATA_LEN);
+ if (rx_flag == MTK_RX_FLAGS_HWLRO) {
+ rx_data_len = MTK_MAX_LRO_RX_LENGTH;
+ rx_dma_size = MTK_HW_LRO_DMA_SIZE;
+ } else {
+ rx_data_len = ETH_DATA_LEN;
+ rx_dma_size = MTK_DMA_SIZE;
+ }
+
+ ring->frag_size = mtk_max_frag_size(rx_data_len);
ring->buf_size = mtk_max_buf_size(ring->frag_size);
- ring->data = kcalloc(MTK_DMA_SIZE, sizeof(*ring->data),
+ ring->data = kcalloc(rx_dma_size, sizeof(*ring->data),
GFP_KERNEL);
if (!ring->data)
return -ENOMEM;
- for (i = 0; i < MTK_DMA_SIZE; i++) {
+ for (i = 0; i < rx_dma_size; i++) {
ring->data[i] = netdev_alloc_frag(ring->frag_size);
if (!ring->data[i])
return -ENOMEM;
}
ring->dma = dma_alloc_coherent(eth->dev,
- MTK_DMA_SIZE * sizeof(*ring->dma),
+ rx_dma_size * sizeof(*ring->dma),
&ring->phys,
GFP_ATOMIC | __GFP_ZERO);
if (!ring->dma)
return -ENOMEM;
- for (i = 0; i < MTK_DMA_SIZE; i++) {
+ for (i = 0; i < rx_dma_size; i++) {
dma_addr_t dma_addr = dma_map_single(eth->dev,
ring->data[i] + NET_SKB_PAD,
ring->buf_size,
@@ -1158,27 +1212,30 @@ static int mtk_rx_alloc(struct mtk_eth *eth)
ring->dma[i].rxd2 = RX_DMA_PLEN0(ring->buf_size);
}
- ring->calc_idx = MTK_DMA_SIZE - 1;
+ ring->dma_size = rx_dma_size;
+ ring->calc_idx_update = false;
+ ring->calc_idx = rx_dma_size - 1;
+ ring->crx_idx_reg = MTK_PRX_CRX_IDX_CFG(ring_no);
/* make sure that all changes to the dma ring are flushed before we
* continue
*/
wmb();
- mtk_w32(eth, eth->rx_ring.phys, MTK_PRX_BASE_PTR0);
- mtk_w32(eth, MTK_DMA_SIZE, MTK_PRX_MAX_CNT0);
- mtk_w32(eth, eth->rx_ring.calc_idx, MTK_PRX_CRX_IDX0);
- mtk_w32(eth, MTK_PST_DRX_IDX0, MTK_PDMA_RST_IDX);
+ mtk_w32(eth, ring->phys, MTK_PRX_BASE_PTR_CFG(ring_no));
+ mtk_w32(eth, rx_dma_size, MTK_PRX_MAX_CNT_CFG(ring_no));
+ mtk_w32(eth, ring->calc_idx, ring->crx_idx_reg);
+ mtk_w32(eth, MTK_PST_DRX_IDX_CFG(ring_no), MTK_PDMA_RST_IDX);
return 0;
}
-static void mtk_rx_clean(struct mtk_eth *eth)
+static void mtk_rx_clean(struct mtk_eth *eth, int ring_no)
{
- struct mtk_rx_ring *ring = ð->rx_ring;
+ struct mtk_rx_ring *ring = ð->rx_ring[ring_no];
int i;
if (ring->data && ring->dma) {
- for (i = 0; i < MTK_DMA_SIZE; i++) {
+ for (i = 0; i < ring->dma_size; i++) {
if (!ring->data[i])
continue;
if (!ring->dma[i].rxd1)
@@ -1195,13 +1252,98 @@ static void mtk_rx_clean(struct mtk_eth *eth)
if (ring->dma) {
dma_free_coherent(eth->dev,
- MTK_DMA_SIZE * sizeof(*ring->dma),
+ ring->dma_size * sizeof(*ring->dma),
ring->dma,
ring->phys);
ring->dma = NULL;
}
}
+static int mtk_hwlro_rx_init(struct mtk_eth *eth)
+{
+ int i;
+ u32 ring_ctrl_dw1 = 0, ring_ctrl_dw2 = 0, ring_ctrl_dw3 = 0;
+ u32 lro_ctrl_dw0 = 0, lro_ctrl_dw3 = 0;
+
+ /* set LRO rings to auto-learn modes */
+ ring_ctrl_dw2 |= MTK_RING_AUTO_LERAN_MODE;
+
+ /* validate LRO ring */
+ ring_ctrl_dw2 |= MTK_RING_VLD;
+
+ /* set AGE timer (unit: 20us) */
+ ring_ctrl_dw2 |= MTK_RING_AGE_TIME_H;
+ ring_ctrl_dw1 |= MTK_RING_AGE_TIME_L;
+
+ /* set max AGG timer (unit: 20us) */
+ ring_ctrl_dw2 |= MTK_RING_MAX_AGG_TIME;
+
+ /* set max LRO AGG count */
+ ring_ctrl_dw2 |= MTK_RING_MAX_AGG_CNT_L;
+ ring_ctrl_dw3 |= MTK_RING_MAX_AGG_CNT_H;
+
+ for (i = 1; i < MTK_MAX_RX_RING_NUM; i++) {
+ mtk_w32(eth, ring_ctrl_dw1, MTK_LRO_CTRL_DW1_CFG(i));
+ mtk_w32(eth, ring_ctrl_dw2, MTK_LRO_CTRL_DW2_CFG(i));
+ mtk_w32(eth, ring_ctrl_dw3, MTK_LRO_CTRL_DW3_CFG(i));
+ }
+
+ /* IPv4 checksum update enable */
+ lro_ctrl_dw0 |= MTK_L3_CKS_UPD_EN;
+
+ /* switch priority comparison to packet count mode */
+ lro_ctrl_dw0 |= MTK_LRO_ALT_PKT_CNT_MODE;
+
+ /* bandwidth threshold setting */
+ mtk_w32(eth, MTK_HW_LRO_BW_THRE, MTK_PDMA_LRO_CTRL_DW2);
+
+ /* auto-learn score delta setting */
+ mtk_w32(eth, MTK_HW_LRO_REPLACE_DELTA, MTK_PDMA_LRO_ALT_SCORE_DELTA);
+
+ /* set refresh timer for altering flows to 1 sec. (unit: 20us) */
+ mtk_w32(eth, (MTK_HW_LRO_TIMER_UNIT << 16) | MTK_HW_LRO_REFRESH_TIME,
+ MTK_PDMA_LRO_ALT_REFRESH_TIMER);
+
+ /* set HW LRO mode & the max aggregation count for rx packets */
+ lro_ctrl_dw3 |= MTK_ADMA_MODE | (MTK_HW_LRO_MAX_AGG_CNT & 0xff);
+
+ /* the minimal remaining room of SDL0 in RXD for lro aggregation */
+ lro_ctrl_dw3 |= MTK_LRO_MIN_RXD_SDL;
+
+ /* enable HW LRO */
+ lro_ctrl_dw0 |= MTK_LRO_EN;
+
+ mtk_w32(eth, lro_ctrl_dw3, MTK_PDMA_LRO_CTRL_DW3);
+ mtk_w32(eth, lro_ctrl_dw0, MTK_PDMA_LRO_CTRL_DW0);
+
+ return 0;
+}
+
+static void mtk_hwlro_rx_uninit(struct mtk_eth *eth)
+{
+ int i;
+ u32 val;
+
+ /* relinquish lro rings, flush aggregated packets */
+ mtk_w32(eth, MTK_LRO_RING_RELINQUISH_REQ, MTK_PDMA_LRO_CTRL_DW0);
+
+ /* wait for relinquishments done */
+ for (i = 0; i < 10; i++) {
+ val = mtk_r32(eth, MTK_PDMA_LRO_CTRL_DW0);
+ if (val & MTK_LRO_RING_RELINQUISH_DONE) {
+ msleep(20);
+ continue;
+ }
+ }
+
+ /* invalidate lro rings */
+ for (i = 1; i < MTK_MAX_RX_RING_NUM; i++)
+ mtk_w32(eth, 0, MTK_LRO_CTRL_DW2_CFG(i));
+
+ /* disable HW LRO */
+ mtk_w32(eth, 0, MTK_PDMA_LRO_CTRL_DW0);
+}
+
/* wait for DMA to finish whatever it is doing before we start using it again */
static int mtk_dma_busy_wait(struct mtk_eth *eth)
{
@@ -1222,6 +1364,7 @@ static int mtk_dma_busy_wait(struct mtk_eth *eth)
static int mtk_dma_init(struct mtk_eth *eth)
{
int err;
+ u32 i;
if (mtk_dma_busy_wait(eth))
return -EBUSY;
@@ -1237,10 +1380,21 @@ static int mtk_dma_init(struct mtk_eth *eth)
if (err)
return err;
- err = mtk_rx_alloc(eth);
+ err = mtk_rx_alloc(eth, 0, MTK_RX_FLAGS_NORMAL);
if (err)
return err;
+ if (eth->hwlro) {
+ for (i = 1; i < MTK_MAX_RX_RING_NUM; i++) {
+ err = mtk_rx_alloc(eth, i, MTK_RX_FLAGS_HWLRO);
+ if (err)
+ return err;
+ }
+ err = mtk_hwlro_rx_init(eth);
+ if (err)
+ return err;
+ }
+
/* Enable random early drop and set drop threshold automatically */
mtk_w32(eth, FC_THRES_DROP_MODE | FC_THRES_DROP_EN | FC_THRES_MIN,
MTK_QDMA_FC_THRES);
@@ -1265,7 +1419,14 @@ static void mtk_dma_free(struct mtk_eth *eth)
eth->phy_scratch_ring = 0;
}
mtk_tx_clean(eth);
- mtk_rx_clean(eth);
+ mtk_rx_clean(eth, 0);
+
+ if (eth->hwlro) {
+ mtk_hwlro_rx_uninit(eth);
+ for (i = 1; i < MTK_MAX_RX_RING_NUM; i++)
+ mtk_rx_clean(eth, i);
+ }
+
kfree(eth->scratch_head);
}
@@ -1765,6 +1926,9 @@ static int mtk_add_mac(struct mtk_eth *eth, struct device_node *np)
mac->hw = eth;
mac->of_node = np;
+ memset(mac->hwlro_ip, 0, sizeof(mac->hwlro_ip));
+ mac->hwlro_ip_cnt = 0;
+
mac->hw_stats = devm_kzalloc(eth->dev,
sizeof(*mac->hw_stats),
GFP_KERNEL);
@@ -1781,6 +1945,11 @@ static int mtk_add_mac(struct mtk_eth *eth, struct device_node *np)
eth->netdev[id]->watchdog_timeo = 5 * HZ;
eth->netdev[id]->netdev_ops = &mtk_netdev_ops;
eth->netdev[id]->base_addr = (unsigned long)eth->base;
+
+ eth->netdev[id]->hw_features = MTK_HW_FEATURES;
+ if (eth->hwlro)
+ eth->netdev[id]->hw_features |= NETIF_F_LRO;
+
eth->netdev[id]->vlan_features = MTK_HW_FEATURES &
~(NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX);
eth->netdev[id]->features |= MTK_HW_FEATURES;
@@ -1848,6 +2017,8 @@ static int mtk_probe(struct platform_device *pdev)
return PTR_ERR(eth->rstc);
}
+ eth->hwlro = of_property_read_bool(pdev->dev.of_node, "mediatek,hwlro");
+
for (i = 0; i < 3; i++) {
eth->irq[i] = platform_get_irq(pdev, i);
if (eth->irq[i] < 0) {
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
index 0b984dc..d91848b 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -39,7 +39,21 @@
NETIF_F_SG | NETIF_F_TSO | \
NETIF_F_TSO6 | \
NETIF_F_IPV6_CSUM)
-#define NEXT_RX_DESP_IDX(X) (((X) + 1) & (MTK_DMA_SIZE - 1))
+#define NEXT_RX_DESP_IDX(X, Y) (((X) + 1) & ((Y) - 1))
+
+#define MTK_MAX_RX_RING_NUM 4
+#define MTK_HW_LRO_DMA_SIZE 8
+
+#define MTK_MAX_LRO_RX_LENGTH (4096 * 3)
+#define MTK_MAX_LRO_IP_CNT 2
+#define MTK_HW_LRO_TIMER_UNIT 1 /* 20 us */
+#define MTK_HW_LRO_REFRESH_TIME 50000 /* 1 sec. */
+#define MTK_HW_LRO_AGG_TIME 10 /* 200us */
+#define MTK_HW_LRO_AGE_TIME 50 /* 1ms */
+#define MTK_HW_LRO_MAX_AGG_CNT 64
+#define MTK_HW_LRO_BW_THRE 3000
+#define MTK_HW_LRO_REPLACE_DELTA 1000
+#define MTK_HW_LRO_SDL_REMAIN_ROOM 1522
/* Frame Engine Global Reset Register */
#define MTK_RST_GL 0x04
@@ -50,6 +64,9 @@
#define MTK_GDM1_AF BIT(28)
#define MTK_GDM2_AF BIT(29)
+/* PDMA HW LRO Alter Flow Timer Register */
+#define MTK_PDMA_LRO_ALT_REFRESH_TIMER 0x1c
+
/* Frame Engine Interrupt Grouping Register */
#define MTK_FE_INT_GRP 0x20
@@ -70,12 +87,29 @@
/* PDMA RX Base Pointer Register */
#define MTK_PRX_BASE_PTR0 0x900
+#define MTK_PRX_BASE_PTR_CFG(x) (MTK_PRX_BASE_PTR0 + (x * 0x10))
/* PDMA RX Maximum Count Register */
#define MTK_PRX_MAX_CNT0 0x904
+#define MTK_PRX_MAX_CNT_CFG(x) (MTK_PRX_MAX_CNT0 + (x * 0x10))
/* PDMA RX CPU Pointer Register */
#define MTK_PRX_CRX_IDX0 0x908
+#define MTK_PRX_CRX_IDX_CFG(x) (MTK_PRX_CRX_IDX0 + (x * 0x10))
+
+/* PDMA HW LRO Control Registers */
+#define MTK_PDMA_LRO_CTRL_DW0 0x980
+#define MTK_LRO_EN BIT(0)
+#define MTK_L3_CKS_UPD_EN BIT(7)
+#define MTK_LRO_ALT_PKT_CNT_MODE BIT(21)
+#define MTK_LRO_RING_RELINQUISH_REQ (0x3 << 26)
+#define MTK_LRO_RING_RELINQUISH_DONE (0x3 << 29)
+
+#define MTK_PDMA_LRO_CTRL_DW1 0x984
+#define MTK_PDMA_LRO_CTRL_DW2 0x988
+#define MTK_PDMA_LRO_CTRL_DW3 0x98c
+#define MTK_ADMA_MODE BIT(15)
+#define MTK_LRO_MIN_RXD_SDL (MTK_HW_LRO_SDL_REMAIN_ROOM << 16)
/* PDMA Global Configuration Register */
#define MTK_PDMA_GLO_CFG 0xa04
@@ -84,6 +118,7 @@
/* PDMA Reset Index Register */
#define MTK_PDMA_RST_IDX 0xa08
#define MTK_PST_DRX_IDX0 BIT(16)
+#define MTK_PST_DRX_IDX_CFG(x) (MTK_PST_DRX_IDX0 << (x))
/* PDMA Delay Interrupt Register */
#define MTK_PDMA_DELAY_INT 0xa0c
@@ -94,10 +129,33 @@
/* PDMA Interrupt Mask Register */
#define MTK_PDMA_INT_MASK 0xa28
+/* PDMA HW LRO Alter Flow Delta Register */
+#define MTK_PDMA_LRO_ALT_SCORE_DELTA 0xa4c
+
/* PDMA Interrupt grouping registers */
#define MTK_PDMA_INT_GRP1 0xa50
#define MTK_PDMA_INT_GRP2 0xa54
+/* PDMA HW LRO IP Setting Registers */
+#define MTK_LRO_RX_RING0_DIP_DW0 0xb04
+#define MTK_LRO_DIP_DW0_CFG(x) (MTK_LRO_RX_RING0_DIP_DW0 + (x * 0x40))
+#define MTK_RING_MYIP_VLD BIT(9)
+
+/* PDMA HW LRO Ring Control Registers */
+#define MTK_LRO_RX_RING0_CTRL_DW1 0xb28
+#define MTK_LRO_RX_RING0_CTRL_DW2 0xb2c
+#define MTK_LRO_RX_RING0_CTRL_DW3 0xb30
+#define MTK_LRO_CTRL_DW1_CFG(x) (MTK_LRO_RX_RING0_CTRL_DW1 + (x * 0x40))
+#define MTK_LRO_CTRL_DW2_CFG(x) (MTK_LRO_RX_RING0_CTRL_DW2 + (x * 0x40))
+#define MTK_LRO_CTRL_DW3_CFG(x) (MTK_LRO_RX_RING0_CTRL_DW3 + (x * 0x40))
+#define MTK_RING_AGE_TIME_L ((MTK_HW_LRO_AGE_TIME & 0x3ff) << 22)
+#define MTK_RING_AGE_TIME_H ((MTK_HW_LRO_AGE_TIME >> 10) & 0x3f)
+#define MTK_RING_AUTO_LERAN_MODE (3 << 6)
+#define MTK_RING_VLD BIT(8)
+#define MTK_RING_MAX_AGG_TIME ((MTK_HW_LRO_AGG_TIME & 0xffff) << 10)
+#define MTK_RING_MAX_AGG_CNT_L ((MTK_HW_LRO_MAX_AGG_CNT & 0x3f) << 26)
+#define MTK_RING_MAX_AGG_CNT_H ((MTK_HW_LRO_MAX_AGG_CNT >> 6) & 0x3)
+
/* QDMA TX Queue Configuration Registers */
#define MTK_QTX_CFG(x) (0x1800 + (x * 0x10))
#define QDMA_RES_THRES 4
@@ -132,7 +190,6 @@
/* QDMA Reset Index Register */
#define MTK_QDMA_RST_IDX 0x1A08
-#define MTK_PST_DRX_IDX0 BIT(16)
/* QDMA Delay Interrupt Register */
#define MTK_QDMA_DELAY_INT 0x1A0C
@@ -367,6 +424,12 @@ struct mtk_tx_ring {
atomic_t free_count;
};
+/* PDMA rx ring mode */
+enum mtk_rx_flags {
+ MTK_RX_FLAGS_NORMAL = 0,
+ MTK_RX_FLAGS_HWLRO,
+};
+
/* struct mtk_rx_ring - This struct holds info describing a RX ring
* @dma: The descriptor ring
* @data: The memory pointed at by the ring
@@ -381,7 +444,10 @@ struct mtk_rx_ring {
dma_addr_t phys;
u16 frag_size;
u16 buf_size;
+ u16 dma_size;
+ bool calc_idx_update;
u16 calc_idx;
+ u32 crx_idx_reg;
};
/* currently no SoC has more than 2 macs */
@@ -429,9 +495,10 @@ struct mtk_eth {
unsigned long sysclk;
struct regmap *ethsys;
struct regmap *pctl;
+ bool hwlro;
atomic_t dma_refcnt;
struct mtk_tx_ring tx_ring;
- struct mtk_rx_ring rx_ring;
+ struct mtk_rx_ring rx_ring[MTK_MAX_RX_RING_NUM];
struct napi_struct tx_napi;
struct napi_struct rx_napi;
struct mtk_tx_dma *scratch_ring;
@@ -457,6 +524,8 @@ struct mtk_mac {
struct mtk_eth *hw;
struct mtk_hw_stats *hw_stats;
struct phy_device *phy_dev;
+ __be32 hwlro_ip[MTK_MAX_LRO_IP_CNT];
+ int hwlro_ip_cnt;
};
/* the struct describing the SoC. these are declared in the soc_xyz.c files */
--
1.9.1
^ permalink raw reply related
* [PATCH net-next v2 0/3] net: ethernet: mediatek: add HW LRO functions
From: Nelson Chang @ 2016-09-14 5:58 UTC (permalink / raw)
To: john, davem, f.fainelli
Cc: nbd, netdev, linux-mediatek, nelsonch.tw, Nelson Chang
The series add the large receive offload (LRO) functions by hardware and
the ethtool functions to configure RX flows of HW LRO.
changes since v2:
- Add ndo_fix_features to prevent NETIF_F_LRO off while RX flow is programmed
- Rephrase the dts property is a capability if the hardware supports LRO
changes since v1:
- Add HW LRO support
- Add ethtool hooks to set LRO RX flows
Nelson Chang (3):
net: ethernet: mediatek: add HW LRO functions of PDMA RX rings
net: ethernet: mediatek: add ethtool functions to configure RX flows
of HW LRO
net: ethernet: mediatek: add dts configuration to enable HW LRO
.../devicetree/bindings/net/mediatek-net.txt | 2 +
drivers/net/ethernet/mediatek/mtk_eth_soc.c | 433 +++++++++++++++++++--
drivers/net/ethernet/mediatek/mtk_eth_soc.h | 75 +++-
3 files changed, 485 insertions(+), 25 deletions(-)
--
1.9.1
^ permalink raw reply
* Re: [PATCH v8 8/9] drm/mediatek: update DSI sub driver flow
From: CK Hu @ 2016-09-14 5:42 UTC (permalink / raw)
To: YT Shen
Cc: Daniel Vetter, Jie Qiu, Mao Huang, yingjoe.chen, Dan Carpenter,
Jitao Shi, Sascha Hauer, linux-mediatek, dri-devel,
Matthias Brugger, shaoming chen, linux-arm-kernel, srv_heupstream,
emil.l.velikov, linux-kernel, Maxime Ripard
In-Reply-To: <1473681672-47144-9-git-send-email-yt.shen@mediatek.com>
Hi, YT:
On Mon, 2016-09-12 at 20:01 +0800, YT Shen wrote:
> This patch update enable/disable flow of DSI module and MIPI TX module.
> Original flow works on there is a bridge chip: DSI -> bridge -> panel.
> In this case: DSI -> panel, the DSI sub driver flow should be updated.
> We need to initialize DSI first so that we can send commands to panel.
>
> Signed-off-by: shaoming chen <shaoming.chen@mediatek.com>
> Signed-off-by: YT Shen <yt.shen@mediatek.com>
> ---
>
[snip...]
>
> +static void mtk_dsi_switch_to_cmd_mode(struct mtk_dsi *dsi)
> +{
> + s32 ret = 0;
> + unsigned long timeout = msecs_to_jiffies(500);
> +
> + mtk_dsi_irq_data_clear(dsi, VM_DONE_INT_FLAG);
> + mtk_dsi_set_cmd_mode(dsi);
> +
> + ret = wait_event_interruptible_timeout(dsi->irq_wait_queue,
> + dsi->irq_data & VM_DONE_INT_FLAG,
> + timeout);
> + if (ret == 0) {
> + dev_info(dsi->dev, "dsi wait engine idle timeout\n");
> +
> + mtk_dsi_enable(dsi);
> + mtk_dsi_reset_engine(dsi);
> + }
I think you should replace this event-waiting with
mtk_dsi_wait_for_irq_done(). And this is a reason for moving
mtk_dsi_wait_for_irq_done() to the patch of irq control.
> +}
> +
> static void mtk_dsi_poweroff(struct mtk_dsi *dsi)
> {
> if (WARN_ON(dsi->refcount == 0))
> @@ -528,6 +574,17 @@ static void mtk_dsi_poweroff(struct mtk_dsi *dsi)
> if (--dsi->refcount != 0)
> return;
>
> + mtk_dsi_switch_to_cmd_mode(dsi);
> +
> + if (dsi->panel) {
> + if (drm_panel_unprepare(dsi->panel)) {
> + DRM_ERROR("failed to unprepare the panel\n");
> + return;
> + }
> + }
I think drm_panel_unprepare should be placed after dsi is disabled. So
move this part after calling mtk_dsi_poweroff() in
mtk_output_dsi_disable().
> +
> + mtk_dsi_reset_engine(dsi);
> +
> mtk_dsi_lane0_ulp_mode_enter(dsi);
> mtk_dsi_clk_ulp_mode_enter(dsi);
>
> @@ -546,29 +603,37 @@ static void mtk_output_dsi_enable(struct mtk_dsi *dsi)
> if (dsi->enabled)
> return;
>
> - if (dsi->panel) {
> - if (drm_panel_prepare(dsi->panel)) {
> - DRM_ERROR("failed to setup the panel\n");
> - return;
> - }
> - }
> -
> ret = mtk_dsi_poweron(dsi);
> if (ret < 0) {
> DRM_ERROR("failed to power on dsi\n");
> return;
> }
>
> + usleep_range(20000, 21000);
> +
> mtk_dsi_rxtx_control(dsi);
> + mtk_dsi_phy_timconfig(dsi);
> + mtk_dsi_ps_control_vact(dsi);
> + mtk_dsi_set_vm_cmd(dsi);
> + mtk_dsi_config_vdo_timing(dsi);
> + mtk_dsi_set_interrupt_enable(dsi);
>
> + mtk_dsi_enable(dsi);
> mtk_dsi_clk_ulp_mode_leave(dsi);
> mtk_dsi_lane0_ulp_mode_leave(dsi);
> mtk_dsi_clk_hs_mode(dsi, 0);
> - mtk_dsi_set_mode(dsi);
>
> - mtk_dsi_ps_control_vact(dsi);
> - mtk_dsi_config_vdo_timing(dsi);
> - mtk_dsi_set_interrupt_enable(dsi);
> + if (dsi->panel) {
> + if (drm_panel_prepare(dsi->panel)) {
> + DRM_ERROR("failed to prepare the panel\n");
> + return;
> + }
> +
> + if (drm_panel_enable(dsi->panel)) {
> + DRM_ERROR("failed to enable the panel\n");
> + return;
> + }
> + }
I think drm_panel_prepare() should be called before DSI is enabled and
drm_panel_enable() should be called after DSI is enabled. But you may
encounter the problem that panel need transfer data when prepare and you
can refer to [1].
[1]
http://lxr.free-electrons.com/source/drivers/gpu/drm/exynos/exynos_drm_dsi.c#L1431
>
> mtk_dsi_set_mode(dsi);
> mtk_dsi_clk_hs_mode(dsi, 1);
> @@ -590,6 +655,7 @@ static void mtk_output_dsi_disable(struct mtk_dsi *dsi)
> }
> }
>
> + mtk_dsi_stop(dsi);
> mtk_dsi_poweroff(dsi);
>
> dsi->enabled = false;
> diff --git a/drivers/gpu/drm/mediatek/mtk_mipi_tx.c b/drivers/gpu/drm/mediatek/mtk_mipi_tx.c
> index 108d31a..34e95c6 100644
> --- a/drivers/gpu/drm/mediatek/mtk_mipi_tx.c
> +++ b/drivers/gpu/drm/mediatek/mtk_mipi_tx.c
> @@ -177,7 +177,9 @@ static int mtk_mipi_tx_pll_prepare(struct clk_hw *hw)
>
> dev_dbg(mipi_tx->dev, "prepare: %u Hz\n", mipi_tx->data_rate);
>
> - if (mipi_tx->data_rate >= 500000000) {
> + if (mipi_tx->data_rate > 1250000000) {
> + return -EINVAL;
> + } else if (mipi_tx->data_rate >= 500000000) {
What is the relationship of this part and "DSI driver flow"? Would this
be an independent patch?
> txdiv = 1;
> txdiv0 = 0;
> txdiv1 = 0;
> @@ -201,6 +203,10 @@ static int mtk_mipi_tx_pll_prepare(struct clk_hw *hw)
> return -EINVAL;
> }
>
> + mtk_mipi_tx_update_bits(mipi_tx, MIPITX_DSI_TOP_CON,
> + RG_DSI_LNT_IMP_CAL_CODE | RG_DSI_LNT_HS_BIAS_EN,
> + (8 << 4) | RG_DSI_LNT_HS_BIAS_EN);
> +
> mtk_mipi_tx_update_bits(mipi_tx, MIPITX_DSI_BG_CON,
> RG_DSI_VOUT_MSK |
> RG_DSI_BG_CKEN | RG_DSI_BG_CORE_EN,
>
You modify many place without 'if (dsi->panel)'. Are all these
modifications compatible with bridge case?
Regards,
CK
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel
^ permalink raw reply
* RE: [PATCH net-next 2/3] net: ethernet: mediatek: add ethtool functions to configure RX flows of HW LRO
From: Nelson Chang @ 2016-09-14 5:22 UTC (permalink / raw)
To: f.fainelli, john, davem; +Cc: nbd, netdev, linux-mediatek, nelsonch.tw
(resend)
Thanks Florian for the review!
I will add ndo_fix_features hook in v2 to prevent the case that a user
wants to turn off NETIF_F_LRO but RX flow is programmed.
If any programmed RX flow exists, NETIF_F_LRO cannot be turned off.
-----Original Message-----
From: Florian Fainelli [mailto:f.fainelli@gmail.com]
Sent: Wednesday, September 14, 2016 2:27 AM
To: Nelson Chang (張家祥); john@phrozen.org; davem@davemloft.net
Cc: nbd@openwrt.org; netdev@vger.kernel.org;
linux-mediatek@lists.infradead.org; nelsonch.tw@gmail.com
Subject: Re: [PATCH net-next 2/3] net: ethernet: mediatek: add ethtool
functions to configure RX flows of HW LRO
On 09/13/2016 06:54 AM, Nelson Chang wrote:
> The codes add ethtool functions to set RX flows for HW LRO. Because
> the HW LRO hardware can only recognize the destination IP of TCP/IP
RX
> flows, the ethtool command to add HW LRO flow is as below:
> ethtool -N [devname] flow-type tcp4 dst-ip [ip_addr] loc [0~1]
>
> Otherwise, cause the hardware can set total four destination IPs,
each
> GMAC (GMAC1/GMAC2) can set two IPs separately at most.
>
> Signed-off-by: Nelson Chang <nelson.chang@mediatek.com>
> ---
> +
> +static int mtk_set_features(struct net_device *dev, netdev_features_t
> +features) {
> + int err = 0;
> +
> + if (!((dev->features ^ features) & NETIF_F_LRO))
> + return 0;
> +
> + if (!(features & NETIF_F_LRO))
> + mtk_hwlro_netdev_disable(dev);
you may want to implement a fix_features ndo operations which makes sure
that NETIF_F_LRO is turned on in case a RX flow is programmed,
otherwise, it may be confusing to the user that a flow was programmed,
but no offload is happening.
^ permalink raw reply
* RE: [PATCH net-next 3/3] net: ethernet: mediatek: add dts configuration to enable HW LRO
From: Nelson Chang @ 2016-09-14 5:20 UTC (permalink / raw)
To: f.fainelli, john, davem; +Cc: nbd, netdev, linux-mediatek, nelsonch.tw
(resend)
The description of the property as you said is more precise.
The property is a capability if the hardware supports LRO. I'll rephrase
the property description in v2.
Thanks Florian!
-----Original Message-----
From: Florian Fainelli [mailto:f.fainelli@gmail.com]
Sent: Wednesday, September 14, 2016 2:25 AM
To: Nelson Chang (張家祥); john@phrozen.org; davem@davemloft.net
Cc: nbd@openwrt.org; netdev@vger.kernel.org;
linux-mediatek@lists.infradead.org; nelsonch.tw@gmail.com
Subject: Re: [PATCH net-next 3/3] net: ethernet: mediatek: add dts
configuration to enable HW LRO
On 09/13/2016 06:54 AM, Nelson Chang wrote:
> Add the configuration of HW LRO in the binding document.
>
> Signed-off-by: Nelson Chang <nelson.chang@mediatek.com>
> ---
> Documentation/devicetree/bindings/net/mediatek-net.txt | 2 ++
> 1 file changed, 2 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/net/mediatek-net.txt
> b/Documentation/devicetree/bindings/net/mediatek-net.txt
> index 32eaaca..f43c0d1 100644
> --- a/Documentation/devicetree/bindings/net/mediatek-net.txt
> +++ b/Documentation/devicetree/bindings/net/mediatek-net.txt
> @@ -20,6 +20,7 @@ Required properties:
> - mediatek,ethsys: phandle to the syscon node that handles the port
> setup
> - mediatek,pctl: phandle to the syscon node that handles the ports
slew rate
> and driver current
> +- mediatek,hwlro: set to enable HW LRO functions of PDMA rx rings
That sounds like implementing a enable/disable policy in the Device Tree
as opposed to providing an indication as to whether the HW supports LRO
or not. If all versions of the hardware support LRO, then you would
rather let the users change NETIF_F_LRO using ethtool features instead
of having this be defined in the Device Tree.
If, on the other hand, not all version of the HW support LRO, then you
would just want to rephrase the property description to say this
describes a capability.
^ permalink raw reply
* Re: [PATCH 0/4] Add V4L2_PIX_FMT_MT21C format for MT8173 codec driver
From: Tiffany Lin @ 2016-09-14 4:52 UTC (permalink / raw)
To: Hans Verkuil
Cc: Andrew-CT Chen, Hans Verkuil, Laurent Pinchart,
Mauro Carvalho Chehab, Matthias Brugger, Daniel Kurtz,
Pawel Osciak, Eddie Huang, Yingjoe Chen, linux-kernel,
linux-media, linux-mediatek
In-Reply-To: <64676168-8c5f-3720-820a-17e7bdbcc735@xs4all.nl>
Hi Hans,
On Thu, 2016-09-08 at 11:27 +0200, Hans Verkuil wrote:
> On 09/08/16 11:11, Tiffany Lin wrote:
> > Hi Hans,
> >
> > On Thu, 2016-09-08 at 09:21 +0200, Hans Verkuil wrote:
> >> Hi Tiffany,
> >>
> >> On 09/07/2016 08:56 AM, Tiffany Lin wrote:
> >>> This patch series add Mediatek compressed block format V4L2_PIX_FMT_MT21C, the
> >>> decoder driver will decoded bitstream to V4L2_PIX_FMT_MT21C format.
> >>>
> >>> User space applications could use MT8173 MDP driver to convert V4L2_PIX_FMT_MT21C to
> >>> V4L2_PIX_FMT_NV12M, V4L2_PIX_FMT_YUV420M and V4L2_PIX_FMT_YVU420.
> >>>
> >>> MDP driver[1] is stand alone driver.
> >>>
> >>> Usage:
> >>> MT21C -> MT8173 MDP -> NV12M/YUV420M/YVU420
> >>> NV12M/NV21M/YUV420M/YVU420M -> mt8173 Encoder -> H264/VP8
> >>> H264/VP8/VP9 -> mtk8173 Decoder -> MT21C
> >>>
> >>> When encode with MT21 source, the pipeline will be:
> >>> MT21C -> MDP driver-> NV12M/NV21M/YUV420M/YVU420M -> Encoder -> H264/VP8
> >>>
> >>> When playback, the pipeline will be:
> >>> H264/VP8/VP9 -> Decoder driver -> MT21C -> MDP Driver -> DRM
> >>>
> >>> [1]https://patchwork.kernel.org/patch/9305329/
> >>>
> >>> Tiffany Lin (4):
> >>> v4l: add Mediatek compressed video block format
> >>> docs-rst: Add compressed video formats used on MT8173 codec driver
> >>> vcodec: mediatek: Add V4L2_PIX_FMT_MT21C support for v4l2 decoder
> >>> arm64: dts: mediatek: Add Video Decoder for MT8173
> >>>
> >>> Documentation/media/uapi/v4l/pixfmt-reserved.rst | 6 +++
> >>> arch/arm64/boot/dts/mediatek/mt8173.dtsi | 44 ++++++++++++++++++++
> >>> drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.c | 7 +++-
> >>> drivers/media/v4l2-core/v4l2-ioctl.c | 1 +
> >>> include/uapi/linux/videodev2.h | 1 +
> >>> 5 files changed, 58 insertions(+), 1 deletion(-)
> >>>
> >>
> >> So basically the video decoder is useless without support for this format and
> >> without the MDP driver, right?
> >>
> > Yes. It also require new vpu firmware.
> > Andrew will help release new vpu firmware include encode/decode/mdp
> > capability.
>
> OK, then I'll park this until:
>
> - the MT21C patch series is OK
> - the MDP patch series is OK
> - the new firmware is released
>
> For the record: the decoder patch series is OK as far as I am concerned.
> It's in my mtkdec branch.
>
Appreciated for your help.
We had upstream new MT21C, MDP and new VPU firmware.
MT21C patch series: https://patchwork.kernel.org/patch/9323883/
MDP patch series: https://patchwork.kernel.org/patch/9321343/
VPU firmware: https://patchwork.linuxtv.org/patch/36968/
best regards,
Tiffany
> Regards,
>
> Hans
^ permalink raw reply
* [PATCH net-next 7/7] net: ethernet: mediatek: avoid race condition during the reset process
From: sean.wang @ 2016-09-14 3:50 UTC (permalink / raw)
To: john, davem; +Cc: nbd, netdev, linux-mediatek, keyhaede, objelf, Sean Wang
In-Reply-To: <1473825041-21072-1-git-send-email-sean.wang@mediatek.com>
From: Sean Wang <sean.wang@mediatek.com>
add the protection of the race condition between
the reset process and hardware access happening
on the related callbacks.
Signed-off-by: Sean Wang <sean.wang@mediatek.com>
---
drivers/net/ethernet/mediatek/mtk_eth_soc.c | 36 +++++++++++++++++++++++++++++
drivers/net/ethernet/mediatek/mtk_eth_soc.h | 3 ++-
2 files changed, 38 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index 48cddf9..a6a9a2f 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -145,6 +145,9 @@ static void mtk_phy_link_adjust(struct net_device *dev)
MAC_MCR_RX_EN | MAC_MCR_BACKOFF_EN |
MAC_MCR_BACKPR_EN;
+ if (unlikely(test_bit(MTK_RESETTING, &mac->hw->state)))
+ return;
+
switch (mac->phy_dev->speed) {
case SPEED_1000:
mcr |= MAC_MCR_SPEED_1000;
@@ -370,6 +373,9 @@ static int mtk_set_mac_address(struct net_device *dev, void *p)
if (ret)
return ret;
+ if (unlikely(test_bit(MTK_RESETTING, &mac->hw->state)))
+ return -EBUSY;
+
spin_lock_bh(&mac->hw->page_lock);
mtk_w32(mac->hw, (macaddr[0] << 8) | macaddr[1],
MTK_GDMA_MAC_ADRH(mac->id));
@@ -770,6 +776,9 @@ static int mtk_start_xmit(struct sk_buff *skb, struct net_device *dev)
*/
spin_lock(ð->page_lock);
+ if (unlikely(test_bit(MTK_RESETTING, ð->state)))
+ goto drop;
+
tx_num = mtk_cal_txd_req(skb);
if (unlikely(atomic_read(&ring->free_count) <= tx_num)) {
mtk_stop_queue(eth);
@@ -842,6 +851,9 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget,
netdev = eth->netdev[mac];
+ if (unlikely(test_bit(MTK_RESETTING, ð->state)))
+ goto release_desc;
+
/* alloc new buffer */
new_data = napi_alloc_frag(ring->frag_size);
if (unlikely(!new_data)) {
@@ -1573,6 +1585,12 @@ static void mtk_pending_work(struct work_struct *work)
rtnl_lock();
+ dev_dbg(eth->dev, "[%s][%d] reset\n", __func__, __LINE__);
+
+ while (test_and_set_bit_lock(MTK_RESETTING, ð->state))
+ cpu_relax();
+
+ dev_dbg(eth->dev, "[%s][%d] mtk_stop starts\n", __func__, __LINE__);
/* stop all devices to make sure that dma is properly shut down */
for (i = 0; i < MTK_MAC_COUNT; i++) {
if (!eth->netdev[i])
@@ -1580,6 +1598,7 @@ static void mtk_pending_work(struct work_struct *work)
mtk_stop(eth->netdev[i]);
__set_bit(i, &restart);
}
+ dev_dbg(eth->dev, "[%s][%d] mtk_stop ends\n", __func__, __LINE__);
/* restart underlying hardware such as power, clock, pin mux
* and the connected phy
@@ -1613,6 +1632,11 @@ static void mtk_pending_work(struct work_struct *work)
dev_close(eth->netdev[i]);
}
}
+
+ dev_dbg(eth->dev, "[%s][%d] reset done\n", __func__, __LINE__);
+
+ clear_bit_unlock(MTK_RESETTING, ð->state);
+
rtnl_unlock();
}
@@ -1657,6 +1681,9 @@ static int mtk_get_settings(struct net_device *dev,
struct mtk_mac *mac = netdev_priv(dev);
int err;
+ if (unlikely(test_bit(MTK_RESETTING, &mac->hw->state)))
+ return -EBUSY;
+
err = phy_read_status(mac->phy_dev);
if (err)
return -ENODEV;
@@ -1707,6 +1734,9 @@ static int mtk_nway_reset(struct net_device *dev)
{
struct mtk_mac *mac = netdev_priv(dev);
+ if (unlikely(test_bit(MTK_RESETTING, &mac->hw->state)))
+ return -EBUSY;
+
return genphy_restart_aneg(mac->phy_dev);
}
@@ -1715,6 +1745,9 @@ static u32 mtk_get_link(struct net_device *dev)
struct mtk_mac *mac = netdev_priv(dev);
int err;
+ if (unlikely(test_bit(MTK_RESETTING, &mac->hw->state)))
+ return -EBUSY;
+
err = genphy_update_link(mac->phy_dev);
if (err)
return ethtool_op_get_link(dev);
@@ -1755,6 +1788,9 @@ static void mtk_get_ethtool_stats(struct net_device *dev,
unsigned int start;
int i;
+ if (unlikely(test_bit(MTK_RESETTING, &mac->hw->state)))
+ return;
+
if (netif_running(dev) && netif_device_present(dev)) {
if (spin_trylock(&hwstats->stats_lock)) {
mtk_stats_update_mac(mac);
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
index 7efa00f..79954b4 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -336,7 +336,8 @@ enum mtk_clks_map {
};
enum mtk_dev_state {
- MTK_HW_INIT
+ MTK_HW_INIT,
+ MTK_RESETTING
};
/* struct mtk_tx_buf - This struct holds the pointers to the memory pointed at
--
1.9.1
^ permalink raw reply related
* [PATCH net-next 6/7] net: ethernet: mediatek: add more resets for internal ethernet circuit block
From: sean.wang @ 2016-09-14 3:50 UTC (permalink / raw)
To: john, davem; +Cc: nbd, netdev, linux-mediatek, keyhaede, objelf, Sean Wang
In-Reply-To: <1473825041-21072-1-git-send-email-sean.wang@mediatek.com>
From: Sean Wang <sean.wang@mediatek.com>
struct mtk_eth has already contained struct regmap ethsys pointer
to the address range of the internal circuit reset, so we reuse it
to reset more internal blocks on ethernet hardware such as packet
processing engine (PPE) and frame engine (FE) instead of rstc which
deals with FE only.
Signed-off-by: Sean Wang <sean.wang@mediatek.com>
---
drivers/net/ethernet/mediatek/mtk_eth_soc.c | 27 +++++++++++++++------------
drivers/net/ethernet/mediatek/mtk_eth_soc.h | 6 +++++-
2 files changed, 20 insertions(+), 13 deletions(-)
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index b9ddbcb..48cddf9 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -1414,6 +1414,19 @@ static int mtk_stop(struct net_device *dev)
return 0;
}
+static void ethsys_reset(struct mtk_eth *eth, u32 reset_bits)
+{
+ regmap_update_bits(eth->ethsys, ETHSYS_RSTCTRL,
+ reset_bits,
+ reset_bits);
+
+ usleep_range(1000, 1100);
+ regmap_update_bits(eth->ethsys, ETHSYS_RSTCTRL,
+ reset_bits,
+ ~reset_bits);
+ mdelay(10);
+}
+
static int mtk_hw_init(struct mtk_eth *eth)
{
int i, val;
@@ -1428,12 +1441,8 @@ static int mtk_hw_init(struct mtk_eth *eth)
clk_prepare_enable(eth->clks[MTK_CLK_ESW]);
clk_prepare_enable(eth->clks[MTK_CLK_GP1]);
clk_prepare_enable(eth->clks[MTK_CLK_GP2]);
-
- /* reset the frame engine */
- reset_control_assert(eth->rstc);
- usleep_range(10, 20);
- reset_control_deassert(eth->rstc);
- usleep_range(10, 20);
+ ethsys_reset(eth, RSTCTRL_FE);
+ ethsys_reset(eth, RSTCTRL_PPE);
regmap_read(eth->ethsys, ETHSYS_SYSCFG0, &val);
for (i = 0; i < MTK_MAC_COUNT; i++) {
@@ -1894,12 +1903,6 @@ static int mtk_probe(struct platform_device *pdev)
return PTR_ERR(eth->pctl);
}
- eth->rstc = devm_reset_control_get(&pdev->dev, "eth");
- if (IS_ERR(eth->rstc)) {
- dev_err(&pdev->dev, "no eth reset found\n");
- return PTR_ERR(eth->rstc);
- }
-
for (i = 0; i < 3; i++) {
eth->irq[i] = platform_get_irq(pdev, i);
if (eth->irq[i] < 0) {
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
index 388cbe7..7efa00f 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -266,6 +266,11 @@
#define SYSCFG0_GE_MASK 0x3
#define SYSCFG0_GE_MODE(x, y) (x << (12 + (y * 2)))
+/*ethernet reset control register*/
+#define ETHSYS_RSTCTRL 0x34
+#define RSTCTRL_FE BIT(6)
+#define RSTCTRL_PPE BIT(31)
+
struct mtk_rx_dma {
unsigned int rxd1;
unsigned int rxd2;
@@ -423,7 +428,6 @@ struct mtk_rx_ring {
struct mtk_eth {
struct device *dev;
void __iomem *base;
- struct reset_control *rstc;
spinlock_t page_lock;
spinlock_t irq_lock;
struct net_device dummy_dev;
--
1.9.1
^ permalink raw reply related
* [PATCH net-next 5/7] net: ethernet: mediatek: add the whole ethernet reset into the reset process
From: sean.wang @ 2016-09-14 3:50 UTC (permalink / raw)
To: john, davem; +Cc: nbd, netdev, linux-mediatek, keyhaede, objelf, Sean Wang
In-Reply-To: <1473825041-21072-1-git-send-email-sean.wang@mediatek.com>
From: Sean Wang <sean.wang@mediatek.com>
1) original driver only resets DMA used by descriptor rings
which can't guarantee it can recover all various kinds of fatal
errors, so the patch tries to reset the underlying hardware
resource from scratch on Mediatek SoC required for ethernet
running, including power, pin mux control, clock and internal
circuits on the ethernet in order to restore into the initial
state which the rebooted machine gives.
2) add state variable inside structure mtk_eth to help distinguish
mtk_hw_init is called between the initialization during boot time
or re-initialization during the reset process.
3) add ge_mode variable inside structure mtk_mac for restoring
the interface mode of the current setup for the target MAC.
4) remove __init attribute from mtk_hw_init definition
Signed-off-by: Sean Wang <sean.wang@mediatek.com>
---
drivers/net/ethernet/mediatek/mtk_eth_soc.c | 52 ++++++++++++++++++++++++-----
drivers/net/ethernet/mediatek/mtk_eth_soc.h | 8 +++++
2 files changed, 52 insertions(+), 8 deletions(-)
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index fd5d064..b9ddbcb 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -231,7 +231,7 @@ static int mtk_phy_connect(struct mtk_mac *mac)
{
struct mtk_eth *eth = mac->hw;
struct device_node *np;
- u32 val, ge_mode;
+ u32 val;
np = of_parse_phandle(mac->of_node, "phy-handle", 0);
if (!np && of_phy_is_fixed_link(mac->of_node))
@@ -245,18 +245,18 @@ static int mtk_phy_connect(struct mtk_mac *mac)
case PHY_INTERFACE_MODE_RGMII_RXID:
case PHY_INTERFACE_MODE_RGMII_ID:
case PHY_INTERFACE_MODE_RGMII:
- ge_mode = 0;
+ mac->ge_mode = 0;
break;
case PHY_INTERFACE_MODE_MII:
- ge_mode = 1;
+ mac->ge_mode = 1;
break;
case PHY_INTERFACE_MODE_REVMII:
- ge_mode = 2;
+ mac->ge_mode = 2;
break;
case PHY_INTERFACE_MODE_RMII:
if (!mac->id)
goto err_phy;
- ge_mode = 3;
+ mac->ge_mode = 3;
break;
default:
goto err_phy;
@@ -265,7 +265,7 @@ static int mtk_phy_connect(struct mtk_mac *mac)
/* put the gmac into the right mode */
regmap_read(eth->ethsys, ETHSYS_SYSCFG0, &val);
val &= ~SYSCFG0_GE_MODE(SYSCFG0_GE_MASK, mac->id);
- val |= SYSCFG0_GE_MODE(ge_mode, mac->id);
+ val |= SYSCFG0_GE_MODE(mac->ge_mode, mac->id);
regmap_write(eth->ethsys, ETHSYS_SYSCFG0, val);
mtk_phy_connect_node(eth, mac, np);
@@ -1414,9 +1414,12 @@ static int mtk_stop(struct net_device *dev)
return 0;
}
-static int __init mtk_hw_init(struct mtk_eth *eth)
+static int mtk_hw_init(struct mtk_eth *eth)
{
- int i;
+ int i, val;
+
+ if (test_and_set_bit(MTK_HW_INIT, ð->state))
+ return 0;
pm_runtime_enable(eth->dev);
pm_runtime_get_sync(eth->dev);
@@ -1432,6 +1435,15 @@ static int __init mtk_hw_init(struct mtk_eth *eth)
reset_control_deassert(eth->rstc);
usleep_range(10, 20);
+ regmap_read(eth->ethsys, ETHSYS_SYSCFG0, &val);
+ for (i = 0; i < MTK_MAC_COUNT; i++) {
+ if (!eth->mac[i])
+ continue;
+ val &= ~SYSCFG0_GE_MODE(SYSCFG0_GE_MASK, eth->mac[i]->id);
+ val |= SYSCFG0_GE_MODE(eth->mac[i]->ge_mode, eth->mac[i]->id);
+ }
+ regmap_write(eth->ethsys, ETHSYS_SYSCFG0, val);
+
/* Set GE2 driving and slew rate */
regmap_write(eth->pctl, GPIO_DRV_SEL10, 0xa00);
@@ -1483,6 +1495,9 @@ static int __init mtk_hw_init(struct mtk_eth *eth)
static int mtk_hw_deinit(struct mtk_eth *eth)
{
+ if (!test_and_clear_bit(MTK_HW_INIT, ð->state))
+ return 0;
+
clk_disable_unprepare(eth->clks[MTK_CLK_GP2]);
clk_disable_unprepare(eth->clks[MTK_CLK_GP1]);
clk_disable_unprepare(eth->clks[MTK_CLK_ESW]);
@@ -1557,6 +1572,27 @@ static void mtk_pending_work(struct work_struct *work)
__set_bit(i, &restart);
}
+ /* restart underlying hardware such as power, clock, pin mux
+ * and the connected phy
+ */
+ mtk_hw_deinit(eth);
+
+ if (eth->dev->pins)
+ devm_kfree(eth->dev, eth->dev->pins);
+ pinctrl_bind_pins(eth->dev);
+
+ mtk_hw_init(eth);
+
+ for (i = 0; i < MTK_MAC_COUNT; i++) {
+ if (!eth->mac[i] ||
+ of_phy_is_fixed_link(eth->mac[i]->of_node))
+ continue;
+ err = phy_init_hw(eth->mac[i]->phy_dev);
+ if (err)
+ dev_err(eth->dev, "%s: PHY init failed.\n",
+ eth->netdev[i]->name);
+ }
+
/* restart DMA and enable IRQs */
for (i = 0; i < MTK_MAC_COUNT; i++) {
if (!test_bit(i, &restart))
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
index 0b984dc..388cbe7 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -330,6 +330,10 @@ enum mtk_clks_map {
MTK_CLK_MAX
};
+enum mtk_dev_state {
+ MTK_HW_INIT
+};
+
/* struct mtk_tx_buf - This struct holds the pointers to the memory pointed at
* by the TX descriptor s
* @skb: The SKB pointer of the packet being sent
@@ -413,6 +417,7 @@ struct mtk_rx_ring {
* @clks: clock array for all clocks required
* @mii_bus: If there is a bus we need to create an instance for it
* @pending_work: The workqueue used to reset the dma ring
+ * @state Initialization and runtime state of the device.
*/
struct mtk_eth {
@@ -441,11 +446,13 @@ struct mtk_eth {
struct mii_bus *mii_bus;
struct work_struct pending_work;
+ unsigned long state;
};
/* struct mtk_mac - the structure that holds the info about the MACs of the
* SoC
* @id: The number of the MAC
+ * @ge_mode: Interface mode kept for setup restoring
* @of_node: Our devicetree node
* @hw: Backpointer to our main datastruture
* @hw_stats: Packet statistics counter
@@ -453,6 +460,7 @@ struct mtk_eth {
*/
struct mtk_mac {
int id;
+ int ge_mode;
struct device_node *of_node;
struct mtk_eth *hw;
struct mtk_hw_stats *hw_stats;
--
1.9.1
^ permalink raw reply related
* [PATCH net-next 4/7] net: ethernet: mediatek: add controlling power domain the ethernet belongs to
From: sean.wang @ 2016-09-14 3:50 UTC (permalink / raw)
To: john, davem; +Cc: nbd, netdev, linux-mediatek, keyhaede, objelf, Sean Wang
In-Reply-To: <1473825041-21072-1-git-send-email-sean.wang@mediatek.com>
From: Sean Wang <sean.wang@mediatek.com>
introduce power domain control which the digital circuit of
the ethernet belongs to inside the flow of hardware initialization
and deinitialization which helps the entire ethernet hardware block
could restart cleanly and completely as being back to the initial
state when the whole machine reboot.
Signed-off-by: Sean Wang <sean.wang@mediatek.com>
---
drivers/net/ethernet/mediatek/mtk_eth_soc.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index 917a49c6..fd5d064 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -18,6 +18,7 @@
#include <linux/mfd/syscon.h>
#include <linux/regmap.h>
#include <linux/clk.h>
+#include <linux/pm_runtime.h>
#include <linux/if_vlan.h>
#include <linux/reset.h>
#include <linux/tcp.h>
@@ -1417,6 +1418,9 @@ static int __init mtk_hw_init(struct mtk_eth *eth)
{
int i;
+ pm_runtime_enable(eth->dev);
+ pm_runtime_get_sync(eth->dev);
+
clk_prepare_enable(eth->clks[MTK_CLK_ETHIF]);
clk_prepare_enable(eth->clks[MTK_CLK_ESW]);
clk_prepare_enable(eth->clks[MTK_CLK_GP1]);
@@ -1484,6 +1488,9 @@ static int mtk_hw_deinit(struct mtk_eth *eth)
clk_disable_unprepare(eth->clks[MTK_CLK_ESW]);
clk_disable_unprepare(eth->clks[MTK_CLK_ETHIF]);
+ pm_runtime_put_sync(eth->dev);
+ pm_runtime_disable(eth->dev);
+
return 0;
}
--
1.9.1
^ permalink raw reply related
* [PATCH net-next 3/7] net: ethernet: mediatek: cleanup error path inside mtk_hw_init
From: sean.wang @ 2016-09-14 3:50 UTC (permalink / raw)
To: john, davem; +Cc: nbd, netdev, linux-mediatek, keyhaede, objelf, Sean Wang
In-Reply-To: <1473825041-21072-1-git-send-email-sean.wang@mediatek.com>
From: Sean Wang <sean.wang@mediatek.com>
This cleans up the error path inside mtk_hw_init call, causing it able
to exit appropriately when something fails and also includes refactoring
mtk_cleanup call to make the partial logic reusable on the error path.
Signed-off-by: Sean Wang <sean.wang@mediatek.com>
---
drivers/net/ethernet/mediatek/mtk_eth_soc.c | 34 ++++++++++++++++++++++++-----
1 file changed, 29 insertions(+), 5 deletions(-)
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index c71b0b3..917a49c6 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -1564,17 +1564,36 @@ static void mtk_pending_work(struct work_struct *work)
rtnl_unlock();
}
-static int mtk_cleanup(struct mtk_eth *eth)
+static int mtk_free_dev(struct mtk_eth *eth)
{
int i;
for (i = 0; i < MTK_MAC_COUNT; i++) {
if (!eth->netdev[i])
continue;
+ free_netdev(eth->netdev[i]);
+ }
+
+ return 0;
+}
+static int mtk_unreg_dev(struct mtk_eth *eth)
+{
+ int i;
+
+ for (i = 0; i < MTK_MAC_COUNT; i++) {
+ if (!eth->netdev[i])
+ continue;
unregister_netdev(eth->netdev[i]);
- free_netdev(eth->netdev[i]);
}
+
+ return 0;
+}
+
+static int mtk_cleanup(struct mtk_eth *eth)
+{
+ mtk_unreg_dev(eth);
+ mtk_free_dev(eth);
cancel_work_sync(ð->pending_work);
return 0;
@@ -1872,7 +1891,7 @@ static int mtk_probe(struct platform_device *pdev)
err = mtk_add_mac(eth, mac_np);
if (err)
- goto err_free_dev;
+ goto err_deinit_hw;
}
err = devm_request_irq(eth->dev, eth->irq[1], mtk_handle_irq_tx, 0,
@@ -1896,7 +1915,7 @@ static int mtk_probe(struct platform_device *pdev)
err = register_netdev(eth->netdev[i]);
if (err) {
dev_err(eth->dev, "error bringing up device\n");
- goto err_free_dev;
+ goto err_deinit_mdio;
} else
netif_info(eth, probe, eth->netdev[i],
"mediatek frame engine at 0x%08lx, irq %d\n",
@@ -1916,8 +1935,13 @@ static int mtk_probe(struct platform_device *pdev)
return 0;
+err_deinit_mdio:
+ mtk_mdio_cleanup(eth);
err_free_dev:
- mtk_cleanup(eth);
+ mtk_free_dev(eth);
+err_deinit_hw:
+ mtk_hw_deinit(eth);
+
return err;
}
--
1.9.1
^ permalink raw reply related
* [PATCH net-next 2/7] net: ethernet: mediatek: add mtk_hw_deinit call as the opposite to mtk_hw_init call
From: sean.wang @ 2016-09-14 3:50 UTC (permalink / raw)
To: john, davem; +Cc: nbd, netdev, linux-mediatek, keyhaede, objelf, Sean Wang
In-Reply-To: <1473825041-21072-1-git-send-email-sean.wang@mediatek.com>
From: Sean Wang <sean.wang@mediatek.com>
grouping things related to the deinitialization of what
mtk_hw_init call does that help to be reused by the reset
process and the error path handling.
Signed-off-by: Sean Wang <sean.wang@mediatek.com>
---
drivers/net/ethernet/mediatek/mtk_eth_soc.c | 15 +++++++++++----
1 file changed, 11 insertions(+), 4 deletions(-)
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index ca46e82..c71b0b3 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -1477,6 +1477,16 @@ static int __init mtk_hw_init(struct mtk_eth *eth)
return 0;
}
+static int mtk_hw_deinit(struct mtk_eth *eth)
+{
+ clk_disable_unprepare(eth->clks[MTK_CLK_GP2]);
+ clk_disable_unprepare(eth->clks[MTK_CLK_GP1]);
+ clk_disable_unprepare(eth->clks[MTK_CLK_ESW]);
+ clk_disable_unprepare(eth->clks[MTK_CLK_ETHIF]);
+
+ return 0;
+}
+
static int __init mtk_init(struct net_device *dev)
{
struct mtk_mac *mac = netdev_priv(dev);
@@ -1923,10 +1933,7 @@ static int mtk_remove(struct platform_device *pdev)
mtk_stop(eth->netdev[i]);
}
- clk_disable_unprepare(eth->clks[MTK_CLK_ETHIF]);
- clk_disable_unprepare(eth->clks[MTK_CLK_ESW]);
- clk_disable_unprepare(eth->clks[MTK_CLK_GP1]);
- clk_disable_unprepare(eth->clks[MTK_CLK_GP2]);
+ mtk_hw_deinit(eth);
netif_napi_del(ð->tx_napi);
netif_napi_del(ð->rx_napi);
--
1.9.1
^ permalink raw reply related
* [PATCH net-next 1/7] net: ethernet: mediatek: refactoring mtk_hw_init to be reused
From: sean.wang @ 2016-09-14 3:50 UTC (permalink / raw)
To: john, davem; +Cc: nbd, netdev, linux-mediatek, keyhaede, objelf, Sean Wang
In-Reply-To: <1473825041-21072-1-git-send-email-sean.wang@mediatek.com>
From: Sean Wang <sean.wang@mediatek.com>
the existing mtk_hw_init includes hardware and software
initialization inside so that it is slightly hard to reuse
them for the process of the reset recovery, so some splitting
is made here for keeping hardware initializing relevant thing
and the else such as IRQ registration and MDIO initialization
what are all about to the interface of core driver moved to the
other proper place because they have no needs to register IRQ and
re-initialize structure again during the reset process.
Signed-off-by: Sean Wang <sean.wang@mediatek.com>
---
drivers/net/ethernet/mediatek/mtk_eth_soc.c | 62 ++++++++++++++++-------------
1 file changed, 34 insertions(+), 28 deletions(-)
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index 66fd45a..ca46e82 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -1415,7 +1415,12 @@ static int mtk_stop(struct net_device *dev)
static int __init mtk_hw_init(struct mtk_eth *eth)
{
- int err, i;
+ int i;
+
+ clk_prepare_enable(eth->clks[MTK_CLK_ETHIF]);
+ clk_prepare_enable(eth->clks[MTK_CLK_ESW]);
+ clk_prepare_enable(eth->clks[MTK_CLK_GP1]);
+ clk_prepare_enable(eth->clks[MTK_CLK_GP2]);
/* reset the frame engine */
reset_control_assert(eth->rstc);
@@ -1441,19 +1446,6 @@ static int __init mtk_hw_init(struct mtk_eth *eth)
/* Enable RX VLan Offloading */
mtk_w32(eth, 1, MTK_CDMP_EG_CTRL);
- err = devm_request_irq(eth->dev, eth->irq[1], mtk_handle_irq_tx, 0,
- dev_name(eth->dev), eth);
- if (err)
- return err;
- err = devm_request_irq(eth->dev, eth->irq[2], mtk_handle_irq_rx, 0,
- dev_name(eth->dev), eth);
- if (err)
- return err;
-
- err = mtk_mdio_init(eth);
- if (err)
- return err;
-
/* disable delay and normal interrupt */
mtk_w32(eth, 0, MTK_QDMA_DELAY_INT);
mtk_w32(eth, 0, MTK_PDMA_DELAY_INT);
@@ -1783,16 +1775,7 @@ static int mtk_add_mac(struct mtk_eth *eth, struct device_node *np)
eth->netdev[id]->features |= MTK_HW_FEATURES;
eth->netdev[id]->ethtool_ops = &mtk_ethtool_ops;
- err = register_netdev(eth->netdev[id]);
- if (err) {
- dev_err(eth->dev, "error bringing up device\n");
- goto free_netdev;
- }
eth->netdev[id]->irq = eth->irq[0];
- netif_info(eth, probe, eth->netdev[id],
- "mediatek frame engine at 0x%08lx, irq %d\n",
- eth->netdev[id]->base_addr, eth->irq[0]);
-
return 0;
free_netdev:
@@ -1862,11 +1845,6 @@ static int mtk_probe(struct platform_device *pdev)
}
}
- clk_prepare_enable(eth->clks[MTK_CLK_ETHIF]);
- clk_prepare_enable(eth->clks[MTK_CLK_ESW]);
- clk_prepare_enable(eth->clks[MTK_CLK_GP1]);
- clk_prepare_enable(eth->clks[MTK_CLK_GP2]);
-
eth->msg_enable = netif_msg_init(mtk_msg_level, MTK_DEFAULT_MSG_ENABLE);
INIT_WORK(ð->pending_work, mtk_pending_work);
@@ -1887,6 +1865,34 @@ static int mtk_probe(struct platform_device *pdev)
goto err_free_dev;
}
+ err = devm_request_irq(eth->dev, eth->irq[1], mtk_handle_irq_tx, 0,
+ dev_name(eth->dev), eth);
+ if (err)
+ goto err_free_dev;
+
+ err = devm_request_irq(eth->dev, eth->irq[2], mtk_handle_irq_rx, 0,
+ dev_name(eth->dev), eth);
+ if (err)
+ goto err_free_dev;
+
+ err = mtk_mdio_init(eth);
+ if (err)
+ goto err_free_dev;
+
+ for (i = 0; i < MTK_MAX_DEVS; i++) {
+ if (!eth->netdev[i])
+ continue;
+
+ err = register_netdev(eth->netdev[i]);
+ if (err) {
+ dev_err(eth->dev, "error bringing up device\n");
+ goto err_free_dev;
+ } else
+ netif_info(eth, probe, eth->netdev[i],
+ "mediatek frame engine at 0x%08lx, irq %d\n",
+ eth->netdev[i]->base_addr, eth->irq[0]);
+ }
+
/* we run 2 devices on the same DMA ring so we need a dummy device
* for NAPI to work
*/
--
1.9.1
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox