From 4769c003e0fcff0ee001a9102e2605bdaa5880f0 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Wed, 8 Aug 2018 01:07:03 -0700 Subject: [PATCH 001/302] ARM: OMAP2+: Fix null hwmod for ti-sysc debug We may call omap_hwmod_parse_module_range() with no hwmod allocated yet and may have debug enabled. Let's fix this by checking for hwmod before trying to use it's name. Fixes: 6c72b3550672 ("ARM: OMAP2+: Parse module IO range from dts for legacy Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/omap_hwmod.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index 2ceffd85dd3d..7f759abcf49c 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c @@ -2220,7 +2220,7 @@ int omap_hwmod_parse_module_range(struct omap_hwmod *oh, size = be32_to_cpup(ranges); pr_debug("omap_hwmod: %s %s at 0x%llx size 0x%llx\n", - oh->name, np->name, base, size); + oh ? oh->name : "", np->name, base, size); res->start = base; res->end = base + size - 1; From 1dbcb97c656eed1a244c960b8b3a469c3d20ce7b Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Wed, 8 Aug 2018 01:07:04 -0700 Subject: [PATCH 002/302] ARM: OMAP2+: Fix module address for modules using mpu_rt_idx If we use device tree data for a module interconnect target we want to map the control registers from the module start. Legacy hwmod platform data however is using child IP offsets for cpsw module with mpu_rt_idx. In cases where we have the interconnect target module already using device tree data with legacy hwmod platform data still around, the sysc register area is not adjusted for mpu_rt_idx causing wrong registers being accessed. Let's fix the issue for mixed dts and platform data mode by ioremapping the module registers using child IP offset if mpu_rt_idx is set. For device tree only data there's no reason to use mpu_rt_idx. Fixes: 6c72b3550672 ("ARM: OMAP2+: Parse module IO range from dts for legacy "ti,hwmods" support") Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/omap_hwmod.c | 37 ++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index 7f759abcf49c..cd65ea4e9c54 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c @@ -2160,6 +2160,37 @@ static int of_dev_hwmod_lookup(struct device_node *np, return -ENODEV; } +/** + * omap_hwmod_fix_mpu_rt_idx - fix up mpu_rt_idx register offsets + * + * @oh: struct omap_hwmod * + * @np: struct device_node * + * + * Fix up module register offsets for modules with mpu_rt_idx. + * Only needed for cpsw with interconnect target module defined + * in device tree while still using legacy hwmod platform data + * for rev, sysc and syss registers. + * + * Can be removed when all cpsw hwmod platform data has been + * dropped. + */ +static void omap_hwmod_fix_mpu_rt_idx(struct omap_hwmod *oh, + struct device_node *np, + struct resource *res) +{ + struct device_node *child = NULL; + int error; + + child = of_get_next_child(np, child); + if (!child) + return; + + error = of_address_to_resource(child, oh->mpu_rt_idx, res); + if (error) + pr_err("%s: error mapping mpu_rt_idx: %i\n", + __func__, error); +} + /** * omap_hwmod_parse_module_range - map module IO range from device tree * @oh: struct omap_hwmod * @@ -2222,6 +2253,12 @@ int omap_hwmod_parse_module_range(struct omap_hwmod *oh, pr_debug("omap_hwmod: %s %s at 0x%llx size 0x%llx\n", oh ? oh->name : "", np->name, base, size); + if (oh && oh->mpu_rt_idx) { + omap_hwmod_fix_mpu_rt_idx(oh, np, res); + + return 0; + } + res->start = base; res->end = base + size - 1; res->flags = IORESOURCE_MEM; From 0ef8e3bb974af56346b34393e643d491d9141c66 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Wed, 8 Aug 2018 01:07:05 -0700 Subject: [PATCH 003/302] bus: ti-sysc: Fix module register ioremap for larger offsets We can have the interconnect target module control registers pretty much anywhere within the module range. The current code attempts an incomplete optimization of the ioremap size but does it wrong and it only works for registers at the beginning of the module. Let's just use the largest control register to calculate the ioremap size. The ioremapped range is for most part cached anyways so there is no need for size optimization. Let's also update the comments accordingly. Fixes: 0eecc636e5a2 ("bus: ti-sysc: Add minimal TI sysc interconnect target driver") Signed-off-by: Tony Lindgren --- drivers/bus/ti-sysc.c | 29 +++++++++++++---------------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/drivers/bus/ti-sysc.c b/drivers/bus/ti-sysc.c index 80d60f43db56..b31bf03ea497 100644 --- a/drivers/bus/ti-sysc.c +++ b/drivers/bus/ti-sysc.c @@ -490,32 +490,29 @@ static int sysc_check_registers(struct sysc *ddata) /** * syc_ioremap - ioremap register space for the interconnect target module - * @ddata: deviec driver data + * @ddata: device driver data * * Note that the interconnect target module registers can be anywhere - * within the first child device address space. For example, SGX has - * them at offset 0x1fc00 in the 32MB module address space. We just - * what we need around the interconnect target module registers. + * within the interconnect target module range. For example, SGX has + * them at offset 0x1fc00 in the 32MB module address space. And cpsw + * has them at offset 0x1200 in the CPSW_WR child. Usually the + * the interconnect target module registers are at the beginning of + * the module range though. */ static int sysc_ioremap(struct sysc *ddata) { - u32 size = 0; + int size; - if (ddata->offsets[SYSC_SYSSTATUS] >= 0) - size = ddata->offsets[SYSC_SYSSTATUS]; - else if (ddata->offsets[SYSC_SYSCONFIG] >= 0) - size = ddata->offsets[SYSC_SYSCONFIG]; - else if (ddata->offsets[SYSC_REVISION] >= 0) - size = ddata->offsets[SYSC_REVISION]; - else + size = max3(ddata->offsets[SYSC_REVISION], + ddata->offsets[SYSC_SYSCONFIG], + ddata->offsets[SYSC_SYSSTATUS]); + + if (size < 0 || (size + sizeof(u32)) > ddata->module_size) return -EINVAL; - size &= 0xfff00; - size += SZ_256; - ddata->module_va = devm_ioremap(ddata->dev, ddata->module_pa, - size); + size + sizeof(u32)); if (!ddata->module_va) return -EIO; From 9c86336c15db1c48cbaddff56caf2be0a930e991 Mon Sep 17 00:00:00 2001 From: Haishuang Yan Date: Mon, 20 Aug 2018 10:51:05 +0800 Subject: [PATCH 004/302] ip6_vti: fix a null pointer deference when destroy vti6 tunnel If load ip6_vti module and create a network namespace when set fb_tunnels_only_for_init_net to 1, then exit the namespace will cause following crash: [ 6601.677036] BUG: unable to handle kernel NULL pointer dereference at 0000000000000008 [ 6601.679057] PGD 8000000425eca067 P4D 8000000425eca067 PUD 424292067 PMD 0 [ 6601.680483] Oops: 0000 [#1] SMP PTI [ 6601.681223] CPU: 7 PID: 93 Comm: kworker/u16:1 Kdump: loaded Tainted: G E 4.18.0+ #3 [ 6601.683153] Hardware name: Fedora Project OpenStack Nova, BIOS seabios-1.7.5-11.el7 04/01/2014 [ 6601.684919] Workqueue: netns cleanup_net [ 6601.685742] RIP: 0010:vti6_exit_batch_net+0x87/0xd0 [ip6_vti] [ 6601.686932] Code: 7b 08 48 89 e6 e8 b9 ea d3 dd 48 8b 1b 48 85 db 75 ec 48 83 c5 08 48 81 fd 00 01 00 00 75 d5 49 8b 84 24 08 01 00 00 48 89 e6 <48> 8b 78 08 e8 90 ea d3 dd 49 8b 45 28 49 39 c6 4c 8d 68 d8 75 a1 [ 6601.690735] RSP: 0018:ffffa897c2737de0 EFLAGS: 00010246 [ 6601.691846] RAX: 0000000000000000 RBX: 0000000000000000 RCX: dead000000000200 [ 6601.693324] RDX: 0000000000000015 RSI: ffffa897c2737de0 RDI: ffffffff9f2ea9e0 [ 6601.694824] RBP: 0000000000000100 R08: 0000000000000000 R09: 0000000000000000 [ 6601.696314] R10: 0000000000000001 R11: 0000000000000000 R12: ffff8dc323c07e00 [ 6601.697812] R13: ffff8dc324a63100 R14: ffffa897c2737e30 R15: ffffa897c2737e30 [ 6601.699345] FS: 0000000000000000(0000) GS:ffff8dc33fdc0000(0000) knlGS:0000000000000000 [ 6601.701068] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 6601.702282] CR2: 0000000000000008 CR3: 0000000424966002 CR4: 00000000001606e0 [ 6601.703791] Call Trace: [ 6601.704329] cleanup_net+0x1b4/0x2c0 [ 6601.705268] process_one_work+0x16c/0x370 [ 6601.706145] worker_thread+0x49/0x3e0 [ 6601.706942] kthread+0xf8/0x130 [ 6601.707626] ? rescuer_thread+0x340/0x340 [ 6601.708476] ? kthread_bind+0x10/0x10 [ 6601.709266] ret_from_fork+0x35/0x40 Reproduce: modprobe ip6_vti echo 1 > /proc/sys/net/core/fb_tunnels_only_for_init_net unshare -n exit This because ip6n->tnls_wc[0] point to fallback device in default, but in non-default namespace, ip6n->tnls_wc[0] will be NULL, so add the NULL check comparatively. Fixes: e2948e5af8ee ("ip6_vti: fix creating fallback tunnel device for vti6") Signed-off-by: Haishuang Yan Signed-off-by: David S. Miller --- net/ipv6/ip6_vti.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/ipv6/ip6_vti.c b/net/ipv6/ip6_vti.c index 38dec9da90d3..5095367c7204 100644 --- a/net/ipv6/ip6_vti.c +++ b/net/ipv6/ip6_vti.c @@ -1094,7 +1094,8 @@ static void __net_exit vti6_destroy_tunnels(struct vti6_net *ip6n, } t = rtnl_dereference(ip6n->tnls_wc[0]); - unregister_netdevice_queue(t->dev, list); + if (t) + unregister_netdevice_queue(t->dev, list); } static int __net_init vti6_init_net(struct net *net) From d3bc0fa8411c35194f99046157e2e26fe60e1d91 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Mon, 20 Aug 2018 13:55:45 +0200 Subject: [PATCH 005/302] fsnotify: fix false positive warning on inode delete When inode is getting deleted and someone else holds reference to a mark attached to the inode, we just detach the connector from the inode. In that case fsnotify_put_mark() called from fsnotify_destroy_marks() will decide to recalculate mask for the inode and __fsnotify_recalc_mask() will WARN about invalid connector type: WARNING: CPU: 1 PID: 12015 at fs/notify/mark.c:139 __fsnotify_recalc_mask+0x2d7/0x350 fs/notify/mark.c:139 Actually there's no reason to warn about detached connector in __fsnotify_recalc_mask() so just silently skip updating the mask in such case. Reported-by: syzbot+c34692a51b9a6ca93540@syzkaller.appspotmail.com Fixes: 3ac70bfcde81 ("fsnotify: add helper to get mask from connector") Signed-off-by: Jan Kara --- fs/notify/mark.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/fs/notify/mark.c b/fs/notify/mark.c index 05506d60131c..59cdb27826de 100644 --- a/fs/notify/mark.c +++ b/fs/notify/mark.c @@ -132,13 +132,13 @@ static void __fsnotify_recalc_mask(struct fsnotify_mark_connector *conn) struct fsnotify_mark *mark; assert_spin_locked(&conn->lock); + /* We can get detached connector here when inode is getting unlinked. */ + if (!fsnotify_valid_obj_type(conn->type)) + return; hlist_for_each_entry(mark, &conn->list, obj_list) { if (mark->flags & FSNOTIFY_MARK_FLAG_ATTACHED) new_mask |= mark->mask; } - if (WARN_ON(!fsnotify_valid_obj_type(conn->type))) - return; - *fsnotify_conn_mask_p(conn) = new_mask; } From f1506a69e3e72196c7c5ce4fd420d5e1a6965ed3 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Sat, 28 Jul 2018 16:17:49 -0300 Subject: [PATCH 006/302] thermal: qoriq: Use devm_thermal_zone_of_sensor_register() By using the managed devm_thermal_zone_of_sensor_register() we can drop the explicit call to thermal_zone_of_sensor_unregister() in the qoriq_tmu_remove() function, which simplifies the code a bit. So switch to devm_thermal_zone_of_sensor_register(). Signed-off-by: Fabio Estevam Reviewed-by: Daniel Lezcano Signed-off-by: Eduardo Valentin --- drivers/thermal/qoriq_thermal.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/thermal/qoriq_thermal.c b/drivers/thermal/qoriq_thermal.c index c866cc165960..e32d6ac79145 100644 --- a/drivers/thermal/qoriq_thermal.c +++ b/drivers/thermal/qoriq_thermal.c @@ -233,8 +233,9 @@ static int qoriq_tmu_probe(struct platform_device *pdev) if (ret < 0) goto err_tmu; - data->tz = thermal_zone_of_sensor_register(&pdev->dev, data->sensor_id, - data, &tmu_tz_ops); + data->tz = devm_thermal_zone_of_sensor_register(&pdev->dev, + data->sensor_id, + data, &tmu_tz_ops); if (IS_ERR(data->tz)) { ret = PTR_ERR(data->tz); dev_err(&pdev->dev, @@ -261,8 +262,6 @@ static int qoriq_tmu_remove(struct platform_device *pdev) { struct qoriq_tmu_data *data = platform_get_drvdata(pdev); - thermal_zone_of_sensor_unregister(&pdev->dev, data->tz); - /* Disable monitoring */ tmu_write(data, TMR_DISABLE, &data->regs->tmr); From 1a893a5a198eff228ddc1a364830f8928b8f9ac5 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Sat, 28 Jul 2018 16:17:50 -0300 Subject: [PATCH 007/302] thermal: qoriq: Simplify the 'site' variable assignment There is no need to assign zero to the variable 'site' and then perform a compound bitwise OR operation afterwards. Make it simpler by assigning the final 'site' value directly. Signed-off-by: Fabio Estevam Reviewed-by: Daniel Lezcano Signed-off-by: Eduardo Valentin --- drivers/thermal/qoriq_thermal.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/thermal/qoriq_thermal.c b/drivers/thermal/qoriq_thermal.c index e32d6ac79145..f807e4d1f72e 100644 --- a/drivers/thermal/qoriq_thermal.c +++ b/drivers/thermal/qoriq_thermal.c @@ -197,7 +197,7 @@ static int qoriq_tmu_probe(struct platform_device *pdev) int ret; struct qoriq_tmu_data *data; struct device_node *np = pdev->dev.of_node; - u32 site = 0; + u32 site; if (!np) { dev_err(&pdev->dev, "Device OF-Node is NULL"); @@ -244,7 +244,7 @@ static int qoriq_tmu_probe(struct platform_device *pdev) } /* Enable monitoring */ - site |= 0x1 << (15 - data->sensor_id); + site = 0x1 << (15 - data->sensor_id); tmu_write(data, site | TMR_ME | TMR_ALPF, &data->regs->tmr); return 0; From 2dfef650217c0e24754cd4c3abbb43e98131a7cf Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Sat, 28 Jul 2018 16:17:51 -0300 Subject: [PATCH 008/302] thermal: qoriq: Switch to SPDX identifier Adopt the SPDX license identifier headers to ease license compliance management. Signed-off-by: Fabio Estevam Reviewed-by: Daniel Lezcano Acked-by: Philippe Ombredanne Signed-off-by: Eduardo Valentin --- drivers/thermal/qoriq_thermal.c | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/drivers/thermal/qoriq_thermal.c b/drivers/thermal/qoriq_thermal.c index f807e4d1f72e..450ed66edf58 100644 --- a/drivers/thermal/qoriq_thermal.c +++ b/drivers/thermal/qoriq_thermal.c @@ -1,16 +1,6 @@ -/* - * Copyright 2016 Freescale Semiconductor, Inc. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - */ +// SPDX-License-Identifier: GPL-2.0 +// +// Copyright 2016 Freescale Semiconductor, Inc. #include #include From f00d25f3154b676fcea4502a25b94bd7f142ca74 Mon Sep 17 00:00:00 2001 From: Tomer Tayar Date: Mon, 20 Aug 2018 00:01:42 +0300 Subject: [PATCH 009/302] qed: Wait for ready indication before rereading the shmem The MFW might be reset and re-update its shared memory. Upon the detection of such a reset the driver rereads this memory, but it has to wait till the data is valid. This patch adds the missing wait for a data ready indication. Signed-off-by: Tomer Tayar Signed-off-by: Ariel Elior Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qed/qed_mcp.c | 50 +++++++++++++++++++---- 1 file changed, 41 insertions(+), 9 deletions(-) diff --git a/drivers/net/ethernet/qlogic/qed/qed_mcp.c b/drivers/net/ethernet/qlogic/qed/qed_mcp.c index d89a0e22f6e4..bdcacb31d88b 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_mcp.c +++ b/drivers/net/ethernet/qlogic/qed/qed_mcp.c @@ -183,18 +183,57 @@ int qed_mcp_free(struct qed_hwfn *p_hwfn) return 0; } +/* Maximum of 1 sec to wait for the SHMEM ready indication */ +#define QED_MCP_SHMEM_RDY_MAX_RETRIES 20 +#define QED_MCP_SHMEM_RDY_ITER_MS 50 + static int qed_load_mcp_offsets(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) { struct qed_mcp_info *p_info = p_hwfn->mcp_info; + u8 cnt = QED_MCP_SHMEM_RDY_MAX_RETRIES; + u8 msec = QED_MCP_SHMEM_RDY_ITER_MS; u32 drv_mb_offsize, mfw_mb_offsize; u32 mcp_pf_id = MCP_PF_ID(p_hwfn); p_info->public_base = qed_rd(p_hwfn, p_ptt, MISC_REG_SHARED_MEM_ADDR); - if (!p_info->public_base) - return 0; + if (!p_info->public_base) { + DP_NOTICE(p_hwfn, + "The address of the MCP scratch-pad is not configured\n"); + return -EINVAL; + } p_info->public_base |= GRCBASE_MCP; + /* Get the MFW MB address and number of supported messages */ + mfw_mb_offsize = qed_rd(p_hwfn, p_ptt, + SECTION_OFFSIZE_ADDR(p_info->public_base, + PUBLIC_MFW_MB)); + p_info->mfw_mb_addr = SECTION_ADDR(mfw_mb_offsize, mcp_pf_id); + p_info->mfw_mb_length = (u16)qed_rd(p_hwfn, p_ptt, + p_info->mfw_mb_addr + + offsetof(struct public_mfw_mb, + sup_msgs)); + + /* The driver can notify that there was an MCP reset, and might read the + * SHMEM values before the MFW has completed initializing them. + * To avoid this, the "sup_msgs" field in the MFW mailbox is used as a + * data ready indication. + */ + while (!p_info->mfw_mb_length && --cnt) { + msleep(msec); + p_info->mfw_mb_length = + (u16)qed_rd(p_hwfn, p_ptt, + p_info->mfw_mb_addr + + offsetof(struct public_mfw_mb, sup_msgs)); + } + + if (!cnt) { + DP_NOTICE(p_hwfn, + "Failed to get the SHMEM ready notification after %d msec\n", + QED_MCP_SHMEM_RDY_MAX_RETRIES * msec); + return -EBUSY; + } + /* Calculate the driver and MFW mailbox address */ drv_mb_offsize = qed_rd(p_hwfn, p_ptt, SECTION_OFFSIZE_ADDR(p_info->public_base, @@ -204,13 +243,6 @@ static int qed_load_mcp_offsets(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) "drv_mb_offsiz = 0x%x, drv_mb_addr = 0x%x mcp_pf_id = 0x%x\n", drv_mb_offsize, p_info->drv_mb_addr, mcp_pf_id); - /* Set the MFW MB address */ - mfw_mb_offsize = qed_rd(p_hwfn, p_ptt, - SECTION_OFFSIZE_ADDR(p_info->public_base, - PUBLIC_MFW_MB)); - p_info->mfw_mb_addr = SECTION_ADDR(mfw_mb_offsize, mcp_pf_id); - p_info->mfw_mb_length = (u16)qed_rd(p_hwfn, p_ptt, p_info->mfw_mb_addr); - /* Get the current driver mailbox sequence before sending * the first command */ From 76271809f49056f079e202bf6513d17b0d6dd34d Mon Sep 17 00:00:00 2001 From: Tomer Tayar Date: Mon, 20 Aug 2018 00:01:43 +0300 Subject: [PATCH 010/302] qed: Wait for MCP halt and resume commands to take place Successive iterations of halting and resuming the management chip (MCP) might fail, since currently the driver doesn't wait for these operations to actually take place. This patch prevents the driver from moving forward before the operations are reflected in the state register. Signed-off-by: Tomer Tayar Signed-off-by: Ariel Elior Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qed/qed_mcp.c | 46 +++++++++++++++---- .../net/ethernet/qlogic/qed/qed_reg_addr.h | 1 + 2 files changed, 39 insertions(+), 8 deletions(-) diff --git a/drivers/net/ethernet/qlogic/qed/qed_mcp.c b/drivers/net/ethernet/qlogic/qed/qed_mcp.c index bdcacb31d88b..5f3dbdc7ff1d 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_mcp.c +++ b/drivers/net/ethernet/qlogic/qed/qed_mcp.c @@ -2109,31 +2109,61 @@ qed_mcp_send_drv_version(struct qed_hwfn *p_hwfn, return rc; } +/* A maximal 100 msec waiting time for the MCP to halt */ +#define QED_MCP_HALT_SLEEP_MS 10 +#define QED_MCP_HALT_MAX_RETRIES 10 + int qed_mcp_halt(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) { - u32 resp = 0, param = 0; + u32 resp = 0, param = 0, cpu_state, cnt = 0; int rc; rc = qed_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_MCP_HALT, 0, &resp, ¶m); - if (rc) + if (rc) { DP_ERR(p_hwfn, "MCP response failure, aborting\n"); + return rc; + } - return rc; + do { + msleep(QED_MCP_HALT_SLEEP_MS); + cpu_state = qed_rd(p_hwfn, p_ptt, MCP_REG_CPU_STATE); + if (cpu_state & MCP_REG_CPU_STATE_SOFT_HALTED) + break; + } while (++cnt < QED_MCP_HALT_MAX_RETRIES); + + if (cnt == QED_MCP_HALT_MAX_RETRIES) { + DP_NOTICE(p_hwfn, + "Failed to halt the MCP [CPU_MODE = 0x%08x, CPU_STATE = 0x%08x]\n", + qed_rd(p_hwfn, p_ptt, MCP_REG_CPU_MODE), cpu_state); + return -EBUSY; + } + + return 0; } +#define QED_MCP_RESUME_SLEEP_MS 10 + int qed_mcp_resume(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) { - u32 value, cpu_mode; + u32 cpu_mode, cpu_state; qed_wr(p_hwfn, p_ptt, MCP_REG_CPU_STATE, 0xffffffff); - value = qed_rd(p_hwfn, p_ptt, MCP_REG_CPU_MODE); - value &= ~MCP_REG_CPU_MODE_SOFT_HALT; - qed_wr(p_hwfn, p_ptt, MCP_REG_CPU_MODE, value); cpu_mode = qed_rd(p_hwfn, p_ptt, MCP_REG_CPU_MODE); + cpu_mode &= ~MCP_REG_CPU_MODE_SOFT_HALT; + qed_wr(p_hwfn, p_ptt, MCP_REG_CPU_MODE, cpu_mode); + msleep(QED_MCP_RESUME_SLEEP_MS); + cpu_state = qed_rd(p_hwfn, p_ptt, MCP_REG_CPU_STATE); - return (cpu_mode & MCP_REG_CPU_MODE_SOFT_HALT) ? -EAGAIN : 0; + if (cpu_state & MCP_REG_CPU_STATE_SOFT_HALTED) { + DP_NOTICE(p_hwfn, + "Failed to resume the MCP [CPU_MODE = 0x%08x, CPU_STATE = 0x%08x]\n", + cpu_mode, cpu_state); + return -EBUSY; + } + + return 0; } int qed_mcp_ov_update_current_config(struct qed_hwfn *p_hwfn, diff --git a/drivers/net/ethernet/qlogic/qed/qed_reg_addr.h b/drivers/net/ethernet/qlogic/qed/qed_reg_addr.h index d8ad2dcad8d5..2279965f8f8a 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_reg_addr.h +++ b/drivers/net/ethernet/qlogic/qed/qed_reg_addr.h @@ -562,6 +562,7 @@ 0 #define MCP_REG_CPU_STATE \ 0xe05004UL +#define MCP_REG_CPU_STATE_SOFT_HALTED (0x1UL << 10) #define MCP_REG_CPU_EVENT_MASK \ 0xe05008UL #define PGLUE_B_REG_PF_BAR0_SIZE \ From eaa50fc59e5841910987e90b0438b2643041f508 Mon Sep 17 00:00:00 2001 From: Tomer Tayar Date: Mon, 20 Aug 2018 00:01:44 +0300 Subject: [PATCH 011/302] qed: Prevent a possible deadlock during driver load and unload The MFW manages an internal lock to prevent concurrent hardware (de)initialization of different PFs. This, together with the busy-waiting for the MFW's responses for commands, might lead to a deadlock during concurrent load or unload of PFs. This patch adds the option to sleep within the busy-waiting, and uses it for the (un)load requests (which are not sent from an interrupt context) to prevent the possible deadlock. Signed-off-by: Tomer Tayar Signed-off-by: Ariel Elior Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qed/qed_mcp.c | 43 ++++++++++++++++------- drivers/net/ethernet/qlogic/qed/qed_mcp.h | 21 ++++++----- 2 files changed, 44 insertions(+), 20 deletions(-) diff --git a/drivers/net/ethernet/qlogic/qed/qed_mcp.c b/drivers/net/ethernet/qlogic/qed/qed_mcp.c index 5f3dbdc7ff1d..b7279e625db3 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_mcp.c +++ b/drivers/net/ethernet/qlogic/qed/qed_mcp.c @@ -48,7 +48,7 @@ #include "qed_reg_addr.h" #include "qed_sriov.h" -#define CHIP_MCP_RESP_ITER_US 10 +#define QED_MCP_RESP_ITER_US 10 #define QED_DRV_MB_MAX_RETRIES (500 * 1000) /* Account for 5 sec */ #define QED_MCP_RESET_RETRIES (50 * 1000) /* Account for 500 msec */ @@ -317,7 +317,7 @@ static void qed_mcp_reread_offsets(struct qed_hwfn *p_hwfn, int qed_mcp_reset(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) { - u32 org_mcp_reset_seq, seq, delay = CHIP_MCP_RESP_ITER_US, cnt = 0; + u32 org_mcp_reset_seq, seq, delay = QED_MCP_RESP_ITER_US, cnt = 0; int rc = 0; /* Ensure that only a single thread is accessing the mailbox */ @@ -449,10 +449,10 @@ static int _qed_mcp_cmd_and_union(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt, struct qed_mcp_mb_params *p_mb_params, - u32 max_retries, u32 delay) + u32 max_retries, u32 usecs) { + u32 cnt = 0, msecs = DIV_ROUND_UP(usecs, 1000); struct qed_mcp_cmd_elem *p_cmd_elem; - u32 cnt = 0; u16 seq_num; int rc = 0; @@ -475,7 +475,11 @@ _qed_mcp_cmd_and_union(struct qed_hwfn *p_hwfn, goto err; spin_unlock_bh(&p_hwfn->mcp_info->cmd_lock); - udelay(delay); + + if (QED_MB_FLAGS_IS_SET(p_mb_params, CAN_SLEEP)) + msleep(msecs); + else + udelay(usecs); } while (++cnt < max_retries); if (cnt >= max_retries) { @@ -504,7 +508,11 @@ _qed_mcp_cmd_and_union(struct qed_hwfn *p_hwfn, * The spinlock stays locked until the list element is removed. */ - udelay(delay); + if (QED_MB_FLAGS_IS_SET(p_mb_params, CAN_SLEEP)) + msleep(msecs); + else + udelay(usecs); + spin_lock_bh(&p_hwfn->mcp_info->cmd_lock); if (p_cmd_elem->b_is_completed) @@ -539,7 +547,7 @@ _qed_mcp_cmd_and_union(struct qed_hwfn *p_hwfn, "MFW mailbox: response 0x%08x param 0x%08x [after %d.%03d ms]\n", p_mb_params->mcp_resp, p_mb_params->mcp_param, - (cnt * delay) / 1000, (cnt * delay) % 1000); + (cnt * usecs) / 1000, (cnt * usecs) % 1000); /* Clear the sequence number from the MFW response */ p_mb_params->mcp_resp &= FW_MSG_CODE_MASK; @@ -557,7 +565,7 @@ static int qed_mcp_cmd_and_union(struct qed_hwfn *p_hwfn, { size_t union_data_size = sizeof(union drv_union_data); u32 max_retries = QED_DRV_MB_MAX_RETRIES; - u32 delay = CHIP_MCP_RESP_ITER_US; + u32 usecs = QED_MCP_RESP_ITER_US; /* MCP not initialized */ if (!qed_mcp_is_init(p_hwfn)) { @@ -574,8 +582,13 @@ static int qed_mcp_cmd_and_union(struct qed_hwfn *p_hwfn, return -EINVAL; } + if (QED_MB_FLAGS_IS_SET(p_mb_params, CAN_SLEEP)) { + max_retries = DIV_ROUND_UP(max_retries, 1000); + usecs *= 1000; + } + return _qed_mcp_cmd_and_union(p_hwfn, p_ptt, p_mb_params, max_retries, - delay); + usecs); } int qed_mcp_cmd(struct qed_hwfn *p_hwfn, @@ -793,6 +806,7 @@ __qed_mcp_load_req(struct qed_hwfn *p_hwfn, mb_params.data_src_size = sizeof(load_req); mb_params.p_data_dst = &load_rsp; mb_params.data_dst_size = sizeof(load_rsp); + mb_params.flags = QED_MB_FLAG_CAN_SLEEP; DP_VERBOSE(p_hwfn, QED_MSG_SP, "Load Request: param 0x%08x [init_hw %d, drv_type %d, hsi_ver %d, pda 0x%04x]\n", @@ -1014,7 +1028,8 @@ int qed_mcp_load_req(struct qed_hwfn *p_hwfn, int qed_mcp_unload_req(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) { - u32 wol_param, mcp_resp, mcp_param; + struct qed_mcp_mb_params mb_params; + u32 wol_param; switch (p_hwfn->cdev->wol_config) { case QED_OV_WOL_DISABLED: @@ -1032,8 +1047,12 @@ int qed_mcp_unload_req(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) wol_param = DRV_MB_PARAM_UNLOAD_WOL_MCP; } - return qed_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_UNLOAD_REQ, wol_param, - &mcp_resp, &mcp_param); + memset(&mb_params, 0, sizeof(mb_params)); + mb_params.cmd = DRV_MSG_CODE_UNLOAD_REQ; + mb_params.param = wol_param; + mb_params.flags = QED_MB_FLAG_CAN_SLEEP; + + return qed_mcp_cmd_and_union(p_hwfn, p_ptt, &mb_params); } int qed_mcp_unload_done(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) diff --git a/drivers/net/ethernet/qlogic/qed/qed_mcp.h b/drivers/net/ethernet/qlogic/qed/qed_mcp.h index 047976d5c6e9..b9d3ecf7aad6 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_mcp.h +++ b/drivers/net/ethernet/qlogic/qed/qed_mcp.h @@ -660,14 +660,19 @@ struct qed_mcp_info { }; struct qed_mcp_mb_params { - u32 cmd; - u32 param; - void *p_data_src; - u8 data_src_size; - void *p_data_dst; - u8 data_dst_size; - u32 mcp_resp; - u32 mcp_param; + u32 cmd; + u32 param; + void *p_data_src; + void *p_data_dst; + u8 data_src_size; + u8 data_dst_size; + u32 mcp_resp; + u32 mcp_param; + u32 flags; +#define QED_MB_FLAG_CAN_SLEEP (0x1 << 0) +#define QED_MB_FLAGS_IS_SET(params, flag) \ + ({ typeof(params) __params = (params); \ + (__params && (__params->flags & QED_MB_FLAG_ ## flag)); }) }; struct qed_drv_tlv_hdr { From b310974e041913231b6e3d5d475d4df55c312301 Mon Sep 17 00:00:00 2001 From: Tomer Tayar Date: Mon, 20 Aug 2018 00:01:45 +0300 Subject: [PATCH 012/302] qed: Avoid sending mailbox commands when MFW is not responsive Keep sending mailbox commands to the MFW when it is not responsive ends up with a redundant amount of timeout expiries. This patch prints the MCP status on the first command which is not responded, and blocks the following commands. Since the (un)load request commands might be not responded due to other PFs, the patch also adds the option to skip the blocking upon a failure. Signed-off-by: Tomer Tayar Signed-off-by: Ariel Elior Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qed/qed_mcp.c | 52 ++++++++++++++++++- drivers/net/ethernet/qlogic/qed/qed_mcp.h | 6 ++- .../net/ethernet/qlogic/qed/qed_reg_addr.h | 1 + 3 files changed, 56 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/qlogic/qed/qed_mcp.c b/drivers/net/ethernet/qlogic/qed/qed_mcp.c index b7279e625db3..5d37ec7e9b0b 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_mcp.c +++ b/drivers/net/ethernet/qlogic/qed/qed_mcp.c @@ -320,6 +320,12 @@ int qed_mcp_reset(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) u32 org_mcp_reset_seq, seq, delay = QED_MCP_RESP_ITER_US, cnt = 0; int rc = 0; + if (p_hwfn->mcp_info->b_block_cmd) { + DP_NOTICE(p_hwfn, + "The MFW is not responsive. Avoid sending MCP_RESET mailbox command.\n"); + return -EBUSY; + } + /* Ensure that only a single thread is accessing the mailbox */ spin_lock_bh(&p_hwfn->mcp_info->cmd_lock); @@ -445,6 +451,33 @@ static void __qed_mcp_cmd_and_union(struct qed_hwfn *p_hwfn, (p_mb_params->cmd | seq_num), p_mb_params->param); } +static void qed_mcp_cmd_set_blocking(struct qed_hwfn *p_hwfn, bool block_cmd) +{ + p_hwfn->mcp_info->b_block_cmd = block_cmd; + + DP_INFO(p_hwfn, "%s sending of mailbox commands to the MFW\n", + block_cmd ? "Block" : "Unblock"); +} + +static void qed_mcp_print_cpu_info(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt) +{ + u32 cpu_mode, cpu_state, cpu_pc_0, cpu_pc_1, cpu_pc_2; + u32 delay = QED_MCP_RESP_ITER_US; + + cpu_mode = qed_rd(p_hwfn, p_ptt, MCP_REG_CPU_MODE); + cpu_state = qed_rd(p_hwfn, p_ptt, MCP_REG_CPU_STATE); + cpu_pc_0 = qed_rd(p_hwfn, p_ptt, MCP_REG_CPU_PROGRAM_COUNTER); + udelay(delay); + cpu_pc_1 = qed_rd(p_hwfn, p_ptt, MCP_REG_CPU_PROGRAM_COUNTER); + udelay(delay); + cpu_pc_2 = qed_rd(p_hwfn, p_ptt, MCP_REG_CPU_PROGRAM_COUNTER); + + DP_NOTICE(p_hwfn, + "MCP CPU info: mode 0x%08x, state 0x%08x, pc {0x%08x, 0x%08x, 0x%08x}\n", + cpu_mode, cpu_state, cpu_pc_0, cpu_pc_1, cpu_pc_2); +} + static int _qed_mcp_cmd_and_union(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt, @@ -531,11 +564,15 @@ _qed_mcp_cmd_and_union(struct qed_hwfn *p_hwfn, DP_NOTICE(p_hwfn, "The MFW failed to respond to command 0x%08x [param 0x%08x].\n", p_mb_params->cmd, p_mb_params->param); + qed_mcp_print_cpu_info(p_hwfn, p_ptt); spin_lock_bh(&p_hwfn->mcp_info->cmd_lock); qed_mcp_cmd_del_elem(p_hwfn, p_cmd_elem); spin_unlock_bh(&p_hwfn->mcp_info->cmd_lock); + if (!QED_MB_FLAGS_IS_SET(p_mb_params, AVOID_BLOCK)) + qed_mcp_cmd_set_blocking(p_hwfn, true); + return -EAGAIN; } @@ -573,6 +610,13 @@ static int qed_mcp_cmd_and_union(struct qed_hwfn *p_hwfn, return -EBUSY; } + if (p_hwfn->mcp_info->b_block_cmd) { + DP_NOTICE(p_hwfn, + "The MFW is not responsive. Avoid sending mailbox command 0x%08x [param 0x%08x].\n", + p_mb_params->cmd, p_mb_params->param); + return -EBUSY; + } + if (p_mb_params->data_src_size > union_data_size || p_mb_params->data_dst_size > union_data_size) { DP_ERR(p_hwfn, @@ -806,7 +850,7 @@ __qed_mcp_load_req(struct qed_hwfn *p_hwfn, mb_params.data_src_size = sizeof(load_req); mb_params.p_data_dst = &load_rsp; mb_params.data_dst_size = sizeof(load_rsp); - mb_params.flags = QED_MB_FLAG_CAN_SLEEP; + mb_params.flags = QED_MB_FLAG_CAN_SLEEP | QED_MB_FLAG_AVOID_BLOCK; DP_VERBOSE(p_hwfn, QED_MSG_SP, "Load Request: param 0x%08x [init_hw %d, drv_type %d, hsi_ver %d, pda 0x%04x]\n", @@ -1050,7 +1094,7 @@ int qed_mcp_unload_req(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) memset(&mb_params, 0, sizeof(mb_params)); mb_params.cmd = DRV_MSG_CODE_UNLOAD_REQ; mb_params.param = wol_param; - mb_params.flags = QED_MB_FLAG_CAN_SLEEP; + mb_params.flags = QED_MB_FLAG_CAN_SLEEP | QED_MB_FLAG_AVOID_BLOCK; return qed_mcp_cmd_and_union(p_hwfn, p_ptt, &mb_params); } @@ -2158,6 +2202,8 @@ int qed_mcp_halt(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) return -EBUSY; } + qed_mcp_cmd_set_blocking(p_hwfn, true); + return 0; } @@ -2182,6 +2228,8 @@ int qed_mcp_resume(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) return -EBUSY; } + qed_mcp_cmd_set_blocking(p_hwfn, false); + return 0; } diff --git a/drivers/net/ethernet/qlogic/qed/qed_mcp.h b/drivers/net/ethernet/qlogic/qed/qed_mcp.h index b9d3ecf7aad6..85e6b3989e7a 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_mcp.h +++ b/drivers/net/ethernet/qlogic/qed/qed_mcp.h @@ -635,11 +635,14 @@ struct qed_mcp_info { */ spinlock_t cmd_lock; + /* Flag to indicate whether sending a MFW mailbox command is blocked */ + bool b_block_cmd; + /* Spinlock used for syncing SW link-changes and link-changes * originating from attention context. */ spinlock_t link_lock; - bool block_mb_sending; + u32 public_base; u32 drv_mb_addr; u32 mfw_mb_addr; @@ -670,6 +673,7 @@ struct qed_mcp_mb_params { u32 mcp_param; u32 flags; #define QED_MB_FLAG_CAN_SLEEP (0x1 << 0) +#define QED_MB_FLAG_AVOID_BLOCK (0x1 << 1) #define QED_MB_FLAGS_IS_SET(params, flag) \ ({ typeof(params) __params = (params); \ (__params && (__params->flags & QED_MB_FLAG_ ## flag)); }) diff --git a/drivers/net/ethernet/qlogic/qed/qed_reg_addr.h b/drivers/net/ethernet/qlogic/qed/qed_reg_addr.h index 2279965f8f8a..f736f70956fd 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_reg_addr.h +++ b/drivers/net/ethernet/qlogic/qed/qed_reg_addr.h @@ -565,6 +565,7 @@ #define MCP_REG_CPU_STATE_SOFT_HALTED (0x1UL << 10) #define MCP_REG_CPU_EVENT_MASK \ 0xe05008UL +#define MCP_REG_CPU_PROGRAM_COUNTER 0xe0501cUL #define PGLUE_B_REG_PF_BAR0_SIZE \ 0x2aae60UL #define PGLUE_B_REG_PF_BAR1_SIZE \ From c954579087f4c0185206cfa777e697874b1e7d13 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 30 Jul 2018 07:56:06 +0000 Subject: [PATCH 013/302] thermal: rcar_thermal: convert to SPDX identifiers As original license mentioned, it is GPL-2.0 in SPDX. Then, MODULE_LICENSE() should be "GPL v2" instead of "GPL". See ${LINUX}/include/linux/module.h "GPL" [GNU Public License v2 or later] "GPL v2" [GNU Public License v2] Signed-off-by: Kuninori Morimoto Reviewed-by: Daniel Lezcano Reviewed-by: Geert Uytterhoeven Reviewed-by: Simon Horman Signed-off-by: Eduardo Valentin --- drivers/thermal/rcar_thermal.c | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/drivers/thermal/rcar_thermal.c b/drivers/thermal/rcar_thermal.c index e77e63070e99..78f932822d38 100644 --- a/drivers/thermal/rcar_thermal.c +++ b/drivers/thermal/rcar_thermal.c @@ -1,21 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0 /* * R-Car THS/TSC thermal sensor driver * * Copyright (C) 2012 Renesas Solutions Corp. * Kuninori Morimoto - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ #include #include @@ -660,6 +648,6 @@ static struct platform_driver rcar_thermal_driver = { }; module_platform_driver(rcar_thermal_driver); -MODULE_LICENSE("GPL"); +MODULE_LICENSE("GPL v2"); MODULE_DESCRIPTION("R-Car THS/TSC thermal sensor driver"); MODULE_AUTHOR("Kuninori Morimoto "); From d316522d06e9894429ace4b5f99e181bde4e7bd7 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 20 Aug 2018 11:42:35 -0700 Subject: [PATCH 014/302] thermal: rcar_gen3_thermal: convert to SPDX identifiers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Kuninori Morimoto Reviewed-by: Geert Uytterhoeven Reviewed-by: Daniel Lezcano Reviewed-by: Niklas Söderlund Reviewed-by: Simon Horman Signed-off-by: Eduardo Valentin --- drivers/thermal/rcar_gen3_thermal.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/drivers/thermal/rcar_gen3_thermal.c b/drivers/thermal/rcar_gen3_thermal.c index 766521eb7071..7aed5337bdd3 100644 --- a/drivers/thermal/rcar_gen3_thermal.c +++ b/drivers/thermal/rcar_gen3_thermal.c @@ -1,19 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0 /* * R-Car Gen3 THS thermal sensor driver * Based on rcar_thermal.c and work from Hien Dang and Khiem Nguyen. * * Copyright (C) 2016 Renesas Electronics Corporation. * Copyright (C) 2016 Sang Engineering - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * */ #include #include From 152395fd03d4ce1e535a75cdbf58105e50587611 Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Tue, 31 Jul 2018 00:56:49 +0800 Subject: [PATCH 015/302] thermal: of-thermal: disable passive polling when thermal zone is disabled When thermal zone is in passive mode, disabling its mode from sysfs is NOT taking effect at all, it is still polling the temperature of the disabled thermal zone and handling all thermal trips, it makes user confused. The disabling operation should disable the thermal zone behavior completely, for both active and passive mode, this patch clears the passive_delay when thermal zone is disabled and restores it when it is enabled. Signed-off-by: Anson Huang Signed-off-by: Eduardo Valentin --- drivers/thermal/of-thermal.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/thermal/of-thermal.c b/drivers/thermal/of-thermal.c index 977a8307fbb1..4f2816559205 100644 --- a/drivers/thermal/of-thermal.c +++ b/drivers/thermal/of-thermal.c @@ -260,10 +260,13 @@ static int of_thermal_set_mode(struct thermal_zone_device *tz, mutex_lock(&tz->lock); - if (mode == THERMAL_DEVICE_ENABLED) + if (mode == THERMAL_DEVICE_ENABLED) { tz->polling_delay = data->polling_delay; - else + tz->passive_delay = data->passive_delay; + } else { tz->polling_delay = 0; + tz->passive_delay = 0; + } mutex_unlock(&tz->lock); From 176eb614b118c96e7797f5ddefd10708c316f621 Mon Sep 17 00:00:00 2001 From: Kai-Heng Feng Date: Mon, 20 Aug 2018 12:43:51 +0800 Subject: [PATCH 016/302] r8152: disable RX aggregation on new Dell TB16 dock There's a new Dell TB16 dock with a different iSerialNumber. Apply the same fix from commit 0b1655143df0 ("r8152: disable RX aggregation on Dell TB16 dock") to this model. BugLink: https://bugs.launchpad.net/bugs/1785780 Signed-off-by: Kai-Heng Feng Signed-off-by: David S. Miller --- drivers/net/usb/r8152.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c index 97742708460b..2cd71bdb6484 100644 --- a/drivers/net/usb/r8152.c +++ b/drivers/net/usb/r8152.c @@ -5217,8 +5217,8 @@ static int rtl8152_probe(struct usb_interface *intf, netdev->hw_features &= ~NETIF_F_RXCSUM; } - if (le16_to_cpu(udev->descriptor.bcdDevice) == 0x3011 && - udev->serial && !strcmp(udev->serial, "000001000000")) { + if (le16_to_cpu(udev->descriptor.bcdDevice) == 0x3011 && udev->serial && + (!strcmp(udev->serial, "000001000000") || !strcmp(udev->serial, "000002000000"))) { dev_info(&udev->dev, "Dell TB16 Dock, disable RX aggregation"); set_bit(DELL_TB_RX_AGG_BUG, &tp->flags); } From 80f1a0f4e0cd4bfc8a74fc1c39843a6e7b206b95 Mon Sep 17 00:00:00 2001 From: David Ahern Date: Mon, 20 Aug 2018 13:02:41 -0700 Subject: [PATCH 017/302] net/ipv6: Put lwtstate when destroying fib6_info Prior to the introduction of fib6_info lwtstate was managed by the dst code. With fib6_info releasing lwtstate needs to be done when the struct is freed. Fixes: 93531c674315 ("net/ipv6: separate handling of FIB entries from dst based routes") Signed-off-by: David Ahern Signed-off-by: David S. Miller --- net/ipv6/ip6_fib.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c index d212738e9d10..c861a6d4671d 100644 --- a/net/ipv6/ip6_fib.c +++ b/net/ipv6/ip6_fib.c @@ -198,6 +198,8 @@ void fib6_info_destroy_rcu(struct rcu_head *head) } } + lwtstate_put(f6i->fib6_nh.nh_lwtstate); + if (f6i->fib6_nh.nh_dev) dev_put(f6i->fib6_nh.nh_dev); From ab08dcd724543896303eae7de6288242bbaff458 Mon Sep 17 00:00:00 2001 From: Yue Haibing Date: Tue, 21 Aug 2018 01:41:56 +0000 Subject: [PATCH 018/302] rhashtable: remove duplicated include from rhashtable.c Remove duplicated include. Signed-off-by: Yue Haibing Signed-off-by: David S. Miller --- lib/rhashtable.c | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/rhashtable.c b/lib/rhashtable.c index ae4223e0f5bc..672eecda874a 100644 --- a/lib/rhashtable.c +++ b/lib/rhashtable.c @@ -28,7 +28,6 @@ #include #include #include -#include #define HASH_DEFAULT_SIZE 64UL #define HASH_MIN_SIZE 4U From 09a4e0be5826aa66c4ce9954841f110ffe63ef4f Mon Sep 17 00:00:00 2001 From: Eric Sandeen Date: Thu, 16 Aug 2018 21:44:02 -0500 Subject: [PATCH 019/302] isofs: reject hardware sector size > 2048 bytes The largest block size supported by isofs is ISOFS_BLOCK_SIZE (2048), but isofs_fill_super calls sb_min_blocksize and sets the blocksize to the device's logical block size if it's larger than what we ended up with after option parsing. If for some reason we try to mount a hard 4k device as an isofs filesystem, we'll set opt.blocksize to 4096, and when we try to read the superblock we found via: block = iso_blknum << (ISOFS_BLOCK_BITS - s->s_blocksize_bits) with s_blocksize_bits greater than ISOFS_BLOCK_BITS, we'll have a negative shift and the bread will fail somewhat cryptically: isofs_fill_super: bread failed, dev=sda, iso_blknum=17, block=-2147483648 It seems best to just catch and clearly reject mounts of such a device. Reported-by: Bryan Gurney Signed-off-by: Eric Sandeen Signed-off-by: Jan Kara --- fs/isofs/inode.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c index ec3fba7d492f..488a9e7f8f66 100644 --- a/fs/isofs/inode.c +++ b/fs/isofs/inode.c @@ -24,6 +24,7 @@ #include #include #include +#include #include "isofs.h" #include "zisofs.h" @@ -653,6 +654,12 @@ static int isofs_fill_super(struct super_block *s, void *data, int silent) /* * What if bugger tells us to go beyond page size? */ + if (bdev_logical_block_size(s->s_bdev) > 2048) { + printk(KERN_WARNING + "ISOFS: unsupported/invalid hardware sector size %d\n", + bdev_logical_block_size(s->s_bdev)); + goto out_freesbi; + } opt.blocksize = sb_min_blocksize(s, opt.blocksize); sbi->s_high_sierra = 0; /* default is iso9660 */ From 19f5e9e015675fcdbf2c20e804b2e84e80201454 Mon Sep 17 00:00:00 2001 From: Ludovic Desroches Date: Mon, 20 Aug 2018 10:54:44 +0200 Subject: [PATCH 020/302] mmc: atmel-mci: fix bad logic of sg_copy_{from,to}_buffer conversion The conversion to sg_copy_{from,to}_buffer has been done in the wrong way. sg_copy_to_buffer is a copy from an SG list to a linear buffer so it can't replace memcpy(buf + offset, &value, remaining) where buf is the virtual address of the SG. Same for sg_copy_to_buffer but in the opposite way. Signed-off-by: Ludovic Desroches Suggested-by: Douglas Gilbert Fixes: 5b4277814e3f ("mmc: atmel-mci: use sg_copy_{from,to}_buffer") Signed-off-by: Ulf Hansson --- drivers/mmc/host/atmel-mci.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c index 5aa2c9404e92..be53044086c7 100644 --- a/drivers/mmc/host/atmel-mci.c +++ b/drivers/mmc/host/atmel-mci.c @@ -1976,7 +1976,7 @@ static void atmci_read_data_pio(struct atmel_mci *host) do { value = atmci_readl(host, ATMCI_RDR); if (likely(offset + 4 <= sg->length)) { - sg_pcopy_to_buffer(sg, 1, &value, sizeof(u32), offset); + sg_pcopy_from_buffer(sg, 1, &value, sizeof(u32), offset); offset += 4; nbytes += 4; @@ -1993,7 +1993,7 @@ static void atmci_read_data_pio(struct atmel_mci *host) } else { unsigned int remaining = sg->length - offset; - sg_pcopy_to_buffer(sg, 1, &value, remaining, offset); + sg_pcopy_from_buffer(sg, 1, &value, remaining, offset); nbytes += remaining; flush_dcache_page(sg_page(sg)); @@ -2003,7 +2003,7 @@ static void atmci_read_data_pio(struct atmel_mci *host) goto done; offset = 4 - remaining; - sg_pcopy_to_buffer(sg, 1, (u8 *)&value + remaining, + sg_pcopy_from_buffer(sg, 1, (u8 *)&value + remaining, offset, 0); nbytes += offset; } @@ -2042,7 +2042,7 @@ static void atmci_write_data_pio(struct atmel_mci *host) do { if (likely(offset + 4 <= sg->length)) { - sg_pcopy_from_buffer(sg, 1, &value, sizeof(u32), offset); + sg_pcopy_to_buffer(sg, 1, &value, sizeof(u32), offset); atmci_writel(host, ATMCI_TDR, value); offset += 4; @@ -2059,7 +2059,7 @@ static void atmci_write_data_pio(struct atmel_mci *host) unsigned int remaining = sg->length - offset; value = 0; - sg_pcopy_from_buffer(sg, 1, &value, remaining, offset); + sg_pcopy_to_buffer(sg, 1, &value, remaining, offset); nbytes += remaining; host->sg = sg = sg_next(sg); @@ -2070,7 +2070,7 @@ static void atmci_write_data_pio(struct atmel_mci *host) } offset = 4 - remaining; - sg_pcopy_from_buffer(sg, 1, (u8 *)&value + remaining, + sg_pcopy_to_buffer(sg, 1, (u8 *)&value + remaining, offset, 0); atmci_writel(host, ATMCI_TDR, value); nbytes += offset; From 17e96d8516e31c3cb52cb8e2ee79d1d2e6948c11 Mon Sep 17 00:00:00 2001 From: Ludovic Desroches Date: Mon, 20 Aug 2018 10:54:45 +0200 Subject: [PATCH 021/302] mmc: android-goldfish: fix bad logic of sg_copy_{from,to}_buffer conversion The conversion to sg_copy_{from,to}_buffer has been done in the wrong way. sg_copy_to_buffer is a copy from an SG list to a linear buffer so it can't replace memcpy(dest, host->virt_base, data->sg->length) where dest is the virtual address of the SG. Same for sg_copy_from_buffer but in the opposite way. Signed-off-by: Ludovic Desroches Suggested-by: Douglas Gilbert Fixes: 53d7e098ba08 ("mmc: android-goldfish: use sg_copy_{from,to}_buffer") Signed-off-by: Ulf Hansson --- drivers/mmc/host/android-goldfish.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/host/android-goldfish.c b/drivers/mmc/host/android-goldfish.c index 294de177632c..61e4e2a213c9 100644 --- a/drivers/mmc/host/android-goldfish.c +++ b/drivers/mmc/host/android-goldfish.c @@ -217,7 +217,7 @@ static void goldfish_mmc_xfer_done(struct goldfish_mmc_host *host, * We don't really have DMA, so we need * to copy from our platform driver buffer */ - sg_copy_to_buffer(data->sg, 1, host->virt_base, + sg_copy_from_buffer(data->sg, 1, host->virt_base, data->sg->length); } host->data->bytes_xfered += data->sg->length; @@ -393,7 +393,7 @@ static void goldfish_mmc_prepare_data(struct goldfish_mmc_host *host, * We don't really have DMA, so we need to copy to our * platform driver buffer */ - sg_copy_from_buffer(data->sg, 1, host->virt_base, + sg_copy_to_buffer(data->sg, 1, host->virt_base, data->sg->length); } } From 26caddf274cf1e89fd4ce44ab2b8dbc7a7f97681 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Tue, 21 Aug 2018 15:05:55 +0300 Subject: [PATCH 022/302] mmc: block: Fix unsupported parallel dispatch of requests The mmc block driver does not support parallel dispatch of requests. In normal circumstances, all requests are anyway funneled through a single work item, so parallel dispatch never happens. However it can happen if there is no elevator. Fix that by detecting if a dispatch is in progress and returning busy (BLK_STS_RESOURCE) in that case Fixes: 81196976ed94 ("mmc: block: Add blk-mq support") Cc: stable@vger.kernel.org # v4.16+ Signed-off-by: Adrian Hunter Signed-off-by: Ulf Hansson --- drivers/mmc/core/queue.c | 12 +++++++----- drivers/mmc/core/queue.h | 1 + 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/mmc/core/queue.c b/drivers/mmc/core/queue.c index 648eb6743ed5..6edffeed9953 100644 --- a/drivers/mmc/core/queue.c +++ b/drivers/mmc/core/queue.c @@ -238,10 +238,6 @@ static void mmc_mq_exit_request(struct blk_mq_tag_set *set, struct request *req, mmc_exit_request(mq->queue, req); } -/* - * We use BLK_MQ_F_BLOCKING and have only 1 hardware queue, which means requests - * will not be dispatched in parallel. - */ static blk_status_t mmc_mq_queue_rq(struct blk_mq_hw_ctx *hctx, const struct blk_mq_queue_data *bd) { @@ -264,7 +260,7 @@ static blk_status_t mmc_mq_queue_rq(struct blk_mq_hw_ctx *hctx, spin_lock_irq(q->queue_lock); - if (mq->recovery_needed) { + if (mq->recovery_needed || mq->busy) { spin_unlock_irq(q->queue_lock); return BLK_STS_RESOURCE; } @@ -291,6 +287,9 @@ static blk_status_t mmc_mq_queue_rq(struct blk_mq_hw_ctx *hctx, break; } + /* Parallel dispatch of requests is not supported at the moment */ + mq->busy = true; + mq->in_flight[issue_type] += 1; get_card = (mmc_tot_in_flight(mq) == 1); cqe_retune_ok = (mmc_cqe_qcnt(mq) == 1); @@ -333,9 +332,12 @@ static blk_status_t mmc_mq_queue_rq(struct blk_mq_hw_ctx *hctx, mq->in_flight[issue_type] -= 1; if (mmc_tot_in_flight(mq) == 0) put_card = true; + mq->busy = false; spin_unlock_irq(q->queue_lock); if (put_card) mmc_put_card(card, &mq->ctx); + } else { + WRITE_ONCE(mq->busy, false); } return ret; diff --git a/drivers/mmc/core/queue.h b/drivers/mmc/core/queue.h index 17e59d50b496..9bf3c9245075 100644 --- a/drivers/mmc/core/queue.h +++ b/drivers/mmc/core/queue.h @@ -81,6 +81,7 @@ struct mmc_queue { unsigned int cqe_busy; #define MMC_CQE_DCMD_BUSY BIT(0) #define MMC_CQE_QUEUE_FULL BIT(1) + bool busy; bool use_cqe; bool recovery_needed; bool in_recovery; From 51474eff2bc2777061ab3658e014a37dc9d7a775 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Tue, 14 Aug 2018 11:57:07 +0200 Subject: [PATCH 023/302] Bluetooth: Make BT_HCIUART_RTL configuration option depend on ACPI At the moment we only support ACPI enumeration for serial port attached RTL bluetooth controllers. This commit adds a dependency on ACPI to the BT_HCIUART_RTL configuration option, fixing the following warning when ACPI is not enabled: drivers/bluetooth/hci_h5.c:920:22: warning: 'rtl_vnd' defined but not used Cc: Arnd Bergmann Reported-by: Arnd Bergmann Signed-off-by: Hans de Goede Acked-by: Arnd Bergmann Acked-by: Geert Uytterhoeven Signed-off-by: Marcel Holtmann --- drivers/bluetooth/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/bluetooth/Kconfig b/drivers/bluetooth/Kconfig index 2df11cc08a46..845b0314ce3a 100644 --- a/drivers/bluetooth/Kconfig +++ b/drivers/bluetooth/Kconfig @@ -200,6 +200,7 @@ config BT_HCIUART_RTL depends on BT_HCIUART depends on BT_HCIUART_SERDEV depends on GPIOLIB + depends on ACPI select BT_HCIUART_3WIRE select BT_RTL help From addb3ffbca66954fb1d1791d2db2153c403f81af Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Tue, 14 Aug 2018 10:10:31 -0500 Subject: [PATCH 024/302] Bluetooth: mediatek: Fix memory leak In case memory resources for *fw* were allocated, release them before return. Addresses-Coverity-ID: 1472611 ("Resource leak") Fixes: 7237c4c9ec92 ("Bluetooth: mediatek: Add protocol support for MediaTek serial devices") Signed-off-by: Gustavo A. R. Silva Acked-by: Sean Wang Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btmtkuart.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/bluetooth/btmtkuart.c b/drivers/bluetooth/btmtkuart.c index ed2a5c7cb77f..4593baff2bc9 100644 --- a/drivers/bluetooth/btmtkuart.c +++ b/drivers/bluetooth/btmtkuart.c @@ -144,8 +144,10 @@ static int mtk_setup_fw(struct hci_dev *hdev) fw_size = fw->size; /* The size of patch header is 30 bytes, should be skip */ - if (fw_size < 30) - return -EINVAL; + if (fw_size < 30) { + err = -EINVAL; + goto free_fw; + } fw_size -= 30; fw_ptr += 30; @@ -172,8 +174,8 @@ static int mtk_setup_fw(struct hci_dev *hdev) fw_ptr += dlen; } +free_fw: release_firmware(fw); - return err; } From 093dee661d6004738c4cbcbf48835c1e6c6ebae3 Mon Sep 17 00:00:00 2001 From: Yue Haibing Date: Tue, 21 Aug 2018 13:58:08 +0000 Subject: [PATCH 025/302] sch_cake: Remove unused including Remove including that don't need it. Signed-off-by: Yue Haibing Signed-off-by: David S. Miller --- net/sched/sch_cake.c | 1 - 1 file changed, 1 deletion(-) diff --git a/net/sched/sch_cake.c b/net/sched/sch_cake.c index 35fc7252187c..4d26b0823cdf 100644 --- a/net/sched/sch_cake.c +++ b/net/sched/sch_cake.c @@ -64,7 +64,6 @@ #include #include #include -#include #include #include #include From c27f1e2e9f29563cb093e96261e87c1ef83aeb98 Mon Sep 17 00:00:00 2001 From: Yue Haibing Date: Tue, 21 Aug 2018 14:05:42 +0000 Subject: [PATCH 026/302] rds: tcp: remove duplicated include from tcp.c Remove duplicated include. Signed-off-by: Yue Haibing Acked-by: Sowmini Varadhan Signed-off-by: David S. Miller --- net/rds/tcp.c | 1 - 1 file changed, 1 deletion(-) diff --git a/net/rds/tcp.c b/net/rds/tcp.c index 2c7b7c352d3e..b9bbcf3d6c63 100644 --- a/net/rds/tcp.c +++ b/net/rds/tcp.c @@ -37,7 +37,6 @@ #include #include #include -#include #include #include "rds.h" From b93c1b5ac8643cc08bb74fa8ae21d6c63dfcb23d Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Tue, 21 Aug 2018 10:40:38 -0700 Subject: [PATCH 027/302] hv_netvsc: ignore devices that are not PCI Registering another device with same MAC address (such as TAP, VPN or DPDK KNI) will confuse the VF autobinding logic. Restrict the search to only run if the device is known to be a PCI attached VF. Fixes: e8ff40d4bff1 ("hv_netvsc: improve VF device matching") Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/hyperv/netvsc_drv.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c index 507f68190cb1..1121a1ec407c 100644 --- a/drivers/net/hyperv/netvsc_drv.c +++ b/drivers/net/hyperv/netvsc_drv.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -2039,12 +2040,16 @@ static int netvsc_register_vf(struct net_device *vf_netdev) { struct net_device *ndev; struct net_device_context *net_device_ctx; + struct device *pdev = vf_netdev->dev.parent; struct netvsc_device *netvsc_dev; int ret; if (vf_netdev->addr_len != ETH_ALEN) return NOTIFY_DONE; + if (!pdev || !dev_is_pci(pdev) || dev_is_pf(pdev)) + return NOTIFY_DONE; + /* * We will use the MAC address to locate the synthetic interface to * associate with the VF interface. If we don't find a matching From edfaf94fa705181eeb2fe0c36c0b902dedbd40f1 Mon Sep 17 00:00:00 2001 From: Cong Wang Date: Sun, 19 Aug 2018 12:22:05 -0700 Subject: [PATCH 028/302] net_sched: improve and refactor tcf_action_put_many() tcf_action_put_many() is mostly called to clean up actions on failure path, but tcf_action_put_many(&actions[acts_deleted]) is used in the ugliest way: it passes a slice of the array and uses an additional NULL at the end to avoid out-of-bound access. acts_deleted is completely unnecessary since we can teach tcf_action_put_many() scan the whole array and checks against NULL pointer. Which also means tcf_action_delete() should set deleted action pointers to NULL to avoid double free. Fixes: 90b73b77d08e ("net: sched: change action API to use array of pointers to actions") Cc: Jiri Pirko Cc: Vlad Buslov Signed-off-by: Cong Wang Signed-off-by: David S. Miller --- net/sched/act_api.c | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/net/sched/act_api.c b/net/sched/act_api.c index 229d63c99be2..cd69a6afcf88 100644 --- a/net/sched/act_api.c +++ b/net/sched/act_api.c @@ -686,14 +686,18 @@ static int tcf_action_put(struct tc_action *p) return __tcf_action_put(p, false); } +/* Put all actions in this array, skip those NULL's. */ static void tcf_action_put_many(struct tc_action *actions[]) { int i; - for (i = 0; i < TCA_ACT_MAX_PRIO && actions[i]; i++) { + for (i = 0; i < TCA_ACT_MAX_PRIO; i++) { struct tc_action *a = actions[i]; - const struct tc_action_ops *ops = a->ops; + const struct tc_action_ops *ops; + if (!a) + continue; + ops = a->ops; if (tcf_action_put(a)) module_put(ops->owner); } @@ -1176,7 +1180,7 @@ static int tca_action_flush(struct net *net, struct nlattr *nla, } static int tcf_action_delete(struct net *net, struct tc_action *actions[], - int *acts_deleted, struct netlink_ext_ack *extack) + struct netlink_ext_ack *extack) { u32 act_index; int ret, i; @@ -1196,20 +1200,17 @@ static int tcf_action_delete(struct net *net, struct tc_action *actions[], } else { /* now do the delete */ ret = ops->delete(net, act_index); - if (ret < 0) { - *acts_deleted = i + 1; + if (ret < 0) return ret; - } } + actions[i] = NULL; } - *acts_deleted = i; return 0; } static int tcf_del_notify(struct net *net, struct nlmsghdr *n, struct tc_action *actions[], - int *acts_deleted, u32 portid, size_t attr_size, - struct netlink_ext_ack *extack) + u32 portid, size_t attr_size, struct netlink_ext_ack *extack) { int ret; struct sk_buff *skb; @@ -1227,7 +1228,7 @@ tcf_del_notify(struct net *net, struct nlmsghdr *n, struct tc_action *actions[], } /* now do the delete */ - ret = tcf_action_delete(net, actions, acts_deleted, extack); + ret = tcf_action_delete(net, actions, extack); if (ret < 0) { NL_SET_ERR_MSG(extack, "Failed to delete TC action"); kfree_skb(skb); @@ -1249,8 +1250,7 @@ tca_action_gd(struct net *net, struct nlattr *nla, struct nlmsghdr *n, struct nlattr *tb[TCA_ACT_MAX_PRIO + 1]; struct tc_action *act; size_t attr_size = 0; - struct tc_action *actions[TCA_ACT_MAX_PRIO + 1] = {}; - int acts_deleted = 0; + struct tc_action *actions[TCA_ACT_MAX_PRIO] = {}; ret = nla_parse_nested(tb, TCA_ACT_MAX_PRIO, nla, NULL, extack); if (ret < 0) @@ -1280,14 +1280,13 @@ tca_action_gd(struct net *net, struct nlattr *nla, struct nlmsghdr *n, if (event == RTM_GETACTION) ret = tcf_get_notify(net, portid, n, actions, event, extack); else { /* delete */ - ret = tcf_del_notify(net, n, actions, &acts_deleted, portid, - attr_size, extack); + ret = tcf_del_notify(net, n, actions, portid, attr_size, extack); if (ret) goto err; - return ret; + return 0; } err: - tcf_action_put_many(&actions[acts_deleted]); + tcf_action_put_many(actions); return ret; } From 97a3f84f2c84f81b859aedd2c186df09c2ee21a6 Mon Sep 17 00:00:00 2001 From: Cong Wang Date: Sun, 19 Aug 2018 12:22:06 -0700 Subject: [PATCH 029/302] net_sched: remove unnecessary ops->delete() All ops->delete() wants is getting the tn->idrinfo, but we already have tc_action before calling ops->delete(), and tc_action has a pointer ->idrinfo. More importantly, each type of action does the same thing, that is, just calling tcf_idr_delete_index(). So it can be just removed. Fixes: b409074e6693 ("net: sched: add 'delete' function to action ops") Cc: Jiri Pirko Cc: Vlad Buslov Signed-off-by: Cong Wang Signed-off-by: David S. Miller --- include/net/act_api.h | 2 -- net/sched/act_api.c | 15 +++++++-------- net/sched/act_bpf.c | 8 -------- net/sched/act_connmark.c | 8 -------- net/sched/act_csum.c | 8 -------- net/sched/act_gact.c | 8 -------- net/sched/act_ife.c | 8 -------- net/sched/act_ipt.c | 16 ---------------- net/sched/act_mirred.c | 8 -------- net/sched/act_nat.c | 8 -------- net/sched/act_pedit.c | 8 -------- net/sched/act_police.c | 8 -------- net/sched/act_sample.c | 8 -------- net/sched/act_simple.c | 8 -------- net/sched/act_skbedit.c | 8 -------- net/sched/act_skbmod.c | 8 -------- net/sched/act_tunnel_key.c | 8 -------- net/sched/act_vlan.c | 8 -------- 18 files changed, 7 insertions(+), 146 deletions(-) diff --git a/include/net/act_api.h b/include/net/act_api.h index 1ad5b19e83a9..e32708491d83 100644 --- a/include/net/act_api.h +++ b/include/net/act_api.h @@ -102,7 +102,6 @@ struct tc_action_ops { size_t (*get_fill_size)(const struct tc_action *act); struct net_device *(*get_dev)(const struct tc_action *a); void (*put_dev)(struct net_device *dev); - int (*delete)(struct net *net, u32 index); }; struct tc_action_net { @@ -158,7 +157,6 @@ void tcf_idr_insert(struct tc_action_net *tn, struct tc_action *a); void tcf_idr_cleanup(struct tc_action_net *tn, u32 index); int tcf_idr_check_alloc(struct tc_action_net *tn, u32 *index, struct tc_action **a, int bind); -int tcf_idr_delete_index(struct tc_action_net *tn, u32 index); int __tcf_idr_release(struct tc_action *a, bool bind, bool strict); static inline int tcf_idr_release(struct tc_action *a, bool bind) diff --git a/net/sched/act_api.c b/net/sched/act_api.c index cd69a6afcf88..00bf7d2b0bdd 100644 --- a/net/sched/act_api.c +++ b/net/sched/act_api.c @@ -337,9 +337,8 @@ bool tcf_idr_check(struct tc_action_net *tn, u32 index, struct tc_action **a, } EXPORT_SYMBOL(tcf_idr_check); -int tcf_idr_delete_index(struct tc_action_net *tn, u32 index) +static int tcf_idr_delete_index(struct tcf_idrinfo *idrinfo, u32 index) { - struct tcf_idrinfo *idrinfo = tn->idrinfo; struct tc_action *p; int ret = 0; @@ -370,7 +369,6 @@ int tcf_idr_delete_index(struct tc_action_net *tn, u32 index) spin_unlock(&idrinfo->lock); return ret; } -EXPORT_SYMBOL(tcf_idr_delete_index); int tcf_idr_create(struct tc_action_net *tn, u32 index, struct nlattr *est, struct tc_action **a, const struct tc_action_ops *ops, @@ -1182,24 +1180,25 @@ static int tca_action_flush(struct net *net, struct nlattr *nla, static int tcf_action_delete(struct net *net, struct tc_action *actions[], struct netlink_ext_ack *extack) { - u32 act_index; - int ret, i; + int i; for (i = 0; i < TCA_ACT_MAX_PRIO && actions[i]; i++) { struct tc_action *a = actions[i]; const struct tc_action_ops *ops = a->ops; - /* Actions can be deleted concurrently so we must save their * type and id to search again after reference is released. */ - act_index = a->tcfa_index; + struct tcf_idrinfo *idrinfo = a->idrinfo; + u32 act_index = a->tcfa_index; if (tcf_action_put(a)) { /* last reference, action was deleted concurrently */ module_put(ops->owner); } else { + int ret; + /* now do the delete */ - ret = ops->delete(net, act_index); + ret = tcf_idr_delete_index(idrinfo, act_index); if (ret < 0) return ret; } diff --git a/net/sched/act_bpf.c b/net/sched/act_bpf.c index d30b23e42436..0c68bc9cf0b4 100644 --- a/net/sched/act_bpf.c +++ b/net/sched/act_bpf.c @@ -395,13 +395,6 @@ static int tcf_bpf_search(struct net *net, struct tc_action **a, u32 index, return tcf_idr_search(tn, a, index); } -static int tcf_bpf_delete(struct net *net, u32 index) -{ - struct tc_action_net *tn = net_generic(net, bpf_net_id); - - return tcf_idr_delete_index(tn, index); -} - static struct tc_action_ops act_bpf_ops __read_mostly = { .kind = "bpf", .type = TCA_ACT_BPF, @@ -412,7 +405,6 @@ static struct tc_action_ops act_bpf_ops __read_mostly = { .init = tcf_bpf_init, .walk = tcf_bpf_walker, .lookup = tcf_bpf_search, - .delete = tcf_bpf_delete, .size = sizeof(struct tcf_bpf), }; diff --git a/net/sched/act_connmark.c b/net/sched/act_connmark.c index 54c0bf54f2ac..6f0f273f1139 100644 --- a/net/sched/act_connmark.c +++ b/net/sched/act_connmark.c @@ -198,13 +198,6 @@ static int tcf_connmark_search(struct net *net, struct tc_action **a, u32 index, return tcf_idr_search(tn, a, index); } -static int tcf_connmark_delete(struct net *net, u32 index) -{ - struct tc_action_net *tn = net_generic(net, connmark_net_id); - - return tcf_idr_delete_index(tn, index); -} - static struct tc_action_ops act_connmark_ops = { .kind = "connmark", .type = TCA_ACT_CONNMARK, @@ -214,7 +207,6 @@ static struct tc_action_ops act_connmark_ops = { .init = tcf_connmark_init, .walk = tcf_connmark_walker, .lookup = tcf_connmark_search, - .delete = tcf_connmark_delete, .size = sizeof(struct tcf_connmark_info), }; diff --git a/net/sched/act_csum.c b/net/sched/act_csum.c index e698d3fe2080..b8a67ae3105a 100644 --- a/net/sched/act_csum.c +++ b/net/sched/act_csum.c @@ -659,13 +659,6 @@ static size_t tcf_csum_get_fill_size(const struct tc_action *act) return nla_total_size(sizeof(struct tc_csum)); } -static int tcf_csum_delete(struct net *net, u32 index) -{ - struct tc_action_net *tn = net_generic(net, csum_net_id); - - return tcf_idr_delete_index(tn, index); -} - static struct tc_action_ops act_csum_ops = { .kind = "csum", .type = TCA_ACT_CSUM, @@ -677,7 +670,6 @@ static struct tc_action_ops act_csum_ops = { .walk = tcf_csum_walker, .lookup = tcf_csum_search, .get_fill_size = tcf_csum_get_fill_size, - .delete = tcf_csum_delete, .size = sizeof(struct tcf_csum), }; diff --git a/net/sched/act_gact.c b/net/sched/act_gact.c index 6a3f25a8ffb3..cd1d9bd32ef9 100644 --- a/net/sched/act_gact.c +++ b/net/sched/act_gact.c @@ -243,13 +243,6 @@ static size_t tcf_gact_get_fill_size(const struct tc_action *act) return sz; } -static int tcf_gact_delete(struct net *net, u32 index) -{ - struct tc_action_net *tn = net_generic(net, gact_net_id); - - return tcf_idr_delete_index(tn, index); -} - static struct tc_action_ops act_gact_ops = { .kind = "gact", .type = TCA_ACT_GACT, @@ -261,7 +254,6 @@ static struct tc_action_ops act_gact_ops = { .walk = tcf_gact_walker, .lookup = tcf_gact_search, .get_fill_size = tcf_gact_get_fill_size, - .delete = tcf_gact_delete, .size = sizeof(struct tcf_gact), }; diff --git a/net/sched/act_ife.c b/net/sched/act_ife.c index d1081bdf1bdb..92fcf8ba5bca 100644 --- a/net/sched/act_ife.c +++ b/net/sched/act_ife.c @@ -853,13 +853,6 @@ static int tcf_ife_search(struct net *net, struct tc_action **a, u32 index, return tcf_idr_search(tn, a, index); } -static int tcf_ife_delete(struct net *net, u32 index) -{ - struct tc_action_net *tn = net_generic(net, ife_net_id); - - return tcf_idr_delete_index(tn, index); -} - static struct tc_action_ops act_ife_ops = { .kind = "ife", .type = TCA_ACT_IFE, @@ -870,7 +863,6 @@ static struct tc_action_ops act_ife_ops = { .init = tcf_ife_init, .walk = tcf_ife_walker, .lookup = tcf_ife_search, - .delete = tcf_ife_delete, .size = sizeof(struct tcf_ife_info), }; diff --git a/net/sched/act_ipt.c b/net/sched/act_ipt.c index 51f235bbeb5b..23273b5303fd 100644 --- a/net/sched/act_ipt.c +++ b/net/sched/act_ipt.c @@ -337,13 +337,6 @@ static int tcf_ipt_search(struct net *net, struct tc_action **a, u32 index, return tcf_idr_search(tn, a, index); } -static int tcf_ipt_delete(struct net *net, u32 index) -{ - struct tc_action_net *tn = net_generic(net, ipt_net_id); - - return tcf_idr_delete_index(tn, index); -} - static struct tc_action_ops act_ipt_ops = { .kind = "ipt", .type = TCA_ACT_IPT, @@ -354,7 +347,6 @@ static struct tc_action_ops act_ipt_ops = { .init = tcf_ipt_init, .walk = tcf_ipt_walker, .lookup = tcf_ipt_search, - .delete = tcf_ipt_delete, .size = sizeof(struct tcf_ipt), }; @@ -395,13 +387,6 @@ static int tcf_xt_search(struct net *net, struct tc_action **a, u32 index, return tcf_idr_search(tn, a, index); } -static int tcf_xt_delete(struct net *net, u32 index) -{ - struct tc_action_net *tn = net_generic(net, xt_net_id); - - return tcf_idr_delete_index(tn, index); -} - static struct tc_action_ops act_xt_ops = { .kind = "xt", .type = TCA_ACT_XT, @@ -412,7 +397,6 @@ static struct tc_action_ops act_xt_ops = { .init = tcf_xt_init, .walk = tcf_xt_walker, .lookup = tcf_xt_search, - .delete = tcf_xt_delete, .size = sizeof(struct tcf_ipt), }; diff --git a/net/sched/act_mirred.c b/net/sched/act_mirred.c index 38fd20f10f67..8bf66d0a6800 100644 --- a/net/sched/act_mirred.c +++ b/net/sched/act_mirred.c @@ -395,13 +395,6 @@ static void tcf_mirred_put_dev(struct net_device *dev) dev_put(dev); } -static int tcf_mirred_delete(struct net *net, u32 index) -{ - struct tc_action_net *tn = net_generic(net, mirred_net_id); - - return tcf_idr_delete_index(tn, index); -} - static struct tc_action_ops act_mirred_ops = { .kind = "mirred", .type = TCA_ACT_MIRRED, @@ -416,7 +409,6 @@ static struct tc_action_ops act_mirred_ops = { .size = sizeof(struct tcf_mirred), .get_dev = tcf_mirred_get_dev, .put_dev = tcf_mirred_put_dev, - .delete = tcf_mirred_delete, }; static __net_init int mirred_init_net(struct net *net) diff --git a/net/sched/act_nat.c b/net/sched/act_nat.c index 822e903bfc25..4313aa102440 100644 --- a/net/sched/act_nat.c +++ b/net/sched/act_nat.c @@ -300,13 +300,6 @@ static int tcf_nat_search(struct net *net, struct tc_action **a, u32 index, return tcf_idr_search(tn, a, index); } -static int tcf_nat_delete(struct net *net, u32 index) -{ - struct tc_action_net *tn = net_generic(net, nat_net_id); - - return tcf_idr_delete_index(tn, index); -} - static struct tc_action_ops act_nat_ops = { .kind = "nat", .type = TCA_ACT_NAT, @@ -316,7 +309,6 @@ static struct tc_action_ops act_nat_ops = { .init = tcf_nat_init, .walk = tcf_nat_walker, .lookup = tcf_nat_search, - .delete = tcf_nat_delete, .size = sizeof(struct tcf_nat), }; diff --git a/net/sched/act_pedit.c b/net/sched/act_pedit.c index 8a7a7cb94e83..107034070019 100644 --- a/net/sched/act_pedit.c +++ b/net/sched/act_pedit.c @@ -460,13 +460,6 @@ static int tcf_pedit_search(struct net *net, struct tc_action **a, u32 index, return tcf_idr_search(tn, a, index); } -static int tcf_pedit_delete(struct net *net, u32 index) -{ - struct tc_action_net *tn = net_generic(net, pedit_net_id); - - return tcf_idr_delete_index(tn, index); -} - static struct tc_action_ops act_pedit_ops = { .kind = "pedit", .type = TCA_ACT_PEDIT, @@ -477,7 +470,6 @@ static struct tc_action_ops act_pedit_ops = { .init = tcf_pedit_init, .walk = tcf_pedit_walker, .lookup = tcf_pedit_search, - .delete = tcf_pedit_delete, .size = sizeof(struct tcf_pedit), }; diff --git a/net/sched/act_police.c b/net/sched/act_police.c index 06f0742db593..5d8bfa878477 100644 --- a/net/sched/act_police.c +++ b/net/sched/act_police.c @@ -320,13 +320,6 @@ static int tcf_police_search(struct net *net, struct tc_action **a, u32 index, return tcf_idr_search(tn, a, index); } -static int tcf_police_delete(struct net *net, u32 index) -{ - struct tc_action_net *tn = net_generic(net, police_net_id); - - return tcf_idr_delete_index(tn, index); -} - MODULE_AUTHOR("Alexey Kuznetsov"); MODULE_DESCRIPTION("Policing actions"); MODULE_LICENSE("GPL"); @@ -340,7 +333,6 @@ static struct tc_action_ops act_police_ops = { .init = tcf_police_init, .walk = tcf_police_walker, .lookup = tcf_police_search, - .delete = tcf_police_delete, .size = sizeof(struct tcf_police), }; diff --git a/net/sched/act_sample.c b/net/sched/act_sample.c index 207b4132d1b0..44e9c00657bc 100644 --- a/net/sched/act_sample.c +++ b/net/sched/act_sample.c @@ -232,13 +232,6 @@ static int tcf_sample_search(struct net *net, struct tc_action **a, u32 index, return tcf_idr_search(tn, a, index); } -static int tcf_sample_delete(struct net *net, u32 index) -{ - struct tc_action_net *tn = net_generic(net, sample_net_id); - - return tcf_idr_delete_index(tn, index); -} - static struct tc_action_ops act_sample_ops = { .kind = "sample", .type = TCA_ACT_SAMPLE, @@ -249,7 +242,6 @@ static struct tc_action_ops act_sample_ops = { .cleanup = tcf_sample_cleanup, .walk = tcf_sample_walker, .lookup = tcf_sample_search, - .delete = tcf_sample_delete, .size = sizeof(struct tcf_sample), }; diff --git a/net/sched/act_simple.c b/net/sched/act_simple.c index e616523ba3c1..52400d49f81f 100644 --- a/net/sched/act_simple.c +++ b/net/sched/act_simple.c @@ -196,13 +196,6 @@ static int tcf_simp_search(struct net *net, struct tc_action **a, u32 index, return tcf_idr_search(tn, a, index); } -static int tcf_simp_delete(struct net *net, u32 index) -{ - struct tc_action_net *tn = net_generic(net, simp_net_id); - - return tcf_idr_delete_index(tn, index); -} - static struct tc_action_ops act_simp_ops = { .kind = "simple", .type = TCA_ACT_SIMP, @@ -213,7 +206,6 @@ static struct tc_action_ops act_simp_ops = { .init = tcf_simp_init, .walk = tcf_simp_walker, .lookup = tcf_simp_search, - .delete = tcf_simp_delete, .size = sizeof(struct tcf_defact), }; diff --git a/net/sched/act_skbedit.c b/net/sched/act_skbedit.c index 926d7bc4a89d..73e44ce2a883 100644 --- a/net/sched/act_skbedit.c +++ b/net/sched/act_skbedit.c @@ -299,13 +299,6 @@ static int tcf_skbedit_search(struct net *net, struct tc_action **a, u32 index, return tcf_idr_search(tn, a, index); } -static int tcf_skbedit_delete(struct net *net, u32 index) -{ - struct tc_action_net *tn = net_generic(net, skbedit_net_id); - - return tcf_idr_delete_index(tn, index); -} - static struct tc_action_ops act_skbedit_ops = { .kind = "skbedit", .type = TCA_ACT_SKBEDIT, @@ -316,7 +309,6 @@ static struct tc_action_ops act_skbedit_ops = { .cleanup = tcf_skbedit_cleanup, .walk = tcf_skbedit_walker, .lookup = tcf_skbedit_search, - .delete = tcf_skbedit_delete, .size = sizeof(struct tcf_skbedit), }; diff --git a/net/sched/act_skbmod.c b/net/sched/act_skbmod.c index d6a1af0c4171..588077fafd6c 100644 --- a/net/sched/act_skbmod.c +++ b/net/sched/act_skbmod.c @@ -259,13 +259,6 @@ static int tcf_skbmod_search(struct net *net, struct tc_action **a, u32 index, return tcf_idr_search(tn, a, index); } -static int tcf_skbmod_delete(struct net *net, u32 index) -{ - struct tc_action_net *tn = net_generic(net, skbmod_net_id); - - return tcf_idr_delete_index(tn, index); -} - static struct tc_action_ops act_skbmod_ops = { .kind = "skbmod", .type = TCA_ACT_SKBMOD, @@ -276,7 +269,6 @@ static struct tc_action_ops act_skbmod_ops = { .cleanup = tcf_skbmod_cleanup, .walk = tcf_skbmod_walker, .lookup = tcf_skbmod_search, - .delete = tcf_skbmod_delete, .size = sizeof(struct tcf_skbmod), }; diff --git a/net/sched/act_tunnel_key.c b/net/sched/act_tunnel_key.c index 8f09cf08d8fe..420759153d5f 100644 --- a/net/sched/act_tunnel_key.c +++ b/net/sched/act_tunnel_key.c @@ -548,13 +548,6 @@ static int tunnel_key_search(struct net *net, struct tc_action **a, u32 index, return tcf_idr_search(tn, a, index); } -static int tunnel_key_delete(struct net *net, u32 index) -{ - struct tc_action_net *tn = net_generic(net, tunnel_key_net_id); - - return tcf_idr_delete_index(tn, index); -} - static struct tc_action_ops act_tunnel_key_ops = { .kind = "tunnel_key", .type = TCA_ACT_TUNNEL_KEY, @@ -565,7 +558,6 @@ static struct tc_action_ops act_tunnel_key_ops = { .cleanup = tunnel_key_release, .walk = tunnel_key_walker, .lookup = tunnel_key_search, - .delete = tunnel_key_delete, .size = sizeof(struct tcf_tunnel_key), }; diff --git a/net/sched/act_vlan.c b/net/sched/act_vlan.c index 209e70ad2c09..033d273afe50 100644 --- a/net/sched/act_vlan.c +++ b/net/sched/act_vlan.c @@ -296,13 +296,6 @@ static int tcf_vlan_search(struct net *net, struct tc_action **a, u32 index, return tcf_idr_search(tn, a, index); } -static int tcf_vlan_delete(struct net *net, u32 index) -{ - struct tc_action_net *tn = net_generic(net, vlan_net_id); - - return tcf_idr_delete_index(tn, index); -} - static struct tc_action_ops act_vlan_ops = { .kind = "vlan", .type = TCA_ACT_VLAN, @@ -313,7 +306,6 @@ static struct tc_action_ops act_vlan_ops = { .cleanup = tcf_vlan_cleanup, .walk = tcf_vlan_walker, .lookup = tcf_vlan_search, - .delete = tcf_vlan_delete, .size = sizeof(struct tcf_vlan), }; From b144e7ec51a132eac00a68bf897b6349d810022f Mon Sep 17 00:00:00 2001 From: Cong Wang Date: Sun, 19 Aug 2018 12:22:07 -0700 Subject: [PATCH 030/302] net_sched: remove unused parameter for tcf_action_delete() Fixes: 16af6067392c ("net: sched: implement reference counted action release") Cc: Jiri Pirko Cc: Vlad Buslov Signed-off-by: Cong Wang Signed-off-by: David S. Miller --- net/sched/act_api.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/net/sched/act_api.c b/net/sched/act_api.c index 00bf7d2b0bdd..ba55226928a3 100644 --- a/net/sched/act_api.c +++ b/net/sched/act_api.c @@ -1177,8 +1177,7 @@ static int tca_action_flush(struct net *net, struct nlattr *nla, return err; } -static int tcf_action_delete(struct net *net, struct tc_action *actions[], - struct netlink_ext_ack *extack) +static int tcf_action_delete(struct net *net, struct tc_action *actions[]) { int i; @@ -1227,7 +1226,7 @@ tcf_del_notify(struct net *net, struct nlmsghdr *n, struct tc_action *actions[], } /* now do the delete */ - ret = tcf_action_delete(net, actions, extack); + ret = tcf_action_delete(net, actions); if (ret < 0) { NL_SET_ERR_MSG(extack, "Failed to delete TC action"); kfree_skb(skb); From 7d485c451fc82f8ae431cdb379521bc6d0641064 Mon Sep 17 00:00:00 2001 From: Cong Wang Date: Sun, 19 Aug 2018 12:22:08 -0700 Subject: [PATCH 031/302] net_sched: remove unused tcf_idr_check() tcf_idr_check() is replaced by tcf_idr_check_alloc(), and __tcf_idr_check() now can be folded into tcf_idr_search(). Fixes: 0190c1d452a9 ("net: sched: atomically check-allocate action") Cc: Jiri Pirko Cc: Vlad Buslov Signed-off-by: Cong Wang Signed-off-by: David S. Miller --- include/net/act_api.h | 2 -- net/sched/act_api.c | 22 +++------------------- 2 files changed, 3 insertions(+), 21 deletions(-) diff --git a/include/net/act_api.h b/include/net/act_api.h index e32708491d83..eaa0e8b93d5b 100644 --- a/include/net/act_api.h +++ b/include/net/act_api.h @@ -147,8 +147,6 @@ int tcf_generic_walker(struct tc_action_net *tn, struct sk_buff *skb, const struct tc_action_ops *ops, struct netlink_ext_ack *extack); int tcf_idr_search(struct tc_action_net *tn, struct tc_action **a, u32 index); -bool tcf_idr_check(struct tc_action_net *tn, u32 index, struct tc_action **a, - int bind); int tcf_idr_create(struct tc_action_net *tn, u32 index, struct nlattr *est, struct tc_action **a, const struct tc_action_ops *ops, int bind, bool cpustats); diff --git a/net/sched/act_api.c b/net/sched/act_api.c index ba55226928a3..d76948f02a02 100644 --- a/net/sched/act_api.c +++ b/net/sched/act_api.c @@ -300,21 +300,17 @@ int tcf_generic_walker(struct tc_action_net *tn, struct sk_buff *skb, } EXPORT_SYMBOL(tcf_generic_walker); -static bool __tcf_idr_check(struct tc_action_net *tn, u32 index, - struct tc_action **a, int bind) +int tcf_idr_search(struct tc_action_net *tn, struct tc_action **a, u32 index) { struct tcf_idrinfo *idrinfo = tn->idrinfo; struct tc_action *p; spin_lock(&idrinfo->lock); p = idr_find(&idrinfo->action_idr, index); - if (IS_ERR(p)) { + if (IS_ERR(p)) p = NULL; - } else if (p) { + else if (p) refcount_inc(&p->tcfa_refcnt); - if (bind) - atomic_inc(&p->tcfa_bindcnt); - } spin_unlock(&idrinfo->lock); if (p) { @@ -323,20 +319,8 @@ static bool __tcf_idr_check(struct tc_action_net *tn, u32 index, } return false; } - -int tcf_idr_search(struct tc_action_net *tn, struct tc_action **a, u32 index) -{ - return __tcf_idr_check(tn, index, a, 0); -} EXPORT_SYMBOL(tcf_idr_search); -bool tcf_idr_check(struct tc_action_net *tn, u32 index, struct tc_action **a, - int bind) -{ - return __tcf_idr_check(tn, index, a, bind); -} -EXPORT_SYMBOL(tcf_idr_check); - static int tcf_idr_delete_index(struct tcf_idrinfo *idrinfo, u32 index) { struct tc_action *p; From 244cd96adb5f5ab39551081fb1f9009a54bb12ee Mon Sep 17 00:00:00 2001 From: Cong Wang Date: Sun, 19 Aug 2018 12:22:09 -0700 Subject: [PATCH 032/302] net_sched: remove list_head from tc_action After commit 90b73b77d08e, list_head is no longer needed. Now we just need to convert the list iteration to array iteration for drivers. Fixes: 90b73b77d08e ("net: sched: change action API to use array of pointers to actions") Cc: Jiri Pirko Cc: Vlad Buslov Signed-off-by: Cong Wang Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c | 6 ++--- .../ethernet/chelsio/cxgb4/cxgb4_tc_flower.c | 10 +++----- .../net/ethernet/chelsio/cxgb4/cxgb4_tc_u32.c | 5 ++-- drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 6 ++--- .../net/ethernet/mellanox/mlx5/core/en_tc.c | 19 +++++++------- .../net/ethernet/mellanox/mlxsw/spectrum.c | 3 +-- .../ethernet/mellanox/mlxsw/spectrum_flower.c | 6 ++--- .../ethernet/netronome/nfp/flower/action.c | 6 ++--- .../net/ethernet/qlogic/qede/qede_filter.c | 6 ++--- .../net/ethernet/stmicro/stmmac/stmmac_tc.c | 5 ++-- include/net/act_api.h | 1 - include/net/pkt_cls.h | 25 +++++++++++-------- net/dsa/slave.c | 4 +-- net/sched/act_api.c | 1 - 14 files changed, 43 insertions(+), 60 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c index 139d96c5a023..092c817f8f11 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c @@ -110,16 +110,14 @@ static int bnxt_tc_parse_actions(struct bnxt *bp, struct tcf_exts *tc_exts) { const struct tc_action *tc_act; - LIST_HEAD(tc_actions); - int rc; + int i, rc; if (!tcf_exts_has_actions(tc_exts)) { netdev_info(bp->dev, "no actions"); return -EINVAL; } - tcf_exts_to_list(tc_exts, &tc_actions); - list_for_each_entry(tc_act, &tc_actions, list) { + tcf_exts_for_each_action(i, tc_act, tc_exts) { /* Drop action */ if (is_tcf_gact_shot(tc_act)) { actions->flags |= BNXT_TC_ACTION_FLAG_DROP; diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c index 623f73dd7738..c116f96956fe 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c @@ -417,10 +417,9 @@ static void cxgb4_process_flow_actions(struct net_device *in, struct ch_filter_specification *fs) { const struct tc_action *a; - LIST_HEAD(actions); + int i; - tcf_exts_to_list(cls->exts, &actions); - list_for_each_entry(a, &actions, list) { + tcf_exts_for_each_action(i, a, cls->exts) { if (is_tcf_gact_ok(a)) { fs->action = FILTER_PASS; } else if (is_tcf_gact_shot(a)) { @@ -591,10 +590,9 @@ static int cxgb4_validate_flow_actions(struct net_device *dev, bool act_redir = false; bool act_pedit = false; bool act_vlan = false; - LIST_HEAD(actions); + int i; - tcf_exts_to_list(cls->exts, &actions); - list_for_each_entry(a, &actions, list) { + tcf_exts_for_each_action(i, a, cls->exts) { if (is_tcf_gact_ok(a)) { /* Do nothing */ } else if (is_tcf_gact_shot(a)) { diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_u32.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_u32.c index 18eb2aedd4cb..c7d2b4dc7568 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_u32.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_u32.c @@ -93,14 +93,13 @@ static int fill_action_fields(struct adapter *adap, unsigned int num_actions = 0; const struct tc_action *a; struct tcf_exts *exts; - LIST_HEAD(actions); + int i; exts = cls->knode.exts; if (!tcf_exts_has_actions(exts)) return -EINVAL; - tcf_exts_to_list(exts, &actions); - list_for_each_entry(a, &actions, list) { + tcf_exts_for_each_action(i, a, exts) { /* Don't allow more than one action per rule. */ if (num_actions) return -EINVAL; diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index 447098005490..af4c9ae7f432 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -9171,14 +9171,12 @@ static int parse_tc_actions(struct ixgbe_adapter *adapter, struct tcf_exts *exts, u64 *action, u8 *queue) { const struct tc_action *a; - LIST_HEAD(actions); + int i; if (!tcf_exts_has_actions(exts)) return -EINVAL; - tcf_exts_to_list(exts, &actions); - list_for_each_entry(a, &actions, list) { - + tcf_exts_for_each_action(i, a, exts) { /* Drop action */ if (is_tcf_gact_shot(a)) { *action = IXGBE_FDIR_DROP_QUEUE; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c index 9131a1376e7d..9fed54017659 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c @@ -1982,14 +1982,15 @@ static bool modify_header_match_supported(struct mlx5_flow_spec *spec, goto out_ok; modify_ip_header = false; - tcf_exts_to_list(exts, &actions); - list_for_each_entry(a, &actions, list) { + tcf_exts_for_each_action(i, a, exts) { + int k; + if (!is_tcf_pedit(a)) continue; nkeys = tcf_pedit_nkeys(a); - for (i = 0; i < nkeys; i++) { - htype = tcf_pedit_htype(a, i); + for (k = 0; k < nkeys; k++) { + htype = tcf_pedit_htype(a, k); if (htype == TCA_PEDIT_KEY_EX_HDR_TYPE_IP4 || htype == TCA_PEDIT_KEY_EX_HDR_TYPE_IP6) { modify_ip_header = true; @@ -2053,15 +2054,14 @@ static int parse_tc_nic_actions(struct mlx5e_priv *priv, struct tcf_exts *exts, const struct tc_action *a; LIST_HEAD(actions); u32 action = 0; - int err; + int err, i; if (!tcf_exts_has_actions(exts)) return -EINVAL; attr->flow_tag = MLX5_FS_DEFAULT_FLOW_TAG; - tcf_exts_to_list(exts, &actions); - list_for_each_entry(a, &actions, list) { + tcf_exts_for_each_action(i, a, exts) { if (is_tcf_gact_shot(a)) { action |= MLX5_FLOW_CONTEXT_ACTION_DROP; if (MLX5_CAP_FLOWTABLE(priv->mdev, @@ -2666,7 +2666,7 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv, struct tcf_exts *exts, LIST_HEAD(actions); bool encap = false; u32 action = 0; - int err; + int err, i; if (!tcf_exts_has_actions(exts)) return -EINVAL; @@ -2674,8 +2674,7 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv, struct tcf_exts *exts, attr->in_rep = rpriv->rep; attr->in_mdev = priv->mdev; - tcf_exts_to_list(exts, &actions); - list_for_each_entry(a, &actions, list) { + tcf_exts_for_each_action(i, a, exts) { if (is_tcf_gact_shot(a)) { action |= MLX5_FLOW_CONTEXT_ACTION_DROP | MLX5_FLOW_CONTEXT_ACTION_COUNT; diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index 6070d1591d1e..930700413b1d 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -1346,8 +1346,7 @@ static int mlxsw_sp_port_add_cls_matchall(struct mlxsw_sp_port *mlxsw_sp_port, return -ENOMEM; mall_tc_entry->cookie = f->cookie; - tcf_exts_to_list(f->exts, &actions); - a = list_first_entry(&actions, struct tc_action, list); + a = tcf_exts_first_action(f->exts); if (is_tcf_mirred_egress_mirror(a) && protocol == htons(ETH_P_ALL)) { struct mlxsw_sp_port_mall_mirror_tc_entry *mirror; diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c index ebd1b24ebaa5..8d211972c5e9 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c @@ -21,8 +21,7 @@ static int mlxsw_sp_flower_parse_actions(struct mlxsw_sp *mlxsw_sp, struct netlink_ext_ack *extack) { const struct tc_action *a; - LIST_HEAD(actions); - int err; + int err, i; if (!tcf_exts_has_actions(exts)) return 0; @@ -32,8 +31,7 @@ static int mlxsw_sp_flower_parse_actions(struct mlxsw_sp *mlxsw_sp, if (err) return err; - tcf_exts_to_list(exts, &actions); - list_for_each_entry(a, &actions, list) { + tcf_exts_for_each_action(i, a, exts) { if (is_tcf_gact_ok(a)) { err = mlxsw_sp_acl_rulei_act_terminate(rulei); if (err) { diff --git a/drivers/net/ethernet/netronome/nfp/flower/action.c b/drivers/net/ethernet/netronome/nfp/flower/action.c index 0ba0356ec4e6..9044496803e6 100644 --- a/drivers/net/ethernet/netronome/nfp/flower/action.c +++ b/drivers/net/ethernet/netronome/nfp/flower/action.c @@ -796,11 +796,10 @@ int nfp_flower_compile_action(struct nfp_app *app, struct net_device *netdev, struct nfp_fl_payload *nfp_flow) { - int act_len, act_cnt, err, tun_out_cnt, out_cnt; + int act_len, act_cnt, err, tun_out_cnt, out_cnt, i; enum nfp_flower_tun_type tun_type; const struct tc_action *a; u32 csum_updated = 0; - LIST_HEAD(actions); memset(nfp_flow->action_data, 0, NFP_FL_MAX_A_SIZ); nfp_flow->meta.act_len = 0; @@ -810,8 +809,7 @@ int nfp_flower_compile_action(struct nfp_app *app, tun_out_cnt = 0; out_cnt = 0; - tcf_exts_to_list(flow->exts, &actions); - list_for_each_entry(a, &actions, list) { + tcf_exts_for_each_action(i, a, flow->exts) { err = nfp_flower_loop_action(app, a, flow, nfp_flow, &act_len, netdev, &tun_type, &tun_out_cnt, &out_cnt, &csum_updated); diff --git a/drivers/net/ethernet/qlogic/qede/qede_filter.c b/drivers/net/ethernet/qlogic/qede/qede_filter.c index 9673d19308e6..b16ce7d93caf 100644 --- a/drivers/net/ethernet/qlogic/qede/qede_filter.c +++ b/drivers/net/ethernet/qlogic/qede/qede_filter.c @@ -2006,18 +2006,16 @@ int qede_get_arfs_filter_count(struct qede_dev *edev) static int qede_parse_actions(struct qede_dev *edev, struct tcf_exts *exts) { - int rc = -EINVAL, num_act = 0; + int rc = -EINVAL, num_act = 0, i; const struct tc_action *a; bool is_drop = false; - LIST_HEAD(actions); if (!tcf_exts_has_actions(exts)) { DP_NOTICE(edev, "No tc actions received\n"); return rc; } - tcf_exts_to_list(exts, &actions); - list_for_each_entry(a, &actions, list) { + tcf_exts_for_each_action(i, a, exts) { num_act++; if (is_tcf_gact_shot(a)) diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c index 1a96dd9c1091..531294f4978b 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c @@ -61,7 +61,7 @@ static int tc_fill_actions(struct stmmac_tc_entry *entry, struct stmmac_tc_entry *action_entry = entry; const struct tc_action *act; struct tcf_exts *exts; - LIST_HEAD(actions); + int i; exts = cls->knode.exts; if (!tcf_exts_has_actions(exts)) @@ -69,8 +69,7 @@ static int tc_fill_actions(struct stmmac_tc_entry *entry, if (frag) action_entry = frag; - tcf_exts_to_list(exts, &actions); - list_for_each_entry(act, &actions, list) { + tcf_exts_for_each_action(i, act, exts) { /* Accept */ if (is_tcf_gact_ok(act)) { action_entry->val.af = 1; diff --git a/include/net/act_api.h b/include/net/act_api.h index eaa0e8b93d5b..f9c4b871af88 100644 --- a/include/net/act_api.h +++ b/include/net/act_api.h @@ -23,7 +23,6 @@ struct tc_action { const struct tc_action_ops *ops; __u32 type; /* for backward compat(TCA_OLD_COMPAT) */ __u32 order; - struct list_head list; struct tcf_idrinfo *idrinfo; u32 tcfa_index; diff --git a/include/net/pkt_cls.h b/include/net/pkt_cls.h index ef727f71336e..c17d51865469 100644 --- a/include/net/pkt_cls.h +++ b/include/net/pkt_cls.h @@ -298,19 +298,13 @@ static inline void tcf_exts_put_net(struct tcf_exts *exts) #endif } -static inline void tcf_exts_to_list(const struct tcf_exts *exts, - struct list_head *actions) -{ #ifdef CONFIG_NET_CLS_ACT - int i; - - for (i = 0; i < exts->nr_actions; i++) { - struct tc_action *a = exts->actions[i]; - - list_add_tail(&a->list, actions); - } +#define tcf_exts_for_each_action(i, a, exts) \ + for (i = 0; i < TCA_ACT_MAX_PRIO && ((a) = (exts)->actions[i]); i++) +#else +#define tcf_exts_for_each_action(i, a, exts) \ + for (; 0; ) #endif -} static inline void tcf_exts_stats_update(const struct tcf_exts *exts, @@ -361,6 +355,15 @@ static inline bool tcf_exts_has_one_action(struct tcf_exts *exts) #endif } +static inline struct tc_action *tcf_exts_first_action(struct tcf_exts *exts) +{ +#ifdef CONFIG_NET_CLS_ACT + return exts->actions[0]; +#else + return NULL; +#endif +} + /** * tcf_exts_exec - execute tc filter extensions * @skb: socket buffer diff --git a/net/dsa/slave.c b/net/dsa/slave.c index 962c4fd338ba..1c45c1d6d241 100644 --- a/net/dsa/slave.c +++ b/net/dsa/slave.c @@ -767,7 +767,6 @@ static int dsa_slave_add_cls_matchall(struct net_device *dev, const struct tc_action *a; struct dsa_port *to_dp; int err = -EOPNOTSUPP; - LIST_HEAD(actions); if (!ds->ops->port_mirror_add) return err; @@ -775,8 +774,7 @@ static int dsa_slave_add_cls_matchall(struct net_device *dev, if (!tcf_exts_has_one_action(cls->exts)) return err; - tcf_exts_to_list(cls->exts, &actions); - a = list_first_entry(&actions, struct tc_action, list); + a = tcf_exts_first_action(cls->exts); if (is_tcf_mirred_egress_mirror(a) && protocol == htons(ETH_P_ALL)) { struct dsa_mall_mirror_tc_entry *mirror; diff --git a/net/sched/act_api.c b/net/sched/act_api.c index d76948f02a02..db83dac1e7f4 100644 --- a/net/sched/act_api.c +++ b/net/sched/act_api.c @@ -391,7 +391,6 @@ int tcf_idr_create(struct tc_action_net *tn, u32 index, struct nlattr *est, p->idrinfo = idrinfo; p->ops = ops; - INIT_LIST_HEAD(&p->list); *a = p; return 0; err3: From a0c2e90fe131d9a7440ac05c9c31fc35dfac2fa8 Mon Sep 17 00:00:00 2001 From: Cong Wang Date: Sun, 19 Aug 2018 12:22:10 -0700 Subject: [PATCH 033/302] net_sched: remove unused tcfa_capab Cc: Jamal Hadi Salim Signed-off-by: Cong Wang Signed-off-by: David S. Miller --- include/net/act_api.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/include/net/act_api.h b/include/net/act_api.h index f9c4b871af88..970303448c90 100644 --- a/include/net/act_api.h +++ b/include/net/act_api.h @@ -28,7 +28,6 @@ struct tc_action { u32 tcfa_index; refcount_t tcfa_refcnt; atomic_t tcfa_bindcnt; - u32 tcfa_capab; int tcfa_action; struct tcf_t tcfa_tm; struct gnet_stats_basic_packed tcfa_bstats; @@ -43,7 +42,6 @@ struct tc_action { #define tcf_index common.tcfa_index #define tcf_refcnt common.tcfa_refcnt #define tcf_bindcnt common.tcfa_bindcnt -#define tcf_capab common.tcfa_capab #define tcf_action common.tcfa_action #define tcf_tm common.tcfa_tm #define tcf_bstats common.tcfa_bstats From 8ce5be1c899d31f3cd047e5f707cd9dbfb81e076 Mon Sep 17 00:00:00 2001 From: Cong Wang Date: Sun, 19 Aug 2018 12:22:11 -0700 Subject: [PATCH 034/302] Revert "net: sched: act_ife: disable bh when taking ife_mod_lock" This reverts commit 42c625a486f3 ("net: sched: act_ife: disable bh when taking ife_mod_lock"), because what ife_mod_lock protects is absolutely not touched in rate est timer BH context, they have no race. A better fix is following up. Cc: Vlad Buslov Cc: Jamal Hadi Salim Signed-off-by: Cong Wang Signed-off-by: David S. Miller --- net/sched/act_ife.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/net/sched/act_ife.c b/net/sched/act_ife.c index 92fcf8ba5bca..9decbb74b3ac 100644 --- a/net/sched/act_ife.c +++ b/net/sched/act_ife.c @@ -167,16 +167,16 @@ static struct tcf_meta_ops *find_ife_oplist(u16 metaid) { struct tcf_meta_ops *o; - read_lock_bh(&ife_mod_lock); + read_lock(&ife_mod_lock); list_for_each_entry(o, &ifeoplist, list) { if (o->metaid == metaid) { if (!try_module_get(o->owner)) o = NULL; - read_unlock_bh(&ife_mod_lock); + read_unlock(&ife_mod_lock); return o; } } - read_unlock_bh(&ife_mod_lock); + read_unlock(&ife_mod_lock); return NULL; } @@ -190,12 +190,12 @@ int register_ife_op(struct tcf_meta_ops *mops) !mops->get || !mops->alloc) return -EINVAL; - write_lock_bh(&ife_mod_lock); + write_lock(&ife_mod_lock); list_for_each_entry(m, &ifeoplist, list) { if (m->metaid == mops->metaid || (strcmp(mops->name, m->name) == 0)) { - write_unlock_bh(&ife_mod_lock); + write_unlock(&ife_mod_lock); return -EEXIST; } } @@ -204,7 +204,7 @@ int register_ife_op(struct tcf_meta_ops *mops) mops->release = ife_release_meta_gen; list_add_tail(&mops->list, &ifeoplist); - write_unlock_bh(&ife_mod_lock); + write_unlock(&ife_mod_lock); return 0; } EXPORT_SYMBOL_GPL(unregister_ife_op); @@ -214,7 +214,7 @@ int unregister_ife_op(struct tcf_meta_ops *mops) struct tcf_meta_ops *m; int err = -ENOENT; - write_lock_bh(&ife_mod_lock); + write_lock(&ife_mod_lock); list_for_each_entry(m, &ifeoplist, list) { if (m->metaid == mops->metaid) { list_del(&mops->list); @@ -222,7 +222,7 @@ int unregister_ife_op(struct tcf_meta_ops *mops) break; } } - write_unlock_bh(&ife_mod_lock); + write_unlock(&ife_mod_lock); return err; } @@ -343,13 +343,13 @@ static int use_all_metadata(struct tcf_ife_info *ife) int rc = 0; int installed = 0; - read_lock_bh(&ife_mod_lock); + read_lock(&ife_mod_lock); list_for_each_entry(o, &ifeoplist, list) { rc = add_metainfo(ife, o->metaid, NULL, 0, true); if (rc == 0) installed += 1; } - read_unlock_bh(&ife_mod_lock); + read_unlock(&ife_mod_lock); if (installed) return 0; From 4e407ff5cd67ec76eeeea1deec227b7982dc7f66 Mon Sep 17 00:00:00 2001 From: Cong Wang Date: Sun, 19 Aug 2018 12:22:12 -0700 Subject: [PATCH 035/302] act_ife: move tcfa_lock down to where necessary The only time we need to take tcfa_lock is when adding a new metainfo to an existing ife->metalist. We don't need to take tcfa_lock so early and so broadly in tcf_ife_init(). This means we can always take ife_mod_lock first, avoid the reverse locking ordering warning as reported by Vlad. Reported-by: Vlad Buslov Tested-by: Vlad Buslov Cc: Vlad Buslov Cc: Jamal Hadi Salim Signed-off-by: Cong Wang Signed-off-by: David S. Miller --- net/sched/act_ife.c | 38 +++++++++++++------------------------- 1 file changed, 13 insertions(+), 25 deletions(-) diff --git a/net/sched/act_ife.c b/net/sched/act_ife.c index 9decbb74b3ac..244a8cf48183 100644 --- a/net/sched/act_ife.c +++ b/net/sched/act_ife.c @@ -265,11 +265,8 @@ static const char *ife_meta_id2name(u32 metaid) #endif /* called when adding new meta information - * under ife->tcf_lock for existing action */ -static int load_metaops_and_vet(struct tcf_ife_info *ife, u32 metaid, - void *val, int len, bool exists, - bool rtnl_held) +static int load_metaops_and_vet(u32 metaid, void *val, int len, bool rtnl_held) { struct tcf_meta_ops *ops = find_ife_oplist(metaid); int ret = 0; @@ -277,15 +274,11 @@ static int load_metaops_and_vet(struct tcf_ife_info *ife, u32 metaid, if (!ops) { ret = -ENOENT; #ifdef CONFIG_MODULES - if (exists) - spin_unlock_bh(&ife->tcf_lock); if (rtnl_held) rtnl_unlock(); request_module("ife-meta-%s", ife_meta_id2name(metaid)); if (rtnl_held) rtnl_lock(); - if (exists) - spin_lock_bh(&ife->tcf_lock); ops = find_ife_oplist(metaid); #endif } @@ -302,10 +295,9 @@ static int load_metaops_and_vet(struct tcf_ife_info *ife, u32 metaid, } /* called when adding new meta information - * under ife->tcf_lock for existing action */ static int add_metainfo(struct tcf_ife_info *ife, u32 metaid, void *metaval, - int len, bool atomic) + int len, bool atomic, bool exists) { struct tcf_meta_info *mi = NULL; struct tcf_meta_ops *ops = find_ife_oplist(metaid); @@ -332,12 +324,16 @@ static int add_metainfo(struct tcf_ife_info *ife, u32 metaid, void *metaval, } } + if (exists) + spin_lock_bh(&ife->tcf_lock); list_add_tail(&mi->metalist, &ife->metalist); + if (exists) + spin_unlock_bh(&ife->tcf_lock); return ret; } -static int use_all_metadata(struct tcf_ife_info *ife) +static int use_all_metadata(struct tcf_ife_info *ife, bool exists) { struct tcf_meta_ops *o; int rc = 0; @@ -345,7 +341,7 @@ static int use_all_metadata(struct tcf_ife_info *ife) read_lock(&ife_mod_lock); list_for_each_entry(o, &ifeoplist, list) { - rc = add_metainfo(ife, o->metaid, NULL, 0, true); + rc = add_metainfo(ife, o->metaid, NULL, 0, true, exists); if (rc == 0) installed += 1; } @@ -422,7 +418,6 @@ static void tcf_ife_cleanup(struct tc_action *a) kfree_rcu(p, rcu); } -/* under ife->tcf_lock for existing action */ static int populate_metalist(struct tcf_ife_info *ife, struct nlattr **tb, bool exists, bool rtnl_held) { @@ -436,12 +431,11 @@ static int populate_metalist(struct tcf_ife_info *ife, struct nlattr **tb, val = nla_data(tb[i]); len = nla_len(tb[i]); - rc = load_metaops_and_vet(ife, i, val, len, exists, - rtnl_held); + rc = load_metaops_and_vet(i, val, len, rtnl_held); if (rc != 0) return rc; - rc = add_metainfo(ife, i, val, len, exists); + rc = add_metainfo(ife, i, val, len, false, exists); if (rc) return rc; } @@ -540,8 +534,6 @@ static int tcf_ife_init(struct net *net, struct nlattr *nla, p->eth_type = ife_type; } - if (exists) - spin_lock_bh(&ife->tcf_lock); if (ret == ACT_P_CREATED) INIT_LIST_HEAD(&ife->metalist); @@ -551,10 +543,7 @@ static int tcf_ife_init(struct net *net, struct nlattr *nla, NULL, NULL); if (err) { metadata_parse_err: - if (exists) - spin_unlock_bh(&ife->tcf_lock); tcf_idr_release(*a, bind); - kfree(p); return err; } @@ -569,17 +558,16 @@ static int tcf_ife_init(struct net *net, struct nlattr *nla, * as we can. You better have at least one else we are * going to bail out */ - err = use_all_metadata(ife); + err = use_all_metadata(ife, exists); if (err) { - if (exists) - spin_unlock_bh(&ife->tcf_lock); tcf_idr_release(*a, bind); - kfree(p); return err; } } + if (exists) + spin_lock_bh(&ife->tcf_lock); ife->tcf_action = parm->action; /* protected by tcf_lock when modifying existing action */ rcu_swap_protected(ife->params, p, 1); From 5ffe57da29b3802baeddaa40909682bbb4cb4d48 Mon Sep 17 00:00:00 2001 From: Cong Wang Date: Sun, 19 Aug 2018 12:22:13 -0700 Subject: [PATCH 036/302] act_ife: fix a potential deadlock use_all_metadata() acquires read_lock(&ife_mod_lock), then calls add_metainfo() which calls find_ife_oplist() which acquires the same lock again. Deadlock! Introduce __add_metainfo() which accepts struct tcf_meta_ops *ops as an additional parameter and let its callers to decide how to find it. For use_all_metadata(), it already has ops, no need to find it again, just call __add_metainfo() directly. And, as ife_mod_lock is only needed for find_ife_oplist(), this means we can make non-atomic allocation for populate_metalist() now. Fixes: 817e9f2c5c26 ("act_ife: acquire ife_mod_lock before reading ifeoplist") Cc: Jamal Hadi Salim Signed-off-by: Cong Wang Signed-off-by: David S. Miller --- net/sched/act_ife.c | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/net/sched/act_ife.c b/net/sched/act_ife.c index 244a8cf48183..196430aefe87 100644 --- a/net/sched/act_ife.c +++ b/net/sched/act_ife.c @@ -296,22 +296,16 @@ static int load_metaops_and_vet(u32 metaid, void *val, int len, bool rtnl_held) /* called when adding new meta information */ -static int add_metainfo(struct tcf_ife_info *ife, u32 metaid, void *metaval, - int len, bool atomic, bool exists) +static int __add_metainfo(const struct tcf_meta_ops *ops, + struct tcf_ife_info *ife, u32 metaid, void *metaval, + int len, bool atomic, bool exists) { struct tcf_meta_info *mi = NULL; - struct tcf_meta_ops *ops = find_ife_oplist(metaid); int ret = 0; - if (!ops) - return -ENOENT; - mi = kzalloc(sizeof(*mi), atomic ? GFP_ATOMIC : GFP_KERNEL); - if (!mi) { - /*put back what find_ife_oplist took */ - module_put(ops->owner); + if (!mi) return -ENOMEM; - } mi->metaid = metaid; mi->ops = ops; @@ -319,7 +313,6 @@ static int add_metainfo(struct tcf_ife_info *ife, u32 metaid, void *metaval, ret = ops->alloc(mi, metaval, atomic ? GFP_ATOMIC : GFP_KERNEL); if (ret != 0) { kfree(mi); - module_put(ops->owner); return ret; } } @@ -333,6 +326,21 @@ static int add_metainfo(struct tcf_ife_info *ife, u32 metaid, void *metaval, return ret; } +static int add_metainfo(struct tcf_ife_info *ife, u32 metaid, void *metaval, + int len, bool exists) +{ + const struct tcf_meta_ops *ops = find_ife_oplist(metaid); + int ret; + + if (!ops) + return -ENOENT; + ret = __add_metainfo(ops, ife, metaid, metaval, len, false, exists); + if (ret) + /*put back what find_ife_oplist took */ + module_put(ops->owner); + return ret; +} + static int use_all_metadata(struct tcf_ife_info *ife, bool exists) { struct tcf_meta_ops *o; @@ -341,7 +349,7 @@ static int use_all_metadata(struct tcf_ife_info *ife, bool exists) read_lock(&ife_mod_lock); list_for_each_entry(o, &ifeoplist, list) { - rc = add_metainfo(ife, o->metaid, NULL, 0, true, exists); + rc = __add_metainfo(o, ife, o->metaid, NULL, 0, true, exists); if (rc == 0) installed += 1; } @@ -435,7 +443,7 @@ static int populate_metalist(struct tcf_ife_info *ife, struct nlattr **tb, if (rc != 0) return rc; - rc = add_metainfo(ife, i, val, len, false, exists); + rc = add_metainfo(ife, i, val, len, exists); if (rc) return rc; } From 96c26e04581667e3cd17ed74c2fc3499afea49b8 Mon Sep 17 00:00:00 2001 From: Prashant Bhole Date: Mon, 20 Aug 2018 09:54:25 +0900 Subject: [PATCH 037/302] xsk: fix return value of xdp_umem_assign_dev() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit s/ENOTSUPP/EOPNOTSUPP/ in function umem_assign_dev(). This function's return value is directly returned by xsk_bind(). EOPNOTSUPP is bind()'s possible return value. Fixes: f734607e819b ("xsk: refactor xdp_umem_assign_dev()") Signed-off-by: Prashant Bhole Acked-by: Song Liu Acked-by: Björn Töpel Signed-off-by: Daniel Borkmann --- net/xdp/xdp_umem.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/xdp/xdp_umem.c b/net/xdp/xdp_umem.c index 911ca6d3cb5a..bfe2dbea480b 100644 --- a/net/xdp/xdp_umem.c +++ b/net/xdp/xdp_umem.c @@ -74,14 +74,14 @@ int xdp_umem_assign_dev(struct xdp_umem *umem, struct net_device *dev, return 0; if (!dev->netdev_ops->ndo_bpf || !dev->netdev_ops->ndo_xsk_async_xmit) - return force_zc ? -ENOTSUPP : 0; /* fail or fallback */ + return force_zc ? -EOPNOTSUPP : 0; /* fail or fallback */ bpf.command = XDP_QUERY_XSK_UMEM; rtnl_lock(); err = xdp_umem_query(dev, queue_id); if (err) { - err = err < 0 ? -ENOTSUPP : -EBUSY; + err = err < 0 ? -EOPNOTSUPP : -EBUSY; goto err_rtnl_unlock; } From 4f3530f4a41d49c41015020cd9a5ed5c95b5d2db Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Wed, 8 Aug 2018 01:07:06 -0700 Subject: [PATCH 038/302] bus: ti-sysc: Fix no_console_suspend handling If no_console_suspend is set, we should keep console enabled during suspend. Lets fix this by only producing a warning if we can't idle hardware during suspend. Fixes: ef55f8215a78 ("bus: ti-sysc: Improve suspend and resume handling") Signed-off-by: Tony Lindgren --- drivers/bus/ti-sysc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/bus/ti-sysc.c b/drivers/bus/ti-sysc.c index b31bf03ea497..4576a1268e0e 100644 --- a/drivers/bus/ti-sysc.c +++ b/drivers/bus/ti-sysc.c @@ -1175,10 +1175,10 @@ static int sysc_child_suspend_noirq(struct device *dev) if (!pm_runtime_status_suspended(dev)) { error = pm_generic_runtime_suspend(dev); if (error) { - dev_err(dev, "%s error at %i: %i\n", - __func__, __LINE__, error); + dev_warn(dev, "%s busy at %i: %i\n", + __func__, __LINE__, error); - return error; + return 0; } error = sysc_runtime_suspend(ddata->dev); From f4efa74c09a7eddcc12cd13208f78743763f6e7a Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Wed, 1 Aug 2018 22:28:21 +0200 Subject: [PATCH 039/302] ARM: dts: omap4-droid4: fix vibrations on Droid 4 Vibration GPIOs don't have anything to do with wakeup. Move it to normal section; this fixes vibrations on Droid 4. Fixes: a5effd968301 ("ARM: dts: omap4-droid4: Add vibrator") Signed-off-by: Pavel Machek Reviewed-by: Sebastian Reichel Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/omap4-droid4-xt894.dts | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/arch/arm/boot/dts/omap4-droid4-xt894.dts b/arch/arm/boot/dts/omap4-droid4-xt894.dts index e7c3c563ff8f..edc97f89fae4 100644 --- a/arch/arm/boot/dts/omap4-droid4-xt894.dts +++ b/arch/arm/boot/dts/omap4-droid4-xt894.dts @@ -618,15 +618,6 @@ OMAP4_IOPAD(0x10a, PIN_INPUT | MUX_MODE1) /* abe_mcbsp3_clkx */ OMAP4_IOPAD(0x10c, PIN_INPUT | MUX_MODE1) /* abe_mcbsp3_fsx */ >; }; -}; - -&omap4_pmx_wkup { - usb_gpio_mux_sel2: pinmux_usb_gpio_mux_sel2_pins { - /* gpio_wk0 */ - pinctrl-single,pins = < - OMAP4_IOPAD(0x040, PIN_OUTPUT_PULLDOWN | MUX_MODE3) - >; - }; vibrator_direction_pin: pinmux_vibrator_direction_pin { pinctrl-single,pins = < @@ -641,6 +632,15 @@ OMAP4_IOPAD(0X1d0, PIN_OUTPUT | MUX_MODE1) /* dmtimer9_pwm_evt (gpio_28) */ }; }; +&omap4_pmx_wkup { + usb_gpio_mux_sel2: pinmux_usb_gpio_mux_sel2_pins { + /* gpio_wk0 */ + pinctrl-single,pins = < + OMAP4_IOPAD(0x040, PIN_OUTPUT_PULLDOWN | MUX_MODE3) + >; + }; +}; + /* * As uart1 is wired to mdm6600 with rts and cts, we can use the cts pin for * uart1 wakeirq. From ce32d59ee2cd036f6e8a6ed17a06a0b0bec5c67c Mon Sep 17 00:00:00 2001 From: Keerthy Date: Wed, 25 Jul 2018 11:25:35 +0530 Subject: [PATCH 040/302] arm: dts: am4372: setup rtc as system-power-controller RTC alarm2 is connected to pmic_en line and hence can be used to control the pmic enabling/disabling. Hence add the system-power-controller for rtc node. Signed-off-by: Keerthy Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/am4372.dtsi | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/boot/dts/am4372.dtsi b/arch/arm/boot/dts/am4372.dtsi index f0cbd86312dc..d4b7c59eec68 100644 --- a/arch/arm/boot/dts/am4372.dtsi +++ b/arch/arm/boot/dts/am4372.dtsi @@ -469,6 +469,7 @@ rtc: rtc@44e3e000 { ti,hwmods = "rtc"; clocks = <&clk_32768_ck>; clock-names = "int-clk"; + system-power-controller; status = "disabled"; }; From 64d9d13828c6c8e188bba63794eee923df3d69a9 Mon Sep 17 00:00:00 2001 From: Jeremy Cline Date: Tue, 31 Jul 2018 01:37:30 +0000 Subject: [PATCH 041/302] fs/quota: Replace XQM_MAXQUOTAS usage with MAXQUOTAS XQM_MAXQUOTAS and MAXQUOTAS are, it appears, equivalent. Replace all usage of XQM_MAXQUOTAS and remove it along with the unused XQM_*QUOTA definitions. Signed-off-by: Jeremy Cline Signed-off-by: Jan Kara --- fs/quota/quota.c | 12 +++++------- include/linux/quota.h | 8 +------- 2 files changed, 6 insertions(+), 14 deletions(-) diff --git a/fs/quota/quota.c b/fs/quota/quota.c index 860bfbe7a07a..d403392d8a0f 100644 --- a/fs/quota/quota.c +++ b/fs/quota/quota.c @@ -120,8 +120,6 @@ static int quota_getinfo(struct super_block *sb, int type, void __user *addr) struct if_dqinfo uinfo; int ret; - /* This checks whether qc_state has enough entries... */ - BUILD_BUG_ON(MAXQUOTAS > XQM_MAXQUOTAS); if (!sb->s_qcop->get_state) return -ENOSYS; ret = sb->s_qcop->get_state(sb, &state); @@ -354,10 +352,10 @@ static int quota_getstate(struct super_block *sb, struct fs_quota_stat *fqs) * GETXSTATE quotactl has space for just one set of time limits so * report them for the first enabled quota type */ - for (type = 0; type < XQM_MAXQUOTAS; type++) + for (type = 0; type < MAXQUOTAS; type++) if (state.s_state[type].flags & QCI_ACCT_ENABLED) break; - BUG_ON(type == XQM_MAXQUOTAS); + BUG_ON(type == MAXQUOTAS); fqs->qs_btimelimit = state.s_state[type].spc_timelimit; fqs->qs_itimelimit = state.s_state[type].ino_timelimit; fqs->qs_rtbtimelimit = state.s_state[type].rt_spc_timelimit; @@ -427,10 +425,10 @@ static int quota_getstatev(struct super_block *sb, struct fs_quota_statv *fqs) * GETXSTATV quotactl has space for just one set of time limits so * report them for the first enabled quota type */ - for (type = 0; type < XQM_MAXQUOTAS; type++) + for (type = 0; type < MAXQUOTAS; type++) if (state.s_state[type].flags & QCI_ACCT_ENABLED) break; - BUG_ON(type == XQM_MAXQUOTAS); + BUG_ON(type == MAXQUOTAS); fqs->qs_btimelimit = state.s_state[type].spc_timelimit; fqs->qs_itimelimit = state.s_state[type].ino_timelimit; fqs->qs_rtbtimelimit = state.s_state[type].rt_spc_timelimit; @@ -701,7 +699,7 @@ static int do_quotactl(struct super_block *sb, int type, int cmd, qid_t id, { int ret; - if (type >= (XQM_COMMAND(cmd) ? XQM_MAXQUOTAS : MAXQUOTAS)) + if (type >= MAXQUOTAS) return -EINVAL; /* * Quota not supported on this fs? Check this before s_quota_types diff --git a/include/linux/quota.h b/include/linux/quota.h index ca9772c8e48b..f32dd270b8e3 100644 --- a/include/linux/quota.h +++ b/include/linux/quota.h @@ -408,13 +408,7 @@ struct qc_type_state { struct qc_state { unsigned int s_incoredqs; /* Number of dquots in core */ - /* - * Per quota type information. The array should really have - * max(MAXQUOTAS, XQM_MAXQUOTAS) entries. BUILD_BUG_ON in - * quota_getinfo() makes sure XQM_MAXQUOTAS is large enough. Once VFS - * supports project quotas, this can be changed to MAXQUOTAS - */ - struct qc_type_state s_state[XQM_MAXQUOTAS]; + struct qc_type_state s_state[MAXQUOTAS]; /* Per quota type information */ }; /* Structure for communicating via ->set_info */ From 7b6924d94a60c6b8c1279ca003e8744e6cd9e8b1 Mon Sep 17 00:00:00 2001 From: Jeremy Cline Date: Tue, 31 Jul 2018 01:37:31 +0000 Subject: [PATCH 042/302] fs/quota: Fix spectre gadget in do_quotactl 'type' is user-controlled, so sanitize it after the bounds check to avoid using it in speculative execution. This covers the following potential gadgets detected with the help of smatch: * fs/ext4/super.c:5741 ext4_quota_read() warn: potential spectre issue 'sb_dqopt(sb)->files' [r] * fs/ext4/super.c:5778 ext4_quota_write() warn: potential spectre issue 'sb_dqopt(sb)->files' [r] * fs/f2fs/super.c:1552 f2fs_quota_read() warn: potential spectre issue 'sb_dqopt(sb)->files' [r] * fs/f2fs/super.c:1608 f2fs_quota_write() warn: potential spectre issue 'sb_dqopt(sb)->files' [r] * fs/quota/dquot.c:412 mark_info_dirty() warn: potential spectre issue 'sb_dqopt(sb)->info' [w] * fs/quota/dquot.c:933 dqinit_needed() warn: potential spectre issue 'dquots' [r] * fs/quota/dquot.c:2112 dquot_commit_info() warn: potential spectre issue 'dqopt->ops' [r] * fs/quota/dquot.c:2362 vfs_load_quota_inode() warn: potential spectre issue 'dqopt->files' [w] (local cap) * fs/quota/dquot.c:2369 vfs_load_quota_inode() warn: potential spectre issue 'dqopt->ops' [w] (local cap) * fs/quota/dquot.c:2370 vfs_load_quota_inode() warn: potential spectre issue 'dqopt->info' [w] (local cap) * fs/quota/quota.c:110 quota_getfmt() warn: potential spectre issue 'sb_dqopt(sb)->info' [r] * fs/quota/quota_v2.c:84 v2_check_quota_file() warn: potential spectre issue 'quota_magics' [w] * fs/quota/quota_v2.c:85 v2_check_quota_file() warn: potential spectre issue 'quota_versions' [w] * fs/quota/quota_v2.c:96 v2_read_file_info() warn: potential spectre issue 'dqopt->info' [r] * fs/quota/quota_v2.c:172 v2_write_file_info() warn: potential spectre issue 'dqopt->info' [r] Additionally, a quick inspection indicates there are array accesses with 'type' in quota_on() and quota_off() functions which are also addressed by this. Cc: Josh Poimboeuf Cc: stable@vger.kernel.org Signed-off-by: Jeremy Cline Signed-off-by: Jan Kara --- fs/quota/quota.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fs/quota/quota.c b/fs/quota/quota.c index d403392d8a0f..f0cbf58ad4da 100644 --- a/fs/quota/quota.c +++ b/fs/quota/quota.c @@ -18,6 +18,7 @@ #include #include #include +#include static int check_quotactl_permission(struct super_block *sb, int type, int cmd, qid_t id) @@ -701,6 +702,7 @@ static int do_quotactl(struct super_block *sb, int type, int cmd, qid_t id, if (type >= MAXQUOTAS) return -EINVAL; + type = array_index_nospec(type, MAXQUOTAS); /* * Quota not supported on this fs? Check this before s_quota_types * since they needn't be set if quota is not supported at all. From b845c898b2f1ea458d5453f0fa1da6e2dfce3bb4 Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Tue, 21 Aug 2018 15:55:00 +0200 Subject: [PATCH 043/302] bpf, sockmap: fix sock_hash_alloc and reject zero-sized keys Currently, it is possible to create a sock hash map with key size of 0 and have the kernel return a fd back to user space. This is invalid for hash maps (and kernel also hasn't been tested for zero key size support in general at this point). Thus, reject such configuration. Fixes: 81110384441a ("bpf: sockmap, add hash map support") Signed-off-by: Daniel Borkmann Acked-by: John Fastabend Acked-by: Song Liu --- kernel/bpf/sockmap.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/kernel/bpf/sockmap.c b/kernel/bpf/sockmap.c index 98e621a29e8e..60ceb0e1fa56 100644 --- a/kernel/bpf/sockmap.c +++ b/kernel/bpf/sockmap.c @@ -2140,7 +2140,9 @@ static struct bpf_map *sock_hash_alloc(union bpf_attr *attr) return ERR_PTR(-EPERM); /* check sanity of attributes */ - if (attr->max_entries == 0 || attr->value_size != 4 || + if (attr->max_entries == 0 || + attr->key_size == 0 || + attr->value_size != 4 || attr->map_flags & ~SOCK_CREATE_FLAG_MASK) return ERR_PTR(-EINVAL); From eb29429d81e31b191f3b2bd19cf820279cec6463 Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Wed, 22 Aug 2018 18:09:17 +0200 Subject: [PATCH 044/302] bpf, sockmap: fix sock hash count in alloc_sock_hash_elem When we try to allocate a new sock hash entry and the allocation fails, then sock hash map fails to reduce the map element counter, meaning we keep accounting this element although it was never used. Fix it by dropping the element counter on error. Fixes: 81110384441a ("bpf: sockmap, add hash map support") Signed-off-by: Daniel Borkmann Acked-by: John Fastabend --- kernel/bpf/sockmap.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/kernel/bpf/sockmap.c b/kernel/bpf/sockmap.c index 60ceb0e1fa56..40c6ef9fc828 100644 --- a/kernel/bpf/sockmap.c +++ b/kernel/bpf/sockmap.c @@ -2269,8 +2269,10 @@ static struct htab_elem *alloc_sock_hash_elem(struct bpf_htab *htab, } l_new = kmalloc_node(htab->elem_size, GFP_ATOMIC | __GFP_NOWARN, htab->map.numa_node); - if (!l_new) + if (!l_new) { + atomic_dec(&htab->count); return ERR_PTR(-ENOMEM); + } memcpy(l_new->key, key, key_size); l_new->sk = sk; From 67db7cd249e71f64346f481b629724376d063e08 Mon Sep 17 00:00:00 2001 From: John Fastabend Date: Wed, 22 Aug 2018 08:37:32 -0700 Subject: [PATCH 045/302] tls: possible hang when do_tcp_sendpages hits sndbuf is full case Currently, the lower protocols sk_write_space handler is not called if TLS is sending a scatterlist via tls_push_sg. However, normally tls_push_sg calls do_tcp_sendpage, which may be under memory pressure, that in turn may trigger a wait via sk_wait_event. Typically, this happens when the in-flight bytes exceed the sdnbuf size. In the normal case when enough ACKs are received sk_write_space() will be called and the sk_wait_event will be woken up allowing it to send more data and/or return to the user. But, in the TLS case because the sk_write_space() handler does not wake up the events the above send will wait until the sndtimeo is exceeded. By default this is MAX_SCHEDULE_TIMEOUT so it look like a hang to the user (especially this impatient user). To fix this pass the sk_write_space event to the lower layers sk_write_space event which in the TCP case will wake any pending events. I observed the above while integrating sockmap and ktls. It initially appeared as test_sockmap (modified to use ktls) occasionally hanging. To reliably reproduce this reduce the sndbuf size and stress the tls layer by sending many 1B sends. This results in every byte needing a header and each byte individually being sent to the crypto layer. Signed-off-by: John Fastabend Acked-by: Dave Watson Signed-off-by: Daniel Borkmann --- net/tls/tls_main.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/net/tls/tls_main.c b/net/tls/tls_main.c index 93c0c225ab34..180b6640e531 100644 --- a/net/tls/tls_main.c +++ b/net/tls/tls_main.c @@ -213,9 +213,14 @@ static void tls_write_space(struct sock *sk) { struct tls_context *ctx = tls_get_ctx(sk); - /* We are already sending pages, ignore notification */ - if (ctx->in_tcp_sendpages) + /* If in_tcp_sendpages call lower protocol write space handler + * to ensure we wake up any waiting operations there. For example + * if do_tcp_sendpages where to call sk_wait_event. + */ + if (ctx->in_tcp_sendpages) { + ctx->sk_write_space(sk); return; + } if (!sk->sk_write_pending && tls_is_pending_closed_record(ctx)) { gfp_t sk_allocation = sk->sk_allocation; From 9b2e0388bec8ec5427403e23faff3b58dd1c3200 Mon Sep 17 00:00:00 2001 From: John Fastabend Date: Wed, 22 Aug 2018 08:37:37 -0700 Subject: [PATCH 046/302] bpf: sockmap: write_space events need to be passed to TCP handler When sockmap code is using the stream parser it also handles the write space events in order to handle the case where (a) verdict redirects skb to another socket and (b) the sockmap then sends the skb but due to memory constraints (or other EAGAIN errors) needs to do a retry. But the initial code missed a third case where the skb_send_sock_locked() triggers an sk_wait_event(). A typically case would be when sndbuf size is exceeded. If this happens because we do not pass the write_space event to the lower layers we never wake up the event and it will wait for sndtimeo. Which as noted in ktls fix may be rather large and look like a hang to the user. To reproduce the best test is to reduce the sndbuf size and send 1B data chunks to stress the memory handling. To fix this pass the event from the upper layer to the lower layer. Signed-off-by: John Fastabend Signed-off-by: Daniel Borkmann --- kernel/bpf/sockmap.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/kernel/bpf/sockmap.c b/kernel/bpf/sockmap.c index 40c6ef9fc828..cf5195c7c331 100644 --- a/kernel/bpf/sockmap.c +++ b/kernel/bpf/sockmap.c @@ -1427,12 +1427,15 @@ static void smap_tx_work(struct work_struct *w) static void smap_write_space(struct sock *sk) { struct smap_psock *psock; + void (*write_space)(struct sock *sk); rcu_read_lock(); psock = smap_psock_sk(sk); if (likely(psock && test_bit(SMAP_TX_RUNNING, &psock->state))) schedule_work(&psock->tx_work); + write_space = psock->save_write_space; rcu_read_unlock(); + write_space(sk); } static void smap_stop_sock(struct smap_psock *psock, struct sock *sk) From 8604ffcbf04f8f4f3f55a9e46e5ff948b2ed4290 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Thu, 16 Aug 2018 12:01:03 +0200 Subject: [PATCH 047/302] drm/amdgpu: fix VM clearing for the root PD MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We need to figure out the address after validating the BO, not before. Signed-off-by: Christian König Reviewed-by: Felix Kuehling Reviewed-by: Junwei Zhang Reviewed-by: Huang Rui Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index ece0ac703e27..e40ca8676418 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -369,7 +369,6 @@ static int amdgpu_vm_clear_bo(struct amdgpu_device *adev, uint64_t addr; int r; - addr = amdgpu_bo_gpu_offset(bo); entries = amdgpu_bo_size(bo) / 8; if (pte_support_ats) { @@ -401,6 +400,7 @@ static int amdgpu_vm_clear_bo(struct amdgpu_device *adev, if (r) goto error; + addr = amdgpu_bo_gpu_offset(bo); if (ats_entries) { uint64_t ats_value; From d98ff24e8e9be3329eea7c84d5e244d0c1cd0ab3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Tue, 21 Aug 2018 15:09:39 +0200 Subject: [PATCH 048/302] drm/amdgpu: fix preamble handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit At this point the command submission can still be interrupted. Signed-off-by: Christian König Acked-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c index 502b94fb116a..09703c87d676 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c @@ -1012,13 +1012,9 @@ static int amdgpu_cs_ib_fill(struct amdgpu_device *adev, if (r) return r; - if (chunk_ib->flags & AMDGPU_IB_FLAG_PREAMBLE) { - parser->job->preamble_status |= AMDGPU_PREAMBLE_IB_PRESENT; - if (!parser->ctx->preamble_presented) { - parser->job->preamble_status |= AMDGPU_PREAMBLE_IB_PRESENT_FIRST; - parser->ctx->preamble_presented = true; - } - } + if (chunk_ib->flags & AMDGPU_IB_FLAG_PREAMBLE) + parser->job->preamble_status |= + AMDGPU_PREAMBLE_IB_PRESENT; if (parser->ring && parser->ring != ring) return -EINVAL; @@ -1241,6 +1237,12 @@ static int amdgpu_cs_submit(struct amdgpu_cs_parser *p, amdgpu_cs_post_dependencies(p); + if ((job->preamble_status & AMDGPU_PREAMBLE_IB_PRESENT) && + !p->ctx->preamble_presented) { + job->preamble_status |= AMDGPU_PREAMBLE_IB_PRESENT_FIRST; + p->ctx->preamble_presented = true; + } + cs->out.handle = seq; job->uf_sequence = seq; From 2f40c6eac74a2a60921cdec9e9a8a57e88e31434 Mon Sep 17 00:00:00 2001 From: Emily Deng Date: Wed, 22 Aug 2018 20:18:25 +0800 Subject: [PATCH 049/302] amdgpu: fix multi-process hang issue MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit SWDEV-146499: hang during multi vulkan process testing cause: the second frame's PREAMBLE_IB have clear-state and LOAD actions, those actions ruin the pipeline that is still doing process in the previous frame's work-load IB. fix: need insert pipeline sync if have context switch for SRIOV (because only SRIOV will report PREEMPTION flag to UMD) Signed-off-by: Monk Liu Signed-off-by: Emily Deng Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c index 5518e623fed2..51b5e977ca88 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c @@ -164,8 +164,10 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned num_ibs, return r; } + need_ctx_switch = ring->current_ctx != fence_ctx; if (ring->funcs->emit_pipeline_sync && job && ((tmp = amdgpu_sync_get_fence(&job->sched_sync, NULL)) || + (amdgpu_sriov_vf(adev) && need_ctx_switch) || amdgpu_vm_need_pipeline_sync(ring, job))) { need_pipe_sync = true; dma_fence_put(tmp); @@ -196,7 +198,6 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned num_ibs, } skip_preamble = ring->current_ctx == fence_ctx; - need_ctx_switch = ring->current_ctx != fence_ctx; if (job && ring->funcs->emit_cntxcntl) { if (need_ctx_switch) status |= AMDGPU_HAVE_CTX_SWITCH; From eb7e5cfced102e61814f6f3e4cb4acb9f9315760 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Wed, 22 Aug 2018 10:07:35 -0400 Subject: [PATCH 050/302] drm/amdgpu: Fix page fault and kasan warning on pci device remove. Problem: When executing echo 1 > /sys/class/drm/card0/device/remove kasan warning as bellow and page fault happen because adev->gart.pages already freed by the time amdgpu_gart_unbind is called. BUG: KASAN: user-memory-access in amdgpu_gart_unbind+0x98/0x180 [amdgpu] Write of size 8 at addr 0000000000003648 by task bash/1828 CPU: 2 PID: 1828 Comm: bash Tainted: G W O 4.18.0-rc1-dev+ #29 Hardware name: Gigabyte Technology Co., Ltd. AX370-Gaming/AX370-Gaming-CF, BIOS F3 06/19/2017 Call Trace: dump_stack+0x71/0xab kasan_report+0x109/0x390 amdgpu_gart_unbind+0x98/0x180 [amdgpu] ttm_tt_unbind+0x43/0x60 [ttm] ttm_bo_move_ttm+0x83/0x1c0 [ttm] ttm_bo_handle_move_mem+0xb97/0xd00 [ttm] ttm_bo_evict+0x273/0x530 [ttm] ttm_mem_evict_first+0x29c/0x360 [ttm] ttm_bo_force_list_clean+0xfc/0x210 [ttm] ttm_bo_clean_mm+0xe7/0x160 [ttm] amdgpu_ttm_fini+0xda/0x1d0 [amdgpu] amdgpu_bo_fini+0xf/0x60 [amdgpu] gmc_v8_0_sw_fini+0x36/0x70 [amdgpu] amdgpu_device_fini+0x2d0/0x7d0 [amdgpu] amdgpu_driver_unload_kms+0x6a/0xd0 [amdgpu] drm_dev_unregister+0x79/0x180 [drm] amdgpu_pci_remove+0x2a/0x60 [amdgpu] pci_device_remove+0x5b/0x100 device_release_driver_internal+0x236/0x360 pci_stop_bus_device+0xbf/0xf0 pci_stop_and_remove_bus_device_locked+0x16/0x30 remove_store+0xda/0xf0 kernfs_fop_write+0x186/0x220 __vfs_write+0xcc/0x330 vfs_write+0xe6/0x250 ksys_write+0xb1/0x140 do_syscall_64+0x77/0x1e0 entry_SYSCALL_64_after_hwframe+0x44/0xa9 RIP: 0033:0x7f66ebbb32c0 Fix: Split gmc_v{6,7,8,9}_0_gart_fini to postpone amdgpu_gart_fini to after memory managers are shut down since gart unbind happens as part of this procedure Signed-off-by: Andrey Grodzovsky Reviewed-by: Junwei Zhang Acked-by: Huang Rui Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c | 9 ++------- drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c | 16 ++-------------- drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c | 16 ++-------------- drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c | 16 ++-------------- 4 files changed, 8 insertions(+), 49 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c index 75317f283c69..ad151fefa41f 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c @@ -632,12 +632,6 @@ static void gmc_v6_0_gart_disable(struct amdgpu_device *adev) amdgpu_gart_table_vram_unpin(adev); } -static void gmc_v6_0_gart_fini(struct amdgpu_device *adev) -{ - amdgpu_gart_table_vram_free(adev); - amdgpu_gart_fini(adev); -} - static void gmc_v6_0_vm_decode_fault(struct amdgpu_device *adev, u32 status, u32 addr, u32 mc_client) { @@ -935,8 +929,9 @@ static int gmc_v6_0_sw_fini(void *handle) amdgpu_gem_force_release(adev); amdgpu_vm_manager_fini(adev); - gmc_v6_0_gart_fini(adev); + amdgpu_gart_table_vram_free(adev); amdgpu_bo_fini(adev); + amdgpu_gart_fini(adev); release_firmware(adev->gmc.fw); adev->gmc.fw = NULL; diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c index 36dc367c4b45..f8d8a3a73e42 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c @@ -746,19 +746,6 @@ static void gmc_v7_0_gart_disable(struct amdgpu_device *adev) amdgpu_gart_table_vram_unpin(adev); } -/** - * gmc_v7_0_gart_fini - vm fini callback - * - * @adev: amdgpu_device pointer - * - * Tears down the driver GART/VM setup (CIK). - */ -static void gmc_v7_0_gart_fini(struct amdgpu_device *adev) -{ - amdgpu_gart_table_vram_free(adev); - amdgpu_gart_fini(adev); -} - /** * gmc_v7_0_vm_decode_fault - print human readable fault info * @@ -1095,8 +1082,9 @@ static int gmc_v7_0_sw_fini(void *handle) amdgpu_gem_force_release(adev); amdgpu_vm_manager_fini(adev); kfree(adev->gmc.vm_fault_info); - gmc_v7_0_gart_fini(adev); + amdgpu_gart_table_vram_free(adev); amdgpu_bo_fini(adev); + amdgpu_gart_fini(adev); release_firmware(adev->gmc.fw); adev->gmc.fw = NULL; diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c index 70fc97b59b4f..9333109b210d 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c @@ -968,19 +968,6 @@ static void gmc_v8_0_gart_disable(struct amdgpu_device *adev) amdgpu_gart_table_vram_unpin(adev); } -/** - * gmc_v8_0_gart_fini - vm fini callback - * - * @adev: amdgpu_device pointer - * - * Tears down the driver GART/VM setup (CIK). - */ -static void gmc_v8_0_gart_fini(struct amdgpu_device *adev) -{ - amdgpu_gart_table_vram_free(adev); - amdgpu_gart_fini(adev); -} - /** * gmc_v8_0_vm_decode_fault - print human readable fault info * @@ -1199,8 +1186,9 @@ static int gmc_v8_0_sw_fini(void *handle) amdgpu_gem_force_release(adev); amdgpu_vm_manager_fini(adev); kfree(adev->gmc.vm_fault_info); - gmc_v8_0_gart_fini(adev); + amdgpu_gart_table_vram_free(adev); amdgpu_bo_fini(adev); + amdgpu_gart_fini(adev); release_firmware(adev->gmc.fw); adev->gmc.fw = NULL; diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c index 399a5db27649..72f8018fa2a8 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c @@ -942,26 +942,12 @@ static int gmc_v9_0_sw_init(void *handle) return 0; } -/** - * gmc_v9_0_gart_fini - vm fini callback - * - * @adev: amdgpu_device pointer - * - * Tears down the driver GART/VM setup (CIK). - */ -static void gmc_v9_0_gart_fini(struct amdgpu_device *adev) -{ - amdgpu_gart_table_vram_free(adev); - amdgpu_gart_fini(adev); -} - static int gmc_v9_0_sw_fini(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; amdgpu_gem_force_release(adev); amdgpu_vm_manager_fini(adev); - gmc_v9_0_gart_fini(adev); /* * TODO: @@ -974,7 +960,9 @@ static int gmc_v9_0_sw_fini(void *handle) */ amdgpu_bo_free_kernel(&adev->stolen_vga_memory, NULL, NULL); + amdgpu_gart_table_vram_free(adev); amdgpu_bo_fini(adev); + amdgpu_gart_fini(adev); return 0; } From 00e1cae78120ee19462e7f96135cd1cc59a086e7 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Wed, 22 Aug 2018 00:02:19 +0200 Subject: [PATCH 051/302] net: ethernet: renesas: use SPDX identifier for Renesas drivers Signed-off-by: Wolfram Sang Acked-by: Sergei Shtylyov Reviewed-by: Simon Horman Signed-off-by: David S. Miller --- drivers/net/ethernet/renesas/ravb.h | 5 +---- drivers/net/ethernet/renesas/ravb_main.c | 5 +---- drivers/net/ethernet/renesas/sh_eth.c | 13 +------------ drivers/net/ethernet/renesas/sh_eth.h | 13 +------------ 4 files changed, 4 insertions(+), 32 deletions(-) diff --git a/drivers/net/ethernet/renesas/ravb.h b/drivers/net/ethernet/renesas/ravb.h index b81f4faf7b10..1470fc12282b 100644 --- a/drivers/net/ethernet/renesas/ravb.h +++ b/drivers/net/ethernet/renesas/ravb.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* Renesas Ethernet AVB device driver * * Copyright (C) 2014-2015 Renesas Electronics Corporation @@ -5,10 +6,6 @@ * Copyright (C) 2015-2016 Cogent Embedded, Inc. * * Based on the SuperH Ethernet driver - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License version 2, - * as published by the Free Software Foundation. */ #ifndef __RAVB_H__ diff --git a/drivers/net/ethernet/renesas/ravb_main.c b/drivers/net/ethernet/renesas/ravb_main.c index c06f2df895c2..aff5516b781e 100644 --- a/drivers/net/ethernet/renesas/ravb_main.c +++ b/drivers/net/ethernet/renesas/ravb_main.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* Renesas Ethernet AVB device driver * * Copyright (C) 2014-2015 Renesas Electronics Corporation @@ -5,10 +6,6 @@ * Copyright (C) 2015-2016 Cogent Embedded, Inc. * * Based on the SuperH Ethernet driver - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License version 2, - * as published by the Free Software Foundation. */ #include diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c index 5573199c4536..ad4433d59237 100644 --- a/drivers/net/ethernet/renesas/sh_eth.c +++ b/drivers/net/ethernet/renesas/sh_eth.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* SuperH Ethernet device driver * * Copyright (C) 2014 Renesas Electronics Corporation @@ -5,18 +6,6 @@ * Copyright (C) 2008-2014 Renesas Solutions Corp. * Copyright (C) 2013-2017 Cogent Embedded, Inc. * Copyright (C) 2014 Codethink Limited - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in - * the file called "COPYING". */ #include diff --git a/drivers/net/ethernet/renesas/sh_eth.h b/drivers/net/ethernet/renesas/sh_eth.h index f94be99cf400..0c18650bbfe6 100644 --- a/drivers/net/ethernet/renesas/sh_eth.h +++ b/drivers/net/ethernet/renesas/sh_eth.h @@ -1,19 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* SuperH Ethernet device driver * * Copyright (C) 2006-2012 Nobuhiro Iwamatsu * Copyright (C) 2008-2012 Renesas Solutions Corp. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in - * the file called "COPYING". */ #ifndef __SH_ETH_H__ From 3d0371b313b84ba7c16ebf2526a7a34f1c57b19e Mon Sep 17 00:00:00 2001 From: Samuel Mendoza-Jonas Date: Wed, 22 Aug 2018 14:57:44 +1000 Subject: [PATCH 052/302] net/ncsi: Fixup .dumpit message flags and ID check in Netlink handler The ncsi_pkg_info_all_nl() .dumpit handler is missing the NLM_F_MULTI flag, causing additional package information after the first to be lost. Also fixup a sanity check in ncsi_write_package_info() to reject out of range package IDs. Signed-off-by: Samuel Mendoza-Jonas Signed-off-by: David S. Miller --- net/ncsi/ncsi-netlink.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/ncsi/ncsi-netlink.c b/net/ncsi/ncsi-netlink.c index 82e6edf9c5d9..45f33d6dedf7 100644 --- a/net/ncsi/ncsi-netlink.c +++ b/net/ncsi/ncsi-netlink.c @@ -100,7 +100,7 @@ static int ncsi_write_package_info(struct sk_buff *skb, bool found; int rc; - if (id > ndp->package_num) { + if (id > ndp->package_num - 1) { netdev_info(ndp->ndev.dev, "NCSI: No package with id %u\n", id); return -ENODEV; } @@ -240,7 +240,7 @@ static int ncsi_pkg_info_all_nl(struct sk_buff *skb, return 0; /* done */ hdr = genlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq, - &ncsi_genl_family, 0, NCSI_CMD_PKG_INFO); + &ncsi_genl_family, NLM_F_MULTI, NCSI_CMD_PKG_INFO); if (!hdr) { rc = -EMSGSIZE; goto err; From 93cfb6c17690c465509967aeb237717d10513a88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Toke=20H=C3=B8iland-J=C3=B8rgensen?= Date: Wed, 22 Aug 2018 12:29:43 +0200 Subject: [PATCH 053/302] sch_cake: Fix TC filter flow override and expand it to hosts as well MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The TC filter flow mapping override completely skipped the call to cake_hash(); however that meant that the internal state was not being updated, which ultimately leads to deadlocks in some configurations. Fix that by passing the overridden flow ID into cake_hash() instead so it can react appropriately. In addition, the major number of the class ID can now be set to override the host mapping in host isolation mode. If both host and flow are overridden (or if the respective modes are disabled), flow dissection and hashing will be skipped entirely; otherwise, the hashing will be kept for the portions that are not set by the filter. Signed-off-by: Toke Høiland-Jørgensen Signed-off-by: David S. Miller --- net/sched/sch_cake.c | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/net/sched/sch_cake.c b/net/sched/sch_cake.c index 4d26b0823cdf..c07c30b916d5 100644 --- a/net/sched/sch_cake.c +++ b/net/sched/sch_cake.c @@ -620,15 +620,20 @@ static bool cake_ddst(int flow_mode) } static u32 cake_hash(struct cake_tin_data *q, const struct sk_buff *skb, - int flow_mode) + int flow_mode, u16 flow_override, u16 host_override) { - u32 flow_hash = 0, srchost_hash, dsthost_hash; + u32 flow_hash = 0, srchost_hash = 0, dsthost_hash = 0; u16 reduced_hash, srchost_idx, dsthost_idx; struct flow_keys keys, host_keys; if (unlikely(flow_mode == CAKE_FLOW_NONE)) return 0; + /* If both overrides are set we can skip packet dissection entirely */ + if ((flow_override || !(flow_mode & CAKE_FLOW_FLOWS)) && + (host_override || !(flow_mode & CAKE_FLOW_HOSTS))) + goto skip_hash; + skb_flow_dissect_flow_keys(skb, &keys, FLOW_DISSECTOR_F_STOP_AT_FLOW_LABEL); @@ -675,6 +680,14 @@ static u32 cake_hash(struct cake_tin_data *q, const struct sk_buff *skb, if (flow_mode & CAKE_FLOW_FLOWS) flow_hash = flow_hash_from_keys(&keys); +skip_hash: + if (flow_override) + flow_hash = flow_override - 1; + if (host_override) { + dsthost_hash = host_override - 1; + srchost_hash = host_override - 1; + } + if (!(flow_mode & CAKE_FLOW_FLOWS)) { if (flow_mode & CAKE_FLOW_SRC_IP) flow_hash ^= srchost_hash; @@ -1570,7 +1583,7 @@ static u32 cake_classify(struct Qdisc *sch, struct cake_tin_data **t, struct cake_sched_data *q = qdisc_priv(sch); struct tcf_proto *filter; struct tcf_result res; - u32 flow = 0; + u16 flow = 0, host = 0; int result; filter = rcu_dereference_bh(q->filter_list); @@ -1594,10 +1607,12 @@ static u32 cake_classify(struct Qdisc *sch, struct cake_tin_data **t, #endif if (TC_H_MIN(res.classid) <= CAKE_QUEUES) flow = TC_H_MIN(res.classid); + if (TC_H_MAJ(res.classid) <= (CAKE_QUEUES << 16)) + host = TC_H_MAJ(res.classid) >> 16; } hash: *t = cake_select_tin(sch, skb); - return flow ?: cake_hash(*t, skb, flow_mode) + 1; + return cake_hash(*t, skb, flow_mode, flow, host) + 1; } static void cake_reconfigure(struct Qdisc *sch); From 191672ca07a7c10c3b84d01019a33d59b4317997 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Wed, 22 Aug 2018 17:25:44 +0200 Subject: [PATCH 054/302] net_sched: fix unused variable warning in stmmac The new tcf_exts_for_each_action() macro doesn't reference its arguments when CONFIG_NET_CLS_ACT is disabled, which leads to a harmless warning in at least one driver: drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c: In function 'tc_fill_actions': drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c:64:6: error: unused variable 'i' [-Werror=unused-variable] Adding a cast to void lets us avoid this kind of warning. To be on the safe side, do it for all three arguments, not just the one that caused the warning. Fixes: 244cd96adb5f ("net_sched: remove list_head from tc_action") Signed-off-by: Arnd Bergmann Signed-off-by: David S. Miller --- include/net/pkt_cls.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/net/pkt_cls.h b/include/net/pkt_cls.h index c17d51865469..75a3f3fdb359 100644 --- a/include/net/pkt_cls.h +++ b/include/net/pkt_cls.h @@ -303,7 +303,7 @@ static inline void tcf_exts_put_net(struct tcf_exts *exts) for (i = 0; i < TCA_ACT_MAX_PRIO && ((a) = (exts)->actions[i]); i++) #else #define tcf_exts_for_each_action(i, a, exts) \ - for (; 0; ) + for (; 0; (void)(i), (void)(a), (void)(exts)) #endif static inline void From e500c6d349f7f36120886841c6f057ce248b48b2 Mon Sep 17 00:00:00 2001 From: Cong Wang Date: Wed, 22 Aug 2018 12:58:34 -0700 Subject: [PATCH 055/302] addrconf: reduce unnecessary atomic allocations All the 3 callers of addrconf_add_mroute() assert RTNL lock, they don't take any additional lock either, so it is safe to convert it to GFP_KERNEL. Same for sit_add_v4_addrs(). Cc: David Ahern Signed-off-by: Cong Wang Reviewed-by: David Ahern Signed-off-by: David S. Miller --- net/ipv6/addrconf.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 2fac4ad74867..d51a8c0b3372 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -2398,7 +2398,7 @@ static void addrconf_add_mroute(struct net_device *dev) ipv6_addr_set(&cfg.fc_dst, htonl(0xFF000000), 0, 0, 0); - ip6_route_add(&cfg, GFP_ATOMIC, NULL); + ip6_route_add(&cfg, GFP_KERNEL, NULL); } static struct inet6_dev *addrconf_add_dev(struct net_device *dev) @@ -3062,7 +3062,7 @@ static void sit_add_v4_addrs(struct inet6_dev *idev) if (addr.s6_addr32[3]) { add_addr(idev, &addr, plen, scope); addrconf_prefix_route(&addr, plen, 0, idev->dev, 0, pflags, - GFP_ATOMIC); + GFP_KERNEL); return; } @@ -3087,7 +3087,7 @@ static void sit_add_v4_addrs(struct inet6_dev *idev) add_addr(idev, &addr, plen, flag); addrconf_prefix_route(&addr, plen, 0, idev->dev, - 0, pflags, GFP_ATOMIC); + 0, pflags, GFP_KERNEL); } } } From 431280eebed9f5079553daf003011097763e71fd Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Wed, 22 Aug 2018 13:30:45 -0700 Subject: [PATCH 056/302] ipv4: tcp: send zero IPID for RST and ACK sent in SYN-RECV and TIME-WAIT state tcp uses per-cpu (and per namespace) sockets (net->ipv4.tcp_sk) internally to send some control packets. 1) RST packets, through tcp_v4_send_reset() 2) ACK packets in SYN-RECV and TIME-WAIT state, through tcp_v4_send_ack() These packets assert IP_DF, and also use the hashed IP ident generator to provide an IPv4 ID number. Geoff Alexander reported this could be used to build off-path attacks. These packets should not be fragmented, since their size is smaller than IPV4_MIN_MTU. Only some tunneled paths could eventually have to fragment, regardless of inner IPID. We really can use zero IPID, to address the flaw, and as a bonus, avoid a couple of atomic operations in ip_idents_reserve() Signed-off-by: Eric Dumazet Reported-by: Geoff Alexander Tested-by: Geoff Alexander Signed-off-by: David S. Miller --- net/ipv4/tcp_ipv4.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 9e041fa5c545..44c09eddbb78 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -2517,6 +2517,12 @@ static int __net_init tcp_sk_init(struct net *net) if (res) goto fail; sock_set_flag(sk, SOCK_USE_WRITE_QUEUE); + + /* Please enforce IP_DF and IPID==0 for RST and + * ACK sent in SYN-RECV and TIME-WAIT state. + */ + inet_sk(sk)->pmtudisc = IP_PMTUDISC_DO; + *per_cpu_ptr(net->ipv4.tcp_sk, cpu) = sk; } From fb99886224294b2291d267da41395022fa4200e2 Mon Sep 17 00:00:00 2001 From: Kevin Yang Date: Wed, 22 Aug 2018 17:43:14 -0400 Subject: [PATCH 057/302] tcp_bbr: add bbr_check_probe_rtt_done() helper This patch add a helper function bbr_check_probe_rtt_done() to 1. check the condition to see if bbr should exit probe_rtt mode; 2. process the logic of exiting probe_rtt mode. Fixes: 0f8782ea1497 ("tcp_bbr: add BBR congestion control") Signed-off-by: Kevin Yang Signed-off-by: Neal Cardwell Signed-off-by: Yuchung Cheng Reviewed-by: Soheil Hassas Yeganeh Signed-off-by: David S. Miller --- net/ipv4/tcp_bbr.c | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/net/ipv4/tcp_bbr.c b/net/ipv4/tcp_bbr.c index 13d34427ca3d..fd7bccf36a26 100644 --- a/net/ipv4/tcp_bbr.c +++ b/net/ipv4/tcp_bbr.c @@ -95,11 +95,10 @@ struct bbr { u32 mode:3, /* current bbr_mode in state machine */ prev_ca_state:3, /* CA state on previous ACK */ packet_conservation:1, /* use packet conservation? */ - restore_cwnd:1, /* decided to revert cwnd to old value */ round_start:1, /* start of packet-timed tx->ack round? */ idle_restart:1, /* restarting after idle? */ probe_rtt_round_done:1, /* a BBR_PROBE_RTT round at 4 pkts? */ - unused:12, + unused:13, lt_is_sampling:1, /* taking long-term ("LT") samples now? */ lt_rtt_cnt:7, /* round trips in long-term interval */ lt_use_bw:1; /* use lt_bw as our bw estimate? */ @@ -396,17 +395,11 @@ static bool bbr_set_cwnd_to_recover_or_restore( cwnd = tcp_packets_in_flight(tp) + acked; } else if (prev_state >= TCP_CA_Recovery && state < TCP_CA_Recovery) { /* Exiting loss recovery; restore cwnd saved before recovery. */ - bbr->restore_cwnd = 1; + cwnd = max(cwnd, bbr->prior_cwnd); bbr->packet_conservation = 0; } bbr->prev_ca_state = state; - if (bbr->restore_cwnd) { - /* Restore cwnd after exiting loss recovery or PROBE_RTT. */ - cwnd = max(cwnd, bbr->prior_cwnd); - bbr->restore_cwnd = 0; - } - if (bbr->packet_conservation) { *new_cwnd = max(cwnd, tcp_packets_in_flight(tp) + acked); return true; /* yes, using packet conservation */ @@ -748,6 +741,20 @@ static void bbr_check_drain(struct sock *sk, const struct rate_sample *rs) bbr_reset_probe_bw_mode(sk); /* we estimate queue is drained */ } +static void bbr_check_probe_rtt_done(struct sock *sk) +{ + struct tcp_sock *tp = tcp_sk(sk); + struct bbr *bbr = inet_csk_ca(sk); + + if (!(bbr->probe_rtt_done_stamp && + after(tcp_jiffies32, bbr->probe_rtt_done_stamp))) + return; + + bbr->min_rtt_stamp = tcp_jiffies32; /* wait a while until PROBE_RTT */ + tp->snd_cwnd = max(tp->snd_cwnd, bbr->prior_cwnd); + bbr_reset_mode(sk); +} + /* The goal of PROBE_RTT mode is to have BBR flows cooperatively and * periodically drain the bottleneck queue, to converge to measure the true * min_rtt (unloaded propagation delay). This allows the flows to keep queues @@ -806,12 +813,8 @@ static void bbr_update_min_rtt(struct sock *sk, const struct rate_sample *rs) } else if (bbr->probe_rtt_done_stamp) { if (bbr->round_start) bbr->probe_rtt_round_done = 1; - if (bbr->probe_rtt_round_done && - after(tcp_jiffies32, bbr->probe_rtt_done_stamp)) { - bbr->min_rtt_stamp = tcp_jiffies32; - bbr->restore_cwnd = 1; /* snap to prior_cwnd */ - bbr_reset_mode(sk); - } + if (bbr->probe_rtt_round_done) + bbr_check_probe_rtt_done(sk); } } /* Restart after idle ends only once we process a new S/ACK for data */ @@ -862,7 +865,6 @@ static void bbr_init(struct sock *sk) bbr->has_seen_rtt = 0; bbr_init_pacing_rate_from_rtt(sk); - bbr->restore_cwnd = 0; bbr->round_start = 0; bbr->idle_restart = 0; bbr->full_bw_reached = 0; From 5490b32dce6932ea7ee8e3b2f76db2957c92af6e Mon Sep 17 00:00:00 2001 From: Kevin Yang Date: Wed, 22 Aug 2018 17:43:15 -0400 Subject: [PATCH 058/302] tcp_bbr: in restart from idle, see if we should exit PROBE_RTT This patch fix the case where BBR does not exit PROBE_RTT mode when it restarts from idle. When BBR restarts from idle and if BBR is in PROBE_RTT mode, BBR should check if it's time to exit PROBE_RTT. If yes, then BBR should exit PROBE_RTT mode and restore the cwnd to its full value. Fixes: 0f8782ea1497 ("tcp_bbr: add BBR congestion control") Signed-off-by: Kevin Yang Signed-off-by: Neal Cardwell Reviewed-by: Yuchung Cheng Reviewed-by: Soheil Hassas Yeganeh Signed-off-by: David S. Miller --- net/ipv4/tcp_bbr.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/net/ipv4/tcp_bbr.c b/net/ipv4/tcp_bbr.c index fd7bccf36a26..1d4bdd3b5e4d 100644 --- a/net/ipv4/tcp_bbr.c +++ b/net/ipv4/tcp_bbr.c @@ -174,6 +174,8 @@ static const u32 bbr_lt_bw_diff = 4000 / 8; /* If we estimate we're policed, use lt_bw for this many round trips: */ static const u32 bbr_lt_bw_max_rtts = 48; +static void bbr_check_probe_rtt_done(struct sock *sk); + /* Do we estimate that STARTUP filled the pipe? */ static bool bbr_full_bw_reached(const struct sock *sk) { @@ -308,6 +310,8 @@ static void bbr_cwnd_event(struct sock *sk, enum tcp_ca_event event) */ if (bbr->mode == BBR_PROBE_BW) bbr_set_pacing_rate(sk, bbr_bw(sk), BBR_UNIT); + else if (bbr->mode == BBR_PROBE_RTT) + bbr_check_probe_rtt_done(sk); } } From 8e995bf14fdb7e33681d5c3312b602fa342b878a Mon Sep 17 00:00:00 2001 From: Kevin Yang Date: Wed, 22 Aug 2018 17:43:16 -0400 Subject: [PATCH 059/302] tcp_bbr: apply PROBE_RTT cwnd cap even if acked==0 This commit fixes a corner case where TCP BBR would enter PROBE_RTT mode but not reduce its cwnd. If a TCP receiver ACKed less than one full segment, the number of delivered/acked packets was 0, so that bbr_set_cwnd() would short-circuit and exit early, without cutting cwnd to the value we want for PROBE_RTT. The fix is to instead make sure that even when 0 full packets are ACKed, we do apply all the appropriate caps, including the cap that applies in PROBE_RTT mode. Fixes: 0f8782ea1497 ("tcp_bbr: add BBR congestion control") Signed-off-by: Kevin Yang Signed-off-by: Neal Cardwell Reviewed-by: Yuchung Cheng Reviewed-by: Soheil Hassas Yeganeh Signed-off-by: David S. Miller --- net/ipv4/tcp_bbr.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/ipv4/tcp_bbr.c b/net/ipv4/tcp_bbr.c index 1d4bdd3b5e4d..02ff2dde9609 100644 --- a/net/ipv4/tcp_bbr.c +++ b/net/ipv4/tcp_bbr.c @@ -420,10 +420,10 @@ static void bbr_set_cwnd(struct sock *sk, const struct rate_sample *rs, { struct tcp_sock *tp = tcp_sk(sk); struct bbr *bbr = inet_csk_ca(sk); - u32 cwnd = 0, target_cwnd = 0; + u32 cwnd = tp->snd_cwnd, target_cwnd = 0; if (!acked) - return; + goto done; /* no packet fully ACKed; just apply caps */ if (bbr_set_cwnd_to_recover_or_restore(sk, rs, acked, &cwnd)) goto done; From 3ed614dce3ca9912d22be215ff0f11104b69fe62 Mon Sep 17 00:00:00 2001 From: Huazhong Tan Date: Thu, 23 Aug 2018 11:10:10 +0800 Subject: [PATCH 060/302] net: hns: fix length and page_offset overflow when CONFIG_ARM64_64K_PAGES When enable the config item "CONFIG_ARM64_64K_PAGES", the size of PAGE_SIZE is 65536(64K). But the type of length and page_offset are u16, they will overflow. So change them to u32. Fixes: 6fe6611ff275 ("net: add Hisilicon Network Subsystem hnae framework support") Signed-off-by: Huazhong Tan Signed-off-by: Salil Mehta Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns/hnae.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/hisilicon/hns/hnae.h b/drivers/net/ethernet/hisilicon/hns/hnae.h index fa5b30f547f6..cad52bd331f7 100644 --- a/drivers/net/ethernet/hisilicon/hns/hnae.h +++ b/drivers/net/ethernet/hisilicon/hns/hnae.h @@ -220,10 +220,10 @@ struct hnae_desc_cb { /* priv data for the desc, e.g. skb when use with ip stack*/ void *priv; - u16 page_offset; - u16 reuse_flag; + u32 page_offset; + u32 length; /* length of the buffer */ - u16 length; /* length of the buffer */ + u16 reuse_flag; /* desc type, used by the ring user to mark the type of the priv data */ u16 type; From ac4a5b52f5970479f4b2d94a7f98dbf9eaf675ab Mon Sep 17 00:00:00 2001 From: Huazhong Tan Date: Thu, 23 Aug 2018 11:10:11 +0800 Subject: [PATCH 061/302] net: hns: modify variable type in hns_nic_reuse_page 'truesize' is supposed to be u32, not int, so fix it. Signed-off-by: Huazhong tan Signed-off-by: Salil Mehta Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns/hns_enet.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/hisilicon/hns/hns_enet.c b/drivers/net/ethernet/hisilicon/hns/hns_enet.c index 9f2b552aee33..c8c0b0309c27 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_enet.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_enet.c @@ -512,7 +512,8 @@ static void hns_nic_reuse_page(struct sk_buff *skb, int i, struct hnae_desc_cb *desc_cb) { struct hnae_desc *desc; - int truesize, size; + u32 truesize; + int size; int last_offset; bool twobufs; From b1ccd4c0ab6ef499f47dd84ed4920502a7147bba Mon Sep 17 00:00:00 2001 From: Huazhong Tan Date: Thu, 23 Aug 2018 11:10:12 +0800 Subject: [PATCH 062/302] net: hns: fix skb->truesize underestimation skb->truesize is not meant to be tracking amount of used bytes in a skb, but amount of reserved/consumed bytes in memory. For instance, if we use a single byte in last page fragment, we have to account the full size of the fragment. So skb_add_rx_frag needs to calculate the length of the entire buffer into turesize. Fixes: 9cbe9fd5214e ("net: hns: optimize XGE capability by reducing cpu usage") Signed-off-by: Huazhong tan Signed-off-by: Salil Mehta Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns/hns_enet.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/hisilicon/hns/hns_enet.c b/drivers/net/ethernet/hisilicon/hns/hns_enet.c index c8c0b0309c27..71bd3bff6c67 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_enet.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_enet.c @@ -531,7 +531,7 @@ static void hns_nic_reuse_page(struct sk_buff *skb, int i, } skb_add_rx_frag(skb, i, desc_cb->priv, desc_cb->page_offset + pull_len, - size - pull_len, truesize - pull_len); + size - pull_len, truesize); /* avoid re-using remote pages,flag default unreuse */ if (unlikely(page_to_nid(desc_cb->priv) != numa_node_id())) From 339379a2fb13decd1802b403370cc3cdf21d819f Mon Sep 17 00:00:00 2001 From: Huazhong Tan Date: Thu, 23 Aug 2018 11:10:13 +0800 Subject: [PATCH 063/302] net: hns: use eth_get_headlen interface instead of hns_nic_get_headlen Update hns to drop the hns_nic_get_headlen function in favour of eth_get_headlen, and hence also removes now redundant hns_nic_get_headlen. Signed-off-by: Huazhong Tan Signed-off-by: Salil Mehta Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns/hns_enet.c | 103 +----------------- 1 file changed, 1 insertion(+), 102 deletions(-) diff --git a/drivers/net/ethernet/hisilicon/hns/hns_enet.c b/drivers/net/ethernet/hisilicon/hns/hns_enet.c index 71bd3bff6c67..02a0ba20fad5 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_enet.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_enet.c @@ -406,107 +406,6 @@ netdev_tx_t hns_nic_net_xmit_hw(struct net_device *ndev, return NETDEV_TX_BUSY; } -/** - * hns_nic_get_headlen - determine size of header for RSC/LRO/GRO/FCOE - * @data: pointer to the start of the headers - * @max: total length of section to find headers in - * - * This function is meant to determine the length of headers that will - * be recognized by hardware for LRO, GRO, and RSC offloads. The main - * motivation of doing this is to only perform one pull for IPv4 TCP - * packets so that we can do basic things like calculating the gso_size - * based on the average data per packet. - **/ -static unsigned int hns_nic_get_headlen(unsigned char *data, u32 flag, - unsigned int max_size) -{ - unsigned char *network; - u8 hlen; - - /* this should never happen, but better safe than sorry */ - if (max_size < ETH_HLEN) - return max_size; - - /* initialize network frame pointer */ - network = data; - - /* set first protocol and move network header forward */ - network += ETH_HLEN; - - /* handle any vlan tag if present */ - if (hnae_get_field(flag, HNS_RXD_VLAN_M, HNS_RXD_VLAN_S) - == HNS_RX_FLAG_VLAN_PRESENT) { - if ((typeof(max_size))(network - data) > (max_size - VLAN_HLEN)) - return max_size; - - network += VLAN_HLEN; - } - - /* handle L3 protocols */ - if (hnae_get_field(flag, HNS_RXD_L3ID_M, HNS_RXD_L3ID_S) - == HNS_RX_FLAG_L3ID_IPV4) { - if ((typeof(max_size))(network - data) > - (max_size - sizeof(struct iphdr))) - return max_size; - - /* access ihl as a u8 to avoid unaligned access on ia64 */ - hlen = (network[0] & 0x0F) << 2; - - /* verify hlen meets minimum size requirements */ - if (hlen < sizeof(struct iphdr)) - return network - data; - - /* record next protocol if header is present */ - } else if (hnae_get_field(flag, HNS_RXD_L3ID_M, HNS_RXD_L3ID_S) - == HNS_RX_FLAG_L3ID_IPV6) { - if ((typeof(max_size))(network - data) > - (max_size - sizeof(struct ipv6hdr))) - return max_size; - - /* record next protocol */ - hlen = sizeof(struct ipv6hdr); - } else { - return network - data; - } - - /* relocate pointer to start of L4 header */ - network += hlen; - - /* finally sort out TCP/UDP */ - if (hnae_get_field(flag, HNS_RXD_L4ID_M, HNS_RXD_L4ID_S) - == HNS_RX_FLAG_L4ID_TCP) { - if ((typeof(max_size))(network - data) > - (max_size - sizeof(struct tcphdr))) - return max_size; - - /* access doff as a u8 to avoid unaligned access on ia64 */ - hlen = (network[12] & 0xF0) >> 2; - - /* verify hlen meets minimum size requirements */ - if (hlen < sizeof(struct tcphdr)) - return network - data; - - network += hlen; - } else if (hnae_get_field(flag, HNS_RXD_L4ID_M, HNS_RXD_L4ID_S) - == HNS_RX_FLAG_L4ID_UDP) { - if ((typeof(max_size))(network - data) > - (max_size - sizeof(struct udphdr))) - return max_size; - - network += sizeof(struct udphdr); - } - - /* If everything has gone correctly network should be the - * data section of the packet and will be the end of the header. - * If not then it probably represents the end of the last recognized - * header. - */ - if ((typeof(max_size))(network - data) < max_size) - return network - data; - else - return max_size; -} - static void hns_nic_reuse_page(struct sk_buff *skb, int i, struct hnae_ring *ring, int pull_len, struct hnae_desc_cb *desc_cb) @@ -696,7 +595,7 @@ static int hns_nic_poll_rx_skb(struct hns_nic_ring_data *ring_data, } else { ring->stats.seg_pkt_cnt++; - pull_len = hns_nic_get_headlen(va, bnum_flag, HNS_RX_HEAD_SIZE); + pull_len = eth_get_headlen(va, HNS_RX_HEAD_SIZE); memcpy(__skb_put(skb, pull_len), va, ALIGN(pull_len, sizeof(long))); From d23c4b6336ef30898dcdff351f21e633e7a64930 Mon Sep 17 00:00:00 2001 From: Hangbin Liu Date: Thu, 23 Aug 2018 11:31:37 +0800 Subject: [PATCH 064/302] net/ipv6: init ip6 anycast rt->dst.input as ip6_input Commit 6edb3c96a5f02 ("net/ipv6: Defer initialization of dst to data path") forgot to handle anycast route and init anycast rt->dst.input to ip6_forward. Fix it by setting anycast rt->dst.input back to ip6_input. Fixes: 6edb3c96a5f02 ("net/ipv6: Defer initialization of dst to data path") Signed-off-by: Hangbin Liu Reviewed-by: David Ahern Signed-off-by: David S. Miller --- net/ipv6/route.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 7208c16302f6..c4ea13e8360b 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -956,7 +956,7 @@ static void ip6_rt_init_dst(struct rt6_info *rt, struct fib6_info *ort) rt->dst.error = 0; rt->dst.output = ip6_output; - if (ort->fib6_type == RTN_LOCAL) { + if (ort->fib6_type == RTN_LOCAL || ort->fib6_type == RTN_ANYCAST) { rt->dst.input = ip6_input; } else if (ipv6_addr_type(&ort->fib6_dst.addr) & IPV6_ADDR_MULTICAST) { rt->dst.input = ip6_mc_input; From 27a5959308559fa6afcaa4e6cd81d25bcb2dda7c Mon Sep 17 00:00:00 2001 From: Huazhong Tan Date: Thu, 23 Aug 2018 11:37:15 +0800 Subject: [PATCH 065/302] net: hns3: fix page_offset overflow when CONFIG_ARM64_64K_PAGES When enable the config item "CONFIG_ARM64_64K_PAGES", the size of PAGE_SIZE is 65536(64K). But the type of page_offset is u16, it will overflow. So change it to u32, when "CONFIG_ARM64_64K_PAGES" enabled. Fixes: 76ad4f0ee747 ("net: hns3: Add support of HNS3 Ethernet Driver for hip08 SoC") Signed-off-by: Huazhong Tan Signed-off-by: Salil Mehta Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns3/hns3_enet.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h index a02a96aee2a2..cb450d7ec8c1 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h @@ -284,11 +284,11 @@ struct hns3_desc_cb { /* priv data for the desc, e.g. skb when use with ip stack*/ void *priv; - u16 page_offset; - u16 reuse_flag; - + u32 page_offset; u32 length; /* length of the buffer */ + u16 reuse_flag; + /* desc type, used by the ring user to mark the type of the priv data */ u16 type; }; From 583e7281f1d8234f3a3e483bd6fba7a72d24aa4e Mon Sep 17 00:00:00 2001 From: Huazhong Tan Date: Thu, 23 Aug 2018 11:37:16 +0800 Subject: [PATCH 066/302] net: hns3: modify variable type in hns3_nic_reuse_page 'truesize' is supposed to be u32, not int, so fix it. Signed-off-by: Huazhong tan Signed-off-by: Salil Mehta Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns3/hns3_enet.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index 3554dca7a680..955c4ab18b03 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -2019,7 +2019,8 @@ static void hns3_nic_reuse_page(struct sk_buff *skb, int i, struct hns3_desc_cb *desc_cb) { struct hns3_desc *desc; - int truesize, size; + u32 truesize; + int size; int last_offset; bool twobufs; From 9faf870e559a710c44e747ba20383ea82d8ac5d2 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Wed, 22 Aug 2018 21:28:01 +0300 Subject: [PATCH 067/302] mmc: renesas_sdhi_internal_dmac: fix #define RST_RESERVED_BITS The DM_CM_RST register actually has bits 0-31 defaulting to 1s and bits 32-63 defaulting to 0s -- fix off-by-one in #define RST_RESERVED_BITS. Signed-off-by: Sergei Shtylyov Reviewed-by: Wolfram Sang Fixes: 2a68ea7896e3 ("mmc: renesas-sdhi: add support for R-Car Gen3 SDHI DMAC") Cc: stable@vger.kernel.org # v4.14+ Signed-off-by: Ulf Hansson --- drivers/mmc/host/renesas_sdhi_internal_dmac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mmc/host/renesas_sdhi_internal_dmac.c b/drivers/mmc/host/renesas_sdhi_internal_dmac.c index 35cc0de6be67..f16677f424b9 100644 --- a/drivers/mmc/host/renesas_sdhi_internal_dmac.c +++ b/drivers/mmc/host/renesas_sdhi_internal_dmac.c @@ -45,7 +45,7 @@ /* DM_CM_RST */ #define RST_DTRANRST1 BIT(9) #define RST_DTRANRST0 BIT(8) -#define RST_RESERVED_BITS GENMASK_ULL(32, 0) +#define RST_RESERVED_BITS GENMASK_ULL(31, 0) /* DM_CM_INFO1 and DM_CM_INFO1_MASK */ #define INFO1_CLEAR 0 From d2332f887ddfba50fee93b8e1736376517c2df0c Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Wed, 22 Aug 2018 21:22:26 +0300 Subject: [PATCH 068/302] mmc: renesas_sdhi_internal_dmac: mask DMAC interrupts I have encountered an interrupt storm during the eMMC chip probing (and the chip finally didn't get detected). It turned out that U-Boot left the SDHI DMA interrupts enabled while the Linux driver didn't use those. Masking those interrupts in renesas_sdhi_internal_dmac_request_dma() gets rid of both issues... Signed-off-by: Sergei Shtylyov Reviewed-by: Wolfram Sang Fixes: 2a68ea7896e3 ("mmc: renesas-sdhi: add support for R-Car Gen3 SDHI DMAC") Cc: stable@vger.kernel.org # v4.14+ Signed-off-by: Ulf Hansson --- drivers/mmc/host/renesas_sdhi_internal_dmac.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/mmc/host/renesas_sdhi_internal_dmac.c b/drivers/mmc/host/renesas_sdhi_internal_dmac.c index f16677f424b9..ca0b43973769 100644 --- a/drivers/mmc/host/renesas_sdhi_internal_dmac.c +++ b/drivers/mmc/host/renesas_sdhi_internal_dmac.c @@ -49,10 +49,12 @@ /* DM_CM_INFO1 and DM_CM_INFO1_MASK */ #define INFO1_CLEAR 0 +#define INFO1_MASK_CLEAR GENMASK_ULL(31, 0) #define INFO1_DTRANEND1 BIT(17) #define INFO1_DTRANEND0 BIT(16) /* DM_CM_INFO2 and DM_CM_INFO2_MASK */ +#define INFO2_MASK_CLEAR GENMASK_ULL(31, 0) #define INFO2_DTRANERR1 BIT(17) #define INFO2_DTRANERR0 BIT(16) @@ -252,6 +254,12 @@ renesas_sdhi_internal_dmac_request_dma(struct tmio_mmc_host *host, { struct renesas_sdhi *priv = host_to_priv(host); + /* Disable DMAC interrupts, we don't use them */ + renesas_sdhi_internal_dmac_dm_write(host, DM_CM_INFO1_MASK, + INFO1_MASK_CLEAR); + renesas_sdhi_internal_dmac_dm_write(host, DM_CM_INFO2_MASK, + INFO2_MASK_CLEAR); + /* Each value is set to non-zero to assume "enabling" each DMA */ host->chan_rx = host->chan_tx = (void *)0xdeadbeaf; From 4381147df9098706caa5cf9fda37e53b2fe4871f Mon Sep 17 00:00:00 2001 From: Anirudh Venkataramanan Date: Thu, 9 Aug 2018 06:28:51 -0700 Subject: [PATCH 069/302] ice: Fix multiple static analyser warnings This patch fixes the following smatch errors: 1) Fix "odd binop '0x0 & 0xc'" when performing the bitwise-and with a constant value of zero (ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_128_FLAG). Remove a similar bitwise-and with 0 in ice_add_marker_act() and use the right mask ICE_LG_ACT_GENERIC_OFFSET_M in the expression. 2) Fix a similar issue "odd binop '0x0 & 0x1800' in ice_req_irq_msix_misc. 3) Fix "odd binop '0x380000 & 0x7fff8'" in ice_add_marker_act(). Also, use a new define ICE_LG_ACT_GENERIC_OFF_RX_DESC_PROF_IDX instead of magic number '7'. 4) Fix warn: odd binop '0x0 & 0x18' in ice_set_dflt_vsi_ctx() by removing unnecessary logic to explicitly unset bits 3 and 4 in port_vlan_bits. These bits are unset already by the memset on ctxt->info. Reported-by: Dan Carpenter Signed-off-by: Anirudh Venkataramanan Tested-by: Tony Brelinski Signed-off-by: Jeff Kirsher --- .../net/ethernet/intel/ice/ice_adminq_cmd.h | 1 + drivers/net/ethernet/intel/ice/ice_common.c | 25 +++++++++++-------- drivers/net/ethernet/intel/ice/ice_main.c | 19 ++++++-------- drivers/net/ethernet/intel/ice/ice_switch.c | 4 +-- 4 files changed, 25 insertions(+), 24 deletions(-) diff --git a/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h b/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h index 7541ec2270b3..6d3e11659ba5 100644 --- a/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h +++ b/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h @@ -594,6 +594,7 @@ struct ice_sw_rule_lg_act { #define ICE_LG_ACT_GENERIC_OFFSET_M (0x7 << ICE_LG_ACT_GENERIC_OFFSET_S) #define ICE_LG_ACT_GENERIC_PRIORITY_S 22 #define ICE_LG_ACT_GENERIC_PRIORITY_M (0x7 << ICE_LG_ACT_GENERIC_PRIORITY_S) +#define ICE_LG_ACT_GENERIC_OFF_RX_DESC_PROF_IDX 7 /* Action = 7 - Set Stat count */ #define ICE_LG_ACT_STAT_COUNT 0x7 diff --git a/drivers/net/ethernet/intel/ice/ice_common.c b/drivers/net/ethernet/intel/ice/ice_common.c index 71d032cc5fa7..d5300b606d5a 100644 --- a/drivers/net/ethernet/intel/ice/ice_common.c +++ b/drivers/net/ethernet/intel/ice/ice_common.c @@ -1619,20 +1619,23 @@ __ice_aq_get_set_rss_lut(struct ice_hw *hw, u16 vsi_id, u8 lut_type, u8 *lut, } /* LUT size is only valid for Global and PF table types */ - if (lut_size == ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_128) { - flags |= (ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_128_FLAG << - ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_S) & - ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_M; - } else if (lut_size == ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_512) { + switch (lut_size) { + case ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_128: + break; + case ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_512: flags |= (ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_512_FLAG << ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_S) & ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_M; - } else if ((lut_size == ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_2K) && - (lut_type == ICE_AQC_GSET_RSS_LUT_TABLE_TYPE_PF)) { - flags |= (ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_2K_FLAG << - ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_S) & - ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_M; - } else { + break; + case ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_2K: + if (lut_type == ICE_AQC_GSET_RSS_LUT_TABLE_TYPE_PF) { + flags |= (ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_2K_FLAG << + ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_S) & + ICE_AQC_GSET_RSS_LUT_TABLE_SIZE_M; + break; + } + /* fall-through */ + default: status = ICE_ERR_PARAM; goto ice_aq_get_set_rss_lut_exit; } diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c index 5299caf55a7f..186e764a469a 100644 --- a/drivers/net/ethernet/intel/ice/ice_main.c +++ b/drivers/net/ethernet/intel/ice/ice_main.c @@ -1352,14 +1352,13 @@ static void ice_set_dflt_vsi_ctx(struct ice_vsi_ctx *ctxt) ctxt->info.sw_flags = ICE_AQ_VSI_SW_FLAG_SRC_PRUNE; /* Traffic from VSI can be sent to LAN */ ctxt->info.sw_flags2 = ICE_AQ_VSI_SW_FLAG_LAN_ENA; - /* Allow all packets untagged/tagged */ + /* By default bits 3 and 4 in port_vlan_flags are 0's which results in + * legacy behavior (show VLAN, DEI, and UP) in descriptor. Also, allow + * all packets untagged/tagged. + */ ctxt->info.port_vlan_flags = ((ICE_AQ_VSI_PVLAN_MODE_ALL & ICE_AQ_VSI_PVLAN_MODE_M) >> ICE_AQ_VSI_PVLAN_MODE_S); - /* Show VLAN/UP from packets in Rx descriptors */ - ctxt->info.port_vlan_flags |= ((ICE_AQ_VSI_PVLAN_EMOD_STR_BOTH & - ICE_AQ_VSI_PVLAN_EMOD_M) >> - ICE_AQ_VSI_PVLAN_EMOD_S); /* Have 1:1 UP mapping for both ingress/egress tables */ table |= ICE_UP_TABLE_TRANSLATE(0, 0); table |= ICE_UP_TABLE_TRANSLATE(1, 1); @@ -2058,15 +2057,13 @@ static int ice_req_irq_msix_misc(struct ice_pf *pf) skip_req_irq: ice_ena_misc_vector(pf); - val = (pf->oicr_idx & PFINT_OICR_CTL_MSIX_INDX_M) | - (ICE_RX_ITR & PFINT_OICR_CTL_ITR_INDX_M) | - PFINT_OICR_CTL_CAUSE_ENA_M; + val = ((pf->oicr_idx & PFINT_OICR_CTL_MSIX_INDX_M) | + PFINT_OICR_CTL_CAUSE_ENA_M); wr32(hw, PFINT_OICR_CTL, val); /* This enables Admin queue Interrupt causes */ - val = (pf->oicr_idx & PFINT_FW_CTL_MSIX_INDX_M) | - (ICE_RX_ITR & PFINT_FW_CTL_ITR_INDX_M) | - PFINT_FW_CTL_CAUSE_ENA_M; + val = ((pf->oicr_idx & PFINT_FW_CTL_MSIX_INDX_M) | + PFINT_FW_CTL_CAUSE_ENA_M); wr32(hw, PFINT_FW_CTL, val); itr_gran = hw->itr_gran_200; diff --git a/drivers/net/ethernet/intel/ice/ice_switch.c b/drivers/net/ethernet/intel/ice/ice_switch.c index 723d15f1e90b..6b7ec2ae5ad6 100644 --- a/drivers/net/ethernet/intel/ice/ice_switch.c +++ b/drivers/net/ethernet/intel/ice/ice_switch.c @@ -645,14 +645,14 @@ ice_add_marker_act(struct ice_hw *hw, struct ice_fltr_mgmt_list_entry *m_ent, act |= (1 << ICE_LG_ACT_GENERIC_VALUE_S) & ICE_LG_ACT_GENERIC_VALUE_M; lg_act->pdata.lg_act.act[1] = cpu_to_le32(act); - act = (7 << ICE_LG_ACT_GENERIC_OFFSET_S) & ICE_LG_ACT_GENERIC_VALUE_M; + act = (ICE_LG_ACT_GENERIC_OFF_RX_DESC_PROF_IDX << + ICE_LG_ACT_GENERIC_OFFSET_S) & ICE_LG_ACT_GENERIC_OFFSET_M; /* Third action Marker value */ act |= ICE_LG_ACT_GENERIC; act |= (sw_marker << ICE_LG_ACT_GENERIC_VALUE_S) & ICE_LG_ACT_GENERIC_VALUE_M; - act |= (0 << ICE_LG_ACT_GENERIC_OFFSET_S) & ICE_LG_ACT_GENERIC_VALUE_M; lg_act->pdata.lg_act.act[2] = cpu_to_le32(act); /* call the fill switch rule to fill the lookup tx rx structure */ From 6efa6239e7f8777dccddcebb643e6d9a0304bf43 Mon Sep 17 00:00:00 2001 From: Bruce Allan Date: Thu, 9 Aug 2018 06:28:52 -0700 Subject: [PATCH 070/302] ice: Remove unnecessary node owner check There is already a check for owner == ICE_SCHED_NODE_OWNER_LAN at the beginning of ice_sched_update_vsi_child_nodes. Remove the additional check to address the static analysis tool smatch issue "warn: we tested 'owner' before and it was 'false'". Signed-off-by: Bruce Allan Signed-off-by: Anirudh Venkataramanan Tested-by: Tony Brelinski Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ice/ice_sched.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/net/ethernet/intel/ice/ice_sched.c b/drivers/net/ethernet/intel/ice/ice_sched.c index 2e6c1d92cc88..eeae199469b6 100644 --- a/drivers/net/ethernet/intel/ice/ice_sched.c +++ b/drivers/net/ethernet/intel/ice/ice_sched.c @@ -1576,8 +1576,7 @@ ice_sched_update_vsi_child_nodes(struct ice_port_info *pi, u16 vsi_id, u8 tc, return status; } - if (owner == ICE_SCHED_NODE_OWNER_LAN) - vsi->max_lanq[tc] = new_numqs; + vsi->max_lanq[tc] = new_numqs; return status; } From c0203475765f827e7b2eaf0a87222d0766e2cc4b Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Wed, 22 Aug 2018 23:49:37 +0200 Subject: [PATCH 071/302] bpf: use per htab salt for bucket hash All BPF hash and LRU maps currently have a known and global seed we feed into jhash() which is 0. This is suboptimal, thus fix it by generating a random seed upon hashtab setup time which we can later on feed into jhash() on lookup, update and deletions. Fixes: 0f8e4bd8a1fc8 ("bpf: add hashtable type of eBPF maps") Signed-off-by: Daniel Borkmann Acked-by: Alexei Starovoitov Acked-by: Song Liu Reviewed-by: Eduardo Valentin --- kernel/bpf/hashtab.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/kernel/bpf/hashtab.c b/kernel/bpf/hashtab.c index 04b8eda94e7d..03cc59ee9c95 100644 --- a/kernel/bpf/hashtab.c +++ b/kernel/bpf/hashtab.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include "percpu_freelist.h" #include "bpf_lru_list.h" @@ -41,6 +42,7 @@ struct bpf_htab { atomic_t count; /* number of elements in this hashtable */ u32 n_buckets; /* number of hash buckets */ u32 elem_size; /* size of each element in bytes */ + u32 hashrnd; }; /* each htab element is struct htab_elem + key + value */ @@ -371,6 +373,7 @@ static struct bpf_map *htab_map_alloc(union bpf_attr *attr) if (!htab->buckets) goto free_htab; + htab->hashrnd = get_random_int(); for (i = 0; i < htab->n_buckets; i++) { INIT_HLIST_NULLS_HEAD(&htab->buckets[i].head, i); raw_spin_lock_init(&htab->buckets[i].lock); @@ -402,9 +405,9 @@ static struct bpf_map *htab_map_alloc(union bpf_attr *attr) return ERR_PTR(err); } -static inline u32 htab_map_hash(const void *key, u32 key_len) +static inline u32 htab_map_hash(const void *key, u32 key_len, u32 hashrnd) { - return jhash(key, key_len, 0); + return jhash(key, key_len, hashrnd); } static inline struct bucket *__select_bucket(struct bpf_htab *htab, u32 hash) @@ -470,7 +473,7 @@ static void *__htab_map_lookup_elem(struct bpf_map *map, void *key) key_size = map->key_size; - hash = htab_map_hash(key, key_size); + hash = htab_map_hash(key, key_size, htab->hashrnd); head = select_bucket(htab, hash); @@ -597,7 +600,7 @@ static int htab_map_get_next_key(struct bpf_map *map, void *key, void *next_key) if (!key) goto find_first_elem; - hash = htab_map_hash(key, key_size); + hash = htab_map_hash(key, key_size, htab->hashrnd); head = select_bucket(htab, hash); @@ -824,7 +827,7 @@ static int htab_map_update_elem(struct bpf_map *map, void *key, void *value, key_size = map->key_size; - hash = htab_map_hash(key, key_size); + hash = htab_map_hash(key, key_size, htab->hashrnd); b = __select_bucket(htab, hash); head = &b->head; @@ -880,7 +883,7 @@ static int htab_lru_map_update_elem(struct bpf_map *map, void *key, void *value, key_size = map->key_size; - hash = htab_map_hash(key, key_size); + hash = htab_map_hash(key, key_size, htab->hashrnd); b = __select_bucket(htab, hash); head = &b->head; @@ -945,7 +948,7 @@ static int __htab_percpu_map_update_elem(struct bpf_map *map, void *key, key_size = map->key_size; - hash = htab_map_hash(key, key_size); + hash = htab_map_hash(key, key_size, htab->hashrnd); b = __select_bucket(htab, hash); head = &b->head; @@ -998,7 +1001,7 @@ static int __htab_lru_percpu_map_update_elem(struct bpf_map *map, void *key, key_size = map->key_size; - hash = htab_map_hash(key, key_size); + hash = htab_map_hash(key, key_size, htab->hashrnd); b = __select_bucket(htab, hash); head = &b->head; @@ -1071,7 +1074,7 @@ static int htab_map_delete_elem(struct bpf_map *map, void *key) key_size = map->key_size; - hash = htab_map_hash(key, key_size); + hash = htab_map_hash(key, key_size, htab->hashrnd); b = __select_bucket(htab, hash); head = &b->head; @@ -1103,7 +1106,7 @@ static int htab_lru_map_delete_elem(struct bpf_map *map, void *key) key_size = map->key_size; - hash = htab_map_hash(key, key_size); + hash = htab_map_hash(key, key_size, htab->hashrnd); b = __select_bucket(htab, hash); head = &b->head; From 5ab522443bd1dafa9e32d6f4b029128efda072de Mon Sep 17 00:00:00 2001 From: Anirudh Venkataramanan Date: Thu, 9 Aug 2018 06:28:53 -0700 Subject: [PATCH 072/302] ice: Cleanup magic number Use define for the unit size shift of the Rx LAN context descriptor base address instead of the magic number 7. Signed-off-by: Anirudh Venkataramanan Tested-by: Tony Brelinski Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ice/ice_lan_tx_rx.h | 1 + drivers/net/ethernet/intel/ice/ice_main.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/intel/ice/ice_lan_tx_rx.h b/drivers/net/ethernet/intel/ice/ice_lan_tx_rx.h index d23a91665b46..068dbc740b76 100644 --- a/drivers/net/ethernet/intel/ice/ice_lan_tx_rx.h +++ b/drivers/net/ethernet/intel/ice/ice_lan_tx_rx.h @@ -265,6 +265,7 @@ enum ice_rx_flex_desc_status_error_0_bits { struct ice_rlan_ctx { u16 head; u16 cpuid; /* bigger than needed, see above for reason */ +#define ICE_RLAN_BASE_S 7 u64 base; u16 qlen; #define ICE_RLAN_CTX_DBUF_S 7 diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c index 186e764a469a..7d65e0ed3588 100644 --- a/drivers/net/ethernet/intel/ice/ice_main.c +++ b/drivers/net/ethernet/intel/ice/ice_main.c @@ -3983,7 +3983,7 @@ static int ice_setup_rx_ctx(struct ice_ring *ring) /* clear the context structure first */ memset(&rlan_ctx, 0, sizeof(rlan_ctx)); - rlan_ctx.base = ring->dma >> 7; + rlan_ctx.base = ring->dma >> ICE_RLAN_BASE_S; rlan_ctx.qlen = ring->count; From f8ba7db850350319348b6d3c276f8ba19bc098ef Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Thu, 9 Aug 2018 06:28:54 -0700 Subject: [PATCH 073/302] ice: Report stats for allocated queues via ethtool stats It is not safe to have the string table for statistics change order or size over the lifetime of a given netdevice. This is because of the nature of the 3-step process for obtaining stats. First, user space performs a request for the size of the strings table. Second it performs a separate request for the strings themselves, after allocating space for the table. Third, it requests the stats themselves, also allocating space for the table. If the size decreased, there is potential to see garbage data or stats values. In the worst case, we could potentially see stats values become mis-aligned with their strings, so that it looks like a statistic is being reported differently than it actually is. Even worse, if the size increased, there is potential that the strings table or stats table was not allocated large enough and the stats code could access and write to memory it should not, potentially resulting in undefined behavior and system crashes. It isn't even safe if the size always changes under the RTNL lock. This is because the calls take place over multiple user space commands, so it is not possible to hold the RTNL lock for the entire duration of obtaining strings and stats. Further, not all consumers of the ethtool API are the user space ethtool program, and it is possible that one assumes the strings will not change (valid under the current contract), and thus only requests the stats values when requesting stats in a loop. Finally, it's not possible in the general case to detect when the size changes, because it is quite possible that one value which could impact the stat size increased, while another decreased. This would result in the same total number of stats, but reordering them so that stats no longer line up with the strings they belong to. Since only size changes aren't enough, we would need some sort of hash or token to determine when the strings no longer match. This would require extending the ethtool stats commands, but there is no more space in the relevant structures. The real solution to resolve this would be to add a completely new API for stats, probably over netlink. In the ice driver, the only thing impacting the stats that is not constant is the number of queues. Instead of reporting stats for each used queue, report stats for each allocated queue. We do not change the number of queues allocated for a given netdevice, as we pass this into the alloc_etherdev_mq() function to set the num_tx_queues and num_rx_queues. This resolves the potential bugs at the slight cost of displaying many queue statistics which will not be activated. Signed-off-by: Jacob Keller Signed-off-by: Anirudh Venkataramanan Tested-by: Tony Brelinski Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ice/ice.h | 7 +++ drivers/net/ethernet/intel/ice/ice_ethtool.c | 52 +++++++++++++++----- 2 files changed, 46 insertions(+), 13 deletions(-) diff --git a/drivers/net/ethernet/intel/ice/ice.h b/drivers/net/ethernet/intel/ice/ice.h index d8b5fff581e7..ed071ea75f20 100644 --- a/drivers/net/ethernet/intel/ice/ice.h +++ b/drivers/net/ethernet/intel/ice/ice.h @@ -89,6 +89,13 @@ extern const char ice_drv_ver[]; #define ice_for_each_rxq(vsi, i) \ for ((i) = 0; (i) < (vsi)->num_rxq; (i)++) +/* Macros for each allocated tx/rx ring whether used or not in a VSI */ +#define ice_for_each_alloc_txq(vsi, i) \ + for ((i) = 0; (i) < (vsi)->alloc_txq; (i)++) + +#define ice_for_each_alloc_rxq(vsi, i) \ + for ((i) = 0; (i) < (vsi)->alloc_rxq; (i)++) + struct ice_tc_info { u16 qoffset; u16 qcount; diff --git a/drivers/net/ethernet/intel/ice/ice_ethtool.c b/drivers/net/ethernet/intel/ice/ice_ethtool.c index 1db304c01d10..c71a9b528d6d 100644 --- a/drivers/net/ethernet/intel/ice/ice_ethtool.c +++ b/drivers/net/ethernet/intel/ice/ice_ethtool.c @@ -26,7 +26,7 @@ static int ice_q_stats_len(struct net_device *netdev) { struct ice_netdev_priv *np = netdev_priv(netdev); - return ((np->vsi->num_txq + np->vsi->num_rxq) * + return ((np->vsi->alloc_txq + np->vsi->alloc_rxq) * (sizeof(struct ice_q_stats) / sizeof(u64))); } @@ -218,7 +218,7 @@ static void ice_get_strings(struct net_device *netdev, u32 stringset, u8 *data) p += ETH_GSTRING_LEN; } - ice_for_each_txq(vsi, i) { + ice_for_each_alloc_txq(vsi, i) { snprintf(p, ETH_GSTRING_LEN, "tx-queue-%u.tx_packets", i); p += ETH_GSTRING_LEN; @@ -226,7 +226,7 @@ static void ice_get_strings(struct net_device *netdev, u32 stringset, u8 *data) p += ETH_GSTRING_LEN; } - ice_for_each_rxq(vsi, i) { + ice_for_each_alloc_rxq(vsi, i) { snprintf(p, ETH_GSTRING_LEN, "rx-queue-%u.rx_packets", i); p += ETH_GSTRING_LEN; @@ -253,6 +253,24 @@ static int ice_get_sset_count(struct net_device *netdev, int sset) { switch (sset) { case ETH_SS_STATS: + /* The number (and order) of strings reported *must* remain + * constant for a given netdevice. This function must not + * report a different number based on run time parameters + * (such as the number of queues in use, or the setting of + * a private ethtool flag). This is due to the nature of the + * ethtool stats API. + * + * User space programs such as ethtool must make 3 separate + * ioctl requests, one for size, one for the strings, and + * finally one for the stats. Since these cross into + * user space, changes to the number or size could result in + * undefined memory access or incorrect string<->value + * correlations for statistics. + * + * Even if it appears to be safe, changes to the size or + * order of strings will suffer from race conditions and are + * not safe. + */ return ICE_ALL_STATS_LEN(netdev); default: return -EOPNOTSUPP; @@ -280,18 +298,26 @@ ice_get_ethtool_stats(struct net_device *netdev, /* populate per queue stats */ rcu_read_lock(); - ice_for_each_txq(vsi, j) { + ice_for_each_alloc_txq(vsi, j) { ring = READ_ONCE(vsi->tx_rings[j]); - if (!ring) - continue; - data[i++] = ring->stats.pkts; - data[i++] = ring->stats.bytes; + if (ring) { + data[i++] = ring->stats.pkts; + data[i++] = ring->stats.bytes; + } else { + data[i++] = 0; + data[i++] = 0; + } } - ice_for_each_rxq(vsi, j) { + ice_for_each_alloc_rxq(vsi, j) { ring = READ_ONCE(vsi->rx_rings[j]); - data[i++] = ring->stats.pkts; - data[i++] = ring->stats.bytes; + if (ring) { + data[i++] = ring->stats.pkts; + data[i++] = ring->stats.bytes; + } else { + data[i++] = 0; + data[i++] = 0; + } } rcu_read_unlock(); @@ -519,7 +545,7 @@ ice_set_ringparam(struct net_device *netdev, struct ethtool_ringparam *ring) goto done; } - for (i = 0; i < vsi->num_txq; i++) { + for (i = 0; i < vsi->alloc_txq; i++) { /* clone ring and setup updated count */ tx_rings[i] = *vsi->tx_rings[i]; tx_rings[i].count = new_tx_cnt; @@ -551,7 +577,7 @@ ice_set_ringparam(struct net_device *netdev, struct ethtool_ringparam *ring) goto done; } - for (i = 0; i < vsi->num_rxq; i++) { + for (i = 0; i < vsi->alloc_rxq; i++) { /* clone ring and setup updated count */ rx_rings[i] = *vsi->rx_rings[i]; rx_rings[i].count = new_rx_cnt; From b29bc220e2c7bd494a4605defcd93b18d5a8cf86 Mon Sep 17 00:00:00 2001 From: Preethi Banala Date: Thu, 9 Aug 2018 06:28:55 -0700 Subject: [PATCH 074/302] ice: Clean control queues only when they are initialized Clean control queues only when they are initialized. One of the ways to validate if the basic initialization is done is by checking value of cq->sq.head and cq->rq.head variables that specify the register address. This patch adds a check to avoid NULL pointer dereference crash when tried to shutdown uninitialized control queue. Signed-off-by: Preethi Banala Signed-off-by: Anirudh Venkataramanan Tested-by: Tony Brelinski Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ice/ice_controlq.c | 24 ++++++++++++------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/drivers/net/ethernet/intel/ice/ice_controlq.c b/drivers/net/ethernet/intel/ice/ice_controlq.c index 7c511f144ed6..c064416080e7 100644 --- a/drivers/net/ethernet/intel/ice/ice_controlq.c +++ b/drivers/net/ethernet/intel/ice/ice_controlq.c @@ -597,10 +597,14 @@ static enum ice_status ice_init_check_adminq(struct ice_hw *hw) return 0; init_ctrlq_free_rq: - ice_shutdown_rq(hw, cq); - ice_shutdown_sq(hw, cq); - mutex_destroy(&cq->sq_lock); - mutex_destroy(&cq->rq_lock); + if (cq->rq.head) { + ice_shutdown_rq(hw, cq); + mutex_destroy(&cq->rq_lock); + } + if (cq->sq.head) { + ice_shutdown_sq(hw, cq); + mutex_destroy(&cq->sq_lock); + } return status; } @@ -706,10 +710,14 @@ static void ice_shutdown_ctrlq(struct ice_hw *hw, enum ice_ctl_q q_type) return; } - ice_shutdown_sq(hw, cq); - ice_shutdown_rq(hw, cq); - mutex_destroy(&cq->sq_lock); - mutex_destroy(&cq->rq_lock); + if (cq->sq.head) { + ice_shutdown_sq(hw, cq); + mutex_destroy(&cq->sq_lock); + } + if (cq->rq.head) { + ice_shutdown_rq(hw, cq); + mutex_destroy(&cq->rq_lock); + } } /** From 3d6b640efcc1b07709b42dd2e9609401c6f88633 Mon Sep 17 00:00:00 2001 From: Anirudh Venkataramanan Date: Thu, 9 Aug 2018 06:28:56 -0700 Subject: [PATCH 075/302] ice: Fix bugs in control queue processing This patch is a consolidation of multiple bug fixes for control queue processing. 1) In ice_clean_adminq_subtask() remove unnecessary reads/writes to registers. The bits PFINT_FW_CTL, PFINT_MBX_CTL and PFINT_SB_CTL are not set when an interrupt arrives, which means that clearing them again can be omitted. 2) Get an accurate value in "pending" by re-reading the control queue head register from the hardware. 3) Fix a corner case involving lost control queue messages by checking for new control messages (using ice_ctrlq_pending) before exiting the cleanup routine. Signed-off-by: Anirudh Venkataramanan Tested-by: Tony Brelinski Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ice/ice_controlq.c | 5 +++- drivers/net/ethernet/intel/ice/ice_main.c | 26 ++++++++++++++++--- 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/drivers/net/ethernet/intel/ice/ice_controlq.c b/drivers/net/ethernet/intel/ice/ice_controlq.c index c064416080e7..62be72fdc8f3 100644 --- a/drivers/net/ethernet/intel/ice/ice_controlq.c +++ b/drivers/net/ethernet/intel/ice/ice_controlq.c @@ -1065,8 +1065,11 @@ ice_clean_rq_elem(struct ice_hw *hw, struct ice_ctl_q_info *cq, clean_rq_elem_out: /* Set pending if needed, unlock and return */ - if (pending) + if (pending) { + /* re-read HW head to calculate actual pending messages */ + ntu = (u16)(rd32(hw, cq->rq.head) & cq->rq.head_mask); *pending = (u16)((ntc > ntu ? cq->rq.count : 0) + (ntu - ntc)); + } clean_rq_elem_err: mutex_unlock(&cq->rq_lock); diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c index 7d65e0ed3588..f3ba4f76b6cb 100644 --- a/drivers/net/ethernet/intel/ice/ice_main.c +++ b/drivers/net/ethernet/intel/ice/ice_main.c @@ -916,6 +916,21 @@ static int __ice_clean_ctrlq(struct ice_pf *pf, enum ice_ctl_q q_type) return pending && (i == ICE_DFLT_IRQ_WORK); } +/** + * ice_ctrlq_pending - check if there is a difference between ntc and ntu + * @hw: pointer to hardware info + * @cq: control queue information + * + * returns true if there are pending messages in a queue, false if there aren't + */ +static bool ice_ctrlq_pending(struct ice_hw *hw, struct ice_ctl_q_info *cq) +{ + u16 ntu; + + ntu = (u16)(rd32(hw, cq->rq.head) & cq->rq.head_mask); + return cq->rq.next_to_clean != ntu; +} + /** * ice_clean_adminq_subtask - clean the AdminQ rings * @pf: board private structure @@ -923,7 +938,6 @@ static int __ice_clean_ctrlq(struct ice_pf *pf, enum ice_ctl_q q_type) static void ice_clean_adminq_subtask(struct ice_pf *pf) { struct ice_hw *hw = &pf->hw; - u32 val; if (!test_bit(__ICE_ADMINQ_EVENT_PENDING, pf->state)) return; @@ -933,9 +947,13 @@ static void ice_clean_adminq_subtask(struct ice_pf *pf) clear_bit(__ICE_ADMINQ_EVENT_PENDING, pf->state); - /* re-enable Admin queue interrupt causes */ - val = rd32(hw, PFINT_FW_CTL); - wr32(hw, PFINT_FW_CTL, (val | PFINT_FW_CTL_CAUSE_ENA_M)); + /* There might be a situation where new messages arrive to a control + * queue between processing the last message and clearing the + * EVENT_PENDING bit. So before exiting, check queue head again (using + * ice_ctrlq_pending) and process new messages if any. + */ + if (ice_ctrlq_pending(hw, &hw->adminq)) + __ice_clean_ctrlq(pf, ICE_CTL_Q_ADMIN); ice_flush(hw); } From 1eb43fc754485d772b1165118a8fb80c385f0492 Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Thu, 9 Aug 2018 06:28:57 -0700 Subject: [PATCH 076/302] ice: Use order_base_2 to calculate higher power of 2 Currently, we use a combination of ilog2 and is_power_of_2() to calculate the next power of 2 for the qcount. This appears to be causing a warning on some combinations of GCC and the Linux kernel: MODPOST 1 modules WARNING: "____ilog2_NaN" [ice.ko] undefined! This appears to because because GCC realizes that qcount could be zero in some circumstances and thus attempts to link against the intentionally undefined ___ilog2_NaN function. The order_base_2 function is intentionally defined to return 0 when passed 0 as an argument, and thus will be safe to use here. This not only fixes the warning but makes the resulting code slightly cleaner, and is really what we should have used originally. Also update the comment to make it more clear that we are rounding up, not just incrementing the ilog2 of qcount unconditionally. Signed-off-by: Jacob Keller Signed-off-by: Anirudh Venkataramanan Tested-by: Tony Brelinski Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ice/ice_main.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c index f3ba4f76b6cb..3eff1d2d1543 100644 --- a/drivers/net/ethernet/intel/ice/ice_main.c +++ b/drivers/net/ethernet/intel/ice/ice_main.c @@ -1313,11 +1313,8 @@ static void ice_vsi_setup_q_map(struct ice_vsi *vsi, struct ice_vsi_ctx *ctxt) qcount = numq_tc; } - /* find higher power-of-2 of qcount */ - pow = ilog2(qcount); - - if (!is_power_of_2(qcount)) - pow++; + /* find the (rounded up) power-of-2 of qcount */ + pow = order_base_2(qcount); for (i = 0; i < ICE_MAX_TRAFFIC_CLASS; i++) { if (!(vsi->tc_cfg.ena_tc & BIT(i))) { From 5d8778d803e21f235e9bc727b5bd619f02abb88b Mon Sep 17 00:00:00 2001 From: Brett Creeley Date: Thu, 9 Aug 2018 06:28:58 -0700 Subject: [PATCH 077/302] ice: Set VLAN flags correctly In the struct ice_aqc_vsi_props the field port_vlan_flags is an overloaded term because it is used for both port VLANs (PVLANs) and regular VLANs. This is an issue and is very confusing especially when dealing with VFs because normal VLANs and port VLANs are not the same. To fix this the field was renamed to vlan_flags and all of the #define's labeled *_PVLAN_* were renamed to *_VLAN_* if they are not specific to port VLANs. Also in ice_vsi_manage_vlan_stripping, set the ICE_AQ_VSI_VLAN_MODE_ALL bit to allow the driver to add a VLAN tag to all packets it sends. Signed-off-by: Brett Creeley Signed-off-by: Anirudh Venkataramanan Tested-by: Tony Brelinski Signed-off-by: Jeff Kirsher --- .../net/ethernet/intel/ice/ice_adminq_cmd.h | 24 +++++++------- drivers/net/ethernet/intel/ice/ice_main.c | 31 +++++++++++-------- 2 files changed, 30 insertions(+), 25 deletions(-) diff --git a/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h b/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h index 6d3e11659ba5..a0614f472658 100644 --- a/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h +++ b/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h @@ -329,19 +329,19 @@ struct ice_aqc_vsi_props { /* VLAN section */ __le16 pvid; /* VLANS include priority bits */ u8 pvlan_reserved[2]; - u8 port_vlan_flags; -#define ICE_AQ_VSI_PVLAN_MODE_S 0 -#define ICE_AQ_VSI_PVLAN_MODE_M (0x3 << ICE_AQ_VSI_PVLAN_MODE_S) -#define ICE_AQ_VSI_PVLAN_MODE_UNTAGGED 0x1 -#define ICE_AQ_VSI_PVLAN_MODE_TAGGED 0x2 -#define ICE_AQ_VSI_PVLAN_MODE_ALL 0x3 + u8 vlan_flags; +#define ICE_AQ_VSI_VLAN_MODE_S 0 +#define ICE_AQ_VSI_VLAN_MODE_M (0x3 << ICE_AQ_VSI_VLAN_MODE_S) +#define ICE_AQ_VSI_VLAN_MODE_UNTAGGED 0x1 +#define ICE_AQ_VSI_VLAN_MODE_TAGGED 0x2 +#define ICE_AQ_VSI_VLAN_MODE_ALL 0x3 #define ICE_AQ_VSI_PVLAN_INSERT_PVID BIT(2) -#define ICE_AQ_VSI_PVLAN_EMOD_S 3 -#define ICE_AQ_VSI_PVLAN_EMOD_M (0x3 << ICE_AQ_VSI_PVLAN_EMOD_S) -#define ICE_AQ_VSI_PVLAN_EMOD_STR_BOTH (0x0 << ICE_AQ_VSI_PVLAN_EMOD_S) -#define ICE_AQ_VSI_PVLAN_EMOD_STR_UP (0x1 << ICE_AQ_VSI_PVLAN_EMOD_S) -#define ICE_AQ_VSI_PVLAN_EMOD_STR (0x2 << ICE_AQ_VSI_PVLAN_EMOD_S) -#define ICE_AQ_VSI_PVLAN_EMOD_NOTHING (0x3 << ICE_AQ_VSI_PVLAN_EMOD_S) +#define ICE_AQ_VSI_VLAN_EMOD_S 3 +#define ICE_AQ_VSI_VLAN_EMOD_M (0x3 << ICE_AQ_VSI_VLAN_EMOD_S) +#define ICE_AQ_VSI_VLAN_EMOD_STR_BOTH (0x0 << ICE_AQ_VSI_VLAN_EMOD_S) +#define ICE_AQ_VSI_VLAN_EMOD_STR_UP (0x1 << ICE_AQ_VSI_VLAN_EMOD_S) +#define ICE_AQ_VSI_VLAN_EMOD_STR (0x2 << ICE_AQ_VSI_VLAN_EMOD_S) +#define ICE_AQ_VSI_VLAN_EMOD_NOTHING (0x3 << ICE_AQ_VSI_VLAN_EMOD_S) u8 pvlan_reserved2[3]; /* ingress egress up sections */ __le32 ingress_table; /* bitmap, 3 bits per up */ diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c index 3eff1d2d1543..68003fad33d1 100644 --- a/drivers/net/ethernet/intel/ice/ice_main.c +++ b/drivers/net/ethernet/intel/ice/ice_main.c @@ -1367,13 +1367,15 @@ static void ice_set_dflt_vsi_ctx(struct ice_vsi_ctx *ctxt) ctxt->info.sw_flags = ICE_AQ_VSI_SW_FLAG_SRC_PRUNE; /* Traffic from VSI can be sent to LAN */ ctxt->info.sw_flags2 = ICE_AQ_VSI_SW_FLAG_LAN_ENA; - /* By default bits 3 and 4 in port_vlan_flags are 0's which results in - * legacy behavior (show VLAN, DEI, and UP) in descriptor. Also, allow - * all packets untagged/tagged. + + /* By default bits 3 and 4 in vlan_flags are 0's which results in legacy + * behavior (show VLAN, DEI, and UP) in descriptor. Also, allow all + * packets untagged/tagged. */ - ctxt->info.port_vlan_flags = ((ICE_AQ_VSI_PVLAN_MODE_ALL & - ICE_AQ_VSI_PVLAN_MODE_M) >> - ICE_AQ_VSI_PVLAN_MODE_S); + ctxt->info.vlan_flags = ((ICE_AQ_VSI_VLAN_MODE_ALL & + ICE_AQ_VSI_VLAN_MODE_M) >> + ICE_AQ_VSI_VLAN_MODE_S); + /* Have 1:1 UP mapping for both ingress/egress tables */ table |= ICE_UP_TABLE_TRANSLATE(0, 0); table |= ICE_UP_TABLE_TRANSLATE(1, 1); @@ -3732,10 +3734,10 @@ static int ice_vsi_manage_vlan_insertion(struct ice_vsi *vsi) enum ice_status status; /* Here we are configuring the VSI to let the driver add VLAN tags by - * setting port_vlan_flags to ICE_AQ_VSI_PVLAN_MODE_ALL. The actual VLAN - * tag insertion happens in the Tx hot path, in ice_tx_map. + * setting vlan_flags to ICE_AQ_VSI_VLAN_MODE_ALL. The actual VLAN tag + * insertion happens in the Tx hot path, in ice_tx_map. */ - ctxt.info.port_vlan_flags = ICE_AQ_VSI_PVLAN_MODE_ALL; + ctxt.info.vlan_flags = ICE_AQ_VSI_VLAN_MODE_ALL; ctxt.info.valid_sections = cpu_to_le16(ICE_AQ_VSI_PROP_VLAN_VALID); ctxt.vsi_num = vsi->vsi_num; @@ -3747,7 +3749,7 @@ static int ice_vsi_manage_vlan_insertion(struct ice_vsi *vsi) return -EIO; } - vsi->info.port_vlan_flags = ctxt.info.port_vlan_flags; + vsi->info.vlan_flags = ctxt.info.vlan_flags; return 0; } @@ -3769,12 +3771,15 @@ static int ice_vsi_manage_vlan_stripping(struct ice_vsi *vsi, bool ena) */ if (ena) { /* Strip VLAN tag from Rx packet and put it in the desc */ - ctxt.info.port_vlan_flags = ICE_AQ_VSI_PVLAN_EMOD_STR_BOTH; + ctxt.info.vlan_flags = ICE_AQ_VSI_VLAN_EMOD_STR_BOTH; } else { /* Disable stripping. Leave tag in packet */ - ctxt.info.port_vlan_flags = ICE_AQ_VSI_PVLAN_EMOD_NOTHING; + ctxt.info.vlan_flags = ICE_AQ_VSI_VLAN_EMOD_NOTHING; } + /* Allow all packets untagged/tagged */ + ctxt.info.vlan_flags |= ICE_AQ_VSI_VLAN_MODE_ALL; + ctxt.info.valid_sections = cpu_to_le16(ICE_AQ_VSI_PROP_VLAN_VALID); ctxt.vsi_num = vsi->vsi_num; @@ -3785,7 +3790,7 @@ static int ice_vsi_manage_vlan_stripping(struct ice_vsi *vsi, bool ena) return -EIO; } - vsi->info.port_vlan_flags = ctxt.info.port_vlan_flags; + vsi->info.vlan_flags = ctxt.info.vlan_flags; return 0; } From 785e76d7a2051a9e28b9134d5388a45b16f5eb72 Mon Sep 17 00:00:00 2001 From: Quentin Monnet Date: Thu, 23 Aug 2018 17:46:25 +0100 Subject: [PATCH 078/302] tools: bpftool: return from do_event_pipe() on bad arguments When command line parsing fails in the while loop in do_event_pipe() because the number of arguments is incorrect or because the keyword is unknown, an error message is displayed, but bpftool remains stuck in the loop. Make sure we exit the loop upon failure. Fixes: f412eed9dfde ("tools: bpftool: add simple perf event output reader") Signed-off-by: Quentin Monnet Reviewed-by: Jakub Kicinski Signed-off-by: Daniel Borkmann --- tools/bpf/bpftool/map_perf_ring.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tools/bpf/bpftool/map_perf_ring.c b/tools/bpf/bpftool/map_perf_ring.c index 1832100d1b27..6d41323be291 100644 --- a/tools/bpf/bpftool/map_perf_ring.c +++ b/tools/bpf/bpftool/map_perf_ring.c @@ -194,8 +194,10 @@ int do_event_pipe(int argc, char **argv) } while (argc) { - if (argc < 2) + if (argc < 2) { BAD_ARG(); + goto err_close_map; + } if (is_prefix(*argv, "cpu")) { char *endptr; @@ -221,6 +223,7 @@ int do_event_pipe(int argc, char **argv) NEXT_ARG(); } else { BAD_ARG(); + goto err_close_map; } do_all = false; From 3bcd7fa37f33cda8c5639a908e9eb42d856e5d8b Mon Sep 17 00:00:00 2001 From: Bruce Allan Date: Thu, 9 Aug 2018 06:28:59 -0700 Subject: [PATCH 079/302] ice: Update to interrupts enabled in OICR Remove the following interrupt causes that are not applicable or not handled: - PFINT_OICR_HLP_RDY_M - PFINT_OICR_CPM_RDY_M - PFINT_OICR_GPIO_M - PFINT_OICR_STORM_DETECT_M Add the following interrupt cause that's actually handled in ice_misc_intr: - PFINT_OICR_PE_CRITERR_M Signed-off-by: Bruce Allan Signed-off-by: Anirudh Venkataramanan Tested-by: Tony Brelinski Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ice/ice_hw_autogen.h | 8 -------- drivers/net/ethernet/intel/ice/ice_main.c | 9 +++------ 2 files changed, 3 insertions(+), 14 deletions(-) diff --git a/drivers/net/ethernet/intel/ice/ice_hw_autogen.h b/drivers/net/ethernet/intel/ice/ice_hw_autogen.h index 499904874b3f..6076fc87df9d 100644 --- a/drivers/net/ethernet/intel/ice/ice_hw_autogen.h +++ b/drivers/net/ethernet/intel/ice/ice_hw_autogen.h @@ -121,10 +121,6 @@ #define PFINT_FW_CTL_CAUSE_ENA_S 30 #define PFINT_FW_CTL_CAUSE_ENA_M BIT(PFINT_FW_CTL_CAUSE_ENA_S) #define PFINT_OICR 0x0016CA00 -#define PFINT_OICR_HLP_RDY_S 14 -#define PFINT_OICR_HLP_RDY_M BIT(PFINT_OICR_HLP_RDY_S) -#define PFINT_OICR_CPM_RDY_S 15 -#define PFINT_OICR_CPM_RDY_M BIT(PFINT_OICR_CPM_RDY_S) #define PFINT_OICR_ECC_ERR_S 16 #define PFINT_OICR_ECC_ERR_M BIT(PFINT_OICR_ECC_ERR_S) #define PFINT_OICR_MAL_DETECT_S 19 @@ -133,10 +129,6 @@ #define PFINT_OICR_GRST_M BIT(PFINT_OICR_GRST_S) #define PFINT_OICR_PCI_EXCEPTION_S 21 #define PFINT_OICR_PCI_EXCEPTION_M BIT(PFINT_OICR_PCI_EXCEPTION_S) -#define PFINT_OICR_GPIO_S 22 -#define PFINT_OICR_GPIO_M BIT(PFINT_OICR_GPIO_S) -#define PFINT_OICR_STORM_DETECT_S 24 -#define PFINT_OICR_STORM_DETECT_M BIT(PFINT_OICR_STORM_DETECT_S) #define PFINT_OICR_HMC_ERR_S 26 #define PFINT_OICR_HMC_ERR_M BIT(PFINT_OICR_HMC_ERR_S) #define PFINT_OICR_PE_CRITERR_S 28 diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c index 68003fad33d1..34be94a30a60 100644 --- a/drivers/net/ethernet/intel/ice/ice_main.c +++ b/drivers/net/ethernet/intel/ice/ice_main.c @@ -1704,15 +1704,12 @@ static void ice_ena_misc_vector(struct ice_pf *pf) wr32(hw, PFINT_OICR_ENA, 0); /* disable all */ rd32(hw, PFINT_OICR); /* read to clear */ - val = (PFINT_OICR_HLP_RDY_M | - PFINT_OICR_CPM_RDY_M | - PFINT_OICR_ECC_ERR_M | + val = (PFINT_OICR_ECC_ERR_M | PFINT_OICR_MAL_DETECT_M | PFINT_OICR_GRST_M | PFINT_OICR_PCI_EXCEPTION_M | - PFINT_OICR_GPIO_M | - PFINT_OICR_STORM_DETECT_M | - PFINT_OICR_HMC_ERR_M); + PFINT_OICR_HMC_ERR_M | + PFINT_OICR_PE_CRITERR_M); wr32(hw, PFINT_OICR_ENA, val); From c7f2c42b80ed6009f44e355aefc1e40db9485a9d Mon Sep 17 00:00:00 2001 From: Anirudh Venkataramanan Date: Thu, 9 Aug 2018 06:29:00 -0700 Subject: [PATCH 080/302] ice: Fix a few null pointer dereference issues 1) When ice_ena_msix_range() fails to reserve vectors, a devm_kfree() warning was seen in the error flow path. So check pf->irq_tracker before use in ice_clear_interrupt_scheme(). 2) In ice_vsi_cfg(), check vsi->netdev before use. 3) In ice_get_link_status, check link_up before use. Signed-off-by: Anirudh Venkataramanan Tested-by: Tony Brelinski Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ice/ice_common.c | 2 +- drivers/net/ethernet/intel/ice/ice_main.c | 17 ++++++++++------- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/drivers/net/ethernet/intel/ice/ice_common.c b/drivers/net/ethernet/intel/ice/ice_common.c index d5300b606d5a..ebd701ac9428 100644 --- a/drivers/net/ethernet/intel/ice/ice_common.c +++ b/drivers/net/ethernet/intel/ice/ice_common.c @@ -1483,7 +1483,7 @@ enum ice_status ice_get_link_status(struct ice_port_info *pi, bool *link_up) struct ice_phy_info *phy_info; enum ice_status status = 0; - if (!pi) + if (!pi || !link_up) return ICE_ERR_PARAM; phy_info = &pi->phy; diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c index 34be94a30a60..d5d83c8848f8 100644 --- a/drivers/net/ethernet/intel/ice/ice_main.c +++ b/drivers/net/ethernet/intel/ice/ice_main.c @@ -3257,8 +3257,10 @@ static void ice_clear_interrupt_scheme(struct ice_pf *pf) if (test_bit(ICE_FLAG_MSIX_ENA, pf->flags)) ice_dis_msix(pf); - devm_kfree(&pf->pdev->dev, pf->irq_tracker); - pf->irq_tracker = NULL; + if (pf->irq_tracker) { + devm_kfree(&pf->pdev->dev, pf->irq_tracker); + pf->irq_tracker = NULL; + } } /** @@ -4112,11 +4114,12 @@ static int ice_vsi_cfg(struct ice_vsi *vsi) { int err; - ice_set_rx_mode(vsi->netdev); - - err = ice_restore_vlan(vsi); - if (err) - return err; + if (vsi->netdev) { + ice_set_rx_mode(vsi->netdev); + err = ice_restore_vlan(vsi); + if (err) + return err; + } err = ice_vsi_cfg_txqs(vsi); if (!err) From dab0588fb616c1774bbf108eab1749dda4ac6942 Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Thu, 9 Aug 2018 06:29:01 -0700 Subject: [PATCH 081/302] ice: Fix potential return of uninitialized value In ice_vsi_setup_[tx|rx]_rings, err is uninitialized which can result in a garbage value return to the caller. Fix that. Signed-off-by: Jesse Brandeburg Signed-off-by: Anirudh Venkataramanan Tested-by: Tony Brelinski Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ice/ice_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c index d5d83c8848f8..e23156515186 100644 --- a/drivers/net/ethernet/intel/ice/ice_main.c +++ b/drivers/net/ethernet/intel/ice/ice_main.c @@ -4885,7 +4885,7 @@ int ice_down(struct ice_vsi *vsi) */ static int ice_vsi_setup_tx_rings(struct ice_vsi *vsi) { - int i, err; + int i, err = 0; if (!vsi->num_txq) { dev_err(&vsi->back->pdev->dev, "VSI %d has 0 Tx queues\n", @@ -4910,7 +4910,7 @@ static int ice_vsi_setup_tx_rings(struct ice_vsi *vsi) */ static int ice_vsi_setup_rx_rings(struct ice_vsi *vsi) { - int i, err; + int i, err = 0; if (!vsi->num_rxq) { dev_err(&vsi->back->pdev->dev, "VSI %d has 0 Rx queues\n", From 43f8b22450f0a721915f1d2c7e3db6dd9573e76b Mon Sep 17 00:00:00 2001 From: Bruce Allan Date: Thu, 9 Aug 2018 06:29:02 -0700 Subject: [PATCH 082/302] ice: Change struct members from bool to u8 Recent versions of checkpatch have a new warning based on a documented preference of Linus to not use bool in structures due to wasted space and the size of bool is implementation dependent. For more information, see the email thread at https://lkml.org/lkml/2017/11/21/384. Signed-off-by: Bruce Allan Signed-off-by: Anirudh Venkataramanan Tested-by: Tony Brelinski Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ice/ice.h | 8 ++++---- drivers/net/ethernet/intel/ice/ice_switch.h | 6 +++--- drivers/net/ethernet/intel/ice/ice_txrx.h | 2 +- drivers/net/ethernet/intel/ice/ice_type.h | 16 ++++++++-------- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/drivers/net/ethernet/intel/ice/ice.h b/drivers/net/ethernet/intel/ice/ice.h index ed071ea75f20..868f4a1d0f72 100644 --- a/drivers/net/ethernet/intel/ice/ice.h +++ b/drivers/net/ethernet/intel/ice/ice.h @@ -196,9 +196,9 @@ struct ice_vsi { struct list_head tmp_sync_list; /* MAC filters to be synced */ struct list_head tmp_unsync_list; /* MAC filters to be unsynced */ - bool irqs_ready; - bool current_isup; /* Sync 'link up' logging */ - bool stat_offsets_loaded; + u8 irqs_ready; + u8 current_isup; /* Sync 'link up' logging */ + u8 stat_offsets_loaded; /* queue information */ u8 tx_mapping_mode; /* ICE_MAP_MODE_[CONTIG|SCATTER] */ @@ -269,7 +269,7 @@ struct ice_pf { struct ice_hw_port_stats stats; struct ice_hw_port_stats stats_prev; struct ice_hw hw; - bool stat_prev_loaded; /* has previous stats been loaded */ + u8 stat_prev_loaded; /* has previous stats been loaded */ char int_name[ICE_INT_NAME_STR_LEN]; }; diff --git a/drivers/net/ethernet/intel/ice/ice_switch.h b/drivers/net/ethernet/intel/ice/ice_switch.h index 6f4a0d159dbf..9b8ec128ee31 100644 --- a/drivers/net/ethernet/intel/ice/ice_switch.h +++ b/drivers/net/ethernet/intel/ice/ice_switch.h @@ -17,7 +17,7 @@ struct ice_vsi_ctx { u16 vsis_unallocated; u16 flags; struct ice_aqc_vsi_props info; - bool alloc_from_pool; + u8 alloc_from_pool; }; enum ice_sw_fwd_act_type { @@ -94,8 +94,8 @@ struct ice_fltr_info { u8 qgrp_size; /* Rule creations populate these indicators basing on the switch type */ - bool lb_en; /* Indicate if packet can be looped back */ - bool lan_en; /* Indicate if packet can be forwarded to the uplink */ + u8 lb_en; /* Indicate if packet can be looped back */ + u8 lan_en; /* Indicate if packet can be forwarded to the uplink */ }; /* Bookkeeping structure to hold bitmap of VSIs corresponding to VSI list id */ diff --git a/drivers/net/ethernet/intel/ice/ice_txrx.h b/drivers/net/ethernet/intel/ice/ice_txrx.h index 567067b650c4..31bc998fe200 100644 --- a/drivers/net/ethernet/intel/ice/ice_txrx.h +++ b/drivers/net/ethernet/intel/ice/ice_txrx.h @@ -143,7 +143,7 @@ struct ice_ring { u16 next_to_use; u16 next_to_clean; - bool ring_active; /* is ring online or not */ + u8 ring_active; /* is ring online or not */ /* stats structs */ struct ice_q_stats stats; diff --git a/drivers/net/ethernet/intel/ice/ice_type.h b/drivers/net/ethernet/intel/ice/ice_type.h index 99c8a9a71b5e..97c366e0ca59 100644 --- a/drivers/net/ethernet/intel/ice/ice_type.h +++ b/drivers/net/ethernet/intel/ice/ice_type.h @@ -83,7 +83,7 @@ struct ice_link_status { u64 phy_type_low; u16 max_frame_size; u16 link_speed; - bool lse_ena; /* Link Status Event notification */ + u8 lse_ena; /* Link Status Event notification */ u8 link_info; u8 an_info; u8 ext_info; @@ -101,7 +101,7 @@ struct ice_phy_info { struct ice_link_status link_info_old; u64 phy_type_low; enum ice_media_type media_type; - bool get_link_info; + u8 get_link_info; }; /* Common HW capabilities for SW use */ @@ -167,7 +167,7 @@ struct ice_nvm_info { u32 oem_ver; /* OEM version info */ u16 sr_words; /* Shadow RAM size in words */ u16 ver; /* NVM package version */ - bool blank_nvm_mode; /* is NVM empty (no FW present) */ + u8 blank_nvm_mode; /* is NVM empty (no FW present) */ }; /* Max number of port to queue branches w.r.t topology */ @@ -181,7 +181,7 @@ struct ice_sched_node { struct ice_aqc_txsched_elem_data info; u32 agg_id; /* aggregator group id */ u16 vsi_id; - bool in_use; /* suspended or in use */ + u8 in_use; /* suspended or in use */ u8 tx_sched_layer; /* Logical Layer (1-9) */ u8 num_children; u8 tc_num; @@ -218,7 +218,7 @@ struct ice_sched_vsi_info { struct ice_sched_tx_policy { u16 max_num_vsis; u8 max_num_lan_qs_per_tc[ICE_MAX_TRAFFIC_CLASS]; - bool rdma_ena; + u8 rdma_ena; }; struct ice_port_info { @@ -243,7 +243,7 @@ struct ice_port_info { struct list_head agg_list; /* lists all aggregator */ u8 lport; #define ICE_LPORT_MASK 0xff - bool is_vf; + u8 is_vf; }; struct ice_switch_info { @@ -287,7 +287,7 @@ struct ice_hw { u8 max_cgds; u8 sw_entry_point_layer; - bool evb_veb; /* true for VEB, false for VEPA */ + u8 evb_veb; /* true for VEB, false for VEPA */ struct ice_bus_info bus; struct ice_nvm_info nvm; struct ice_hw_dev_caps dev_caps; /* device capabilities */ @@ -318,7 +318,7 @@ struct ice_hw { u8 itr_gran_100; u8 itr_gran_50; u8 itr_gran_25; - bool ucast_shared; /* true if VSIs can share unicast addr */ + u8 ucast_shared; /* true if VSIs can share unicast addr */ }; From 3968540ba61e9a19a0c4bda733db70952708d264 Mon Sep 17 00:00:00 2001 From: Anirudh Venkataramanan Date: Thu, 9 Aug 2018 06:29:03 -0700 Subject: [PATCH 083/302] ice: Trivial formatting fixes 1) Add missing "\n" when printing link event error message. 2) Update dev_err statement in probe. 3) Add function description for ice_clear_pf_cfg. 4) Fix coding style for ice_acquire_nvm. 5) netdev->mtu is unsigned so use %u. Signed-off-by: Anirudh Venkataramanan Tested-by: Tony Brelinski Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ice/ice_common.c | 3 +++ drivers/net/ethernet/intel/ice/ice_main.c | 6 +++--- drivers/net/ethernet/intel/ice/ice_nvm.c | 5 ++--- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/drivers/net/ethernet/intel/ice/ice_common.c b/drivers/net/ethernet/intel/ice/ice_common.c index ebd701ac9428..661beea6af79 100644 --- a/drivers/net/ethernet/intel/ice/ice_common.c +++ b/drivers/net/ethernet/intel/ice/ice_common.c @@ -45,6 +45,9 @@ static enum ice_status ice_set_mac_type(struct ice_hw *hw) /** * ice_clear_pf_cfg - Clear PF configuration * @hw: pointer to the hardware structure + * + * Clears any existing PF configuration (VSIs, VSI lists, switch rules, port + * configuration, flow director filters, etc.). */ enum ice_status ice_clear_pf_cfg(struct ice_hw *hw) { diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c index e23156515186..f1e80eed2fd6 100644 --- a/drivers/net/ethernet/intel/ice/ice_main.c +++ b/drivers/net/ethernet/intel/ice/ice_main.c @@ -901,7 +901,7 @@ static int __ice_clean_ctrlq(struct ice_pf *pf, enum ice_ctl_q q_type) case ice_aqc_opc_get_link_status: if (ice_handle_link_event(pf)) dev_err(&pf->pdev->dev, - "Could not handle link event"); + "Could not handle link event\n"); break; default: dev_dbg(&pf->pdev->dev, @@ -3284,7 +3284,7 @@ static int ice_probe(struct pci_dev *pdev, err = pcim_iomap_regions(pdev, BIT(ICE_BAR0), pci_name(pdev)); if (err) { - dev_err(&pdev->dev, "I/O map error %d\n", err); + dev_err(&pdev->dev, "BAR0 I/O map error %d\n", err); return err; } @@ -5252,7 +5252,7 @@ static int ice_change_mtu(struct net_device *netdev, int new_mtu) u8 count = 0; if (new_mtu == netdev->mtu) { - netdev_warn(netdev, "mtu is already %d\n", netdev->mtu); + netdev_warn(netdev, "mtu is already %u\n", netdev->mtu); return 0; } diff --git a/drivers/net/ethernet/intel/ice/ice_nvm.c b/drivers/net/ethernet/intel/ice/ice_nvm.c index 92da0a626ce0..295a8cd87fc1 100644 --- a/drivers/net/ethernet/intel/ice/ice_nvm.c +++ b/drivers/net/ethernet/intel/ice/ice_nvm.c @@ -131,9 +131,8 @@ ice_read_sr_word_aq(struct ice_hw *hw, u16 offset, u16 *data) * * This function will request NVM ownership. */ -static enum -ice_status ice_acquire_nvm(struct ice_hw *hw, - enum ice_aq_res_access_type access) +static enum ice_status +ice_acquire_nvm(struct ice_hw *hw, enum ice_aq_res_access_type access) { if (hw->nvm.blank_nvm_mode) return 0; From 82c82ab658655befcb6aa47cbdb98dadce1a0cfe Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Tue, 21 Aug 2018 12:00:08 +0200 Subject: [PATCH 084/302] udf: Remove dead code from udf_find_fileset() Remove dead code and slightly simplify code in udf_find_fileset(). Signed-off-by: Jan Kara --- fs/udf/super.c | 62 +------------------------------------------------- 1 file changed, 1 insertion(+), 61 deletions(-) diff --git a/fs/udf/super.c b/fs/udf/super.c index 3040dc2a32f6..68d57b61f3af 100644 --- a/fs/udf/super.c +++ b/fs/udf/super.c @@ -764,9 +764,7 @@ static int udf_find_fileset(struct super_block *sb, struct kernel_lb_addr *root) { struct buffer_head *bh = NULL; - long lastblock; uint16_t ident; - struct udf_sb_info *sbi; if (fileset->logicalBlockNum != 0xFFFFFFFF || fileset->partitionReferenceNum != 0xFFFF) { @@ -779,69 +777,11 @@ static int udf_find_fileset(struct super_block *sb, return 1; } - } - - sbi = UDF_SB(sb); - if (!bh) { - /* Search backwards through the partitions */ - struct kernel_lb_addr newfileset; - -/* --> cvg: FIXME - is it reasonable? */ - return 1; - - for (newfileset.partitionReferenceNum = sbi->s_partitions - 1; - (newfileset.partitionReferenceNum != 0xFFFF && - fileset->logicalBlockNum == 0xFFFFFFFF && - fileset->partitionReferenceNum == 0xFFFF); - newfileset.partitionReferenceNum--) { - lastblock = sbi->s_partmaps - [newfileset.partitionReferenceNum] - .s_partition_len; - newfileset.logicalBlockNum = 0; - - do { - bh = udf_read_ptagged(sb, &newfileset, 0, - &ident); - if (!bh) { - newfileset.logicalBlockNum++; - continue; - } - - switch (ident) { - case TAG_IDENT_SBD: - { - struct spaceBitmapDesc *sp; - sp = (struct spaceBitmapDesc *) - bh->b_data; - newfileset.logicalBlockNum += 1 + - ((le32_to_cpu(sp->numOfBytes) + - sizeof(struct spaceBitmapDesc) - - 1) >> sb->s_blocksize_bits); - brelse(bh); - break; - } - case TAG_IDENT_FSD: - *fileset = newfileset; - break; - default: - newfileset.logicalBlockNum++; - brelse(bh); - bh = NULL; - break; - } - } while (newfileset.logicalBlockNum < lastblock && - fileset->logicalBlockNum == 0xFFFFFFFF && - fileset->partitionReferenceNum == 0xFFFF); - } - } - - if ((fileset->logicalBlockNum != 0xFFFFFFFF || - fileset->partitionReferenceNum != 0xFFFF) && bh) { udf_debug("Fileset at block=%u, partition=%u\n", fileset->logicalBlockNum, fileset->partitionReferenceNum); - sbi->s_partition = fileset->partitionReferenceNum; + UDF_SB(sb)->s_partition = fileset->partitionReferenceNum; udf_load_fileset(sb, bh, root); brelse(bh); return 0; From ee4af50ca94f58afc3532662779b9cf80bbe27c8 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Tue, 21 Aug 2018 14:52:34 +0200 Subject: [PATCH 085/302] udf: Fix mounting of Win7 created UDF filesystems Win7 is creating UDF filesystems with single partition with number 8192. Current partition descriptor scanning code does not handle this well as it incorrectly assumes that partition numbers will form mostly contiguous space of small numbers. This results in unmountable media due to errors like: UDF-fs: error (device dm-1): udf_read_tagged: tag version 0x0000 != 0x0002 || 0x0003, block 0 UDF-fs: warning (device dm-1): udf_fill_super: No fileset found Fix the problem by handling partition descriptors in a way that sparse partition numbering does not matter. Reported-and-tested-by: jean-luc malet CC: stable@vger.kernel.org Fixes: 7b78fd02fb19530fd101ae137a1f46aa466d9bb6 Signed-off-by: Jan Kara --- fs/udf/super.c | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/fs/udf/super.c b/fs/udf/super.c index 68d57b61f3af..6f515651a2c2 100644 --- a/fs/udf/super.c +++ b/fs/udf/super.c @@ -1510,10 +1510,16 @@ static void udf_load_logicalvolint(struct super_block *sb, struct kernel_extent_ */ #define PART_DESC_ALLOC_STEP 32 +struct part_desc_seq_scan_data { + struct udf_vds_record rec; + u32 partnum; +}; + struct desc_seq_scan_data { struct udf_vds_record vds[VDS_POS_LENGTH]; unsigned int size_part_descs; - struct udf_vds_record *part_descs_loc; + unsigned int num_part_descs; + struct part_desc_seq_scan_data *part_descs_loc; }; static struct udf_vds_record *handle_partition_descriptor( @@ -1522,10 +1528,14 @@ static struct udf_vds_record *handle_partition_descriptor( { struct partitionDesc *desc = (struct partitionDesc *)bh->b_data; int partnum; + int i; partnum = le16_to_cpu(desc->partitionNumber); - if (partnum >= data->size_part_descs) { - struct udf_vds_record *new_loc; + for (i = 0; i < data->num_part_descs; i++) + if (partnum == data->part_descs_loc[i].partnum) + return &(data->part_descs_loc[i].rec); + if (data->num_part_descs >= data->size_part_descs) { + struct part_desc_seq_scan_data *new_loc; unsigned int new_size = ALIGN(partnum, PART_DESC_ALLOC_STEP); new_loc = kcalloc(new_size, sizeof(*new_loc), GFP_KERNEL); @@ -1537,7 +1547,7 @@ static struct udf_vds_record *handle_partition_descriptor( data->part_descs_loc = new_loc; data->size_part_descs = new_size; } - return &(data->part_descs_loc[partnum]); + return &(data->part_descs_loc[data->num_part_descs++].rec); } @@ -1587,6 +1597,7 @@ static noinline int udf_process_sequence( memset(data.vds, 0, sizeof(struct udf_vds_record) * VDS_POS_LENGTH); data.size_part_descs = PART_DESC_ALLOC_STEP; + data.num_part_descs = 0; data.part_descs_loc = kcalloc(data.size_part_descs, sizeof(*data.part_descs_loc), GFP_KERNEL); @@ -1598,7 +1609,6 @@ static noinline int udf_process_sequence( * are in it. */ for (; (!done && block <= lastblock); block++) { - bh = udf_read_tagged(sb, block, block, &ident); if (!bh) break; @@ -1670,13 +1680,10 @@ static noinline int udf_process_sequence( } /* Now handle prevailing Partition Descriptors */ - for (i = 0; i < data.size_part_descs; i++) { - if (data.part_descs_loc[i].block) { - ret = udf_load_partdesc(sb, - data.part_descs_loc[i].block); - if (ret < 0) - return ret; - } + for (i = 0; i < data.num_part_descs; i++) { + ret = udf_load_partdesc(sb, data.part_descs_loc[i].rec.block); + if (ret < 0) + return ret; } return 0; From 5e2e2f9f76e157063a656351728703cb02b068f1 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 23 Aug 2018 16:59:25 +0300 Subject: [PATCH 086/302] PM / clk: signedness bug in of_pm_clk_add_clks() "count" needs to be signed for the error handling to work. I made "i" signed as well so they match. Fixes: 02113ba93ea4 (PM / clk: Add support for obtaining clocks from device-tree) Cc: 4.6+ # 4.6+ Signed-off-by: Dan Carpenter Signed-off-by: Rafael J. Wysocki --- drivers/base/power/clock_ops.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/base/power/clock_ops.c b/drivers/base/power/clock_ops.c index 8e2e4757adcb..5a42ae4078c2 100644 --- a/drivers/base/power/clock_ops.c +++ b/drivers/base/power/clock_ops.c @@ -185,7 +185,7 @@ EXPORT_SYMBOL_GPL(of_pm_clk_add_clk); int of_pm_clk_add_clks(struct device *dev) { struct clk **clks; - unsigned int i, count; + int i, count; int ret; if (!dev || !dev->of_node) From a9910c0886470b659a6c3629d6467d5639c327e9 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Thu, 19 Jul 2018 22:04:07 +0800 Subject: [PATCH 087/302] ixgb: use dma_zalloc_coherent instead of allocator/memset Use dma_zalloc_coherent instead of dma_alloc_coherent followed by memset 0. Signed-off-by: YueHaibing Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgb/ixgb_main.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/intel/ixgb/ixgb_main.c b/drivers/net/ethernet/intel/ixgb/ixgb_main.c index 43664adf7a3c..d3e72d0f66ef 100644 --- a/drivers/net/ethernet/intel/ixgb/ixgb_main.c +++ b/drivers/net/ethernet/intel/ixgb/ixgb_main.c @@ -771,14 +771,13 @@ ixgb_setup_rx_resources(struct ixgb_adapter *adapter) rxdr->size = rxdr->count * sizeof(struct ixgb_rx_desc); rxdr->size = ALIGN(rxdr->size, 4096); - rxdr->desc = dma_alloc_coherent(&pdev->dev, rxdr->size, &rxdr->dma, - GFP_KERNEL); + rxdr->desc = dma_zalloc_coherent(&pdev->dev, rxdr->size, &rxdr->dma, + GFP_KERNEL); if (!rxdr->desc) { vfree(rxdr->buffer_info); return -ENOMEM; } - memset(rxdr->desc, 0, rxdr->size); rxdr->next_to_clean = 0; rxdr->next_to_use = 0; From cf1acec008f8d7761aa3fd7c4bca7e17b2d2512d Mon Sep 17 00:00:00 2001 From: Bo Chen Date: Mon, 23 Jul 2018 09:01:29 -0700 Subject: [PATCH 088/302] e1000: check on netif_running() before calling e1000_up() When the device is not up, the call to 'e1000_up()' from the error handling path of 'e1000_set_ringparam()' causes a kernel oops with a null-pointer dereference. The null-pointer dereference is triggered in function 'e1000_alloc_rx_buffers()' at line 'buffer_info = &rx_ring->buffer_info[i]'. This bug was reported by COD, a tool for testing kernel module binaries I am building. This bug was also detected by KFI from Dr. Kai Cong. This patch fixes the bug by checking on 'netif_running()' before calling 'e1000_up()' in 'e1000_set_ringparam()'. Signed-off-by: Bo Chen Acked-by: Alexander Duyck Tested-by: Aaron Brown Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/e1000/e1000_ethtool.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/intel/e1000/e1000_ethtool.c b/drivers/net/ethernet/intel/e1000/e1000_ethtool.c index bdb3f8e65ed4..c1e4e94f100f 100644 --- a/drivers/net/ethernet/intel/e1000/e1000_ethtool.c +++ b/drivers/net/ethernet/intel/e1000/e1000_ethtool.c @@ -644,7 +644,8 @@ static int e1000_set_ringparam(struct net_device *netdev, err_alloc_rx: kfree(txdr); err_alloc_tx: - e1000_up(adapter); + if (netif_running(adapter->netdev)) + e1000_up(adapter); err_setup: clear_bit(__E1000_RESETTING, &adapter->flags); return err; From ee400a3f1bfe7004a3e14b81c38ccc5583c26295 Mon Sep 17 00:00:00 2001 From: Bo Chen Date: Mon, 23 Jul 2018 09:01:30 -0700 Subject: [PATCH 089/302] e1000: ensure to free old tx/rx rings in set_ringparam() In 'e1000_set_ringparam()', the tx_ring and rx_ring are updated with new value and the old tx/rx rings are freed only when the device is up. There are resource leaks on old tx/rx rings when the device is not up. This bug is reported by COD, a tool for testing kernel module binaries I am building. This patch fixes the bug by always calling 'kfree()' on old tx/rx rings in 'e1000_set_ringparam()'. Signed-off-by: Bo Chen Reviewed-by: Alexander Duyck Tested-by: Aaron Brown Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/e1000/e1000_ethtool.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/intel/e1000/e1000_ethtool.c b/drivers/net/ethernet/intel/e1000/e1000_ethtool.c index c1e4e94f100f..2569a168334c 100644 --- a/drivers/net/ethernet/intel/e1000/e1000_ethtool.c +++ b/drivers/net/ethernet/intel/e1000/e1000_ethtool.c @@ -624,14 +624,14 @@ static int e1000_set_ringparam(struct net_device *netdev, adapter->tx_ring = tx_old; e1000_free_all_rx_resources(adapter); e1000_free_all_tx_resources(adapter); - kfree(tx_old); - kfree(rx_old); adapter->rx_ring = rxdr; adapter->tx_ring = txdr; err = e1000_up(adapter); if (err) goto err_setup; } + kfree(tx_old); + kfree(rx_old); clear_bit(__E1000_RESETTING, &adapter->flags); return 0; From a798fbac33c4cbfe7d539298623b7af6c3f9525a Mon Sep 17 00:00:00 2001 From: Jesus Sanchez-Palencia Date: Thu, 26 Jul 2018 10:20:38 -0700 Subject: [PATCH 090/302] igb: Use an advanced ctx descriptor for launchtime On i210, Launchtime (TxTime) requires the usage of an "Advanced Transmit Context Descriptor" for retrieving the timestamp of a packet. The igb driver correctly builds such descriptor on the segmentation flow (i.e. igb_tso()) or on the checksum one (i.e. igb_tx_csum()), but the feature is broken for AF_PACKET if the IGB_TX_FLAGS_VLAN is not set, which happens due to an early return on igb_tx_csum(). This flag is only set by the kernel when a VLAN interface is used, thus we can't just rely on it. Here we are fixing this issue by checking if launchtime is enabled for the current tx_ring before performing the early return. Signed-off-by: Jesus Sanchez-Palencia Tested-by: Aaron Brown Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/igb/igb_main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c index d03c2f0d7592..74416f8a9446 100644 --- a/drivers/net/ethernet/intel/igb/igb_main.c +++ b/drivers/net/ethernet/intel/igb/igb_main.c @@ -5816,7 +5816,8 @@ static void igb_tx_csum(struct igb_ring *tx_ring, struct igb_tx_buffer *first) if (skb->ip_summed != CHECKSUM_PARTIAL) { csum_failed: - if (!(first->tx_flags & IGB_TX_FLAGS_VLAN)) + if (!(first->tx_flags & IGB_TX_FLAGS_VLAN) && + !tx_ring->launchtime_enable) return; goto no_csum; } From 151356270b0761e455ed82bba3353fb494451555 Mon Sep 17 00:00:00 2001 From: Jia-Ju Bai Date: Fri, 27 Jul 2018 16:04:53 +0800 Subject: [PATCH 091/302] igb: Replace GFP_ATOMIC with GFP_KERNEL in igb_sw_init() igb_sw_init() is never called in atomic context. It calls kzalloc() and kcalloc() with GFP_ATOMIC, which is not necessary. GFP_ATOMIC can be replaced with GFP_KERNEL. This is found by a static analysis tool named DCNS written by myself. Signed-off-by: Jia-Ju Bai Tested-by: Aaron Brown Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/igb/igb_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c index 74416f8a9446..a32c576c1e65 100644 --- a/drivers/net/ethernet/intel/igb/igb_main.c +++ b/drivers/net/ethernet/intel/igb/igb_main.c @@ -3873,7 +3873,7 @@ static int igb_sw_init(struct igb_adapter *adapter) adapter->mac_table = kcalloc(hw->mac.rar_entry_count, sizeof(struct igb_mac_addr), - GFP_ATOMIC); + GFP_KERNEL); if (!adapter->mac_table) return -ENOMEM; @@ -3883,7 +3883,7 @@ static int igb_sw_init(struct igb_adapter *adapter) /* Setup and initialize a copy of the hw vlan table array */ adapter->shadow_vfta = kcalloc(E1000_VLAN_FILTER_TBL_SIZE, sizeof(u32), - GFP_ATOMIC); + GFP_KERNEL); if (!adapter->shadow_vfta) return -ENOMEM; From 69a64658de502c8ca383fe2c5a5208f00b5844cd Mon Sep 17 00:00:00 2001 From: Jia-Ju Bai Date: Fri, 27 Jul 2018 16:07:38 +0800 Subject: [PATCH 092/302] igb: Replace mdelay() with msleep() in igb_integrated_phy_loopback() igb_integrated_phy_loopback() is never called in atomic context. It calls mdelay() to busily wait, which is not necessary. mdelay() can be replaced with msleep(). This is found by a static analysis tool named DCNS written by myself. Signed-off-by: Jia-Ju Bai Tested-by: Aaron Brown Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/igb/igb_ethtool.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/intel/igb/igb_ethtool.c b/drivers/net/ethernet/intel/igb/igb_ethtool.c index f92f7918112d..5acf3b743876 100644 --- a/drivers/net/ethernet/intel/igb/igb_ethtool.c +++ b/drivers/net/ethernet/intel/igb/igb_ethtool.c @@ -1649,7 +1649,7 @@ static int igb_integrated_phy_loopback(struct igb_adapter *adapter) if (hw->phy.type == e1000_phy_m88) igb_phy_disable_receiver(adapter); - mdelay(500); + msleep(500); return 0; } From 374f78f75be98c72876a4d0311b278cd226effba Mon Sep 17 00:00:00 2001 From: Jia-Ju Bai Date: Fri, 27 Jul 2018 16:22:31 +0800 Subject: [PATCH 093/302] ixgbe: Replace GFP_ATOMIC with GFP_KERNEL ixgbe_fcoe_ddp_setup(), ixgbe_setup_fcoe_ddp_resources() and ixgbe_sw_init() are never called in atomic context. They call kmalloc(), dma_pool_alloc() and kzalloc() with GFP_ATOMIC, which is not necessary. GFP_ATOMIC can be replaced with GFP_KERNEL. This is found by a static analysis tool named DCNS written by myself. Signed-off-by: Jia-Ju Bai Acked-by: Sebastian Basierski Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c | 4 ++-- drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c index 94b3165ff543..ccd852ad62a4 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c @@ -192,7 +192,7 @@ static int ixgbe_fcoe_ddp_setup(struct net_device *netdev, u16 xid, } /* alloc the udl from per cpu ddp pool */ - ddp->udl = dma_pool_alloc(ddp_pool->pool, GFP_ATOMIC, &ddp->udp); + ddp->udl = dma_pool_alloc(ddp_pool->pool, GFP_KERNEL, &ddp->udp); if (!ddp->udl) { e_err(drv, "failed allocated ddp context\n"); goto out_noddp_unmap; @@ -760,7 +760,7 @@ int ixgbe_setup_fcoe_ddp_resources(struct ixgbe_adapter *adapter) return 0; /* Extra buffer to be shared by all DDPs for HW work around */ - buffer = kmalloc(IXGBE_FCBUFF_MIN, GFP_ATOMIC); + buffer = kmalloc(IXGBE_FCBUFF_MIN, GFP_KERNEL); if (!buffer) return -ENOMEM; diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index af4c9ae7f432..663d59ba527a 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -6201,7 +6201,7 @@ static int ixgbe_sw_init(struct ixgbe_adapter *adapter, adapter->mac_table = kcalloc(hw->mac.num_rar_entries, sizeof(struct ixgbe_mac_addr), - GFP_ATOMIC); + GFP_KERNEL); if (!adapter->mac_table) return -ENOMEM; From fabf1bce103aa8e3db27ff2cc55f8e0fb0abcc30 Mon Sep 17 00:00:00 2001 From: Tony Nguyen Date: Mon, 30 Jul 2018 15:52:48 -0700 Subject: [PATCH 094/302] ixgbe: Prevent unsupported configurations with XDP These changes address comments by Jakub Kicinski on commit 38b7e7f8ae82 ("ixgbe: Do not allow LRO or MTU change with XDP"). Change the MTU check with XDP to allow any supported value and only reject those outside of the range as opposed to rejecting any change when XDP is active. In situations where MTU size is not supported, return -EINVAL instead of -EPERM. Add checks when enabling SRIOV, DCB, or adding L2FW offloaded device as they are not supported with XDP. CC: Jakub Kicinski Signed-off-by: Tony Nguyen Acked-by: Jakub Kicinski Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 28 +++++++++++++++++-- .../net/ethernet/intel/ixgbe/ixgbe_sriov.c | 5 ++++ 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index 663d59ba527a..9a23d33a47ed 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -6620,8 +6620,18 @@ static int ixgbe_change_mtu(struct net_device *netdev, int new_mtu) struct ixgbe_adapter *adapter = netdev_priv(netdev); if (adapter->xdp_prog) { - e_warn(probe, "MTU cannot be changed while XDP program is loaded\n"); - return -EPERM; + int new_frame_size = new_mtu + ETH_HLEN + ETH_FCS_LEN + + VLAN_HLEN; + int i; + + for (i = 0; i < adapter->num_rx_queues; i++) { + struct ixgbe_ring *ring = adapter->rx_ring[i]; + + if (new_frame_size > ixgbe_rx_bufsz(ring)) { + e_warn(probe, "Requested MTU size is not supported with XDP\n"); + return -EINVAL; + } + } } /* @@ -8983,6 +8993,15 @@ int ixgbe_setup_tc(struct net_device *dev, u8 tc) #ifdef CONFIG_IXGBE_DCB if (tc) { + if (adapter->xdp_prog) { + e_warn(probe, "DCB is not supported with XDP\n"); + + ixgbe_init_interrupt_scheme(adapter); + if (netif_running(dev)) + ixgbe_open(dev); + return -EINVAL; + } + netdev_set_num_tc(dev, tc); ixgbe_set_prio_tc_map(adapter); @@ -9934,6 +9953,11 @@ static void *ixgbe_fwd_add(struct net_device *pdev, struct net_device *vdev) int tcs = adapter->hw_tcs ? : 1; int pool, err; + if (adapter->xdp_prog) { + e_warn(probe, "L2FW offload is not supported with XDP\n"); + return ERR_PTR(-EINVAL); + } + /* The hardware supported by ixgbe only filters on the destination MAC * address. In order to avoid issues we only support offloading modes * where the hardware can actually provide the functionality. diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c index 6f59933cdff7..9264a5f8a5d0 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c @@ -53,6 +53,11 @@ static int __ixgbe_enable_sriov(struct ixgbe_adapter *adapter, struct ixgbe_hw *hw = &adapter->hw; int i; + if (adapter->xdp_prog) { + e_warn(probe, "SRIOV is not supported with XDP\n"); + return -EINVAL; + } + /* Enable VMDq flag so device will be set in VM mode */ adapter->flags |= IXGBE_FLAG_SRIOV_ENABLED | IXGBE_FLAG_VMDQ_ENABLED; From 939b701ad63314f5aa90dcd3d866f73954945209 Mon Sep 17 00:00:00 2001 From: Sebastian Basierski Date: Tue, 31 Jul 2018 18:16:00 +0200 Subject: [PATCH 095/302] ixgbe: fix driver behaviour after issuing VFLR Since VFLR doesn't clear VFMBMEM (VF Mailbox Memory) and is not re-enabling queues correctly we should fix this behavior. Signed-off-by: Sebastian Basierski Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- .../net/ethernet/intel/ixgbe/ixgbe_sriov.c | 26 +++++++++++++++++++ drivers/net/ethernet/intel/ixgbe/ixgbe_type.h | 1 + 2 files changed, 27 insertions(+) diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c index 9264a5f8a5d0..3c6f01c41b78 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c @@ -693,8 +693,13 @@ static int ixgbe_set_vf_macvlan(struct ixgbe_adapter *adapter, static inline void ixgbe_vf_reset_event(struct ixgbe_adapter *adapter, u32 vf) { struct ixgbe_hw *hw = &adapter->hw; + struct ixgbe_ring_feature *vmdq = &adapter->ring_feature[RING_F_VMDQ]; struct vf_data_storage *vfinfo = &adapter->vfinfo[vf]; + u32 q_per_pool = __ALIGN_MASK(1, ~vmdq->mask); u8 num_tcs = adapter->hw_tcs; + u32 reg_val; + u32 queue; + u32 word; /* remove VLAN filters beloning to this VF */ ixgbe_clear_vf_vlans(adapter, vf); @@ -731,6 +736,27 @@ static inline void ixgbe_vf_reset_event(struct ixgbe_adapter *adapter, u32 vf) /* reset VF api back to unknown */ adapter->vfinfo[vf].vf_api = ixgbe_mbox_api_10; + + /* Restart each queue for given VF */ + for (queue = 0; queue < q_per_pool; queue++) { + unsigned int reg_idx = (vf * q_per_pool) + queue; + + reg_val = IXGBE_READ_REG(hw, IXGBE_PVFTXDCTL(reg_idx)); + + /* Re-enabling only configured queues */ + if (reg_val) { + reg_val |= IXGBE_TXDCTL_ENABLE; + IXGBE_WRITE_REG(hw, IXGBE_PVFTXDCTL(reg_idx), reg_val); + reg_val &= ~IXGBE_TXDCTL_ENABLE; + IXGBE_WRITE_REG(hw, IXGBE_PVFTXDCTL(reg_idx), reg_val); + } + } + + /* Clear VF's mailbox memory */ + for (word = 0; word < IXGBE_VFMAILBOX_SIZE; word++) + IXGBE_WRITE_REG_ARRAY(hw, IXGBE_PFMBMEM(vf), word, 0); + + IXGBE_WRITE_FLUSH(hw); } static int ixgbe_set_vf_mac(struct ixgbe_adapter *adapter, diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h index 44cfb2021145..41bcbb337e83 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h @@ -2518,6 +2518,7 @@ enum { /* Translated register #defines */ #define IXGBE_PVFTDH(P) (0x06010 + (0x40 * (P))) #define IXGBE_PVFTDT(P) (0x06018 + (0x40 * (P))) +#define IXGBE_PVFTXDCTL(P) (0x06028 + (0x40 * (P))) #define IXGBE_PVFTDWBAL(P) (0x06038 + (0x40 * (P))) #define IXGBE_PVFTDWBAH(P) (0x0603C + (0x40 * (P))) From fa38e30ac73fbb01d7e5d0fd1b12d412fa3ac3ee Mon Sep 17 00:00:00 2001 From: Martyna Szapar Date: Tue, 7 Aug 2018 17:11:23 -0700 Subject: [PATCH 096/302] i40e: Fix for Tx timeouts when interface is brought up if DCB is enabled If interface is connected to switch port configured for DCB there are TX timeouts when bringing up interface. Problem started appearing after adding in i40e driver code mqprio hardware offload mode. In function i40e_vsi_configure_bw_alloc was added resetting BW rate which should be executing when mqprio qdisc is removed but was also when there was no mqprio qdisc added and DCB was enabled. In this patch was added additional check for DCB flag so now when DCB is enabled the correct DCB configs from before mqprio patch are restored. Signed-off-by: Martyna Szapar Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_main.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index f2c622e78802..ac685ad4d877 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -5122,15 +5122,17 @@ static int i40e_vsi_configure_bw_alloc(struct i40e_vsi *vsi, u8 enabled_tc, u8 *bw_share) { struct i40e_aqc_configure_vsi_tc_bw_data bw_data; + struct i40e_pf *pf = vsi->back; i40e_status ret; int i; - if (vsi->back->flags & I40E_FLAG_TC_MQPRIO) + /* There is no need to reset BW when mqprio mode is on. */ + if (pf->flags & I40E_FLAG_TC_MQPRIO) return 0; - if (!vsi->mqprio_qopt.qopt.hw) { + if (!vsi->mqprio_qopt.qopt.hw && !(pf->flags & I40E_FLAG_DCB_ENABLED)) { ret = i40e_set_bw_limit(vsi, vsi->seid, 0); if (ret) - dev_info(&vsi->back->pdev->dev, + dev_info(&pf->pdev->dev, "Failed to reset tx rate for vsi->seid %u\n", vsi->seid); return ret; @@ -5139,12 +5141,11 @@ static int i40e_vsi_configure_bw_alloc(struct i40e_vsi *vsi, u8 enabled_tc, for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) bw_data.tc_bw_credits[i] = bw_share[i]; - ret = i40e_aq_config_vsi_tc_bw(&vsi->back->hw, vsi->seid, &bw_data, - NULL); + ret = i40e_aq_config_vsi_tc_bw(&pf->hw, vsi->seid, &bw_data, NULL); if (ret) { - dev_info(&vsi->back->pdev->dev, + dev_info(&pf->pdev->dev, "AQ command Config VSI BW allocation per TC failed = %d\n", - vsi->back->hw.aq.asq_last_status); + pf->hw.aq.asq_last_status); return -EINVAL; } From 07f3701387dcab3a4fb0166098fb2754a1b927e1 Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Mon, 20 Aug 2018 08:12:27 -0700 Subject: [PATCH 097/302] i40e: fix condition of WARN_ONCE for stat strings Commit 9b10df596bd4 ("i40e: use WARN_ONCE to replace the commented BUG_ON size check") introduced a warning check to make sure that the size of the stat strings was always the expected value. This code accidentally inverted the check of the data pointer. Fix this so that we accurately count the size of the stats we copied in. This fixes an erroneous WARN kernel splat that occurs when requesting ethtool statistics. Signed-off-by: Jacob Keller Tested-by: Andrew Bowers Tested-by: Mauro S M Rodrigues Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c index abcd096ede14..5ff6caa83948 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c @@ -2013,7 +2013,7 @@ static void i40e_get_stat_strings(struct net_device *netdev, u8 *data) for (i = 0; i < I40E_MAX_USER_PRIORITY; i++) i40e_add_stat_strings(&data, i40e_gstrings_pfc_stats, i); - WARN_ONCE(p - data != i40e_get_stats_count(netdev) * ETH_GSTRING_LEN, + WARN_ONCE(data - p != i40e_get_stats_count(netdev) * ETH_GSTRING_LEN, "stat strings count mismatch!"); } From a296b16270ab8d3b1c2a41ca1dd4d2fc34b598d9 Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Thu, 16 Aug 2018 11:36:38 +0800 Subject: [PATCH 098/302] drm/amd/display: Fix bug use wrong pp interface Used wrong pp interface, the original interface is exposed by dpm on SI and paritial CI. Pointed out by Francis David v2: dal only need to set min_dcefclk and min_fclk to smu. so use display_clock_voltage_request interface, instand of update all display configuration. Acked-by: Alex Deucher Signed-off-by: Rex Zhu Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c index fbe878ae1e8c..4ba0003a9d32 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c @@ -480,12 +480,20 @@ void pp_rv_set_display_requirement(struct pp_smu *pp, { struct dc_context *ctx = pp->ctx; struct amdgpu_device *adev = ctx->driver_context; + void *pp_handle = adev->powerplay.pp_handle; const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + struct pp_display_clock_request clock = {0}; - if (!pp_funcs || !pp_funcs->display_configuration_changed) + if (!pp_funcs || !pp_funcs->display_clock_voltage_request) return; - amdgpu_dpm_display_configuration_changed(adev); + clock.clock_type = amd_pp_dcf_clock; + clock.clock_freq_in_khz = req->hard_min_dcefclk_khz; + pp_funcs->display_clock_voltage_request(pp_handle, &clock); + + clock.clock_type = amd_pp_f_clock; + clock.clock_freq_in_khz = req->hard_min_fclk_khz; + pp_funcs->display_clock_voltage_request(pp_handle, &clock); } void pp_rv_set_wm_ranges(struct pp_smu *pp, From 757ab15c3f4968b5a29caf3fe8b67660ce84c3cd Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Tue, 21 Aug 2018 10:44:10 +0200 Subject: [PATCH 099/302] cpuidle: menu: Retain tick when shallow state is selected The case addressed by commit 5ef499cd571c (cpuidle: menu: Handle stopped tick more aggressively) in the stopped tick case is present when the tick has not been stopped yet too. Namely, if only two CPU idle states, shallow state A with target residency significantly below the tick boundary and deep state B with target residency significantly above it, are available and the predicted idle duration is above the tick boundary, but below the target residency of state B, state A will be selected and the CPU may spend indefinite amount of time in it, which is not quite energy-efficient. However, if the tick has not been stopped yet and the governor is about to select a shallow idle state for the CPU even though the idle duration predicted by it is above the tick boundary, it should be fine to wake up the CPU early, so the tick can be retained then and the governor will have a chance to select a deeper state when it runs next time. [Note that when this really happens, it will make the idle duration predictor believe that the CPU might be idle longer than predicted, which will make it more likely to predict longer idle durations going forward, but that will also cause deeper idle states to be selected going forward, on average, which is what's needed here.] Fixes: 87c9fe6ee495 (cpuidle: menu: Avoid selecting shallow states with stopped tick) Reported-by: Leo Yan Cc: 4.17+ # 4.17+: 5ef499cd571c (cpuidle: menu: Handle ...) Signed-off-by: Rafael J. Wysocki --- drivers/cpuidle/governors/menu.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c index 110483f0e3fb..e26a40971b26 100644 --- a/drivers/cpuidle/governors/menu.c +++ b/drivers/cpuidle/governors/menu.c @@ -379,9 +379,20 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev, if (idx == -1) idx = i; /* first enabled state */ if (s->target_residency > data->predicted_us) { - if (!tick_nohz_tick_stopped()) + if (data->predicted_us < TICK_USEC) break; + if (!tick_nohz_tick_stopped()) { + /* + * If the state selected so far is shallow, + * waking up early won't hurt, so retain the + * tick in that case and let the governor run + * again in the next iteration of the loop. + */ + expected_interval = drv->states[idx].target_residency; + break; + } + /* * If the state selected so far is shallow and this * state's target residency matches the time till the From cc98963dbaaea93d17608641b8d6942a5327fc31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Horia=20Geant=C4=83?= Date: Mon, 6 Aug 2018 15:29:09 +0300 Subject: [PATCH 100/302] crypto: caam/jr - fix descriptor DMA unmapping MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Descriptor address needs to be swapped to CPU endianness before being DMA unmapped. Cc: # 4.8+ Fixes: 261ea058f016 ("crypto: caam - handle core endianness != caam endianness") Reported-by: Laurentiu Tudor Signed-off-by: Horia Geantă Signed-off-by: Herbert Xu --- drivers/crypto/caam/jr.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/crypto/caam/jr.c b/drivers/crypto/caam/jr.c index f4f258075b89..acdd72016ffe 100644 --- a/drivers/crypto/caam/jr.c +++ b/drivers/crypto/caam/jr.c @@ -190,7 +190,8 @@ static void caam_jr_dequeue(unsigned long devarg) BUG_ON(CIRC_CNT(head, tail + i, JOBR_DEPTH) <= 0); /* Unmap just-run descriptor so we can post-process */ - dma_unmap_single(dev, jrp->outring[hw_idx].desc, + dma_unmap_single(dev, + caam_dma_to_cpu(jrp->outring[hw_idx].desc), jrp->entinfo[sw_idx].desc_size, DMA_TO_DEVICE); From ad876a18048f43b1f66f5d474b7598538668c5de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Horia=20Geant=C4=83?= Date: Mon, 6 Aug 2018 15:29:39 +0300 Subject: [PATCH 101/302] crypto: caam/qi - fix error path in xts setkey MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit xts setkey callback returns 0 on some error paths. Fix this by returning -EINVAL. Cc: # 4.12+ Fixes: b189817cf789 ("crypto: caam/qi - add ablkcipher and authenc algorithms") Signed-off-by: Horia Geantă Signed-off-by: Herbert Xu --- drivers/crypto/caam/caamalg_qi.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/crypto/caam/caamalg_qi.c b/drivers/crypto/caam/caamalg_qi.c index 6e61cc93c2b0..d7aa7d7ff102 100644 --- a/drivers/crypto/caam/caamalg_qi.c +++ b/drivers/crypto/caam/caamalg_qi.c @@ -679,10 +679,8 @@ static int xts_ablkcipher_setkey(struct crypto_ablkcipher *ablkcipher, int ret = 0; if (keylen != 2 * AES_MIN_KEY_SIZE && keylen != 2 * AES_MAX_KEY_SIZE) { - crypto_ablkcipher_set_flags(ablkcipher, - CRYPTO_TFM_RES_BAD_KEY_LEN); dev_err(jrdev, "key size mismatch\n"); - return -EINVAL; + goto badkey; } ctx->cdata.keylen = keylen; @@ -715,7 +713,7 @@ static int xts_ablkcipher_setkey(struct crypto_ablkcipher *ablkcipher, return ret; badkey: crypto_ablkcipher_set_flags(ablkcipher, CRYPTO_TFM_RES_BAD_KEY_LEN); - return 0; + return -EINVAL; } /* From f1bf9e60a0779ec97de9ecdc353e1d01cdd73f43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Horia=20Geant=C4=83?= Date: Mon, 6 Aug 2018 15:29:55 +0300 Subject: [PATCH 102/302] crypto: caam - fix DMA mapping direction for RSA forms 2 & 3 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Crypto engine needs some temporary locations in external memory for running RSA decrypt forms 2 and 3 (CRT). These are named "tmp1" and "tmp2" in the PDB. Update DMA mapping direction of tmp1 and tmp2 from TO_DEVICE to BIDIRECTIONAL, since engine needs r/w access. Cc: # 4.13+ Fixes: 52e26d77b8b3 ("crypto: caam - add support for RSA key form 2") Fixes: 4a651b122adb ("crypto: caam - add support for RSA key form 3") Signed-off-by: Horia Geantă Signed-off-by: Herbert Xu --- drivers/crypto/caam/caampkc.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/crypto/caam/caampkc.c b/drivers/crypto/caam/caampkc.c index 578ea63a3109..f26d62e5533a 100644 --- a/drivers/crypto/caam/caampkc.c +++ b/drivers/crypto/caam/caampkc.c @@ -71,8 +71,8 @@ static void rsa_priv_f2_unmap(struct device *dev, struct rsa_edesc *edesc, dma_unmap_single(dev, pdb->d_dma, key->d_sz, DMA_TO_DEVICE); dma_unmap_single(dev, pdb->p_dma, p_sz, DMA_TO_DEVICE); dma_unmap_single(dev, pdb->q_dma, q_sz, DMA_TO_DEVICE); - dma_unmap_single(dev, pdb->tmp1_dma, p_sz, DMA_TO_DEVICE); - dma_unmap_single(dev, pdb->tmp2_dma, q_sz, DMA_TO_DEVICE); + dma_unmap_single(dev, pdb->tmp1_dma, p_sz, DMA_BIDIRECTIONAL); + dma_unmap_single(dev, pdb->tmp2_dma, q_sz, DMA_BIDIRECTIONAL); } static void rsa_priv_f3_unmap(struct device *dev, struct rsa_edesc *edesc, @@ -90,8 +90,8 @@ static void rsa_priv_f3_unmap(struct device *dev, struct rsa_edesc *edesc, dma_unmap_single(dev, pdb->dp_dma, p_sz, DMA_TO_DEVICE); dma_unmap_single(dev, pdb->dq_dma, q_sz, DMA_TO_DEVICE); dma_unmap_single(dev, pdb->c_dma, p_sz, DMA_TO_DEVICE); - dma_unmap_single(dev, pdb->tmp1_dma, p_sz, DMA_TO_DEVICE); - dma_unmap_single(dev, pdb->tmp2_dma, q_sz, DMA_TO_DEVICE); + dma_unmap_single(dev, pdb->tmp1_dma, p_sz, DMA_BIDIRECTIONAL); + dma_unmap_single(dev, pdb->tmp2_dma, q_sz, DMA_BIDIRECTIONAL); } /* RSA Job Completion handler */ @@ -417,13 +417,13 @@ static int set_rsa_priv_f2_pdb(struct akcipher_request *req, goto unmap_p; } - pdb->tmp1_dma = dma_map_single(dev, key->tmp1, p_sz, DMA_TO_DEVICE); + pdb->tmp1_dma = dma_map_single(dev, key->tmp1, p_sz, DMA_BIDIRECTIONAL); if (dma_mapping_error(dev, pdb->tmp1_dma)) { dev_err(dev, "Unable to map RSA tmp1 memory\n"); goto unmap_q; } - pdb->tmp2_dma = dma_map_single(dev, key->tmp2, q_sz, DMA_TO_DEVICE); + pdb->tmp2_dma = dma_map_single(dev, key->tmp2, q_sz, DMA_BIDIRECTIONAL); if (dma_mapping_error(dev, pdb->tmp2_dma)) { dev_err(dev, "Unable to map RSA tmp2 memory\n"); goto unmap_tmp1; @@ -451,7 +451,7 @@ static int set_rsa_priv_f2_pdb(struct akcipher_request *req, return 0; unmap_tmp1: - dma_unmap_single(dev, pdb->tmp1_dma, p_sz, DMA_TO_DEVICE); + dma_unmap_single(dev, pdb->tmp1_dma, p_sz, DMA_BIDIRECTIONAL); unmap_q: dma_unmap_single(dev, pdb->q_dma, q_sz, DMA_TO_DEVICE); unmap_p: @@ -504,13 +504,13 @@ static int set_rsa_priv_f3_pdb(struct akcipher_request *req, goto unmap_dq; } - pdb->tmp1_dma = dma_map_single(dev, key->tmp1, p_sz, DMA_TO_DEVICE); + pdb->tmp1_dma = dma_map_single(dev, key->tmp1, p_sz, DMA_BIDIRECTIONAL); if (dma_mapping_error(dev, pdb->tmp1_dma)) { dev_err(dev, "Unable to map RSA tmp1 memory\n"); goto unmap_qinv; } - pdb->tmp2_dma = dma_map_single(dev, key->tmp2, q_sz, DMA_TO_DEVICE); + pdb->tmp2_dma = dma_map_single(dev, key->tmp2, q_sz, DMA_BIDIRECTIONAL); if (dma_mapping_error(dev, pdb->tmp2_dma)) { dev_err(dev, "Unable to map RSA tmp2 memory\n"); goto unmap_tmp1; @@ -538,7 +538,7 @@ static int set_rsa_priv_f3_pdb(struct akcipher_request *req, return 0; unmap_tmp1: - dma_unmap_single(dev, pdb->tmp1_dma, p_sz, DMA_TO_DEVICE); + dma_unmap_single(dev, pdb->tmp1_dma, p_sz, DMA_BIDIRECTIONAL); unmap_qinv: dma_unmap_single(dev, pdb->c_dma, p_sz, DMA_TO_DEVICE); unmap_dq: From 7fa885e2a22fd0f91a2c23d9275f5021f618ff5a Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Tue, 7 Aug 2018 23:18:36 +0200 Subject: [PATCH 103/302] crypto: arm64/sm4-ce - check for the right CPU feature bit ARMv8.2 specifies special instructions for the SM3 cryptographic hash and the SM4 symmetric cipher. While it is unlikely that a core would implement one and not the other, we should only use SM4 instructions if the SM4 CPU feature bit is set, and we currently check the SM3 feature bit instead. So fix that. Fixes: e99ce921c468 ("crypto: arm64 - add support for SM4...") Cc: Signed-off-by: Ard Biesheuvel Signed-off-by: Herbert Xu --- arch/arm64/crypto/sm4-ce-glue.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/crypto/sm4-ce-glue.c b/arch/arm64/crypto/sm4-ce-glue.c index b7fb5274b250..0c4fc223f225 100644 --- a/arch/arm64/crypto/sm4-ce-glue.c +++ b/arch/arm64/crypto/sm4-ce-glue.c @@ -69,5 +69,5 @@ static void __exit sm4_ce_mod_fini(void) crypto_unregister_alg(&sm4_ce_alg); } -module_cpu_feature_match(SM3, sm4_ce_mod_init); +module_cpu_feature_match(SM4, sm4_ce_mod_init); module_exit(sm4_ce_mod_fini); From 65b2c12dcdb883fc015c0ec65d6c2f857e0456ac Mon Sep 17 00:00:00 2001 From: Ganesh Goudar Date: Fri, 10 Aug 2018 18:27:41 +0530 Subject: [PATCH 104/302] crypto: chtls - fix null dereference chtls_free_uld() call chtls_free_uld() only for the initialized cdev, this fixes NULL dereference in chtls_free_uld() Signed-off-by: Ganesh Goudar Signed-off-by: Atul Gupta Signed-off-by: Herbert Xu --- drivers/crypto/chelsio/chtls/chtls.h | 5 +++++ drivers/crypto/chelsio/chtls/chtls_main.c | 7 +++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/crypto/chelsio/chtls/chtls.h b/drivers/crypto/chelsio/chtls/chtls.h index a53a0e6ba024..7725b6ee14ef 100644 --- a/drivers/crypto/chelsio/chtls/chtls.h +++ b/drivers/crypto/chelsio/chtls/chtls.h @@ -96,6 +96,10 @@ enum csk_flags { CSK_CONN_INLINE, /* Connection on HW */ }; +enum chtls_cdev_state { + CHTLS_CDEV_STATE_UP = 1 +}; + struct listen_ctx { struct sock *lsk; struct chtls_dev *cdev; @@ -146,6 +150,7 @@ struct chtls_dev { unsigned int send_page_order; int max_host_sndbuf; struct key_map kmap; + unsigned int cdev_state; }; struct chtls_hws { diff --git a/drivers/crypto/chelsio/chtls/chtls_main.c b/drivers/crypto/chelsio/chtls/chtls_main.c index 9b07f9165658..f59b044ebd25 100644 --- a/drivers/crypto/chelsio/chtls/chtls_main.c +++ b/drivers/crypto/chelsio/chtls/chtls_main.c @@ -160,6 +160,7 @@ static void chtls_register_dev(struct chtls_dev *cdev) tlsdev->hash = chtls_create_hash; tlsdev->unhash = chtls_destroy_hash; tls_register_device(&cdev->tlsdev); + cdev->cdev_state = CHTLS_CDEV_STATE_UP; } static void chtls_unregister_dev(struct chtls_dev *cdev) @@ -281,8 +282,10 @@ static void chtls_free_all_uld(void) struct chtls_dev *cdev, *tmp; mutex_lock(&cdev_mutex); - list_for_each_entry_safe(cdev, tmp, &cdev_list, list) - chtls_free_uld(cdev); + list_for_each_entry_safe(cdev, tmp, &cdev_list, list) { + if (cdev->cdev_state == CHTLS_CDEV_STATE_UP) + chtls_free_uld(cdev); + } mutex_unlock(&cdev_mutex); } From e5b954e8d11fdde55eed35017370a3a0d8837754 Mon Sep 17 00:00:00 2001 From: Dave Watson Date: Wed, 15 Aug 2018 10:29:42 -0700 Subject: [PATCH 105/302] crypto: aesni - Use unaligned loads from gcm_context_data A regression was reported bisecting to 1476db2d12 "Move HashKey computation from stack to gcm_context". That diff moved HashKey computation from the stack, which was explicitly aligned in the asm, to a struct provided from the C code, depending on AESNI_ALIGN_ATTR for alignment. It appears some compilers may not align this struct correctly, resulting in a crash on the movdqa instruction when attempting to encrypt or decrypt data. Fix by using unaligned loads for the HashKeys. On modern hardware there is no perf difference between the unaligned and aligned loads. All other accesses to gcm_context_data already use unaligned loads. Reported-by: Mauro Rossi Fixes: 1476db2d12 ("Move HashKey computation from stack to gcm_context") Cc: Signed-off-by: Dave Watson Signed-off-by: Herbert Xu --- arch/x86/crypto/aesni-intel_asm.S | 66 +++++++++++++++---------------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/arch/x86/crypto/aesni-intel_asm.S b/arch/x86/crypto/aesni-intel_asm.S index e762ef417562..d27a50656aa1 100644 --- a/arch/x86/crypto/aesni-intel_asm.S +++ b/arch/x86/crypto/aesni-intel_asm.S @@ -223,34 +223,34 @@ ALL_F: .octa 0xffffffffffffffffffffffffffffffff pcmpeqd TWOONE(%rip), \TMP2 pand POLY(%rip), \TMP2 pxor \TMP2, \TMP3 - movdqa \TMP3, HashKey(%arg2) + movdqu \TMP3, HashKey(%arg2) movdqa \TMP3, \TMP5 pshufd $78, \TMP3, \TMP1 pxor \TMP3, \TMP1 - movdqa \TMP1, HashKey_k(%arg2) + movdqu \TMP1, HashKey_k(%arg2) GHASH_MUL \TMP5, \TMP3, \TMP1, \TMP2, \TMP4, \TMP6, \TMP7 # TMP5 = HashKey^2<<1 (mod poly) - movdqa \TMP5, HashKey_2(%arg2) + movdqu \TMP5, HashKey_2(%arg2) # HashKey_2 = HashKey^2<<1 (mod poly) pshufd $78, \TMP5, \TMP1 pxor \TMP5, \TMP1 - movdqa \TMP1, HashKey_2_k(%arg2) + movdqu \TMP1, HashKey_2_k(%arg2) GHASH_MUL \TMP5, \TMP3, \TMP1, \TMP2, \TMP4, \TMP6, \TMP7 # TMP5 = HashKey^3<<1 (mod poly) - movdqa \TMP5, HashKey_3(%arg2) + movdqu \TMP5, HashKey_3(%arg2) pshufd $78, \TMP5, \TMP1 pxor \TMP5, \TMP1 - movdqa \TMP1, HashKey_3_k(%arg2) + movdqu \TMP1, HashKey_3_k(%arg2) GHASH_MUL \TMP5, \TMP3, \TMP1, \TMP2, \TMP4, \TMP6, \TMP7 # TMP5 = HashKey^3<<1 (mod poly) - movdqa \TMP5, HashKey_4(%arg2) + movdqu \TMP5, HashKey_4(%arg2) pshufd $78, \TMP5, \TMP1 pxor \TMP5, \TMP1 - movdqa \TMP1, HashKey_4_k(%arg2) + movdqu \TMP1, HashKey_4_k(%arg2) .endm # GCM_INIT initializes a gcm_context struct to prepare for encoding/decoding. @@ -271,7 +271,7 @@ ALL_F: .octa 0xffffffffffffffffffffffffffffffff movdqu %xmm0, CurCount(%arg2) # ctx_data.current_counter = iv PRECOMPUTE \SUBKEY, %xmm1, %xmm2, %xmm3, %xmm4, %xmm5, %xmm6, %xmm7, - movdqa HashKey(%arg2), %xmm13 + movdqu HashKey(%arg2), %xmm13 CALC_AAD_HASH %xmm13, \AAD, \AADLEN, %xmm0, %xmm1, %xmm2, %xmm3, \ %xmm4, %xmm5, %xmm6 @@ -997,7 +997,7 @@ TMP6 XMM0 XMM1 XMM2 XMM3 XMM4 XMM5 XMM6 XMM7 XMM8 operation pshufd $78, \XMM5, \TMP6 pxor \XMM5, \TMP6 paddd ONE(%rip), \XMM0 # INCR CNT - movdqa HashKey_4(%arg2), \TMP5 + movdqu HashKey_4(%arg2), \TMP5 PCLMULQDQ 0x11, \TMP5, \TMP4 # TMP4 = a1*b1 movdqa \XMM0, \XMM1 paddd ONE(%rip), \XMM0 # INCR CNT @@ -1016,7 +1016,7 @@ TMP6 XMM0 XMM1 XMM2 XMM3 XMM4 XMM5 XMM6 XMM7 XMM8 operation pxor (%arg1), \XMM2 pxor (%arg1), \XMM3 pxor (%arg1), \XMM4 - movdqa HashKey_4_k(%arg2), \TMP5 + movdqu HashKey_4_k(%arg2), \TMP5 PCLMULQDQ 0x00, \TMP5, \TMP6 # TMP6 = (a1+a0)*(b1+b0) movaps 0x10(%arg1), \TMP1 AESENC \TMP1, \XMM1 # Round 1 @@ -1031,7 +1031,7 @@ TMP6 XMM0 XMM1 XMM2 XMM3 XMM4 XMM5 XMM6 XMM7 XMM8 operation movdqa \XMM6, \TMP1 pshufd $78, \XMM6, \TMP2 pxor \XMM6, \TMP2 - movdqa HashKey_3(%arg2), \TMP5 + movdqu HashKey_3(%arg2), \TMP5 PCLMULQDQ 0x11, \TMP5, \TMP1 # TMP1 = a1 * b1 movaps 0x30(%arg1), \TMP3 AESENC \TMP3, \XMM1 # Round 3 @@ -1044,7 +1044,7 @@ TMP6 XMM0 XMM1 XMM2 XMM3 XMM4 XMM5 XMM6 XMM7 XMM8 operation AESENC \TMP3, \XMM2 AESENC \TMP3, \XMM3 AESENC \TMP3, \XMM4 - movdqa HashKey_3_k(%arg2), \TMP5 + movdqu HashKey_3_k(%arg2), \TMP5 PCLMULQDQ 0x00, \TMP5, \TMP2 # TMP2 = (a1+a0)*(b1+b0) movaps 0x50(%arg1), \TMP3 AESENC \TMP3, \XMM1 # Round 5 @@ -1058,7 +1058,7 @@ TMP6 XMM0 XMM1 XMM2 XMM3 XMM4 XMM5 XMM6 XMM7 XMM8 operation movdqa \XMM7, \TMP1 pshufd $78, \XMM7, \TMP2 pxor \XMM7, \TMP2 - movdqa HashKey_2(%arg2), \TMP5 + movdqu HashKey_2(%arg2), \TMP5 # Multiply TMP5 * HashKey using karatsuba @@ -1074,7 +1074,7 @@ TMP6 XMM0 XMM1 XMM2 XMM3 XMM4 XMM5 XMM6 XMM7 XMM8 operation AESENC \TMP3, \XMM2 AESENC \TMP3, \XMM3 AESENC \TMP3, \XMM4 - movdqa HashKey_2_k(%arg2), \TMP5 + movdqu HashKey_2_k(%arg2), \TMP5 PCLMULQDQ 0x00, \TMP5, \TMP2 # TMP2 = (a1+a0)*(b1+b0) movaps 0x80(%arg1), \TMP3 AESENC \TMP3, \XMM1 # Round 8 @@ -1092,7 +1092,7 @@ TMP6 XMM0 XMM1 XMM2 XMM3 XMM4 XMM5 XMM6 XMM7 XMM8 operation movdqa \XMM8, \TMP1 pshufd $78, \XMM8, \TMP2 pxor \XMM8, \TMP2 - movdqa HashKey(%arg2), \TMP5 + movdqu HashKey(%arg2), \TMP5 PCLMULQDQ 0x11, \TMP5, \TMP1 # TMP1 = a1*b1 movaps 0x90(%arg1), \TMP3 AESENC \TMP3, \XMM1 # Round 9 @@ -1121,7 +1121,7 @@ aes_loop_par_enc_done\@: AESENCLAST \TMP3, \XMM2 AESENCLAST \TMP3, \XMM3 AESENCLAST \TMP3, \XMM4 - movdqa HashKey_k(%arg2), \TMP5 + movdqu HashKey_k(%arg2), \TMP5 PCLMULQDQ 0x00, \TMP5, \TMP2 # TMP2 = (a1+a0)*(b1+b0) movdqu (%arg4,%r11,1), \TMP3 pxor \TMP3, \XMM1 # Ciphertext/Plaintext XOR EK @@ -1205,7 +1205,7 @@ TMP6 XMM0 XMM1 XMM2 XMM3 XMM4 XMM5 XMM6 XMM7 XMM8 operation pshufd $78, \XMM5, \TMP6 pxor \XMM5, \TMP6 paddd ONE(%rip), \XMM0 # INCR CNT - movdqa HashKey_4(%arg2), \TMP5 + movdqu HashKey_4(%arg2), \TMP5 PCLMULQDQ 0x11, \TMP5, \TMP4 # TMP4 = a1*b1 movdqa \XMM0, \XMM1 paddd ONE(%rip), \XMM0 # INCR CNT @@ -1224,7 +1224,7 @@ TMP6 XMM0 XMM1 XMM2 XMM3 XMM4 XMM5 XMM6 XMM7 XMM8 operation pxor (%arg1), \XMM2 pxor (%arg1), \XMM3 pxor (%arg1), \XMM4 - movdqa HashKey_4_k(%arg2), \TMP5 + movdqu HashKey_4_k(%arg2), \TMP5 PCLMULQDQ 0x00, \TMP5, \TMP6 # TMP6 = (a1+a0)*(b1+b0) movaps 0x10(%arg1), \TMP1 AESENC \TMP1, \XMM1 # Round 1 @@ -1239,7 +1239,7 @@ TMP6 XMM0 XMM1 XMM2 XMM3 XMM4 XMM5 XMM6 XMM7 XMM8 operation movdqa \XMM6, \TMP1 pshufd $78, \XMM6, \TMP2 pxor \XMM6, \TMP2 - movdqa HashKey_3(%arg2), \TMP5 + movdqu HashKey_3(%arg2), \TMP5 PCLMULQDQ 0x11, \TMP5, \TMP1 # TMP1 = a1 * b1 movaps 0x30(%arg1), \TMP3 AESENC \TMP3, \XMM1 # Round 3 @@ -1252,7 +1252,7 @@ TMP6 XMM0 XMM1 XMM2 XMM3 XMM4 XMM5 XMM6 XMM7 XMM8 operation AESENC \TMP3, \XMM2 AESENC \TMP3, \XMM3 AESENC \TMP3, \XMM4 - movdqa HashKey_3_k(%arg2), \TMP5 + movdqu HashKey_3_k(%arg2), \TMP5 PCLMULQDQ 0x00, \TMP5, \TMP2 # TMP2 = (a1+a0)*(b1+b0) movaps 0x50(%arg1), \TMP3 AESENC \TMP3, \XMM1 # Round 5 @@ -1266,7 +1266,7 @@ TMP6 XMM0 XMM1 XMM2 XMM3 XMM4 XMM5 XMM6 XMM7 XMM8 operation movdqa \XMM7, \TMP1 pshufd $78, \XMM7, \TMP2 pxor \XMM7, \TMP2 - movdqa HashKey_2(%arg2), \TMP5 + movdqu HashKey_2(%arg2), \TMP5 # Multiply TMP5 * HashKey using karatsuba @@ -1282,7 +1282,7 @@ TMP6 XMM0 XMM1 XMM2 XMM3 XMM4 XMM5 XMM6 XMM7 XMM8 operation AESENC \TMP3, \XMM2 AESENC \TMP3, \XMM3 AESENC \TMP3, \XMM4 - movdqa HashKey_2_k(%arg2), \TMP5 + movdqu HashKey_2_k(%arg2), \TMP5 PCLMULQDQ 0x00, \TMP5, \TMP2 # TMP2 = (a1+a0)*(b1+b0) movaps 0x80(%arg1), \TMP3 AESENC \TMP3, \XMM1 # Round 8 @@ -1300,7 +1300,7 @@ TMP6 XMM0 XMM1 XMM2 XMM3 XMM4 XMM5 XMM6 XMM7 XMM8 operation movdqa \XMM8, \TMP1 pshufd $78, \XMM8, \TMP2 pxor \XMM8, \TMP2 - movdqa HashKey(%arg2), \TMP5 + movdqu HashKey(%arg2), \TMP5 PCLMULQDQ 0x11, \TMP5, \TMP1 # TMP1 = a1*b1 movaps 0x90(%arg1), \TMP3 AESENC \TMP3, \XMM1 # Round 9 @@ -1329,7 +1329,7 @@ aes_loop_par_dec_done\@: AESENCLAST \TMP3, \XMM2 AESENCLAST \TMP3, \XMM3 AESENCLAST \TMP3, \XMM4 - movdqa HashKey_k(%arg2), \TMP5 + movdqu HashKey_k(%arg2), \TMP5 PCLMULQDQ 0x00, \TMP5, \TMP2 # TMP2 = (a1+a0)*(b1+b0) movdqu (%arg4,%r11,1), \TMP3 pxor \TMP3, \XMM1 # Ciphertext/Plaintext XOR EK @@ -1405,10 +1405,10 @@ TMP7 XMM1 XMM2 XMM3 XMM4 XMMDst movdqa \XMM1, \TMP6 pshufd $78, \XMM1, \TMP2 pxor \XMM1, \TMP2 - movdqa HashKey_4(%arg2), \TMP5 + movdqu HashKey_4(%arg2), \TMP5 PCLMULQDQ 0x11, \TMP5, \TMP6 # TMP6 = a1*b1 PCLMULQDQ 0x00, \TMP5, \XMM1 # XMM1 = a0*b0 - movdqa HashKey_4_k(%arg2), \TMP4 + movdqu HashKey_4_k(%arg2), \TMP4 PCLMULQDQ 0x00, \TMP4, \TMP2 # TMP2 = (a1+a0)*(b1+b0) movdqa \XMM1, \XMMDst movdqa \TMP2, \XMM1 # result in TMP6, XMMDst, XMM1 @@ -1418,10 +1418,10 @@ TMP7 XMM1 XMM2 XMM3 XMM4 XMMDst movdqa \XMM2, \TMP1 pshufd $78, \XMM2, \TMP2 pxor \XMM2, \TMP2 - movdqa HashKey_3(%arg2), \TMP5 + movdqu HashKey_3(%arg2), \TMP5 PCLMULQDQ 0x11, \TMP5, \TMP1 # TMP1 = a1*b1 PCLMULQDQ 0x00, \TMP5, \XMM2 # XMM2 = a0*b0 - movdqa HashKey_3_k(%arg2), \TMP4 + movdqu HashKey_3_k(%arg2), \TMP4 PCLMULQDQ 0x00, \TMP4, \TMP2 # TMP2 = (a1+a0)*(b1+b0) pxor \TMP1, \TMP6 pxor \XMM2, \XMMDst @@ -1433,10 +1433,10 @@ TMP7 XMM1 XMM2 XMM3 XMM4 XMMDst movdqa \XMM3, \TMP1 pshufd $78, \XMM3, \TMP2 pxor \XMM3, \TMP2 - movdqa HashKey_2(%arg2), \TMP5 + movdqu HashKey_2(%arg2), \TMP5 PCLMULQDQ 0x11, \TMP5, \TMP1 # TMP1 = a1*b1 PCLMULQDQ 0x00, \TMP5, \XMM3 # XMM3 = a0*b0 - movdqa HashKey_2_k(%arg2), \TMP4 + movdqu HashKey_2_k(%arg2), \TMP4 PCLMULQDQ 0x00, \TMP4, \TMP2 # TMP2 = (a1+a0)*(b1+b0) pxor \TMP1, \TMP6 pxor \XMM3, \XMMDst @@ -1446,10 +1446,10 @@ TMP7 XMM1 XMM2 XMM3 XMM4 XMMDst movdqa \XMM4, \TMP1 pshufd $78, \XMM4, \TMP2 pxor \XMM4, \TMP2 - movdqa HashKey(%arg2), \TMP5 + movdqu HashKey(%arg2), \TMP5 PCLMULQDQ 0x11, \TMP5, \TMP1 # TMP1 = a1*b1 PCLMULQDQ 0x00, \TMP5, \XMM4 # XMM4 = a0*b0 - movdqa HashKey_k(%arg2), \TMP4 + movdqu HashKey_k(%arg2), \TMP4 PCLMULQDQ 0x00, \TMP4, \TMP2 # TMP2 = (a1+a0)*(b1+b0) pxor \TMP1, \TMP6 pxor \XMM4, \XMMDst From c2b24c36e0a30ebd8fc7d068da7f0451f2c05c76 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Mon, 20 Aug 2018 16:58:34 +0200 Subject: [PATCH 106/302] crypto: arm64/aes-gcm-ce - fix scatterwalk API violation Commit 71e52c278c54 ("crypto: arm64/aes-ce-gcm - operate on two input blocks at a time") modified the granularity at which the AES/GCM code processes its input to allow subsequent changes to be applied that improve performance by using aggregation to process multiple input blocks at once. For this reason, it doubled the algorithm's 'chunksize' property to 2 x AES_BLOCK_SIZE, but retained the non-SIMD fallback path that processes a single block at a time. In some cases, this violates the skcipher scatterwalk API, by calling skcipher_walk_done() with a non-zero residue value for a chunk that is expected to be handled in its entirety. This results in a WARN_ON() to be hit by the TLS self test code, but is likely to break other user cases as well. Unfortunately, none of the current test cases exercises this exact code path at the moment. Fixes: 71e52c278c54 ("crypto: arm64/aes-ce-gcm - operate on two ...") Reported-by: Vakul Garg Signed-off-by: Ard Biesheuvel Tested-by: Vakul Garg Signed-off-by: Herbert Xu --- arch/arm64/crypto/ghash-ce-glue.c | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/arch/arm64/crypto/ghash-ce-glue.c b/arch/arm64/crypto/ghash-ce-glue.c index 6e9f33d14930..067d8937d5af 100644 --- a/arch/arm64/crypto/ghash-ce-glue.c +++ b/arch/arm64/crypto/ghash-ce-glue.c @@ -417,7 +417,7 @@ static int gcm_encrypt(struct aead_request *req) __aes_arm64_encrypt(ctx->aes_key.key_enc, tag, iv, nrounds); put_unaligned_be32(2, iv + GCM_IV_SIZE); - while (walk.nbytes >= AES_BLOCK_SIZE) { + while (walk.nbytes >= (2 * AES_BLOCK_SIZE)) { int blocks = walk.nbytes / AES_BLOCK_SIZE; u8 *dst = walk.dst.virt.addr; u8 *src = walk.src.virt.addr; @@ -437,11 +437,18 @@ static int gcm_encrypt(struct aead_request *req) NULL); err = skcipher_walk_done(&walk, - walk.nbytes % AES_BLOCK_SIZE); + walk.nbytes % (2 * AES_BLOCK_SIZE)); } - if (walk.nbytes) + if (walk.nbytes) { __aes_arm64_encrypt(ctx->aes_key.key_enc, ks, iv, nrounds); + if (walk.nbytes > AES_BLOCK_SIZE) { + crypto_inc(iv, AES_BLOCK_SIZE); + __aes_arm64_encrypt(ctx->aes_key.key_enc, + ks + AES_BLOCK_SIZE, iv, + nrounds); + } + } } /* handle the tail */ @@ -545,7 +552,7 @@ static int gcm_decrypt(struct aead_request *req) __aes_arm64_encrypt(ctx->aes_key.key_enc, tag, iv, nrounds); put_unaligned_be32(2, iv + GCM_IV_SIZE); - while (walk.nbytes >= AES_BLOCK_SIZE) { + while (walk.nbytes >= (2 * AES_BLOCK_SIZE)) { int blocks = walk.nbytes / AES_BLOCK_SIZE; u8 *dst = walk.dst.virt.addr; u8 *src = walk.src.virt.addr; @@ -564,11 +571,21 @@ static int gcm_decrypt(struct aead_request *req) } while (--blocks > 0); err = skcipher_walk_done(&walk, - walk.nbytes % AES_BLOCK_SIZE); + walk.nbytes % (2 * AES_BLOCK_SIZE)); } - if (walk.nbytes) + if (walk.nbytes) { + if (walk.nbytes > AES_BLOCK_SIZE) { + u8 *iv2 = iv + AES_BLOCK_SIZE; + + memcpy(iv2, iv, AES_BLOCK_SIZE); + crypto_inc(iv2, AES_BLOCK_SIZE); + + __aes_arm64_encrypt(ctx->aes_key.key_enc, iv2, + iv2, nrounds); + } __aes_arm64_encrypt(ctx->aes_key.key_enc, iv, iv, nrounds); + } } /* handle the tail */ From 0522236d4f9c5ab2e79889cb020d1acbe5da416e Mon Sep 17 00:00:00 2001 From: Ondrej Mosnacek Date: Wed, 22 Aug 2018 08:26:31 +0200 Subject: [PATCH 107/302] crypto: vmx - Fix sleep-in-atomic bugs This patch fixes sleep-in-atomic bugs in AES-CBC and AES-XTS VMX implementations. The problem is that the blkcipher_* functions should not be called in atomic context. The bugs can be reproduced via the AF_ALG interface by trying to encrypt/decrypt sufficiently large buffers (at least 64 KiB) using the VMX implementations of 'cbc(aes)' or 'xts(aes)'. Such operations then trigger BUG in crypto_yield(): [ 891.863680] BUG: sleeping function called from invalid context at include/crypto/algapi.h:424 [ 891.864622] in_atomic(): 1, irqs_disabled(): 0, pid: 12347, name: kcapi-enc [ 891.864739] 1 lock held by kcapi-enc/12347: [ 891.864811] #0: 00000000f5d42c46 (sk_lock-AF_ALG){+.+.}, at: skcipher_recvmsg+0x50/0x530 [ 891.865076] CPU: 5 PID: 12347 Comm: kcapi-enc Not tainted 4.19.0-0.rc0.git3.1.fc30.ppc64le #1 [ 891.865251] Call Trace: [ 891.865340] [c0000003387578c0] [c000000000d67ea4] dump_stack+0xe8/0x164 (unreliable) [ 891.865511] [c000000338757910] [c000000000172a58] ___might_sleep+0x2f8/0x310 [ 891.865679] [c000000338757990] [c0000000006bff74] blkcipher_walk_done+0x374/0x4a0 [ 891.865825] [c0000003387579e0] [d000000007e73e70] p8_aes_cbc_encrypt+0x1c8/0x260 [vmx_crypto] [ 891.865993] [c000000338757ad0] [c0000000006c0ee0] skcipher_encrypt_blkcipher+0x60/0x80 [ 891.866128] [c000000338757b10] [c0000000006ec504] skcipher_recvmsg+0x424/0x530 [ 891.866283] [c000000338757bd0] [c000000000b00654] sock_recvmsg+0x74/0xa0 [ 891.866403] [c000000338757c10] [c000000000b00f64] ___sys_recvmsg+0xf4/0x2f0 [ 891.866515] [c000000338757d90] [c000000000b02bb8] __sys_recvmsg+0x68/0xe0 [ 891.866631] [c000000338757e30] [c00000000000bbe4] system_call+0x5c/0x70 Fixes: 8c755ace357c ("crypto: vmx - Adding CBC routines for VMX module") Fixes: c07f5d3da643 ("crypto: vmx - Adding support for XTS") Cc: stable@vger.kernel.org Signed-off-by: Ondrej Mosnacek Signed-off-by: Herbert Xu --- drivers/crypto/vmx/aes_cbc.c | 30 ++++++++++++++---------------- drivers/crypto/vmx/aes_xts.c | 21 ++++++++++++++------- 2 files changed, 28 insertions(+), 23 deletions(-) diff --git a/drivers/crypto/vmx/aes_cbc.c b/drivers/crypto/vmx/aes_cbc.c index 5285ece4f33a..b71895871be3 100644 --- a/drivers/crypto/vmx/aes_cbc.c +++ b/drivers/crypto/vmx/aes_cbc.c @@ -107,24 +107,23 @@ static int p8_aes_cbc_encrypt(struct blkcipher_desc *desc, ret = crypto_skcipher_encrypt(req); skcipher_request_zero(req); } else { - preempt_disable(); - pagefault_disable(); - enable_kernel_vsx(); - blkcipher_walk_init(&walk, dst, src, nbytes); ret = blkcipher_walk_virt(desc, &walk); while ((nbytes = walk.nbytes)) { + preempt_disable(); + pagefault_disable(); + enable_kernel_vsx(); aes_p8_cbc_encrypt(walk.src.virt.addr, walk.dst.virt.addr, nbytes & AES_BLOCK_MASK, &ctx->enc_key, walk.iv, 1); + disable_kernel_vsx(); + pagefault_enable(); + preempt_enable(); + nbytes &= AES_BLOCK_SIZE - 1; ret = blkcipher_walk_done(desc, &walk, nbytes); } - - disable_kernel_vsx(); - pagefault_enable(); - preempt_enable(); } return ret; @@ -147,24 +146,23 @@ static int p8_aes_cbc_decrypt(struct blkcipher_desc *desc, ret = crypto_skcipher_decrypt(req); skcipher_request_zero(req); } else { - preempt_disable(); - pagefault_disable(); - enable_kernel_vsx(); - blkcipher_walk_init(&walk, dst, src, nbytes); ret = blkcipher_walk_virt(desc, &walk); while ((nbytes = walk.nbytes)) { + preempt_disable(); + pagefault_disable(); + enable_kernel_vsx(); aes_p8_cbc_encrypt(walk.src.virt.addr, walk.dst.virt.addr, nbytes & AES_BLOCK_MASK, &ctx->dec_key, walk.iv, 0); + disable_kernel_vsx(); + pagefault_enable(); + preempt_enable(); + nbytes &= AES_BLOCK_SIZE - 1; ret = blkcipher_walk_done(desc, &walk, nbytes); } - - disable_kernel_vsx(); - pagefault_enable(); - preempt_enable(); } return ret; diff --git a/drivers/crypto/vmx/aes_xts.c b/drivers/crypto/vmx/aes_xts.c index 8bd9aff0f55f..e9954a7d4694 100644 --- a/drivers/crypto/vmx/aes_xts.c +++ b/drivers/crypto/vmx/aes_xts.c @@ -116,32 +116,39 @@ static int p8_aes_xts_crypt(struct blkcipher_desc *desc, ret = enc? crypto_skcipher_encrypt(req) : crypto_skcipher_decrypt(req); skcipher_request_zero(req); } else { + blkcipher_walk_init(&walk, dst, src, nbytes); + + ret = blkcipher_walk_virt(desc, &walk); + preempt_disable(); pagefault_disable(); enable_kernel_vsx(); - blkcipher_walk_init(&walk, dst, src, nbytes); - - ret = blkcipher_walk_virt(desc, &walk); iv = walk.iv; memset(tweak, 0, AES_BLOCK_SIZE); aes_p8_encrypt(iv, tweak, &ctx->tweak_key); + disable_kernel_vsx(); + pagefault_enable(); + preempt_enable(); + while ((nbytes = walk.nbytes)) { + preempt_disable(); + pagefault_disable(); + enable_kernel_vsx(); if (enc) aes_p8_xts_encrypt(walk.src.virt.addr, walk.dst.virt.addr, nbytes & AES_BLOCK_MASK, &ctx->enc_key, NULL, tweak); else aes_p8_xts_decrypt(walk.src.virt.addr, walk.dst.virt.addr, nbytes & AES_BLOCK_MASK, &ctx->dec_key, NULL, tweak); + disable_kernel_vsx(); + pagefault_enable(); + preempt_enable(); nbytes &= AES_BLOCK_SIZE - 1; ret = blkcipher_walk_done(desc, &walk, nbytes); } - - disable_kernel_vsx(); - pagefault_enable(); - preempt_enable(); } return ret; } From 3d7c82060d1fe65bde4023aac41a0b1bd7718e07 Mon Sep 17 00:00:00 2001 From: Srikanth Jampala Date: Wed, 22 Aug 2018 12:40:52 +0530 Subject: [PATCH 108/302] crypto: cavium/nitrox - fix for command corruption in queue full case with backlog submissions. Earlier used to post the current command without checking queue full after backlog submissions. So, post the current command only after confirming the space in queue after backlog submissions. Maintain host write index instead of reading device registers to get the next free slot to post the command. Return -ENOSPC in queue full case. Signed-off-by: Srikanth Jampala Reviewed-by: Gadam Sreerama Tested-by: Jha, Chandan Signed-off-by: Herbert Xu --- drivers/crypto/cavium/nitrox/nitrox_dev.h | 3 +- drivers/crypto/cavium/nitrox/nitrox_lib.c | 1 + drivers/crypto/cavium/nitrox/nitrox_reqmgr.c | 57 +++++++++++--------- 3 files changed, 35 insertions(+), 26 deletions(-) diff --git a/drivers/crypto/cavium/nitrox/nitrox_dev.h b/drivers/crypto/cavium/nitrox/nitrox_dev.h index 9a476bb6d4c7..af596455b420 100644 --- a/drivers/crypto/cavium/nitrox/nitrox_dev.h +++ b/drivers/crypto/cavium/nitrox/nitrox_dev.h @@ -35,6 +35,7 @@ struct nitrox_cmdq { /* requests in backlog queues */ atomic_t backlog_count; + int write_idx; /* command size 32B/64B */ u8 instr_size; u8 qno; @@ -87,7 +88,7 @@ struct nitrox_bh { struct bh_data *slc; }; -/* NITROX-5 driver state */ +/* NITROX-V driver state */ #define NITROX_UCODE_LOADED 0 #define NITROX_READY 1 diff --git a/drivers/crypto/cavium/nitrox/nitrox_lib.c b/drivers/crypto/cavium/nitrox/nitrox_lib.c index ebe267379ac9..4d31df07777f 100644 --- a/drivers/crypto/cavium/nitrox/nitrox_lib.c +++ b/drivers/crypto/cavium/nitrox/nitrox_lib.c @@ -36,6 +36,7 @@ static int cmdq_common_init(struct nitrox_cmdq *cmdq) cmdq->head = PTR_ALIGN(cmdq->head_unaligned, PKT_IN_ALIGN); cmdq->dma = PTR_ALIGN(cmdq->dma_unaligned, PKT_IN_ALIGN); cmdq->qsize = (qsize + PKT_IN_ALIGN); + cmdq->write_idx = 0; spin_lock_init(&cmdq->response_lock); spin_lock_init(&cmdq->cmdq_lock); diff --git a/drivers/crypto/cavium/nitrox/nitrox_reqmgr.c b/drivers/crypto/cavium/nitrox/nitrox_reqmgr.c index deaefd532aaa..4a362fc22f62 100644 --- a/drivers/crypto/cavium/nitrox/nitrox_reqmgr.c +++ b/drivers/crypto/cavium/nitrox/nitrox_reqmgr.c @@ -42,6 +42,16 @@ * Invalid flag options in AES-CCM IV. */ +static inline int incr_index(int index, int count, int max) +{ + if ((index + count) >= max) + index = index + count - max; + else + index += count; + + return index; +} + /** * dma_free_sglist - unmap and free the sg lists. * @ndev: N5 device @@ -426,30 +436,29 @@ static void post_se_instr(struct nitrox_softreq *sr, struct nitrox_cmdq *cmdq) { struct nitrox_device *ndev = sr->ndev; - union nps_pkt_in_instr_baoff_dbell pkt_in_baoff_dbell; - u64 offset; + int idx; u8 *ent; spin_lock_bh(&cmdq->cmdq_lock); - /* get the next write offset */ - offset = NPS_PKT_IN_INSTR_BAOFF_DBELLX(cmdq->qno); - pkt_in_baoff_dbell.value = nitrox_read_csr(ndev, offset); + idx = cmdq->write_idx; /* copy the instruction */ - ent = cmdq->head + pkt_in_baoff_dbell.s.aoff; + ent = cmdq->head + (idx * cmdq->instr_size); memcpy(ent, &sr->instr, cmdq->instr_size); - /* flush the command queue updates */ - dma_wmb(); - sr->tstamp = jiffies; atomic_set(&sr->status, REQ_POSTED); response_list_add(sr, cmdq); + sr->tstamp = jiffies; + /* flush the command queue updates */ + dma_wmb(); /* Ring doorbell with count 1 */ writeq(1, cmdq->dbell_csr_addr); /* orders the doorbell rings */ mmiowb(); + cmdq->write_idx = incr_index(idx, 1, ndev->qlen); + spin_unlock_bh(&cmdq->cmdq_lock); } @@ -459,6 +468,9 @@ static int post_backlog_cmds(struct nitrox_cmdq *cmdq) struct nitrox_softreq *sr, *tmp; int ret = 0; + if (!atomic_read(&cmdq->backlog_count)) + return 0; + spin_lock_bh(&cmdq->backlog_lock); list_for_each_entry_safe(sr, tmp, &cmdq->backlog_head, backlog) { @@ -466,7 +478,7 @@ static int post_backlog_cmds(struct nitrox_cmdq *cmdq) /* submit until space available */ if (unlikely(cmdq_full(cmdq, ndev->qlen))) { - ret = -EBUSY; + ret = -ENOSPC; break; } /* delete from backlog list */ @@ -491,23 +503,20 @@ static int nitrox_enqueue_request(struct nitrox_softreq *sr) { struct nitrox_cmdq *cmdq = sr->cmdq; struct nitrox_device *ndev = sr->ndev; - int ret = -EBUSY; + + /* try to post backlog requests */ + post_backlog_cmds(cmdq); if (unlikely(cmdq_full(cmdq, ndev->qlen))) { if (!(sr->flags & CRYPTO_TFM_REQ_MAY_BACKLOG)) - return -EAGAIN; - + return -ENOSPC; + /* add to backlog list */ backlog_list_add(sr, cmdq); - } else { - ret = post_backlog_cmds(cmdq); - if (ret) { - backlog_list_add(sr, cmdq); - return ret; - } - post_se_instr(sr, cmdq); - ret = -EINPROGRESS; + return -EBUSY; } - return ret; + post_se_instr(sr, cmdq); + + return -EINPROGRESS; } /** @@ -624,11 +633,9 @@ int nitrox_process_se_request(struct nitrox_device *ndev, */ sr->instr.fdata[0] = *((u64 *)&req->gph); sr->instr.fdata[1] = 0; - /* flush the soft_req changes before posting the cmd */ - wmb(); ret = nitrox_enqueue_request(sr); - if (ret == -EAGAIN) + if (ret == -ENOSPC) goto send_fail; return ret; From 602b74eda81311dbdb5dbab08c30f789f648ebdc Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Fri, 24 Aug 2018 15:41:35 +0300 Subject: [PATCH 109/302] mlxsw: spectrum_switchdev: Do not leak RIFs when removing bridge When a bridge device is removed, the VLANs are flushed from each configured port. This causes the ports to decrement the reference count on the associated FIDs (filtering identifier). If the reference count of a FID is 1 and it has a RIF (router interface), then this RIF is destroyed. However, if no port is member in the VLAN for which a RIF exists, then the RIF will continue to exist after the removal of the bridge. To reproduce: # ip link add name br0 type bridge vlan_filtering 1 # ip link set dev swp1 master br0 # ip link add link br0 name br0.10 type vlan id 10 # ip address add 192.0.2.0/24 dev br0.10 # ip link del dev br0 The RIF associated with br0.10 continues to exist. Fix this by iterating over all the bridge device uppers when it is destroyed and take care of destroying their RIFs. Fixes: 99f44bb3527b ("mlxsw: spectrum: Enable L3 interfaces on top of bridge devices") Signed-off-by: Ido Schimmel Reviewed-by: Petr Machata Signed-off-by: David S. Miller --- .../net/ethernet/mellanox/mlxsw/spectrum.h | 2 ++ .../ethernet/mellanox/mlxsw/spectrum_router.c | 11 ++++++++++ .../mellanox/mlxsw/spectrum_switchdev.c | 20 +++++++++++++++++++ 3 files changed, 33 insertions(+) diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h index 3ae930196741..3cdb7aca90b7 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h @@ -414,6 +414,8 @@ mlxsw_sp_netdevice_ipip_ul_event(struct mlxsw_sp *mlxsw_sp, void mlxsw_sp_port_vlan_router_leave(struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan); void mlxsw_sp_rif_destroy(struct mlxsw_sp_rif *rif); +void mlxsw_sp_rif_destroy_by_dev(struct mlxsw_sp *mlxsw_sp, + struct net_device *dev); /* spectrum_kvdl.c */ enum mlxsw_sp_kvdl_entry_type { diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c index 3a96307f51b0..2ab9cf25a08a 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c @@ -6234,6 +6234,17 @@ void mlxsw_sp_rif_destroy(struct mlxsw_sp_rif *rif) mlxsw_sp_vr_put(mlxsw_sp, vr); } +void mlxsw_sp_rif_destroy_by_dev(struct mlxsw_sp *mlxsw_sp, + struct net_device *dev) +{ + struct mlxsw_sp_rif *rif; + + rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, dev); + if (!rif) + return; + mlxsw_sp_rif_destroy(rif); +} + static void mlxsw_sp_rif_subport_params_init(struct mlxsw_sp_rif_params *params, struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan) diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c index 0d8444aaba01..db715da7bab7 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c @@ -127,6 +127,24 @@ bool mlxsw_sp_bridge_device_is_offloaded(const struct mlxsw_sp *mlxsw_sp, return !!mlxsw_sp_bridge_device_find(mlxsw_sp->bridge, br_dev); } +static int mlxsw_sp_bridge_device_upper_rif_destroy(struct net_device *dev, + void *data) +{ + struct mlxsw_sp *mlxsw_sp = data; + + mlxsw_sp_rif_destroy_by_dev(mlxsw_sp, dev); + return 0; +} + +static void mlxsw_sp_bridge_device_rifs_destroy(struct mlxsw_sp *mlxsw_sp, + struct net_device *dev) +{ + mlxsw_sp_rif_destroy_by_dev(mlxsw_sp, dev); + netdev_walk_all_upper_dev_rcu(dev, + mlxsw_sp_bridge_device_upper_rif_destroy, + mlxsw_sp); +} + static struct mlxsw_sp_bridge_device * mlxsw_sp_bridge_device_create(struct mlxsw_sp_bridge *bridge, struct net_device *br_dev) @@ -165,6 +183,8 @@ static void mlxsw_sp_bridge_device_destroy(struct mlxsw_sp_bridge *bridge, struct mlxsw_sp_bridge_device *bridge_device) { + mlxsw_sp_bridge_device_rifs_destroy(bridge->mlxsw_sp, + bridge_device->dev); list_del(&bridge_device->list); if (bridge_device->vlan_enabled) bridge->vlan_enabled_exists = false; From ab5f11055fdf8dfc3ddbd89e8e3cc550de41d1d3 Mon Sep 17 00:00:00 2001 From: Ahmad Fatoum Date: Tue, 21 Aug 2018 17:35:48 +0200 Subject: [PATCH 110/302] net: macb: Fix regression breaking non-MDIO fixed-link PHYs commit 739de9a1563a ("net: macb: Reorganize macb_mii bringup") broke initializing macb on the EVB-KSZ9477 eval board. There, of_mdiobus_register was called even for the fixed-link representing the RGMII-link to the switch with the result that the driver attempts to enumerate PHYs on a non-existent MDIO bus: libphy: MACB_mii_bus: probed mdio_bus f0028000.ethernet-ffffffff: fixed-link has invalid PHY address mdio_bus f0028000.ethernet-ffffffff: scan phy fixed-link at address 0 [snip] mdio_bus f0028000.ethernet-ffffffff: scan phy fixed-link at address 31 The "MDIO" bus registration succeeds regardless, having claimed the reset GPIO, and calling of_phy_register_fixed_link later on fails because it tries to claim the same GPIO: macb f0028000.ethernet: broken fixed-link specification Fix this by registering the fixed-link before calling mdiobus_register. Fixes: 739de9a1563a ("net: macb: Reorganize macb_mii bringup") Signed-off-by: Ahmad Fatoum Signed-off-by: David S. Miller --- drivers/net/ethernet/cadence/macb_main.c | 27 +++++++++++++++--------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c index dc09f9a8a49b..f46b854d34b5 100644 --- a/drivers/net/ethernet/cadence/macb_main.c +++ b/drivers/net/ethernet/cadence/macb_main.c @@ -482,11 +482,6 @@ static int macb_mii_probe(struct net_device *dev) if (np) { if (of_phy_is_fixed_link(np)) { - if (of_phy_register_fixed_link(np) < 0) { - dev_err(&bp->pdev->dev, - "broken fixed-link specification\n"); - return -ENODEV; - } bp->phy_node = of_node_get(np); } else { bp->phy_node = of_parse_phandle(np, "phy-handle", 0); @@ -569,7 +564,7 @@ static int macb_mii_init(struct macb *bp) { struct macb_platform_data *pdata; struct device_node *np; - int err; + int err = -ENXIO; /* Enable management port */ macb_writel(bp, NCR, MACB_BIT(MPE)); @@ -592,12 +587,23 @@ static int macb_mii_init(struct macb *bp) dev_set_drvdata(&bp->dev->dev, bp->mii_bus); np = bp->pdev->dev.of_node; - if (pdata) - bp->mii_bus->phy_mask = pdata->phy_mask; + if (np && of_phy_is_fixed_link(np)) { + if (of_phy_register_fixed_link(np) < 0) { + dev_err(&bp->pdev->dev, + "broken fixed-link specification %pOF\n", np); + goto err_out_free_mdiobus; + } + + err = mdiobus_register(bp->mii_bus); + } else { + if (pdata) + bp->mii_bus->phy_mask = pdata->phy_mask; + + err = of_mdiobus_register(bp->mii_bus, np); + } - err = of_mdiobus_register(bp->mii_bus, np); if (err) - goto err_out_free_mdiobus; + goto err_out_free_fixed_link; err = macb_mii_probe(bp->dev); if (err) @@ -607,6 +613,7 @@ static int macb_mii_init(struct macb *bp) err_out_unregister_bus: mdiobus_unregister(bp->mii_bus); +err_out_free_fixed_link: if (np && of_phy_is_fixed_link(np)) of_phy_deregister_fixed_link(np); err_out_free_mdiobus: From f7b9e8e111e0ce04ed7d1a1cb5b01b6e57775708 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 22 Aug 2018 15:27:23 +0200 Subject: [PATCH 111/302] Revert "net: stmmac: fix build failure due to missing COMMON_CLK dependency" This reverts commit bde4975310eb1982bd0bbff673989052d92fd481. All legacy clock implementations now implement clk_set_rate() (Some implementations may be dummies, though). Signed-off-by: Geert Uytterhoeven Acked-by: Arnd Bergmann Acked-by: Jose Abreu Signed-off-by: David S. Miller --- drivers/net/ethernet/stmicro/stmmac/Kconfig | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/Kconfig b/drivers/net/ethernet/stmicro/stmmac/Kconfig index edf20361ea5f..bf4acebb6bcd 100644 --- a/drivers/net/ethernet/stmicro/stmmac/Kconfig +++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig @@ -33,7 +33,7 @@ config DWMAC_DWC_QOS_ETH select PHYLIB select CRC32 select MII - depends on OF && COMMON_CLK && HAS_DMA + depends on OF && HAS_DMA help Support for chips using the snps,dwc-qos-ethernet.txt DT binding. @@ -57,7 +57,7 @@ config DWMAC_ANARION config DWMAC_IPQ806X tristate "QCA IPQ806x DWMAC support" default ARCH_QCOM - depends on OF && COMMON_CLK && (ARCH_QCOM || COMPILE_TEST) + depends on OF && (ARCH_QCOM || COMPILE_TEST) select MFD_SYSCON help Support for QCA IPQ806X DWMAC Ethernet. @@ -100,7 +100,7 @@ config DWMAC_OXNAS config DWMAC_ROCKCHIP tristate "Rockchip dwmac support" default ARCH_ROCKCHIP - depends on OF && COMMON_CLK && (ARCH_ROCKCHIP || COMPILE_TEST) + depends on OF && (ARCH_ROCKCHIP || COMPILE_TEST) select MFD_SYSCON help Support for Ethernet controller on Rockchip RK3288 SoC. @@ -123,7 +123,7 @@ config DWMAC_SOCFPGA config DWMAC_STI tristate "STi GMAC support" default ARCH_STI - depends on OF && COMMON_CLK && (ARCH_STI || COMPILE_TEST) + depends on OF && (ARCH_STI || COMPILE_TEST) select MFD_SYSCON ---help--- Support for ethernet controller on STi SOCs. @@ -147,7 +147,7 @@ config DWMAC_STM32 config DWMAC_SUNXI tristate "Allwinner GMAC support" default ARCH_SUNXI - depends on OF && COMMON_CLK && (ARCH_SUNXI || COMPILE_TEST) + depends on OF && (ARCH_SUNXI || COMPILE_TEST) ---help--- Support for Allwinner A20/A31 GMAC ethernet controllers. From 0da70f808029476001109b6cb076737bc04cea2e Mon Sep 17 00:00:00 2001 From: Anssi Hannula Date: Thu, 23 Aug 2018 10:45:22 +0300 Subject: [PATCH 112/302] net: macb: do not disable MDIO bus at open/close time macb_reset_hw() is called from macb_close() and indirectly from macb_open(). macb_reset_hw() zeroes the NCR register, including the MPE (Management Port Enable) bit. This will prevent accessing any other PHYs for other Ethernet MACs on the MDIO bus, which remains registered at macb_reset_hw() time, until macb_init_hw() is called from macb_open() which sets the MPE bit again. I.e. currently the MDIO bus has a short disruption at open time and is disabled at close time until the interface is opened again. Fix that by only touching the RE and TE bits when enabling and disabling RX/TX. v2: Make macb_init_hw() NCR write a single statement. Fixes: 6c36a7074436 ("macb: Use generic PHY layer") Signed-off-by: Anssi Hannula Reviewed-by: Claudiu Beznea Tested-by: Claudiu Beznea Signed-off-by: David S. Miller --- drivers/net/ethernet/cadence/macb_main.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c index f46b854d34b5..c6707ea2d751 100644 --- a/drivers/net/ethernet/cadence/macb_main.c +++ b/drivers/net/ethernet/cadence/macb_main.c @@ -2035,14 +2035,17 @@ static void macb_reset_hw(struct macb *bp) { struct macb_queue *queue; unsigned int q; + u32 ctrl = macb_readl(bp, NCR); /* Disable RX and TX (XXX: Should we halt the transmission * more gracefully?) */ - macb_writel(bp, NCR, 0); + ctrl &= ~(MACB_BIT(RE) | MACB_BIT(TE)); /* Clear the stats registers (XXX: Update stats first?) */ - macb_writel(bp, NCR, MACB_BIT(CLRSTAT)); + ctrl |= MACB_BIT(CLRSTAT); + + macb_writel(bp, NCR, ctrl); /* Clear all status flags */ macb_writel(bp, TSR, -1); @@ -2230,7 +2233,7 @@ static void macb_init_hw(struct macb *bp) } /* Enable TX and RX */ - macb_writel(bp, NCR, MACB_BIT(RE) | MACB_BIT(TE) | MACB_BIT(MPE)); + macb_writel(bp, NCR, macb_readl(bp, NCR) | MACB_BIT(RE) | MACB_BIT(TE)); } /* The hash address register is 64 bits long and takes up two From 6750c87074c5b534d82fdaabb1deb45b8f1f57de Mon Sep 17 00:00:00 2001 From: Manish Chopra Date: Thu, 23 Aug 2018 13:20:52 -0700 Subject: [PATCH 113/302] qlge: Fix netdev features configuration. qlge_fix_features() is not supposed to modify hardware or driver state, rather it is supposed to only fix requested fetures bits. Currently qlge_fix_features() also goes for interface down and up unnecessarily if there is not even any change in features set. This patch changes/fixes following - 1) Move reload of interface or device re-config from qlge_fix_features() to qlge_set_features(). 2) Reload of interface in qlge_set_features() only if relevant feature bit (NETIF_F_HW_VLAN_CTAG_RX) is changed. 3) Get rid of qlge_fix_features() since driver is not really required to fix any features bit. Signed-off-by: Manish Reviewed-by: Benjamin Poirier Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qlge/qlge_main.c | 23 +++++++------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/drivers/net/ethernet/qlogic/qlge/qlge_main.c b/drivers/net/ethernet/qlogic/qlge/qlge_main.c index 353f1c129af1..059ba9429e51 100644 --- a/drivers/net/ethernet/qlogic/qlge/qlge_main.c +++ b/drivers/net/ethernet/qlogic/qlge/qlge_main.c @@ -2384,26 +2384,20 @@ static int qlge_update_hw_vlan_features(struct net_device *ndev, return status; } -static netdev_features_t qlge_fix_features(struct net_device *ndev, - netdev_features_t features) -{ - int err; - - /* Update the behavior of vlan accel in the adapter */ - err = qlge_update_hw_vlan_features(ndev, features); - if (err) - return err; - - return features; -} - static int qlge_set_features(struct net_device *ndev, netdev_features_t features) { netdev_features_t changed = ndev->features ^ features; + int err; + + if (changed & NETIF_F_HW_VLAN_CTAG_RX) { + /* Update the behavior of vlan accel in the adapter */ + err = qlge_update_hw_vlan_features(ndev, features); + if (err) + return err; - if (changed & NETIF_F_HW_VLAN_CTAG_RX) qlge_vlan_mode(ndev, features); + } return 0; } @@ -4719,7 +4713,6 @@ static const struct net_device_ops qlge_netdev_ops = { .ndo_set_mac_address = qlge_set_mac_address, .ndo_validate_addr = eth_validate_addr, .ndo_tx_timeout = qlge_tx_timeout, - .ndo_fix_features = qlge_fix_features, .ndo_set_features = qlge_set_features, .ndo_vlan_rx_add_vid = qlge_vlan_rx_add_vid, .ndo_vlan_rx_kill_vid = qlge_vlan_rx_kill_vid, From 2d66f997f0545c8f7fc5cf0b49af1decb35170e7 Mon Sep 17 00:00:00 2001 From: Jason Wang Date: Fri, 24 Aug 2018 16:53:13 +0800 Subject: [PATCH 114/302] vhost: correctly check the iova range when waking virtqueue We don't wakeup the virtqueue if the first byte of pending iova range is the last byte of the range we just got updated. This will lead a virtqueue to wait for IOTLB updating forever. Fixing by correct the check and wake up the virtqueue in this case. Fixes: 6b1e6cc7855b ("vhost: new device IOTLB API") Reported-by: Peter Xu Signed-off-by: Jason Wang Reviewed-by: Peter Xu Tested-by: Peter Xu Acked-by: Michael S. Tsirkin Signed-off-by: David S. Miller --- drivers/vhost/vhost.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c index 96c1d8400822..b13c6b4b2c66 100644 --- a/drivers/vhost/vhost.c +++ b/drivers/vhost/vhost.c @@ -952,7 +952,7 @@ static void vhost_iotlb_notify_vq(struct vhost_dev *d, list_for_each_entry_safe(node, n, &d->pending_list, node) { struct vhost_iotlb_msg *vq_msg = &node->msg.iotlb; if (msg->iova <= vq_msg->iova && - msg->iova + msg->size - 1 > vq_msg->iova && + msg->iova + msg->size - 1 >= vq_msg->iova && vq_msg->type == VHOST_IOTLB_MISS) { vhost_poll_queue(&node->vq->poll); list_del(&node->node); From e75d039a54090470b7a42e803fd4f9398390f907 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Fri, 24 Aug 2018 12:18:30 +0100 Subject: [PATCH 115/302] qed: fix spelling mistake "comparsion" -> "comparison" Trivial fix to spelling mistake in DP_ERR error message Signed-off-by: Colin Ian King Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qed/qed_init_ops.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/qlogic/qed/qed_init_ops.c b/drivers/net/ethernet/qlogic/qed/qed_init_ops.c index d9ab5add27a8..34193c2f1699 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_init_ops.c +++ b/drivers/net/ethernet/qlogic/qed/qed_init_ops.c @@ -407,7 +407,7 @@ static void qed_init_cmd_rd(struct qed_hwfn *p_hwfn, if (i == QED_INIT_MAX_POLL_COUNT) { DP_ERR(p_hwfn, - "Timeout when polling reg: 0x%08x [ Waiting-for: %08x Got: %08x (comparsion %08x)]\n", + "Timeout when polling reg: 0x%08x [ Waiting-for: %08x Got: %08x (comparison %08x)]\n", addr, le32_to_cpu(cmd->expected_val), val, le32_to_cpu(cmd->op_data)); } From 98c8f125fd8a6240ea343c1aa50a1be9047791b8 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Sat, 25 Aug 2018 22:58:01 -0700 Subject: [PATCH 116/302] net: sched: Fix memory exposure from short TCA_U32_SEL Via u32_change(), TCA_U32_SEL has an unspecified type in the netlink policy, so max length isn't enforced, only minimum. This means nkeys (from userspace) was being trusted without checking the actual size of nla_len(), which could lead to a memory over-read, and ultimately an exposure via a call to u32_dump(). Reachability is CAP_NET_ADMIN within a namespace. Reported-by: Al Viro Cc: Jamal Hadi Salim Cc: Cong Wang Cc: Jiri Pirko Cc: "David S. Miller" Cc: netdev@vger.kernel.org Signed-off-by: Kees Cook Acked-by: Jamal Hadi Salim Signed-off-by: David S. Miller --- net/sched/cls_u32.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c index d5d2a6dc3921..f218ccf1e2d9 100644 --- a/net/sched/cls_u32.c +++ b/net/sched/cls_u32.c @@ -914,6 +914,7 @@ static int u32_change(struct net *net, struct sk_buff *in_skb, struct nlattr *opt = tca[TCA_OPTIONS]; struct nlattr *tb[TCA_U32_MAX + 1]; u32 htid, flags = 0; + size_t sel_size; int err; #ifdef CONFIG_CLS_U32_PERF size_t size; @@ -1076,8 +1077,13 @@ static int u32_change(struct net *net, struct sk_buff *in_skb, } s = nla_data(tb[TCA_U32_SEL]); + sel_size = struct_size(s, keys, s->nkeys); + if (nla_len(tb[TCA_U32_SEL]) < sel_size) { + err = -EINVAL; + goto erridr; + } - n = kzalloc(sizeof(*n) + s->nkeys*sizeof(struct tc_u32_key), GFP_KERNEL); + n = kzalloc(offsetof(typeof(*n), sel) + sel_size, GFP_KERNEL); if (n == NULL) { err = -ENOBUFS; goto erridr; @@ -1092,7 +1098,7 @@ static int u32_change(struct net *net, struct sk_buff *in_skb, } #endif - memcpy(&n->sel, s, sizeof(*s) + s->nkeys*sizeof(struct tc_u32_key)); + memcpy(&n->sel, s, sel_size); RCU_INIT_POINTER(n->ht_up, ht); n->handle = handle; n->fshift = s->hmask ? ffs(ntohl(s->hmask)) - 1 : 0; From 3ad867001c91657c46dcf6656d52eb6080286fd5 Mon Sep 17 00:00:00 2001 From: Lothar Felten Date: Tue, 14 Aug 2018 09:09:37 +0200 Subject: [PATCH 117/302] hwmon: (ina2xx) fix sysfs shunt resistor read access fix the sysfs shunt resistor read access: return the shunt resistor value, not the calibration register contents. update email address Signed-off-by: Lothar Felten Signed-off-by: Guenter Roeck --- Documentation/hwmon/ina2xx | 2 +- drivers/hwmon/ina2xx.c | 13 +++++++++++-- include/linux/platform_data/ina2xx.h | 2 +- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/Documentation/hwmon/ina2xx b/Documentation/hwmon/ina2xx index 72d16f08e431..b8df81f6d6bc 100644 --- a/Documentation/hwmon/ina2xx +++ b/Documentation/hwmon/ina2xx @@ -32,7 +32,7 @@ Supported chips: Datasheet: Publicly available at the Texas Instruments website http://www.ti.com/ -Author: Lothar Felten +Author: Lothar Felten Description ----------- diff --git a/drivers/hwmon/ina2xx.c b/drivers/hwmon/ina2xx.c index e9e6aeabbf84..71d3445ba869 100644 --- a/drivers/hwmon/ina2xx.c +++ b/drivers/hwmon/ina2xx.c @@ -17,7 +17,7 @@ * Bi-directional Current/Power Monitor with I2C Interface * Datasheet: http://www.ti.com/product/ina230 * - * Copyright (C) 2012 Lothar Felten + * Copyright (C) 2012 Lothar Felten * Thanks to Jan Volkering * * This program is free software; you can redistribute it and/or modify @@ -329,6 +329,15 @@ static int ina2xx_set_shunt(struct ina2xx_data *data, long val) return 0; } +static ssize_t ina2xx_show_shunt(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct ina2xx_data *data = dev_get_drvdata(dev); + + return snprintf(buf, PAGE_SIZE, "%li\n", data->rshunt); +} + static ssize_t ina2xx_store_shunt(struct device *dev, struct device_attribute *da, const char *buf, size_t count) @@ -403,7 +412,7 @@ static SENSOR_DEVICE_ATTR(power1_input, S_IRUGO, ina2xx_show_value, NULL, /* shunt resistance */ static SENSOR_DEVICE_ATTR(shunt_resistor, S_IRUGO | S_IWUSR, - ina2xx_show_value, ina2xx_store_shunt, + ina2xx_show_shunt, ina2xx_store_shunt, INA2XX_CALIBRATION); /* update interval (ina226 only) */ diff --git a/include/linux/platform_data/ina2xx.h b/include/linux/platform_data/ina2xx.h index 9abc0ca7259b..9f0aa1b48c78 100644 --- a/include/linux/platform_data/ina2xx.h +++ b/include/linux/platform_data/ina2xx.h @@ -1,7 +1,7 @@ /* * Driver for Texas Instruments INA219, INA226 power monitor chips * - * Copyright (C) 2012 Lothar Felten + * Copyright (C) 2012 Lothar Felten * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as From 9d19371df50a73301aec66a479b490587e889055 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 14 Aug 2018 12:12:36 +0300 Subject: [PATCH 118/302] hwmon: (adt7475) Potential error pointer dereferences The adt7475_update_device() function returns error pointers. The problem is that in show_pwmfreq() we dereference it before the check. And then in pwm_use_point2_pwm_at_crit_show() there isn't a check at all. I don't know if it's required, but it silences a static checker warning and it's doesn't hurt anything to check. Signed-off-by: Dan Carpenter Reviewed-by: Tokunori Ikegami Signed-off-by: Guenter Roeck --- drivers/hwmon/adt7475.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/hwmon/adt7475.c b/drivers/hwmon/adt7475.c index 90837f7c7d0f..16045149f3db 100644 --- a/drivers/hwmon/adt7475.c +++ b/drivers/hwmon/adt7475.c @@ -962,13 +962,14 @@ static ssize_t show_pwmfreq(struct device *dev, struct device_attribute *attr, { struct adt7475_data *data = adt7475_update_device(dev); struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); - int i = clamp_val(data->range[sattr->index] & 0xf, 0, - ARRAY_SIZE(pwmfreq_table) - 1); + int idx; if (IS_ERR(data)) return PTR_ERR(data); + idx = clamp_val(data->range[sattr->index] & 0xf, 0, + ARRAY_SIZE(pwmfreq_table) - 1); - return sprintf(buf, "%d\n", pwmfreq_table[i]); + return sprintf(buf, "%d\n", pwmfreq_table[idx]); } static ssize_t set_pwmfreq(struct device *dev, struct device_attribute *attr, @@ -1004,6 +1005,10 @@ static ssize_t pwm_use_point2_pwm_at_crit_show(struct device *dev, char *buf) { struct adt7475_data *data = adt7475_update_device(dev); + + if (IS_ERR(data)) + return PTR_ERR(data); + return sprintf(buf, "%d\n", !!(data->config4 & CONFIG4_MAXDUTY)); } From f196dec6d50abb2e65fb54a0621b2f1b4d922995 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 14 Aug 2018 13:07:47 +0300 Subject: [PATCH 119/302] hwmon: (adt7475) Make adt7475_read_word() return errors The adt7475_read_word() function was meant to return negative error codes on failure. Signed-off-by: Dan Carpenter Reviewed-by: Tokunori Ikegami Signed-off-by: Guenter Roeck --- drivers/hwmon/adt7475.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/drivers/hwmon/adt7475.c b/drivers/hwmon/adt7475.c index 16045149f3db..f4c7516eb989 100644 --- a/drivers/hwmon/adt7475.c +++ b/drivers/hwmon/adt7475.c @@ -302,14 +302,18 @@ static inline u16 volt2reg(int channel, long volt, u8 bypass_attn) return clamp_val(reg, 0, 1023) & (0xff << 2); } -static u16 adt7475_read_word(struct i2c_client *client, int reg) +static int adt7475_read_word(struct i2c_client *client, int reg) { - u16 val; + int val1, val2; - val = i2c_smbus_read_byte_data(client, reg); - val |= (i2c_smbus_read_byte_data(client, reg + 1) << 8); + val1 = i2c_smbus_read_byte_data(client, reg); + if (val1 < 0) + return val1; + val2 = i2c_smbus_read_byte_data(client, reg + 1); + if (val2 < 0) + return val2; - return val; + return val1 | (val2 << 8); } static void adt7475_write_word(struct i2c_client *client, int reg, u16 val) From d49dbfade96d5b0863ca8a90122a805edd5ef50a Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Wed, 15 Aug 2018 08:14:37 -0500 Subject: [PATCH 120/302] hwmon: (nct6775) Fix potential Spectre v1 val can be indirectly controlled by user-space, hence leading to a potential exploitation of the Spectre variant 1 vulnerability. This issue was detected with the help of Smatch: vers/hwmon/nct6775.c:2698 store_pwm_weight_temp_sel() warn: potential spectre issue 'data->temp_src' [r] Fix this by sanitizing val before using it to index data->temp_src Notice that given that speculation windows are large, the policy is to kill the speculation on the first load and not worry if it can be completed with a dependent load/store [1]. [1] https://marc.info/?l=linux-kernel&m=152449131114778&w=2 Cc: stable@vger.kernel.org Signed-off-by: Gustavo A. R. Silva Signed-off-by: Guenter Roeck --- drivers/hwmon/nct6775.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/hwmon/nct6775.c b/drivers/hwmon/nct6775.c index c6bd61e4695a..944f5b63aecd 100644 --- a/drivers/hwmon/nct6775.c +++ b/drivers/hwmon/nct6775.c @@ -63,6 +63,7 @@ #include #include #include +#include #include "lm75.h" #define USE_ALTERNATE @@ -2689,6 +2690,7 @@ store_pwm_weight_temp_sel(struct device *dev, struct device_attribute *attr, return err; if (val > NUM_TEMP) return -EINVAL; + val = array_index_nospec(val, NUM_TEMP + 1); if (val && (!(data->have_temp & BIT(val - 1)) || !data->temp_src[val - 1])) return -EINVAL; From c7c09dc187f0323ad40b5b6c57a6db673a386a7f Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Fri, 24 Aug 2018 11:29:27 +0800 Subject: [PATCH 121/302] nios2: kconfig: remove duplicate DEBUG_STACK_USAGE symbol defintions DEBUG_STACK_USAGE is already defined in lib/Kconfig.debug Signed-off-by: Tobias Klauser Signed-off-by: Ley Foon Tan --- arch/nios2/Kconfig.debug | 9 --------- 1 file changed, 9 deletions(-) diff --git a/arch/nios2/Kconfig.debug b/arch/nios2/Kconfig.debug index 7a49f0d28d14..f1da8a7b17ff 100644 --- a/arch/nios2/Kconfig.debug +++ b/arch/nios2/Kconfig.debug @@ -3,15 +3,6 @@ config TRACE_IRQFLAGS_SUPPORT def_bool y -config DEBUG_STACK_USAGE - bool "Enable stack utilization instrumentation" - depends on DEBUG_KERNEL - help - Enables the display of the minimum amount of free stack which each - task has ever had available in the sysrq-T and sysrq-P debug output. - - This option will slow down process creation somewhat. - config EARLY_PRINTK bool "Activate early kernel debugging" default y From 2b7bd20d5605e0314d677ea21b462543e73e466c Mon Sep 17 00:00:00 2001 From: Souptick Joarder Date: Sat, 28 Jul 2018 19:08:45 +0530 Subject: [PATCH 122/302] drm/mediatek: Convert drm_atomic_helper_suspend/resume() convert drm_atomic_helper_suspend/resume() to use drm_mode_config_helper_suspend/resume(). Signed-off-by: Souptick Joarder Signed-off-by: Ajit Negi Signed-off-by: CK Hu --- drivers/gpu/drm/mediatek/mtk_drm_drv.c | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c index 39721119713b..b68922a793cb 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c @@ -580,29 +580,24 @@ static int mtk_drm_sys_suspend(struct device *dev) { struct mtk_drm_private *private = dev_get_drvdata(dev); struct drm_device *drm = private->drm; + int ret; - drm_kms_helper_poll_disable(drm); - - private->suspend_state = drm_atomic_helper_suspend(drm); - if (IS_ERR(private->suspend_state)) { - drm_kms_helper_poll_enable(drm); - return PTR_ERR(private->suspend_state); - } - + ret = drm_mode_config_helper_suspend(drm); DRM_DEBUG_DRIVER("mtk_drm_sys_suspend\n"); - return 0; + + return ret; } static int mtk_drm_sys_resume(struct device *dev) { struct mtk_drm_private *private = dev_get_drvdata(dev); struct drm_device *drm = private->drm; + int ret; - drm_atomic_helper_resume(drm, private->suspend_state); - drm_kms_helper_poll_enable(drm); - + ret = drm_mode_config_helper_resume(drm); DRM_DEBUG_DRIVER("mtk_drm_sys_resume\n"); - return 0; + + return ret; } #endif From 8272806d21bf2a7fd74602cc7bade7d12f73ac4b Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Tue, 17 Jul 2018 10:35:18 +0200 Subject: [PATCH 123/302] drm/mediatek: Replace drm_dev_unref with drm_dev_put This patch unifies the naming of DRM functions for reference counting of struct drm_device. The resulting code is more aligned with the rest of the Linux kernel interfaces. Signed-off-by: Thomas Zimmermann Reviewed-by: Philipp Zabel Signed-off-by: CK Hu --- drivers/gpu/drm/mediatek/mtk_drm_drv.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c index b68922a793cb..47ec604289b7 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c @@ -381,7 +381,7 @@ static int mtk_drm_bind(struct device *dev) err_deinit: mtk_drm_kms_deinit(drm); err_free: - drm_dev_unref(drm); + drm_dev_put(drm); return ret; } @@ -390,7 +390,7 @@ static void mtk_drm_unbind(struct device *dev) struct mtk_drm_private *private = dev_get_drvdata(dev); drm_dev_unregister(private->drm); - drm_dev_unref(private->drm); + drm_dev_put(private->drm); private->drm = NULL; } @@ -564,7 +564,7 @@ static int mtk_drm_remove(struct platform_device *pdev) drm_dev_unregister(drm); mtk_drm_kms_deinit(drm); - drm_dev_unref(drm); + drm_dev_put(drm); component_master_del(&pdev->dev, &mtk_drm_ops); pm_runtime_disable(&pdev->dev); From 29d32e466e98e03378878e95339334971d0fdaf4 Mon Sep 17 00:00:00 2001 From: Stu Hsieh Date: Thu, 9 Aug 2018 10:15:36 +0800 Subject: [PATCH 124/302] drm/mediatek: add connection from RDMA0 to DPI1 This patch add connection from RDMA0 to DPI1 Signed-off-by: Stu Hsieh Signed-off-by: CK Hu --- drivers/gpu/drm/mediatek/mtk_drm_ddp.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp.c b/drivers/gpu/drm/mediatek/mtk_drm_ddp.c index 87e4191c250e..03e3628b5b0d 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_ddp.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp.c @@ -106,6 +106,7 @@ #define OVL1_MOUT_EN_COLOR1 0x1 #define GAMMA_MOUT_EN_RDMA1 0x1 #define RDMA0_SOUT_DPI0 0x2 +#define RDMA0_SOUT_DPI1 0x3 #define RDMA0_SOUT_DSI2 0x4 #define RDMA0_SOUT_DSI3 0x5 #define RDMA1_SOUT_DPI0 0x2 @@ -224,6 +225,9 @@ static unsigned int mtk_ddp_mout_en(enum mtk_ddp_comp_id cur, } else if (cur == DDP_COMPONENT_RDMA0 && next == DDP_COMPONENT_DPI0) { *addr = DISP_REG_CONFIG_DISP_RDMA0_SOUT_EN; value = RDMA0_SOUT_DPI0; + } else if (cur == DDP_COMPONENT_RDMA0 && next == DDP_COMPONENT_DPI1) { + *addr = DISP_REG_CONFIG_DISP_RDMA0_SOUT_EN; + value = RDMA0_SOUT_DPI1; } else if (cur == DDP_COMPONENT_RDMA0 && next == DDP_COMPONENT_DSI2) { *addr = DISP_REG_CONFIG_DISP_RDMA0_SOUT_EN; value = RDMA0_SOUT_DSI2; From 48d25d243bfb20a7230e9f226c560b71d989d962 Mon Sep 17 00:00:00 2001 From: Stu Hsieh Date: Thu, 9 Aug 2018 10:15:37 +0800 Subject: [PATCH 125/302] drm/mediatek: add connection from RDMA0 to DSI1 This patch add connection from RDMA0 to DSI1 Signed-off-by: Stu Hsieh Signed-off-by: CK Hu --- drivers/gpu/drm/mediatek/mtk_drm_ddp.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp.c b/drivers/gpu/drm/mediatek/mtk_drm_ddp.c index 03e3628b5b0d..310d8482d5a0 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_ddp.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp.c @@ -107,6 +107,7 @@ #define GAMMA_MOUT_EN_RDMA1 0x1 #define RDMA0_SOUT_DPI0 0x2 #define RDMA0_SOUT_DPI1 0x3 +#define RDMA0_SOUT_DSI1 0x1 #define RDMA0_SOUT_DSI2 0x4 #define RDMA0_SOUT_DSI3 0x5 #define RDMA1_SOUT_DPI0 0x2 @@ -228,6 +229,9 @@ static unsigned int mtk_ddp_mout_en(enum mtk_ddp_comp_id cur, } else if (cur == DDP_COMPONENT_RDMA0 && next == DDP_COMPONENT_DPI1) { *addr = DISP_REG_CONFIG_DISP_RDMA0_SOUT_EN; value = RDMA0_SOUT_DPI1; + } else if (cur == DDP_COMPONENT_RDMA0 && next == DDP_COMPONENT_DSI1) { + *addr = DISP_REG_CONFIG_DISP_RDMA0_SOUT_EN; + value = RDMA0_SOUT_DSI1; } else if (cur == DDP_COMPONENT_RDMA0 && next == DDP_COMPONENT_DSI2) { *addr = DISP_REG_CONFIG_DISP_RDMA0_SOUT_EN; value = RDMA0_SOUT_DSI2; From 0a14785ee32ad40458657edaf1025f71ebbc1147 Mon Sep 17 00:00:00 2001 From: Stu Hsieh Date: Thu, 9 Aug 2018 10:15:38 +0800 Subject: [PATCH 126/302] drm/mediatek: add connection from RDMA1 to DSI0 This patch add connection from RDMA1 to DSI0 Signed-off-by: Stu Hsieh Signed-off-by: CK Hu --- drivers/gpu/drm/mediatek/mtk_drm_ddp.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp.c b/drivers/gpu/drm/mediatek/mtk_drm_ddp.c index 310d8482d5a0..31189fad8d4e 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_ddp.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp.c @@ -124,6 +124,7 @@ #define DPI0_SEL_IN_RDMA2 0x3 #define DPI1_SEL_IN_RDMA1 (0x1 << 8) #define DPI1_SEL_IN_RDMA2 (0x3 << 8) +#define DSI0_SEL_IN_RDMA1 0x1 #define DSI1_SEL_IN_RDMA1 0x1 #define DSI1_SEL_IN_RDMA2 0x4 #define DSI2_SEL_IN_RDMA1 (0x1 << 16) @@ -290,6 +291,9 @@ static unsigned int mtk_ddp_sel_in(enum mtk_ddp_comp_id cur, } else if (cur == DDP_COMPONENT_RDMA1 && next == DDP_COMPONENT_DPI1) { *addr = DISP_REG_CONFIG_DPI_SEL_IN; value = DPI1_SEL_IN_RDMA1; + } else if (cur == DDP_COMPONENT_RDMA1 && next == DDP_COMPONENT_DSI0) { + *addr = DISP_REG_CONFIG_DSIE_SEL_IN; + value = DSI0_SEL_IN_RDMA1; } else if (cur == DDP_COMPONENT_RDMA1 && next == DDP_COMPONENT_DSI1) { *addr = DISP_REG_CONFIG_DSIO_SEL_IN; value = DSI1_SEL_IN_RDMA1; From 85186efc2a5975801cd4ba03a9143305e474b645 Mon Sep 17 00:00:00 2001 From: Stu Hsieh Date: Thu, 9 Aug 2018 10:15:39 +0800 Subject: [PATCH 127/302] drm/mediatek: add connection from RDMA2 to DSI0 This patch add connection from RDMA2 to DSI0 Signed-off-by: Stu Hsieh Signed-off-by: CK Hu --- drivers/gpu/drm/mediatek/mtk_drm_ddp.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp.c b/drivers/gpu/drm/mediatek/mtk_drm_ddp.c index 31189fad8d4e..3239f22785fd 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_ddp.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp.c @@ -125,6 +125,7 @@ #define DPI1_SEL_IN_RDMA1 (0x1 << 8) #define DPI1_SEL_IN_RDMA2 (0x3 << 8) #define DSI0_SEL_IN_RDMA1 0x1 +#define DSI0_SEL_IN_RDMA2 0x4 #define DSI1_SEL_IN_RDMA1 0x1 #define DSI1_SEL_IN_RDMA2 0x4 #define DSI2_SEL_IN_RDMA1 (0x1 << 16) @@ -309,6 +310,9 @@ static unsigned int mtk_ddp_sel_in(enum mtk_ddp_comp_id cur, } else if (cur == DDP_COMPONENT_RDMA2 && next == DDP_COMPONENT_DPI1) { *addr = DISP_REG_CONFIG_DPI_SEL_IN; value = DPI1_SEL_IN_RDMA2; + } else if (cur == DDP_COMPONENT_RDMA2 && next == DDP_COMPONENT_DSI0) { + *addr = DISP_REG_CONFIG_DSIE_SEL_IN; + value = DSI0_SEL_IN_RDMA2; } else if (cur == DDP_COMPONENT_RDMA2 && next == DDP_COMPONENT_DSI1) { *addr = DISP_REG_CONFIG_DSIE_SEL_IN; value = DSI1_SEL_IN_RDMA2; From 182add0b1b9170a1f8f2a049fe2e298222cf405a Mon Sep 17 00:00:00 2001 From: Stu Hsieh Date: Thu, 9 Aug 2018 10:15:40 +0800 Subject: [PATCH 128/302] drm/mediatek: add memory mode and layer_config for RDMA This patch add memory mode for RDMA and layer_config for RDMA If use RDMA to read data from memory, it should set memory mode to RDMA Layer config set the data address and pitch to RDMA from plane setting. Signed-off-by: Stu Hsieh Signed-off-by: CK Hu --- drivers/gpu/drm/mediatek/mtk_disp_rdma.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/drivers/gpu/drm/mediatek/mtk_disp_rdma.c b/drivers/gpu/drm/mediatek/mtk_disp_rdma.c index 585943c81e1f..08866550740f 100644 --- a/drivers/gpu/drm/mediatek/mtk_disp_rdma.c +++ b/drivers/gpu/drm/mediatek/mtk_disp_rdma.c @@ -31,14 +31,20 @@ #define RDMA_REG_UPDATE_INT BIT(0) #define DISP_REG_RDMA_GLOBAL_CON 0x0010 #define RDMA_ENGINE_EN BIT(0) +#define RDMA_MODE_MEMORY BIT(1) #define DISP_REG_RDMA_SIZE_CON_0 0x0014 #define DISP_REG_RDMA_SIZE_CON_1 0x0018 #define DISP_REG_RDMA_TARGET_LINE 0x001c +#define DISP_RDMA_MEM_SRC_PITCH 0x002c +#define DISP_RDMA_MEM_GMC_SETTING_0 0x0030 #define DISP_REG_RDMA_FIFO_CON 0x0040 #define RDMA_FIFO_UNDERFLOW_EN BIT(31) #define RDMA_FIFO_PSEUDO_SIZE(bytes) (((bytes) / 16) << 16) #define RDMA_OUTPUT_VALID_FIFO_THRESHOLD(bytes) ((bytes) / 16) #define RDMA_FIFO_SIZE(rdma) ((rdma)->data->fifo_size) +#define DISP_RDMA_MEM_START_ADDR 0x0f00 + +#define RDMA_MEM_GMC 0x40402020 struct mtk_disp_rdma_data { unsigned int fifo_size; @@ -138,12 +144,27 @@ static void mtk_rdma_config(struct mtk_ddp_comp *comp, unsigned int width, writel(reg, comp->regs + DISP_REG_RDMA_FIFO_CON); } +static void mtk_rdma_layer_config(struct mtk_ddp_comp *comp, unsigned int idx, + struct mtk_plane_state *state) +{ + struct mtk_plane_pending_state *pending = &state->pending; + unsigned int addr = pending->addr; + unsigned int pitch = pending->pitch & 0xffff; + + writel_relaxed(addr, comp->regs + DISP_RDMA_MEM_START_ADDR); + writel_relaxed(pitch, comp->regs + DISP_RDMA_MEM_SRC_PITCH); + writel(RDMA_MEM_GMC, comp->regs + DISP_RDMA_MEM_GMC_SETTING_0); + rdma_update_bits(comp, DISP_REG_RDMA_GLOBAL_CON, + RDMA_MODE_MEMORY, RDMA_MODE_MEMORY); +} + static const struct mtk_ddp_comp_funcs mtk_disp_rdma_funcs = { .config = mtk_rdma_config, .start = mtk_rdma_start, .stop = mtk_rdma_stop, .enable_vblank = mtk_rdma_enable_vblank, .disable_vblank = mtk_rdma_disable_vblank, + .layer_config = mtk_rdma_layer_config, }; static int mtk_disp_rdma_bind(struct device *dev, struct device *master, From b428391ed6bd5e3cb8ea9d1738ef4bd16af6cdb2 Mon Sep 17 00:00:00 2001 From: Stu Hsieh Date: Thu, 9 Aug 2018 10:15:41 +0800 Subject: [PATCH 129/302] drm/mediatek: add RGB color format support for RDMA This patch add RGB color format support for RDMA, including RGB565, RGB888, RGBA8888 and ARGB8888. Signed-off-by: Stu Hsieh Signed-off-by: CK Hu --- drivers/gpu/drm/mediatek/mtk_disp_rdma.c | 45 ++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/drivers/gpu/drm/mediatek/mtk_disp_rdma.c b/drivers/gpu/drm/mediatek/mtk_disp_rdma.c index 08866550740f..091e48e51501 100644 --- a/drivers/gpu/drm/mediatek/mtk_disp_rdma.c +++ b/drivers/gpu/drm/mediatek/mtk_disp_rdma.c @@ -35,6 +35,12 @@ #define DISP_REG_RDMA_SIZE_CON_0 0x0014 #define DISP_REG_RDMA_SIZE_CON_1 0x0018 #define DISP_REG_RDMA_TARGET_LINE 0x001c +#define DISP_RDMA_MEM_CON 0x0024 +#define MEM_MODE_INPUT_FORMAT_RGB565 (0x000 << 4) +#define MEM_MODE_INPUT_FORMAT_RGB888 (0x001 << 4) +#define MEM_MODE_INPUT_FORMAT_RGBA8888 (0x002 << 4) +#define MEM_MODE_INPUT_FORMAT_ARGB8888 (0x003 << 4) +#define MEM_MODE_INPUT_SWAP BIT(8) #define DISP_RDMA_MEM_SRC_PITCH 0x002c #define DISP_RDMA_MEM_GMC_SETTING_0 0x0030 #define DISP_REG_RDMA_FIFO_CON 0x0040 @@ -144,12 +150,51 @@ static void mtk_rdma_config(struct mtk_ddp_comp *comp, unsigned int width, writel(reg, comp->regs + DISP_REG_RDMA_FIFO_CON); } +static unsigned int rdma_fmt_convert(struct mtk_disp_rdma *rdma, + unsigned int fmt) +{ + /* The return value in switch "MEM_MODE_INPUT_FORMAT_XXX" + * is defined in mediatek HW data sheet. + * The alphabet order in XXX is no relation to data + * arrangement in memory. + */ + switch (fmt) { + default: + case DRM_FORMAT_RGB565: + return MEM_MODE_INPUT_FORMAT_RGB565; + case DRM_FORMAT_BGR565: + return MEM_MODE_INPUT_FORMAT_RGB565 | MEM_MODE_INPUT_SWAP; + case DRM_FORMAT_RGB888: + return MEM_MODE_INPUT_FORMAT_RGB888; + case DRM_FORMAT_BGR888: + return MEM_MODE_INPUT_FORMAT_RGB888 | MEM_MODE_INPUT_SWAP; + case DRM_FORMAT_RGBX8888: + case DRM_FORMAT_RGBA8888: + return MEM_MODE_INPUT_FORMAT_ARGB8888; + case DRM_FORMAT_BGRX8888: + case DRM_FORMAT_BGRA8888: + return MEM_MODE_INPUT_FORMAT_ARGB8888 | MEM_MODE_INPUT_SWAP; + case DRM_FORMAT_XRGB8888: + case DRM_FORMAT_ARGB8888: + return MEM_MODE_INPUT_FORMAT_RGBA8888; + case DRM_FORMAT_XBGR8888: + case DRM_FORMAT_ABGR8888: + return MEM_MODE_INPUT_FORMAT_RGBA8888 | MEM_MODE_INPUT_SWAP; + } +} + static void mtk_rdma_layer_config(struct mtk_ddp_comp *comp, unsigned int idx, struct mtk_plane_state *state) { + struct mtk_disp_rdma *rdma = comp_to_rdma(comp); struct mtk_plane_pending_state *pending = &state->pending; unsigned int addr = pending->addr; unsigned int pitch = pending->pitch & 0xffff; + unsigned int fmt = pending->format; + unsigned int con; + + con = rdma_fmt_convert(rdma, fmt); + writel_relaxed(con, comp->regs + DISP_RDMA_MEM_CON); writel_relaxed(addr, comp->regs + DISP_RDMA_MEM_START_ADDR); writel_relaxed(pitch, comp->regs + DISP_RDMA_MEM_SRC_PITCH); From 55b53f6f7ccf0990ad83acf4fdb0436ff79fdfb6 Mon Sep 17 00:00:00 2001 From: Stu Hsieh Date: Thu, 9 Aug 2018 10:15:42 +0800 Subject: [PATCH 130/302] drm/mediatek: add the comment about color format setting for OVL This patch add the comment about color format setting for OVL Signed-off-by: Stu Hsieh Signed-off-by: CK Hu --- drivers/gpu/drm/mediatek/mtk_disp_ovl.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c index 978782a77629..0facd823c552 100644 --- a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c +++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c @@ -157,6 +157,11 @@ static void mtk_ovl_layer_off(struct mtk_ddp_comp *comp, unsigned int idx) static unsigned int ovl_fmt_convert(struct mtk_disp_ovl *ovl, unsigned int fmt) { + /* The return value in switch "MEM_MODE_INPUT_FORMAT_XXX" + * is defined in mediatek HW data sheet. + * The alphabet order in XXX is no relation to data + * arrangement in memory. + */ switch (fmt) { default: case DRM_FORMAT_RGB565: From 94420a63cf784945061b7b5f38511b7a48f034eb Mon Sep 17 00:00:00 2001 From: Stu Hsieh Date: Thu, 9 Aug 2018 10:15:43 +0800 Subject: [PATCH 131/302] drm/mediatek: add YUYV/UYVY color format support for RDMA This patch add YUYV/UYVY color format support for RDMA and transform matrix for YUYV/UYVY. Signed-off-by: Stu Hsieh Signed-off-by: CK Hu --- drivers/gpu/drm/mediatek/mtk_disp_rdma.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/drivers/gpu/drm/mediatek/mtk_disp_rdma.c b/drivers/gpu/drm/mediatek/mtk_disp_rdma.c index 091e48e51501..2d27e15445d2 100644 --- a/drivers/gpu/drm/mediatek/mtk_disp_rdma.c +++ b/drivers/gpu/drm/mediatek/mtk_disp_rdma.c @@ -33,6 +33,9 @@ #define RDMA_ENGINE_EN BIT(0) #define RDMA_MODE_MEMORY BIT(1) #define DISP_REG_RDMA_SIZE_CON_0 0x0014 +#define RDMA_MATRIX_ENABLE BIT(17) +#define RDMA_MATRIX_INT_MTX_SEL GENMASK(23, 20) +#define RDMA_MATRIX_INT_MTX_BT601_to_RGB (6 << 20) #define DISP_REG_RDMA_SIZE_CON_1 0x0018 #define DISP_REG_RDMA_TARGET_LINE 0x001c #define DISP_RDMA_MEM_CON 0x0024 @@ -40,6 +43,8 @@ #define MEM_MODE_INPUT_FORMAT_RGB888 (0x001 << 4) #define MEM_MODE_INPUT_FORMAT_RGBA8888 (0x002 << 4) #define MEM_MODE_INPUT_FORMAT_ARGB8888 (0x003 << 4) +#define MEM_MODE_INPUT_FORMAT_UYVY (0x004 << 4) +#define MEM_MODE_INPUT_FORMAT_YUYV (0x005 << 4) #define MEM_MODE_INPUT_SWAP BIT(8) #define DISP_RDMA_MEM_SRC_PITCH 0x002c #define DISP_RDMA_MEM_GMC_SETTING_0 0x0030 @@ -180,6 +185,10 @@ static unsigned int rdma_fmt_convert(struct mtk_disp_rdma *rdma, case DRM_FORMAT_XBGR8888: case DRM_FORMAT_ABGR8888: return MEM_MODE_INPUT_FORMAT_RGBA8888 | MEM_MODE_INPUT_SWAP; + case DRM_FORMAT_UYVY: + return MEM_MODE_INPUT_FORMAT_UYVY; + case DRM_FORMAT_YUYV: + return MEM_MODE_INPUT_FORMAT_YUYV; } } @@ -196,6 +205,17 @@ static void mtk_rdma_layer_config(struct mtk_ddp_comp *comp, unsigned int idx, con = rdma_fmt_convert(rdma, fmt); writel_relaxed(con, comp->regs + DISP_RDMA_MEM_CON); + if (fmt == DRM_FORMAT_UYVY || fmt == DRM_FORMAT_YUYV) { + rdma_update_bits(comp, DISP_REG_RDMA_SIZE_CON_0, + RDMA_MATRIX_ENABLE, RDMA_MATRIX_ENABLE); + rdma_update_bits(comp, DISP_REG_RDMA_SIZE_CON_0, + RDMA_MATRIX_INT_MTX_SEL, + RDMA_MATRIX_INT_MTX_BT601_to_RGB); + } else { + rdma_update_bits(comp, DISP_REG_RDMA_SIZE_CON_0, + RDMA_MATRIX_ENABLE, 0); + } + writel_relaxed(addr, comp->regs + DISP_RDMA_MEM_START_ADDR); writel_relaxed(pitch, comp->regs + DISP_RDMA_MEM_SRC_PITCH); writel(RDMA_MEM_GMC, comp->regs + DISP_RDMA_MEM_GMC_SETTING_0); From 650afd49572b56a5c58134d4acfeb77acc69d622 Mon Sep 17 00:00:00 2001 From: Stu Hsieh Date: Thu, 9 Aug 2018 10:15:44 +0800 Subject: [PATCH 132/302] drm/mediatek: add function to get layer number for component This patch add function to get layer number for component Signed-off-by: Stu Hsieh Signed-off-by: CK Hu --- drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h index 7413ffeb3c9d..8399229e6ad2 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h +++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h @@ -78,6 +78,7 @@ struct mtk_ddp_comp_funcs { void (*stop)(struct mtk_ddp_comp *comp); void (*enable_vblank)(struct mtk_ddp_comp *comp, struct drm_crtc *crtc); void (*disable_vblank)(struct mtk_ddp_comp *comp); + unsigned int (*layer_nr)(struct mtk_ddp_comp *comp); void (*layer_on)(struct mtk_ddp_comp *comp, unsigned int idx); void (*layer_off)(struct mtk_ddp_comp *comp, unsigned int idx); void (*layer_config)(struct mtk_ddp_comp *comp, unsigned int idx, @@ -128,6 +129,14 @@ static inline void mtk_ddp_comp_disable_vblank(struct mtk_ddp_comp *comp) comp->funcs->disable_vblank(comp); } +static inline unsigned int mtk_ddp_comp_layer_nr(struct mtk_ddp_comp *comp) +{ + if (comp->funcs && comp->funcs->layer_nr) + return comp->funcs->layer_nr(comp); + + return 0; +} + static inline void mtk_ddp_comp_layer_on(struct mtk_ddp_comp *comp, unsigned int idx) { From 1cbcb763ea5035e7ef01010ea68eb3b5143ad7cb Mon Sep 17 00:00:00 2001 From: Stu Hsieh Date: Thu, 9 Aug 2018 10:15:45 +0800 Subject: [PATCH 133/302] drm/mediatek: add function to return OVL layer number This patch add function to return OVL layer number For now, MT8173, MT2712, MT2701 OVL all has 4 layer. Signed-off-by: Stu Hsieh Signed-off-by: CK Hu --- drivers/gpu/drm/mediatek/mtk_disp_ovl.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c index 0facd823c552..28d191192945 100644 --- a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c +++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c @@ -132,6 +132,11 @@ static void mtk_ovl_config(struct mtk_ddp_comp *comp, unsigned int w, writel(0x0, comp->regs + DISP_REG_OVL_RST); } +static unsigned int mtk_ovl_layer_nr(struct mtk_ddp_comp *comp) +{ + return 4; +} + static void mtk_ovl_layer_on(struct mtk_ddp_comp *comp, unsigned int idx) { unsigned int reg; @@ -226,6 +231,7 @@ static const struct mtk_ddp_comp_funcs mtk_disp_ovl_funcs = { .stop = mtk_ovl_stop, .enable_vblank = mtk_ovl_enable_vblank, .disable_vblank = mtk_ovl_disable_vblank, + .layer_nr = mtk_ovl_layer_nr, .layer_on = mtk_ovl_layer_on, .layer_off = mtk_ovl_layer_off, .layer_config = mtk_ovl_layer_config, From 98b6d76f957ba80017a3118fe0e33030b4bc017b Mon Sep 17 00:00:00 2001 From: Stu Hsieh Date: Thu, 9 Aug 2018 10:15:46 +0800 Subject: [PATCH 134/302] drm/mediatek: add function to return RDMA layer number This patch add function to return RDMA layer number RDMA always has one layer. Signed-off-by: Stu Hsieh Signed-off-by: CK Hu --- drivers/gpu/drm/mediatek/mtk_disp_rdma.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/gpu/drm/mediatek/mtk_disp_rdma.c b/drivers/gpu/drm/mediatek/mtk_disp_rdma.c index 2d27e15445d2..b0a5cffe345a 100644 --- a/drivers/gpu/drm/mediatek/mtk_disp_rdma.c +++ b/drivers/gpu/drm/mediatek/mtk_disp_rdma.c @@ -192,6 +192,11 @@ static unsigned int rdma_fmt_convert(struct mtk_disp_rdma *rdma, } } +static unsigned int mtk_rdma_layer_nr(struct mtk_ddp_comp *comp) +{ + return 1; +} + static void mtk_rdma_layer_config(struct mtk_ddp_comp *comp, unsigned int idx, struct mtk_plane_state *state) { @@ -229,6 +234,7 @@ static const struct mtk_ddp_comp_funcs mtk_disp_rdma_funcs = { .stop = mtk_rdma_stop, .enable_vblank = mtk_rdma_enable_vblank, .disable_vblank = mtk_rdma_disable_vblank, + .layer_nr = mtk_rdma_layer_nr, .layer_config = mtk_rdma_layer_config, }; From 66b2cf9623facfad790b335fcfd717258a00896b Mon Sep 17 00:00:00 2001 From: Stu Hsieh Date: Thu, 9 Aug 2018 10:15:47 +0800 Subject: [PATCH 135/302] drm/mediatek: use layer_nr function to get layer number to init plane This patch use layer_nr function to get layer number to init plane When plane init in crtc create, it use the number of OVL layer to init plane. That's OVL can read 4 memory address. For mt2712 third ddp, it use RDMA to read memory. RDMA can read 1 memory address, so it just init one plane. For compatibility, this patch use mtk_ddp_comp_layer_nr function to get layer number from their HW component in ddp for plane init. Signed-off-by: Stu Hsieh Signed-off-by: CK Hu --- drivers/gpu/drm/mediatek/mtk_drm_crtc.c | 21 ++++++++++++++------- drivers/gpu/drm/mediatek/mtk_drm_crtc.h | 1 - 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c index 2d6aa150a9ff..845d1608465e 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c @@ -45,7 +45,8 @@ struct mtk_drm_crtc { bool pending_needs_vblank; struct drm_pending_vblank_event *event; - struct drm_plane planes[OVL_LAYER_NR]; + struct drm_plane *planes; + unsigned int layer_nr; bool pending_planes; void __iomem *config_regs; @@ -286,7 +287,7 @@ static int mtk_crtc_ddp_hw_init(struct mtk_drm_crtc *mtk_crtc) } /* Initially configure all planes */ - for (i = 0; i < OVL_LAYER_NR; i++) { + for (i = 0; i < mtk_crtc->layer_nr; i++) { struct drm_plane *plane = &mtk_crtc->planes[i]; struct mtk_plane_state *plane_state; @@ -351,7 +352,7 @@ static void mtk_crtc_ddp_config(struct drm_crtc *crtc) } if (mtk_crtc->pending_planes) { - for (i = 0; i < OVL_LAYER_NR; i++) { + for (i = 0; i < mtk_crtc->layer_nr; i++) { struct drm_plane *plane = &mtk_crtc->planes[i]; struct mtk_plane_state *plane_state; @@ -403,7 +404,7 @@ static void mtk_drm_crtc_atomic_disable(struct drm_crtc *crtc, return; /* Set all pending plane state to disabled */ - for (i = 0; i < OVL_LAYER_NR; i++) { + for (i = 0; i < mtk_crtc->layer_nr; i++) { struct drm_plane *plane = &mtk_crtc->planes[i]; struct mtk_plane_state *plane_state; @@ -450,7 +451,7 @@ static void mtk_drm_crtc_atomic_flush(struct drm_crtc *crtc, if (mtk_crtc->event) mtk_crtc->pending_needs_vblank = true; - for (i = 0; i < OVL_LAYER_NR; i++) { + for (i = 0; i < mtk_crtc->layer_nr; i++) { struct drm_plane *plane = &mtk_crtc->planes[i]; struct mtk_plane_state *plane_state; @@ -598,7 +599,12 @@ int mtk_drm_crtc_create(struct drm_device *drm_dev, mtk_crtc->ddp_comp[i] = comp; } - for (zpos = 0; zpos < OVL_LAYER_NR; zpos++) { + mtk_crtc->layer_nr = mtk_ddp_comp_layer_nr(mtk_crtc->ddp_comp[0]); + mtk_crtc->planes = devm_kzalloc(dev, mtk_crtc->layer_nr * + sizeof(struct drm_plane), + GFP_KERNEL); + + for (zpos = 0; zpos < mtk_crtc->layer_nr; zpos++) { type = (zpos == 0) ? DRM_PLANE_TYPE_PRIMARY : (zpos == 1) ? DRM_PLANE_TYPE_CURSOR : DRM_PLANE_TYPE_OVERLAY; @@ -609,7 +615,8 @@ int mtk_drm_crtc_create(struct drm_device *drm_dev, } ret = mtk_drm_crtc_init(drm_dev, mtk_crtc, &mtk_crtc->planes[0], - &mtk_crtc->planes[1], pipe); + mtk_crtc->layer_nr > 1 ? &mtk_crtc->planes[1] : + NULL, pipe); if (ret < 0) goto unprepare; drm_mode_crtc_set_gamma_size(&mtk_crtc->base, MTK_LUT_SIZE); diff --git a/drivers/gpu/drm/mediatek/mtk_drm_crtc.h b/drivers/gpu/drm/mediatek/mtk_drm_crtc.h index 9d9410c67ae9..60bcc8aba8e3 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_crtc.h +++ b/drivers/gpu/drm/mediatek/mtk_drm_crtc.h @@ -18,7 +18,6 @@ #include "mtk_drm_ddp_comp.h" #include "mtk_drm_plane.h" -#define OVL_LAYER_NR 4 #define MTK_LUT_SIZE 512 #define MTK_MAX_BPC 10 #define MTK_MIN_BPC 3 From f265905c939e21a0c9e83540d4c2776c3e43c310 Mon Sep 17 00:00:00 2001 From: Stu Hsieh Date: Thu, 9 Aug 2018 10:15:48 +0800 Subject: [PATCH 136/302] drm/mediatek: update some variable name from ovl to comp This patch update some variable name from ovl to comp Because RDMA would be first HW in ddp, the naming ovl should be change to comp. Signed-off-by: Stu Hsieh Signed-off-by: CK Hu --- drivers/gpu/drm/mediatek/mtk_drm_crtc.c | 26 ++++++++++++------------- drivers/gpu/drm/mediatek/mtk_drm_crtc.h | 2 +- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c index 845d1608465e..0b976dfd04df 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c @@ -172,9 +172,9 @@ static void mtk_drm_crtc_mode_set_nofb(struct drm_crtc *crtc) static int mtk_drm_crtc_enable_vblank(struct drm_crtc *crtc) { struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc); - struct mtk_ddp_comp *ovl = mtk_crtc->ddp_comp[0]; + struct mtk_ddp_comp *comp = mtk_crtc->ddp_comp[0]; - mtk_ddp_comp_enable_vblank(ovl, &mtk_crtc->base); + mtk_ddp_comp_enable_vblank(comp, &mtk_crtc->base); return 0; } @@ -182,9 +182,9 @@ static int mtk_drm_crtc_enable_vblank(struct drm_crtc *crtc) static void mtk_drm_crtc_disable_vblank(struct drm_crtc *crtc) { struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc); - struct mtk_ddp_comp *ovl = mtk_crtc->ddp_comp[0]; + struct mtk_ddp_comp *comp = mtk_crtc->ddp_comp[0]; - mtk_ddp_comp_disable_vblank(ovl); + mtk_ddp_comp_disable_vblank(comp); } static int mtk_crtc_ddp_clk_enable(struct mtk_drm_crtc *mtk_crtc) @@ -335,7 +335,7 @@ static void mtk_crtc_ddp_config(struct drm_crtc *crtc) { struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc); struct mtk_crtc_state *state = to_mtk_crtc_state(mtk_crtc->base.state); - struct mtk_ddp_comp *ovl = mtk_crtc->ddp_comp[0]; + struct mtk_ddp_comp *comp = mtk_crtc->ddp_comp[0]; unsigned int i; /* @@ -344,7 +344,7 @@ static void mtk_crtc_ddp_config(struct drm_crtc *crtc) * queue update module registers on vblank. */ if (state->pending_config) { - mtk_ddp_comp_config(ovl, state->pending_width, + mtk_ddp_comp_config(comp, state->pending_width, state->pending_height, state->pending_vrefresh, 0); @@ -359,7 +359,7 @@ static void mtk_crtc_ddp_config(struct drm_crtc *crtc) plane_state = to_mtk_plane_state(plane->state); if (plane_state->pending.config) { - mtk_ddp_comp_layer_config(ovl, i, plane_state); + mtk_ddp_comp_layer_config(comp, i, plane_state); plane_state->pending.config = false; } } @@ -371,12 +371,12 @@ static void mtk_drm_crtc_atomic_enable(struct drm_crtc *crtc, struct drm_crtc_state *old_state) { struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc); - struct mtk_ddp_comp *ovl = mtk_crtc->ddp_comp[0]; + struct mtk_ddp_comp *comp = mtk_crtc->ddp_comp[0]; int ret; DRM_DEBUG_DRIVER("%s %d\n", __func__, crtc->base.id); - ret = mtk_smi_larb_get(ovl->larb_dev); + ret = mtk_smi_larb_get(comp->larb_dev); if (ret) { DRM_ERROR("Failed to get larb: %d\n", ret); return; @@ -384,7 +384,7 @@ static void mtk_drm_crtc_atomic_enable(struct drm_crtc *crtc, ret = mtk_crtc_ddp_hw_init(mtk_crtc); if (ret) { - mtk_smi_larb_put(ovl->larb_dev); + mtk_smi_larb_put(comp->larb_dev); return; } @@ -396,7 +396,7 @@ static void mtk_drm_crtc_atomic_disable(struct drm_crtc *crtc, struct drm_crtc_state *old_state) { struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc); - struct mtk_ddp_comp *ovl = mtk_crtc->ddp_comp[0]; + struct mtk_ddp_comp *comp = mtk_crtc->ddp_comp[0]; int i; DRM_DEBUG_DRIVER("%s %d\n", __func__, crtc->base.id); @@ -419,7 +419,7 @@ static void mtk_drm_crtc_atomic_disable(struct drm_crtc *crtc, drm_crtc_vblank_off(crtc); mtk_crtc_ddp_hw_fini(mtk_crtc); - mtk_smi_larb_put(ovl->larb_dev); + mtk_smi_larb_put(comp->larb_dev); mtk_crtc->enabled = false; } @@ -517,7 +517,7 @@ static int mtk_drm_crtc_init(struct drm_device *drm, return ret; } -void mtk_crtc_ddp_irq(struct drm_crtc *crtc, struct mtk_ddp_comp *ovl) +void mtk_crtc_ddp_irq(struct drm_crtc *crtc, struct mtk_ddp_comp *comp) { struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc); struct mtk_drm_private *priv = crtc->dev->dev_private; diff --git a/drivers/gpu/drm/mediatek/mtk_drm_crtc.h b/drivers/gpu/drm/mediatek/mtk_drm_crtc.h index 60bcc8aba8e3..091adb2087eb 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_crtc.h +++ b/drivers/gpu/drm/mediatek/mtk_drm_crtc.h @@ -23,7 +23,7 @@ #define MTK_MIN_BPC 3 void mtk_drm_crtc_commit(struct drm_crtc *crtc); -void mtk_crtc_ddp_irq(struct drm_crtc *crtc, struct mtk_ddp_comp *ovl); +void mtk_crtc_ddp_irq(struct drm_crtc *crtc, struct mtk_ddp_comp *comp); int mtk_drm_crtc_create(struct drm_device *drm_dev, const enum mtk_ddp_comp_id *path, unsigned int path_len); From 08bcbed747eb87f00d2e2590b49607af1a9f4fe9 Mon Sep 17 00:00:00 2001 From: Stu Hsieh Date: Thu, 9 Aug 2018 10:15:49 +0800 Subject: [PATCH 137/302] drm/mediatek: fix connection from RDMA2 to DSI1 This patch fix connection from RDMA2 to DSI1 Signed-off-by: Stu Hsieh Signed-off-by: CK Hu --- drivers/gpu/drm/mediatek/mtk_drm_ddp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp.c b/drivers/gpu/drm/mediatek/mtk_drm_ddp.c index 3239f22785fd..546b3e3b300b 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_ddp.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp.c @@ -314,7 +314,7 @@ static unsigned int mtk_ddp_sel_in(enum mtk_ddp_comp_id cur, *addr = DISP_REG_CONFIG_DSIE_SEL_IN; value = DSI0_SEL_IN_RDMA2; } else if (cur == DDP_COMPONENT_RDMA2 && next == DDP_COMPONENT_DSI1) { - *addr = DISP_REG_CONFIG_DSIE_SEL_IN; + *addr = DISP_REG_CONFIG_DSIO_SEL_IN; value = DSI1_SEL_IN_RDMA2; } else if (cur == DDP_COMPONENT_RDMA2 && next == DDP_COMPONENT_DSI2) { *addr = DISP_REG_CONFIG_DSIE_SEL_IN; From 538d6e9d597584e80514698e24321645debde78f Mon Sep 17 00:00:00 2001 From: Leonard Crestez Date: Tue, 24 Jul 2018 19:14:19 +0300 Subject: [PATCH 138/302] Revert "ARM: dts: imx7d: Invert legacy PCI irq mapping" This reverts commit 1c86c9dd82f859b474474a7fee0d5195da2c9c1d. That commit followed the reference manual but unfortunately the imx7d manual is incorrect. Tested with ath9k pcie card and confirmed internally. Signed-off-by: Leonard Crestez Acked-by: Lucas Stach Fixes: 1c86c9dd82f8 ("ARM: dts: imx7d: Invert legacy PCI irq mapping") Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx7d.dtsi | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/arch/arm/boot/dts/imx7d.dtsi b/arch/arm/boot/dts/imx7d.dtsi index 7cbc2ffa4b3a..7234e8330a57 100644 --- a/arch/arm/boot/dts/imx7d.dtsi +++ b/arch/arm/boot/dts/imx7d.dtsi @@ -126,10 +126,14 @@ pcie: pcie@33800000 { interrupt-names = "msi"; #interrupt-cells = <1>; interrupt-map-mask = <0 0 0 0x7>; - interrupt-map = <0 0 0 1 &intc GIC_SPI 122 IRQ_TYPE_LEVEL_HIGH>, - <0 0 0 2 &intc GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>, - <0 0 0 3 &intc GIC_SPI 124 IRQ_TYPE_LEVEL_HIGH>, - <0 0 0 4 &intc GIC_SPI 125 IRQ_TYPE_LEVEL_HIGH>; + /* + * Reference manual lists pci irqs incorrectly + * Real hardware ordering is same as imx6: D+MSI, C, B, A + */ + interrupt-map = <0 0 0 1 &intc GIC_SPI 125 IRQ_TYPE_LEVEL_HIGH>, + <0 0 0 2 &intc GIC_SPI 124 IRQ_TYPE_LEVEL_HIGH>, + <0 0 0 3 &intc GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>, + <0 0 0 4 &intc GIC_SPI 122 IRQ_TYPE_LEVEL_HIGH>; clocks = <&clks IMX7D_PCIE_CTRL_ROOT_CLK>, <&clks IMX7D_PLL_ENET_MAIN_100M_CLK>, <&clks IMX7D_PCIE_PHY_ROOT_CLK>; From 90a96087b5fa835790a54c588184adfc867dbc12 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Fri, 20 Jul 2018 17:39:16 -0300 Subject: [PATCH 139/302] ARM: dts: imx28-evk: Move regulators outside simple-bus It is recommended to place regulators outside simple-bus, so move them accordingly. Signed-off-by: Fabio Estevam Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx28-evk.dts | 135 +++++++++++++++----------------- 1 file changed, 61 insertions(+), 74 deletions(-) diff --git a/arch/arm/boot/dts/imx28-evk.dts b/arch/arm/boot/dts/imx28-evk.dts index 6b0ae667640f..210aee097b36 100644 --- a/arch/arm/boot/dts/imx28-evk.dts +++ b/arch/arm/boot/dts/imx28-evk.dts @@ -13,6 +13,67 @@ memory@40000000 { reg = <0x40000000 0x08000000>; }; + + reg_3p3v: regulator-3p3v { + compatible = "regulator-fixed"; + regulator-name = "3P3V"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + + reg_vddio_sd0: regulator-vddio-sd0 { + compatible = "regulator-fixed"; + regulator-name = "vddio-sd0"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + gpio = <&gpio3 28 0>; + }; + + reg_fec_3v3: regulator-fec-3v3 { + compatible = "regulator-fixed"; + regulator-name = "fec-3v3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + gpio = <&gpio2 15 0>; + }; + + reg_usb0_vbus: regulator-usb0-vbus { + compatible = "regulator-fixed"; + regulator-name = "usb0_vbus"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + gpio = <&gpio3 9 0>; + enable-active-high; + }; + + reg_usb1_vbus: regulator-usb1-vbus { + compatible = "regulator-fixed"; + regulator-name = "usb1_vbus"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + gpio = <&gpio3 8 0>; + enable-active-high; + }; + + reg_lcd_3v3: regulator-lcd-3v3 { + compatible = "regulator-fixed"; + regulator-name = "lcd-3v3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + gpio = <&gpio3 30 0>; + enable-active-high; + }; + + reg_can_3v3: regulator-can-3v3 { + compatible = "regulator-fixed"; + regulator-name = "can-3v3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + gpio = <&gpio2 13 0>; + enable-active-high; + }; + apb@80000000 { apbh@80000000 { gpmi-nand@8000c000 { @@ -269,80 +330,6 @@ mac1: ethernet@800f4000 { }; }; - regulators { - compatible = "simple-bus"; - #address-cells = <1>; - #size-cells = <0>; - - reg_3p3v: regulator@0 { - compatible = "regulator-fixed"; - reg = <0>; - regulator-name = "3P3V"; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - regulator-always-on; - }; - - reg_vddio_sd0: regulator@1 { - compatible = "regulator-fixed"; - reg = <1>; - regulator-name = "vddio-sd0"; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - gpio = <&gpio3 28 0>; - }; - - reg_fec_3v3: regulator@2 { - compatible = "regulator-fixed"; - reg = <2>; - regulator-name = "fec-3v3"; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - gpio = <&gpio2 15 0>; - }; - - reg_usb0_vbus: regulator@3 { - compatible = "regulator-fixed"; - reg = <3>; - regulator-name = "usb0_vbus"; - regulator-min-microvolt = <5000000>; - regulator-max-microvolt = <5000000>; - gpio = <&gpio3 9 0>; - enable-active-high; - }; - - reg_usb1_vbus: regulator@4 { - compatible = "regulator-fixed"; - reg = <4>; - regulator-name = "usb1_vbus"; - regulator-min-microvolt = <5000000>; - regulator-max-microvolt = <5000000>; - gpio = <&gpio3 8 0>; - enable-active-high; - }; - - reg_lcd_3v3: regulator@5 { - compatible = "regulator-fixed"; - reg = <5>; - regulator-name = "lcd-3v3"; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - gpio = <&gpio3 30 0>; - enable-active-high; - }; - - reg_can_3v3: regulator@6 { - compatible = "regulator-fixed"; - reg = <6>; - regulator-name = "can-3v3"; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - gpio = <&gpio2 13 0>; - enable-active-high; - }; - - }; - sound { compatible = "fsl,imx28-evk-sgtl5000", "fsl,mxs-audio-sgtl5000"; From c1539840fc25d89f3fe51038144dc0233b333453 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Fri, 20 Jul 2018 17:39:17 -0300 Subject: [PATCH 140/302] ARM: dts: imx28-evk: Convert to the new display bindings imx28-evk board has a Seiko 43WVF1G parallel display. Instead of hardcoding the display timings in the device tree, use the "sii,43wvf1g" compatible instead. This aligns with the new mxsfb bindings scheme documented at: Documentation/devicetree/bindings/display/mxsfb.txt Signed-off-by: Fabio Estevam Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx28-evk.dts | 48 ++++++++++++++++----------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/arch/arm/boot/dts/imx28-evk.dts b/arch/arm/boot/dts/imx28-evk.dts index 210aee097b36..93ab5bdfe068 100644 --- a/arch/arm/boot/dts/imx28-evk.dts +++ b/arch/arm/boot/dts/imx28-evk.dts @@ -74,6 +74,26 @@ reg_can_3v3: regulator-can-3v3 { enable-active-high; }; + reg_lcd_5v: regulator-lcd-5v { + compatible = "regulator-fixed"; + regulator-name = "lcd-5v"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + }; + + panel { + compatible = "sii,43wvf1g"; + backlight = <&backlight_display>; + dvdd-supply = <®_lcd_3v3>; + avdd-supply = <®_lcd_5v>; + + port { + panel_in: endpoint { + remote-endpoint = <&display_out>; + }; + }; + }; + apb@80000000 { apbh@80000000 { gpmi-nand@8000c000 { @@ -177,31 +197,11 @@ lcdif@80030000 { pinctrl-names = "default"; pinctrl-0 = <&lcdif_24bit_pins_a &lcdif_pins_evk>; - lcd-supply = <®_lcd_3v3>; - display = <&display0>; status = "okay"; - display0: display0 { - bits-per-pixel = <32>; - bus-width = <24>; - - display-timings { - native-mode = <&timing0>; - timing0: timing0 { - clock-frequency = <33500000>; - hactive = <800>; - vactive = <480>; - hback-porch = <89>; - hfront-porch = <164>; - vback-porch = <23>; - vfront-porch = <10>; - hsync-len = <10>; - vsync-len = <10>; - hsync-active = <0>; - vsync-active = <0>; - de-active = <1>; - pixelclk-active = <0>; - }; + port { + display_out: endpoint { + remote-endpoint = <&panel_in>; }; }; }; @@ -350,7 +350,7 @@ user { }; }; - backlight { + backlight_display: backlight { compatible = "pwm-backlight"; pwms = <&pwm 2 5000000>; brightness-levels = <0 4 8 16 32 64 128 255>; From cde305e9ce28d96d7f63e4fb5298291e90a91f8f Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Fri, 20 Jul 2018 17:39:18 -0300 Subject: [PATCH 141/302] ARM: dts: imx23-evk: Move regulators outside simple-bus It is recommended to place regulators outside simple-bus, so move them accordingly. Signed-off-by: Fabio Estevam Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx23-evk.dts | 42 +++++++++++++-------------------- 1 file changed, 17 insertions(+), 25 deletions(-) diff --git a/arch/arm/boot/dts/imx23-evk.dts b/arch/arm/boot/dts/imx23-evk.dts index 9fb47724b9c1..494095d40327 100644 --- a/arch/arm/boot/dts/imx23-evk.dts +++ b/arch/arm/boot/dts/imx23-evk.dts @@ -13,6 +13,23 @@ memory@40000000 { reg = <0x40000000 0x08000000>; }; + reg_vddio_sd0: regulator-vddio-sd0 { + compatible = "regulator-fixed"; + regulator-name = "vddio-sd0"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + gpio = <&gpio1 29 0>; + }; + + reg_lcd_3v3: regulator-lcd-3v3 { + compatible = "regulator-fixed"; + regulator-name = "lcd-3v3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + gpio = <&gpio1 18 0>; + enable-active-high; + }; + apb@80000000 { apbh@80000000 { gpmi-nand@8000c000 { @@ -118,31 +135,6 @@ usb0: usb@80080000 { }; }; - regulators { - compatible = "simple-bus"; - #address-cells = <1>; - #size-cells = <0>; - - reg_vddio_sd0: regulator@0 { - compatible = "regulator-fixed"; - reg = <0>; - regulator-name = "vddio-sd0"; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - gpio = <&gpio1 29 0>; - }; - - reg_lcd_3v3: regulator@1 { - compatible = "regulator-fixed"; - reg = <1>; - regulator-name = "lcd-3v3"; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - gpio = <&gpio1 18 0>; - enable-active-high; - }; - }; - backlight { compatible = "pwm-backlight"; pwms = <&pwm 2 5000000>; From 549644b8c3c125355a361def1e42f8319ac6ad6c Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Fri, 20 Jul 2018 17:39:19 -0300 Subject: [PATCH 142/302] ARM: dts: imx23-evk: Convert to the new display bindings imx23-evk board has a Seiko 43WVF1G parallel display. Instead of hardcoding the display timings in the device tree, use the "sii,43wvf1g" compatible instead. This aligns with the new mxsfb bindings scheme documented at: Documentation/devicetree/bindings/display/mxsfb.txt Signed-off-by: Fabio Estevam Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx23-evk.dts | 48 ++++++++++++++++----------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/arch/arm/boot/dts/imx23-evk.dts b/arch/arm/boot/dts/imx23-evk.dts index 494095d40327..ad2ae25b7b4d 100644 --- a/arch/arm/boot/dts/imx23-evk.dts +++ b/arch/arm/boot/dts/imx23-evk.dts @@ -30,6 +30,26 @@ reg_lcd_3v3: regulator-lcd-3v3 { enable-active-high; }; + reg_lcd_5v: regulator-lcd-5v { + compatible = "regulator-fixed"; + regulator-name = "lcd-5v"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + }; + + panel { + compatible = "sii,43wvf1g"; + backlight = <&backlight_display>; + dvdd-supply = <®_lcd_3v3>; + avdd-supply = <®_lcd_5v>; + + port { + panel_in: endpoint { + remote-endpoint = <&display_out>; + }; + }; + }; + apb@80000000 { apbh@80000000 { gpmi-nand@8000c000 { @@ -69,31 +89,11 @@ MX23_PAD_SSP1_DETECT__SSP1_DETECT lcdif@80030000 { pinctrl-names = "default"; pinctrl-0 = <&lcdif_24bit_pins_a>; - lcd-supply = <®_lcd_3v3>; - display = <&display0>; status = "okay"; - display0: display0 { - bits-per-pixel = <32>; - bus-width = <24>; - - display-timings { - native-mode = <&timing0>; - timing0: timing0 { - clock-frequency = <9200000>; - hactive = <480>; - vactive = <272>; - hback-porch = <15>; - hfront-porch = <8>; - vback-porch = <12>; - vfront-porch = <4>; - hsync-len = <1>; - vsync-len = <1>; - hsync-active = <0>; - vsync-active = <0>; - de-active = <1>; - pixelclk-active = <0>; - }; + port { + display_out: endpoint { + remote-endpoint = <&panel_in>; }; }; }; @@ -135,7 +135,7 @@ usb0: usb@80080000 { }; }; - backlight { + backlight_display: backlight { compatible = "pwm-backlight"; pwms = <&pwm 2 5000000>; brightness-levels = <0 4 8 16 32 64 128 255>; From 0ffbc2824282793a3ebf04d4804dea15d5b211c6 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Fri, 20 Jul 2018 17:39:20 -0300 Subject: [PATCH 143/302] ARM: mxs_defconfig: Select CONFIG_DRM_PANEL_SEIKO_43WVF1G imx23-evk and imx28-evk boards use a Seiko 43WVF1G panel. Now that the DRM mxsfb driver is the one selected by default, let's also select CONFIG_DRM_PANEL_SEIKO_43WVF1G so that these boards continue to have a working display by default. Signed-off-by: Fabio Estevam Signed-off-by: Shawn Guo --- arch/arm/configs/mxs_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/mxs_defconfig b/arch/arm/configs/mxs_defconfig index 148226e36152..7b8212857535 100644 --- a/arch/arm/configs/mxs_defconfig +++ b/arch/arm/configs/mxs_defconfig @@ -95,6 +95,7 @@ CONFIG_MFD_MXS_LRADC=y CONFIG_REGULATOR=y CONFIG_REGULATOR_FIXED_VOLTAGE=y CONFIG_DRM=y +CONFIG_DRM_PANEL_SEIKO_43WVF1G=y CONFIG_DRM_MXSFB=y CONFIG_FB_MODE_HELPERS=y CONFIG_BACKLIGHT_LCD_SUPPORT=y From b9543a2e39dc909e6b7ec901b6c7208d01d5c0dd Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Fri, 20 Jul 2018 17:39:21 -0300 Subject: [PATCH 144/302] ARM: imx_v6_v7_defconfig: Select CONFIG_DRM_PANEL_SEIKO_43WVF1G imx6sl-evk, imx6sll-evk and imx6sx-sdb boards use a Seiko 43WVF1G panel. Now that the DRM mxsfb driver is the one selected by default, let's also select CONFIG_DRM_PANEL_SEIKO_43WVF1G so that these boards continue to have a working display by default. Signed-off-by: Fabio Estevam Signed-off-by: Shawn Guo --- arch/arm/configs/imx_v6_v7_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/imx_v6_v7_defconfig b/arch/arm/configs/imx_v6_v7_defconfig index e2c127608bcc..7eca43ff69bb 100644 --- a/arch/arm/configs/imx_v6_v7_defconfig +++ b/arch/arm/configs/imx_v6_v7_defconfig @@ -257,6 +257,7 @@ CONFIG_IMX_IPUV3_CORE=y CONFIG_DRM=y CONFIG_DRM_PANEL_LVDS=y CONFIG_DRM_PANEL_SIMPLE=y +CONFIG_DRM_PANEL_SEIKO_43WVF1G=y CONFIG_DRM_DW_HDMI_AHB_AUDIO=m CONFIG_DRM_DW_HDMI_CEC=y CONFIG_DRM_IMX=y From 166cd4421b0dabd2e438f5384f4ecf930dc8ab08 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 23 Aug 2018 23:43:45 +0200 Subject: [PATCH 145/302] mtd: rawnand: docg4: Remove wrong __init annotations If gcc (e.g. 4.1.2) decides not to inline init_mtd_structs() and read_id_reg(), this will cause section mismatches, and crashes: WARNING: drivers/mtd/nand/raw/docg4.o(.text+0xc10): Section mismatch in reference from the function docg4_attach_chip() to the function .init.text:init_mtd_structs() The function docg4_attach_chip() references the function __init init_mtd_structs(). This is often because docg4_attach_chip lacks a __init annotation or the annotation of init_mtd_structs is wrong. WARNING: drivers/mtd/nand/raw/docg4.o(.text+0xc3e): Section mismatch in reference from the function docg4_attach_chip() to the function .init.text:read_id_reg() The function docg4_attach_chip() references the function __init read_id_reg(). This is often because docg4_attach_chip lacks a __init annotation or the annotation of read_id_reg is wrong. Fix this by dropping the now incorrect __init annotations from init_mtd_structs() and read_id_reg(). Fixes: 66a38478dcc5b5a3 ("mtd: rawnand: docg4: convert driver to nand_scan()") Signed-off-by: Geert Uytterhoeven Signed-off-by: Boris Brezillon --- drivers/mtd/nand/raw/docg4.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mtd/nand/raw/docg4.c b/drivers/mtd/nand/raw/docg4.c index a3f04315c05c..427fcbc1b71c 100644 --- a/drivers/mtd/nand/raw/docg4.c +++ b/drivers/mtd/nand/raw/docg4.c @@ -1218,7 +1218,7 @@ static int docg4_resume(struct platform_device *pdev) return 0; } -static void __init init_mtd_structs(struct mtd_info *mtd) +static void init_mtd_structs(struct mtd_info *mtd) { /* initialize mtd and nand data structures */ @@ -1290,7 +1290,7 @@ static void __init init_mtd_structs(struct mtd_info *mtd) } -static int __init read_id_reg(struct mtd_info *mtd) +static int read_id_reg(struct mtd_info *mtd) { struct nand_chip *nand = mtd_to_nand(mtd); struct docg4_priv *doc = nand_get_controller_data(nand); From 1ab534e85c93945f7862378d8c8adcf408205b19 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Fri, 24 Aug 2018 10:03:51 -0700 Subject: [PATCH 146/302] x86/spectre: Add missing family 6 check to microcode check The check for Spectre microcodes does not check for family 6, only the model numbers. Add a family 6 check to avoid ambiguity with other families. Fixes: a5b296636453 ("x86/cpufeature: Blacklist SPEC_CTRL/PRED_CMD on early Spectre v2 microcodes") Signed-off-by: Andi Kleen Signed-off-by: Thomas Gleixner Cc: x86@kernel.org Cc: linux-kernel@vger.kernel.org Cc: stable@vger.kernel.org Link: https://lkml.kernel.org/r/20180824170351.34874-2-andi@firstfloor.org --- arch/x86/kernel/cpu/intel.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c index 401e8c133108..fc3c07fe7df5 100644 --- a/arch/x86/kernel/cpu/intel.c +++ b/arch/x86/kernel/cpu/intel.c @@ -150,6 +150,9 @@ static bool bad_spectre_microcode(struct cpuinfo_x86 *c) if (cpu_has(c, X86_FEATURE_HYPERVISOR)) return false; + if (c->x86 != 6) + return false; + for (i = 0; i < ARRAY_SIZE(spectre_bad_microcodes); i++) { if (c->x86_model == spectre_bad_microcodes[i].model && c->x86_stepping == spectre_bad_microcodes[i].stepping) From cc51e5428ea54f575d49cfcede1d4cb3a72b4ec4 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Fri, 24 Aug 2018 10:03:50 -0700 Subject: [PATCH 147/302] x86/speculation/l1tf: Increase l1tf memory limit for Nehalem+ On Nehalem and newer core CPUs the CPU cache internally uses 44 bits physical address space. The L1TF workaround is limited by this internal cache address width, and needs to have one bit free there for the mitigation to work. Older client systems report only 36bit physical address space so the range check decides that L1TF is not mitigated for a 36bit phys/32GB system with some memory holes. But since these actually have the larger internal cache width this warning is bogus because it would only really be needed if the system had more than 43bits of memory. Add a new internal x86_cache_bits field. Normally it is the same as the physical bits field reported by CPUID, but for Nehalem and newerforce it to be at least 44bits. Change the L1TF memory size warning to use the new cache_bits field to avoid bogus warnings and remove the bogus comment about memory size. Fixes: 17dbca119312 ("x86/speculation/l1tf: Add sysfs reporting for l1tf") Reported-by: George Anchev Reported-by: Christopher Snowhill Signed-off-by: Andi Kleen Signed-off-by: Thomas Gleixner Cc: x86@kernel.org Cc: linux-kernel@vger.kernel.org Cc: Michael Hocko Cc: vbabka@suse.cz Cc: stable@vger.kernel.org Link: https://lkml.kernel.org/r/20180824170351.34874-1-andi@firstfloor.org --- arch/x86/include/asm/processor.h | 4 ++- arch/x86/kernel/cpu/bugs.c | 46 ++++++++++++++++++++++++++++---- arch/x86/kernel/cpu/common.c | 1 + 3 files changed, 45 insertions(+), 6 deletions(-) diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index c24297268ebc..d53c54b842da 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h @@ -132,6 +132,8 @@ struct cpuinfo_x86 { /* Index into per_cpu list: */ u16 cpu_index; u32 microcode; + /* Address space bits used by the cache internally */ + u8 x86_cache_bits; unsigned initialized : 1; } __randomize_layout; @@ -183,7 +185,7 @@ extern void cpu_detect(struct cpuinfo_x86 *c); static inline unsigned long long l1tf_pfn_limit(void) { - return BIT_ULL(boot_cpu_data.x86_phys_bits - 1 - PAGE_SHIFT); + return BIT_ULL(boot_cpu_data.x86_cache_bits - 1 - PAGE_SHIFT); } extern void early_cpu_init(void); diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c index 4c2313d0b9ca..40bdaea97fe7 100644 --- a/arch/x86/kernel/cpu/bugs.c +++ b/arch/x86/kernel/cpu/bugs.c @@ -668,6 +668,45 @@ EXPORT_SYMBOL_GPL(l1tf_mitigation); enum vmx_l1d_flush_state l1tf_vmx_mitigation = VMENTER_L1D_FLUSH_AUTO; EXPORT_SYMBOL_GPL(l1tf_vmx_mitigation); +/* + * These CPUs all support 44bits physical address space internally in the + * cache but CPUID can report a smaller number of physical address bits. + * + * The L1TF mitigation uses the top most address bit for the inversion of + * non present PTEs. When the installed memory reaches into the top most + * address bit due to memory holes, which has been observed on machines + * which report 36bits physical address bits and have 32G RAM installed, + * then the mitigation range check in l1tf_select_mitigation() triggers. + * This is a false positive because the mitigation is still possible due to + * the fact that the cache uses 44bit internally. Use the cache bits + * instead of the reported physical bits and adjust them on the affected + * machines to 44bit if the reported bits are less than 44. + */ +static void override_cache_bits(struct cpuinfo_x86 *c) +{ + if (c->x86 != 6) + return; + + switch (c->x86_model) { + case INTEL_FAM6_NEHALEM: + case INTEL_FAM6_WESTMERE: + case INTEL_FAM6_SANDYBRIDGE: + case INTEL_FAM6_IVYBRIDGE: + case INTEL_FAM6_HASWELL_CORE: + case INTEL_FAM6_HASWELL_ULT: + case INTEL_FAM6_HASWELL_GT3E: + case INTEL_FAM6_BROADWELL_CORE: + case INTEL_FAM6_BROADWELL_GT3E: + case INTEL_FAM6_SKYLAKE_MOBILE: + case INTEL_FAM6_SKYLAKE_DESKTOP: + case INTEL_FAM6_KABYLAKE_MOBILE: + case INTEL_FAM6_KABYLAKE_DESKTOP: + if (c->x86_cache_bits < 44) + c->x86_cache_bits = 44; + break; + } +} + static void __init l1tf_select_mitigation(void) { u64 half_pa; @@ -675,6 +714,8 @@ static void __init l1tf_select_mitigation(void) if (!boot_cpu_has_bug(X86_BUG_L1TF)) return; + override_cache_bits(&boot_cpu_data); + switch (l1tf_mitigation) { case L1TF_MITIGATION_OFF: case L1TF_MITIGATION_FLUSH_NOWARN: @@ -694,11 +735,6 @@ static void __init l1tf_select_mitigation(void) return; #endif - /* - * This is extremely unlikely to happen because almost all - * systems have far more MAX_PA/2 than RAM can be fit into - * DIMM slots. - */ half_pa = (u64)l1tf_pfn_limit() << PAGE_SHIFT; if (e820__mapped_any(half_pa, ULLONG_MAX - half_pa, E820_TYPE_RAM)) { pr_warn("System has more than MAX_PA/2 memory. L1TF mitigation not effective.\n"); diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 84dee5ab745a..44c4ef3d989b 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -919,6 +919,7 @@ void get_cpu_address_sizes(struct cpuinfo_x86 *c) else if (cpu_has(c, X86_FEATURE_PAE) || cpu_has(c, X86_FEATURE_PSE36)) c->x86_phys_bits = 36; #endif + c->x86_cache_bits = c->x86_phys_bits; } static void identify_cpu_without_cpuid(struct cpuinfo_x86 *c) From e3a5dc08715abba646324fd8456282bd77798e9c Mon Sep 17 00:00:00 2001 From: Nikolas Nyby Date: Sat, 25 Aug 2018 19:10:54 -0400 Subject: [PATCH 148/302] x86/Kconfig: Fix trivial typo Fix a typo in the Kconfig help text: adverticed -> advertised. Signed-off-by: Nikolas Nyby Signed-off-by: Thomas Gleixner Cc: trivial@kernel.org Cc: tglx@linutronix.de Cc: x86@kernel.org Link: https://lkml.kernel.org/r/20180825231054.23813-1-nikolas@gnu.org --- arch/x86/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index c5ff296bc5d1..1a0be022f91d 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -2843,7 +2843,7 @@ config X86_SYSFB This option, if enabled, marks VGA/VBE/EFI framebuffers as generic framebuffers so the new generic system-framebuffer drivers can be used on x86. If the framebuffer is not compatible with the generic - modes, it is adverticed as fallback platform framebuffer so legacy + modes, it is advertised as fallback platform framebuffer so legacy drivers like efifb, vesafb and uvesafb can pick it up. If this option is not selected, all system framebuffers are always marked as fallback platform framebuffers as usual. From f7c90c2aa4004808dff777ba6ae2c7294dd06851 Mon Sep 17 00:00:00 2001 From: Juergen Gross Date: Tue, 21 Aug 2018 17:37:54 +0200 Subject: [PATCH 149/302] x86/xen: don't write ptes directly in 32-bit PV guests In some cases 32-bit PAE PV guests still write PTEs directly instead of using hypercalls. This is especially bad when clearing a PTE as this is done via 32-bit writes which will produce intermediate L1TF attackable PTEs. Change the code to use hypercalls instead. Signed-off-by: Juergen Gross Reviewed-by: Jan Beulich Signed-off-by: Boris Ostrovsky --- arch/x86/xen/mmu_pv.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/arch/x86/xen/mmu_pv.c b/arch/x86/xen/mmu_pv.c index 9e7012858420..9396b4d17064 100644 --- a/arch/x86/xen/mmu_pv.c +++ b/arch/x86/xen/mmu_pv.c @@ -434,14 +434,13 @@ static void xen_set_pud(pud_t *ptr, pud_t val) static void xen_set_pte_atomic(pte_t *ptep, pte_t pte) { trace_xen_mmu_set_pte_atomic(ptep, pte); - set_64bit((u64 *)ptep, native_pte_val(pte)); + __xen_set_pte(ptep, pte); } static void xen_pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep) { trace_xen_mmu_pte_clear(mm, addr, ptep); - if (!xen_batched_set_pte(ptep, native_make_pte(0))) - native_pte_clear(mm, addr, ptep); + __xen_set_pte(ptep, native_make_pte(0)); } static void xen_pmd_clear(pmd_t *pmdp) @@ -1569,7 +1568,7 @@ static void __init xen_set_pte_init(pte_t *ptep, pte_t pte) pte = __pte_ma(((pte_val_ma(*ptep) & _PAGE_RW) | ~_PAGE_RW) & pte_val_ma(pte)); #endif - native_set_pte(ptep, pte); + __xen_set_pte(ptep, pte); } /* Early in boot, while setting up the initial pagetable, assume From 908946c4bee705542f38bc06c0203a6d83e3700c Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Mon, 27 Aug 2018 08:37:46 -0600 Subject: [PATCH 150/302] Fix up libata MAINTAINERS entry The email was botched in one entry, and I also forgot to update the location of the git tree. It'll be under the linux-block umbrella, just with different branches. Reported-by: Baruch Siach Fixes: 7634ccd2da97 ("libata: maintainership update") Signed-off-by: Jens Axboe Signed-off-by: Linus Torvalds --- MAINTAINERS | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index a5b256b25905..9ad052aeac39 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -8255,9 +8255,9 @@ F: drivers/ata/pata_arasan_cf.c LIBATA PATA DRIVERS M: Bartlomiej Zolnierkiewicz -M: Jens Axboe +M: Jens Axboe L: linux-ide@vger.kernel.org -T: git git://git.kernel.org/pub/scm/linux/kernel/git/tj/libata.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/axboe/linux-block.git S: Maintained F: drivers/ata/pata_*.c F: drivers/ata/ata_generic.c @@ -8275,7 +8275,7 @@ LIBATA SATA AHCI PLATFORM devices support M: Hans de Goede M: Jens Axboe L: linux-ide@vger.kernel.org -T: git git://git.kernel.org/pub/scm/linux/kernel/git/tj/libata.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/axboe/linux-block.git S: Maintained F: drivers/ata/ahci_platform.c F: drivers/ata/libahci_platform.c @@ -8291,7 +8291,7 @@ F: drivers/ata/sata_promise.* LIBATA SUBSYSTEM (Serial and Parallel ATA drivers) M: Jens Axboe L: linux-ide@vger.kernel.org -T: git git://git.kernel.org/pub/scm/linux/kernel/git/tj/libata.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/axboe/linux-block.git S: Maintained F: drivers/ata/ F: include/linux/ata.h From 973e5405f2f67ddbb2bf07b3ffc71908a37fea8e Mon Sep 17 00:00:00 2001 From: Juergen Gross Date: Mon, 13 Aug 2018 16:01:10 +0200 Subject: [PATCH 151/302] xen/blkback: don't keep persistent grants too long MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Persistent grants are allocated until a threshold per ring is being reached. Those grants won't be freed until the ring is being destroyed meaning there will be resources kept busy which might no longer be used. Instead of freeing only persistent grants until the threshold is reached add a timestamp and remove all persistent grants not having been in use for a minute. Signed-off-by: Juergen Gross Reviewed-by: Roger Pau Monné Signed-off-by: Konrad Rzeszutek Wilk --- .../ABI/testing/sysfs-driver-xen-blkback | 10 +++ drivers/block/xen-blkback/blkback.c | 90 ++++++++++--------- drivers/block/xen-blkback/common.h | 8 +- 3 files changed, 61 insertions(+), 47 deletions(-) diff --git a/Documentation/ABI/testing/sysfs-driver-xen-blkback b/Documentation/ABI/testing/sysfs-driver-xen-blkback index 8bb43b66eb55..4e7babb3ba1f 100644 --- a/Documentation/ABI/testing/sysfs-driver-xen-blkback +++ b/Documentation/ABI/testing/sysfs-driver-xen-blkback @@ -15,3 +15,13 @@ Description: blkback. If the frontend tries to use more than max_persistent_grants, the LRU kicks in and starts removing 5% of max_persistent_grants every 100ms. + +What: /sys/module/xen_blkback/parameters/persistent_grant_unused_seconds +Date: August 2018 +KernelVersion: 4.19 +Contact: Roger Pau Monné +Description: + How long a persistent grant is allowed to remain + allocated without being in use. The time is in + seconds, 0 means indefinitely long. + The default is 60 seconds. diff --git a/drivers/block/xen-blkback/blkback.c b/drivers/block/xen-blkback/blkback.c index b55b245e8052..9eae7b243f68 100644 --- a/drivers/block/xen-blkback/blkback.c +++ b/drivers/block/xen-blkback/blkback.c @@ -83,6 +83,18 @@ module_param_named(max_persistent_grants, xen_blkif_max_pgrants, int, 0644); MODULE_PARM_DESC(max_persistent_grants, "Maximum number of grants to map persistently"); +/* + * How long a persistent grant is allowed to remain allocated without being in + * use. The time is in seconds, 0 means indefinitely long. + */ + +static unsigned int xen_blkif_pgrant_timeout = 60; +module_param_named(persistent_grant_unused_seconds, xen_blkif_pgrant_timeout, + uint, 0644); +MODULE_PARM_DESC(persistent_grant_unused_seconds, + "Time in seconds an unused persistent grant is allowed to " + "remain allocated. Default is 60, 0 means unlimited."); + /* * Maximum number of rings/queues blkback supports, allow as many queues as there * are CPUs if user has not specified a value. @@ -123,6 +135,13 @@ module_param(log_stats, int, 0644); /* Number of free pages to remove on each call to gnttab_free_pages */ #define NUM_BATCH_FREE_PAGES 10 +static inline bool persistent_gnt_timeout(struct persistent_gnt *persistent_gnt) +{ + return xen_blkif_pgrant_timeout && + (jiffies - persistent_gnt->last_used >= + HZ * xen_blkif_pgrant_timeout); +} + static inline int get_free_page(struct xen_blkif_ring *ring, struct page **page) { unsigned long flags; @@ -278,7 +297,7 @@ static void put_persistent_gnt(struct xen_blkif_ring *ring, { if(!test_bit(PERSISTENT_GNT_ACTIVE, persistent_gnt->flags)) pr_alert_ratelimited("freeing a grant already unused\n"); - set_bit(PERSISTENT_GNT_WAS_ACTIVE, persistent_gnt->flags); + persistent_gnt->last_used = jiffies; clear_bit(PERSISTENT_GNT_ACTIVE, persistent_gnt->flags); atomic_dec(&ring->persistent_gnt_in_use); } @@ -371,26 +390,26 @@ static void purge_persistent_gnt(struct xen_blkif_ring *ring) struct persistent_gnt *persistent_gnt; struct rb_node *n; unsigned int num_clean, total; - bool scan_used = false, clean_used = false; + bool scan_used = false; struct rb_root *root; - if (ring->persistent_gnt_c < xen_blkif_max_pgrants || - (ring->persistent_gnt_c == xen_blkif_max_pgrants && - !ring->blkif->vbd.overflow_max_grants)) { - goto out; - } - if (work_busy(&ring->persistent_purge_work)) { pr_alert_ratelimited("Scheduled work from previous purge is still busy, cannot purge list\n"); goto out; } - num_clean = (xen_blkif_max_pgrants / 100) * LRU_PERCENT_CLEAN; - num_clean = ring->persistent_gnt_c - xen_blkif_max_pgrants + num_clean; - num_clean = min(ring->persistent_gnt_c, num_clean); - if ((num_clean == 0) || - (num_clean > (ring->persistent_gnt_c - atomic_read(&ring->persistent_gnt_in_use)))) - goto out; + if (ring->persistent_gnt_c < xen_blkif_max_pgrants || + (ring->persistent_gnt_c == xen_blkif_max_pgrants && + !ring->blkif->vbd.overflow_max_grants)) { + num_clean = 0; + } else { + num_clean = (xen_blkif_max_pgrants / 100) * LRU_PERCENT_CLEAN; + num_clean = ring->persistent_gnt_c - xen_blkif_max_pgrants + + num_clean; + num_clean = min(ring->persistent_gnt_c, num_clean); + pr_debug("Going to purge at least %u persistent grants\n", + num_clean); + } /* * At this point, we can assure that there will be no calls @@ -401,9 +420,7 @@ static void purge_persistent_gnt(struct xen_blkif_ring *ring) * number of grants. */ - total = num_clean; - - pr_debug("Going to purge %u persistent grants\n", num_clean); + total = 0; BUG_ON(!list_empty(&ring->persistent_purge_list)); root = &ring->persistent_gnts; @@ -412,47 +429,38 @@ static void purge_persistent_gnt(struct xen_blkif_ring *ring) BUG_ON(persistent_gnt->handle == BLKBACK_INVALID_HANDLE); - if (clean_used) { - clear_bit(PERSISTENT_GNT_WAS_ACTIVE, persistent_gnt->flags); - continue; - } - if (test_bit(PERSISTENT_GNT_ACTIVE, persistent_gnt->flags)) continue; - if (!scan_used && - (test_bit(PERSISTENT_GNT_WAS_ACTIVE, persistent_gnt->flags))) + if (!scan_used && !persistent_gnt_timeout(persistent_gnt)) + continue; + if (scan_used && total >= num_clean) continue; rb_erase(&persistent_gnt->node, root); list_add(&persistent_gnt->remove_node, &ring->persistent_purge_list); - if (--num_clean == 0) - goto finished; + total++; } /* - * If we get here it means we also need to start cleaning + * Check whether we also need to start cleaning * grants that were used since last purge in order to cope * with the requested num */ - if (!scan_used && !clean_used) { - pr_debug("Still missing %u purged frames\n", num_clean); + if (!scan_used && total < num_clean) { + pr_debug("Still missing %u purged frames\n", num_clean - total); scan_used = true; goto purge_list; } -finished: - if (!clean_used) { - pr_debug("Finished scanning for grants to clean, removing used flag\n"); - clean_used = true; - goto purge_list; + + if (total) { + ring->persistent_gnt_c -= total; + ring->blkif->vbd.overflow_max_grants = 0; + + /* We can defer this work */ + schedule_work(&ring->persistent_purge_work); + pr_debug("Purged %u/%u\n", num_clean, total); } - ring->persistent_gnt_c -= (total - num_clean); - ring->blkif->vbd.overflow_max_grants = 0; - - /* We can defer this work */ - schedule_work(&ring->persistent_purge_work); - pr_debug("Purged %u/%u\n", (total - num_clean), total); - out: return; } diff --git a/drivers/block/xen-blkback/common.h b/drivers/block/xen-blkback/common.h index ecb35fe8ca8d..7bff72db3b7e 100644 --- a/drivers/block/xen-blkback/common.h +++ b/drivers/block/xen-blkback/common.h @@ -234,14 +234,9 @@ struct xen_vbd { struct backend_info; /* Number of available flags */ -#define PERSISTENT_GNT_FLAGS_SIZE 2 +#define PERSISTENT_GNT_FLAGS_SIZE 1 /* This persistent grant is currently in use */ #define PERSISTENT_GNT_ACTIVE 0 -/* - * This persistent grant has been used, this flag is set when we remove the - * PERSISTENT_GNT_ACTIVE, to know that this grant has been used recently. - */ -#define PERSISTENT_GNT_WAS_ACTIVE 1 /* Number of requests that we can fit in a ring */ #define XEN_BLKIF_REQS_PER_PAGE 32 @@ -250,6 +245,7 @@ struct persistent_gnt { struct page *page; grant_ref_t gnt; grant_handle_t handle; + unsigned long last_used; DECLARE_BITMAP(flags, PERSISTENT_GNT_FLAGS_SIZE); struct rb_node node; struct list_head remove_node; From a46b53672b2c2e3770b38a4abf90d16364d2584b Mon Sep 17 00:00:00 2001 From: Juergen Gross Date: Mon, 13 Aug 2018 16:01:11 +0200 Subject: [PATCH 152/302] xen/blkfront: cleanup stale persistent grants MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a periodic cleanup function to remove old persistent grants which are no longer in use on the backend side. This avoids starvation in case there are lots of persistent grants for a device which no longer is involved in I/O business. Signed-off-by: Juergen Gross Reviewed-by: Roger Pau Monné Signed-off-by: Konrad Rzeszutek Wilk --- drivers/block/xen-blkfront.c | 94 ++++++++++++++++++++++++++++++++++-- 1 file changed, 90 insertions(+), 4 deletions(-) diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c index 8986adab9bf5..a2a395f85a41 100644 --- a/drivers/block/xen-blkfront.c +++ b/drivers/block/xen-blkfront.c @@ -46,6 +46,7 @@ #include #include #include +#include #include #include @@ -121,6 +122,8 @@ static inline struct blkif_req *blkif_req(struct request *rq) static DEFINE_MUTEX(blkfront_mutex); static const struct block_device_operations xlvbd_block_fops; +static struct delayed_work blkfront_work; +static LIST_HEAD(info_list); /* * Maximum number of segments in indirect requests, the actual value used by @@ -216,6 +219,7 @@ struct blkfront_info /* Save uncomplete reqs and bios for migration. */ struct list_head requests; struct bio_list bio_list; + struct list_head info_list; }; static unsigned int nr_minors; @@ -1759,6 +1763,12 @@ static int write_per_ring_nodes(struct xenbus_transaction xbt, return err; } +static void free_info(struct blkfront_info *info) +{ + list_del(&info->info_list); + kfree(info); +} + /* Common code used when first setting up, and when resuming. */ static int talk_to_blkback(struct xenbus_device *dev, struct blkfront_info *info) @@ -1880,7 +1890,10 @@ static int talk_to_blkback(struct xenbus_device *dev, destroy_blkring: blkif_free(info, 0); - kfree(info); + mutex_lock(&blkfront_mutex); + free_info(info); + mutex_unlock(&blkfront_mutex); + dev_set_drvdata(&dev->dev, NULL); return err; @@ -1991,6 +2004,10 @@ static int blkfront_probe(struct xenbus_device *dev, info->handle = simple_strtoul(strrchr(dev->nodename, '/')+1, NULL, 0); dev_set_drvdata(&dev->dev, info); + mutex_lock(&blkfront_mutex); + list_add(&info->info_list, &info_list); + mutex_unlock(&blkfront_mutex); + return 0; } @@ -2301,6 +2318,12 @@ static void blkfront_gather_backend_features(struct blkfront_info *info) if (indirect_segments <= BLKIF_MAX_SEGMENTS_PER_REQUEST) indirect_segments = 0; info->max_indirect_segments = indirect_segments; + + if (info->feature_persistent) { + mutex_lock(&blkfront_mutex); + schedule_delayed_work(&blkfront_work, HZ * 10); + mutex_unlock(&blkfront_mutex); + } } /* @@ -2482,7 +2505,9 @@ static int blkfront_remove(struct xenbus_device *xbdev) mutex_unlock(&info->mutex); if (!bdev) { - kfree(info); + mutex_lock(&blkfront_mutex); + free_info(info); + mutex_unlock(&blkfront_mutex); return 0; } @@ -2502,7 +2527,9 @@ static int blkfront_remove(struct xenbus_device *xbdev) if (info && !bdev->bd_openers) { xlvbd_release_gendisk(info); disk->private_data = NULL; - kfree(info); + mutex_lock(&blkfront_mutex); + free_info(info); + mutex_unlock(&blkfront_mutex); } mutex_unlock(&bdev->bd_mutex); @@ -2585,7 +2612,7 @@ static void blkif_release(struct gendisk *disk, fmode_t mode) dev_info(disk_to_dev(bdev->bd_disk), "releasing disk\n"); xlvbd_release_gendisk(info); disk->private_data = NULL; - kfree(info); + free_info(info); } out: @@ -2618,6 +2645,61 @@ static struct xenbus_driver blkfront_driver = { .is_ready = blkfront_is_ready, }; +static void purge_persistent_grants(struct blkfront_info *info) +{ + unsigned int i; + unsigned long flags; + + for (i = 0; i < info->nr_rings; i++) { + struct blkfront_ring_info *rinfo = &info->rinfo[i]; + struct grant *gnt_list_entry, *tmp; + + spin_lock_irqsave(&rinfo->ring_lock, flags); + + if (rinfo->persistent_gnts_c == 0) { + spin_unlock_irqrestore(&rinfo->ring_lock, flags); + continue; + } + + list_for_each_entry_safe(gnt_list_entry, tmp, &rinfo->grants, + node) { + if (gnt_list_entry->gref == GRANT_INVALID_REF || + gnttab_query_foreign_access(gnt_list_entry->gref)) + continue; + + list_del(&gnt_list_entry->node); + gnttab_end_foreign_access(gnt_list_entry->gref, 0, 0UL); + rinfo->persistent_gnts_c--; + __free_page(gnt_list_entry->page); + kfree(gnt_list_entry); + } + + spin_unlock_irqrestore(&rinfo->ring_lock, flags); + } +} + +static void blkfront_delay_work(struct work_struct *work) +{ + struct blkfront_info *info; + bool need_schedule_work = false; + + mutex_lock(&blkfront_mutex); + + list_for_each_entry(info, &info_list, info_list) { + if (info->feature_persistent) { + need_schedule_work = true; + mutex_lock(&info->mutex); + purge_persistent_grants(info); + mutex_unlock(&info->mutex); + } + } + + if (need_schedule_work) + schedule_delayed_work(&blkfront_work, HZ * 10); + + mutex_unlock(&blkfront_mutex); +} + static int __init xlblk_init(void) { int ret; @@ -2650,6 +2732,8 @@ static int __init xlblk_init(void) return -ENODEV; } + INIT_DELAYED_WORK(&blkfront_work, blkfront_delay_work); + ret = xenbus_register_frontend(&blkfront_driver); if (ret) { unregister_blkdev(XENVBD_MAJOR, DEV_NAME); @@ -2663,6 +2747,8 @@ module_init(xlblk_init); static void __exit xlblk_exit(void) { + cancel_delayed_work_sync(&blkfront_work); + xenbus_unregister_driver(&blkfront_driver); unregister_blkdev(XENVBD_MAJOR, DEV_NAME); kfree(minors); From 4bcddbae019df2614ea36976ba3d36313f93c6d3 Mon Sep 17 00:00:00 2001 From: Juergen Gross Date: Mon, 13 Aug 2018 16:01:12 +0200 Subject: [PATCH 153/302] xen/blkfront: reorder tests in xlblk_init() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In case we don't want pv block devices we should not test parameters for sanity and eventually print out error messages. So test precluding conditions before checking parameters. Signed-off-by: Juergen Gross Reviewed-by: Roger Pau Monné Signed-off-by: Konrad Rzeszutek Wilk --- drivers/block/xen-blkfront.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c index a2a395f85a41..a71d817e900d 100644 --- a/drivers/block/xen-blkfront.c +++ b/drivers/block/xen-blkfront.c @@ -2708,6 +2708,15 @@ static int __init xlblk_init(void) if (!xen_domain()) return -ENODEV; + if (!xen_has_pv_disk_devices()) + return -ENODEV; + + if (register_blkdev(XENVBD_MAJOR, DEV_NAME)) { + pr_warn("xen_blk: can't get major %d with name %s\n", + XENVBD_MAJOR, DEV_NAME); + return -ENODEV; + } + if (xen_blkif_max_segments < BLKIF_MAX_SEGMENTS_PER_REQUEST) xen_blkif_max_segments = BLKIF_MAX_SEGMENTS_PER_REQUEST; @@ -2723,15 +2732,6 @@ static int __init xlblk_init(void) xen_blkif_max_queues = nr_cpus; } - if (!xen_has_pv_disk_devices()) - return -ENODEV; - - if (register_blkdev(XENVBD_MAJOR, DEV_NAME)) { - printk(KERN_WARNING "xen_blk: can't get major %d with name %s\n", - XENVBD_MAJOR, DEV_NAME); - return -ENODEV; - } - INIT_DELAYED_WORK(&blkfront_work, blkfront_delay_work); ret = xenbus_register_frontend(&blkfront_driver); From d77ff24e7fa2258877fa0b87efa06b9a58a37aab Mon Sep 17 00:00:00 2001 From: Juergen Gross Date: Mon, 13 Aug 2018 16:01:13 +0200 Subject: [PATCH 154/302] xen/blkback: move persistent grants flags to bool MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The struct persistent_gnt flags member is meant to be a bitfield of different flags. There is only PERSISTENT_GNT_ACTIVE flag left, so convert it to a bool named "active". Signed-off-by: Juergen Gross Reviewed-by: Roger Pau Monné Signed-off-by: Konrad Rzeszutek Wilk --- drivers/block/xen-blkback/blkback.c | 13 ++++++------- drivers/block/xen-blkback/common.h | 7 +------ 2 files changed, 7 insertions(+), 13 deletions(-) diff --git a/drivers/block/xen-blkback/blkback.c b/drivers/block/xen-blkback/blkback.c index 9eae7b243f68..fd1e19f1a49f 100644 --- a/drivers/block/xen-blkback/blkback.c +++ b/drivers/block/xen-blkback/blkback.c @@ -255,8 +255,7 @@ static int add_persistent_gnt(struct xen_blkif_ring *ring, } } - bitmap_zero(persistent_gnt->flags, PERSISTENT_GNT_FLAGS_SIZE); - set_bit(PERSISTENT_GNT_ACTIVE, persistent_gnt->flags); + persistent_gnt->active = true; /* Add new node and rebalance tree. */ rb_link_node(&(persistent_gnt->node), parent, new); rb_insert_color(&(persistent_gnt->node), &ring->persistent_gnts); @@ -280,11 +279,11 @@ static struct persistent_gnt *get_persistent_gnt(struct xen_blkif_ring *ring, else if (gref > data->gnt) node = node->rb_right; else { - if(test_bit(PERSISTENT_GNT_ACTIVE, data->flags)) { + if (data->active) { pr_alert_ratelimited("requesting a grant already in use\n"); return NULL; } - set_bit(PERSISTENT_GNT_ACTIVE, data->flags); + data->active = true; atomic_inc(&ring->persistent_gnt_in_use); return data; } @@ -295,10 +294,10 @@ static struct persistent_gnt *get_persistent_gnt(struct xen_blkif_ring *ring, static void put_persistent_gnt(struct xen_blkif_ring *ring, struct persistent_gnt *persistent_gnt) { - if(!test_bit(PERSISTENT_GNT_ACTIVE, persistent_gnt->flags)) + if (!persistent_gnt->active) pr_alert_ratelimited("freeing a grant already unused\n"); persistent_gnt->last_used = jiffies; - clear_bit(PERSISTENT_GNT_ACTIVE, persistent_gnt->flags); + persistent_gnt->active = false; atomic_dec(&ring->persistent_gnt_in_use); } @@ -429,7 +428,7 @@ static void purge_persistent_gnt(struct xen_blkif_ring *ring) BUG_ON(persistent_gnt->handle == BLKBACK_INVALID_HANDLE); - if (test_bit(PERSISTENT_GNT_ACTIVE, persistent_gnt->flags)) + if (persistent_gnt->active) continue; if (!scan_used && !persistent_gnt_timeout(persistent_gnt)) continue; diff --git a/drivers/block/xen-blkback/common.h b/drivers/block/xen-blkback/common.h index 7bff72db3b7e..2339b8d39c5e 100644 --- a/drivers/block/xen-blkback/common.h +++ b/drivers/block/xen-blkback/common.h @@ -233,11 +233,6 @@ struct xen_vbd { struct backend_info; -/* Number of available flags */ -#define PERSISTENT_GNT_FLAGS_SIZE 1 -/* This persistent grant is currently in use */ -#define PERSISTENT_GNT_ACTIVE 0 - /* Number of requests that we can fit in a ring */ #define XEN_BLKIF_REQS_PER_PAGE 32 @@ -246,7 +241,7 @@ struct persistent_gnt { grant_ref_t gnt; grant_handle_t handle; unsigned long last_used; - DECLARE_BITMAP(flags, PERSISTENT_GNT_FLAGS_SIZE); + bool active; struct rb_node node; struct list_head remove_node; }; From 6f2f39ad1a54978394851c05e327419ebeb7227e Mon Sep 17 00:00:00 2001 From: Juergen Gross Date: Mon, 13 Aug 2018 16:01:14 +0200 Subject: [PATCH 155/302] xen/blkback: remove unused pers_gnts_lock from struct xen_blkif_ring MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit pers_gnts_lock isn't being used anywhere. Remove it. Signed-off-by: Juergen Gross Reviewed-by: Roger Pau Monné Signed-off-by: Konrad Rzeszutek Wilk --- drivers/block/xen-blkback/common.h | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/block/xen-blkback/common.h b/drivers/block/xen-blkback/common.h index 2339b8d39c5e..1d3002d773f7 100644 --- a/drivers/block/xen-blkback/common.h +++ b/drivers/block/xen-blkback/common.h @@ -269,7 +269,6 @@ struct xen_blkif_ring { wait_queue_head_t pending_free_wq; /* Tree to store persistent grants. */ - spinlock_t pers_gnts_lock; struct rb_root persistent_gnts; unsigned int persistent_gnt_c; atomic_t persistent_gnt_in_use; From 061a5427530633de93ace4ef001b99961984af62 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sun, 26 Aug 2018 10:09:06 -0600 Subject: [PATCH 156/302] blk-wbt: abstract out end IO completion handler Prep patch for calling the handler from a different context, no functional changes in this patch. Tested-by: Agarwal, Anchal Signed-off-by: Jens Axboe --- block/blk-wbt.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/block/blk-wbt.c b/block/blk-wbt.c index 84507d3e9a98..4575b4650370 100644 --- a/block/blk-wbt.c +++ b/block/blk-wbt.c @@ -123,16 +123,11 @@ static void rwb_wake_all(struct rq_wb *rwb) } } -static void __wbt_done(struct rq_qos *rqos, enum wbt_flags wb_acct) +static void wbt_rqw_done(struct rq_wb *rwb, struct rq_wait *rqw, + enum wbt_flags wb_acct) { - struct rq_wb *rwb = RQWB(rqos); - struct rq_wait *rqw; int inflight, limit; - if (!(wb_acct & WBT_TRACKED)) - return; - - rqw = get_rq_wait(rwb, wb_acct); inflight = atomic_dec_return(&rqw->inflight); /* @@ -170,6 +165,18 @@ static void __wbt_done(struct rq_qos *rqos, enum wbt_flags wb_acct) } } +static void __wbt_done(struct rq_qos *rqos, enum wbt_flags wb_acct) +{ + struct rq_wb *rwb = RQWB(rqos); + struct rq_wait *rqw; + + if (!(wb_acct & WBT_TRACKED)) + return; + + rqw = get_rq_wait(rwb, wb_acct); + wbt_rqw_done(rwb, rqw, wb_acct); +} + /* * Called on completion of a request. Note that it's also called when * a request is merged, when the request gets freed. From 38cfb5a45ee013bfab5d1ae4c4738815e744b440 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sun, 26 Aug 2018 10:10:05 -0600 Subject: [PATCH 157/302] blk-wbt: improve waking of tasks We have two potential issues: 1) After commit 2887e41b910b, we only wake one process at the time when we finish an IO. We really want to wake up as many tasks as can queue IO. Before this commit, we woke up everyone, which could cause a thundering herd issue. 2) A task can potentially consume two wakeups, causing us to (in practice) miss a wakeup. Fix both by providing our own wakeup function, which stops __wake_up_common() from waking up more tasks if we fail to get a queueing token. With the strict ordering we have on the wait list, this wakes the right tasks and the right amount of tasks. Based on a patch from Jianchao Wang . Tested-by: Agarwal, Anchal Signed-off-by: Jens Axboe --- block/blk-wbt.c | 65 +++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 57 insertions(+), 8 deletions(-) diff --git a/block/blk-wbt.c b/block/blk-wbt.c index 4575b4650370..bfb0d21d19ce 100644 --- a/block/blk-wbt.c +++ b/block/blk-wbt.c @@ -161,7 +161,7 @@ static void wbt_rqw_done(struct rq_wb *rwb, struct rq_wait *rqw, int diff = limit - inflight; if (!inflight || diff >= rwb->wb_background / 2) - wake_up(&rqw->wait); + wake_up_all(&rqw->wait); } } @@ -488,6 +488,34 @@ static inline unsigned int get_limit(struct rq_wb *rwb, unsigned long rw) return limit; } +struct wbt_wait_data { + struct wait_queue_entry wq; + struct task_struct *task; + struct rq_wb *rwb; + struct rq_wait *rqw; + unsigned long rw; + bool got_token; +}; + +static int wbt_wake_function(struct wait_queue_entry *curr, unsigned int mode, + int wake_flags, void *key) +{ + struct wbt_wait_data *data = container_of(curr, struct wbt_wait_data, + wq); + + /* + * If we fail to get a budget, return -1 to interrupt the wake up + * loop in __wake_up_common. + */ + if (!rq_wait_inc_below(data->rqw, get_limit(data->rwb, data->rw))) + return -1; + + data->got_token = true; + list_del_init(&curr->entry); + wake_up_process(data->task); + return 1; +} + /* * Block if we will exceed our limit, or if we are currently waiting for * the timer to kick off queuing again. @@ -498,31 +526,52 @@ static void __wbt_wait(struct rq_wb *rwb, enum wbt_flags wb_acct, __acquires(lock) { struct rq_wait *rqw = get_rq_wait(rwb, wb_acct); - DECLARE_WAITQUEUE(wait, current); + struct wbt_wait_data data = { + .wq = { + .func = wbt_wake_function, + .entry = LIST_HEAD_INIT(data.wq.entry), + }, + .task = current, + .rwb = rwb, + .rqw = rqw, + .rw = rw, + }; bool has_sleeper; has_sleeper = wq_has_sleeper(&rqw->wait); if (!has_sleeper && rq_wait_inc_below(rqw, get_limit(rwb, rw))) return; - add_wait_queue_exclusive(&rqw->wait, &wait); + prepare_to_wait_exclusive(&rqw->wait, &data.wq, TASK_UNINTERRUPTIBLE); do { - set_current_state(TASK_UNINTERRUPTIBLE); - - if (!has_sleeper && rq_wait_inc_below(rqw, get_limit(rwb, rw))) + if (data.got_token) break; + if (!has_sleeper && + rq_wait_inc_below(rqw, get_limit(rwb, rw))) { + finish_wait(&rqw->wait, &data.wq); + + /* + * We raced with wbt_wake_function() getting a token, + * which means we now have two. Put our local token + * and wake anyone else potentially waiting for one. + */ + if (data.got_token) + wbt_rqw_done(rwb, rqw, wb_acct); + break; + } + if (lock) { spin_unlock_irq(lock); io_schedule(); spin_lock_irq(lock); } else io_schedule(); + has_sleeper = false; } while (1); - __set_current_state(TASK_RUNNING); - remove_wait_queue(&rqw->wait, &wait); + finish_wait(&rqw->wait, &data.wq); } static inline bool wbt_should_throttle(struct rq_wb *rwb, struct bio *bio) From b2d7a075a1ccef2fb321d595802190c8e9b39004 Mon Sep 17 00:00:00 2001 From: Juergen Gross Date: Tue, 21 Aug 2018 17:37:55 +0200 Subject: [PATCH 158/302] x86/pae: use 64 bit atomic xchg function in native_ptep_get_and_clear Using only 32-bit writes for the pte will result in an intermediate L1TF vulnerable PTE. When running as a Xen PV guest this will at once switch the guest to shadow mode resulting in a loss of performance. Use arch_atomic64_xchg() instead which will perform the requested operation atomically with all 64 bits. Some performance considerations according to: https://software.intel.com/sites/default/files/managed/ad/dc/Intel-Xeon-Scalable-Processor-throughput-latency.pdf The main number should be the latency, as there is no tight loop around native_ptep_get_and_clear(). "lock cmpxchg8b" has a latency of 20 cycles, while "lock xchg" (with a memory operand) isn't mentioned in that document. "lock xadd" (with xadd having 3 cycles less latency than xchg) has a latency of 11, so we can assume a latency of 14 for "lock xchg". Signed-off-by: Juergen Gross Reviewed-by: Thomas Gleixner Reviewed-by: Jan Beulich Tested-by: Jason Andryuk Signed-off-by: Boris Ostrovsky --- arch/x86/include/asm/pgtable-3level.h | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/arch/x86/include/asm/pgtable-3level.h b/arch/x86/include/asm/pgtable-3level.h index a564084c6141..f8b1ad2c3828 100644 --- a/arch/x86/include/asm/pgtable-3level.h +++ b/arch/x86/include/asm/pgtable-3level.h @@ -2,6 +2,8 @@ #ifndef _ASM_X86_PGTABLE_3LEVEL_H #define _ASM_X86_PGTABLE_3LEVEL_H +#include + /* * Intel Physical Address Extension (PAE) Mode - three-level page * tables on PPro+ CPUs. @@ -150,10 +152,7 @@ static inline pte_t native_ptep_get_and_clear(pte_t *ptep) { pte_t res; - /* xchg acts as a barrier before the setting of the high bits */ - res.pte_low = xchg(&ptep->pte_low, 0); - res.pte_high = ptep->pte_high; - ptep->pte_high = 0; + res.pte = (pteval_t)arch_atomic64_xchg((atomic64_t *)ptep, 0); return res; } From 336d139f8718b1336c9d22f0e462611ae1229850 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Mon, 27 Aug 2018 16:01:41 +0900 Subject: [PATCH 159/302] mtd: rawnand: denali: do not pass zero maxchips to nand_scan() Commit 49aa76b16676 ("mtd: rawnand: do not execute nand_scan_ident() if maxchips is zero") gave a new meaning for calling nand_scan_ident() with maxchips=0. It is a special usage for some drivers such as docg4, but actually the Denali driver may pass maxchips=0 to nand_scan() when the driver is enabled but no NAND chip is found on the board for some reasons. If nand_scan_with_ids() is called with maxchips=0, nand_scan_ident() is skipped, then nand_set_defaults() is skipped as well. Thus, the driver must set chip->controller beforehand. Otherwise, nand_attach() causes NULL pointer dereference. In fact, the Denali controller knows the number of connected chips before calling nand_scan_ident(); if DEVICE_RESET fails, there is no chip in that chip select. Then, denali_reset_banks() sets the maxchips to the number of detected chips. If no chip is found, maxchips is zero. In this case, there is no point for calling nand_scan() because we know it will fail for sure. Let's make the probe function fail immediately. Fixes: 49aa76b16676 ("mtd: rawnand: do not execute nand_scan_ident() if maxchips is zero") Signed-off-by: Masahiro Yamada Acked-by: Miquel Raynal Signed-off-by: Boris Brezillon --- drivers/mtd/nand/raw/denali.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/mtd/nand/raw/denali.c b/drivers/mtd/nand/raw/denali.c index ca18612c4201..67b2065e7a19 100644 --- a/drivers/mtd/nand/raw/denali.c +++ b/drivers/mtd/nand/raw/denali.c @@ -1338,6 +1338,11 @@ int denali_init(struct denali_nand_info *denali) denali_enable_irq(denali); denali_reset_banks(denali); + if (!denali->max_banks) { + /* Error out earlier if no chip is found for some reasons. */ + ret = -ENODEV; + goto disable_irq; + } denali->active_bank = DENALI_INVALID_BANK; From b0a84beb2e35536839ea289182684528f379b860 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Mon, 27 Aug 2018 13:32:12 -0600 Subject: [PATCH 160/302] blk-wbt: remove dead code We already note and mark discard and swap IO from bio_to_wbt_flags(). Signed-off-by: Jens Axboe --- block/blk-wbt.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/block/blk-wbt.c b/block/blk-wbt.c index bfb0d21d19ce..8e20a0677dcf 100644 --- a/block/blk-wbt.c +++ b/block/blk-wbt.c @@ -636,11 +636,6 @@ static void wbt_wait(struct rq_qos *rqos, struct bio *bio, spinlock_t *lock) return; } - if (current_is_kswapd()) - flags |= WBT_KSWAPD; - if (bio_op(bio) == REQ_OP_DISCARD) - flags |= WBT_DISCARD; - __wbt_wait(rwb, flags, bio->bi_opf, lock); if (!blk_stat_is_active(rwb->cb)) From fca5d959972c18839f0306f19df2f121623447dd Mon Sep 17 00:00:00 2001 From: Felix Kuehling Date: Tue, 21 Aug 2018 17:14:32 -0400 Subject: [PATCH 161/302] drm/amdgpu: Adjust the VM size based on system memory size v2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Set the VM size based on system memory size between the ASIC-specific limits given by min_vm_size and max_bits. GFXv9 GPUs will keep their default VM size of 256TB (48 bit). Only older GPUs will adjust VM size depending on system memory size. This makes more VM space available for ROCm applications on GFXv8 GPUs that want to map all available VRAM and system memory in their SVM address space. v2: * Clarify comment * Round up memory size before >> 30 * Round up automatic vm_size to power of two Signed-off-by: Felix Kuehling Acked-by: Junwei Zhang Reviewed-by: Huang Rui Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 32 ++++++++++++++++++++++---- drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h | 2 +- 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index e40ca8676418..d174d50e3bd3 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -2483,28 +2483,52 @@ static uint32_t amdgpu_vm_get_block_size(uint64_t vm_size) * amdgpu_vm_adjust_size - adjust vm size, block size and fragment size * * @adev: amdgpu_device pointer - * @vm_size: the default vm size if it's set auto + * @min_vm_size: the minimum vm size in GB if it's set auto * @fragment_size_default: Default PTE fragment size * @max_level: max VMPT level * @max_bits: max address space size in bits * */ -void amdgpu_vm_adjust_size(struct amdgpu_device *adev, uint32_t vm_size, +void amdgpu_vm_adjust_size(struct amdgpu_device *adev, uint32_t min_vm_size, uint32_t fragment_size_default, unsigned max_level, unsigned max_bits) { + unsigned int max_size = 1 << (max_bits - 30); + unsigned int vm_size; uint64_t tmp; /* adjust vm size first */ if (amdgpu_vm_size != -1) { - unsigned max_size = 1 << (max_bits - 30); - vm_size = amdgpu_vm_size; if (vm_size > max_size) { dev_warn(adev->dev, "VM size (%d) too large, max is %u GB\n", amdgpu_vm_size, max_size); vm_size = max_size; } + } else { + struct sysinfo si; + unsigned int phys_ram_gb; + + /* Optimal VM size depends on the amount of physical + * RAM available. Underlying requirements and + * assumptions: + * + * - Need to map system memory and VRAM from all GPUs + * - VRAM from other GPUs not known here + * - Assume VRAM <= system memory + * - On GFX8 and older, VM space can be segmented for + * different MTYPEs + * - Need to allow room for fragmentation, guard pages etc. + * + * This adds up to a rough guess of system memory x3. + * Round up to power of two to maximize the available + * VM size with the given page table size. + */ + si_meminfo(&si); + phys_ram_gb = ((uint64_t)si.totalram * si.mem_unit + + (1 << 30) - 1) >> 30; + vm_size = roundup_pow_of_two( + min(max(phys_ram_gb * 3, min_vm_size), max_size)); } adev->vm_manager.max_pfn = (uint64_t)vm_size << 18; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h index 67a15d439ac0..9fa9df0c5e7f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h @@ -321,7 +321,7 @@ struct amdgpu_bo_va_mapping *amdgpu_vm_bo_lookup_mapping(struct amdgpu_vm *vm, void amdgpu_vm_bo_trace_cs(struct amdgpu_vm *vm, struct ww_acquire_ctx *ticket); void amdgpu_vm_bo_rmv(struct amdgpu_device *adev, struct amdgpu_bo_va *bo_va); -void amdgpu_vm_adjust_size(struct amdgpu_device *adev, uint32_t vm_size, +void amdgpu_vm_adjust_size(struct amdgpu_device *adev, uint32_t min_vm_size, uint32_t fragment_size_default, unsigned max_level, unsigned max_bits); int amdgpu_vm_ioctl(struct drm_device *dev, void *data, struct drm_file *filp); From 8ef23364b654d44244400d79988e677e504b21ba Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Fri, 24 Aug 2018 17:26:23 +0800 Subject: [PATCH 162/302] drm/amdgpu: Enable/disable gfx PG feature in rlc safe mode This is required by gfx hw and can fix the rlc hang when do s3 stree test on Cz/St. Reviewed-by: Alex Deucher Signed-off-by: Hang Zhou Signed-off-by: Rex Zhu Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c index 5cd45210113f..5a9534a82d40 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c @@ -5664,6 +5664,11 @@ static int gfx_v8_0_set_powergating_state(void *handle, if (amdgpu_sriov_vf(adev)) return 0; + if (adev->pg_flags & (AMD_PG_SUPPORT_GFX_SMG | + AMD_PG_SUPPORT_RLC_SMU_HS | + AMD_PG_SUPPORT_CP | + AMD_PG_SUPPORT_GFX_DMG)) + adev->gfx.rlc.funcs->enter_safe_mode(adev); switch (adev->asic_type) { case CHIP_CARRIZO: case CHIP_STONEY: @@ -5713,7 +5718,11 @@ static int gfx_v8_0_set_powergating_state(void *handle, default: break; } - + if (adev->pg_flags & (AMD_PG_SUPPORT_GFX_SMG | + AMD_PG_SUPPORT_RLC_SMU_HS | + AMD_PG_SUPPORT_CP | + AMD_PG_SUPPORT_GFX_DMG)) + adev->gfx.rlc.funcs->exit_safe_mode(adev); return 0; } From 6d39df146ff12fb5c71634ad135144d5423590ec Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Thu, 23 Aug 2018 15:30:45 +0800 Subject: [PATCH 163/302] drm/amdgpu: Fix vce initialize failed on Kaveri/Mullins MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Forgot to add vce pg support via smu for Kaveri/Mullins. Fixes: 561a5c83eadd ("drm/amd/pp: Unify powergate_uvd/vce/mmhub to set_powergating_by_smu") v2: refine patch descriptions suggested by Michel Reviewed-by: Alex Deucher Tested-by: Michel Dänzer Signed-off-by: Rex Zhu Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/kv_dpm.c | 41 ++++++++++++++++++----------- 1 file changed, 26 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/kv_dpm.c b/drivers/gpu/drm/amd/amdgpu/kv_dpm.c index 3f57f6463dc8..a713c8b6e09c 100644 --- a/drivers/gpu/drm/amd/amdgpu/kv_dpm.c +++ b/drivers/gpu/drm/amd/amdgpu/kv_dpm.c @@ -66,7 +66,6 @@ static int kv_set_thermal_temperature_range(struct amdgpu_device *adev, static int kv_init_fps_limits(struct amdgpu_device *adev); static void kv_dpm_powergate_uvd(void *handle, bool gate); -static void kv_dpm_powergate_vce(struct amdgpu_device *adev, bool gate); static void kv_dpm_powergate_samu(struct amdgpu_device *adev, bool gate); static void kv_dpm_powergate_acp(struct amdgpu_device *adev, bool gate); @@ -1374,6 +1373,8 @@ static int kv_dpm_enable(struct amdgpu_device *adev) static void kv_dpm_disable(struct amdgpu_device *adev) { + struct kv_power_info *pi = kv_get_pi(adev); + amdgpu_irq_put(adev, &adev->pm.dpm.thermal.irq, AMDGPU_THERMAL_IRQ_LOW_TO_HIGH); amdgpu_irq_put(adev, &adev->pm.dpm.thermal.irq, @@ -1387,7 +1388,8 @@ static void kv_dpm_disable(struct amdgpu_device *adev) /* powerup blocks */ kv_dpm_powergate_acp(adev, false); kv_dpm_powergate_samu(adev, false); - kv_dpm_powergate_vce(adev, false); + if (pi->caps_vce_pg) /* power on the VCE block */ + amdgpu_kv_notify_message_to_smu(adev, PPSMC_MSG_VCEPowerON); kv_dpm_powergate_uvd(adev, false); kv_enable_smc_cac(adev, false); @@ -1551,7 +1553,6 @@ static int kv_update_vce_dpm(struct amdgpu_device *adev, int ret; if (amdgpu_new_state->evclk > 0 && amdgpu_current_state->evclk == 0) { - kv_dpm_powergate_vce(adev, false); if (pi->caps_stable_p_state) pi->vce_boot_level = table->count - 1; else @@ -1573,7 +1574,6 @@ static int kv_update_vce_dpm(struct amdgpu_device *adev, kv_enable_vce_dpm(adev, true); } else if (amdgpu_new_state->evclk == 0 && amdgpu_current_state->evclk > 0) { kv_enable_vce_dpm(adev, false); - kv_dpm_powergate_vce(adev, true); } return 0; @@ -1702,24 +1702,32 @@ static void kv_dpm_powergate_uvd(void *handle, bool gate) } } -static void kv_dpm_powergate_vce(struct amdgpu_device *adev, bool gate) +static void kv_dpm_powergate_vce(void *handle, bool gate) { + struct amdgpu_device *adev = (struct amdgpu_device *)handle; struct kv_power_info *pi = kv_get_pi(adev); - - if (pi->vce_power_gated == gate) - return; + int ret; pi->vce_power_gated = gate; - if (!pi->caps_vce_pg) - return; - - if (gate) - amdgpu_kv_notify_message_to_smu(adev, PPSMC_MSG_VCEPowerOFF); - else - amdgpu_kv_notify_message_to_smu(adev, PPSMC_MSG_VCEPowerON); + if (gate) { + /* stop the VCE block */ + ret = amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VCE, + AMD_PG_STATE_GATE); + kv_enable_vce_dpm(adev, false); + if (pi->caps_vce_pg) /* power off the VCE block */ + amdgpu_kv_notify_message_to_smu(adev, PPSMC_MSG_VCEPowerOFF); + } else { + if (pi->caps_vce_pg) /* power on the VCE block */ + amdgpu_kv_notify_message_to_smu(adev, PPSMC_MSG_VCEPowerON); + kv_enable_vce_dpm(adev, true); + /* re-init the VCE block */ + ret = amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VCE, + AMD_PG_STATE_UNGATE); + } } + static void kv_dpm_powergate_samu(struct amdgpu_device *adev, bool gate) { struct kv_power_info *pi = kv_get_pi(adev); @@ -3313,6 +3321,9 @@ static int kv_set_powergating_by_smu(void *handle, case AMD_IP_BLOCK_TYPE_UVD: kv_dpm_powergate_uvd(handle, gate); break; + case AMD_IP_BLOCK_TYPE_VCE: + kv_dpm_powergate_vce(handle, gate); + break; default: break; } From 2ab4d0e74256fc49b7b270f63c1d1e47c2455abc Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Fri, 24 Aug 2018 16:17:54 +0800 Subject: [PATCH 164/302] drm/amdgpu: Update power state at the end of smu hw_init. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For SI/Kv, the power state is managed by function amdgpu_pm_compute_clocks. when dpm enabled, we should call amdgpu_pm_compute_clocks to update current power state instand of set boot state. this change can fix the oops when kfd driver was enabled on Kv. Reviewed-by: Alex Deucher Tested-by: Michel Dänzer Signed-off-by: Rex Zhu Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/kv_dpm.c | 4 +--- drivers/gpu/drm/amd/amdgpu/si_dpm.c | 3 +-- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/kv_dpm.c b/drivers/gpu/drm/amd/amdgpu/kv_dpm.c index a713c8b6e09c..b497c37cef7e 100644 --- a/drivers/gpu/drm/amd/amdgpu/kv_dpm.c +++ b/drivers/gpu/drm/amd/amdgpu/kv_dpm.c @@ -1353,8 +1353,6 @@ static int kv_dpm_enable(struct amdgpu_device *adev) return ret; } - kv_update_current_ps(adev, adev->pm.dpm.boot_ps); - if (adev->irq.installed && amdgpu_is_internal_thermal_sensor(adev->pm.int_thermal_type)) { ret = kv_set_thermal_temperature_range(adev, KV_TEMP_RANGE_MIN, KV_TEMP_RANGE_MAX); @@ -3069,7 +3067,7 @@ static int kv_dpm_hw_init(void *handle) else adev->pm.dpm_enabled = true; mutex_unlock(&adev->pm.mutex); - + amdgpu_pm_compute_clocks(adev); return ret; } diff --git a/drivers/gpu/drm/amd/amdgpu/si_dpm.c b/drivers/gpu/drm/amd/amdgpu/si_dpm.c index db327b412562..1de96995e690 100644 --- a/drivers/gpu/drm/amd/amdgpu/si_dpm.c +++ b/drivers/gpu/drm/amd/amdgpu/si_dpm.c @@ -6887,7 +6887,6 @@ static int si_dpm_enable(struct amdgpu_device *adev) si_enable_auto_throttle_source(adev, AMDGPU_DPM_AUTO_THROTTLE_SRC_THERMAL, true); si_thermal_start_thermal_controller(adev); - ni_update_current_ps(adev, boot_ps); return 0; } @@ -7763,7 +7762,7 @@ static int si_dpm_hw_init(void *handle) else adev->pm.dpm_enabled = true; mutex_unlock(&adev->pm.mutex); - + amdgpu_pm_compute_clocks(adev); return ret; } From 72ef23de207bad349ddc648296f330e176ac175b Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Thu, 23 Aug 2018 15:41:57 +0800 Subject: [PATCH 165/302] drm/amdgpu: Power on uvd block when hw_fini MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit when hw_fini/suspend, smu only need to power on uvd block if uvd pg is supported, don't need to call uvd to do hw_init. v2: fix typo in patch descriptions and comments. Reviewed-by: Alex Deucher Tested-by: Michel Dänzer Signed-off-by: Rex Zhu Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/kv_dpm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/kv_dpm.c b/drivers/gpu/drm/amd/amdgpu/kv_dpm.c index b497c37cef7e..cb79a93c2eb7 100644 --- a/drivers/gpu/drm/amd/amdgpu/kv_dpm.c +++ b/drivers/gpu/drm/amd/amdgpu/kv_dpm.c @@ -65,7 +65,6 @@ static int kv_set_thermal_temperature_range(struct amdgpu_device *adev, int min_temp, int max_temp); static int kv_init_fps_limits(struct amdgpu_device *adev); -static void kv_dpm_powergate_uvd(void *handle, bool gate); static void kv_dpm_powergate_samu(struct amdgpu_device *adev, bool gate); static void kv_dpm_powergate_acp(struct amdgpu_device *adev, bool gate); @@ -1388,7 +1387,8 @@ static void kv_dpm_disable(struct amdgpu_device *adev) kv_dpm_powergate_samu(adev, false); if (pi->caps_vce_pg) /* power on the VCE block */ amdgpu_kv_notify_message_to_smu(adev, PPSMC_MSG_VCEPowerON); - kv_dpm_powergate_uvd(adev, false); + if (pi->caps_uvd_pg) /* power on the UVD block */ + amdgpu_kv_notify_message_to_smu(adev, PPSMC_MSG_UVDPowerON); kv_enable_smc_cac(adev, false); kv_enable_didt(adev, false); From 4a2de54dc1d7668fa364d8483420ba64b120963b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Fri, 24 Aug 2018 14:48:02 +0200 Subject: [PATCH 166/302] drm/amdgpu: fix holding mn_lock while allocating memory MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We can't hold the mn_lock while allocating memory. Signed-off-by: Christian König Acked-by: Chunming Zhou Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 31 ++++++++++++++++---------- 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c index 09703c87d676..b6e9df11115d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c @@ -1203,26 +1203,24 @@ static int amdgpu_cs_submit(struct amdgpu_cs_parser *p, int r; + job = p->job; + p->job = NULL; + + r = drm_sched_job_init(&job->base, entity, p->filp); + if (r) + goto error_unlock; + + /* No memory allocation is allowed while holding the mn lock */ amdgpu_mn_lock(p->mn); amdgpu_bo_list_for_each_userptr_entry(e, p->bo_list) { struct amdgpu_bo *bo = e->robj; if (amdgpu_ttm_tt_userptr_needs_pages(bo->tbo.ttm)) { - amdgpu_mn_unlock(p->mn); - return -ERESTARTSYS; + r = -ERESTARTSYS; + goto error_abort; } } - job = p->job; - p->job = NULL; - - r = drm_sched_job_init(&job->base, entity, p->filp); - if (r) { - amdgpu_job_free(job); - amdgpu_mn_unlock(p->mn); - return r; - } - job->owner = p->filp; p->fence = dma_fence_get(&job->base.s_fence->finished); @@ -1260,6 +1258,15 @@ static int amdgpu_cs_submit(struct amdgpu_cs_parser *p, amdgpu_mn_unlock(p->mn); return 0; + +error_abort: + dma_fence_put(&job->base.s_fence->finished); + job->base.s_fence = NULL; + +error_unlock: + amdgpu_job_free(job); + amdgpu_mn_unlock(p->mn); + return r; } int amdgpu_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) From e7603dadd3cc2fa65924d9e8ce0c6f2964866da0 Mon Sep 17 00:00:00 2001 From: SivapiriyanKumarasamy Date: Wed, 15 Aug 2018 16:55:18 -0400 Subject: [PATCH 167/302] drm/amd/display: Fix memory leak caused by missed dc_sink_release [Why] There is currently an intermittent hang from a memory leak in DTN stress testing. It is caused by unfreed memory during driver disable. [How] Do a dc_sink_release in the case that skips it incorrectly. Signed-off-by: SivapiriyanKumarasamy Reviewed-by: Aric Cyr Acked-by: Leo Li Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 567867915d32..37eaf72ace54 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -754,8 +754,12 @@ bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason) * fail-safe mode */ if (dc_is_hdmi_signal(link->connector_signal) || - dc_is_dvi_signal(link->connector_signal)) + dc_is_dvi_signal(link->connector_signal)) { + if (prev_sink != NULL) + dc_sink_release(prev_sink); + return false; + } default: break; } From 2f4e7db0f7456d8312de88d321b889dbd10c18fd Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Thu, 23 Aug 2018 11:46:13 +0800 Subject: [PATCH 168/302] drm/amdgpu: Remove duplicated power source update when ac/dc switch, driver will be notified by acpi event. then the power source will be updated. so don't need to get power source when set power state. Reviewed-by: Alex Deucher Signed-off-by: Rex Zhu Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c index 8f98629fbe59..7b4e657a95c7 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c @@ -1932,14 +1932,6 @@ void amdgpu_pm_compute_clocks(struct amdgpu_device *adev) amdgpu_fence_wait_empty(ring); } - mutex_lock(&adev->pm.mutex); - /* update battery/ac status */ - if (power_supply_is_system_supplied() > 0) - adev->pm.ac_power = true; - else - adev->pm.ac_power = false; - mutex_unlock(&adev->pm.mutex); - if (adev->powerplay.pp_funcs->dispatch_tasks) { if (!amdgpu_device_has_dc_support(adev)) { mutex_lock(&adev->pm.mutex); From 46cb52ad414ac829680d0bb8cc7090ac2b577ca7 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Sun, 15 Jul 2018 22:09:29 +0200 Subject: [PATCH 169/302] ata: ftide010: Add a quirk for SQ201 The DMA is broken on this specific device for some unknown reason (probably badly designed or plain broken interface electronics) and will only work with PIO. Other users of the same hardware does not have this problem. Add a specific quirk so that this Gemini device gets DMA turned off. Also fix up some code around passing the port information around in probe while we're at it. Signed-off-by: Linus Walleij Signed-off-by: Jens Axboe --- drivers/ata/pata_ftide010.c | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/drivers/ata/pata_ftide010.c b/drivers/ata/pata_ftide010.c index 5d4b72e21161..569a4a662dcd 100644 --- a/drivers/ata/pata_ftide010.c +++ b/drivers/ata/pata_ftide010.c @@ -256,14 +256,12 @@ static struct ata_port_operations pata_ftide010_port_ops = { .qc_issue = ftide010_qc_issue, }; -static struct ata_port_info ftide010_port_info[] = { - { - .flags = ATA_FLAG_SLAVE_POSS, - .mwdma_mask = ATA_MWDMA2, - .udma_mask = ATA_UDMA6, - .pio_mask = ATA_PIO4, - .port_ops = &pata_ftide010_port_ops, - }, +static struct ata_port_info ftide010_port_info = { + .flags = ATA_FLAG_SLAVE_POSS, + .mwdma_mask = ATA_MWDMA2, + .udma_mask = ATA_UDMA6, + .pio_mask = ATA_PIO4, + .port_ops = &pata_ftide010_port_ops, }; #if IS_ENABLED(CONFIG_SATA_GEMINI) @@ -349,6 +347,7 @@ static int pata_ftide010_gemini_cable_detect(struct ata_port *ap) } static int pata_ftide010_gemini_init(struct ftide010 *ftide, + struct ata_port_info *pi, bool is_ata1) { struct device *dev = ftide->dev; @@ -373,7 +372,13 @@ static int pata_ftide010_gemini_init(struct ftide010 *ftide, /* Flag port as SATA-capable */ if (gemini_sata_bridge_enabled(sg, is_ata1)) - ftide010_port_info[0].flags |= ATA_FLAG_SATA; + pi->flags |= ATA_FLAG_SATA; + + /* This device has broken DMA, only PIO works */ + if (of_machine_is_compatible("itian,sq201")) { + pi->mwdma_mask = 0; + pi->udma_mask = 0; + } /* * We assume that a simple 40-wire cable is used in the PATA mode. @@ -435,6 +440,7 @@ static int pata_ftide010_gemini_init(struct ftide010 *ftide, } #else static int pata_ftide010_gemini_init(struct ftide010 *ftide, + struct ata_port_info *pi, bool is_ata1) { return -ENOTSUPP; @@ -446,7 +452,7 @@ static int pata_ftide010_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct device_node *np = dev->of_node; - const struct ata_port_info pi = ftide010_port_info[0]; + struct ata_port_info pi = ftide010_port_info; const struct ata_port_info *ppi[] = { &pi, NULL }; struct ftide010 *ftide; struct resource *res; @@ -490,6 +496,7 @@ static int pata_ftide010_probe(struct platform_device *pdev) * are ATA0. This will also set up the cable types. */ ret = pata_ftide010_gemini_init(ftide, + &pi, (res->start == 0x63400000)); if (ret) goto err_dis_clk; From 62d2a1940709198a522a43ff8be8b8f6b3654dec Mon Sep 17 00:00:00 2001 From: Chengguang Xu Date: Tue, 28 Aug 2018 07:31:11 +0800 Subject: [PATCH 170/302] block: remove unnecessary condition check kmem_cache_destroy() can handle NULL pointer correctly, so there is no need to check e->icq_cache before calling kmem_cache_destroy(). Signed-off-by: Chengguang Xu Signed-off-by: Jens Axboe --- block/elevator.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/block/elevator.c b/block/elevator.c index 5ea6e7d600e4..6a06b5d040e5 100644 --- a/block/elevator.c +++ b/block/elevator.c @@ -895,8 +895,7 @@ int elv_register(struct elevator_type *e) spin_lock(&elv_list_lock); if (elevator_find(e->elevator_name, e->uses_mq)) { spin_unlock(&elv_list_lock); - if (e->icq_cache) - kmem_cache_destroy(e->icq_cache); + kmem_cache_destroy(e->icq_cache); return -EBUSY; } list_add_tail(&e->list, &elv_list); From db193954ed9e35701b6e489fa4cc97b08589341b Mon Sep 17 00:00:00 2001 From: John Pittman Date: Mon, 27 Aug 2018 14:33:05 -0400 Subject: [PATCH 171/302] block: bsg: move atomic_t ref_count variable to refcount API Currently, variable ref_count within the bsg_device struct is of type atomic_t. For variables being used as reference counters, the refcount API should be used instead of atomic. The newer refcount API works to prevent counter overflows and use-after-free bugs. So, move this varable from the atomic API to refcount, potentially avoiding the issues mentioned. Signed-off-by: John Pittman Signed-off-by: Jens Axboe --- block/bsg.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/block/bsg.c b/block/bsg.c index db588add6ba6..9a442c23a715 100644 --- a/block/bsg.c +++ b/block/bsg.c @@ -37,7 +37,7 @@ struct bsg_device { struct request_queue *queue; spinlock_t lock; struct hlist_node dev_list; - atomic_t ref_count; + refcount_t ref_count; char name[20]; int max_queue; }; @@ -252,7 +252,7 @@ static int bsg_put_device(struct bsg_device *bd) mutex_lock(&bsg_mutex); - if (!atomic_dec_and_test(&bd->ref_count)) { + if (!refcount_dec_and_test(&bd->ref_count)) { mutex_unlock(&bsg_mutex); return 0; } @@ -290,7 +290,7 @@ static struct bsg_device *bsg_add_device(struct inode *inode, bd->queue = rq; - atomic_set(&bd->ref_count, 1); + refcount_set(&bd->ref_count, 1); hlist_add_head(&bd->dev_list, bsg_dev_idx_hash(iminor(inode))); strncpy(bd->name, dev_name(rq->bsg_dev.class_dev), sizeof(bd->name) - 1); @@ -308,7 +308,7 @@ static struct bsg_device *__bsg_get_device(int minor, struct request_queue *q) hlist_for_each_entry(bd, bsg_dev_idx_hash(minor), dev_list) { if (bd->queue == q) { - atomic_inc(&bd->ref_count); + refcount_inc(&bd->ref_count); goto found; } } From f1ed3df20d2d223e0852cc4ac1f19bba869a7e3c Mon Sep 17 00:00:00 2001 From: Michal Wnukowski Date: Wed, 15 Aug 2018 15:51:57 -0700 Subject: [PATCH 172/302] nvme-pci: add a memory barrier to nvme_dbbuf_update_and_check_event In many architectures loads may be reordered with older stores to different locations. In the nvme driver the following two operations could be reordered: - Write shadow doorbell (dbbuf_db) into memory. - Read EventIdx (dbbuf_ei) from memory. This can result in a potential race condition between driver and VM host processing requests (if given virtual NVMe controller has a support for shadow doorbell). If that occurs, then the NVMe controller may decide to wait for MMIO doorbell from guest operating system, and guest driver may decide not to issue MMIO doorbell on any of subsequent commands. This issue is purely timing-dependent one, so there is no easy way to reproduce it. Currently the easiest known approach is to run "Oracle IO Numbers" (orion) that is shipped with Oracle DB: orion -run advanced -num_large 0 -size_small 8 -type rand -simulate \ concat -write 40 -duration 120 -matrix row -testname nvme_test Where nvme_test is a .lun file that contains a list of NVMe block devices to run test against. Limiting number of vCPUs assigned to given VM instance seems to increase chances for this bug to occur. On test environment with VM that got 4 NVMe drives and 1 vCPU assigned the virtual NVMe controller hang could be observed within 10-20 minutes. That correspond to about 400-500k IO operations processed (or about 100GB of IO read/writes). Orion tool was used as a validation and set to run in a loop for 36 hours (equivalent of pushing 550M IO operations). No issues were observed. That suggest that the patch fixes the issue. Fixes: f9f38e33389c ("nvme: improve performance for virtual NVMe devices") Signed-off-by: Michal Wnukowski Reviewed-by: Keith Busch Reviewed-by: Sagi Grimberg [hch: updated changelog and comment a bit] Signed-off-by: Christoph Hellwig --- drivers/nvme/host/pci.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c index 1b9951d2067e..d668682f91df 100644 --- a/drivers/nvme/host/pci.c +++ b/drivers/nvme/host/pci.c @@ -316,6 +316,14 @@ static bool nvme_dbbuf_update_and_check_event(u16 value, u32 *dbbuf_db, old_value = *dbbuf_db; *dbbuf_db = value; + /* + * Ensure that the doorbell is updated before reading the event + * index from memory. The controller needs to provide similar + * ordering to ensure the envent index is updated before reading + * the doorbell. + */ + mb(); + if (!nvme_dbbuf_need_event(*dbbuf_ei, value, old_value)) return false; } From afd299ca996929f4f98ac20da0044c0cdc124879 Mon Sep 17 00:00:00 2001 From: James Smart Date: Thu, 9 Aug 2018 16:00:14 -0700 Subject: [PATCH 173/302] nvme-fcloop: Fix dropped LS's to removed target port When a targetport is removed from the config, fcloop will avoid calling the LS done() routine thinking the targetport is gone. This leaves the initiator reset/reconnect hanging as it waits for a status on the Create_Association LS for the reconnect. Change the filter in the LS callback path. If tport null (set when failed validation before "sending to remote port"), be sure to call done. This was the main bug. But, continue the logic that only calls done if tport was set but there is no remoteport (e.g. case where remoteport has been removed, thus host doesn't expect a completion). Signed-off-by: James Smart Signed-off-by: Christoph Hellwig --- drivers/nvme/target/fcloop.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/nvme/target/fcloop.c b/drivers/nvme/target/fcloop.c index 34712def81b1..5251689a1d9a 100644 --- a/drivers/nvme/target/fcloop.c +++ b/drivers/nvme/target/fcloop.c @@ -311,7 +311,7 @@ fcloop_tgt_lsrqst_done_work(struct work_struct *work) struct fcloop_tport *tport = tls_req->tport; struct nvmefc_ls_req *lsreq = tls_req->lsreq; - if (tport->remoteport) + if (!tport || tport->remoteport) lsreq->done(lsreq, tls_req->status); } @@ -329,6 +329,7 @@ fcloop_ls_req(struct nvme_fc_local_port *localport, if (!rport->targetport) { tls_req->status = -ECONNREFUSED; + tls_req->tport = NULL; schedule_work(&tls_req->work); return ret; } From 04db0e5ec58167364a80fd33ddb4f3b67434eb85 Mon Sep 17 00:00:00 2001 From: Chaitanya Kulkarni Date: Wed, 15 Aug 2018 18:48:25 -0700 Subject: [PATCH 174/302] nvmet: free workqueue object if module init fails Signed-off-by: Chaitanya Kulkarni Signed-off-by: Christoph Hellwig --- drivers/nvme/target/core.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/nvme/target/core.c b/drivers/nvme/target/core.c index ebf3e7a6c49e..b5ec96abd048 100644 --- a/drivers/nvme/target/core.c +++ b/drivers/nvme/target/core.c @@ -1210,7 +1210,7 @@ static int __init nvmet_init(void) error = nvmet_init_discovery(); if (error) - goto out; + goto out_free_work_queue; error = nvmet_init_configfs(); if (error) @@ -1219,6 +1219,8 @@ static int __init nvmet_init(void) out_exit_discovery: nvmet_exit_discovery(); +out_free_work_queue: + destroy_workqueue(buffered_io_wq); out: return error; } From 496f3347d834aec91c38b45d6249ed00f58ad233 Mon Sep 17 00:00:00 2001 From: Neeraj Dantu Date: Tue, 28 Aug 2018 16:37:58 +0000 Subject: [PATCH 175/302] ARM: dts: Fix file permission for am335x-osd3358-sm-red.dts Fix wrong mode for dts file added by commit bb3e3fbbac86 ("ARM: dts: Add DT support for Octavo Systems OSD3358-SM-RED based on TI AM335x"). Signed-off-by: Neeraj Dantu CC: Robert Nelson CC: Jason Kridner Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/am335x-osd3358-sm-red.dts | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 arch/arm/boot/dts/am335x-osd3358-sm-red.dts diff --git a/arch/arm/boot/dts/am335x-osd3358-sm-red.dts b/arch/arm/boot/dts/am335x-osd3358-sm-red.dts old mode 100755 new mode 100644 From 2d59bb602314a4b2593fde267734266b5e872dd0 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Mon, 27 Aug 2018 19:18:21 -0700 Subject: [PATCH 176/302] ARM: dts: omap4-droid4: Fix emmc errors seen on some devices Otherwise we can get the following errors occasionally on some devices: mmc1: tried to HW reset card, got error -110 mmcblk1: error -110 requesting status mmcblk1: recovery failed! print_req_error: I/O error, dev mmcblk1, sector 14329 ... I have one device that hits this error almost on every boot, and another one that hits it only rarely with the other ones I've used behave without problems. I'm not sure if the issue is related to a particular eMMC card model, but in case it is, both of the machines with issues have: # cat /sys/class/mmc_host/mmc1/mmc1:0001/manfid \ /sys/class/mmc_host/mmc1/mmc1:0001/oemid \ /sys/class/mmc_host/mmc1/mmc1:0001/name 0x000045 0x0100 SEM16G and the working ones have: 0x000011 0x0100 016G92 Note that "ti,non-removable" is different as omap_hsmmc_reg_get() does not call omap_hsmmc_disable_boot_regulators() if no_regulator_off_init is set. And currently we set no_regulator_off_init only for "ti,non-removable" and not for "non-removable". It seems that we should have "non-removable" with some other mmc generic property behave in the same way instead of having to use a non-generic property. But let's fix the issue first. Fixes: 7e2f8c0ae670 ("ARM: dts: Add minimal support for motorola droid 4 xt894") Cc: Marcel Partap Cc: Merlijn Wajer Cc: Michael Scott Cc: NeKit Cc: Pavel Machek Cc: Sebastian Reichel Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/omap4-droid4-xt894.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/omap4-droid4-xt894.dts b/arch/arm/boot/dts/omap4-droid4-xt894.dts index 3c26a4bbc340..04758a2a87f0 100644 --- a/arch/arm/boot/dts/omap4-droid4-xt894.dts +++ b/arch/arm/boot/dts/omap4-droid4-xt894.dts @@ -354,7 +354,7 @@ &mmc1 { &mmc2 { vmmc-supply = <&vsdio>; bus-width = <8>; - non-removable; + ti,non-removable; }; &mmc3 { From 6ddd9769db4fc11a98bd7e58be1764e47fdb8384 Mon Sep 17 00:00:00 2001 From: Emily Deng Date: Tue, 28 Aug 2018 20:52:40 +0800 Subject: [PATCH 177/302] drm/amdgpu: Need to set moved to true when evict bo MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix the VMC page fault when the running sequence is as below: 1.amdgpu_gem_create_ioctl 2.ttm_bo_swapout->amdgpu_vm_bo_invalidate, as not called amdgpu_vm_bo_base_init, so won't called list_add_tail(&base->bo_list, &bo->va). Even the bo was evicted, it won't set the bo_base->moved. 3.drm_gem_open_ioctl->amdgpu_vm_bo_base_init, here only called list_move_tail(&base->vm_status, &vm->evicted), but not set the bo_base->moved. 4.amdgpu_vm_bo_map->amdgpu_vm_bo_insert_map, as the bo_base->moved is not set true, the function amdgpu_vm_bo_insert_map will call list_move(&bo_va->base.vm_status, &vm->moved) 5.amdgpu_cs_ioctl won't validate the swapout bo, as it is only in the moved list, not in the evict list. So VMC page fault occurs. Signed-off-by: Emily Deng Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index d174d50e3bd3..b17771dd5ce7 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -172,6 +172,7 @@ static void amdgpu_vm_bo_base_init(struct amdgpu_vm_bo_base *base, * is validated on next vm use to avoid fault. * */ list_move_tail(&base->vm_status, &vm->evicted); + base->moved = true; } /** From 5b2695fd4b20f9b8320e9ecbfc232842bacf5b6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 19 Jul 2018 21:21:57 +0300 Subject: [PATCH 178/302] drm/i915: Fix glk/cnl display w/a #1175 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The workaround was supposed to look at the plane destination coordinates. Currently it's looking at some mixture of src and dst coordinates that doesn't make sense. Fix it up. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20180719182214.4323-2-ville.syrjala@linux.intel.com Fixes: 394676f05bee (drm/i915: Add WA for planes ending close to left screen edge) Reviewed-by: Imre Deak (cherry picked from commit b1f1c2c11fc6c6cd3e361061e30f9b2839897b28) Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/intel_display.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index ed3fa1c8a983..4a3c8ee9a973 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -2988,6 +2988,7 @@ static int skl_check_main_surface(const struct intel_crtc_state *crtc_state, int w = drm_rect_width(&plane_state->base.src) >> 16; int h = drm_rect_height(&plane_state->base.src) >> 16; int dst_x = plane_state->base.dst.x1; + int dst_w = drm_rect_width(&plane_state->base.dst); int pipe_src_w = crtc_state->pipe_src_w; int max_width = skl_max_plane_width(fb, 0, rotation); int max_height = 4096; @@ -3009,10 +3010,10 @@ static int skl_check_main_surface(const struct intel_crtc_state *crtc_state, * screen may cause FIFO underflow and display corruption. */ if ((IS_GEMINILAKE(dev_priv) || IS_CANNONLAKE(dev_priv)) && - (dst_x + w < 4 || dst_x > pipe_src_w - 4)) { + (dst_x + dst_w < 4 || dst_x > pipe_src_w - 4)) { DRM_DEBUG_KMS("requested plane X %s position %d invalid (valid range %d-%d)\n", - dst_x + w < 4 ? "end" : "start", - dst_x + w < 4 ? dst_x + w : dst_x, + dst_x + dst_w < 4 ? "end" : "start", + dst_x + dst_w < 4 ? dst_x + dst_w : dst_x, 4, pipe_src_w - 4); return -ERANGE; } From 1b1b1162745e5f9e5c6c095afc8081df3edabc50 Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi Date: Thu, 23 Aug 2018 13:51:36 -0700 Subject: [PATCH 179/302] drm/i915: Free write_buf that we allocated with kzalloc. We use kzalloc to allocate the write_buf that we use for i2c transfer on hdcp write. But it seems that we are forgetting to free the memory that is not needed after i2c transfer is completed. Reported-by: Brian J Wood Fixes: 2320175feb74 ("drm/i915: Implement HDCP for HDMI") Cc: Ramalingam C Cc: Sean Paul Cc: Jani Nikula Cc: Rodrigo Vivi Cc: # v4.17+ Signed-off-by: Rodrigo Vivi Reviewed-by: Chris Wilson Link: https://patchwork.freedesktop.org/patch/msgid/20180823205136.31310-1-rodrigo.vivi@intel.com (cherry picked from commit 62d3a8deaa10b8346d979d0dabde56c33b742afa) Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/intel_hdmi.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index a9076402dcb0..192972a7d287 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -943,8 +943,12 @@ static int intel_hdmi_hdcp_write(struct intel_digital_port *intel_dig_port, ret = i2c_transfer(adapter, &msg, 1); if (ret == 1) - return 0; - return ret >= 0 ? -EIO : ret; + ret = 0; + else if (ret >= 0) + ret = -EIO; + + kfree(write_buf); + return ret; } static From 11f65ad111fa29de2d11929f773bf1e553d5b7c4 Mon Sep 17 00:00:00 2001 From: Palmer Dabbelt Date: Mon, 20 Aug 2018 15:47:57 -0700 Subject: [PATCH 180/302] dt-bindings: riscv,cpu-intc: Cleanups from a missed review I managed to miss one of Rob's code reviews on the mailing list . The patch has already been merged, so I'm submitting a fixup. Sorry! Fixes: b67bc7cb4088 ("dt-bindings: interrupt-controller: RISC-V local interrupt controller") Cc: Rob Herring Cc: Christoph Hellwig Cc: Karsten Merker Signed-off-by: Palmer Dabbelt --- .../interrupt-controller/riscv,cpu-intc.txt | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/Documentation/devicetree/bindings/interrupt-controller/riscv,cpu-intc.txt b/Documentation/devicetree/bindings/interrupt-controller/riscv,cpu-intc.txt index b0a8af51c388..265b223cd978 100644 --- a/Documentation/devicetree/bindings/interrupt-controller/riscv,cpu-intc.txt +++ b/Documentation/devicetree/bindings/interrupt-controller/riscv,cpu-intc.txt @@ -11,7 +11,7 @@ The RISC-V supervisor ISA manual specifies three interrupt sources that are attached to every HLIC: software interrupts, the timer interrupt, and external interrupts. Software interrupts are used to send IPIs between cores. The timer interrupt comes from an architecturally mandated real-time timer that is -controller via Supervisor Binary Interface (SBI) calls and CSR reads. External +controlled via Supervisor Binary Interface (SBI) calls and CSR reads. External interrupts connect all other device interrupts to the HLIC, which are routed via the platform-level interrupt controller (PLIC). @@ -25,7 +25,15 @@ in the system. Required properties: - compatible : "riscv,cpu-intc" -- #interrupt-cells : should be <1> +- #interrupt-cells : should be <1>. The interrupt sources are defined by the + RISC-V supervisor ISA manual, with only the following three interrupts being + defined for supervisor mode: + - Source 1 is the supervisor software interrupt, which can be sent by an SBI + call and is reserved for use by software. + - Source 5 is the supervisor timer interrupt, which can be configured by + SBI calls and implements a one-shot timer. + - Source 9 is the supervisor external interrupt, which chains to all other + device interrupts. - interrupt-controller : Identifies the node as an interrupt controller Furthermore, this interrupt-controller MUST be embedded inside the cpu @@ -38,7 +46,7 @@ An example device tree entry for a HLIC is show below. ... cpu1-intc: interrupt-controller { #interrupt-cells = <1>; - compatible = "riscv,cpu-intc", "sifive,fu540-c000-cpu-intc"; + compatible = "sifive,fu540-c000-cpu-intc", "riscv,cpu-intc"; interrupt-controller; }; }; From 0ce5671c4450527f90d2bfb31302f78580587983 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Fri, 24 Aug 2018 11:22:55 -0700 Subject: [PATCH 181/302] riscv: tlb: Provide definition of tlb_flush() before including tlb.h As of commit fd1102f0aade ("mm: mmu_notifier fix for tlb_end_vma"), asm-generic/tlb.h now calls tlb_flush() from a static inline function, so we need to make sure that it's declared before #including the asm-generic header in the arch header. Reported-by: Guenter Roeck Fixes: fd1102f0aade ("mm: mmu_notifier fix for tlb_end_vma") Signed-off-by: Will Deacon [groeck: Use forward declaration instead of moving inline function] Signed-off-by: Guenter Roeck Signed-off-by: Palmer Dabbelt --- arch/riscv/include/asm/tlb.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/riscv/include/asm/tlb.h b/arch/riscv/include/asm/tlb.h index c229509288ea..439dc7072e05 100644 --- a/arch/riscv/include/asm/tlb.h +++ b/arch/riscv/include/asm/tlb.h @@ -14,6 +14,10 @@ #ifndef _ASM_RISCV_TLB_H #define _ASM_RISCV_TLB_H +struct mmu_gather; + +static void tlb_flush(struct mmu_gather *tlb); + #include static inline void tlb_flush(struct mmu_gather *tlb) From 47d80a68f10d3290204a12f7836a9a8190dfc327 Mon Sep 17 00:00:00 2001 From: Palmer Dabbelt Date: Tue, 28 Aug 2018 09:37:16 -0700 Subject: [PATCH 182/302] RISC-V: Use a less ugly workaround for unused variable warnings Thanks to Christoph Hellwig for pointing out a cleaner way to do this, as my approach was quite ugly. CC: Christoph Hellwig Signed-off-by: Palmer Dabbelt --- arch/riscv/kernel/sys_riscv.c | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/arch/riscv/kernel/sys_riscv.c b/arch/riscv/kernel/sys_riscv.c index 568026ccf6e8..fb03a4482ad6 100644 --- a/arch/riscv/kernel/sys_riscv.c +++ b/arch/riscv/kernel/sys_riscv.c @@ -65,24 +65,11 @@ SYSCALL_DEFINE6(mmap2, unsigned long, addr, unsigned long, len, SYSCALL_DEFINE3(riscv_flush_icache, uintptr_t, start, uintptr_t, end, uintptr_t, flags) { -#ifdef CONFIG_SMP - struct mm_struct *mm = current->mm; - bool local = (flags & SYS_RISCV_FLUSH_ICACHE_LOCAL) != 0; -#endif - /* Check the reserved flags. */ if (unlikely(flags & ~SYS_RISCV_FLUSH_ICACHE_ALL)) return -EINVAL; - /* - * Without CONFIG_SMP flush_icache_mm is a just a flush_icache_all(), - * which generates unused variable warnings all over this function. - */ -#ifdef CONFIG_SMP - flush_icache_mm(mm, local); -#else - flush_icache_all(); -#endif + flush_icache_mm(current->mm, flags & SYS_RISCV_FLUSH_ICACHE_LOCAL); return 0; } From 076e2cedd6ea4786569c35f8725b4efdc1ecf2f2 Mon Sep 17 00:00:00 2001 From: Joe Jin Date: Tue, 28 Aug 2018 07:56:08 -0700 Subject: [PATCH 183/302] xen: export device state to sysfs Export device state to sysfs to allow for easier get device state. Signed-off-by: Joe Jin Reviewed-by: Boris Ostrovsky Cc: Boris Ostrovsky Cc: Juergen Gross Cc: Konrad Rzeszutek Wilk Signed-off-by: Boris Ostrovsky --- Documentation/ABI/stable/sysfs-bus-xen-backend | 9 +++++++++ drivers/xen/xenbus/xenbus_probe.c | 9 +++++++++ 2 files changed, 18 insertions(+) diff --git a/Documentation/ABI/stable/sysfs-bus-xen-backend b/Documentation/ABI/stable/sysfs-bus-xen-backend index 3d5951c8bf5f..e8b60bd766f7 100644 --- a/Documentation/ABI/stable/sysfs-bus-xen-backend +++ b/Documentation/ABI/stable/sysfs-bus-xen-backend @@ -73,3 +73,12 @@ KernelVersion: 3.0 Contact: Konrad Rzeszutek Wilk Description: Number of sectors written by the frontend. + +What: /sys/bus/xen-backend/devices/*/state +Date: August 2018 +KernelVersion: 4.19 +Contact: Joe Jin +Description: + The state of the device. One of: 'Unknown', + 'Initialising', 'Initialised', 'Connected', 'Closing', + 'Closed', 'Reconfiguring', 'Reconfigured'. diff --git a/drivers/xen/xenbus/xenbus_probe.c b/drivers/xen/xenbus/xenbus_probe.c index f2088838f690..5b471889d723 100644 --- a/drivers/xen/xenbus/xenbus_probe.c +++ b/drivers/xen/xenbus/xenbus_probe.c @@ -402,10 +402,19 @@ static ssize_t modalias_show(struct device *dev, } static DEVICE_ATTR_RO(modalias); +static ssize_t state_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return sprintf(buf, "%s\n", + xenbus_strstate(to_xenbus_device(dev)->state)); +} +static DEVICE_ATTR_RO(state); + static struct attribute *xenbus_dev_attrs[] = { &dev_attr_nodename.attr, &dev_attr_devtype.attr, &dev_attr_modalias.attr, + &dev_attr_state.attr, NULL, }; From 6d3c8ce012cefbdd73a3bba3c7f9a44af1c6a0bb Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Tue, 28 Aug 2018 17:10:46 +0100 Subject: [PATCH 184/302] x86/xen: remove redundant variable save_pud Variable save_pud is being assigned but is never used hence it is redundant and can be removed. Cleans up clang warning: variable 'save_pud' set but not used [-Wunused-but-set-variable] Signed-off-by: Colin Ian King Reviewed-by: Boris Ostrovsky Signed-off-by: Boris Ostrovsky --- arch/x86/xen/mmu_pv.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/arch/x86/xen/mmu_pv.c b/arch/x86/xen/mmu_pv.c index 9396b4d17064..ede298c183e9 100644 --- a/arch/x86/xen/mmu_pv.c +++ b/arch/x86/xen/mmu_pv.c @@ -2059,7 +2059,6 @@ void __init xen_relocate_p2m(void) pud_t *pud; pgd_t *pgd; unsigned long *new_p2m; - int save_pud; size = PAGE_ALIGN(xen_start_info->nr_pages * sizeof(unsigned long)); n_pte = roundup(size, PAGE_SIZE) >> PAGE_SHIFT; @@ -2089,7 +2088,6 @@ void __init xen_relocate_p2m(void) pgd = __va(read_cr3_pa()); new_p2m = (unsigned long *)(2 * PGDIR_SIZE); - save_pud = n_pud; for (idx_pud = 0; idx_pud < n_pud; idx_pud++) { pud = early_memremap(pud_phys, PAGE_SIZE); clear_page(pud); From 450b6b9b169382205f88858541a8b79830262ce7 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Thu, 23 Aug 2018 18:06:54 -0500 Subject: [PATCH 185/302] clk: npcm7xx: fix memory allocation One of the more common cases of allocation size calculations is finding the size of a structure that has a zero-sized array at the end, along with memory for some number of elements for that array. For example: struct foo { int stuff; void *entry[]; }; instance = kzalloc(sizeof(struct foo) + sizeof(void *) * count, GFP_KERNEL); Instead of leaving these open-coded and prone to type mistakes, we can now use the new struct_size() helper: instance = kzalloc(struct_size(instance, entry, count), GFP_KERNEL); Notice that, currently, there is a bug during the allocation: sizeof(npcm7xx_clk_data) should be sizeof(*npcm7xx_clk_data) Fix this bug by using struct_size() in kzalloc() This issue was detected with the help of Coccinelle. Cc: stable@vger.kernel.org Signed-off-by: Gustavo A. R. Silva Reviewed-by: Kees Cook Reviewed-by: Avi Fishman Signed-off-by: Stephen Boyd --- drivers/clk/clk-npcm7xx.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/clk/clk-npcm7xx.c b/drivers/clk/clk-npcm7xx.c index 740af90a9508..c5edf8f2fd19 100644 --- a/drivers/clk/clk-npcm7xx.c +++ b/drivers/clk/clk-npcm7xx.c @@ -558,8 +558,8 @@ static void __init npcm7xx_clk_init(struct device_node *clk_np) if (!clk_base) goto npcm7xx_init_error; - npcm7xx_clk_data = kzalloc(sizeof(*npcm7xx_clk_data->hws) * - NPCM7XX_NUM_CLOCKS + sizeof(npcm7xx_clk_data), GFP_KERNEL); + npcm7xx_clk_data = kzalloc(struct_size(npcm7xx_clk_data, hws, + NPCM7XX_NUM_CLOCKS), GFP_KERNEL); if (!npcm7xx_clk_data) goto npcm7xx_init_np_err; From afce0cc9ad8aa510650e781a51e43c26e2a34cf6 Mon Sep 17 00:00:00 2001 From: Julien Grall Date: Tue, 14 Aug 2018 11:33:32 +0100 Subject: [PATCH 186/302] Documentation/arm64/sve: Couple of improvements and typos - Fix mismatch between SVE registers (Z) and FPSIMD register (V) - Don't prefix the path for [3] with Linux to stay consistent with [1] and [2]. Signed-off-by: Julien Grall Signed-off-by: Will Deacon --- Documentation/arm64/sve.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/arm64/sve.txt b/Documentation/arm64/sve.txt index f128f736b4a5..7169a0ec41d8 100644 --- a/Documentation/arm64/sve.txt +++ b/Documentation/arm64/sve.txt @@ -200,7 +200,7 @@ prctl(PR_SVE_SET_VL, unsigned long arg) thread. * Changing the vector length causes all of P0..P15, FFR and all bits of - Z0..V31 except for Z0 bits [127:0] .. Z31 bits [127:0] to become + Z0..Z31 except for Z0 bits [127:0] .. Z31 bits [127:0] to become unspecified. Calling PR_SVE_SET_VL with vl equal to the thread's current vector length, or calling PR_SVE_SET_VL with the PR_SVE_SET_VL_ONEXEC flag, does not constitute a change to the vector length for this purpose. @@ -500,7 +500,7 @@ References [2] arch/arm64/include/uapi/asm/ptrace.h AArch64 Linux ptrace ABI definitions -[3] linux/Documentation/arm64/cpu-feature-registers.txt +[3] Documentation/arm64/cpu-feature-registers.txt [4] ARM IHI0055C http://infocenter.arm.com/help/topic/com.arm.doc.ihi0055c/IHI0055C_beta_aapcs64.pdf From 1d8f574708a3fb6f18c85486d0c5217df893c0cf Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Fri, 24 Aug 2018 15:08:29 +0100 Subject: [PATCH 187/302] arm/arm64: smccc-1.1: Make return values unsigned long An unfortunate consequence of having a strong typing for the input values to the SMC call is that it also affects the type of the return values, limiting r0 to 32 bits and r{1,2,3} to whatever was passed as an input. Let's turn everything into "unsigned long", which satisfies the requirements of both architectures, and allows for the full range of return values. Reported-by: Julien Grall Signed-off-by: Marc Zyngier Signed-off-by: Will Deacon --- include/linux/arm-smccc.h | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h index ca1d2cc2cdfa..5a91ff33720b 100644 --- a/include/linux/arm-smccc.h +++ b/include/linux/arm-smccc.h @@ -199,31 +199,31 @@ asmlinkage void __arm_smccc_hvc(unsigned long a0, unsigned long a1, #define __declare_arg_0(a0, res) \ struct arm_smccc_res *___res = res; \ - register u32 r0 asm("r0") = a0; \ + register unsigned long r0 asm("r0") = (u32)a0; \ register unsigned long r1 asm("r1"); \ register unsigned long r2 asm("r2"); \ register unsigned long r3 asm("r3") #define __declare_arg_1(a0, a1, res) \ struct arm_smccc_res *___res = res; \ - register u32 r0 asm("r0") = a0; \ - register typeof(a1) r1 asm("r1") = a1; \ + register unsigned long r0 asm("r0") = (u32)a0; \ + register unsigned long r1 asm("r1") = a1; \ register unsigned long r2 asm("r2"); \ register unsigned long r3 asm("r3") #define __declare_arg_2(a0, a1, a2, res) \ struct arm_smccc_res *___res = res; \ - register u32 r0 asm("r0") = a0; \ - register typeof(a1) r1 asm("r1") = a1; \ - register typeof(a2) r2 asm("r2") = a2; \ + register unsigned long r0 asm("r0") = (u32)a0; \ + register unsigned long r1 asm("r1") = a1; \ + register unsigned long r2 asm("r2") = a2; \ register unsigned long r3 asm("r3") #define __declare_arg_3(a0, a1, a2, a3, res) \ struct arm_smccc_res *___res = res; \ - register u32 r0 asm("r0") = a0; \ - register typeof(a1) r1 asm("r1") = a1; \ - register typeof(a2) r2 asm("r2") = a2; \ - register typeof(a3) r3 asm("r3") = a3 + register unsigned long r0 asm("r0") = (u32)a0; \ + register unsigned long r1 asm("r1") = a1; \ + register unsigned long r2 asm("r2") = a2; \ + register unsigned long r3 asm("r3") = a3 #define __declare_arg_4(a0, a1, a2, a3, a4, res) \ __declare_arg_3(a0, a1, a2, a3, res); \ From 36156f9241cb0f9e37d998052873ca7501ad4b36 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 27 Aug 2018 10:21:45 +0200 Subject: [PATCH 188/302] of: add helper to lookup compatible child node Add of_get_compatible_child() helper that can be used to lookup compatible child nodes. Several drivers currently use of_find_compatible_node() to lookup child nodes while failing to notice that the of_find_ functions search the entire tree depth-first (from a given start node) and therefore can match unrelated nodes. The fact that these functions also drop a reference to the node they start searching from (e.g. the parent node) is typically also overlooked, something which can lead to use-after-free bugs. Signed-off-by: Johan Hovold Signed-off-by: Rob Herring --- drivers/of/base.c | 25 +++++++++++++++++++++++++ include/linux/of.h | 8 ++++++++ 2 files changed, 33 insertions(+) diff --git a/drivers/of/base.c b/drivers/of/base.c index 466e3c8582f0..bc420d2aa5f5 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -719,6 +719,31 @@ struct device_node *of_get_next_available_child(const struct device_node *node, } EXPORT_SYMBOL(of_get_next_available_child); +/** + * of_get_compatible_child - Find compatible child node + * @parent: parent node + * @compatible: compatible string + * + * Lookup child node whose compatible property contains the given compatible + * string. + * + * Returns a node pointer with refcount incremented, use of_node_put() on it + * when done; or NULL if not found. + */ +struct device_node *of_get_compatible_child(const struct device_node *parent, + const char *compatible) +{ + struct device_node *child; + + for_each_child_of_node(parent, child) { + if (of_device_is_compatible(child, compatible)) + break; + } + + return child; +} +EXPORT_SYMBOL(of_get_compatible_child); + /** * of_get_child_by_name - Find the child node by name for a given parent * @node: parent node diff --git a/include/linux/of.h b/include/linux/of.h index 4d25e4f952d9..b99a1a8c2952 100644 --- a/include/linux/of.h +++ b/include/linux/of.h @@ -290,6 +290,8 @@ extern struct device_node *of_get_next_child(const struct device_node *node, extern struct device_node *of_get_next_available_child( const struct device_node *node, struct device_node *prev); +extern struct device_node *of_get_compatible_child(const struct device_node *parent, + const char *compatible); extern struct device_node *of_get_child_by_name(const struct device_node *node, const char *name); @@ -632,6 +634,12 @@ static inline bool of_have_populated_dt(void) return false; } +static inline struct device_node *of_get_compatible_child(const struct device_node *parent, + const char *compatible) +{ + return NULL; +} + static inline struct device_node *of_get_child_by_name( const struct device_node *node, const char *name) From 8f3fafc9c2f0ece10832c25f7ffcb07c97a32ad4 Mon Sep 17 00:00:00 2001 From: Scott Bauer Date: Thu, 26 Apr 2018 11:51:08 -0600 Subject: [PATCH 189/302] cdrom: Fix info leak/OOB read in cdrom_ioctl_drive_status Like d88b6d04: "cdrom: information leak in cdrom_ioctl_media_changed()" There is another cast from unsigned long to int which causes a bounds check to fail with specially crafted input. The value is then used as an index in the slot array in cdrom_slot_status(). Signed-off-by: Scott Bauer Signed-off-by: Scott Bauer Cc: stable@vger.kernel.org Signed-off-by: Jens Axboe --- drivers/cdrom/cdrom.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c index 113fc6edb2b0..a5d5a96479bf 100644 --- a/drivers/cdrom/cdrom.c +++ b/drivers/cdrom/cdrom.c @@ -2546,7 +2546,7 @@ static int cdrom_ioctl_drive_status(struct cdrom_device_info *cdi, if (!CDROM_CAN(CDC_SELECT_DISC) || (arg == CDSL_CURRENT || arg == CDSL_NONE)) return cdi->ops->drive_status(cdi, CDSL_CURRENT); - if (((int)arg >= cdi->capacity)) + if (arg >= cdi->capacity) return -EINVAL; return cdrom_slot_status(cdi, arg); } From 74081c9f16a213f8f2681c175dc6ad7d17ad16ba Mon Sep 17 00:00:00 2001 From: Fabrizio Castro Date: Tue, 14 Aug 2018 13:33:48 +0100 Subject: [PATCH 190/302] dt-bindings: watchdog: renesas-wdt: Document r8a774a1 support RZ/G2M (R8A774A1) watchdog implementation is compatible with R-Car Gen3, therefore add relevant documentation. Signed-off-by: Fabrizio Castro Reviewed-by: Biju Das Reviewed-by: Rob Herring Reviewed-by: Simon Horman Reviewed-by: Guenter Roeck Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- Documentation/devicetree/bindings/watchdog/renesas-wdt.txt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/watchdog/renesas-wdt.txt b/Documentation/devicetree/bindings/watchdog/renesas-wdt.txt index 5d47a262474c..9407212a85a8 100644 --- a/Documentation/devicetree/bindings/watchdog/renesas-wdt.txt +++ b/Documentation/devicetree/bindings/watchdog/renesas-wdt.txt @@ -7,6 +7,7 @@ Required properties: Examples with soctypes are: - "renesas,r8a7743-wdt" (RZ/G1M) - "renesas,r8a7745-wdt" (RZ/G1E) + - "renesas,r8a774a1-wdt" (RZ/G2M) - "renesas,r8a7790-wdt" (R-Car H2) - "renesas,r8a7791-wdt" (R-Car M2-W) - "renesas,r8a7792-wdt" (R-Car V2H) @@ -21,8 +22,8 @@ Required properties: - "renesas,r7s72100-wdt" (RZ/A1) The generic compatible string must be: - "renesas,rza-wdt" for RZ/A - - "renesas,rcar-gen2-wdt" for R-Car Gen2 and RZ/G - - "renesas,rcar-gen3-wdt" for R-Car Gen3 + - "renesas,rcar-gen2-wdt" for R-Car Gen2 and RZ/G1 + - "renesas,rcar-gen3-wdt" for R-Car Gen3 and RZ/G2 - reg : Should contain WDT registers location and length - clocks : the clock feeding the watchdog timer. From 1dbd150d04f11a6e8d03c80132167e8d3391f8ce Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 27 Aug 2018 15:27:08 +0200 Subject: [PATCH 191/302] ARM: defconfig: Update the ARM Versatile defconfig This updates the ARM Versatile defconfig to the latest Kconfig structural changes and adds the DUMB VGA bridge driver so that VGA works out of the box, e.g. with QEMU. Signed-off-by: Linus Walleij Signed-off-by: Olof Johansson --- arch/arm/configs/versatile_defconfig | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/arch/arm/configs/versatile_defconfig b/arch/arm/configs/versatile_defconfig index df68dc4056e5..5282324c7cef 100644 --- a/arch/arm/configs/versatile_defconfig +++ b/arch/arm/configs/versatile_defconfig @@ -5,19 +5,19 @@ CONFIG_HIGH_RES_TIMERS=y CONFIG_LOG_BUF_SHIFT=14 CONFIG_BLK_DEV_INITRD=y CONFIG_SLAB=y -CONFIG_MODULES=y -CONFIG_MODULE_UNLOAD=y -CONFIG_PARTITION_ADVANCED=y # CONFIG_ARCH_MULTI_V7 is not set CONFIG_ARCH_VERSATILE=y CONFIG_AEABI=y CONFIG_OABI_COMPAT=y -CONFIG_CMA=y CONFIG_ZBOOT_ROM_TEXT=0x0 CONFIG_ZBOOT_ROM_BSS=0x0 CONFIG_CMDLINE="root=1f03 mem=32M" CONFIG_FPE_NWFPE=y CONFIG_VFP=y +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +CONFIG_PARTITION_ADVANCED=y +CONFIG_CMA=y CONFIG_NET=y CONFIG_PACKET=y CONFIG_UNIX=y @@ -59,6 +59,7 @@ CONFIG_GPIO_PL061=y CONFIG_DRM=y CONFIG_DRM_PANEL_ARM_VERSATILE=y CONFIG_DRM_PANEL_SIMPLE=y +CONFIG_DRM_DUMB_VGA_DAC=y CONFIG_DRM_PL111=y CONFIG_FB_MODE_HELPERS=y CONFIG_BACKLIGHT_LCD_SUPPORT=y @@ -89,9 +90,10 @@ CONFIG_NFSD=y CONFIG_NFSD_V3=y CONFIG_NLS_CODEPAGE_850=m CONFIG_NLS_ISO8859_1=m +CONFIG_FONTS=y +CONFIG_FONT_ACORN_8x8=y +CONFIG_DEBUG_FS=y CONFIG_MAGIC_SYSRQ=y CONFIG_DEBUG_KERNEL=y CONFIG_DEBUG_USER=y CONFIG_DEBUG_LL=y -CONFIG_FONTS=y -CONFIG_FONT_ACORN_8x8=y From 67e6ddb5be440a92b82e87ca0ab8f973ae31b12c Mon Sep 17 00:00:00 2001 From: Nishanth Menon Date: Mon, 27 Aug 2018 19:46:50 -0500 Subject: [PATCH 192/302] arm64: defconfig: Enable TI's AM6 SoC platform Enable K3 SoC platform for TI's AM6 SoC. Signed-off-by: Nishanth Menon Acked-by: Tony Lindgren Signed-off-by: Olof Johansson --- arch/arm64/configs/defconfig | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index f67e8d5e93ad..db8d364f8476 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -38,6 +38,7 @@ CONFIG_ARCH_BCM_IPROC=y CONFIG_ARCH_BERLIN=y CONFIG_ARCH_BRCMSTB=y CONFIG_ARCH_EXYNOS=y +CONFIG_ARCH_K3=y CONFIG_ARCH_LAYERSCAPE=y CONFIG_ARCH_LG1K=y CONFIG_ARCH_HISI=y @@ -605,6 +606,8 @@ CONFIG_ARCH_TEGRA_132_SOC=y CONFIG_ARCH_TEGRA_210_SOC=y CONFIG_ARCH_TEGRA_186_SOC=y CONFIG_ARCH_TEGRA_194_SOC=y +CONFIG_ARCH_K3_AM6_SOC=y +CONFIG_SOC_TI=y CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND=y CONFIG_EXTCON_USB_GPIO=y CONFIG_EXTCON_USBC_CROS_EC=y From f013027e266553effa3e9d9d62236ae5ee3b25e7 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 16 Aug 2018 08:34:46 +0100 Subject: [PATCH 193/302] drm/i915: Stop holding a ref to the ppgtt from each vma The context owns both the ppgtt and the vma within it, and our activity tracking on the context ensures that we do not release active ppgtt. As the context fulfils our obligations for active memory tracking, we can relinquish the reference from the vma. This fixes a silly transient refleak from closed vma being kept alive until the entire system was idle, keeping all vm alive as well. Reported-by: Paulo Zanoni Testcase: igt/gem_ctx_create/files Fixes: 3365e2268b6b ("drm/i915: Lazily unbind vma on close") Signed-off-by: Chris Wilson Cc: Tvrtko Ursulin Cc: Paulo Zanoni Reviewed-by: Mika Kuoppala Tested-by: Mika Kuoppala Link: https://patchwork.freedesktop.org/patch/msgid/20180816073448.19396-1-chris@chris-wilson.co.uk (cherry picked from commit a4417b7b419a68540ad7945ac4efbb39d19afa63) Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/i915_vma.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_vma.c b/drivers/gpu/drm/i915/i915_vma.c index 11d834f94220..98358b4b36de 100644 --- a/drivers/gpu/drm/i915/i915_vma.c +++ b/drivers/gpu/drm/i915/i915_vma.c @@ -199,7 +199,6 @@ vma_create(struct drm_i915_gem_object *obj, vma->flags |= I915_VMA_GGTT; list_add(&vma->obj_link, &obj->vma_list); } else { - i915_ppgtt_get(i915_vm_to_ppgtt(vm)); list_add_tail(&vma->obj_link, &obj->vma_list); } @@ -807,9 +806,6 @@ static void __i915_vma_destroy(struct i915_vma *vma) if (vma->obj) rb_erase(&vma->obj_node, &vma->obj->vma_tree); - if (!i915_vma_is_ggtt(vma)) - i915_ppgtt_put(i915_vm_to_ppgtt(vma->vm)); - rbtree_postorder_for_each_entry_safe(iter, n, &vma->active, node) { GEM_BUG_ON(i915_gem_active_isset(&iter->base)); kfree(iter); From 299c2a904b1e8d5096d4813df6371357d97a6cd1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Sch=C3=B6n?= Date: Fri, 17 Aug 2018 22:07:28 +0200 Subject: [PATCH 194/302] drm/i915: Increase LSPCON timeout MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 100 ms is not enough time for the LSPCON adapter on Intel NUC devices to settle. This causes dropped display modes at boot or screen reconfiguration. Empirical testing can reproduce the error up to a timeout of 190 ms. Basic boot and stress testing at 200 ms has not (yet) failed. Increase timeout to 400 ms to get some margin of error. Changes from v1: The initial suggestion of 1000 ms was lowered due to concerns about delaying valid timeout cases. Update patch metadata. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=107503 Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1570392 Fixes: 357c0ae9198a ("drm/i915/lspcon: Wait for expected LSPCON mode to settle") Cc: Shashank Sharma Cc: Imre Deak Cc: Jani Nikula Cc: # v4.11+ Reviewed-by: Rodrigo Vivi Reviewed-by: Shashank Sharma Signed-off-by: Fredrik Schön Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20180817200728.8154-1-fredrik.schon@gmail.com (cherry picked from commit 59f1c8ab30d6f9042562949f42cbd3f3cf69de94) Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/intel_lspcon.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_lspcon.c b/drivers/gpu/drm/i915/intel_lspcon.c index 5dae16ccd9f1..3e085c5f2b81 100644 --- a/drivers/gpu/drm/i915/intel_lspcon.c +++ b/drivers/gpu/drm/i915/intel_lspcon.c @@ -74,7 +74,7 @@ static enum drm_lspcon_mode lspcon_wait_mode(struct intel_lspcon *lspcon, DRM_DEBUG_KMS("Waiting for LSPCON mode %s to settle\n", lspcon_mode_name(mode)); - wait_for((current_mode = lspcon_get_current_mode(lspcon)) == mode, 100); + wait_for((current_mode = lspcon_get_current_mode(lspcon)) == mode, 400); if (current_mode != mode) DRM_ERROR("LSPCON mode hasn't settled\n"); From 80ab316901bc4ae6dd0b5903dbe22766307eac9b Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 17 Aug 2018 11:02:41 +0100 Subject: [PATCH 195/302] drm/i915/audio: Hook up component bindings even if displays are disabled If the display has been disabled by modparam, we still want to connect together the HW bits and bobs with the associated drivers so that we can continue to manage their runtime power gating. Fixes: 108109444ff6 ("drm/i915: Check num_pipes before initializing audio component") Signed-off-by: Chris Wilson Cc: Imre Deak Cc: Takashi Iwai Cc: Jani Nikula Cc: Elaine Wang Reviewed-by: Imre Deak Link: https://patchwork.freedesktop.org/patch/msgid/20180817100241.4628-1-chris@chris-wilson.co.uk (cherry picked from commit 35a5fd9ebfa93758ca579e30f337b6c9126d995b) Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/intel_audio.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_audio.c b/drivers/gpu/drm/i915/intel_audio.c index b725835b47ef..769f3f586661 100644 --- a/drivers/gpu/drm/i915/intel_audio.c +++ b/drivers/gpu/drm/i915/intel_audio.c @@ -962,9 +962,6 @@ void i915_audio_component_init(struct drm_i915_private *dev_priv) { int ret; - if (INTEL_INFO(dev_priv)->num_pipes == 0) - return; - ret = component_add(dev_priv->drm.dev, &i915_audio_component_bind_ops); if (ret < 0) { DRM_ERROR("failed to add audio component (%d)\n", ret); From ff69279a44e9ba876466b7d3ab84d6dbd31cac92 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Wed, 29 Aug 2018 08:47:53 +0200 Subject: [PATCH 196/302] powerpc: disable support for relative ksymtab references The newly added code that emits ksymtab entries as pairs of 32-bit relative references interacts poorly with the way powerpc lays out its address space: when a module exports a per-CPU variable, the primary module region covering the ksymtab entry -and thus the 32-bit relative reference- is too far away from the actual per-CPU variable's base address (to which the per-CPU offsets are applied to obtain the respective address of each CPU's copy), resulting in corruption when the module loader attempts to resolve symbol references of modules that are loaded on top and link to the exported per-CPU symbol. So let's disable this feature on powerpc. Even though it implements CONFIG_RELOCATABLE, it does not implement CONFIG_RANDOMIZE_BASE and so KASLR kernels (which are the main target of the feature) do not exist on powerpc anyway. Reported-by: Andreas Schwab Suggested-by: Nicholas Piggin Signed-off-by: Ard Biesheuvel Signed-off-by: Linus Torvalds --- arch/powerpc/Kconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index db0b6eebbfa5..a80669209155 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -177,7 +177,6 @@ config PPC select HAVE_ARCH_KGDB select HAVE_ARCH_MMAP_RND_BITS select HAVE_ARCH_MMAP_RND_COMPAT_BITS if COMPAT - select HAVE_ARCH_PREL32_RELOCATIONS select HAVE_ARCH_SECCOMP_FILTER select HAVE_ARCH_TRACEHOOK select HAVE_CBPF_JIT if !PPC64 From 36bf9da2913054c218337d8cd7cb11bddc1fafb0 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Mon, 27 Aug 2018 14:45:14 +0900 Subject: [PATCH 197/302] x86/build: Remove jump label quirk for GCC older than 4.5.2 Commit cafa0010cd51 ("Raise the minimum required gcc version to 4.6") bumped the minimum GCC version to 4.6 for all architectures. Remove the workaround code. It was the only user of cc-if-fullversion. Remove the macro as well. Signed-off-by: Masahiro Yamada Signed-off-by: Thomas Gleixner Cc: "H. Peter Anvin" Cc: Michal Marek Cc: linux-kbuild@vger.kernel.org Link: https://lkml.kernel.org/r/1535348714-25457-1-git-send-email-yamada.masahiro@socionext.com --- arch/x86/Makefile | 12 ------------ scripts/Kbuild.include | 4 ---- 2 files changed, 16 deletions(-) diff --git a/arch/x86/Makefile b/arch/x86/Makefile index 94859241bc3e..8fc8f94ef5f5 100644 --- a/arch/x86/Makefile +++ b/arch/x86/Makefile @@ -179,18 +179,6 @@ ifndef CC_HAVE_ASM_GOTO $(error Compiler lacks asm-goto support.) endif -# -# Jump labels need '-maccumulate-outgoing-args' for gcc < 4.5.2 to prevent a -# GCC bug (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=46226). There's no way -# to test for this bug at compile-time because the test case needs to execute, -# which is a no-go for cross compilers. So check the GCC version instead. -# -ifdef CONFIG_JUMP_LABEL - ifneq ($(ACCUMULATE_OUTGOING_ARGS), 1) - ACCUMULATE_OUTGOING_ARGS = $(call cc-if-fullversion, -lt, 040502, 1) - endif -endif - ifeq ($(ACCUMULATE_OUTGOING_ARGS), 1) # This compiler flag is not supported by Clang: KBUILD_CFLAGS += $(call cc-option,-maccumulate-outgoing-args,) diff --git a/scripts/Kbuild.include b/scripts/Kbuild.include index c75413d05a63..ce53639a864a 100644 --- a/scripts/Kbuild.include +++ b/scripts/Kbuild.include @@ -153,10 +153,6 @@ cc-fullversion = $(shell $(CONFIG_SHELL) \ # Usage: EXTRA_CFLAGS += $(call cc-ifversion, -lt, 0402, -O1) cc-ifversion = $(shell [ $(cc-version) $(1) $(2) ] && echo $(3) || echo $(4)) -# cc-if-fullversion -# Usage: EXTRA_CFLAGS += $(call cc-if-fullversion, -lt, 040502, -O1) -cc-if-fullversion = $(shell [ $(cc-fullversion) $(1) $(2) ] && echo $(3) || echo $(4)) - # cc-ldoption # Usage: ldflags += $(call cc-ldoption, -Wl$(comma)--hash-style=both) cc-ldoption = $(call try-run,\ From 1f59a4581b5ecfe9b4f049a7a2cf904d8352842d Mon Sep 17 00:00:00 2001 From: Nick Desaulniers Date: Mon, 27 Aug 2018 14:40:09 -0700 Subject: [PATCH 198/302] x86/irqflags: Mark native_restore_fl extern inline This should have been marked extern inline in order to pick up the out of line definition in arch/x86/kernel/irqflags.S. Fixes: 208cbb325589 ("x86/irqflags: Provide a declaration for native_save_fl") Reported-by: Ben Hutchings Signed-off-by: Nick Desaulniers Signed-off-by: Thomas Gleixner Reviewed-by: Juergen Gross Cc: "H. Peter Anvin" Cc: Boris Ostrovsky Cc: Greg Kroah-Hartman Cc: stable@vger.kernel.org Link: https://lkml.kernel.org/r/20180827214011.55428-1-ndesaulniers@google.com --- arch/x86/include/asm/irqflags.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/x86/include/asm/irqflags.h b/arch/x86/include/asm/irqflags.h index c14f2a74b2be..15450a675031 100644 --- a/arch/x86/include/asm/irqflags.h +++ b/arch/x86/include/asm/irqflags.h @@ -33,7 +33,8 @@ extern inline unsigned long native_save_fl(void) return flags; } -static inline void native_restore_fl(unsigned long flags) +extern inline void native_restore_fl(unsigned long flags); +extern inline void native_restore_fl(unsigned long flags) { asm volatile("push %0 ; popf" : /* no output */ From f12d11c5c184626b4befdee3d573ec8237405a33 Mon Sep 17 00:00:00 2001 From: Jann Horn Date: Tue, 28 Aug 2018 20:40:33 +0200 Subject: [PATCH 199/302] x86/entry/64: Wipe KASAN stack shadow before rewind_stack_do_exit() Reset the KASAN shadow state of the task stack before rewinding RSP. Without this, a kernel oops will leave parts of the stack poisoned, and code running under do_exit() can trip over such poisoned regions and cause nonsensical false-positive KASAN reports about stack-out-of-bounds bugs. This does not wipe the exception stacks; if an oops happens on an exception stack, it might result in random KASAN false-positives from other tasks afterwards. This is probably relatively uninteresting, since if the kernel oopses on an exception stack, there are most likely bigger things to worry about. It'd be more interesting if vmapped stacks and KASAN were compatible, since then handle_stack_overflow() would oops from exception stack context. Fixes: 2deb4be28077 ("x86/dumpstack: When OOPSing, rewind the stack before do_exit()") Signed-off-by: Jann Horn Signed-off-by: Thomas Gleixner Acked-by: Andrey Ryabinin Cc: Andy Lutomirski Cc: Dmitry Vyukov Cc: Alexander Potapenko Cc: Kees Cook Cc: kasan-dev@googlegroups.com Cc: stable@vger.kernel.org Link: https://lkml.kernel.org/r/20180828184033.93712-1-jannh@google.com --- arch/x86/kernel/dumpstack.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/x86/kernel/dumpstack.c b/arch/x86/kernel/dumpstack.c index 9c8652974f8e..1596e6bfea6f 100644 --- a/arch/x86/kernel/dumpstack.c +++ b/arch/x86/kernel/dumpstack.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -346,7 +347,10 @@ void oops_end(unsigned long flags, struct pt_regs *regs, int signr) * We're not going to return, but we might be on an IST stack or * have very little stack space left. Rewind the stack and kill * the task. + * Before we rewind the stack, we have to tell KASAN that we're going to + * reuse the task stack and that existing poisons are invalid. */ + kasan_unpoison_task_stack(current); rewind_stack_do_exit(signr); } NOKPROBE_SYMBOL(oops_end); From cb9d7fd51d9fbb329d182423bd7b92d0f8cb0e01 Mon Sep 17 00:00:00 2001 From: Vincent Whitchurch Date: Tue, 21 Aug 2018 17:25:07 +0200 Subject: [PATCH 200/302] watchdog: Mark watchdog touch functions as notrace Some architectures need to use stop_machine() to patch functions for ftrace, and the assumption is that the stopped CPUs do not make function calls to traceable functions when they are in the stopped state. Commit ce4f06dcbb5d ("stop_machine: Touch_nmi_watchdog() after MULTI_STOP_PREPARE") added calls to the watchdog touch functions from the stopped CPUs and those functions lack notrace annotations. This leads to crashes when enabling/disabling ftrace on ARM kernels built with the Thumb-2 instruction set. Fix it by adding the necessary notrace annotations. Fixes: ce4f06dcbb5d ("stop_machine: Touch_nmi_watchdog() after MULTI_STOP_PREPARE") Signed-off-by: Vincent Whitchurch Signed-off-by: Thomas Gleixner Cc: Peter Zijlstra Cc: oleg@redhat.com Cc: tj@kernel.org Cc: stable@vger.kernel.org Link: https://lkml.kernel.org/r/20180821152507.18313-1-vincent.whitchurch@axis.com --- kernel/watchdog.c | 4 ++-- kernel/watchdog_hld.c | 2 +- kernel/workqueue.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/kernel/watchdog.c b/kernel/watchdog.c index 5470dce212c0..977918d5d350 100644 --- a/kernel/watchdog.c +++ b/kernel/watchdog.c @@ -261,7 +261,7 @@ static void __touch_watchdog(void) * entering idle state. This should only be used for scheduler events. * Use touch_softlockup_watchdog() for everything else. */ -void touch_softlockup_watchdog_sched(void) +notrace void touch_softlockup_watchdog_sched(void) { /* * Preemption can be enabled. It doesn't matter which CPU's timestamp @@ -270,7 +270,7 @@ void touch_softlockup_watchdog_sched(void) raw_cpu_write(watchdog_touch_ts, 0); } -void touch_softlockup_watchdog(void) +notrace void touch_softlockup_watchdog(void) { touch_softlockup_watchdog_sched(); wq_watchdog_touch(raw_smp_processor_id()); diff --git a/kernel/watchdog_hld.c b/kernel/watchdog_hld.c index 1f7020d65d0a..71381168dede 100644 --- a/kernel/watchdog_hld.c +++ b/kernel/watchdog_hld.c @@ -29,7 +29,7 @@ static struct cpumask dead_events_mask; static unsigned long hardlockup_allcpu_dumped; static atomic_t watchdog_cpus = ATOMIC_INIT(0); -void arch_touch_nmi_watchdog(void) +notrace void arch_touch_nmi_watchdog(void) { /* * Using __raw here because some code paths have diff --git a/kernel/workqueue.c b/kernel/workqueue.c index 60e80198c3df..0280deac392e 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -5574,7 +5574,7 @@ static void wq_watchdog_timer_fn(struct timer_list *unused) mod_timer(&wq_watchdog_timer, jiffies + thresh); } -void wq_watchdog_touch(int cpu) +notrace void wq_watchdog_touch(int cpu) { if (cpu >= 0) per_cpu(wq_watchdog_touched_cpu, cpu) = jiffies; From 13ba17bee18e321b073b49a88dcab10881f757da Mon Sep 17 00:00:00 2001 From: Mukesh Ojha Date: Fri, 24 Aug 2018 18:03:53 +0530 Subject: [PATCH 201/302] notifier: Remove notifier header file wherever not used The conversion of the hotplug notifiers to a state machine left the notifier.h includes around in some places. Remove them. Signed-off-by: Mukesh Ojha Signed-off-by: Thomas Gleixner Link: https://lkml.kernel.org/r/1535114033-4605-1-git-send-email-mojha@codeaurora.org --- fs/buffer.c | 1 - kernel/printk/printk.c | 1 - lib/percpu_counter.c | 1 - mm/page-writeback.c | 1 - mm/page_alloc.c | 1 - mm/slub.c | 1 - net/core/dev.c | 1 - 7 files changed, 7 deletions(-) diff --git a/fs/buffer.c b/fs/buffer.c index 4cc679d5bf58..6f1ae3ac9789 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -39,7 +39,6 @@ #include #include #include -#include #include #include #include diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c index 924e37fb1620..fd6f8ed28e01 100644 --- a/kernel/printk/printk.c +++ b/kernel/printk/printk.c @@ -38,7 +38,6 @@ #include #include #include -#include #include #include #include diff --git a/lib/percpu_counter.c b/lib/percpu_counter.c index c72577e472f2..a66595ba5543 100644 --- a/lib/percpu_counter.c +++ b/lib/percpu_counter.c @@ -4,7 +4,6 @@ */ #include -#include #include #include #include diff --git a/mm/page-writeback.c b/mm/page-writeback.c index 6551d3b0dc30..84ae9bf5858a 100644 --- a/mm/page-writeback.c +++ b/mm/page-writeback.c @@ -27,7 +27,6 @@ #include #include #include -#include #include #include #include diff --git a/mm/page_alloc.c b/mm/page_alloc.c index e75865d58ba7..05e983f42316 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -32,7 +32,6 @@ #include #include #include -#include #include #include #include diff --git a/mm/slub.c b/mm/slub.c index ce2b9e5cea77..8da34a8af53d 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -19,7 +19,6 @@ #include #include "slab.h" #include -#include #include #include #include diff --git a/net/core/dev.c b/net/core/dev.c index 325fc5088370..82114e1111e6 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -93,7 +93,6 @@ #include #include #include -#include #include #include #include From 113fc08357ad4e8b84caa75402430875d9ac4c1a Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Mon, 27 Aug 2018 12:39:43 +0900 Subject: [PATCH 202/302] objtool: Remove workaround for unreachable warnings from old GCC Commit cafa0010cd51 ("Raise the minimum required gcc version to 4.6") bumped the minimum GCC version to 4.6 for all architectures. This effectively reverts commit da541b20021c ("objtool: Skip unreachable warnings for GCC 4.4 and older"), which was a workaround for GCC 4.4 or older. Signed-off-by: Masahiro Yamada Signed-off-by: Thomas Gleixner Acked-by: Josh Poimboeuf Cc: Peter Zijlstra Cc: Michal Marek Cc: linux-kbuild@vger.kernel.org Link: https://lkml.kernel.org/r/1535341183-19994-1-git-send-email-yamada.masahiro@socionext.com --- scripts/Makefile.build | 2 -- 1 file changed, 2 deletions(-) diff --git a/scripts/Makefile.build b/scripts/Makefile.build index 1c48572223d1..5a2d1c9578a0 100644 --- a/scripts/Makefile.build +++ b/scripts/Makefile.build @@ -246,8 +246,6 @@ objtool_args += --no-fp endif ifdef CONFIG_GCOV_KERNEL objtool_args += --no-unreachable -else -objtool_args += $(call cc-ifversion, -lt, 0405, --no-unreachable) endif ifdef CONFIG_RETPOLINE ifneq ($(RETPOLINE_CFLAGS),) From 9222f606506c5f8ca2c8b8c939d59ed3e6ac4148 Mon Sep 17 00:00:00 2001 From: Jiri Kosina Date: Tue, 28 Aug 2018 08:55:14 +0200 Subject: [PATCH 203/302] x86/alternatives: Lockdep-enforce text_mutex in text_poke*() text_poke() and text_poke_bp() must be called with text_mutex held. Put proper lockdep anotation in place instead of just mentioning the requirement in a comment. Reported-by: Peter Zijlstra Signed-off-by: Jiri Kosina Signed-off-by: Thomas Gleixner Acked-by: Peter Zijlstra (Intel) Acked-by: Masami Hiramatsu Cc: Andy Lutomirski Link: https://lkml.kernel.org/r/nycvar.YFH.7.76.1808280853520.25787@cbobk.fhfr.pm --- arch/x86/kernel/alternative.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c index 014f214da581..b9d5e7c9ef43 100644 --- a/arch/x86/kernel/alternative.c +++ b/arch/x86/kernel/alternative.c @@ -684,8 +684,6 @@ void *__init_or_module text_poke_early(void *addr, const void *opcode, * It means the size must be writable atomically and the address must be aligned * in a way that permits an atomic write. It also makes sure we fit on a single * page. - * - * Note: Must be called under text_mutex. */ void *text_poke(void *addr, const void *opcode, size_t len) { @@ -700,6 +698,8 @@ void *text_poke(void *addr, const void *opcode, size_t len) */ BUG_ON(!after_bootmem); + lockdep_assert_held(&text_mutex); + if (!core_kernel_text((unsigned long)addr)) { pages[0] = vmalloc_to_page(addr); pages[1] = vmalloc_to_page(addr + PAGE_SIZE); @@ -782,8 +782,6 @@ int poke_int3_handler(struct pt_regs *regs) * - replace the first byte (int3) by the first byte of * replacing opcode * - sync cores - * - * Note: must be called under text_mutex. */ void *text_poke_bp(void *addr, const void *opcode, size_t len, void *handler) { @@ -792,6 +790,9 @@ void *text_poke_bp(void *addr, const void *opcode, size_t len, void *handler) bp_int3_handler = handler; bp_int3_addr = (u8 *)addr + sizeof(int3); bp_patching_in_progress = true; + + lockdep_assert_held(&text_mutex); + /* * Corresponding read barrier in int3 notifier for making sure the * in_progress and handler are correctly ordered wrt. patching. From 26e609eccd37967d3681662433086894830c5d62 Mon Sep 17 00:00:00 2001 From: Uros Bizjak Date: Tue, 14 Aug 2018 18:59:51 +0200 Subject: [PATCH 204/302] x86/asm: Use CC_SET()/CC_OUT() in __gen_sigismember() Replace open-coded set instructions with CC_SET()/CC_OUT(). Signed-off-by: Uros Bizjak Signed-off-by: Thomas Gleixner Link: https://lkml.kernel.org/r/20180814165951.13538-1-ubizjak@gmail.com --- arch/x86/include/asm/signal.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/arch/x86/include/asm/signal.h b/arch/x86/include/asm/signal.h index 5f9012ff52ed..33d3c88a7225 100644 --- a/arch/x86/include/asm/signal.h +++ b/arch/x86/include/asm/signal.h @@ -39,6 +39,7 @@ extern void do_signal(struct pt_regs *regs); #define __ARCH_HAS_SA_RESTORER +#include #include #ifdef __i386__ @@ -86,9 +87,9 @@ static inline int __const_sigismember(sigset_t *set, int _sig) static inline int __gen_sigismember(sigset_t *set, int _sig) { - unsigned char ret; - asm("btl %2,%1\n\tsetc %0" - : "=qm"(ret) : "m"(*set), "Ir"(_sig-1) : "cc"); + bool ret; + asm("btl %2,%1" CC_SET(c) + : CC_OUT(c) (ret) : "m"(*set), "Ir"(_sig-1)); return ret; } From 755a8bf5579d22eb5636685c516d8dede799e27b Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Fri, 24 Aug 2018 15:08:30 +0100 Subject: [PATCH 205/302] arm/arm64: smccc-1.1: Handle function result as parameters If someone has the silly idea to write something along those lines: extern u64 foo(void); void bar(struct arm_smccc_res *res) { arm_smccc_1_1_smc(0xbad, foo(), res); } they are in for a surprise, as this gets compiled as: 0000000000000588 : 588: a9be7bfd stp x29, x30, [sp, #-32]! 58c: 910003fd mov x29, sp 590: f9000bf3 str x19, [sp, #16] 594: aa0003f3 mov x19, x0 598: aa1e03e0 mov x0, x30 59c: 94000000 bl 0 <_mcount> 5a0: 94000000 bl 0 5a4: aa0003e1 mov x1, x0 5a8: d4000003 smc #0x0 5ac: b4000073 cbz x19, 5b8 5b0: a9000660 stp x0, x1, [x19] 5b4: a9010e62 stp x2, x3, [x19, #16] 5b8: f9400bf3 ldr x19, [sp, #16] 5bc: a8c27bfd ldp x29, x30, [sp], #32 5c0: d65f03c0 ret 5c4: d503201f nop The call to foo "overwrites" the x0 register for the return value, and we end up calling the wrong secure service. A solution is to evaluate all the parameters before assigning anything to specific registers, leading to the expected result: 0000000000000588 : 588: a9be7bfd stp x29, x30, [sp, #-32]! 58c: 910003fd mov x29, sp 590: f9000bf3 str x19, [sp, #16] 594: aa0003f3 mov x19, x0 598: aa1e03e0 mov x0, x30 59c: 94000000 bl 0 <_mcount> 5a0: 94000000 bl 0 5a4: aa0003e1 mov x1, x0 5a8: d28175a0 mov x0, #0xbad 5ac: d4000003 smc #0x0 5b0: b4000073 cbz x19, 5bc 5b4: a9000660 stp x0, x1, [x19] 5b8: a9010e62 stp x2, x3, [x19, #16] 5bc: f9400bf3 ldr x19, [sp, #16] 5c0: a8c27bfd ldp x29, x30, [sp], #32 5c4: d65f03c0 ret Reported-by: Julien Grall Signed-off-by: Marc Zyngier Signed-off-by: Will Deacon --- include/linux/arm-smccc.h | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h index 5a91ff33720b..18863d56273c 100644 --- a/include/linux/arm-smccc.h +++ b/include/linux/arm-smccc.h @@ -205,41 +205,51 @@ asmlinkage void __arm_smccc_hvc(unsigned long a0, unsigned long a1, register unsigned long r3 asm("r3") #define __declare_arg_1(a0, a1, res) \ + typeof(a1) __a1 = a1; \ struct arm_smccc_res *___res = res; \ register unsigned long r0 asm("r0") = (u32)a0; \ - register unsigned long r1 asm("r1") = a1; \ + register unsigned long r1 asm("r1") = __a1; \ register unsigned long r2 asm("r2"); \ register unsigned long r3 asm("r3") #define __declare_arg_2(a0, a1, a2, res) \ + typeof(a1) __a1 = a1; \ + typeof(a2) __a2 = a2; \ struct arm_smccc_res *___res = res; \ register unsigned long r0 asm("r0") = (u32)a0; \ - register unsigned long r1 asm("r1") = a1; \ - register unsigned long r2 asm("r2") = a2; \ + register unsigned long r1 asm("r1") = __a1; \ + register unsigned long r2 asm("r2") = __a2; \ register unsigned long r3 asm("r3") #define __declare_arg_3(a0, a1, a2, a3, res) \ + typeof(a1) __a1 = a1; \ + typeof(a2) __a2 = a2; \ + typeof(a3) __a3 = a3; \ struct arm_smccc_res *___res = res; \ register unsigned long r0 asm("r0") = (u32)a0; \ - register unsigned long r1 asm("r1") = a1; \ - register unsigned long r2 asm("r2") = a2; \ - register unsigned long r3 asm("r3") = a3 + register unsigned long r1 asm("r1") = __a1; \ + register unsigned long r2 asm("r2") = __a2; \ + register unsigned long r3 asm("r3") = __a3 #define __declare_arg_4(a0, a1, a2, a3, a4, res) \ + typeof(a4) __a4 = a4; \ __declare_arg_3(a0, a1, a2, a3, res); \ - register typeof(a4) r4 asm("r4") = a4 + register unsigned long r4 asm("r4") = __a4 #define __declare_arg_5(a0, a1, a2, a3, a4, a5, res) \ + typeof(a5) __a5 = a5; \ __declare_arg_4(a0, a1, a2, a3, a4, res); \ - register typeof(a5) r5 asm("r5") = a5 + register unsigned long r5 asm("r5") = __a5 #define __declare_arg_6(a0, a1, a2, a3, a4, a5, a6, res) \ + typeof(a6) __a6 = a6; \ __declare_arg_5(a0, a1, a2, a3, a4, a5, res); \ - register typeof(a6) r6 asm("r6") = a6 + register unsigned long r6 asm("r6") = __a6 #define __declare_arg_7(a0, a1, a2, a3, a4, a5, a6, a7, res) \ + typeof(a7) __a7 = a7; \ __declare_arg_6(a0, a1, a2, a3, a4, a5, a6, res); \ - register typeof(a7) r7 asm("r7") = a7 + register unsigned long r7 asm("r7") = __a7 #define ___declare_args(count, ...) __declare_arg_ ## count(__VA_ARGS__) #define __declare_args(count, ...) ___declare_args(count, __VA_ARGS__) From f42b0e18f2e5cf34f73ef1b6327b49040b307a33 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Mon, 27 Aug 2018 07:50:47 -0500 Subject: [PATCH 206/302] of: add node name compare helper functions In preparation to remove device_node.name pointer, add helper functions for node name comparisons which are a common pattern throughout the kernel. Cc: Frank Rowand Signed-off-by: Rob Herring --- drivers/of/base.c | 22 ++++++++++++++++++++++ include/linux/of.h | 13 +++++++++++++ 2 files changed, 35 insertions(+) diff --git a/drivers/of/base.c b/drivers/of/base.c index bc420d2aa5f5..9095b8290150 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -54,6 +54,28 @@ DEFINE_MUTEX(of_mutex); */ DEFINE_RAW_SPINLOCK(devtree_lock); +bool of_node_name_eq(const struct device_node *np, const char *name) +{ + const char *node_name; + size_t len; + + if (!np) + return false; + + node_name = kbasename(np->full_name); + len = strchrnul(node_name, '@') - node_name; + + return (strlen(name) == len) && (strncmp(node_name, name, len) == 0); +} + +bool of_node_name_prefix(const struct device_node *np, const char *prefix) +{ + if (!np) + return false; + + return strncmp(kbasename(np->full_name), prefix, strlen(prefix)) == 0; +} + int of_n_addr_cells(struct device_node *np) { u32 cells; diff --git a/include/linux/of.h b/include/linux/of.h index b99a1a8c2952..688c52dd7b3e 100644 --- a/include/linux/of.h +++ b/include/linux/of.h @@ -256,6 +256,9 @@ static inline unsigned long of_read_ulong(const __be32 *cell, int size) #define OF_IS_DYNAMIC(x) test_bit(OF_DYNAMIC, &x->_flags) #define OF_MARK_DYNAMIC(x) set_bit(OF_DYNAMIC, &x->_flags) +extern bool of_node_name_eq(const struct device_node *np, const char *name); +extern bool of_node_name_prefix(const struct device_node *np, const char *prefix); + static inline const char *of_node_full_name(const struct device_node *np) { return np ? np->full_name : ""; @@ -563,6 +566,16 @@ static inline struct device_node *to_of_node(const struct fwnode_handle *fwnode) return NULL; } +static inline bool of_node_name_eq(const struct device_node *np, const char *name) +{ + return false; +} + +static inline bool of_node_name_prefix(const struct device_node *np, const char *prefix) +{ + return false; +} + static inline const char* of_node_full_name(const struct device_node *np) { return ""; From 7fd6d98b89f382d414e1db528e29a67bbd749457 Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Thu, 30 Aug 2018 11:50:13 +0300 Subject: [PATCH 207/302] i2c: i801: Allow ACPI AML access I/O ports not reserved for SMBus Commit 7ae81952cda ("i2c: i801: Allow ACPI SystemIO OpRegion to conflict with PCI BAR") made it possible for AML code to access SMBus I/O ports by installing custom SystemIO OpRegion handler and blocking i80i driver access upon first AML read/write to this OpRegion. However, while ThinkPad T560 does have SystemIO OpRegion declared under the SMBus device, it does not access any of the SMBus registers: Device (SMBU) { ... OperationRegion (SMBP, PCI_Config, 0x50, 0x04) Field (SMBP, DWordAcc, NoLock, Preserve) { , 5, TCOB, 11, Offset (0x04) } Name (TCBV, 0x00) Method (TCBS, 0, NotSerialized) { If ((TCBV == 0x00)) { TCBV = (\_SB.PCI0.SMBU.TCOB << 0x05) } Return (TCBV) /* \_SB_.PCI0.SMBU.TCBV */ } OperationRegion (TCBA, SystemIO, TCBS (), 0x10) Field (TCBA, ByteAcc, NoLock, Preserve) { Offset (0x04), , 9, CPSC, 1 } } Problem with the current approach is that it blocks all I/O port access and because this system has touchpad connected to the SMBus controller after first AML access (happens during suspend/resume cycle) the touchpad fails to work anymore. Fix this so that we allow ACPI AML I/O port access if it does not touch the region reserved for the SMBus. Fixes: 7ae81952cda ("i2c: i801: Allow ACPI SystemIO OpRegion to conflict with PCI BAR") Link: https://bugzilla.kernel.org/show_bug.cgi?id=200737 Reported-by: Yussuf Khalil Signed-off-by: Mika Westerberg Reviewed-by: Jean Delvare Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-i801.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index 941c223f6491..04b60a349d7e 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c @@ -1415,6 +1415,13 @@ static void i801_add_tco(struct i801_priv *priv) } #ifdef CONFIG_ACPI +static bool i801_acpi_is_smbus_ioport(const struct i801_priv *priv, + acpi_physical_address address) +{ + return address >= priv->smba && + address <= pci_resource_end(priv->pci_dev, SMBBAR); +} + static acpi_status i801_acpi_io_handler(u32 function, acpi_physical_address address, u32 bits, u64 *value, void *handler_context, void *region_context) @@ -1430,7 +1437,7 @@ i801_acpi_io_handler(u32 function, acpi_physical_address address, u32 bits, */ mutex_lock(&priv->acpi_lock); - if (!priv->acpi_reserved) { + if (!priv->acpi_reserved && i801_acpi_is_smbus_ioport(priv, address)) { priv->acpi_reserved = true; dev_warn(&pdev->dev, "BIOS is accessing SMBus registers\n"); From 9d9a152ebaa86a9dede4624919566483c955d0a7 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 29 Aug 2018 15:06:31 +0200 Subject: [PATCH 208/302] i2c: designware: Re-init controllers with pm_disabled set on resume On Bay Trail and Cherry Trail devices we set the pm_disabled flag for I2C busses which the OS shares with the PUNIT as these need special handling. Until now we called dev_pm_syscore_device(dev, true) for I2C controllers with this flag set to keep these I2C controllers always on. After commit 12864ff8545f ("ACPI / LPSS: Avoid PM quirks on suspend and resume from hibernation"), this no longer works. This commit modifies lpss_iosf_exit_d3_state() to only run if lpss_iosf_enter_d3_state() has ran before it, so that it does not run on a resume from hibernate (or from S3). On these systems the conditions for lpss_iosf_enter_d3_state() to run never become true, so lpss_iosf_exit_d3_state() never gets called and the 2 LPSS DMA controllers never get forced into D0 mode, instead they are left in their default automatic power-on when needed mode. The not forcing of D0 mode for the DMA controllers enables these systems to properly enter S0ix modes, which is a good thing. But after entering S0ix modes the I2C controller connected to the PMIC no longer works, leading to e.g. broken battery monitoring. The _PS3 method for this I2C controller looks like this: Method (_PS3, 0, NotSerialized) // _PS3: Power State 3 { If ((((PMID == 0x04) || (PMID == 0x05)) || (PMID == 0x06))) { Return (Zero) } PSAT |= 0x03 Local0 = PSAT /* \_SB_.I2C5.PSAT */ } Where PMID = 0x05, so we enter the Return (Zero) path on these systems. So even if we were to not call dev_pm_syscore_device(dev, true) the I2C controller will be left in D0 rather then be switched to D3. Yet on other Bay and Cherry Trail devices S0ix is not entered unless *all* I2C controllers are in D3 mode. This combined with the I2C controller no longer working now that we reach S0ix states on these systems leads to me believing that the PUNIT itself puts the I2C controller in D3 when all other conditions for entering S0ix states are true. Since now the I2C controller is put in D3 over a suspend/resume we must re-initialize it afterwards and that does indeed fix it no longer working. This commit implements this fix by: 1) Making the suspend_late callback a no-op if pm_disabled is set and making the resume_early callback skip the clock re-enable (since it now was not disabled) while still doing the necessary I2C controller re-init. 2) Removing the dev_pm_syscore_device(dev, true) call, so that the suspend and resume callbacks are actually called. Normally this would cause the ACPI pm code to call _PS3 putting the I2C controller in D3, wreaking havoc since it is shared with the PUNIT, but in this special case the _PS3 method is a no-op so we can safely allow a "fake" suspend / resume. Fixes: 12864ff8545f ("ACPI / LPSS: Avoid PM quirks on suspend and resume ...") Link: https://bugzilla.kernel.org/show_bug.cgi?id=200861 Cc: 4.15+ # 4.15+ Signed-off-by: Hans de Goede Reviewed-by: Andy Shevchenko Acked-by: Jarkko Nikula Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-designware-master.c | 1 - drivers/i2c/busses/i2c-designware-platdrv.c | 7 ++++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/i2c/busses/i2c-designware-master.c b/drivers/i2c/busses/i2c-designware-master.c index e18442b9973a..94d94b4a9a0d 100644 --- a/drivers/i2c/busses/i2c-designware-master.c +++ b/drivers/i2c/busses/i2c-designware-master.c @@ -708,7 +708,6 @@ int i2c_dw_probe(struct dw_i2c_dev *dev) i2c_set_adapdata(adap, dev); if (dev->pm_disabled) { - dev_pm_syscore_device(dev->dev, true); irq_flags = IRQF_NO_SUSPEND; } else { irq_flags = IRQF_SHARED | IRQF_COND_SUSPEND; diff --git a/drivers/i2c/busses/i2c-designware-platdrv.c b/drivers/i2c/busses/i2c-designware-platdrv.c index 1a8d2da5b000..b5750fd85125 100644 --- a/drivers/i2c/busses/i2c-designware-platdrv.c +++ b/drivers/i2c/busses/i2c-designware-platdrv.c @@ -434,6 +434,9 @@ static int dw_i2c_plat_suspend(struct device *dev) { struct dw_i2c_dev *i_dev = dev_get_drvdata(dev); + if (i_dev->pm_disabled) + return 0; + i_dev->disable(i_dev); i2c_dw_prepare_clk(i_dev, false); @@ -444,7 +447,9 @@ static int dw_i2c_plat_resume(struct device *dev) { struct dw_i2c_dev *i_dev = dev_get_drvdata(dev); - i2c_dw_prepare_clk(i_dev, true); + if (!i_dev->pm_disabled) + i2c_dw_prepare_clk(i_dev, true); + i_dev->init(i_dev); return 0; From 1204d12a494cf5dff497859a5febf2ae30a28970 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Kundr=C3=A1t?= Date: Tue, 28 Aug 2018 10:07:40 +0200 Subject: [PATCH 209/302] i2c: algos: bit: make the error messages grepable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Yep, I went looking for one of these, and I wasn't able to find it easily. That's worse than a line which is 82-chars long, IMHO. Signed-off-by: Jan Kundrát Signed-off-by: Wolfram Sang --- drivers/i2c/algos/i2c-algo-bit.c | 55 ++++++++++++++++++-------------- 1 file changed, 31 insertions(+), 24 deletions(-) diff --git a/drivers/i2c/algos/i2c-algo-bit.c b/drivers/i2c/algos/i2c-algo-bit.c index 6ec65adaba49..c33dcfb87993 100644 --- a/drivers/i2c/algos/i2c-algo-bit.c +++ b/drivers/i2c/algos/i2c-algo-bit.c @@ -110,8 +110,8 @@ static int sclhi(struct i2c_algo_bit_data *adap) } #ifdef DEBUG if (jiffies != start && i2c_debug >= 3) - pr_debug("i2c-algo-bit: needed %ld jiffies for SCL to go " - "high\n", jiffies - start); + pr_debug("i2c-algo-bit: needed %ld jiffies for SCL to go high\n", + jiffies - start); #endif done: @@ -171,8 +171,9 @@ static int i2c_outb(struct i2c_adapter *i2c_adap, unsigned char c) setsda(adap, sb); udelay((adap->udelay + 1) / 2); if (sclhi(adap) < 0) { /* timed out */ - bit_dbg(1, &i2c_adap->dev, "i2c_outb: 0x%02x, " - "timeout at bit #%d\n", (int)c, i); + bit_dbg(1, &i2c_adap->dev, + "i2c_outb: 0x%02x, timeout at bit #%d\n", + (int)c, i); return -ETIMEDOUT; } /* FIXME do arbitration here: @@ -185,8 +186,8 @@ static int i2c_outb(struct i2c_adapter *i2c_adap, unsigned char c) } sdahi(adap); if (sclhi(adap) < 0) { /* timeout */ - bit_dbg(1, &i2c_adap->dev, "i2c_outb: 0x%02x, " - "timeout at ack\n", (int)c); + bit_dbg(1, &i2c_adap->dev, + "i2c_outb: 0x%02x, timeout at ack\n", (int)c); return -ETIMEDOUT; } @@ -215,8 +216,9 @@ static int i2c_inb(struct i2c_adapter *i2c_adap) sdahi(adap); for (i = 0; i < 8; i++) { if (sclhi(adap) < 0) { /* timeout */ - bit_dbg(1, &i2c_adap->dev, "i2c_inb: timeout at bit " - "#%d\n", 7 - i); + bit_dbg(1, &i2c_adap->dev, + "i2c_inb: timeout at bit #%d\n", + 7 - i); return -ETIMEDOUT; } indata *= 2; @@ -265,8 +267,9 @@ static int test_bus(struct i2c_adapter *i2c_adap) goto bailout; } if (!scl) { - printk(KERN_WARNING "%s: SCL unexpected low " - "while pulling SDA low!\n", name); + printk(KERN_WARNING + "%s: SCL unexpected low while pulling SDA low!\n", + name); goto bailout; } @@ -278,8 +281,9 @@ static int test_bus(struct i2c_adapter *i2c_adap) goto bailout; } if (!scl) { - printk(KERN_WARNING "%s: SCL unexpected low " - "while pulling SDA high!\n", name); + printk(KERN_WARNING + "%s: SCL unexpected low while pulling SDA high!\n", + name); goto bailout; } @@ -291,8 +295,9 @@ static int test_bus(struct i2c_adapter *i2c_adap) goto bailout; } if (!sda) { - printk(KERN_WARNING "%s: SDA unexpected low " - "while pulling SCL low!\n", name); + printk(KERN_WARNING + "%s: SDA unexpected low while pulling SCL low!\n", + name); goto bailout; } @@ -304,8 +309,9 @@ static int test_bus(struct i2c_adapter *i2c_adap) goto bailout; } if (!sda) { - printk(KERN_WARNING "%s: SDA unexpected low " - "while pulling SCL high!\n", name); + printk(KERN_WARNING + "%s: SDA unexpected low while pulling SCL high!\n", + name); goto bailout; } @@ -352,8 +358,8 @@ static int try_address(struct i2c_adapter *i2c_adap, i2c_start(adap); } if (i && ret) - bit_dbg(1, &i2c_adap->dev, "Used %d tries to %s client at " - "0x%02x: %s\n", i + 1, + bit_dbg(1, &i2c_adap->dev, + "Used %d tries to %s client at 0x%02x: %s\n", i + 1, addr & 1 ? "read from" : "write to", addr >> 1, ret == 1 ? "success" : "failed, timeout?"); return ret; @@ -442,8 +448,9 @@ static int readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msg) if (inval <= 0 || inval > I2C_SMBUS_BLOCK_MAX) { if (!(flags & I2C_M_NO_RD_ACK)) acknak(i2c_adap, 0); - dev_err(&i2c_adap->dev, "readbytes: invalid " - "block length (%d)\n", inval); + dev_err(&i2c_adap->dev, + "readbytes: invalid block length (%d)\n", + inval); return -EPROTO; } /* The original count value accounts for the extra @@ -506,8 +513,8 @@ static int bit_doAddress(struct i2c_adapter *i2c_adap, struct i2c_msg *msg) return -ENXIO; } if (flags & I2C_M_RD) { - bit_dbg(3, &i2c_adap->dev, "emitting repeated " - "start condition\n"); + bit_dbg(3, &i2c_adap->dev, + "emitting repeated start condition\n"); i2c_repstart(adap); /* okay, now switch into reading mode */ addr |= 0x01; @@ -564,8 +571,8 @@ static int bit_xfer(struct i2c_adapter *i2c_adap, } ret = bit_doAddress(i2c_adap, pmsg); if ((ret != 0) && !nak_ok) { - bit_dbg(1, &i2c_adap->dev, "NAK from " - "device addr 0x%02x msg #%d\n", + bit_dbg(1, &i2c_adap->dev, + "NAK from device addr 0x%02x msg #%d\n", msgs[i].addr, i); goto bailout; } From 82fe39a6bc7b866fc3ffd838e3c5a4cadb328b04 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Fri, 24 Aug 2018 16:52:44 +0200 Subject: [PATCH 210/302] i2c: refactor function to release a DMA safe buffer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit a) rename to 'put' instead of 'release' to match 'get' when obtaining the buffer b) change the argument order to have the buffer as first argument c) add a new argument telling the function if the message was transferred. This allows the function to be used also in cases where setting up DMA failed, so the buffer needs to be freed without syncing to the message buffer. Also convert the only user. Signed-off-by: Wolfram Sang Reviewed-by: Niklas Söderlund Signed-off-by: Wolfram Sang --- Documentation/i2c/DMA-considerations | 10 +++++++--- drivers/i2c/busses/i2c-sh_mobile.c | 2 +- drivers/i2c/i2c-core-base.c | 11 ++++++----- include/linux/i2c.h | 2 +- 4 files changed, 15 insertions(+), 10 deletions(-) diff --git a/Documentation/i2c/DMA-considerations b/Documentation/i2c/DMA-considerations index 966610aa4620..203002054120 100644 --- a/Documentation/i2c/DMA-considerations +++ b/Documentation/i2c/DMA-considerations @@ -50,10 +50,14 @@ bounce buffer. But you don't need to care about that detail, just use the returned buffer. If NULL is returned, the threshold was not met or a bounce buffer could not be allocated. Fall back to PIO in that case. -In any case, a buffer obtained from above needs to be released. It ensures data -is copied back to the message and a potentially used bounce buffer is freed:: +In any case, a buffer obtained from above needs to be released. Another helper +function ensures a potentially used bounce buffer is freed:: - i2c_release_dma_safe_msg_buf(msg, dma_buf); + i2c_put_dma_safe_msg_buf(dma_buf, msg, xferred); + +The last argument 'xferred' controls if the buffer is synced back to the +message or not. No syncing is needed in cases setting up DMA had an error and +there was no data transferred. The bounce buffer handling from the core is generic and simple. It will always allocate a new bounce buffer. If you want a more sophisticated handling (e.g. diff --git a/drivers/i2c/busses/i2c-sh_mobile.c b/drivers/i2c/busses/i2c-sh_mobile.c index 439e8778f849..279d0e5bd433 100644 --- a/drivers/i2c/busses/i2c-sh_mobile.c +++ b/drivers/i2c/busses/i2c-sh_mobile.c @@ -507,7 +507,7 @@ static void sh_mobile_i2c_dma_callback(void *data) pd->pos = pd->msg->len; pd->stop_after_dma = true; - i2c_release_dma_safe_msg_buf(pd->msg, pd->dma_buf); + i2c_put_dma_safe_msg_buf(pd->dma_buf, pd->msg, true); iic_set_clr(pd, ICIC, 0, ICIC_TDMAE | ICIC_RDMAE); } diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c index f15737763608..9ee9a15e7134 100644 --- a/drivers/i2c/i2c-core-base.c +++ b/drivers/i2c/i2c-core-base.c @@ -2293,21 +2293,22 @@ u8 *i2c_get_dma_safe_msg_buf(struct i2c_msg *msg, unsigned int threshold) EXPORT_SYMBOL_GPL(i2c_get_dma_safe_msg_buf); /** - * i2c_release_dma_safe_msg_buf - release DMA safe buffer and sync with i2c_msg - * @msg: the message to be synced with + * i2c_put_dma_safe_msg_buf - release DMA safe buffer and sync with i2c_msg * @buf: the buffer obtained from i2c_get_dma_safe_msg_buf(). May be NULL. + * @msg: the message which the buffer corresponds to + * @xferred: bool saying if the message was transferred */ -void i2c_release_dma_safe_msg_buf(struct i2c_msg *msg, u8 *buf) +void i2c_put_dma_safe_msg_buf(u8 *buf, struct i2c_msg *msg, bool xferred) { if (!buf || buf == msg->buf) return; - if (msg->flags & I2C_M_RD) + if (xferred && msg->flags & I2C_M_RD) memcpy(msg->buf, buf, msg->len); kfree(buf); } -EXPORT_SYMBOL_GPL(i2c_release_dma_safe_msg_buf); +EXPORT_SYMBOL_GPL(i2c_put_dma_safe_msg_buf); MODULE_AUTHOR("Simon G. Vogl "); MODULE_DESCRIPTION("I2C-Bus main module"); diff --git a/include/linux/i2c.h b/include/linux/i2c.h index b79387fd57da..65b4eaed1d96 100644 --- a/include/linux/i2c.h +++ b/include/linux/i2c.h @@ -855,7 +855,7 @@ static inline u8 i2c_8bit_addr_from_msg(const struct i2c_msg *msg) } u8 *i2c_get_dma_safe_msg_buf(struct i2c_msg *msg, unsigned int threshold); -void i2c_release_dma_safe_msg_buf(struct i2c_msg *msg, u8 *buf); +void i2c_put_dma_safe_msg_buf(u8 *buf, struct i2c_msg *msg, bool xferred); int i2c_handle_smbus_host_notify(struct i2c_adapter *adap, unsigned short addr); /** From 531db50170a3e6d113c968fe7a6dda8d55d02ede Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Fri, 24 Aug 2018 16:52:45 +0200 Subject: [PATCH 211/302] i2c: sh_mobile: define start_ch() void as it only returns 0 anyhow MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit After various refactoring over the years, start_ch() doesn't return errno anymore, so make the function return void. This saves the error handling when calling it which in turn eases cleanup of resources of a future patch. Signed-off-by: Wolfram Sang Reviewed-by: Niklas Söderlund Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-sh_mobile.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/i2c/busses/i2c-sh_mobile.c b/drivers/i2c/busses/i2c-sh_mobile.c index 279d0e5bd433..b965d52338ba 100644 --- a/drivers/i2c/busses/i2c-sh_mobile.c +++ b/drivers/i2c/busses/i2c-sh_mobile.c @@ -602,8 +602,8 @@ static void sh_mobile_i2c_xfer_dma(struct sh_mobile_i2c_data *pd) dma_async_issue_pending(chan); } -static int start_ch(struct sh_mobile_i2c_data *pd, struct i2c_msg *usr_msg, - bool do_init) +static void start_ch(struct sh_mobile_i2c_data *pd, struct i2c_msg *usr_msg, + bool do_init) { if (do_init) { /* Initialize channel registers */ @@ -627,7 +627,6 @@ static int start_ch(struct sh_mobile_i2c_data *pd, struct i2c_msg *usr_msg, /* Enable all interrupts to begin with */ iic_wr(pd, ICIC, ICIC_DTEE | ICIC_WAITE | ICIC_ALE | ICIC_TACKE); - return 0; } static int poll_dte(struct sh_mobile_i2c_data *pd) @@ -698,9 +697,7 @@ static int sh_mobile_i2c_xfer(struct i2c_adapter *adapter, pd->send_stop = i == num - 1 || msg->flags & I2C_M_STOP; pd->stop_after_dma = false; - err = start_ch(pd, msg, do_start); - if (err) - break; + start_ch(pd, msg, do_start); if (do_start) i2c_op(pd, OP_START, 0); From cebc07d84ad71bc58d6f59b770e4347da48a5a2b Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Fri, 24 Aug 2018 16:52:46 +0200 Subject: [PATCH 212/302] i2c: sh_mobile: fix leak when using DMA bounce buffer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We only freed the bounce buffer after successful DMA, missing the cases where DMA setup may have gone wrong. Use a better location which always gets called after each message and use 'stop_after_dma' as a flag for a successful transfer. Signed-off-by: Wolfram Sang Reviewed-by: Niklas Söderlund Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-sh_mobile.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/i2c/busses/i2c-sh_mobile.c b/drivers/i2c/busses/i2c-sh_mobile.c index b965d52338ba..818cab14e87c 100644 --- a/drivers/i2c/busses/i2c-sh_mobile.c +++ b/drivers/i2c/busses/i2c-sh_mobile.c @@ -507,8 +507,6 @@ static void sh_mobile_i2c_dma_callback(void *data) pd->pos = pd->msg->len; pd->stop_after_dma = true; - i2c_put_dma_safe_msg_buf(pd->dma_buf, pd->msg, true); - iic_set_clr(pd, ICIC, 0, ICIC_TDMAE | ICIC_RDMAE); } @@ -706,6 +704,10 @@ static int sh_mobile_i2c_xfer(struct i2c_adapter *adapter, timeout = wait_event_timeout(pd->wait, pd->sr & (ICSR_TACK | SW_DONE), adapter->timeout); + + /* 'stop_after_dma' tells if DMA transfer was complete */ + i2c_put_dma_safe_msg_buf(pd->dma_buf, pd->msg, pd->stop_after_dma); + if (!timeout) { dev_err(pd->dev, "Transfer request timed out\n"); if (pd->dma_direction != DMA_NONE) From bded6c03e398dc6e862dc8301fb9a60175740653 Mon Sep 17 00:00:00 2001 From: Akshu Agrawal Date: Tue, 21 Aug 2018 12:21:57 +0530 Subject: [PATCH 213/302] clk: x86: Set default parent to 48Mhz System clk provided in ST soc can be set to: 48Mhz, non-spread 25Mhz, spread To get accurate rate, we need it to set it at non-spread option which is 48Mhz. Signed-off-by: Akshu Agrawal Reviewed-by: Daniel Kurtz Fixes: 421bf6a1f061 ("clk: x86: Add ST oscout platform clock") Signed-off-by: Stephen Boyd --- drivers/clk/x86/clk-st.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/x86/clk-st.c b/drivers/clk/x86/clk-st.c index fb62f3938008..3a0996f2d556 100644 --- a/drivers/clk/x86/clk-st.c +++ b/drivers/clk/x86/clk-st.c @@ -46,7 +46,7 @@ static int st_clk_probe(struct platform_device *pdev) clk_oscout1_parents, ARRAY_SIZE(clk_oscout1_parents), 0, st_data->base + CLKDRVSTR2, OSCOUT1CLK25MHZ, 3, 0, NULL); - clk_set_parent(hws[ST_CLK_MUX]->clk, hws[ST_CLK_25M]->clk); + clk_set_parent(hws[ST_CLK_MUX]->clk, hws[ST_CLK_48M]->clk); hws[ST_CLK_GATE] = clk_hw_register_gate(NULL, "oscout1", "oscout1_mux", 0, st_data->base + MISCCLKCNTL1, OSCCLKENB, From 217c3e0196758662aa0429863b09d1c13da1c5d6 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Fri, 31 Aug 2018 07:47:28 +1000 Subject: [PATCH 214/302] disable stringop truncation warnings for now They are too noisy Signed-off-by: Stephen Rothwell Signed-off-by: Linus Torvalds --- Makefile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Makefile b/Makefile index 2b458801ba74..a34a9283ee90 100644 --- a/Makefile +++ b/Makefile @@ -807,6 +807,9 @@ KBUILD_CFLAGS += $(call cc-option,-Wdeclaration-after-statement,) # disable pointer signed / unsigned warnings in gcc 4.0 KBUILD_CFLAGS += $(call cc-disable-warning, pointer-sign) +# disable stringop warnings in gcc 8+ +KBUILD_CFLAGS += $(call cc-disable-warning, stringop-truncation) + # disable invalid "can't wrap" optimizations for signed / pointers KBUILD_CFLAGS += $(call cc-option,-fno-strict-overflow) From 0986b16ab49b18063d29a9e02e9c7fab1928bc8e Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Fri, 24 Aug 2018 12:02:06 +1000 Subject: [PATCH 215/302] m68k/mac: Use correct PMU response format Now that the 68k Mac port has adopted the via-pmu driver, it must decode the PMU response accordingly otherwise the date and time will be wrong. Fixes: ebd722275f9cfc67 ("macintosh/via-pmu: Replace via-pmu68k driver with via-pmu driver") Signed-off-by: Finn Thain Signed-off-by: Geert Uytterhoeven --- arch/m68k/mac/misc.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/arch/m68k/mac/misc.c b/arch/m68k/mac/misc.c index 3534aa6a4dc2..1b083c500b9a 100644 --- a/arch/m68k/mac/misc.c +++ b/arch/m68k/mac/misc.c @@ -98,11 +98,10 @@ static time64_t pmu_read_time(void) if (pmu_request(&req, NULL, 1, PMU_READ_RTC) < 0) return 0; - while (!req.complete) - pmu_poll(); + pmu_wait_complete(&req); - time = (u32)((req.reply[1] << 24) | (req.reply[2] << 16) | - (req.reply[3] << 8) | req.reply[4]); + time = (u32)((req.reply[0] << 24) | (req.reply[1] << 16) | + (req.reply[2] << 8) | req.reply[3]); return time - RTC_OFFSET; } @@ -116,8 +115,7 @@ static void pmu_write_time(time64_t time) (data >> 24) & 0xFF, (data >> 16) & 0xFF, (data >> 8) & 0xFF, data & 0xFF) < 0) return; - while (!req.complete) - pmu_poll(); + pmu_wait_complete(&req); } static __u8 pmu_read_pram(int offset) From f52bb98f5aded4c43e52f5ce19fb83f7261e9e73 Mon Sep 17 00:00:00 2001 From: James Morse Date: Thu, 30 Aug 2018 16:05:32 +0100 Subject: [PATCH 216/302] arm64: mm: always enable CONFIG_HOLES_IN_ZONE Commit 6d526ee26ccd ("arm64: mm: enable CONFIG_HOLES_IN_ZONE for NUMA") only enabled HOLES_IN_ZONE for NUMA systems because the NUMA code was choking on the missing zone for nomap pages. This problem doesn't just apply to NUMA systems. If the architecture doesn't set HAVE_ARCH_PFN_VALID, pfn_valid() will return true if the pfn is part of a valid sparsemem section. When working with multiple pages, the mm code uses pfn_valid_within() to test each page it uses within the sparsemem section is valid. On most systems memory comes in MAX_ORDER_NR_PAGES chunks which all have valid/initialised struct pages. In this case pfn_valid_within() is optimised out. Systems where this isn't true (e.g. due to nomap) should set HOLES_IN_ZONE and provide HAVE_ARCH_PFN_VALID so that mm tests each page as it works with it. Currently non-NUMA arm64 systems can't enable HOLES_IN_ZONE, leading to a VM_BUG_ON(): | page:fffffdff802e1780 is uninitialized and poisoned | raw: ffffffffffffffff ffffffffffffffff ffffffffffffffff ffffffffffffffff | raw: ffffffffffffffff ffffffffffffffff ffffffffffffffff ffffffffffffffff | page dumped because: VM_BUG_ON_PAGE(PagePoisoned(p)) | ------------[ cut here ]------------ | kernel BUG at include/linux/mm.h:978! | Internal error: Oops - BUG: 0 [#1] PREEMPT SMP [...] | CPU: 1 PID: 25236 Comm: dd Not tainted 4.18.0 #7 | Hardware name: QEMU KVM Virtual Machine, BIOS 0.0.0 02/06/2015 | pstate: 40000085 (nZcv daIf -PAN -UAO) | pc : move_freepages_block+0x144/0x248 | lr : move_freepages_block+0x144/0x248 | sp : fffffe0071177680 [...] | Process dd (pid: 25236, stack limit = 0x0000000094cc07fb) | Call trace: | move_freepages_block+0x144/0x248 | steal_suitable_fallback+0x100/0x16c | get_page_from_freelist+0x440/0xb20 | __alloc_pages_nodemask+0xe8/0x838 | new_slab+0xd4/0x418 | ___slab_alloc.constprop.27+0x380/0x4a8 | __slab_alloc.isra.21.constprop.26+0x24/0x34 | kmem_cache_alloc+0xa8/0x180 | alloc_buffer_head+0x1c/0x90 | alloc_page_buffers+0x68/0xb0 | create_empty_buffers+0x20/0x1ec | create_page_buffers+0xb0/0xf0 | __block_write_begin_int+0xc4/0x564 | __block_write_begin+0x10/0x18 | block_write_begin+0x48/0xd0 | blkdev_write_begin+0x28/0x30 | generic_perform_write+0x98/0x16c | __generic_file_write_iter+0x138/0x168 | blkdev_write_iter+0x80/0xf0 | __vfs_write+0xe4/0x10c | vfs_write+0xb4/0x168 | ksys_write+0x44/0x88 | sys_write+0xc/0x14 | el0_svc_naked+0x30/0x34 | Code: aa1303e0 90001a01 91296421 94008902 (d4210000) | ---[ end trace 1601ba47f6e883fe ]--- Remove the NUMA dependency. Link: https://www.spinics.net/lists/arm-kernel/msg671851.html Cc: Cc: Ard Biesheuvel Reported-by: Mikulas Patocka Reviewed-by: Pavel Tatashin Tested-by: Mikulas Patocka Signed-off-by: James Morse Signed-off-by: Will Deacon --- arch/arm64/Kconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index 29e75b47becd..1b1a0e95c751 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -763,7 +763,6 @@ config NEED_PER_CPU_EMBED_FIRST_CHUNK config HOLES_IN_ZONE def_bool y - depends on NUMA source kernel/Kconfig.hz From 6fb86d97207880c1286cd4cb3a7e6a598afbc727 Mon Sep 17 00:00:00 2001 From: Mukesh Ojha Date: Tue, 28 Aug 2018 12:24:54 +0530 Subject: [PATCH 217/302] cpu/hotplug: Remove skip_onerr field from cpuhp_step structure When notifiers were there, `skip_onerr` was used to avoid calling particular step startup/teardown callbacks in the CPU up/down rollback path, which made the hotplug asymmetric. As notifiers are gone now after the full state machine conversion, the `skip_onerr` field is no longer required. Remove it from the structure and its usage. Signed-off-by: Mukesh Ojha Signed-off-by: Thomas Gleixner Acked-by: Peter Zijlstra (Intel) Link: https://lkml.kernel.org/r/1535439294-31426-1-git-send-email-mojha@codeaurora.org --- kernel/cpu.c | 26 ++++---------------------- 1 file changed, 4 insertions(+), 22 deletions(-) diff --git a/kernel/cpu.c b/kernel/cpu.c index ed44d7d34c2d..aa7fe85ad62e 100644 --- a/kernel/cpu.c +++ b/kernel/cpu.c @@ -102,8 +102,6 @@ static inline void cpuhp_lock_release(bool bringup) { } * @name: Name of the step * @startup: Startup function of the step * @teardown: Teardown function of the step - * @skip_onerr: Do not invoke the functions on error rollback - * Will go away once the notifiers are gone * @cant_stop: Bringup/teardown can't be stopped at this step */ struct cpuhp_step { @@ -119,7 +117,6 @@ struct cpuhp_step { struct hlist_node *node); } teardown; struct hlist_head list; - bool skip_onerr; bool cant_stop; bool multi_instance; }; @@ -550,12 +547,8 @@ static int bringup_cpu(unsigned int cpu) static void undo_cpu_up(unsigned int cpu, struct cpuhp_cpu_state *st) { - for (st->state--; st->state > st->target; st->state--) { - struct cpuhp_step *step = cpuhp_get_step(st->state); - - if (!step->skip_onerr) - cpuhp_invoke_callback(cpu, st->state, false, NULL, NULL); - } + for (st->state--; st->state > st->target; st->state--) + cpuhp_invoke_callback(cpu, st->state, false, NULL, NULL); } static int cpuhp_up_callbacks(unsigned int cpu, struct cpuhp_cpu_state *st, @@ -644,12 +637,6 @@ static void cpuhp_thread_fun(unsigned int cpu) WARN_ON_ONCE(!cpuhp_is_ap_state(state)); - if (st->rollback) { - struct cpuhp_step *step = cpuhp_get_step(state); - if (step->skip_onerr) - goto next; - } - if (cpuhp_is_atomic_state(state)) { local_irq_disable(); st->result = cpuhp_invoke_callback(cpu, state, bringup, st->node, &st->last); @@ -673,7 +660,6 @@ static void cpuhp_thread_fun(unsigned int cpu) st->should_run = false; } -next: cpuhp_lock_release(bringup); if (!st->should_run) @@ -916,12 +902,8 @@ void cpuhp_report_idle_dead(void) static void undo_cpu_down(unsigned int cpu, struct cpuhp_cpu_state *st) { - for (st->state++; st->state < st->target; st->state++) { - struct cpuhp_step *step = cpuhp_get_step(st->state); - - if (!step->skip_onerr) - cpuhp_invoke_callback(cpu, st->state, true, NULL, NULL); - } + for (st->state++; st->state < st->target; st->state++) + cpuhp_invoke_callback(cpu, st->state, true, NULL, NULL); } static int cpuhp_down_callbacks(unsigned int cpu, struct cpuhp_cpu_state *st, From 0413bedabc886c3a56804d1c80a58e99077b1d91 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Tue, 28 Aug 2018 15:10:48 -0500 Subject: [PATCH 218/302] of: Add device_type access helper functions In preparation to remove direct access to device_node.type, add of_node_is_type() and of_node_get_device_type() helpers to check and retrieve the device type. Cc: Frank Rowand Signed-off-by: Rob Herring --- include/linux/of.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/include/linux/of.h b/include/linux/of.h index 688c52dd7b3e..99b0ebf49632 100644 --- a/include/linux/of.h +++ b/include/linux/of.h @@ -988,6 +988,18 @@ static inline struct device_node *of_find_matching_node( return of_find_matching_node_and_match(from, matches, NULL); } +static inline const char *of_node_get_device_type(const struct device_node *np) +{ + return of_get_property(np, "type", NULL); +} + +static inline bool of_node_is_type(const struct device_node *np, const char *type) +{ + const char *match = of_node_get_device_type(np); + + return np && match && type && !strcmp(match, type); +} + /** * of_property_count_u8_elems - Count the number of u8 elements in a property * From 342db04ae71273322f0011384a9ed414df8bdae4 Mon Sep 17 00:00:00 2001 From: Jann Horn Date: Tue, 28 Aug 2018 17:49:01 +0200 Subject: [PATCH 219/302] x86/dumpstack: Don't dump kernel memory based on usermode RIP show_opcodes() is used both for dumping kernel instructions and for dumping user instructions. If userspace causes #PF by jumping to a kernel address, show_opcodes() can be reached with regs->ip controlled by the user, pointing to kernel code. Make sure that userspace can't trick us into dumping kernel memory into dmesg. Fixes: 7cccf0725cf7 ("x86/dumpstack: Add a show_ip() function") Signed-off-by: Jann Horn Signed-off-by: Thomas Gleixner Reviewed-by: Kees Cook Reviewed-by: Borislav Petkov Cc: "H. Peter Anvin" Cc: Andy Lutomirski Cc: security@kernel.org Cc: stable@vger.kernel.org Link: https://lkml.kernel.org/r/20180828154901.112726-1-jannh@google.com --- arch/x86/include/asm/stacktrace.h | 2 +- arch/x86/kernel/dumpstack.c | 16 +++++++++++++--- arch/x86/mm/fault.c | 2 +- 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/arch/x86/include/asm/stacktrace.h b/arch/x86/include/asm/stacktrace.h index b6dc698f992a..f335aad404a4 100644 --- a/arch/x86/include/asm/stacktrace.h +++ b/arch/x86/include/asm/stacktrace.h @@ -111,6 +111,6 @@ static inline unsigned long caller_frame_pointer(void) return (unsigned long)frame; } -void show_opcodes(u8 *rip, const char *loglvl); +void show_opcodes(struct pt_regs *regs, const char *loglvl); void show_ip(struct pt_regs *regs, const char *loglvl); #endif /* _ASM_X86_STACKTRACE_H */ diff --git a/arch/x86/kernel/dumpstack.c b/arch/x86/kernel/dumpstack.c index 1596e6bfea6f..f56895106ccf 100644 --- a/arch/x86/kernel/dumpstack.c +++ b/arch/x86/kernel/dumpstack.c @@ -90,14 +90,24 @@ static void printk_stack_address(unsigned long address, int reliable, * Thus, the 2/3rds prologue and 64 byte OPCODE_BUFSIZE is just a random * guesstimate in attempt to achieve all of the above. */ -void show_opcodes(u8 *rip, const char *loglvl) +void show_opcodes(struct pt_regs *regs, const char *loglvl) { #define PROLOGUE_SIZE 42 #define EPILOGUE_SIZE 21 #define OPCODE_BUFSIZE (PROLOGUE_SIZE + 1 + EPILOGUE_SIZE) u8 opcodes[OPCODE_BUFSIZE]; + unsigned long prologue = regs->ip - PROLOGUE_SIZE; + bool bad_ip; - if (probe_kernel_read(opcodes, rip - PROLOGUE_SIZE, OPCODE_BUFSIZE)) { + /* + * Make sure userspace isn't trying to trick us into dumping kernel + * memory by pointing the userspace instruction pointer at it. + */ + bad_ip = user_mode(regs) && + __chk_range_not_ok(prologue, OPCODE_BUFSIZE, TASK_SIZE_MAX); + + if (bad_ip || probe_kernel_read(opcodes, (u8 *)prologue, + OPCODE_BUFSIZE)) { printk("%sCode: Bad RIP value.\n", loglvl); } else { printk("%sCode: %" __stringify(PROLOGUE_SIZE) "ph <%02x> %" @@ -113,7 +123,7 @@ void show_ip(struct pt_regs *regs, const char *loglvl) #else printk("%sRIP: %04x:%pS\n", loglvl, (int)regs->cs, (void *)regs->ip); #endif - show_opcodes((u8 *)regs->ip, loglvl); + show_opcodes(regs, loglvl); } void show_iret_regs(struct pt_regs *regs) diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c index b9123c497e0a..47bebfe6efa7 100644 --- a/arch/x86/mm/fault.c +++ b/arch/x86/mm/fault.c @@ -837,7 +837,7 @@ show_signal_msg(struct pt_regs *regs, unsigned long error_code, printk(KERN_CONT "\n"); - show_opcodes((u8 *)regs->ip, loglvl); + show_opcodes(regs, loglvl); } static void From 829fe4aa9ac16417a904ad1de1307de906854bcf Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Wed, 29 Aug 2018 20:43:17 +0100 Subject: [PATCH 220/302] x86: Allow generating user-space headers without a compiler When bootstrapping an architecture, it's usual to generate the kernel's user-space headers (make headers_install) before building a compiler. Move the compiler check (for asm goto support) to the archprepare target so that it is only done when building code for the target. Fixes: e501ce957a78 ("x86: Force asm-goto") Reported-by: Helmut Grohne Signed-off-by: Ben Hutchings Signed-off-by: Thomas Gleixner Cc: stable@vger.kernel.org Link: https://lkml.kernel.org/r/20180829194317.GA4765@decadent.org.uk --- arch/x86/Makefile | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/arch/x86/Makefile b/arch/x86/Makefile index 8fc8f94ef5f5..8f6e7eb8ae9f 100644 --- a/arch/x86/Makefile +++ b/arch/x86/Makefile @@ -175,10 +175,6 @@ ifdef CONFIG_FUNCTION_GRAPH_TRACER endif endif -ifndef CC_HAVE_ASM_GOTO - $(error Compiler lacks asm-goto support.) -endif - ifeq ($(ACCUMULATE_OUTGOING_ARGS), 1) # This compiler flag is not supported by Clang: KBUILD_CFLAGS += $(call cc-option,-maccumulate-outgoing-args,) @@ -300,6 +296,13 @@ PHONY += vdso_install vdso_install: $(Q)$(MAKE) $(build)=arch/x86/entry/vdso $@ +archprepare: checkbin +checkbin: +ifndef CC_HAVE_ASM_GOTO + @echo Compiler lacks asm-goto support. + @exit 1 +endif + archclean: $(Q)rm -rf $(objtree)/arch/i386 $(Q)rm -rf $(objtree)/arch/x86_64 From 4012e77a903d114f915fc607d6d2ed54a3d6c9b1 Mon Sep 17 00:00:00 2001 From: Andy Lutomirski Date: Wed, 29 Aug 2018 08:47:18 -0700 Subject: [PATCH 221/302] x86/nmi: Fix NMI uaccess race against CR3 switching A NMI can hit in the middle of context switching or in the middle of switch_mm_irqs_off(). In either case, CR3 might not match current->mm, which could cause copy_from_user_nmi() and friends to read the wrong memory. Fix it by adding a new nmi_uaccess_okay() helper and checking it in copy_from_user_nmi() and in __copy_from_user_nmi()'s callers. Signed-off-by: Andy Lutomirski Signed-off-by: Thomas Gleixner Reviewed-by: Rik van Riel Cc: Nadav Amit Cc: Borislav Petkov Cc: Jann Horn Cc: Peter Zijlstra Cc: stable@vger.kernel.org Link: https://lkml.kernel.org/r/dd956eba16646fd0b15c3c0741269dfd84452dac.1535557289.git.luto@kernel.org --- arch/x86/events/core.c | 2 +- arch/x86/include/asm/tlbflush.h | 40 +++++++++++++++++++++++++++++++++ arch/x86/lib/usercopy.c | 5 +++++ arch/x86/mm/tlb.c | 7 ++++++ 4 files changed, 53 insertions(+), 1 deletion(-) diff --git a/arch/x86/events/core.c b/arch/x86/events/core.c index 5f4829f10129..dfb2f7c0d019 100644 --- a/arch/x86/events/core.c +++ b/arch/x86/events/core.c @@ -2465,7 +2465,7 @@ perf_callchain_user(struct perf_callchain_entry_ctx *entry, struct pt_regs *regs perf_callchain_store(entry, regs->ip); - if (!current->mm) + if (!nmi_uaccess_okay()) return; if (perf_callchain_user32(regs, entry)) diff --git a/arch/x86/include/asm/tlbflush.h b/arch/x86/include/asm/tlbflush.h index 29c9da6c62fc..58ce5288878e 100644 --- a/arch/x86/include/asm/tlbflush.h +++ b/arch/x86/include/asm/tlbflush.h @@ -175,8 +175,16 @@ struct tlb_state { * are on. This means that it may not match current->active_mm, * which will contain the previous user mm when we're in lazy TLB * mode even if we've already switched back to swapper_pg_dir. + * + * During switch_mm_irqs_off(), loaded_mm will be set to + * LOADED_MM_SWITCHING during the brief interrupts-off window + * when CR3 and loaded_mm would otherwise be inconsistent. This + * is for nmi_uaccess_okay()'s benefit. */ struct mm_struct *loaded_mm; + +#define LOADED_MM_SWITCHING ((struct mm_struct *)1) + u16 loaded_mm_asid; u16 next_asid; /* last user mm's ctx id */ @@ -246,6 +254,38 @@ struct tlb_state { }; DECLARE_PER_CPU_SHARED_ALIGNED(struct tlb_state, cpu_tlbstate); +/* + * Blindly accessing user memory from NMI context can be dangerous + * if we're in the middle of switching the current user task or + * switching the loaded mm. It can also be dangerous if we + * interrupted some kernel code that was temporarily using a + * different mm. + */ +static inline bool nmi_uaccess_okay(void) +{ + struct mm_struct *loaded_mm = this_cpu_read(cpu_tlbstate.loaded_mm); + struct mm_struct *current_mm = current->mm; + + VM_WARN_ON_ONCE(!loaded_mm); + + /* + * The condition we want to check is + * current_mm->pgd == __va(read_cr3_pa()). This may be slow, though, + * if we're running in a VM with shadow paging, and nmi_uaccess_okay() + * is supposed to be reasonably fast. + * + * Instead, we check the almost equivalent but somewhat conservative + * condition below, and we rely on the fact that switch_mm_irqs_off() + * sets loaded_mm to LOADED_MM_SWITCHING before writing to CR3. + */ + if (loaded_mm != current_mm) + return false; + + VM_WARN_ON_ONCE(current_mm->pgd != __va(read_cr3_pa())); + + return true; +} + /* Initialize cr4 shadow for this CPU. */ static inline void cr4_init_shadow(void) { diff --git a/arch/x86/lib/usercopy.c b/arch/x86/lib/usercopy.c index c8c6ad0d58b8..3f435d7fca5e 100644 --- a/arch/x86/lib/usercopy.c +++ b/arch/x86/lib/usercopy.c @@ -7,6 +7,8 @@ #include #include +#include + /* * We rely on the nested NMI work to allow atomic faults from the NMI path; the * nested NMI paths are careful to preserve CR2. @@ -19,6 +21,9 @@ copy_from_user_nmi(void *to, const void __user *from, unsigned long n) if (__range_not_ok(from, n, TASK_SIZE)) return n; + if (!nmi_uaccess_okay()) + return n; + /* * Even though this function is typically called from NMI/IRQ context * disable pagefaults so that its behaviour is consistent even when diff --git a/arch/x86/mm/tlb.c b/arch/x86/mm/tlb.c index 9517d1b2a281..e96b99eb800c 100644 --- a/arch/x86/mm/tlb.c +++ b/arch/x86/mm/tlb.c @@ -305,6 +305,10 @@ void switch_mm_irqs_off(struct mm_struct *prev, struct mm_struct *next, choose_new_asid(next, next_tlb_gen, &new_asid, &need_flush); + /* Let nmi_uaccess_okay() know that we're changing CR3. */ + this_cpu_write(cpu_tlbstate.loaded_mm, LOADED_MM_SWITCHING); + barrier(); + if (need_flush) { this_cpu_write(cpu_tlbstate.ctxs[new_asid].ctx_id, next->context.ctx_id); this_cpu_write(cpu_tlbstate.ctxs[new_asid].tlb_gen, next_tlb_gen); @@ -335,6 +339,9 @@ void switch_mm_irqs_off(struct mm_struct *prev, struct mm_struct *next, if (next != &init_mm) this_cpu_write(cpu_tlbstate.last_ctx_id, next->context.ctx_id); + /* Make sure we write CR3 before loaded_mm. */ + barrier(); + this_cpu_write(cpu_tlbstate.loaded_mm, next); this_cpu_write(cpu_tlbstate.loaded_mm_asid, new_asid); } From eeb89e2bb1ac45b0836d4170e97a988c3a746c62 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Fri, 31 Aug 2018 10:05:38 +0200 Subject: [PATCH 222/302] x86/efi: Load fixmap GDT in efi_call_phys_epilog() When PTI is enabled on x86-32 the kernel uses the GDT mapped in the fixmap for the simple reason that this address is also mapped for user-space. The efi_call_phys_prolog()/efi_call_phys_epilog() wrappers change the GDT to call EFI runtime services and switch back to the kernel GDT when they return. But the switch-back uses the writable GDT, not the fixmap GDT. When that happened and and the CPU returns to user-space it switches to the user %cr3 and tries to restore user segment registers. This fails because the writable GDT is not mapped in the user page-table, and without a GDT the fault handlers also can't be launched. The result is a triple fault and reboot of the machine. Fix that by restoring the GDT back to the fixmap GDT which is also mapped in the user page-table. Fixes: 7757d607c6b3 x86/pti: ('Allow CONFIG_PAGE_TABLE_ISOLATION for x86_32') Reported-by: Guenter Roeck Signed-off-by: Joerg Roedel Signed-off-by: Thomas Gleixner Tested-by: Guenter Roeck Cc: Ard Biesheuvel Cc: Michal Hocko Cc: Andi Kleen Cc: Linus Torvalds Cc: Dave Hansen Cc: Pavel Machek Cc: hpa@zytor.com Cc: linux-efi@vger.kernel.org Link: https://lkml.kernel.org/r/1535702738-10971-1-git-send-email-joro@8bytes.org --- arch/x86/platform/efi/efi_32.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/arch/x86/platform/efi/efi_32.c b/arch/x86/platform/efi/efi_32.c index 324b93328b37..05ca14222463 100644 --- a/arch/x86/platform/efi/efi_32.c +++ b/arch/x86/platform/efi/efi_32.c @@ -85,14 +85,10 @@ pgd_t * __init efi_call_phys_prolog(void) void __init efi_call_phys_epilog(pgd_t *save_pgd) { - struct desc_ptr gdt_descr; - - gdt_descr.address = (unsigned long)get_cpu_gdt_rw(0); - gdt_descr.size = GDT_SIZE - 1; - load_gdt(&gdt_descr); - load_cr3(save_pgd); __flush_tlb_all(); + + load_fixmap_gdt(0); } void __init efi_runtime_update_mappings(void) From c7486104a5ce7e8763e3cb5157bba8d0f1468d87 Mon Sep 17 00:00:00 2001 From: LuckTony Date: Fri, 31 Aug 2018 09:55:06 -0700 Subject: [PATCH 223/302] x86/mce: Fix set_mce_nospec() to avoid #GP fault The trick with flipping bit 63 to avoid loading the address of the 1:1 mapping of the poisoned page while the 1:1 map is updated used to work when unmapping the page. But it falls down horribly when attempting to directly set the page as uncacheable. The problem is that when the cache mode is changed to uncachable, the pages needs to be flushed from the cache first. But the decoy address is non-canonical due to bit 63 flipped, and the CLFLUSH instruction throws a #GP fault. Add code to change_page_attr_set_clr() to fix the address before calling flush. Fixes: 284ce4011ba6 ("x86/memory_failure: Introduce {set, clear}_mce_nospec()") Suggested-by: Linus Torvalds Signed-off-by: Tony Luck Signed-off-by: Thomas Gleixner Acked-by: Linus Torvalds Cc: Peter Anvin Cc: Borislav Petkov Cc: linux-edac Cc: Dan Williams Cc: Dave Jiang Link: https://lkml.kernel.org/r/20180831165506.GA9605@agluck-desk --- arch/x86/mm/pageattr.c | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c index 8d6c34fe49be..51a5a69ecac9 100644 --- a/arch/x86/mm/pageattr.c +++ b/arch/x86/mm/pageattr.c @@ -1420,6 +1420,29 @@ static int __change_page_attr_set_clr(struct cpa_data *cpa, int checkalias) return 0; } +/* + * Machine check recovery code needs to change cache mode of poisoned + * pages to UC to avoid speculative access logging another error. But + * passing the address of the 1:1 mapping to set_memory_uc() is a fine + * way to encourage a speculative access. So we cheat and flip the top + * bit of the address. This works fine for the code that updates the + * page tables. But at the end of the process we need to flush the cache + * and the non-canonical address causes a #GP fault when used by the + * CLFLUSH instruction. + * + * But in the common case we already have a canonical address. This code + * will fix the top bit if needed and is a no-op otherwise. + */ +static inline unsigned long make_addr_canonical_again(unsigned long addr) +{ +#ifdef CONFIG_X86_64 + return (long)(addr << 1) >> 1; +#else + return addr; +#endif +} + + static int change_page_attr_set_clr(unsigned long *addr, int numpages, pgprot_t mask_set, pgprot_t mask_clr, int force_split, int in_flag, @@ -1465,7 +1488,7 @@ static int change_page_attr_set_clr(unsigned long *addr, int numpages, * Save address for cache flush. *addr is modified in the call * to __change_page_attr_set_clr() below. */ - baddr = *addr; + baddr = make_addr_canonical_again(*addr); } /* Must avoid aliasing mappings in the highmem code */ From e78e5a91456fcecaa2efbb3706572fe043766f4d Mon Sep 17 00:00:00 2001 From: Samuel Neves Date: Sat, 1 Sep 2018 21:14:52 +0100 Subject: [PATCH 224/302] x86/vdso: Fix lsl operand order In the __getcpu function, lsl is using the wrong target and destination registers. Luckily, the compiler tends to choose %eax for both variables, so it has been working so far. Fixes: a582c540ac1b ("x86/vdso: Use RDPID in preference to LSL when available") Signed-off-by: Samuel Neves Signed-off-by: Thomas Gleixner Acked-by: Andy Lutomirski Cc: stable@vger.kernel.org Link: https://lkml.kernel.org/r/20180901201452.27828-1-sneves@dei.uc.pt --- arch/x86/include/asm/vgtod.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/include/asm/vgtod.h b/arch/x86/include/asm/vgtod.h index fb856c9f0449..53748541c487 100644 --- a/arch/x86/include/asm/vgtod.h +++ b/arch/x86/include/asm/vgtod.h @@ -93,7 +93,7 @@ static inline unsigned int __getcpu(void) * * If RDPID is available, use it. */ - alternative_io ("lsl %[p],%[seg]", + alternative_io ("lsl %[seg],%[p]", ".byte 0xf3,0x0f,0xc7,0xf8", /* RDPID %eax/rax */ X86_FEATURE_RDPID, [p] "=a" (p), [seg] "r" (__PER_CPU_SEG)); From ff924c5a1ec7548825cc2d07980b03be4224ffac Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Sat, 1 Sep 2018 21:01:28 -0700 Subject: [PATCH 225/302] x86/pti: Fix section mismatch warning/error Fix the section mismatch warning in arch/x86/mm/pti.c: WARNING: vmlinux.o(.text+0x6972a): Section mismatch in reference from the function pti_clone_pgtable() to the function .init.text:pti_user_pagetable_walk_pte() The function pti_clone_pgtable() references the function __init pti_user_pagetable_walk_pte(). This is often because pti_clone_pgtable lacks a __init annotation or the annotation of pti_user_pagetable_walk_pte is wrong. FATAL: modpost: Section mismatches detected. Fixes: 85900ea51577 ("x86/pti: Map the vsyscall page if needed") Reported-by: kbuild test robot Signed-off-by: Randy Dunlap Signed-off-by: Thomas Gleixner Cc: Andy Lutomirski Link: https://lkml.kernel.org/r/43a6d6a3-d69d-5eda-da09-0b1c88215a2a@infradead.org --- arch/x86/mm/pti.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/mm/pti.c b/arch/x86/mm/pti.c index 31341ae7309f..c1fc1ae6b429 100644 --- a/arch/x86/mm/pti.c +++ b/arch/x86/mm/pti.c @@ -248,7 +248,7 @@ static pmd_t *pti_user_pagetable_walk_pmd(unsigned long address) * * Returns a pointer to a PTE on success, or NULL on failure. */ -static __init pte_t *pti_user_pagetable_walk_pte(unsigned long address) +static pte_t *pti_user_pagetable_walk_pte(unsigned long address) { gfp_t gfp = (GFP_KERNEL | __GFP_NOTRACK | __GFP_ZERO); pmd_t *pmd; From 57361846b52bc686112da6ca5368d11210796804 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sun, 2 Sep 2018 14:37:30 -0700 Subject: [PATCH 226/302] Linux 4.19-rc2 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index a34a9283ee90..19948e556941 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ VERSION = 4 PATCHLEVEL = 19 SUBLEVEL = 0 -EXTRAVERSION = -rc1 +EXTRAVERSION = -rc2 NAME = Merciless Moray # *DOCUMENTATION* From 85e08e5864458b2e5e25defe2601bd835a42912c Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Fri, 27 Jul 2018 09:44:17 +0200 Subject: [PATCH 227/302] mtd: rawnand: Add the nand_wait_readrdy() helper and use it The logic to wait for chip readiness after a page read has been duplicated in nand_do_read_ops() and nand_do_read_oob(). Provide an helper that does the right thing and call it where appropriate. Signed-off-by: Boris Brezillon Signed-off-by: Miquel Raynal --- drivers/mtd/nand/raw/nand_base.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c index d527e448ce19..21a04b7b918c 100644 --- a/drivers/mtd/nand/raw/nand_base.c +++ b/drivers/mtd/nand/raw/nand_base.c @@ -3524,6 +3524,18 @@ static int nand_setup_read_retry(struct mtd_info *mtd, int retry_mode) return chip->setup_read_retry(mtd, retry_mode); } +static void nand_wait_readrdy(struct nand_chip *chip) +{ + if (!(chip->options & NAND_NEED_READRDY)) + return; + + /* Apply delay or wait for ready/busy pin */ + if (!chip->dev_ready) + udelay(chip->chip_delay); + else + nand_wait_ready(nand_to_mtd(chip)); +} + /** * nand_do_read_ops - [INTERN] Read data with ECC * @mtd: MTD device structure @@ -3631,13 +3643,7 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from, } } - if (chip->options & NAND_NEED_READRDY) { - /* Apply delay or wait for ready/busy pin */ - if (!chip->dev_ready) - udelay(chip->chip_delay); - else - nand_wait_ready(mtd); - } + nand_wait_readrdy(chip); if (mtd->ecc_stats.failed - ecc_failures) { if (retry_mode + 1 < chip->read_retries) { @@ -3908,13 +3914,7 @@ static int nand_do_read_oob(struct mtd_info *mtd, loff_t from, len = min(len, readlen); buf = nand_transfer_oob(mtd, buf, ops, len); - if (chip->options & NAND_NEED_READRDY) { - /* Apply delay or wait for ready/busy pin */ - if (!chip->dev_ready) - udelay(chip->chip_delay); - else - nand_wait_ready(mtd); - } + nand_wait_readrdy(chip); max_bitflips = max_t(unsigned int, max_bitflips, ret); From 52f05b6b87decfc74245ac16b4ae18e321b5ae98 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Fri, 27 Jul 2018 09:44:18 +0200 Subject: [PATCH 228/302] mtd: rawnand: Add the nand_wait_rdy_op() helper and use it In order to make sure we use ->exec_op() to wait for chip readiness when it's available we provide an helper that does the selection between ->exec_op(), udelay(chip->chip_delay) and nand_wait_ready() based on what's implemented by the controller driver. We then use it in nand_wait_readrdy(). Signed-off-by: Boris Brezillon Signed-off-by: Miquel Raynal --- drivers/mtd/nand/raw/nand_base.c | 31 ++++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c index 21a04b7b918c..e591410cddc9 100644 --- a/drivers/mtd/nand/raw/nand_base.c +++ b/drivers/mtd/nand/raw/nand_base.c @@ -2246,6 +2246,28 @@ static int nand_get_features_op(struct nand_chip *chip, u8 feature, return 0; } +static int nand_wait_rdy_op(struct nand_chip *chip, unsigned int timeout_ms, + unsigned int delay_ns) +{ + if (chip->exec_op) { + struct nand_op_instr instrs[] = { + NAND_OP_WAIT_RDY(PSEC_TO_MSEC(timeout_ms), + PSEC_TO_NSEC(delay_ns)), + }; + struct nand_operation op = NAND_OPERATION(instrs); + + return nand_exec_op(chip, &op); + } + + /* Apply delay or wait for ready/busy pin */ + if (!chip->dev_ready) + udelay(chip->chip_delay); + else + nand_wait_ready(nand_to_mtd(chip)); + + return 0; +} + /** * nand_reset_op - Do a reset operation * @chip: The NAND chip @@ -3526,14 +3548,13 @@ static int nand_setup_read_retry(struct mtd_info *mtd, int retry_mode) static void nand_wait_readrdy(struct nand_chip *chip) { + const struct nand_sdr_timings *sdr; + if (!(chip->options & NAND_NEED_READRDY)) return; - /* Apply delay or wait for ready/busy pin */ - if (!chip->dev_ready) - udelay(chip->chip_delay); - else - nand_wait_ready(nand_to_mtd(chip)); + sdr = nand_get_sdr_timings(&chip->data_interface); + WARN_ON(nand_wait_rdy_op(chip, PSEC_TO_MSEC(sdr->tR_max), 0)); } /** From 7525c9518ea6feabc8154956df0891a59a69d289 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Fri, 27 Jul 2018 23:05:42 +0200 Subject: [PATCH 229/302] mtd: rawnand: Get rid of the ->read_word() hook Commit c120e75e0e7d ("mtd: nand: use read_oob() instead of cmdfunc() for bad block check") removed this only user of the ->read_word() method but kept the hook in place. Remove it now. Signed-off-by: Boris Brezillon Signed-off-by: Miquel Raynal --- drivers/mtd/nand/raw/atmel/nand-controller.c | 9 --------- drivers/mtd/nand/raw/au1550nd.c | 15 --------------- drivers/mtd/nand/raw/denali.c | 10 ---------- drivers/mtd/nand/raw/hisi504_nand.c | 10 ---------- drivers/mtd/nand/raw/mpc5121_nfc.c | 11 ----------- drivers/mtd/nand/raw/mxc_nand.c | 13 ------------- drivers/mtd/nand/raw/nand_base.c | 14 -------------- drivers/mtd/nand/raw/nandsim.c | 10 ---------- drivers/mtd/nand/raw/sh_flctl.c | 10 ---------- drivers/mtd/nand/raw/socrates_nand.c | 12 ------------ include/linux/mtd/rawnand.h | 2 -- 11 files changed, 116 deletions(-) diff --git a/drivers/mtd/nand/raw/atmel/nand-controller.c b/drivers/mtd/nand/raw/atmel/nand-controller.c index a068b214ebaa..525e1325841d 100644 --- a/drivers/mtd/nand/raw/atmel/nand-controller.c +++ b/drivers/mtd/nand/raw/atmel/nand-controller.c @@ -418,14 +418,6 @@ static u8 atmel_nand_read_byte(struct mtd_info *mtd) return ioread8(nand->activecs->io.virt); } -static u16 atmel_nand_read_word(struct mtd_info *mtd) -{ - struct nand_chip *chip = mtd_to_nand(mtd); - struct atmel_nand *nand = to_atmel_nand(chip); - - return ioread16(nand->activecs->io.virt); -} - static void atmel_nand_write_byte(struct mtd_info *mtd, u8 byte) { struct nand_chip *chip = mtd_to_nand(mtd); @@ -1500,7 +1492,6 @@ static void atmel_nand_init(struct atmel_nand_controller *nc, chip->cmd_ctrl = atmel_nand_cmd_ctrl; chip->read_byte = atmel_nand_read_byte; - chip->read_word = atmel_nand_read_word; chip->write_byte = atmel_nand_write_byte; chip->read_buf = atmel_nand_read_buf; chip->write_buf = atmel_nand_write_buf; diff --git a/drivers/mtd/nand/raw/au1550nd.c b/drivers/mtd/nand/raw/au1550nd.c index 35f5c84cd331..32c0440141fb 100644 --- a/drivers/mtd/nand/raw/au1550nd.c +++ b/drivers/mtd/nand/raw/au1550nd.c @@ -83,20 +83,6 @@ static void au_write_byte16(struct mtd_info *mtd, u_char byte) wmb(); /* drain writebuffer */ } -/** - * au_read_word - read one word from the chip - * @mtd: MTD device structure - * - * read function for 16bit buswidth without endianness conversion - */ -static u16 au_read_word(struct mtd_info *mtd) -{ - struct nand_chip *this = mtd_to_nand(mtd); - u16 ret = readw(this->IO_ADDR_R); - wmb(); /* drain writebuffer */ - return ret; -} - /** * au_write_buf - write buffer to chip * @mtd: MTD device structure @@ -462,7 +448,6 @@ static int au1550nd_probe(struct platform_device *pdev) this->read_byte = (pd->devwidth) ? au_read_byte16 : au_read_byte; ctx->write_byte = (pd->devwidth) ? au_write_byte16 : au_write_byte; - this->read_word = au_read_word; this->write_buf = (pd->devwidth) ? au_write_buf16 : au_write_buf; this->read_buf = (pd->devwidth) ? au_read_buf16 : au_read_buf; diff --git a/drivers/mtd/nand/raw/denali.c b/drivers/mtd/nand/raw/denali.c index 67b2065e7a19..5ff2ca163884 100644 --- a/drivers/mtd/nand/raw/denali.c +++ b/drivers/mtd/nand/raw/denali.c @@ -279,15 +279,6 @@ static void denali_write_byte(struct mtd_info *mtd, uint8_t byte) denali_write_buf(mtd, &byte, 1); } -static uint16_t denali_read_word(struct mtd_info *mtd) -{ - uint16_t word; - - denali_read_buf16(mtd, (uint8_t *)&word, 2); - - return word; -} - static void denali_cmd_ctrl(struct mtd_info *mtd, int dat, unsigned int ctrl) { struct denali_nand_info *denali = mtd_to_denali(mtd); @@ -1354,7 +1345,6 @@ int denali_init(struct denali_nand_info *denali) chip->select_chip = denali_select_chip; chip->read_byte = denali_read_byte; chip->write_byte = denali_write_byte; - chip->read_word = denali_read_word; chip->cmd_ctrl = denali_cmd_ctrl; chip->dev_ready = denali_dev_ready; chip->waitfunc = denali_waitfunc; diff --git a/drivers/mtd/nand/raw/hisi504_nand.c b/drivers/mtd/nand/raw/hisi504_nand.c index 950dc7789296..0f5c48aa5673 100644 --- a/drivers/mtd/nand/raw/hisi504_nand.c +++ b/drivers/mtd/nand/raw/hisi504_nand.c @@ -380,15 +380,6 @@ static uint8_t hisi_nfc_read_byte(struct mtd_info *mtd) return *(uint8_t *)(host->buffer + host->offset - 1); } -static u16 hisi_nfc_read_word(struct mtd_info *mtd) -{ - struct nand_chip *chip = mtd_to_nand(mtd); - struct hinfc_host *host = nand_get_controller_data(chip); - - host->offset += 2; - return *(u16 *)(host->buffer + host->offset - 2); -} - static void hisi_nfc_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len) { @@ -795,7 +786,6 @@ static int hisi_nfc_probe(struct platform_device *pdev) chip->cmdfunc = hisi_nfc_cmdfunc; chip->select_chip = hisi_nfc_select_chip; chip->read_byte = hisi_nfc_read_byte; - chip->read_word = hisi_nfc_read_word; chip->write_buf = hisi_nfc_write_buf; chip->read_buf = hisi_nfc_read_buf; chip->chip_delay = HINFC504_CHIP_DELAY; diff --git a/drivers/mtd/nand/raw/mpc5121_nfc.c b/drivers/mtd/nand/raw/mpc5121_nfc.c index 6d1740d54e0d..c0be9c30b4cf 100644 --- a/drivers/mtd/nand/raw/mpc5121_nfc.c +++ b/drivers/mtd/nand/raw/mpc5121_nfc.c @@ -515,16 +515,6 @@ static u8 mpc5121_nfc_read_byte(struct mtd_info *mtd) return tmp; } -/* Read word from NFC buffers */ -static u16 mpc5121_nfc_read_word(struct mtd_info *mtd) -{ - u16 tmp; - - mpc5121_nfc_read_buf(mtd, (u_char *)&tmp, sizeof(tmp)); - - return tmp; -} - /* * Read NFC configuration from Reset Config Word * @@ -703,7 +693,6 @@ static int mpc5121_nfc_probe(struct platform_device *op) chip->dev_ready = mpc5121_nfc_dev_ready; chip->cmdfunc = mpc5121_nfc_command; chip->read_byte = mpc5121_nfc_read_byte; - chip->read_word = mpc5121_nfc_read_word; chip->read_buf = mpc5121_nfc_read_buf; chip->write_buf = mpc5121_nfc_write_buf; chip->select_chip = mpc5121_nfc_select_chip; diff --git a/drivers/mtd/nand/raw/mxc_nand.c b/drivers/mtd/nand/raw/mxc_nand.c index 4c9214dea424..a0884a621053 100644 --- a/drivers/mtd/nand/raw/mxc_nand.c +++ b/drivers/mtd/nand/raw/mxc_nand.c @@ -921,18 +921,6 @@ static u_char mxc_nand_read_byte(struct mtd_info *mtd) return ret; } -static uint16_t mxc_nand_read_word(struct mtd_info *mtd) -{ - struct nand_chip *nand_chip = mtd_to_nand(mtd); - struct mxc_nand_host *host = nand_get_controller_data(nand_chip); - uint16_t ret; - - ret = *(uint16_t *)(host->data_buf + host->buf_start); - host->buf_start += 2; - - return ret; -} - /* Write data of length len to buffer buf. The data to be * written on NAND Flash is first copied to RAMbuffer. After the Data Input * Operation by the NFC, the data is written to NAND Flash */ @@ -1793,7 +1781,6 @@ static int mxcnd_probe(struct platform_device *pdev) this->dev_ready = mxc_nand_dev_ready; this->cmdfunc = mxc_nand_command; this->read_byte = mxc_nand_read_byte; - this->read_word = mxc_nand_read_word; this->write_buf = mxc_nand_write_buf; this->read_buf = mxc_nand_read_buf; this->set_features = mxc_nand_set_features; diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c index e591410cddc9..306ef6ec41db 100644 --- a/drivers/mtd/nand/raw/nand_base.c +++ b/drivers/mtd/nand/raw/nand_base.c @@ -277,18 +277,6 @@ static uint8_t nand_read_byte16(struct mtd_info *mtd) return (uint8_t) cpu_to_le16(readw(chip->IO_ADDR_R)); } -/** - * nand_read_word - [DEFAULT] read one word from the chip - * @mtd: MTD device structure - * - * Default read function for 16bit buswidth without endianness conversion. - */ -static u16 nand_read_word(struct mtd_info *mtd) -{ - struct nand_chip *chip = mtd_to_nand(mtd); - return readw(chip->IO_ADDR_R); -} - /** * nand_select_chip - [DEFAULT] control CE line * @mtd: MTD device structure @@ -5007,8 +4995,6 @@ static void nand_set_defaults(struct nand_chip *chip) /* If called twice, pointers that depend on busw may need to be reset */ if (!chip->read_byte || chip->read_byte == nand_read_byte) chip->read_byte = busw ? nand_read_byte16 : nand_read_byte; - if (!chip->read_word) - chip->read_word = nand_read_word; if (!chip->block_bad) chip->block_bad = nand_block_bad; if (!chip->block_markbad) diff --git a/drivers/mtd/nand/raw/nandsim.c b/drivers/mtd/nand/raw/nandsim.c index 71ac034aee9c..47a81d1b1397 100644 --- a/drivers/mtd/nand/raw/nandsim.c +++ b/drivers/mtd/nand/raw/nandsim.c @@ -2108,15 +2108,6 @@ static int ns_device_ready(struct mtd_info *mtd) return 1; } -static uint16_t ns_nand_read_word(struct mtd_info *mtd) -{ - struct nand_chip *chip = mtd_to_nand(mtd); - - NS_DBG("read_word\n"); - - return chip->read_byte(mtd) | (chip->read_byte(mtd) << 8); -} - static void ns_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len) { struct nand_chip *chip = mtd_to_nand(mtd); @@ -2267,7 +2258,6 @@ static int __init ns_init_module(void) chip->dev_ready = ns_device_ready; chip->write_buf = ns_nand_write_buf; chip->read_buf = ns_nand_read_buf; - chip->read_word = ns_nand_read_word; chip->ecc.mode = NAND_ECC_SOFT; chip->ecc.algo = NAND_ECC_HAMMING; /* The NAND_SKIP_BBTSCAN option is necessary for 'overridesize' */ diff --git a/drivers/mtd/nand/raw/sh_flctl.c b/drivers/mtd/nand/raw/sh_flctl.c index bb8866e05ff7..ef3036d9bf15 100644 --- a/drivers/mtd/nand/raw/sh_flctl.c +++ b/drivers/mtd/nand/raw/sh_flctl.c @@ -985,15 +985,6 @@ static uint8_t flctl_read_byte(struct mtd_info *mtd) return data; } -static uint16_t flctl_read_word(struct mtd_info *mtd) -{ - struct sh_flctl *flctl = mtd_to_flctl(mtd); - uint16_t *buf = (uint16_t *)&flctl->done_buff[flctl->index]; - - flctl->index += 2; - return *buf; -} - static void flctl_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) { struct sh_flctl *flctl = mtd_to_flctl(mtd); @@ -1186,7 +1177,6 @@ static int flctl_probe(struct platform_device *pdev) nand->chip_delay = 20; nand->read_byte = flctl_read_byte; - nand->read_word = flctl_read_word; nand->write_buf = flctl_write_buf; nand->read_buf = flctl_read_buf; nand->select_chip = flctl_select_chip; diff --git a/drivers/mtd/nand/raw/socrates_nand.c b/drivers/mtd/nand/raw/socrates_nand.c index 9824a9923583..36c45aa21f66 100644 --- a/drivers/mtd/nand/raw/socrates_nand.c +++ b/drivers/mtd/nand/raw/socrates_nand.c @@ -85,17 +85,6 @@ static uint8_t socrates_nand_read_byte(struct mtd_info *mtd) return byte; } -/** - * socrates_nand_read_word - read one word from the chip - * @mtd: MTD device structure - */ -static uint16_t socrates_nand_read_word(struct mtd_info *mtd) -{ - uint16_t word; - socrates_nand_read_buf(mtd, (uint8_t *)&word, sizeof(word)); - return word; -} - /* * Hardware specific access to control-lines */ @@ -172,7 +161,6 @@ static int socrates_nand_probe(struct platform_device *ofdev) nand_chip->cmd_ctrl = socrates_nand_cmd_ctrl; nand_chip->read_byte = socrates_nand_read_byte; - nand_chip->read_word = socrates_nand_read_word; nand_chip->write_buf = socrates_nand_write_buf; nand_chip->read_buf = socrates_nand_read_buf; nand_chip->dev_ready = socrates_nand_device_ready; diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h index efb2345359bb..d155470f53c8 100644 --- a/include/linux/mtd/rawnand.h +++ b/include/linux/mtd/rawnand.h @@ -1182,7 +1182,6 @@ int nand_op_parser_exec_op(struct nand_chip *chip, * @IO_ADDR_W: [BOARDSPECIFIC] address to write the 8 I/O lines of the * flash device. * @read_byte: [REPLACEABLE] read one byte from the chip - * @read_word: [REPLACEABLE] read one word from the chip * @write_byte: [REPLACEABLE] write a single byte to the chip on the * low 8 I/O lines * @write_buf: [REPLACEABLE] write data from the buffer to the chip @@ -1287,7 +1286,6 @@ struct nand_chip { void __iomem *IO_ADDR_W; uint8_t (*read_byte)(struct mtd_info *mtd); - u16 (*read_word)(struct mtd_info *mtd); void (*write_byte)(struct mtd_info *mtd, uint8_t byte); void (*write_buf)(struct mtd_info *mtd, const uint8_t *buf, int len); void (*read_buf)(struct mtd_info *mtd, uint8_t *buf, int len); From 88aa3bbfc020d14b13d67af3f5c08aa992d82cd8 Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Thu, 2 Aug 2018 10:56:25 +0200 Subject: [PATCH 230/302] mtd: rawnand: marvell: use regmap_update_bits() for syscon access The marvell_nfc_init() function fiddles with some bits of a system controller on Armada 7K/8K. However, it does a read/modify/write sequence on GENCONF_CLK_GATING_CTRL and GENCONF_ND_CLK_CTRL, which isn't safe from a concurrency point of view, as the regmap lock isn't taken accross the read/modify/write sequence. To solve this issue, use regmap_update_bits(). While at it, since the "reg" variable is no longer needed for the read/modify/write sequences, get rid of it for the regmap_write() to GENCONF_SOC_DEVICE_MUX, and directly pass the value to be written as argument. Fixes: 02f26ecf8c772 ("mtd: nand: add reworked Marvell NAND controller driver") Signed-off-by: Thomas Petazzoni Signed-off-by: Miquel Raynal --- drivers/mtd/nand/raw/marvell_nand.c | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/drivers/mtd/nand/raw/marvell_nand.c b/drivers/mtd/nand/raw/marvell_nand.c index 7af4d6213ee5..f06b5c41d7a4 100644 --- a/drivers/mtd/nand/raw/marvell_nand.c +++ b/drivers/mtd/nand/raw/marvell_nand.c @@ -2697,24 +2697,23 @@ static int marvell_nfc_init(struct marvell_nfc *nfc) struct regmap *sysctrl_base = syscon_regmap_lookup_by_phandle(np, "marvell,system-controller"); - u32 reg; if (IS_ERR(sysctrl_base)) return PTR_ERR(sysctrl_base); - reg = GENCONF_SOC_DEVICE_MUX_NFC_EN | - GENCONF_SOC_DEVICE_MUX_ECC_CLK_RST | - GENCONF_SOC_DEVICE_MUX_ECC_CORE_RST | - GENCONF_SOC_DEVICE_MUX_NFC_INT_EN; - regmap_write(sysctrl_base, GENCONF_SOC_DEVICE_MUX, reg); + regmap_write(sysctrl_base, GENCONF_SOC_DEVICE_MUX, + GENCONF_SOC_DEVICE_MUX_NFC_EN | + GENCONF_SOC_DEVICE_MUX_ECC_CLK_RST | + GENCONF_SOC_DEVICE_MUX_ECC_CORE_RST | + GENCONF_SOC_DEVICE_MUX_NFC_INT_EN); - regmap_read(sysctrl_base, GENCONF_CLK_GATING_CTRL, ®); - reg |= GENCONF_CLK_GATING_CTRL_ND_GATE; - regmap_write(sysctrl_base, GENCONF_CLK_GATING_CTRL, reg); + regmap_update_bits(sysctrl_base, GENCONF_CLK_GATING_CTRL, + GENCONF_CLK_GATING_CTRL_ND_GATE, + GENCONF_CLK_GATING_CTRL_ND_GATE); - regmap_read(sysctrl_base, GENCONF_ND_CLK_CTRL, ®); - reg |= GENCONF_ND_CLK_CTRL_EN; - regmap_write(sysctrl_base, GENCONF_ND_CLK_CTRL, reg); + regmap_update_bits(sysctrl_base, GENCONF_ND_CLK_CTRL, + GENCONF_ND_CLK_CTRL_EN, + GENCONF_ND_CLK_CTRL_EN); } /* Configure the DMA if appropriate */ From f223713f15171855526232cd71b2dd96eafeb363 Mon Sep 17 00:00:00 2001 From: KOBAYASHI Yoshitake Date: Sat, 4 Aug 2018 14:25:52 +0900 Subject: [PATCH 231/302] mtd: rawnand: toshiba: Add support for Toshiba Memory BENAND (Built-in ECC NAND) This patch is a patch to support TOSHIBA MEMORY CORPORATION BENAND memory devices. Check the status of the built-in ECC with the Read Status command without using the vendor specific command. The Read Status command only knows whether there was bitflips above the threshold and can not get accurate bitflips. For now, I set max_bitflips mtd->bitflip_threshold. Signed-off-by: KOBAYASHI Yoshitake Reviewed-by: Boris Brezillon Signed-off-by: Miquel Raynal --- drivers/mtd/nand/raw/nand_toshiba.c | 88 +++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) diff --git a/drivers/mtd/nand/raw/nand_toshiba.c b/drivers/mtd/nand/raw/nand_toshiba.c index ab43f027cd23..8aec3fa6c5d9 100644 --- a/drivers/mtd/nand/raw/nand_toshiba.c +++ b/drivers/mtd/nand/raw/nand_toshiba.c @@ -17,6 +17,89 @@ #include +/* Bit for detecting BENAND */ +#define TOSHIBA_NAND_ID4_IS_BENAND BIT(7) + +/* Recommended to rewrite for BENAND */ +#define TOSHIBA_NAND_STATUS_REWRITE_RECOMMENDED BIT(3) + +static int toshiba_nand_benand_eccstatus(struct mtd_info *mtd, + struct nand_chip *chip) +{ + int ret; + unsigned int max_bitflips = 0; + u8 status; + + /* Check Status */ + ret = nand_status_op(chip, &status); + if (ret) + return ret; + + if (status & NAND_STATUS_FAIL) { + /* uncorrected */ + mtd->ecc_stats.failed++; + } else if (status & TOSHIBA_NAND_STATUS_REWRITE_RECOMMENDED) { + /* corrected */ + max_bitflips = mtd->bitflip_threshold; + mtd->ecc_stats.corrected += max_bitflips; + } + + return max_bitflips; +} + +static int +toshiba_nand_read_page_benand(struct mtd_info *mtd, + struct nand_chip *chip, uint8_t *buf, + int oob_required, int page) +{ + int ret; + + ret = nand_read_page_raw(mtd, chip, buf, oob_required, page); + if (ret) + return ret; + + return toshiba_nand_benand_eccstatus(mtd, chip); +} + +static int +toshiba_nand_read_subpage_benand(struct mtd_info *mtd, + struct nand_chip *chip, uint32_t data_offs, + uint32_t readlen, uint8_t *bufpoi, int page) +{ + int ret; + + ret = nand_read_page_op(chip, page, data_offs, + bufpoi + data_offs, readlen); + if (ret) + return ret; + + return toshiba_nand_benand_eccstatus(mtd, chip); +} + +static void toshiba_nand_benand_init(struct nand_chip *chip) +{ + struct mtd_info *mtd = nand_to_mtd(chip); + + /* + * On BENAND, the entire OOB region can be used by the MTD user. + * The calculated ECC bytes are stored into other isolated + * area which is not accessible to users. + * This is why chip->ecc.bytes = 0. + */ + chip->ecc.bytes = 0; + chip->ecc.size = 512; + chip->ecc.strength = 8; + chip->ecc.read_page = toshiba_nand_read_page_benand; + chip->ecc.read_subpage = toshiba_nand_read_subpage_benand; + chip->ecc.write_page = nand_write_page_raw; + chip->ecc.read_page_raw = nand_read_page_raw_notsupp; + chip->ecc.write_page_raw = nand_write_page_raw_notsupp; + + chip->options |= NAND_SUBPAGE_READ; + + mtd_set_ooblayout(mtd, &nand_ooblayout_lp_ops); +} + static void toshiba_nand_decode_id(struct nand_chip *chip) { struct mtd_info *mtd = nand_to_mtd(chip); @@ -68,6 +151,11 @@ static int toshiba_nand_init(struct nand_chip *chip) if (nand_is_slc(chip)) chip->bbt_options |= NAND_BBT_SCAN2NDPAGE; + /* Check that chip is BENAND and ECC mode is on-die */ + if (nand_is_slc(chip) && chip->ecc.mode == NAND_ECC_ON_DIE && + chip->id.data[4] & TOSHIBA_NAND_ID4_IS_BENAND) + toshiba_nand_benand_init(chip); + return 0; } From 33c1c5fee2e88de2ae1efc4554aa7f36d10c3874 Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Sun, 5 Aug 2018 16:52:56 +0200 Subject: [PATCH 232/302] mtd: rawnand: marvell: document a bit more the driver A stale document about the old pxa3cc_nand.c driver is available in Documentation/mtd/nand/. Rewrite the parts that explain the IP itself and some non-trivial choices made in the driver directly in marvell_nand.c to then be able to remove this file. Signed-off-by: Miquel Raynal Reviewed-by: Boris Brezillon --- drivers/mtd/nand/raw/marvell_nand.c | 67 +++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/drivers/mtd/nand/raw/marvell_nand.c b/drivers/mtd/nand/raw/marvell_nand.c index f06b5c41d7a4..270f281067ab 100644 --- a/drivers/mtd/nand/raw/marvell_nand.c +++ b/drivers/mtd/nand/raw/marvell_nand.c @@ -5,6 +5,73 @@ * Copyright (C) 2017 Marvell * Author: Miquel RAYNAL * + * + * This NAND controller driver handles two versions of the hardware, + * one is called NFCv1 and is available on PXA SoCs and the other is + * called NFCv2 and is available on Armada SoCs. + * + * The main visible difference is that NFCv1 only has Hamming ECC + * capabilities, while NFCv2 also embeds a BCH ECC engine. Also, DMA + * is not used with NFCv2. + * + * The ECC layouts are depicted in details in Marvell AN-379, but here + * is a brief description. + * + * When using Hamming, the data is split in 512B chunks (either 1, 2 + * or 4) and each chunk will have its own ECC "digest" of 6B at the + * beginning of the OOB area and eventually the remaining free OOB + * bytes (also called "spare" bytes in the driver). This engine + * corrects up to 1 bit per chunk and detects reliably an error if + * there are at most 2 bitflips. Here is the page layout used by the + * controller when Hamming is chosen: + * + * +-------------------------------------------------------------+ + * | Data 1 | ... | Data N | ECC 1 | ... | ECCN | Free OOB bytes | + * +-------------------------------------------------------------+ + * + * When using the BCH engine, there are N identical (data + free OOB + + * ECC) sections and potentially an extra one to deal with + * configurations where the chosen (data + free OOB + ECC) sizes do + * not align with the page (data + OOB) size. ECC bytes are always + * 30B per ECC chunk. Here is the page layout used by the controller + * when BCH is chosen: + * + * +----------------------------------------- + * | Data 1 | Free OOB bytes 1 | ECC 1 | ... + * +----------------------------------------- + * + * ------------------------------------------- + * ... | Data N | Free OOB bytes N | ECC N | + * ------------------------------------------- + * + * --------------------------------------------+ + * Last Data | Last Free OOB bytes | Last ECC | + * --------------------------------------------+ + * + * In both cases, the layout seen by the user is always: all data + * first, then all free OOB bytes and finally all ECC bytes. With BCH, + * ECC bytes are 30B long and are padded with 0xFF to align on 32 + * bytes. + * + * The controller has certain limitations that are handled by the + * driver: + * - It can only read 2k at a time. To overcome this limitation, the + * driver issues data cycles on the bus, without issuing new + * CMD + ADDR cycles. The Marvell term is "naked" operations. + * - The ECC strength in BCH mode cannot be tuned. It is fixed 16 + * bits. What can be tuned is the ECC block size as long as it + * stays between 512B and 2kiB. It's usually chosen based on the + * chip ECC requirements. For instance, using 2kiB ECC chunks + * provides 4b/512B correctability. + * - The controller will always treat data bytes, free OOB bytes + * and ECC bytes in that order, no matter what the real layout is + * (which is usually all data then all OOB bytes). The + * marvell_nfc_layouts array below contains the currently + * supported layouts. + * - Because of these weird layouts, the Bad Block Markers can be + * located in data section. In this case, the NAND_BBT_NO_OOB_BBM + * option must be set to prevent scanning/writing bad block + * markers. */ #include From 64a225881705f78537e477c8eec1a9f5b6bc1f73 Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Sun, 5 Aug 2018 16:52:57 +0200 Subject: [PATCH 233/302] Documentation: mtd: remove stale pxa3xx NAND controller documentation It is preferred to have the documentation about the drivers directly embedded in the driver itself. Remove this file now that the most important information from this file have been re-written in marvell_nand.c. Signed-off-by: Miquel Raynal Acked-by: Boris Brezillon Acked-by: Ezequiel Garcia --- Documentation/mtd/nand/pxa3xx-nand.txt | 113 ------------------------- 1 file changed, 113 deletions(-) delete mode 100644 Documentation/mtd/nand/pxa3xx-nand.txt diff --git a/Documentation/mtd/nand/pxa3xx-nand.txt b/Documentation/mtd/nand/pxa3xx-nand.txt deleted file mode 100644 index 1074cbc67ec6..000000000000 --- a/Documentation/mtd/nand/pxa3xx-nand.txt +++ /dev/null @@ -1,113 +0,0 @@ - -About this document -=================== - -Some notes about Marvell's NAND controller available in PXA and Armada 370/XP -SoC (aka NFCv1 and NFCv2), with an emphasis on the latter. - -NFCv2 controller background -=========================== - -The controller has a 2176 bytes FIFO buffer. Therefore, in order to support -larger pages, I/O operations on 4 KiB and 8 KiB pages is done with a set of -chunked transfers. - -For instance, if we choose a 2048 data chunk and set "BCH" ECC (see below) -we'll have this layout in the pages: - - ------------------------------------------------------------------------------ - | 2048B data | 32B spare | 30B ECC || 2048B data | 32B spare | 30B ECC | ... | - ------------------------------------------------------------------------------ - -The driver reads the data and spare portions independently and builds an internal -buffer with this layout (in the 4 KiB page case): - - ------------------------------------------ - | 4096B data | 64B spare | - ------------------------------------------ - -Also, for the READOOB command the driver disables the ECC and reads a 'spare + ECC' -OOB, one per chunk read. - - ------------------------------------------------------------------- - | 4096B data | 32B spare | 30B ECC | 32B spare | 30B ECC | - ------------------------------------------------------------------- - -So, in order to achieve reading (for instance), we issue several READ0 commands -(with some additional controller-specific magic) and read two chunks of 2080B -(2048 data + 32 spare) each. -The driver accommodates this data to expose the NAND core a contiguous buffer -(4096 data + spare) or (4096 + spare + ECC + spare + ECC). - -ECC -=== - -The controller has built-in hardware ECC capabilities. In addition it is -configurable between two modes: 1) Hamming, 2) BCH. - -Note that the actual BCH mode: BCH-4 or BCH-8 will depend on the way -the controller is configured to transfer the data. - -In the BCH mode the ECC code will be calculated for each transferred chunk -and expected to be located (when reading/programming) right after the spare -bytes as the figure above shows. - -So, repeating the above scheme, a 2048B data chunk will be followed by 32B -spare, and then the ECC controller will read/write the ECC code (30B in -this case): - - ------------------------------------ - | 2048B data | 32B spare | 30B ECC | - ------------------------------------ - -If the ECC mode is 'BCH' then the ECC is *always* 30 bytes long. -If the ECC mode is 'Hamming' the ECC is 6 bytes long, for each 512B block. -So in Hamming mode, a 2048B page will have a 24B ECC. - -Despite all of the above, the controller requires the driver to only read or -write in multiples of 8-bytes, because the data buffer is 64-bits. - -OOB -=== - -Because of the above scheme, and because the "spare" OOB is really located in -the middle of a page, spare OOB cannot be read or write independently of the -data area. In other words, in order to read the OOB (aka READOOB), the entire -page (aka READ0) has to be read. - -In the same sense, in order to write to the spare OOB the driver has to write -an *entire* page. - -Factory bad blocks handling -=========================== - -Given the ECC BCH requires to layout the device's pages in a split -data/OOB/data/OOB way, the controller has a view of the flash page that's -different from the specified (aka the manufacturer's) view. In other words, - -Factory view: - - ----------------------------------------------- - | Data |x OOB | - ----------------------------------------------- - -Driver's view: - - ----------------------------------------------- - | Data | OOB | Data x | OOB | - ----------------------------------------------- - -It can be seen from the above, that the factory bad block marker must be -searched within the 'data' region, and not in the usual OOB region. - -In addition, this means under regular usage the driver will write such -position (since it belongs to the data region) and every used block is -likely to be marked as bad. - -For this reason, marking the block as bad in the OOB is explicitly -disabled by using the NAND_BBT_NO_OOB_BBM option in the driver. The rationale -for this is that there's no point in marking a block as bad, because good -blocks are also 'marked as bad' (in the OOB BBM sense) under normal usage. - -Instead, the driver relies on the bad block table alone, and should only perform -the bad block scan on the very first time (when the device hasn't been used). From 434655af6a187129d8114640443b27d2cecfb979 Mon Sep 17 00:00:00 2001 From: Kurt Kanzenbach Date: Mon, 13 Aug 2018 09:18:45 +0200 Subject: [PATCH 234/302] mtd: rawnand: fsl_ifc: check result of SRAM initialization The SRAM initialization might fail. If that happens further NAND operations won't be successful. Therefore, the chip init routine should fail if the SRAM initialization didn't work. Signed-off-by: Kurt Kanzenbach Signed-off-by: Miquel Raynal --- drivers/mtd/nand/raw/fsl_ifc_nand.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/drivers/mtd/nand/raw/fsl_ifc_nand.c b/drivers/mtd/nand/raw/fsl_ifc_nand.c index 24f59d0066af..e4f5792dc589 100644 --- a/drivers/mtd/nand/raw/fsl_ifc_nand.c +++ b/drivers/mtd/nand/raw/fsl_ifc_nand.c @@ -761,7 +761,7 @@ static const struct nand_controller_ops fsl_ifc_controller_ops = { .attach_chip = fsl_ifc_attach_chip, }; -static void fsl_ifc_sram_init(struct fsl_ifc_mtd *priv) +static int fsl_ifc_sram_init(struct fsl_ifc_mtd *priv) { struct fsl_ifc_ctrl *ctrl = priv->ctrl; struct fsl_ifc_runtime __iomem *ifc_runtime = ctrl->rregs; @@ -805,12 +805,16 @@ static void fsl_ifc_sram_init(struct fsl_ifc_mtd *priv) wait_event_timeout(ctrl->nand_wait, ctrl->nand_stat, msecs_to_jiffies(IFC_TIMEOUT_MSECS)); - if (ctrl->nand_stat != IFC_NAND_EVTER_STAT_OPC) + if (ctrl->nand_stat != IFC_NAND_EVTER_STAT_OPC) { pr_err("fsl-ifc: Failed to Initialise SRAM\n"); + return -ETIMEDOUT; + } /* Restore CSOR and CSOR_ext */ ifc_out32(csor, &ifc_global->csor_cs[cs].csor); ifc_out32(csor_ext, &ifc_global->csor_cs[cs].csor_ext); + + return 0; } static int fsl_ifc_chip_init(struct fsl_ifc_mtd *priv) @@ -914,8 +918,13 @@ static int fsl_ifc_chip_init(struct fsl_ifc_mtd *priv) chip->ecc.algo = NAND_ECC_HAMMING; } - if (ctrl->version >= FSL_IFC_VERSION_1_1_0) - fsl_ifc_sram_init(priv); + if (ctrl->version >= FSL_IFC_VERSION_1_1_0) { + int ret; + + ret = fsl_ifc_sram_init(priv); + if (ret) + return ret; + } /* * As IFC version 2.0.0 has 16KB of internal SRAM as compared to older From ff8648f29fe58c2d94d32a076d2de7b92be4b485 Mon Sep 17 00:00:00 2001 From: Kurt Kanzenbach Date: Mon, 13 Aug 2018 09:18:46 +0200 Subject: [PATCH 235/302] mtd: rawnand: fsl_ifc: fixup SRAM init for newer ctrl versions Newer versions of the IFC controller use a different method of initializing the internal SRAM: Instead of reading from flash, a bit in the NAND configuration register has to be set in order to trigger the self-initializing process. Signed-off-by: Kurt Kanzenbach Signed-off-by: Miquel Raynal --- drivers/mtd/nand/raw/fsl_ifc_nand.c | 33 +++++++++++++++++++++++------ include/linux/fsl_ifc.h | 2 ++ 2 files changed, 28 insertions(+), 7 deletions(-) diff --git a/drivers/mtd/nand/raw/fsl_ifc_nand.c b/drivers/mtd/nand/raw/fsl_ifc_nand.c index e4f5792dc589..7e7729df7827 100644 --- a/drivers/mtd/nand/raw/fsl_ifc_nand.c +++ b/drivers/mtd/nand/raw/fsl_ifc_nand.c @@ -30,6 +30,7 @@ #include #include #include +#include #define ERR_BYTE 0xFF /* Value returned for read bytes when read failed */ @@ -769,6 +770,27 @@ static int fsl_ifc_sram_init(struct fsl_ifc_mtd *priv) uint32_t csor = 0, csor_8k = 0, csor_ext = 0; uint32_t cs = priv->bank; + if (ctrl->version < FSL_IFC_VERSION_1_1_0) + return 0; + + if (ctrl->version > FSL_IFC_VERSION_1_1_0) { + u32 ncfgr, status; + int ret; + + /* Trigger auto initialization */ + ncfgr = ifc_in32(&ifc_runtime->ifc_nand.ncfgr); + ifc_out32(ncfgr | IFC_NAND_NCFGR_SRAM_INIT_EN, &ifc_runtime->ifc_nand.ncfgr); + + /* Wait until done */ + ret = readx_poll_timeout(ifc_in32, &ifc_runtime->ifc_nand.ncfgr, + status, !(status & IFC_NAND_NCFGR_SRAM_INIT_EN), + 10, IFC_TIMEOUT_MSECS * 1000); + if (ret) + dev_err(priv->dev, "Failed to initialize SRAM!\n"); + + return ret; + } + /* Save CSOR and CSOR_ext */ csor = ifc_in32(&ifc_global->csor_cs[cs].csor); csor_ext = ifc_in32(&ifc_global->csor_cs[cs].csor_ext); @@ -825,6 +847,7 @@ static int fsl_ifc_chip_init(struct fsl_ifc_mtd *priv) struct nand_chip *chip = &priv->chip; struct mtd_info *mtd = nand_to_mtd(&priv->chip); u32 csor; + int ret; /* Fill in fsl_ifc_mtd structure */ mtd->dev.parent = priv->dev; @@ -918,13 +941,9 @@ static int fsl_ifc_chip_init(struct fsl_ifc_mtd *priv) chip->ecc.algo = NAND_ECC_HAMMING; } - if (ctrl->version >= FSL_IFC_VERSION_1_1_0) { - int ret; - - ret = fsl_ifc_sram_init(priv); - if (ret) - return ret; - } + ret = fsl_ifc_sram_init(priv); + if (ret) + return ret; /* * As IFC version 2.0.0 has 16KB of internal SRAM as compared to older diff --git a/include/linux/fsl_ifc.h b/include/linux/fsl_ifc.h index 3fdfede2f0f3..5f343b796ad9 100644 --- a/include/linux/fsl_ifc.h +++ b/include/linux/fsl_ifc.h @@ -274,6 +274,8 @@ */ /* Auto Boot Mode */ #define IFC_NAND_NCFGR_BOOT 0x80000000 +/* SRAM Initialization */ +#define IFC_NAND_NCFGR_SRAM_INIT_EN 0x20000000 /* Addressing Mode-ROW0+n/COL0 */ #define IFC_NAND_NCFGR_ADDR_MODE_RC0 0x00000000 /* Addressing Mode-ROW0+n/COL0+n */ From f1bf52e8657299ecc85db657ee825923a082de28 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Mon, 20 Aug 2018 12:26:36 +0900 Subject: [PATCH 236/302] mtd: rawnand: denali: use SPDX-License-Identifier and fix license mismatch Use SPDX-License-Identifier instead of the license boilerplates. This conversion makes it easier for us to scan the license, then I notice license mismatch problems. The license blocks in denali* indicate GPL-2.0 "only", while the MODULE_LICENSE in denali.c and denali_dt.c is GPL-2.0 "or later" as explained in include/linux/module.h as follows: "GPL" [GNU Public License v2 or later] "GPL v2" [GNU Public License v2] I fixed the MODULE_LICENSE tags, assuming the license blocks are the authors' intention. Also, add missing MODULE_DESCRIPTION/AUTHOR to denali.c While I am touching the license things, I added my credit to denali.c because this driver was largely re-written by me in 2017. Signed-off-by: Masahiro Yamada Signed-off-by: Miquel Raynal --- drivers/mtd/nand/raw/denali.c | 17 +++++++---------- drivers/mtd/nand/raw/denali.h | 10 +--------- drivers/mtd/nand/raw/denali_dt.c | 12 ++---------- drivers/mtd/nand/raw/denali_pci.c | 10 +--------- 4 files changed, 11 insertions(+), 38 deletions(-) diff --git a/drivers/mtd/nand/raw/denali.c b/drivers/mtd/nand/raw/denali.c index 5ff2ca163884..177453dfaa07 100644 --- a/drivers/mtd/nand/raw/denali.c +++ b/drivers/mtd/nand/raw/denali.c @@ -1,15 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0 /* * NAND Flash Controller Device Driver * Copyright © 2009-2010, Intel Corporation and its suppliers. * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. + * Copyright (c) 2017 Socionext Inc. + * Reworked by Masahiro Yamada */ #include @@ -25,8 +20,6 @@ #include "denali.h" -MODULE_LICENSE("GPL"); - #define DENALI_NAND_NAME "denali-nand" /* for Indexed Addressing */ @@ -1391,3 +1384,7 @@ void denali_remove(struct denali_nand_info *denali) denali_disable_irq(denali); } EXPORT_SYMBOL(denali_remove); + +MODULE_DESCRIPTION("Driver core for Denali NAND controller"); +MODULE_AUTHOR("Intel Corporation and its suppliers"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/mtd/nand/raw/denali.h b/drivers/mtd/nand/raw/denali.h index 1f8feaf924eb..57a5498f58bb 100644 --- a/drivers/mtd/nand/raw/denali.h +++ b/drivers/mtd/nand/raw/denali.h @@ -1,15 +1,7 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* * NAND Flash Controller Device Driver * Copyright (c) 2009 - 2010, Intel Corporation and its suppliers. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. */ #ifndef __DENALI_H__ diff --git a/drivers/mtd/nand/raw/denali_dt.c b/drivers/mtd/nand/raw/denali_dt.c index 0faaad032e5f..7c6a8a426606 100644 --- a/drivers/mtd/nand/raw/denali_dt.c +++ b/drivers/mtd/nand/raw/denali_dt.c @@ -1,16 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0 /* * NAND Flash Controller Device Driver for DT * * Copyright © 2011, Picochip. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. */ #include @@ -202,6 +194,6 @@ static struct platform_driver denali_dt_driver = { }; module_platform_driver(denali_dt_driver); -MODULE_LICENSE("GPL"); +MODULE_LICENSE("GPL v2"); MODULE_AUTHOR("Jamie Iles"); MODULE_DESCRIPTION("DT driver for Denali NAND controller"); diff --git a/drivers/mtd/nand/raw/denali_pci.c b/drivers/mtd/nand/raw/denali_pci.c index 7c8efc4c7bdf..48e9ac54ad53 100644 --- a/drivers/mtd/nand/raw/denali_pci.c +++ b/drivers/mtd/nand/raw/denali_pci.c @@ -1,15 +1,7 @@ +// SPDX-License-Identifier: GPL-2.0 /* * NAND Flash Controller Device Driver * Copyright © 2009-2010, Intel Corporation and its suppliers. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. */ #include From ab0fb17c7d46406e1aac2dda265874751946626d Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 27 Aug 2018 10:59:43 +0200 Subject: [PATCH 237/302] mtd: rawnand: qcom: don't include dma-direct.h A recent commit removed the incorrect use of phys_to_dma from this driver, but failed to remove the dma-direct.h include, so do that now. Signed-off-by: Christoph Hellwig Signed-off-by: Miquel Raynal --- drivers/mtd/nand/raw/qcom_nandc.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/mtd/nand/raw/qcom_nandc.c b/drivers/mtd/nand/raw/qcom_nandc.c index d1d470bb32e4..d2831b0b28fb 100644 --- a/drivers/mtd/nand/raw/qcom_nandc.c +++ b/drivers/mtd/nand/raw/qcom_nandc.c @@ -23,7 +23,6 @@ #include #include #include -#include /* XXX: drivers shall never use this directly! */ /* NANDc reg offsets */ #define NAND_FLASH_CMD 0x00 From a9fdba0b0e5f63646fdf65e0e01dd757b11cec83 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Mon, 27 Aug 2018 20:52:34 -0500 Subject: [PATCH 238/302] mtd: rawnand: Convert to using %pOFn instead of device_node.name In preparation to remove the node name pointer from struct device_node, convert printf users to use the %pOFn format specifier. Cc: Boris Brezillon Cc: Miquel Raynal Cc: Richard Weinberger Cc: David Woodhouse Cc: Brian Norris Cc: Marek Vasut Cc: linux-mtd@lists.infradead.org Signed-off-by: Rob Herring Acked-by: Boris Brezillon Signed-off-by: Miquel Raynal --- drivers/mtd/nand/raw/fsl_upm.c | 4 ++-- drivers/mtd/nand/raw/ndfc.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/mtd/nand/raw/fsl_upm.c b/drivers/mtd/nand/raw/fsl_upm.c index a88e2cf66e0f..ca82727eca94 100644 --- a/drivers/mtd/nand/raw/fsl_upm.c +++ b/drivers/mtd/nand/raw/fsl_upm.c @@ -184,8 +184,8 @@ static int fun_chip_init(struct fsl_upm_nand *fun, return -ENODEV; nand_set_flash_node(&fun->chip, flash_np); - mtd->name = kasprintf(GFP_KERNEL, "0x%llx.%s", (u64)io_res->start, - flash_np->name); + mtd->name = kasprintf(GFP_KERNEL, "0x%llx.%pOFn", (u64)io_res->start, + flash_np); if (!mtd->name) { ret = -ENOMEM; goto err; diff --git a/drivers/mtd/nand/raw/ndfc.c b/drivers/mtd/nand/raw/ndfc.c index 540fa1a0ea24..b193f373f235 100644 --- a/drivers/mtd/nand/raw/ndfc.c +++ b/drivers/mtd/nand/raw/ndfc.c @@ -174,8 +174,8 @@ static int ndfc_chip_init(struct ndfc_controller *ndfc, return -ENODEV; nand_set_flash_node(chip, flash_np); - mtd->name = kasprintf(GFP_KERNEL, "%s.%s", dev_name(&ndfc->ofdev->dev), - flash_np->name); + mtd->name = kasprintf(GFP_KERNEL, "%s.%pOFn", dev_name(&ndfc->ofdev->dev), + flash_np); if (!mtd->name) { ret = -ENOMEM; goto err; From 81592c69c9ed34138fef8b6fe3a990f8380148f4 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Thu, 23 Aug 2018 14:33:32 -0500 Subject: [PATCH 239/302] mtd: rawnand: jz4780: use struct_size() in devm_kzalloc() One of the more common cases of allocation size calculations is finding the size of a structure that has a zero-sized array at the end, along with memory for some number of elements for that array. For example: struct foo { int stuff; void *entry[]; }; instance = devm_kzalloc(dev, sizeof(struct foo) + sizeof(void *) * count, GFP_KERNEL); Instead of leaving these open-coded and prone to type mistakes, we can now use the new struct_size() helper: instance = devm_kzalloc(dev, struct_size(instance, entry, count), GFP_KERNEL); Signed-off-by: Gustavo A. R. Silva Reviewed-by: Boris Brezillon Reviewed-by: Kees Cook Signed-off-by: Miquel Raynal --- drivers/mtd/nand/raw/jz4780_nand.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mtd/nand/raw/jz4780_nand.c b/drivers/mtd/nand/raw/jz4780_nand.c index db4fa60bd52a..ac6239588f26 100644 --- a/drivers/mtd/nand/raw/jz4780_nand.c +++ b/drivers/mtd/nand/raw/jz4780_nand.c @@ -352,7 +352,7 @@ static int jz4780_nand_probe(struct platform_device *pdev) return -ENODEV; } - nfc = devm_kzalloc(dev, sizeof(*nfc) + (sizeof(nfc->cs[0]) * num_banks), GFP_KERNEL); + nfc = devm_kzalloc(dev, struct_size(nfc, cs, num_banks), GFP_KERNEL); if (!nfc) return -ENOMEM; From 2f91eb6951d9e9d8d751a390cfd3e8b0216d88ef Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Thu, 23 Aug 2018 20:09:38 -0500 Subject: [PATCH 240/302] mtd: rawnand: atmel: use struct_size() in devm_kzalloc() One of the more common cases of allocation size calculations is finding the size of a structure that has a zero-sized array at the end, along with memory for some number of elements for that array. For example: struct foo { int stuff; void *entry[]; }; instance = devm_kzalloc(dev, sizeof(struct foo) + sizeof(void *) * count, GFP_KERNEL); Instead of leaving these open-coded and prone to type mistakes, we can now use the new struct_size() helper: instance = devm_kzalloc(dev, struct_size(instance, entry, count), GFP_KERNEL); This issue was detected with the help of Coccinelle. Signed-off-by: Gustavo A. R. Silva Reviewed-by: Kees Cook Signed-off-by: Miquel Raynal --- drivers/mtd/nand/raw/atmel/nand-controller.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/mtd/nand/raw/atmel/nand-controller.c b/drivers/mtd/nand/raw/atmel/nand-controller.c index 525e1325841d..8b9e05ac24ee 100644 --- a/drivers/mtd/nand/raw/atmel/nand-controller.c +++ b/drivers/mtd/nand/raw/atmel/nand-controller.c @@ -1577,9 +1577,7 @@ static struct atmel_nand *atmel_nand_create(struct atmel_nand_controller *nc, return ERR_PTR(-EINVAL); } - nand = devm_kzalloc(nc->dev, - sizeof(*nand) + (numcs * sizeof(*nand->cs)), - GFP_KERNEL); + nand = devm_kzalloc(nc->dev, struct_size(nand, cs, numcs), GFP_KERNEL); if (!nand) { dev_err(nc->dev, "Failed to allocate NAND object\n"); return ERR_PTR(-ENOMEM); From 47bd59e538d4e7b3ad9c18bef5c1052657bdff59 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Thu, 6 Sep 2018 14:05:13 +0200 Subject: [PATCH 241/302] mtd: rawnand: plat_nand: Pass a nand_chip object to all platform_nand_ctrl hooks Let's make the raw NAND API consistent by patching all helpers and hooks to take a nand_chip object instead of an mtd_info one or remove the mtd_info object when both are passed. In order to do that, we first need to update the platform_nand_ctrl hooks to take a nand_chip object instead of an mtd_info. We add temporary plat_nand_xxx() wrappers to the do the mtd -> chip conversion, but those will be dropped when patching nand_chip hooks to take a nand_chip object. Signed-off-by: Boris Brezillon Reviewed-by: Alexander Sverdlin Acked-by: Alexander Sverdlin Acked-by: Robert Jarzmik Acked-by: Krzysztof Halasa Acked-by: Paul Burton Signed-off-by: Miquel Raynal --- arch/arm/mach-ep93xx/snappercl15.c | 7 +-- arch/arm/mach-ep93xx/ts72xx.c | 7 +-- arch/arm/mach-imx/mach-qong.c | 11 +++-- arch/arm/mach-ixp4xx/ixdp425-setup.c | 3 +- arch/arm/mach-omap1/board-fsample.c | 2 +- arch/arm/mach-omap1/board-h2.c | 2 +- arch/arm/mach-omap1/board-h3.c | 2 +- arch/arm/mach-omap1/board-nand.c | 3 +- arch/arm/mach-omap1/board-perseus2.c | 2 +- arch/arm/mach-omap1/common.h | 4 +- arch/arm/mach-orion5x/ts78xx-setup.c | 18 +++----- arch/arm/mach-pxa/balloon3.c | 8 ++-- arch/arm/mach-pxa/em-x270.c | 5 +-- arch/arm/mach-pxa/palmtx.c | 5 +-- arch/mips/alchemy/devboards/db1200.c | 5 +-- arch/mips/alchemy/devboards/db1300.c | 5 +-- arch/mips/alchemy/devboards/db1550.c | 5 +-- arch/mips/netlogic/xlr/platform-flash.c | 4 +- arch/mips/pnx833x/common/platform.c | 3 +- arch/mips/rb532/devices.c | 5 +-- arch/sh/boards/mach-migor/setup.c | 6 +-- drivers/mtd/nand/raw/plat_nand.c | 57 ++++++++++++++++++++++--- include/linux/mtd/rawnand.h | 10 ++--- 23 files changed, 102 insertions(+), 77 deletions(-) diff --git a/arch/arm/mach-ep93xx/snappercl15.c b/arch/arm/mach-ep93xx/snappercl15.c index 45940c1d7787..aa03ea79c5f5 100644 --- a/arch/arm/mach-ep93xx/snappercl15.c +++ b/arch/arm/mach-ep93xx/snappercl15.c @@ -45,10 +45,9 @@ #define NAND_CTRL_ADDR(chip) (chip->IO_ADDR_W + 0x40) -static void snappercl15_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, +static void snappercl15_nand_cmd_ctrl(struct nand_chip *chip, int cmd, unsigned int ctrl) { - struct nand_chip *chip = mtd_to_nand(mtd); static u16 nand_state = SNAPPERCL15_NAND_WPN; u16 set; @@ -73,10 +72,8 @@ static void snappercl15_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, __raw_writew((cmd & 0xff) | nand_state, chip->IO_ADDR_W); } -static int snappercl15_nand_dev_ready(struct mtd_info *mtd) +static int snappercl15_nand_dev_ready(struct nand_chip *chip) { - struct nand_chip *chip = mtd_to_nand(mtd); - return !!(__raw_readw(NAND_CTRL_ADDR(chip)) & SNAPPERCL15_NAND_RDY); } diff --git a/arch/arm/mach-ep93xx/ts72xx.c b/arch/arm/mach-ep93xx/ts72xx.c index c089a2a4fe30..26259dd9e951 100644 --- a/arch/arm/mach-ep93xx/ts72xx.c +++ b/arch/arm/mach-ep93xx/ts72xx.c @@ -76,11 +76,9 @@ static void __init ts72xx_map_io(void) #define TS72XX_NAND_CONTROL_ADDR_LINE 22 /* 0xN0400000 */ #define TS72XX_NAND_BUSY_ADDR_LINE 23 /* 0xN0800000 */ -static void ts72xx_nand_hwcontrol(struct mtd_info *mtd, +static void ts72xx_nand_hwcontrol(struct nand_chip *chip, int cmd, unsigned int ctrl) { - struct nand_chip *chip = mtd_to_nand(mtd); - if (ctrl & NAND_CTRL_CHANGE) { void __iomem *addr = chip->IO_ADDR_R; unsigned char bits; @@ -99,9 +97,8 @@ static void ts72xx_nand_hwcontrol(struct mtd_info *mtd, __raw_writeb(cmd, chip->IO_ADDR_W); } -static int ts72xx_nand_device_ready(struct mtd_info *mtd) +static int ts72xx_nand_device_ready(struct nand_chip *chip) { - struct nand_chip *chip = mtd_to_nand(mtd); void __iomem *addr = chip->IO_ADDR_R; addr += (1 << TS72XX_NAND_BUSY_ADDR_LINE); diff --git a/arch/arm/mach-imx/mach-qong.c b/arch/arm/mach-imx/mach-qong.c index 42a700053103..ff015f603ac9 100644 --- a/arch/arm/mach-imx/mach-qong.c +++ b/arch/arm/mach-imx/mach-qong.c @@ -129,10 +129,9 @@ static void qong_init_nor_mtd(void) /* * Hardware specific access to control-lines */ -static void qong_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl) +static void qong_nand_cmd_ctrl(struct nand_chip *nand_chip, int cmd, + unsigned int ctrl) { - struct nand_chip *nand_chip = mtd_to_nand(mtd); - if (cmd == NAND_CMD_NONE) return; @@ -145,14 +144,14 @@ static void qong_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl) /* * Read the Device Ready pin. */ -static int qong_nand_device_ready(struct mtd_info *mtd) +static int qong_nand_device_ready(struct nand_chip *chip) { return gpio_get_value(IOMUX_TO_GPIO(MX31_PIN_NFRB)); } -static void qong_nand_select_chip(struct mtd_info *mtd, int chip) +static void qong_nand_select_chip(struct nand_chip *chip, int cs) { - if (chip >= 0) + if (cs >= 0) gpio_set_value(IOMUX_TO_GPIO(MX31_PIN_NFCE_B), 0); else gpio_set_value(IOMUX_TO_GPIO(MX31_PIN_NFCE_B), 1); diff --git a/arch/arm/mach-ixp4xx/ixdp425-setup.c b/arch/arm/mach-ixp4xx/ixdp425-setup.c index 3ec829d52cdd..7c39edc121ba 100644 --- a/arch/arm/mach-ixp4xx/ixdp425-setup.c +++ b/arch/arm/mach-ixp4xx/ixdp425-setup.c @@ -75,9 +75,8 @@ static struct mtd_partition ixdp425_partitions[] = { }; static void -ixdp425_flash_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl) +ixdp425_flash_nand_cmd_ctrl(struct nand_chip *this, int cmd, unsigned int ctrl) { - struct nand_chip *this = mtd_to_nand(mtd); int offset = (int)nand_get_controller_data(this); if (ctrl & NAND_CTRL_CHANGE) { diff --git a/arch/arm/mach-omap1/board-fsample.c b/arch/arm/mach-omap1/board-fsample.c index 69bd601feb83..e9f512a0602e 100644 --- a/arch/arm/mach-omap1/board-fsample.c +++ b/arch/arm/mach-omap1/board-fsample.c @@ -186,7 +186,7 @@ static struct platform_device nor_device = { #define FSAMPLE_NAND_RB_GPIO_PIN 62 -static int nand_dev_ready(struct mtd_info *mtd) +static int nand_dev_ready(struct nand_chip *chip) { return gpio_get_value(FSAMPLE_NAND_RB_GPIO_PIN); } diff --git a/arch/arm/mach-omap1/board-h2.c b/arch/arm/mach-omap1/board-h2.c index 9aeb8ad8c327..d5dd2acd6f78 100644 --- a/arch/arm/mach-omap1/board-h2.c +++ b/arch/arm/mach-omap1/board-h2.c @@ -182,7 +182,7 @@ static struct mtd_partition h2_nand_partitions[] = { #define H2_NAND_RB_GPIO_PIN 62 -static int h2_nand_dev_ready(struct mtd_info *mtd) +static int h2_nand_dev_ready(struct nand_chip *chip) { return gpio_get_value(H2_NAND_RB_GPIO_PIN); } diff --git a/arch/arm/mach-omap1/board-h3.c b/arch/arm/mach-omap1/board-h3.c index 2edcd6356f2d..a75856fe4259 100644 --- a/arch/arm/mach-omap1/board-h3.c +++ b/arch/arm/mach-omap1/board-h3.c @@ -185,7 +185,7 @@ static struct mtd_partition nand_partitions[] = { #define H3_NAND_RB_GPIO_PIN 10 -static int nand_dev_ready(struct mtd_info *mtd) +static int nand_dev_ready(struct nand_chip *chip) { return gpio_get_value(H3_NAND_RB_GPIO_PIN); } diff --git a/arch/arm/mach-omap1/board-nand.c b/arch/arm/mach-omap1/board-nand.c index 1bffbb4e050f..59d56a30bc63 100644 --- a/arch/arm/mach-omap1/board-nand.c +++ b/arch/arm/mach-omap1/board-nand.c @@ -20,9 +20,8 @@ #include "common.h" -void omap1_nand_cmd_ctl(struct mtd_info *mtd, int cmd, unsigned int ctrl) +void omap1_nand_cmd_ctl(struct nand_chip *this, int cmd, unsigned int ctrl) { - struct nand_chip *this = mtd_to_nand(mtd); unsigned long mask; if (cmd == NAND_CMD_NONE) diff --git a/arch/arm/mach-omap1/board-perseus2.c b/arch/arm/mach-omap1/board-perseus2.c index b4951eb82898..c61c7c7520ca 100644 --- a/arch/arm/mach-omap1/board-perseus2.c +++ b/arch/arm/mach-omap1/board-perseus2.c @@ -144,7 +144,7 @@ static struct platform_device nor_device = { #define P2_NAND_RB_GPIO_PIN 62 -static int nand_dev_ready(struct mtd_info *mtd) +static int nand_dev_ready(struct nand_chip *chip) { return gpio_get_value(P2_NAND_RB_GPIO_PIN); } diff --git a/arch/arm/mach-omap1/common.h b/arch/arm/mach-omap1/common.h index c6537d2c2859..504b959ba5cf 100644 --- a/arch/arm/mach-omap1/common.h +++ b/arch/arm/mach-omap1/common.h @@ -26,7 +26,6 @@ #ifndef __ARCH_ARM_MACH_OMAP1_COMMON_H #define __ARCH_ARM_MACH_OMAP1_COMMON_H -#include #include #include @@ -82,7 +81,8 @@ void omap1_restart(enum reboot_mode, const char *); extern void __init omap_check_revision(void); -extern void omap1_nand_cmd_ctl(struct mtd_info *mtd, int cmd, +struct nand_chip; +extern void omap1_nand_cmd_ctl(struct nand_chip *this, int cmd, unsigned int ctrl); extern void omap1_timer_init(void); diff --git a/arch/arm/mach-orion5x/ts78xx-setup.c b/arch/arm/mach-orion5x/ts78xx-setup.c index 94778739e38f..48d85ddf7c31 100644 --- a/arch/arm/mach-orion5x/ts78xx-setup.c +++ b/arch/arm/mach-orion5x/ts78xx-setup.c @@ -131,11 +131,9 @@ static void ts78xx_ts_rtc_unload(void) * NAND_CLE: bit 1 -> bit 1 * NAND_ALE: bit 2 -> bit 0 */ -static void ts78xx_ts_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, - unsigned int ctrl) +static void ts78xx_ts_nand_cmd_ctrl(struct nand_chip *this, int cmd, + unsigned int ctrl) { - struct nand_chip *this = mtd_to_nand(mtd); - if (ctrl & NAND_CTRL_CHANGE) { unsigned char bits; @@ -150,15 +148,14 @@ static void ts78xx_ts_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, writeb(cmd, this->IO_ADDR_W); } -static int ts78xx_ts_nand_dev_ready(struct mtd_info *mtd) +static int ts78xx_ts_nand_dev_ready(struct nand_chip *chip) { return readb(TS_NAND_CTRL) & 0x20; } -static void ts78xx_ts_nand_write_buf(struct mtd_info *mtd, - const uint8_t *buf, int len) +static void ts78xx_ts_nand_write_buf(struct nand_chip *chip, + const uint8_t *buf, int len) { - struct nand_chip *chip = mtd_to_nand(mtd); void __iomem *io_base = chip->IO_ADDR_W; unsigned long off = ((unsigned long)buf & 3); int sz; @@ -182,10 +179,9 @@ static void ts78xx_ts_nand_write_buf(struct mtd_info *mtd, writesb(io_base, buf, len); } -static void ts78xx_ts_nand_read_buf(struct mtd_info *mtd, - uint8_t *buf, int len) +static void ts78xx_ts_nand_read_buf(struct nand_chip *chip, + uint8_t *buf, int len) { - struct nand_chip *chip = mtd_to_nand(mtd); void __iomem *io_base = chip->IO_ADDR_R; unsigned long off = ((unsigned long)buf & 3); int sz; diff --git a/arch/arm/mach-pxa/balloon3.c b/arch/arm/mach-pxa/balloon3.c index af46d2182533..71fda90b9599 100644 --- a/arch/arm/mach-pxa/balloon3.c +++ b/arch/arm/mach-pxa/balloon3.c @@ -571,9 +571,9 @@ static inline void balloon3_i2c_init(void) {} * NAND ******************************************************************************/ #if defined(CONFIG_MTD_NAND_PLATFORM)||defined(CONFIG_MTD_NAND_PLATFORM_MODULE) -static void balloon3_nand_cmd_ctl(struct mtd_info *mtd, int cmd, unsigned int ctrl) +static void balloon3_nand_cmd_ctl(struct nand_chip *this, int cmd, + unsigned int ctrl) { - struct nand_chip *this = mtd_to_nand(mtd); uint8_t balloon3_ctl_set = 0, balloon3_ctl_clr = 0; if (ctrl & NAND_CTRL_CHANGE) { @@ -600,7 +600,7 @@ static void balloon3_nand_cmd_ctl(struct mtd_info *mtd, int cmd, unsigned int ct writeb(cmd, this->IO_ADDR_W); } -static void balloon3_nand_select_chip(struct mtd_info *mtd, int chip) +static void balloon3_nand_select_chip(struct nand_chip *this, int chip) { if (chip < 0 || chip > 3) return; @@ -616,7 +616,7 @@ static void balloon3_nand_select_chip(struct mtd_info *mtd, int chip) BALLOON3_NAND_CONTROL_REG); } -static int balloon3_nand_dev_ready(struct mtd_info *mtd) +static int balloon3_nand_dev_ready(struct nand_chip *this) { return __raw_readl(BALLOON3_NAND_STAT_REG) & BALLOON3_NAND_STAT_RNB; } diff --git a/arch/arm/mach-pxa/em-x270.c b/arch/arm/mach-pxa/em-x270.c index 29be04c6cc48..ba1ec9992830 100644 --- a/arch/arm/mach-pxa/em-x270.c +++ b/arch/arm/mach-pxa/em-x270.c @@ -285,10 +285,9 @@ static void nand_cs_off(void) } /* hardware specific access to control-lines */ -static void em_x270_nand_cmd_ctl(struct mtd_info *mtd, int dat, +static void em_x270_nand_cmd_ctl(struct nand_chip *this, int dat, unsigned int ctrl) { - struct nand_chip *this = mtd_to_nand(mtd); unsigned long nandaddr = (unsigned long)this->IO_ADDR_W; dsb(); @@ -317,7 +316,7 @@ static void em_x270_nand_cmd_ctl(struct mtd_info *mtd, int dat, } /* read device ready pin */ -static int em_x270_nand_device_ready(struct mtd_info *mtd) +static int em_x270_nand_device_ready(struct nand_chip *this) { dsb(); diff --git a/arch/arm/mach-pxa/palmtx.c b/arch/arm/mach-pxa/palmtx.c index 47e3e38e9bec..ed9661e70b83 100644 --- a/arch/arm/mach-pxa/palmtx.c +++ b/arch/arm/mach-pxa/palmtx.c @@ -247,10 +247,9 @@ static inline void palmtx_keys_init(void) {} ******************************************************************************/ #if defined(CONFIG_MTD_NAND_PLATFORM) || \ defined(CONFIG_MTD_NAND_PLATFORM_MODULE) -static void palmtx_nand_cmd_ctl(struct mtd_info *mtd, int cmd, - unsigned int ctrl) +static void palmtx_nand_cmd_ctl(struct nand_chip *this, int cmd, + unsigned int ctrl) { - struct nand_chip *this = mtd_to_nand(mtd); char __iomem *nandaddr = this->IO_ADDR_W; if (cmd == NAND_CMD_NONE) diff --git a/arch/mips/alchemy/devboards/db1200.c b/arch/mips/alchemy/devboards/db1200.c index da7663770425..f043615c1a99 100644 --- a/arch/mips/alchemy/devboards/db1200.c +++ b/arch/mips/alchemy/devboards/db1200.c @@ -197,10 +197,9 @@ static struct i2c_board_info db1200_i2c_devs[] __initdata = { /**********************************************************************/ -static void au1200_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, +static void au1200_nand_cmd_ctrl(struct nand_chip *this, int cmd, unsigned int ctrl) { - struct nand_chip *this = mtd_to_nand(mtd); unsigned long ioaddr = (unsigned long)this->IO_ADDR_W; ioaddr &= 0xffffff00; @@ -220,7 +219,7 @@ static void au1200_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, } } -static int au1200_nand_device_ready(struct mtd_info *mtd) +static int au1200_nand_device_ready(struct nand_chip *this) { return alchemy_rdsmem(AU1000_MEM_STSTAT) & 1; } diff --git a/arch/mips/alchemy/devboards/db1300.c b/arch/mips/alchemy/devboards/db1300.c index efb318e03e0a..1201fa655e78 100644 --- a/arch/mips/alchemy/devboards/db1300.c +++ b/arch/mips/alchemy/devboards/db1300.c @@ -149,10 +149,9 @@ static void __init db1300_gpio_config(void) /**********************************************************************/ -static void au1300_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, +static void au1300_nand_cmd_ctrl(struct nand_chip *this, int cmd, unsigned int ctrl) { - struct nand_chip *this = mtd_to_nand(mtd); unsigned long ioaddr = (unsigned long)this->IO_ADDR_W; ioaddr &= 0xffffff00; @@ -172,7 +171,7 @@ static void au1300_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, } } -static int au1300_nand_device_ready(struct mtd_info *mtd) +static int au1300_nand_device_ready(struct nand_chip *this) { return alchemy_rdsmem(AU1000_MEM_STSTAT) & 1; } diff --git a/arch/mips/alchemy/devboards/db1550.c b/arch/mips/alchemy/devboards/db1550.c index 7d3dfaa10231..cae39cde5de6 100644 --- a/arch/mips/alchemy/devboards/db1550.c +++ b/arch/mips/alchemy/devboards/db1550.c @@ -126,10 +126,9 @@ static struct i2c_board_info db1550_i2c_devs[] __initdata = { /**********************************************************************/ -static void au1550_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, +static void au1550_nand_cmd_ctrl(struct nand_chip *this, int cmd, unsigned int ctrl) { - struct nand_chip *this = mtd_to_nand(mtd); unsigned long ioaddr = (unsigned long)this->IO_ADDR_W; ioaddr &= 0xffffff00; @@ -149,7 +148,7 @@ static void au1550_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, } } -static int au1550_nand_device_ready(struct mtd_info *mtd) +static int au1550_nand_device_ready(struct nand_chip *this) { return alchemy_rdsmem(AU1000_MEM_STSTAT) & 1; } diff --git a/arch/mips/netlogic/xlr/platform-flash.c b/arch/mips/netlogic/xlr/platform-flash.c index 4d1b4c003376..4f76b85b44c9 100644 --- a/arch/mips/netlogic/xlr/platform-flash.c +++ b/arch/mips/netlogic/xlr/platform-flash.c @@ -92,8 +92,8 @@ struct xlr_nand_flash_priv { static struct xlr_nand_flash_priv nand_priv; -static void xlr_nand_ctrl(struct mtd_info *mtd, int cmd, - unsigned int ctrl) +static void xlr_nand_ctrl(struct nand_chip *chip, int cmd, + unsigned int ctrl) { if (ctrl & NAND_CLE) nlm_write_reg(nand_priv.flash_mmio, diff --git a/arch/mips/pnx833x/common/platform.c b/arch/mips/pnx833x/common/platform.c index a7a4e9f5146d..ca8a2889431e 100644 --- a/arch/mips/pnx833x/common/platform.c +++ b/arch/mips/pnx833x/common/platform.c @@ -178,9 +178,8 @@ static struct platform_device pnx833x_sata_device = { }; static void -pnx833x_flash_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl) +pnx833x_flash_nand_cmd_ctrl(struct nand_chip *this, int cmd, unsigned int ctrl) { - struct nand_chip *this = mtd_to_nand(mtd); unsigned long nandaddr = (unsigned long)this->IO_ADDR_W; if (cmd == NAND_CMD_NONE) diff --git a/arch/mips/rb532/devices.c b/arch/mips/rb532/devices.c index 354d258396ff..9173949892ed 100644 --- a/arch/mips/rb532/devices.c +++ b/arch/mips/rb532/devices.c @@ -141,14 +141,13 @@ static struct platform_device cf_slot0 = { }; /* Resources and device for NAND */ -static int rb532_dev_ready(struct mtd_info *mtd) +static int rb532_dev_ready(struct nand_chip *chip) { return gpio_get_value(GPIO_RDY); } -static void rb532_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl) +static void rb532_cmd_ctrl(struct nand_chip *chip, int cmd, unsigned int ctrl) { - struct nand_chip *chip = mtd_to_nand(mtd); unsigned char orbits, nandbits; if (ctrl & NAND_CTRL_CHANGE) { diff --git a/arch/sh/boards/mach-migor/setup.c b/arch/sh/boards/mach-migor/setup.c index 254f2c662703..833f3e49027b 100644 --- a/arch/sh/boards/mach-migor/setup.c +++ b/arch/sh/boards/mach-migor/setup.c @@ -165,11 +165,9 @@ static struct mtd_partition migor_nand_flash_partitions[] = { }, }; -static void migor_nand_flash_cmd_ctl(struct mtd_info *mtd, int cmd, +static void migor_nand_flash_cmd_ctl(struct nand_chip *chip, int cmd, unsigned int ctrl) { - struct nand_chip *chip = mtd_to_nand(mtd); - if (cmd == NAND_CMD_NONE) return; @@ -181,7 +179,7 @@ static void migor_nand_flash_cmd_ctl(struct mtd_info *mtd, int cmd, writeb(cmd, chip->IO_ADDR_W); } -static int migor_nand_flash_ready(struct mtd_info *mtd) +static int migor_nand_flash_ready(struct nand_chip *chip) { return gpio_get_value(GPIO_PTA1); /* NAND_RBn */ } diff --git a/drivers/mtd/nand/raw/plat_nand.c b/drivers/mtd/nand/raw/plat_nand.c index 222626df4b96..24f904300c44 100644 --- a/drivers/mtd/nand/raw/plat_nand.c +++ b/drivers/mtd/nand/raw/plat_nand.c @@ -23,6 +23,42 @@ struct plat_nand_data { void __iomem *io_base; }; +static void plat_nand_cmd_ctrl(struct mtd_info *mtd, int dat, unsigned int ctrl) +{ + struct platform_nand_data *pdata = dev_get_platdata(mtd->dev.parent); + + pdata->ctrl.cmd_ctrl(mtd_to_nand(mtd), dat, ctrl); +} + +static int plat_nand_dev_ready(struct mtd_info *mtd) +{ + struct platform_nand_data *pdata = dev_get_platdata(mtd->dev.parent); + + return pdata->ctrl.dev_ready(mtd_to_nand(mtd)); +} + +static void plat_nand_select_chip(struct mtd_info *mtd, int cs) +{ + struct platform_nand_data *pdata = dev_get_platdata(mtd->dev.parent); + + pdata->ctrl.select_chip(mtd_to_nand(mtd), cs); +} + +static void plat_nand_write_buf(struct mtd_info *mtd, const uint8_t *buf, + int len) +{ + struct platform_nand_data *pdata = dev_get_platdata(mtd->dev.parent); + + pdata->ctrl.write_buf(mtd_to_nand(mtd), buf, len); +} + +static void plat_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) +{ + struct platform_nand_data *pdata = dev_get_platdata(mtd->dev.parent); + + pdata->ctrl.read_buf(mtd_to_nand(mtd), buf, len); +} + /* * Probe for the NAND device. */ @@ -62,11 +98,22 @@ static int plat_nand_probe(struct platform_device *pdev) data->chip.IO_ADDR_R = data->io_base; data->chip.IO_ADDR_W = data->io_base; - data->chip.cmd_ctrl = pdata->ctrl.cmd_ctrl; - data->chip.dev_ready = pdata->ctrl.dev_ready; - data->chip.select_chip = pdata->ctrl.select_chip; - data->chip.write_buf = pdata->ctrl.write_buf; - data->chip.read_buf = pdata->ctrl.read_buf; + + if (pdata->ctrl.cmd_ctrl) + data->chip.cmd_ctrl = plat_nand_cmd_ctrl; + + if (pdata->ctrl.dev_ready) + data->chip.dev_ready = plat_nand_dev_ready; + + if (pdata->ctrl.select_chip) + data->chip.select_chip = plat_nand_select_chip; + + if (pdata->ctrl.write_buf) + data->chip.write_buf = plat_nand_write_buf; + + if (pdata->ctrl.read_buf) + data->chip.read_buf = plat_nand_read_buf; + data->chip.chip_delay = pdata->chip.chip_delay; data->chip.options |= pdata->chip.options; data->chip.bbt_options |= pdata->chip.bbt_options; diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h index d155470f53c8..818cdc0a4dbb 100644 --- a/include/linux/mtd/rawnand.h +++ b/include/linux/mtd/rawnand.h @@ -1595,11 +1595,11 @@ struct platform_device; struct platform_nand_ctrl { int (*probe)(struct platform_device *pdev); void (*remove)(struct platform_device *pdev); - int (*dev_ready)(struct mtd_info *mtd); - void (*select_chip)(struct mtd_info *mtd, int chip); - void (*cmd_ctrl)(struct mtd_info *mtd, int dat, unsigned int ctrl); - void (*write_buf)(struct mtd_info *mtd, const uint8_t *buf, int len); - void (*read_buf)(struct mtd_info *mtd, uint8_t *buf, int len); + int (*dev_ready)(struct nand_chip *chip); + void (*select_chip)(struct nand_chip *chip, int cs); + void (*cmd_ctrl)(struct nand_chip *chip, int dat, unsigned int ctrl); + void (*write_buf)(struct nand_chip *chip, const uint8_t *buf, int len); + void (*read_buf)(struct nand_chip *chip, uint8_t *buf, int len); void *priv; }; From 00ad378f304a091ab2e2df5f944892a6ed558610 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Thu, 6 Sep 2018 14:05:14 +0200 Subject: [PATCH 242/302] mtd: rawnand: Pass a nand_chip object to nand_scan() Let's make the raw NAND API consistent by patching all helpers to take a nand_chip object instead of an mtd_info one. We start with nand_scan(). Signed-off-by: Boris Brezillon Signed-off-by: Miquel Raynal --- Documentation/driver-api/mtdnand.rst | 2 +- drivers/mtd/nand/raw/ams-delta.c | 2 +- drivers/mtd/nand/raw/atmel/nand-controller.c | 2 +- drivers/mtd/nand/raw/au1550nd.c | 2 +- .../mtd/nand/raw/bcm47xxnflash/ops_bcm4706.c | 2 +- drivers/mtd/nand/raw/brcmnand/brcmnand.c | 2 +- drivers/mtd/nand/raw/cafe_nand.c | 2 +- drivers/mtd/nand/raw/cmx270_nand.c | 2 +- drivers/mtd/nand/raw/cs553x_nand.c | 2 +- drivers/mtd/nand/raw/davinci_nand.c | 2 +- drivers/mtd/nand/raw/denali.c | 2 +- drivers/mtd/nand/raw/diskonchip.c | 2 +- drivers/mtd/nand/raw/docg4.c | 2 +- drivers/mtd/nand/raw/fsl_elbc_nand.c | 2 +- drivers/mtd/nand/raw/fsl_ifc_nand.c | 2 +- drivers/mtd/nand/raw/fsl_upm.c | 2 +- drivers/mtd/nand/raw/fsmc_nand.c | 2 +- drivers/mtd/nand/raw/gpio.c | 2 +- drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c | 2 +- drivers/mtd/nand/raw/hisi504_nand.c | 2 +- drivers/mtd/nand/raw/jz4740_nand.c | 2 +- drivers/mtd/nand/raw/jz4780_nand.c | 2 +- drivers/mtd/nand/raw/lpc32xx_mlc.c | 2 +- drivers/mtd/nand/raw/lpc32xx_slc.c | 2 +- drivers/mtd/nand/raw/marvell_nand.c | 2 +- drivers/mtd/nand/raw/mpc5121_nfc.c | 2 +- drivers/mtd/nand/raw/mtk_nand.c | 2 +- drivers/mtd/nand/raw/mxc_nand.c | 2 +- drivers/mtd/nand/raw/nand_base.c | 21 +++++++++---------- drivers/mtd/nand/raw/nandsim.c | 2 +- drivers/mtd/nand/raw/ndfc.c | 2 +- drivers/mtd/nand/raw/nuc900_nand.c | 2 +- drivers/mtd/nand/raw/omap2.c | 2 +- drivers/mtd/nand/raw/orion_nand.c | 2 +- drivers/mtd/nand/raw/oxnas_nand.c | 2 +- drivers/mtd/nand/raw/pasemi_nand.c | 2 +- drivers/mtd/nand/raw/plat_nand.c | 2 +- drivers/mtd/nand/raw/qcom_nandc.c | 2 +- drivers/mtd/nand/raw/s3c2410.c | 2 +- drivers/mtd/nand/raw/sh_flctl.c | 2 +- drivers/mtd/nand/raw/sharpsl.c | 2 +- drivers/mtd/nand/raw/sm_common.c | 2 +- drivers/mtd/nand/raw/socrates_nand.c | 2 +- drivers/mtd/nand/raw/sunxi_nand.c | 2 +- drivers/mtd/nand/raw/tango_nand.c | 2 +- drivers/mtd/nand/raw/tegra_nand.c | 2 +- drivers/mtd/nand/raw/tmio_nand.c | 2 +- drivers/mtd/nand/raw/txx9ndfmc.c | 2 +- drivers/mtd/nand/raw/vf610_nfc.c | 2 +- drivers/mtd/nand/raw/xway_nand.c | 2 +- drivers/staging/mt29f_spinand/mt29f_spinand.c | 2 +- include/linux/mtd/rawnand.h | 7 ++++--- 52 files changed, 64 insertions(+), 64 deletions(-) diff --git a/Documentation/driver-api/mtdnand.rst b/Documentation/driver-api/mtdnand.rst index c55a6034c397..1ab6f35b6410 100644 --- a/Documentation/driver-api/mtdnand.rst +++ b/Documentation/driver-api/mtdnand.rst @@ -246,7 +246,7 @@ necessary information about the device. this->eccmode = NAND_ECC_SOFT; /* Scan to find existence of the device */ - if (nand_scan (board_mtd, 1)) { + if (nand_scan (this, 1)) { err = -ENXIO; goto out_ior; } diff --git a/drivers/mtd/nand/raw/ams-delta.c b/drivers/mtd/nand/raw/ams-delta.c index 37a3cc21c7bc..24ba7296ec08 100644 --- a/drivers/mtd/nand/raw/ams-delta.c +++ b/drivers/mtd/nand/raw/ams-delta.c @@ -235,7 +235,7 @@ static int ams_delta_init(struct platform_device *pdev) goto out_gpio; /* Scan to find existence of the device */ - err = nand_scan(ams_delta_mtd, 1); + err = nand_scan(this, 1); if (err) goto out_mtd; diff --git a/drivers/mtd/nand/raw/atmel/nand-controller.c b/drivers/mtd/nand/raw/atmel/nand-controller.c index 8b9e05ac24ee..cef22a79f3a6 100644 --- a/drivers/mtd/nand/raw/atmel/nand-controller.c +++ b/drivers/mtd/nand/raw/atmel/nand-controller.c @@ -1683,7 +1683,7 @@ atmel_nand_controller_add_nand(struct atmel_nand_controller *nc, nc->caps->ops->nand_init(nc, nand); - ret = nand_scan(mtd, nand->numcs); + ret = nand_scan(chip, nand->numcs); if (ret) { dev_err(nc->dev, "NAND scan failed: %d\n", ret); return ret; diff --git a/drivers/mtd/nand/raw/au1550nd.c b/drivers/mtd/nand/raw/au1550nd.c index 32c0440141fb..614f5d447ba5 100644 --- a/drivers/mtd/nand/raw/au1550nd.c +++ b/drivers/mtd/nand/raw/au1550nd.c @@ -451,7 +451,7 @@ static int au1550nd_probe(struct platform_device *pdev) this->write_buf = (pd->devwidth) ? au_write_buf16 : au_write_buf; this->read_buf = (pd->devwidth) ? au_read_buf16 : au_read_buf; - ret = nand_scan(mtd, 1); + ret = nand_scan(this, 1); if (ret) { dev_err(&pdev->dev, "NAND scan failed with %d\n", ret); goto out3; diff --git a/drivers/mtd/nand/raw/bcm47xxnflash/ops_bcm4706.c b/drivers/mtd/nand/raw/bcm47xxnflash/ops_bcm4706.c index 60874de430eb..9b62bc2d25a0 100644 --- a/drivers/mtd/nand/raw/bcm47xxnflash/ops_bcm4706.c +++ b/drivers/mtd/nand/raw/bcm47xxnflash/ops_bcm4706.c @@ -423,7 +423,7 @@ int bcm47xxnflash_ops_bcm4706_init(struct bcm47xxnflash *b47n) (w4 << 24 | w3 << 18 | w2 << 12 | w1 << 6 | w0)); /* Scan NAND */ - err = nand_scan(nand_to_mtd(&b47n->nand_chip), 1); + err = nand_scan(&b47n->nand_chip, 1); if (err) { pr_err("Could not scan NAND flash: %d\n", err); goto exit; diff --git a/drivers/mtd/nand/raw/brcmnand/brcmnand.c b/drivers/mtd/nand/raw/brcmnand/brcmnand.c index 4b90d5b380c2..a9a94c102654 100644 --- a/drivers/mtd/nand/raw/brcmnand/brcmnand.c +++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c @@ -2301,7 +2301,7 @@ static int brcmnand_init_cs(struct brcmnand_host *host, struct device_node *dn) nand_writereg(ctrl, cfg_offs, nand_readreg(ctrl, cfg_offs) & ~CFG_BUS_WIDTH); - ret = nand_scan(mtd, 1); + ret = nand_scan(chip, 1); if (ret) return ret; diff --git a/drivers/mtd/nand/raw/cafe_nand.c b/drivers/mtd/nand/raw/cafe_nand.c index 1dbe43adcfe7..e497b95d624e 100644 --- a/drivers/mtd/nand/raw/cafe_nand.c +++ b/drivers/mtd/nand/raw/cafe_nand.c @@ -783,7 +783,7 @@ static int cafe_nand_probe(struct pci_dev *pdev, /* Scan to find existence of the device */ cafe->nand.dummy_controller.ops = &cafe_nand_controller_ops; - err = nand_scan(mtd, 2); + err = nand_scan(&cafe->nand, 2); if (err) goto out_irq; diff --git a/drivers/mtd/nand/raw/cmx270_nand.c b/drivers/mtd/nand/raw/cmx270_nand.c index b66e254b6802..e92c0f113eb3 100644 --- a/drivers/mtd/nand/raw/cmx270_nand.c +++ b/drivers/mtd/nand/raw/cmx270_nand.c @@ -193,7 +193,7 @@ static int __init cmx270_init(void) this->write_buf = cmx270_write_buf; /* Scan to find existence of the device */ - ret = nand_scan(cmx270_nand_mtd, 1); + ret = nand_scan(this, 1); if (ret) { pr_notice("No NAND device\n"); goto err_scan; diff --git a/drivers/mtd/nand/raw/cs553x_nand.c b/drivers/mtd/nand/raw/cs553x_nand.c index beafad62e7d5..4065bcd12e64 100644 --- a/drivers/mtd/nand/raw/cs553x_nand.c +++ b/drivers/mtd/nand/raw/cs553x_nand.c @@ -241,7 +241,7 @@ static int __init cs553x_init_one(int cs, int mmio, unsigned long adr) } /* Scan to find existence of the device */ - err = nand_scan(new_mtd, 1); + err = nand_scan(this, 1); if (err) goto out_free; diff --git a/drivers/mtd/nand/raw/davinci_nand.c b/drivers/mtd/nand/raw/davinci_nand.c index 40145e206a6b..1021624195f7 100644 --- a/drivers/mtd/nand/raw/davinci_nand.c +++ b/drivers/mtd/nand/raw/davinci_nand.c @@ -807,7 +807,7 @@ static int nand_davinci_probe(struct platform_device *pdev) /* Scan to find existence of the device(s) */ info->chip.dummy_controller.ops = &davinci_nand_controller_ops; - ret = nand_scan(mtd, pdata->mask_chipsel ? 2 : 1); + ret = nand_scan(&info->chip, pdata->mask_chipsel ? 2 : 1); if (ret < 0) { dev_dbg(&pdev->dev, "no NAND chip(s) found\n"); return ret; diff --git a/drivers/mtd/nand/raw/denali.c b/drivers/mtd/nand/raw/denali.c index 177453dfaa07..2e8a825c740e 100644 --- a/drivers/mtd/nand/raw/denali.c +++ b/drivers/mtd/nand/raw/denali.c @@ -1355,7 +1355,7 @@ int denali_init(struct denali_nand_info *denali) chip->setup_data_interface = denali_setup_data_interface; chip->dummy_controller.ops = &denali_controller_ops; - ret = nand_scan(mtd, denali->max_banks); + ret = nand_scan(chip, denali->max_banks); if (ret) goto disable_irq; diff --git a/drivers/mtd/nand/raw/diskonchip.c b/drivers/mtd/nand/raw/diskonchip.c index 3c46188dd6d2..9159748a2ef0 100644 --- a/drivers/mtd/nand/raw/diskonchip.c +++ b/drivers/mtd/nand/raw/diskonchip.c @@ -1620,7 +1620,7 @@ static int __init doc_probe(unsigned long physadr) else numchips = doc2001_init(mtd); - if ((ret = nand_scan(mtd, numchips)) || (ret = doc->late_init(mtd))) { + if ((ret = nand_scan(nand, numchips)) || (ret = doc->late_init(mtd))) { /* DBB note: i believe nand_release is necessary here, as buffers may have been allocated in nand_base. Check with Thomas. FIX ME! */ diff --git a/drivers/mtd/nand/raw/docg4.c b/drivers/mtd/nand/raw/docg4.c index 427fcbc1b71c..69f60755f38a 100644 --- a/drivers/mtd/nand/raw/docg4.c +++ b/drivers/mtd/nand/raw/docg4.c @@ -1391,7 +1391,7 @@ static int __init probe_docg4(struct platform_device *pdev) * ->attach_chip callback. */ nand->dummy_controller.ops = &docg4_controller_ops; - retval = nand_scan(mtd, 0); + retval = nand_scan(nand, 0); if (retval) goto free_nand; diff --git a/drivers/mtd/nand/raw/fsl_elbc_nand.c b/drivers/mtd/nand/raw/fsl_elbc_nand.c index 55f449b711fd..541343d142e0 100644 --- a/drivers/mtd/nand/raw/fsl_elbc_nand.c +++ b/drivers/mtd/nand/raw/fsl_elbc_nand.c @@ -915,7 +915,7 @@ static int fsl_elbc_nand_probe(struct platform_device *pdev) goto err; priv->chip.controller->ops = &fsl_elbc_controller_ops; - ret = nand_scan(mtd, 1); + ret = nand_scan(&priv->chip, 1); if (ret) goto err; diff --git a/drivers/mtd/nand/raw/fsl_ifc_nand.c b/drivers/mtd/nand/raw/fsl_ifc_nand.c index 7e7729df7827..ad010c72df78 100644 --- a/drivers/mtd/nand/raw/fsl_ifc_nand.c +++ b/drivers/mtd/nand/raw/fsl_ifc_nand.c @@ -1079,7 +1079,7 @@ static int fsl_ifc_nand_probe(struct platform_device *dev) goto err; priv->chip.controller->ops = &fsl_ifc_controller_ops; - ret = nand_scan(mtd, 1); + ret = nand_scan(&priv->chip, 1); if (ret) goto err; diff --git a/drivers/mtd/nand/raw/fsl_upm.c b/drivers/mtd/nand/raw/fsl_upm.c index ca82727eca94..99edae365d16 100644 --- a/drivers/mtd/nand/raw/fsl_upm.c +++ b/drivers/mtd/nand/raw/fsl_upm.c @@ -191,7 +191,7 @@ static int fun_chip_init(struct fsl_upm_nand *fun, goto err; } - ret = nand_scan(mtd, fun->mchip_count); + ret = nand_scan(&fun->chip, fun->mchip_count); if (ret) goto err; diff --git a/drivers/mtd/nand/raw/fsmc_nand.c b/drivers/mtd/nand/raw/fsmc_nand.c index f418236fa020..9991e3b8e237 100644 --- a/drivers/mtd/nand/raw/fsmc_nand.c +++ b/drivers/mtd/nand/raw/fsmc_nand.c @@ -1125,7 +1125,7 @@ static int __init fsmc_nand_probe(struct platform_device *pdev) * Scan to find existence of the device */ nand->dummy_controller.ops = &fsmc_nand_controller_ops; - ret = nand_scan(mtd, 1); + ret = nand_scan(nand, 1); if (ret) goto release_dma_write_chan; diff --git a/drivers/mtd/nand/raw/gpio.c b/drivers/mtd/nand/raw/gpio.c index 2780af26d9ab..983d3be48019 100644 --- a/drivers/mtd/nand/raw/gpio.c +++ b/drivers/mtd/nand/raw/gpio.c @@ -289,7 +289,7 @@ static int gpio_nand_probe(struct platform_device *pdev) if (gpiomtd->nwp && !IS_ERR(gpiomtd->nwp)) gpiod_direction_output(gpiomtd->nwp, 1); - ret = nand_scan(mtd, 1); + ret = nand_scan(chip, 1); if (ret) goto err_wp; diff --git a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c index 1c1ebbc82824..7af207bc3ab5 100644 --- a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c +++ b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c @@ -1934,7 +1934,7 @@ static int gpmi_nand_init(struct gpmi_nand_data *this) goto err_out; chip->dummy_controller.ops = &gpmi_nand_controller_ops; - ret = nand_scan(mtd, GPMI_IS_MX6(this) ? 2 : 1); + ret = nand_scan(chip, GPMI_IS_MX6(this) ? 2 : 1); if (ret) goto err_out; diff --git a/drivers/mtd/nand/raw/hisi504_nand.c b/drivers/mtd/nand/raw/hisi504_nand.c index 0f5c48aa5673..81baa2e6ae56 100644 --- a/drivers/mtd/nand/raw/hisi504_nand.c +++ b/drivers/mtd/nand/raw/hisi504_nand.c @@ -801,7 +801,7 @@ static int hisi_nfc_probe(struct platform_device *pdev) } chip->dummy_controller.ops = &hisi_nfc_controller_ops; - ret = nand_scan(mtd, max_chips); + ret = nand_scan(chip, max_chips); if (ret) return ret; diff --git a/drivers/mtd/nand/raw/jz4740_nand.c b/drivers/mtd/nand/raw/jz4740_nand.c index a7515452bc59..75bb26645c82 100644 --- a/drivers/mtd/nand/raw/jz4740_nand.c +++ b/drivers/mtd/nand/raw/jz4740_nand.c @@ -331,7 +331,7 @@ static int jz_nand_detect_bank(struct platform_device *pdev, if (chipnr == 0) { /* Detect first chip. */ - ret = nand_scan(mtd, 1); + ret = nand_scan(chip, 1); if (ret) goto notfound_id; diff --git a/drivers/mtd/nand/raw/jz4780_nand.c b/drivers/mtd/nand/raw/jz4780_nand.c index ac6239588f26..80f29b28bcc4 100644 --- a/drivers/mtd/nand/raw/jz4780_nand.c +++ b/drivers/mtd/nand/raw/jz4780_nand.c @@ -286,7 +286,7 @@ static int jz4780_nand_init_chip(struct platform_device *pdev, nand_set_flash_node(chip, np); chip->controller->ops = &jz4780_nand_controller_ops; - ret = nand_scan(mtd, 1); + ret = nand_scan(chip, 1); if (ret) return ret; diff --git a/drivers/mtd/nand/raw/lpc32xx_mlc.c b/drivers/mtd/nand/raw/lpc32xx_mlc.c index e82abada130a..453a83b82d73 100644 --- a/drivers/mtd/nand/raw/lpc32xx_mlc.c +++ b/drivers/mtd/nand/raw/lpc32xx_mlc.c @@ -802,7 +802,7 @@ static int lpc32xx_nand_probe(struct platform_device *pdev) * SMALL block or LARGE block. */ nand_chip->dummy_controller.ops = &lpc32xx_nand_controller_ops; - res = nand_scan(mtd, 1); + res = nand_scan(nand_chip, 1); if (res) goto free_irq; diff --git a/drivers/mtd/nand/raw/lpc32xx_slc.c b/drivers/mtd/nand/raw/lpc32xx_slc.c index a4e8b7e75135..ad6eff0591d2 100644 --- a/drivers/mtd/nand/raw/lpc32xx_slc.c +++ b/drivers/mtd/nand/raw/lpc32xx_slc.c @@ -925,7 +925,7 @@ static int lpc32xx_nand_probe(struct platform_device *pdev) /* Find NAND device */ chip->dummy_controller.ops = &lpc32xx_nand_controller_ops; - res = nand_scan(mtd, 1); + res = nand_scan(chip, 1); if (res) goto release_dma; diff --git a/drivers/mtd/nand/raw/marvell_nand.c b/drivers/mtd/nand/raw/marvell_nand.c index 270f281067ab..dde64609415f 100644 --- a/drivers/mtd/nand/raw/marvell_nand.c +++ b/drivers/mtd/nand/raw/marvell_nand.c @@ -2605,7 +2605,7 @@ static int marvell_nand_chip_init(struct device *dev, struct marvell_nfc *nfc, chip->options |= NAND_BUSWIDTH_AUTO; - ret = nand_scan(mtd, marvell_nand->nsels); + ret = nand_scan(chip, marvell_nand->nsels); if (ret) { dev_err(dev, "could not scan the nand chip\n"); return ret; diff --git a/drivers/mtd/nand/raw/mpc5121_nfc.c b/drivers/mtd/nand/raw/mpc5121_nfc.c index c0be9c30b4cf..efaaec462bd7 100644 --- a/drivers/mtd/nand/raw/mpc5121_nfc.c +++ b/drivers/mtd/nand/raw/mpc5121_nfc.c @@ -767,7 +767,7 @@ static int mpc5121_nfc_probe(struct platform_device *op) } /* Detect NAND chips */ - retval = nand_scan(mtd, be32_to_cpup(chips_no)); + retval = nand_scan(chip, be32_to_cpup(chips_no)); if (retval) { dev_err(dev, "NAND Flash not found !\n"); goto error; diff --git a/drivers/mtd/nand/raw/mtk_nand.c b/drivers/mtd/nand/raw/mtk_nand.c index 57b5ed1699e3..7a2ce405f914 100644 --- a/drivers/mtd/nand/raw/mtk_nand.c +++ b/drivers/mtd/nand/raw/mtk_nand.c @@ -1365,7 +1365,7 @@ static int mtk_nfc_nand_chip_init(struct device *dev, struct mtk_nfc *nfc, mtk_nfc_hw_init(nfc); - ret = nand_scan(mtd, nsels); + ret = nand_scan(nand, nsels); if (ret) return ret; diff --git a/drivers/mtd/nand/raw/mxc_nand.c b/drivers/mtd/nand/raw/mxc_nand.c index a0884a621053..1ca03d88adf1 100644 --- a/drivers/mtd/nand/raw/mxc_nand.c +++ b/drivers/mtd/nand/raw/mxc_nand.c @@ -1887,7 +1887,7 @@ static int mxcnd_probe(struct platform_device *pdev) /* Scan the NAND device */ this->dummy_controller.ops = &mxcnd_controller_ops; - err = nand_scan(mtd, is_imx25_nfc(host) ? 4 : 1); + err = nand_scan(this, is_imx25_nfc(host) ? 4 : 1); if (err) goto escan; diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c index 306ef6ec41db..974cbfbde5e2 100644 --- a/drivers/mtd/nand/raw/nand_base.c +++ b/drivers/mtd/nand/raw/nand_base.c @@ -5960,7 +5960,7 @@ static int nand_dt_init(struct nand_chip *chip) /** * nand_scan_ident - Scan for the NAND device - * @mtd: MTD device structure + * @chip: NAND chip object * @maxchips: number of chips to scan for * @table: alternative NAND ID table * @@ -5972,11 +5972,11 @@ static int nand_dt_init(struct nand_chip *chip) * prevented dynamic allocations during this phase which was unconvenient and * as been banned for the benefit of the ->init_ecc()/cleanup_ecc() hooks. */ -static int nand_scan_ident(struct mtd_info *mtd, int maxchips, +static int nand_scan_ident(struct nand_chip *chip, int maxchips, struct nand_flash_dev *table) { + struct mtd_info *mtd = nand_to_mtd(chip); int i, nand_maf_id, nand_dev_id; - struct nand_chip *chip = mtd_to_nand(mtd); int ret; /* Enforce the right timings for reset/detection */ @@ -6430,15 +6430,15 @@ static bool nand_ecc_strength_good(struct mtd_info *mtd) /** * nand_scan_tail - Scan for the NAND device - * @mtd: MTD device structure + * @chip: NAND chip object * * This is the second phase of the normal nand_scan() function. It fills out * all the uninitialized function pointers with the defaults and scans for a * bad block table if appropriate. */ -static int nand_scan_tail(struct mtd_info *mtd) +static int nand_scan_tail(struct nand_chip *chip) { - struct nand_chip *chip = mtd_to_nand(mtd); + struct mtd_info *mtd = nand_to_mtd(chip); struct nand_ecc_ctrl *ecc = &chip->ecc; int ret, i; @@ -6777,7 +6777,7 @@ static void nand_detach(struct nand_chip *chip) /** * nand_scan_with_ids - [NAND Interface] Scan for the NAND device - * @mtd: MTD device structure + * @chip: NAND chip object * @maxchips: number of chips to scan for. @nand_scan_ident() will not be run if * this parameter is zero (useful for specific drivers that must * handle this part of the process themselves, e.g docg4). @@ -6787,14 +6787,13 @@ static void nand_detach(struct nand_chip *chip) * The flash ID is read and the mtd/chip structures are filled with the * appropriate values. */ -int nand_scan_with_ids(struct mtd_info *mtd, int maxchips, +int nand_scan_with_ids(struct nand_chip *chip, int maxchips, struct nand_flash_dev *ids) { - struct nand_chip *chip = mtd_to_nand(mtd); int ret; if (maxchips) { - ret = nand_scan_ident(mtd, maxchips, ids); + ret = nand_scan_ident(chip, maxchips, ids); if (ret) return ret; } @@ -6803,7 +6802,7 @@ int nand_scan_with_ids(struct mtd_info *mtd, int maxchips, if (ret) goto cleanup_ident; - ret = nand_scan_tail(mtd); + ret = nand_scan_tail(chip); if (ret) goto detach_chip; diff --git a/drivers/mtd/nand/raw/nandsim.c b/drivers/mtd/nand/raw/nandsim.c index 47a81d1b1397..60761175e531 100644 --- a/drivers/mtd/nand/raw/nandsim.c +++ b/drivers/mtd/nand/raw/nandsim.c @@ -2309,7 +2309,7 @@ static int __init ns_init_module(void) goto error; chip->dummy_controller.ops = &ns_controller_ops; - retval = nand_scan(nsmtd, 1); + retval = nand_scan(chip, 1); if (retval) { NS_ERR("Could not scan NAND Simulator device\n"); goto error; diff --git a/drivers/mtd/nand/raw/ndfc.c b/drivers/mtd/nand/raw/ndfc.c index b193f373f235..7ce7f37dc67a 100644 --- a/drivers/mtd/nand/raw/ndfc.c +++ b/drivers/mtd/nand/raw/ndfc.c @@ -181,7 +181,7 @@ static int ndfc_chip_init(struct ndfc_controller *ndfc, goto err; } - ret = nand_scan(mtd, 1); + ret = nand_scan(chip, 1); if (ret) goto err; diff --git a/drivers/mtd/nand/raw/nuc900_nand.c b/drivers/mtd/nand/raw/nuc900_nand.c index af5b32c9a791..41ed993b9523 100644 --- a/drivers/mtd/nand/raw/nuc900_nand.c +++ b/drivers/mtd/nand/raw/nuc900_nand.c @@ -270,7 +270,7 @@ static int nuc900_nand_probe(struct platform_device *pdev) nuc900_nand_enable(nuc900_nand); - if (nand_scan(mtd, 1)) + if (nand_scan(chip, 1)) return -ENXIO; mtd_device_register(mtd, partitions, ARRAY_SIZE(partitions)); diff --git a/drivers/mtd/nand/raw/omap2.c b/drivers/mtd/nand/raw/omap2.c index 4546ac0bed4a..c2aff2492fa1 100644 --- a/drivers/mtd/nand/raw/omap2.c +++ b/drivers/mtd/nand/raw/omap2.c @@ -2254,7 +2254,7 @@ static int omap_nand_probe(struct platform_device *pdev) /* scan NAND device connected to chip controller */ nand_chip->options |= info->devsize & NAND_BUSWIDTH_16; - err = nand_scan(mtd, 1); + err = nand_scan(nand_chip, 1); if (err) goto return_error; diff --git a/drivers/mtd/nand/raw/orion_nand.c b/drivers/mtd/nand/raw/orion_nand.c index 52d435285a3f..256a6b018bdc 100644 --- a/drivers/mtd/nand/raw/orion_nand.c +++ b/drivers/mtd/nand/raw/orion_nand.c @@ -174,7 +174,7 @@ static int __init orion_nand_probe(struct platform_device *pdev) return ret; } - ret = nand_scan(mtd, 1); + ret = nand_scan(nc, 1); if (ret) goto no_dev; diff --git a/drivers/mtd/nand/raw/oxnas_nand.c b/drivers/mtd/nand/raw/oxnas_nand.c index 01b00bb69c1e..9aeb024c2a0e 100644 --- a/drivers/mtd/nand/raw/oxnas_nand.c +++ b/drivers/mtd/nand/raw/oxnas_nand.c @@ -142,7 +142,7 @@ static int oxnas_nand_probe(struct platform_device *pdev) chip->chip_delay = 30; /* Scan to find existence of the device */ - err = nand_scan(mtd, 1); + err = nand_scan(chip, 1); if (err) goto err_clk_unprepare; diff --git a/drivers/mtd/nand/raw/pasemi_nand.c b/drivers/mtd/nand/raw/pasemi_nand.c index a47a7e4bd25a..eca4e41d2be3 100644 --- a/drivers/mtd/nand/raw/pasemi_nand.c +++ b/drivers/mtd/nand/raw/pasemi_nand.c @@ -156,7 +156,7 @@ static int pasemi_nand_probe(struct platform_device *ofdev) chip->bbt_options = NAND_BBT_USE_FLASH; /* Scan to find existence of the device */ - err = nand_scan(pasemi_nand_mtd, 1); + err = nand_scan(chip, 1); if (err) goto out_lpc; diff --git a/drivers/mtd/nand/raw/plat_nand.c b/drivers/mtd/nand/raw/plat_nand.c index 24f904300c44..c9a23fb21718 100644 --- a/drivers/mtd/nand/raw/plat_nand.c +++ b/drivers/mtd/nand/raw/plat_nand.c @@ -131,7 +131,7 @@ static int plat_nand_probe(struct platform_device *pdev) } /* Scan to find existence of the device */ - err = nand_scan(mtd, pdata->chip.nr_chips); + err = nand_scan(&data->chip, pdata->chip.nr_chips); if (err) goto out; diff --git a/drivers/mtd/nand/raw/qcom_nandc.c b/drivers/mtd/nand/raw/qcom_nandc.c index d2831b0b28fb..d800347e74da 100644 --- a/drivers/mtd/nand/raw/qcom_nandc.c +++ b/drivers/mtd/nand/raw/qcom_nandc.c @@ -2834,7 +2834,7 @@ static int qcom_nand_host_init_and_register(struct qcom_nand_controller *nandc, /* set up initial status value */ host->status = NAND_STATUS_READY | NAND_STATUS_WP; - ret = nand_scan(mtd, 1); + ret = nand_scan(chip, 1); if (ret) return ret; diff --git a/drivers/mtd/nand/raw/s3c2410.c b/drivers/mtd/nand/raw/s3c2410.c index c21e8892394a..7f30d801d642 100644 --- a/drivers/mtd/nand/raw/s3c2410.c +++ b/drivers/mtd/nand/raw/s3c2410.c @@ -1170,7 +1170,7 @@ static int s3c24xx_nand_probe(struct platform_device *pdev) mtd->dev.parent = &pdev->dev; s3c2410_nand_init_chip(info, nmtd, sets); - err = nand_scan(mtd, sets ? sets->nr_chips : 1); + err = nand_scan(&nmtd->chip, sets ? sets->nr_chips : 1); if (err) goto exit_error; diff --git a/drivers/mtd/nand/raw/sh_flctl.c b/drivers/mtd/nand/raw/sh_flctl.c index ef3036d9bf15..abcc3be89b89 100644 --- a/drivers/mtd/nand/raw/sh_flctl.c +++ b/drivers/mtd/nand/raw/sh_flctl.c @@ -1193,7 +1193,7 @@ static int flctl_probe(struct platform_device *pdev) flctl_setup_dma(flctl); nand->dummy_controller.ops = &flctl_nand_controller_ops; - ret = nand_scan(flctl_mtd, 1); + ret = nand_scan(nand, 1); if (ret) goto err_chip; diff --git a/drivers/mtd/nand/raw/sharpsl.c b/drivers/mtd/nand/raw/sharpsl.c index fc171b17a39b..4afacb0dcf00 100644 --- a/drivers/mtd/nand/raw/sharpsl.c +++ b/drivers/mtd/nand/raw/sharpsl.c @@ -171,7 +171,7 @@ static int sharpsl_nand_probe(struct platform_device *pdev) this->ecc.correct = nand_correct_data; /* Scan to find existence of the device */ - err = nand_scan(mtd, 1); + err = nand_scan(this, 1); if (err) goto err_scan; diff --git a/drivers/mtd/nand/raw/sm_common.c b/drivers/mtd/nand/raw/sm_common.c index 73aafe8c3ef3..02ac6e9b2d16 100644 --- a/drivers/mtd/nand/raw/sm_common.c +++ b/drivers/mtd/nand/raw/sm_common.c @@ -195,7 +195,7 @@ int sm_register_device(struct mtd_info *mtd, int smartmedia) /* Scan for card properties */ chip->dummy_controller.ops = &sm_controller_ops; flash_ids = smartmedia ? nand_smartmedia_flash_ids : nand_xd_flash_ids; - ret = nand_scan_with_ids(mtd, 1, flash_ids); + ret = nand_scan_with_ids(chip, 1, flash_ids); if (ret) return ret; diff --git a/drivers/mtd/nand/raw/socrates_nand.c b/drivers/mtd/nand/raw/socrates_nand.c index 36c45aa21f66..e335560f87af 100644 --- a/drivers/mtd/nand/raw/socrates_nand.c +++ b/drivers/mtd/nand/raw/socrates_nand.c @@ -173,7 +173,7 @@ static int socrates_nand_probe(struct platform_device *ofdev) dev_set_drvdata(&ofdev->dev, host); - res = nand_scan(mtd, 1); + res = nand_scan(nand_chip, 1); if (res) goto out; diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c index 1f0b7ee38df5..179f74b6edf6 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -1940,7 +1940,7 @@ static int sunxi_nand_chip_init(struct device *dev, struct sunxi_nfc *nfc, mtd = nand_to_mtd(nand); mtd->dev.parent = dev; - ret = nand_scan(mtd, nsels); + ret = nand_scan(nand, nsels); if (ret) return ret; diff --git a/drivers/mtd/nand/raw/tango_nand.c b/drivers/mtd/nand/raw/tango_nand.c index 72698691727d..45beb87aec93 100644 --- a/drivers/mtd/nand/raw/tango_nand.c +++ b/drivers/mtd/nand/raw/tango_nand.c @@ -588,7 +588,7 @@ static int chip_init(struct device *dev, struct device_node *np) mtd_set_ooblayout(mtd, &tango_nand_ooblayout_ops); mtd->dev.parent = dev; - err = nand_scan(mtd, 1); + err = nand_scan(chip, 1); if (err) return err; diff --git a/drivers/mtd/nand/raw/tegra_nand.c b/drivers/mtd/nand/raw/tegra_nand.c index 79da1efc88d1..5dcee20e2a8c 100644 --- a/drivers/mtd/nand/raw/tegra_nand.c +++ b/drivers/mtd/nand/raw/tegra_nand.c @@ -1119,7 +1119,7 @@ static int tegra_nand_chips_init(struct device *dev, chip->select_chip = tegra_nand_select_chip; chip->setup_data_interface = tegra_nand_setup_data_interface; - ret = nand_scan(mtd, 1); + ret = nand_scan(chip, 1); if (ret) return ret; diff --git a/drivers/mtd/nand/raw/tmio_nand.c b/drivers/mtd/nand/raw/tmio_nand.c index dcaa924502de..6df499a239ae 100644 --- a/drivers/mtd/nand/raw/tmio_nand.c +++ b/drivers/mtd/nand/raw/tmio_nand.c @@ -436,7 +436,7 @@ static int tmio_probe(struct platform_device *dev) nand_chip->waitfunc = tmio_nand_wait; /* Scan to find existence of the device */ - retval = nand_scan(mtd, 1); + retval = nand_scan(nand_chip, 1); if (retval) goto err_irq; diff --git a/drivers/mtd/nand/raw/txx9ndfmc.c b/drivers/mtd/nand/raw/txx9ndfmc.c index 4d61a14fcb65..169e8bcee61e 100644 --- a/drivers/mtd/nand/raw/txx9ndfmc.c +++ b/drivers/mtd/nand/raw/txx9ndfmc.c @@ -359,7 +359,7 @@ static int __init txx9ndfmc_probe(struct platform_device *dev) if (plat->wide_mask & (1 << i)) chip->options |= NAND_BUSWIDTH_16; - if (nand_scan(mtd, 1)) { + if (nand_scan(chip, 1)) { kfree(txx9_priv->mtdname); kfree(txx9_priv); continue; diff --git a/drivers/mtd/nand/raw/vf610_nfc.c b/drivers/mtd/nand/raw/vf610_nfc.c index 6f6dcbf9095b..3b486f4ce868 100644 --- a/drivers/mtd/nand/raw/vf610_nfc.c +++ b/drivers/mtd/nand/raw/vf610_nfc.c @@ -892,7 +892,7 @@ static int vf610_nfc_probe(struct platform_device *pdev) /* Scan the NAND chip */ chip->dummy_controller.ops = &vf610_nfc_controller_ops; - err = nand_scan(mtd, 1); + err = nand_scan(chip, 1); if (err) goto err_disable_clk; diff --git a/drivers/mtd/nand/raw/xway_nand.c b/drivers/mtd/nand/raw/xway_nand.c index 9926b4e3d69d..e670d3b5a646 100644 --- a/drivers/mtd/nand/raw/xway_nand.c +++ b/drivers/mtd/nand/raw/xway_nand.c @@ -205,7 +205,7 @@ static int xway_nand_probe(struct platform_device *pdev) | cs_flag, EBU_NAND_CON); /* Scan to find existence of the device */ - err = nand_scan(mtd, 1); + err = nand_scan(&data->chip, 1); if (err) return err; diff --git a/drivers/staging/mt29f_spinand/mt29f_spinand.c b/drivers/staging/mt29f_spinand/mt29f_spinand.c index 448478451c4c..b50788b2d1d9 100644 --- a/drivers/staging/mt29f_spinand/mt29f_spinand.c +++ b/drivers/staging/mt29f_spinand/mt29f_spinand.c @@ -934,7 +934,7 @@ static int spinand_probe(struct spi_device *spi_nand) mtd_set_ooblayout(mtd, &spinand_oob_64_ops); #endif - if (nand_scan(mtd, 1)) + if (nand_scan(chip, 1)) return -ENXIO; return mtd_device_register(mtd, NULL, 0); diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h index 818cdc0a4dbb..733b228d94a5 100644 --- a/include/linux/mtd/rawnand.h +++ b/include/linux/mtd/rawnand.h @@ -24,15 +24,16 @@ #include #include +struct nand_chip; struct nand_flash_dev; /* Scan and identify a NAND device */ -int nand_scan_with_ids(struct mtd_info *mtd, int max_chips, +int nand_scan_with_ids(struct nand_chip *chip, int max_chips, struct nand_flash_dev *ids); -static inline int nand_scan(struct mtd_info *mtd, int max_chips) +static inline int nand_scan(struct nand_chip *chip, int max_chips) { - return nand_scan_with_ids(mtd, max_chips, NULL); + return nand_scan_with_ids(chip, max_chips, NULL); } /* Internal helper for board drivers which need to override command function */ From 59ac276f22270fb2094910f9a734c17f41c25e70 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Thu, 6 Sep 2018 14:05:15 +0200 Subject: [PATCH 243/302] mtd: rawnand: Pass a nand_chip object to nand_release() Let's make the raw NAND API consistent by patching all helpers to take a nand_chip object instead of an mtd_info one. Now is nand_release()'s turn. Signed-off-by: Boris Brezillon Signed-off-by: Miquel Raynal --- Documentation/driver-api/mtdnand.rst | 2 +- drivers/mtd/nand/raw/ams-delta.c | 2 +- drivers/mtd/nand/raw/au1550nd.c | 2 +- drivers/mtd/nand/raw/bcm47xxnflash/main.c | 2 +- drivers/mtd/nand/raw/brcmnand/brcmnand.c | 2 +- drivers/mtd/nand/raw/cafe_nand.c | 2 +- drivers/mtd/nand/raw/cmx270_nand.c | 2 +- drivers/mtd/nand/raw/cs553x_nand.c | 2 +- drivers/mtd/nand/raw/davinci_nand.c | 2 +- drivers/mtd/nand/raw/denali.c | 4 +--- drivers/mtd/nand/raw/diskonchip.c | 4 ++-- drivers/mtd/nand/raw/docg4.c | 2 +- drivers/mtd/nand/raw/fsl_elbc_nand.c | 3 +-- drivers/mtd/nand/raw/fsl_ifc_nand.c | 3 +-- drivers/mtd/nand/raw/fsl_upm.c | 2 +- drivers/mtd/nand/raw/fsmc_nand.c | 2 +- drivers/mtd/nand/raw/gpio.c | 2 +- drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c | 2 +- drivers/mtd/nand/raw/hisi504_nand.c | 3 +-- drivers/mtd/nand/raw/jz4740_nand.c | 2 +- drivers/mtd/nand/raw/jz4780_nand.c | 4 ++-- drivers/mtd/nand/raw/lpc32xx_mlc.c | 3 +-- drivers/mtd/nand/raw/lpc32xx_slc.c | 3 +-- drivers/mtd/nand/raw/marvell_nand.c | 4 ++-- drivers/mtd/nand/raw/mpc5121_nfc.c | 2 +- drivers/mtd/nand/raw/mtk_nand.c | 4 ++-- drivers/mtd/nand/raw/mxc_nand.c | 2 +- drivers/mtd/nand/raw/nand_base.c | 8 ++++---- drivers/mtd/nand/raw/nandsim.c | 4 ++-- drivers/mtd/nand/raw/ndfc.c | 2 +- drivers/mtd/nand/raw/nuc900_nand.c | 2 +- drivers/mtd/nand/raw/omap2.c | 2 +- drivers/mtd/nand/raw/orion_nand.c | 5 ++--- drivers/mtd/nand/raw/oxnas_nand.c | 4 ++-- drivers/mtd/nand/raw/pasemi_nand.c | 2 +- drivers/mtd/nand/raw/plat_nand.c | 4 ++-- drivers/mtd/nand/raw/qcom_nandc.c | 2 +- drivers/mtd/nand/raw/r852.c | 4 ++-- drivers/mtd/nand/raw/s3c2410.c | 2 +- drivers/mtd/nand/raw/sh_flctl.c | 2 +- drivers/mtd/nand/raw/sharpsl.c | 4 ++-- drivers/mtd/nand/raw/socrates_nand.c | 5 ++--- drivers/mtd/nand/raw/sunxi_nand.c | 4 ++-- drivers/mtd/nand/raw/tango_nand.c | 2 +- drivers/mtd/nand/raw/tmio_nand.c | 4 ++-- drivers/mtd/nand/raw/txx9ndfmc.c | 2 +- drivers/mtd/nand/raw/vf610_nfc.c | 2 +- drivers/mtd/nand/raw/xway_nand.c | 4 ++-- include/linux/mtd/rawnand.h | 2 +- 49 files changed, 66 insertions(+), 75 deletions(-) diff --git a/Documentation/driver-api/mtdnand.rst b/Documentation/driver-api/mtdnand.rst index 1ab6f35b6410..5470a3d6bd9e 100644 --- a/Documentation/driver-api/mtdnand.rst +++ b/Documentation/driver-api/mtdnand.rst @@ -277,7 +277,7 @@ unregisters the partitions in the MTD layer. static void __exit board_cleanup (void) { /* Release resources, unregister device */ - nand_release (board_mtd); + nand_release (mtd_to_nand(board_mtd)); /* unmap physical address */ iounmap(baseaddr); diff --git a/drivers/mtd/nand/raw/ams-delta.c b/drivers/mtd/nand/raw/ams-delta.c index 24ba7296ec08..acf7971e815d 100644 --- a/drivers/mtd/nand/raw/ams-delta.c +++ b/drivers/mtd/nand/raw/ams-delta.c @@ -264,7 +264,7 @@ static int ams_delta_cleanup(struct platform_device *pdev) void __iomem *io_base = platform_get_drvdata(pdev); /* Release resources, unregister device */ - nand_release(ams_delta_mtd); + nand_release(mtd_to_nand(ams_delta_mtd)); gpio_free_array(_mandatory_gpio, ARRAY_SIZE(_mandatory_gpio)); gpio_free(AMS_DELTA_GPIO_PIN_NAND_RB); diff --git a/drivers/mtd/nand/raw/au1550nd.c b/drivers/mtd/nand/raw/au1550nd.c index 614f5d447ba5..d277a141c7d3 100644 --- a/drivers/mtd/nand/raw/au1550nd.c +++ b/drivers/mtd/nand/raw/au1550nd.c @@ -477,7 +477,7 @@ static int au1550nd_remove(struct platform_device *pdev) struct au1550nd_ctx *ctx = platform_get_drvdata(pdev); struct resource *r = platform_get_resource(pdev, IORESOURCE_MEM, 0); - nand_release(nand_to_mtd(&ctx->chip)); + nand_release(&ctx->chip); iounmap(ctx->base); release_mem_region(r->start, 0x1000); kfree(ctx); diff --git a/drivers/mtd/nand/raw/bcm47xxnflash/main.c b/drivers/mtd/nand/raw/bcm47xxnflash/main.c index fb31429b70a9..d79694160845 100644 --- a/drivers/mtd/nand/raw/bcm47xxnflash/main.c +++ b/drivers/mtd/nand/raw/bcm47xxnflash/main.c @@ -65,7 +65,7 @@ static int bcm47xxnflash_remove(struct platform_device *pdev) { struct bcm47xxnflash *nflash = platform_get_drvdata(pdev); - nand_release(nand_to_mtd(&nflash->nand_chip)); + nand_release(&nflash->nand_chip); return 0; } diff --git a/drivers/mtd/nand/raw/brcmnand/brcmnand.c b/drivers/mtd/nand/raw/brcmnand/brcmnand.c index a9a94c102654..19e6e918f896 100644 --- a/drivers/mtd/nand/raw/brcmnand/brcmnand.c +++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c @@ -2616,7 +2616,7 @@ int brcmnand_remove(struct platform_device *pdev) struct brcmnand_host *host; list_for_each_entry(host, &ctrl->host_list, node) - nand_release(nand_to_mtd(&host->chip)); + nand_release(&host->chip); clk_disable_unprepare(ctrl->clk); diff --git a/drivers/mtd/nand/raw/cafe_nand.c b/drivers/mtd/nand/raw/cafe_nand.c index e497b95d624e..3304594177c6 100644 --- a/drivers/mtd/nand/raw/cafe_nand.c +++ b/drivers/mtd/nand/raw/cafe_nand.c @@ -819,7 +819,7 @@ static void cafe_nand_remove(struct pci_dev *pdev) /* Disable NAND IRQ in global IRQ mask register */ cafe_writel(cafe, ~1 & cafe_readl(cafe, GLOBAL_IRQ_MASK), GLOBAL_IRQ_MASK); free_irq(pdev->irq, mtd); - nand_release(mtd); + nand_release(chip); free_rs(cafe->rs); pci_iounmap(pdev, cafe->mmio); dma_free_coherent(&cafe->pdev->dev, 2112, cafe->dmabuf, cafe->dmaaddr); diff --git a/drivers/mtd/nand/raw/cmx270_nand.c b/drivers/mtd/nand/raw/cmx270_nand.c index e92c0f113eb3..2eb933a8f99e 100644 --- a/drivers/mtd/nand/raw/cmx270_nand.c +++ b/drivers/mtd/nand/raw/cmx270_nand.c @@ -228,7 +228,7 @@ module_init(cmx270_init); static void __exit cmx270_cleanup(void) { /* Release resources, unregister device */ - nand_release(cmx270_nand_mtd); + nand_release(mtd_to_nand(cmx270_nand_mtd)); gpio_free(GPIO_NAND_RB); gpio_free(GPIO_NAND_CS); diff --git a/drivers/mtd/nand/raw/cs553x_nand.c b/drivers/mtd/nand/raw/cs553x_nand.c index 4065bcd12e64..d4be416bb2fa 100644 --- a/drivers/mtd/nand/raw/cs553x_nand.c +++ b/drivers/mtd/nand/raw/cs553x_nand.c @@ -336,7 +336,7 @@ static void __exit cs553x_cleanup(void) mmio_base = this->IO_ADDR_R; /* Release resources, unregister device */ - nand_release(mtd); + nand_release(this); kfree(mtd->name); cs553x_mtd[i] = NULL; diff --git a/drivers/mtd/nand/raw/davinci_nand.c b/drivers/mtd/nand/raw/davinci_nand.c index 1021624195f7..66d3d5966013 100644 --- a/drivers/mtd/nand/raw/davinci_nand.c +++ b/drivers/mtd/nand/raw/davinci_nand.c @@ -841,7 +841,7 @@ static int nand_davinci_remove(struct platform_device *pdev) ecc4_busy = false; spin_unlock_irq(&davinci_nand_lock); - nand_release(nand_to_mtd(&info->chip)); + nand_release(&info->chip); return 0; } diff --git a/drivers/mtd/nand/raw/denali.c b/drivers/mtd/nand/raw/denali.c index 2e8a825c740e..958619fd4d1b 100644 --- a/drivers/mtd/nand/raw/denali.c +++ b/drivers/mtd/nand/raw/denali.c @@ -1378,9 +1378,7 @@ EXPORT_SYMBOL(denali_init); void denali_remove(struct denali_nand_info *denali) { - struct mtd_info *mtd = nand_to_mtd(&denali->nand); - - nand_release(mtd); + nand_release(&denali->nand); denali_disable_irq(denali); } EXPORT_SYMBOL(denali_remove); diff --git a/drivers/mtd/nand/raw/diskonchip.c b/drivers/mtd/nand/raw/diskonchip.c index 9159748a2ef0..43d1e08133ce 100644 --- a/drivers/mtd/nand/raw/diskonchip.c +++ b/drivers/mtd/nand/raw/diskonchip.c @@ -1627,7 +1627,7 @@ static int __init doc_probe(unsigned long physadr) /* nand_release will call mtd_device_unregister, but we haven't yet added it. This is handled without incident by mtd_device_unregister, as far as I can tell. */ - nand_release(mtd); + nand_release(nand); goto fail; } @@ -1662,7 +1662,7 @@ static void release_nanddoc(void) doc = nand_get_controller_data(nand); nextmtd = doc->nextdoc; - nand_release(mtd); + nand_release(nand); iounmap(doc->virtadr); release_mem_region(doc->physadr, DOC_IOREMAP_LEN); free_rs(doc->rs_decoder); diff --git a/drivers/mtd/nand/raw/docg4.c b/drivers/mtd/nand/raw/docg4.c index 69f60755f38a..2d86bc5a886d 100644 --- a/drivers/mtd/nand/raw/docg4.c +++ b/drivers/mtd/nand/raw/docg4.c @@ -1420,7 +1420,7 @@ static int __init probe_docg4(struct platform_device *pdev) static int __exit cleanup_docg4(struct platform_device *pdev) { struct docg4_priv *doc = platform_get_drvdata(pdev); - nand_release(doc->mtd); + nand_release(mtd_to_nand(doc->mtd)); kfree(mtd_to_nand(doc->mtd)); iounmap(doc->virtadr); return 0; diff --git a/drivers/mtd/nand/raw/fsl_elbc_nand.c b/drivers/mtd/nand/raw/fsl_elbc_nand.c index 541343d142e0..22bcd64a66c8 100644 --- a/drivers/mtd/nand/raw/fsl_elbc_nand.c +++ b/drivers/mtd/nand/raw/fsl_elbc_nand.c @@ -942,9 +942,8 @@ static int fsl_elbc_nand_remove(struct platform_device *pdev) { struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = fsl_lbc_ctrl_dev->nand; struct fsl_elbc_mtd *priv = dev_get_drvdata(&pdev->dev); - struct mtd_info *mtd = nand_to_mtd(&priv->chip); - nand_release(mtd); + nand_release(&priv->chip); fsl_elbc_chip_remove(priv); mutex_lock(&fsl_elbc_nand_mutex); diff --git a/drivers/mtd/nand/raw/fsl_ifc_nand.c b/drivers/mtd/nand/raw/fsl_ifc_nand.c index ad010c72df78..70bf8e1552a5 100644 --- a/drivers/mtd/nand/raw/fsl_ifc_nand.c +++ b/drivers/mtd/nand/raw/fsl_ifc_nand.c @@ -1105,9 +1105,8 @@ static int fsl_ifc_nand_probe(struct platform_device *dev) static int fsl_ifc_nand_remove(struct platform_device *dev) { struct fsl_ifc_mtd *priv = dev_get_drvdata(&dev->dev); - struct mtd_info *mtd = nand_to_mtd(&priv->chip); - nand_release(mtd); + nand_release(&priv->chip); fsl_ifc_chip_remove(priv); mutex_lock(&fsl_ifc_nand_mutex); diff --git a/drivers/mtd/nand/raw/fsl_upm.c b/drivers/mtd/nand/raw/fsl_upm.c index 99edae365d16..ffddfc9721ac 100644 --- a/drivers/mtd/nand/raw/fsl_upm.c +++ b/drivers/mtd/nand/raw/fsl_upm.c @@ -326,7 +326,7 @@ static int fun_remove(struct platform_device *ofdev) struct mtd_info *mtd = nand_to_mtd(&fun->chip); int i; - nand_release(mtd); + nand_release(&fun->chip); kfree(mtd->name); for (i = 0; i < fun->mchip_count; i++) { diff --git a/drivers/mtd/nand/raw/fsmc_nand.c b/drivers/mtd/nand/raw/fsmc_nand.c index 9991e3b8e237..25d354e9448e 100644 --- a/drivers/mtd/nand/raw/fsmc_nand.c +++ b/drivers/mtd/nand/raw/fsmc_nand.c @@ -1161,7 +1161,7 @@ static int fsmc_nand_remove(struct platform_device *pdev) struct fsmc_nand_data *host = platform_get_drvdata(pdev); if (host) { - nand_release(nand_to_mtd(&host->nand)); + nand_release(&host->nand); if (host->mode == USE_DMA_ACCESS) { dma_release_channel(host->write_dma_chan); diff --git a/drivers/mtd/nand/raw/gpio.c b/drivers/mtd/nand/raw/gpio.c index 983d3be48019..0e7d00faf33c 100644 --- a/drivers/mtd/nand/raw/gpio.c +++ b/drivers/mtd/nand/raw/gpio.c @@ -194,7 +194,7 @@ static int gpio_nand_remove(struct platform_device *pdev) { struct gpiomtd *gpiomtd = platform_get_drvdata(pdev); - nand_release(nand_to_mtd(&gpiomtd->nand_chip)); + nand_release(&gpiomtd->nand_chip); /* Enable write protection and disable the chip */ if (gpiomtd->nwp && !IS_ERR(gpiomtd->nwp)) diff --git a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c index 7af207bc3ab5..fe99d9323d4a 100644 --- a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c +++ b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c @@ -2026,7 +2026,7 @@ static int gpmi_nand_remove(struct platform_device *pdev) { struct gpmi_nand_data *this = platform_get_drvdata(pdev); - nand_release(nand_to_mtd(&this->nand)); + nand_release(&this->nand); gpmi_free_dma_buffer(this); release_resources(this); return 0; diff --git a/drivers/mtd/nand/raw/hisi504_nand.c b/drivers/mtd/nand/raw/hisi504_nand.c index 81baa2e6ae56..9106a1d60bca 100644 --- a/drivers/mtd/nand/raw/hisi504_nand.c +++ b/drivers/mtd/nand/raw/hisi504_nand.c @@ -818,9 +818,8 @@ static int hisi_nfc_probe(struct platform_device *pdev) static int hisi_nfc_remove(struct platform_device *pdev) { struct hinfc_host *host = platform_get_drvdata(pdev); - struct mtd_info *mtd = nand_to_mtd(&host->chip); - nand_release(mtd); + nand_release(&host->chip); return 0; } diff --git a/drivers/mtd/nand/raw/jz4740_nand.c b/drivers/mtd/nand/raw/jz4740_nand.c index 75bb26645c82..27603d78b157 100644 --- a/drivers/mtd/nand/raw/jz4740_nand.c +++ b/drivers/mtd/nand/raw/jz4740_nand.c @@ -507,7 +507,7 @@ static int jz_nand_remove(struct platform_device *pdev) struct jz_nand *nand = platform_get_drvdata(pdev); size_t i; - nand_release(nand_to_mtd(&nand->chip)); + nand_release(&nand->chip); /* Deassert and disable all chips */ writel(0, nand->base + JZ_REG_NAND_CTRL); diff --git a/drivers/mtd/nand/raw/jz4780_nand.c b/drivers/mtd/nand/raw/jz4780_nand.c index 80f29b28bcc4..7d008aeae165 100644 --- a/drivers/mtd/nand/raw/jz4780_nand.c +++ b/drivers/mtd/nand/raw/jz4780_nand.c @@ -292,7 +292,7 @@ static int jz4780_nand_init_chip(struct platform_device *pdev, ret = mtd_device_register(mtd, NULL, 0); if (ret) { - nand_release(mtd); + nand_release(chip); return ret; } @@ -307,7 +307,7 @@ static void jz4780_nand_cleanup_chips(struct jz4780_nand_controller *nfc) while (!list_empty(&nfc->chips)) { chip = list_first_entry(&nfc->chips, struct jz4780_nand_chip, chip_list); - nand_release(nand_to_mtd(&chip->chip)); + nand_release(&chip->chip); list_del(&chip->chip_list); } } diff --git a/drivers/mtd/nand/raw/lpc32xx_mlc.c b/drivers/mtd/nand/raw/lpc32xx_mlc.c index 453a83b82d73..d240b8ff40ca 100644 --- a/drivers/mtd/nand/raw/lpc32xx_mlc.c +++ b/drivers/mtd/nand/raw/lpc32xx_mlc.c @@ -839,9 +839,8 @@ static int lpc32xx_nand_probe(struct platform_device *pdev) static int lpc32xx_nand_remove(struct platform_device *pdev) { struct lpc32xx_nand_host *host = platform_get_drvdata(pdev); - struct mtd_info *mtd = nand_to_mtd(&host->nand_chip); - nand_release(mtd); + nand_release(&host->nand_chip); free_irq(host->irq, host); if (use_dma) dma_release_channel(host->dma_chan); diff --git a/drivers/mtd/nand/raw/lpc32xx_slc.c b/drivers/mtd/nand/raw/lpc32xx_slc.c index ad6eff0591d2..607e4bdfae03 100644 --- a/drivers/mtd/nand/raw/lpc32xx_slc.c +++ b/drivers/mtd/nand/raw/lpc32xx_slc.c @@ -956,9 +956,8 @@ static int lpc32xx_nand_remove(struct platform_device *pdev) { uint32_t tmp; struct lpc32xx_nand_host *host = platform_get_drvdata(pdev); - struct mtd_info *mtd = nand_to_mtd(&host->nand_chip); - nand_release(mtd); + nand_release(&host->nand_chip); dma_release_channel(host->dma_chan); /* Force CE high */ diff --git a/drivers/mtd/nand/raw/marvell_nand.c b/drivers/mtd/nand/raw/marvell_nand.c index dde64609415f..5a9836c5093c 100644 --- a/drivers/mtd/nand/raw/marvell_nand.c +++ b/drivers/mtd/nand/raw/marvell_nand.c @@ -2618,7 +2618,7 @@ static int marvell_nand_chip_init(struct device *dev, struct marvell_nfc *nfc, ret = mtd_device_register(mtd, NULL, 0); if (ret) { dev_err(dev, "failed to register mtd device: %d\n", ret); - nand_release(mtd); + nand_release(chip); return ret; } @@ -2673,7 +2673,7 @@ static void marvell_nand_chips_cleanup(struct marvell_nfc *nfc) struct marvell_nand_chip *entry, *temp; list_for_each_entry_safe(entry, temp, &nfc->chips, node) { - nand_release(nand_to_mtd(&entry->chip)); + nand_release(&entry->chip); list_del(&entry->node); } } diff --git a/drivers/mtd/nand/raw/mpc5121_nfc.c b/drivers/mtd/nand/raw/mpc5121_nfc.c index efaaec462bd7..3c90d6955476 100644 --- a/drivers/mtd/nand/raw/mpc5121_nfc.c +++ b/drivers/mtd/nand/raw/mpc5121_nfc.c @@ -817,7 +817,7 @@ static int mpc5121_nfc_remove(struct platform_device *op) struct device *dev = &op->dev; struct mtd_info *mtd = dev_get_drvdata(dev); - nand_release(mtd); + nand_release(mtd_to_nand(mtd)); mpc5121_nfc_free(dev, mtd); return 0; diff --git a/drivers/mtd/nand/raw/mtk_nand.c b/drivers/mtd/nand/raw/mtk_nand.c index 7a2ce405f914..46d447f148f1 100644 --- a/drivers/mtd/nand/raw/mtk_nand.c +++ b/drivers/mtd/nand/raw/mtk_nand.c @@ -1372,7 +1372,7 @@ static int mtk_nfc_nand_chip_init(struct device *dev, struct mtk_nfc *nfc, ret = mtd_device_register(mtd, NULL, 0); if (ret) { dev_err(dev, "mtd parse partition error\n"); - nand_release(mtd); + nand_release(nand); return ret; } @@ -1538,7 +1538,7 @@ static int mtk_nfc_remove(struct platform_device *pdev) while (!list_empty(&nfc->chips)) { chip = list_first_entry(&nfc->chips, struct mtk_nfc_nand_chip, node); - nand_release(nand_to_mtd(&chip->nand)); + nand_release(&chip->nand); list_del(&chip->node); } diff --git a/drivers/mtd/nand/raw/mxc_nand.c b/drivers/mtd/nand/raw/mxc_nand.c index 1ca03d88adf1..3c57e14e1c7c 100644 --- a/drivers/mtd/nand/raw/mxc_nand.c +++ b/drivers/mtd/nand/raw/mxc_nand.c @@ -1915,7 +1915,7 @@ static int mxcnd_remove(struct platform_device *pdev) { struct mxc_nand_host *host = platform_get_drvdata(pdev); - nand_release(nand_to_mtd(&host->nand)); + nand_release(&host->nand); if (host->clk_act) clk_disable_unprepare(host->clk); diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c index 974cbfbde5e2..f937efe145af 100644 --- a/drivers/mtd/nand/raw/nand_base.c +++ b/drivers/mtd/nand/raw/nand_base.c @@ -6853,12 +6853,12 @@ EXPORT_SYMBOL_GPL(nand_cleanup); /** * nand_release - [NAND Interface] Unregister the MTD device and free resources * held by the NAND device - * @mtd: MTD device structure + * @chip: NAND chip object */ -void nand_release(struct mtd_info *mtd) +void nand_release(struct nand_chip *chip) { - mtd_device_unregister(mtd); - nand_cleanup(mtd_to_nand(mtd)); + mtd_device_unregister(nand_to_mtd(chip)); + nand_cleanup(chip); } EXPORT_SYMBOL_GPL(nand_release); diff --git a/drivers/mtd/nand/raw/nandsim.c b/drivers/mtd/nand/raw/nandsim.c index 60761175e531..e9f7b9e1aead 100644 --- a/drivers/mtd/nand/raw/nandsim.c +++ b/drivers/mtd/nand/raw/nandsim.c @@ -2354,7 +2354,7 @@ static int __init ns_init_module(void) err_exit: free_nandsim(nand); - nand_release(nsmtd); + nand_release(chip); for (i = 0;i < ARRAY_SIZE(nand->partitions); ++i) kfree(nand->partitions[i].name); error: @@ -2376,7 +2376,7 @@ static void __exit ns_cleanup_module(void) int i; free_nandsim(ns); /* Free nandsim private resources */ - nand_release(nsmtd); /* Unregister driver */ + nand_release(chip); /* Unregister driver */ for (i = 0;i < ARRAY_SIZE(ns->partitions); ++i) kfree(ns->partitions[i].name); kfree(mtd_to_nand(nsmtd)); /* Free other structures */ diff --git a/drivers/mtd/nand/raw/ndfc.c b/drivers/mtd/nand/raw/ndfc.c index 7ce7f37dc67a..ab24e9ca769b 100644 --- a/drivers/mtd/nand/raw/ndfc.c +++ b/drivers/mtd/nand/raw/ndfc.c @@ -258,7 +258,7 @@ static int ndfc_remove(struct platform_device *ofdev) struct ndfc_controller *ndfc = dev_get_drvdata(&ofdev->dev); struct mtd_info *mtd = nand_to_mtd(&ndfc->chip); - nand_release(mtd); + nand_release(&ndfc->chip); kfree(mtd->name); return 0; diff --git a/drivers/mtd/nand/raw/nuc900_nand.c b/drivers/mtd/nand/raw/nuc900_nand.c index 41ed993b9523..0c675b6c0b6e 100644 --- a/drivers/mtd/nand/raw/nuc900_nand.c +++ b/drivers/mtd/nand/raw/nuc900_nand.c @@ -284,7 +284,7 @@ static int nuc900_nand_remove(struct platform_device *pdev) { struct nuc900_nand *nuc900_nand = platform_get_drvdata(pdev); - nand_release(nand_to_mtd(&nuc900_nand->chip)); + nand_release(&nuc900_nand->chip); clk_disable(nuc900_nand->clk); return 0; diff --git a/drivers/mtd/nand/raw/omap2.c b/drivers/mtd/nand/raw/omap2.c index c2aff2492fa1..b243f2ab3622 100644 --- a/drivers/mtd/nand/raw/omap2.c +++ b/drivers/mtd/nand/raw/omap2.c @@ -2290,7 +2290,7 @@ static int omap_nand_remove(struct platform_device *pdev) } if (info->dma) dma_release_channel(info->dma); - nand_release(mtd); + nand_release(nand_chip); return 0; } diff --git a/drivers/mtd/nand/raw/orion_nand.c b/drivers/mtd/nand/raw/orion_nand.c index 256a6b018bdc..5c58d91ffaee 100644 --- a/drivers/mtd/nand/raw/orion_nand.c +++ b/drivers/mtd/nand/raw/orion_nand.c @@ -181,7 +181,7 @@ static int __init orion_nand_probe(struct platform_device *pdev) mtd->name = "orion_nand"; ret = mtd_device_register(mtd, board->parts, board->nr_parts); if (ret) { - nand_release(mtd); + nand_release(nc); goto no_dev; } @@ -196,9 +196,8 @@ static int orion_nand_remove(struct platform_device *pdev) { struct orion_nand_info *info = platform_get_drvdata(pdev); struct nand_chip *chip = &info->chip; - struct mtd_info *mtd = nand_to_mtd(chip); - nand_release(mtd); + nand_release(chip); clk_disable_unprepare(info->clk); diff --git a/drivers/mtd/nand/raw/oxnas_nand.c b/drivers/mtd/nand/raw/oxnas_nand.c index 9aeb024c2a0e..5bc180536320 100644 --- a/drivers/mtd/nand/raw/oxnas_nand.c +++ b/drivers/mtd/nand/raw/oxnas_nand.c @@ -148,7 +148,7 @@ static int oxnas_nand_probe(struct platform_device *pdev) err = mtd_device_register(mtd, NULL, 0); if (err) { - nand_release(mtd); + nand_release(chip); goto err_clk_unprepare; } @@ -176,7 +176,7 @@ static int oxnas_nand_remove(struct platform_device *pdev) struct oxnas_nand_ctrl *oxnas = platform_get_drvdata(pdev); if (oxnas->chips[0]) - nand_release(nand_to_mtd(oxnas->chips[0])); + nand_release(oxnas->chips[0]); clk_disable_unprepare(oxnas->clk); diff --git a/drivers/mtd/nand/raw/pasemi_nand.c b/drivers/mtd/nand/raw/pasemi_nand.c index eca4e41d2be3..c8e2ac04fb86 100644 --- a/drivers/mtd/nand/raw/pasemi_nand.c +++ b/drivers/mtd/nand/raw/pasemi_nand.c @@ -191,7 +191,7 @@ static int pasemi_nand_remove(struct platform_device *ofdev) chip = mtd_to_nand(pasemi_nand_mtd); /* Release resources, unregister device */ - nand_release(pasemi_nand_mtd); + nand_release(chip); release_region(lpcctl, 4); diff --git a/drivers/mtd/nand/raw/plat_nand.c b/drivers/mtd/nand/raw/plat_nand.c index c9a23fb21718..80e1a44f0465 100644 --- a/drivers/mtd/nand/raw/plat_nand.c +++ b/drivers/mtd/nand/raw/plat_nand.c @@ -144,7 +144,7 @@ static int plat_nand_probe(struct platform_device *pdev) if (!err) return err; - nand_release(mtd); + nand_release(&data->chip); out: if (pdata->ctrl.remove) pdata->ctrl.remove(pdev); @@ -159,7 +159,7 @@ static int plat_nand_remove(struct platform_device *pdev) struct plat_nand_data *data = platform_get_drvdata(pdev); struct platform_nand_data *pdata = dev_get_platdata(&pdev->dev); - nand_release(nand_to_mtd(&data->chip)); + nand_release(&data->chip); if (pdata->ctrl.remove) pdata->ctrl.remove(pdev); diff --git a/drivers/mtd/nand/raw/qcom_nandc.c b/drivers/mtd/nand/raw/qcom_nandc.c index d800347e74da..312cfd786b0f 100644 --- a/drivers/mtd/nand/raw/qcom_nandc.c +++ b/drivers/mtd/nand/raw/qcom_nandc.c @@ -2999,7 +2999,7 @@ static int qcom_nandc_remove(struct platform_device *pdev) struct qcom_nand_host *host; list_for_each_entry(host, &nandc->host_list, node) - nand_release(nand_to_mtd(&host->chip)); + nand_release(&host->chip); qcom_nandc_unalloc(nandc); diff --git a/drivers/mtd/nand/raw/r852.c b/drivers/mtd/nand/raw/r852.c index dcdeb0660e5e..bb74a0ac697e 100644 --- a/drivers/mtd/nand/raw/r852.c +++ b/drivers/mtd/nand/raw/r852.c @@ -656,7 +656,7 @@ static int r852_register_nand_device(struct r852_device *dev) dev->card_registred = 1; return 0; error3: - nand_release(mtd); + nand_release(dev->chip); error1: /* Force card redetect */ dev->card_detected = 0; @@ -675,7 +675,7 @@ static void r852_unregister_nand_device(struct r852_device *dev) return; device_remove_file(&mtd->dev, &dev_attr_media_type); - nand_release(mtd); + nand_release(dev->chip); r852_engine_disable(dev); dev->card_registred = 0; } diff --git a/drivers/mtd/nand/raw/s3c2410.c b/drivers/mtd/nand/raw/s3c2410.c index 7f30d801d642..cf045813c160 100644 --- a/drivers/mtd/nand/raw/s3c2410.c +++ b/drivers/mtd/nand/raw/s3c2410.c @@ -781,7 +781,7 @@ static int s3c24xx_nand_remove(struct platform_device *pdev) for (mtdno = 0; mtdno < info->mtd_count; mtdno++, ptr++) { pr_debug("releasing mtd %d (%p)\n", mtdno, ptr); - nand_release(nand_to_mtd(&ptr->chip)); + nand_release(&ptr->chip); } } diff --git a/drivers/mtd/nand/raw/sh_flctl.c b/drivers/mtd/nand/raw/sh_flctl.c index abcc3be89b89..2580fd981077 100644 --- a/drivers/mtd/nand/raw/sh_flctl.c +++ b/drivers/mtd/nand/raw/sh_flctl.c @@ -1216,7 +1216,7 @@ static int flctl_remove(struct platform_device *pdev) struct sh_flctl *flctl = platform_get_drvdata(pdev); flctl_release_dma(flctl); - nand_release(nand_to_mtd(&flctl->chip)); + nand_release(&flctl->chip); pm_runtime_disable(&pdev->dev); return 0; diff --git a/drivers/mtd/nand/raw/sharpsl.c b/drivers/mtd/nand/raw/sharpsl.c index 4afacb0dcf00..c8eb4654bb1c 100644 --- a/drivers/mtd/nand/raw/sharpsl.c +++ b/drivers/mtd/nand/raw/sharpsl.c @@ -187,7 +187,7 @@ static int sharpsl_nand_probe(struct platform_device *pdev) return 0; err_add: - nand_release(mtd); + nand_release(this); err_scan: iounmap(sharpsl->io); @@ -205,7 +205,7 @@ static int sharpsl_nand_remove(struct platform_device *pdev) struct sharpsl_nand *sharpsl = platform_get_drvdata(pdev); /* Release resources, unregister device */ - nand_release(nand_to_mtd(&sharpsl->chip)); + nand_release(&sharpsl->chip); iounmap(sharpsl->io); diff --git a/drivers/mtd/nand/raw/socrates_nand.c b/drivers/mtd/nand/raw/socrates_nand.c index e335560f87af..82ba371a8e18 100644 --- a/drivers/mtd/nand/raw/socrates_nand.c +++ b/drivers/mtd/nand/raw/socrates_nand.c @@ -181,7 +181,7 @@ static int socrates_nand_probe(struct platform_device *ofdev) if (!res) return res; - nand_release(mtd); + nand_release(nand_chip); out: iounmap(host->io_base); @@ -194,9 +194,8 @@ static int socrates_nand_probe(struct platform_device *ofdev) static int socrates_nand_remove(struct platform_device *ofdev) { struct socrates_nand_host *host = dev_get_drvdata(&ofdev->dev); - struct mtd_info *mtd = nand_to_mtd(&host->nand_chip); - nand_release(mtd); + nand_release(&host->nand_chip); iounmap(host->io_base); diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c index 179f74b6edf6..e31ab86bebee 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -1947,7 +1947,7 @@ static int sunxi_nand_chip_init(struct device *dev, struct sunxi_nfc *nfc, ret = mtd_device_register(mtd, NULL, 0); if (ret) { dev_err(dev, "failed to register mtd device: %d\n", ret); - nand_release(mtd); + nand_release(nand); return ret; } @@ -1986,7 +1986,7 @@ static void sunxi_nand_chips_cleanup(struct sunxi_nfc *nfc) while (!list_empty(&nfc->chips)) { chip = list_first_entry(&nfc->chips, struct sunxi_nand_chip, node); - nand_release(nand_to_mtd(&chip->nand)); + nand_release(&chip->nand); sunxi_nand_ecc_cleanup(&chip->nand.ecc); list_del(&chip->node); } diff --git a/drivers/mtd/nand/raw/tango_nand.c b/drivers/mtd/nand/raw/tango_nand.c index 45beb87aec93..1061eb60ee60 100644 --- a/drivers/mtd/nand/raw/tango_nand.c +++ b/drivers/mtd/nand/raw/tango_nand.c @@ -617,7 +617,7 @@ static int tango_nand_remove(struct platform_device *pdev) for (cs = 0; cs < MAX_CS; ++cs) { if (nfc->chips[cs]) - nand_release(nand_to_mtd(&nfc->chips[cs]->nand_chip)); + nand_release(&nfc->chips[cs]->nand_chip); } return 0; diff --git a/drivers/mtd/nand/raw/tmio_nand.c b/drivers/mtd/nand/raw/tmio_nand.c index 6df499a239ae..39594910e6f0 100644 --- a/drivers/mtd/nand/raw/tmio_nand.c +++ b/drivers/mtd/nand/raw/tmio_nand.c @@ -449,7 +449,7 @@ static int tmio_probe(struct platform_device *dev) if (!retval) return retval; - nand_release(mtd); + nand_release(nand_chip); err_irq: tmio_hw_stop(dev, tmio); @@ -460,7 +460,7 @@ static int tmio_remove(struct platform_device *dev) { struct tmio_nand *tmio = platform_get_drvdata(dev); - nand_release(nand_to_mtd(&tmio->chip)); + nand_release(&tmio->chip); tmio_hw_stop(dev, tmio); return 0; } diff --git a/drivers/mtd/nand/raw/txx9ndfmc.c b/drivers/mtd/nand/raw/txx9ndfmc.c index 169e8bcee61e..f722aae2b244 100644 --- a/drivers/mtd/nand/raw/txx9ndfmc.c +++ b/drivers/mtd/nand/raw/txx9ndfmc.c @@ -390,7 +390,7 @@ static int __exit txx9ndfmc_remove(struct platform_device *dev) chip = mtd_to_nand(mtd); txx9_priv = nand_get_controller_data(chip); - nand_release(mtd); + nand_release(chip); kfree(txx9_priv->mtdname); kfree(txx9_priv); } diff --git a/drivers/mtd/nand/raw/vf610_nfc.c b/drivers/mtd/nand/raw/vf610_nfc.c index 3b486f4ce868..a73213c835a5 100644 --- a/drivers/mtd/nand/raw/vf610_nfc.c +++ b/drivers/mtd/nand/raw/vf610_nfc.c @@ -916,7 +916,7 @@ static int vf610_nfc_remove(struct platform_device *pdev) struct mtd_info *mtd = platform_get_drvdata(pdev); struct vf610_nfc *nfc = mtd_to_nfc(mtd); - nand_release(mtd); + nand_release(mtd_to_nand(mtd)); clk_disable_unprepare(nfc->clk); return 0; } diff --git a/drivers/mtd/nand/raw/xway_nand.c b/drivers/mtd/nand/raw/xway_nand.c index e670d3b5a646..1adb41acebfc 100644 --- a/drivers/mtd/nand/raw/xway_nand.c +++ b/drivers/mtd/nand/raw/xway_nand.c @@ -211,7 +211,7 @@ static int xway_nand_probe(struct platform_device *pdev) err = mtd_device_register(mtd, NULL, 0); if (err) - nand_release(mtd); + nand_release(&data->chip); return err; } @@ -223,7 +223,7 @@ static int xway_nand_remove(struct platform_device *pdev) { struct xway_nand_data *data = platform_get_drvdata(pdev); - nand_release(nand_to_mtd(&data->chip)); + nand_release(&data->chip); return 0; } diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h index 733b228d94a5..e9c59f0624ad 100644 --- a/include/linux/mtd/rawnand.h +++ b/include/linux/mtd/rawnand.h @@ -1739,7 +1739,7 @@ int nand_write_data_op(struct nand_chip *chip, const void *buf, */ void nand_cleanup(struct nand_chip *chip); /* Unregister the MTD device and calls nand_cleanup() */ -void nand_release(struct mtd_info *mtd); +void nand_release(struct nand_chip *chip); /* Default extended ID decoding function */ void nand_decode_ext_id(struct nand_chip *chip); From 2b356ab46ebe9b1bc63bda6708b81c9200382e78 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Thu, 6 Sep 2018 14:05:16 +0200 Subject: [PATCH 244/302] mtd: rawnand: Pass a nand_chip object to nand_wait_ready() Let's make the raw NAND API consistent by patching all helpers to take a nand_chip object instead of an mtd_info one. Now is nand_wait_ready()'s turn. Signed-off-by: Boris Brezillon Signed-off-by: Miquel Raynal --- drivers/mtd/nand/raw/bcm47xxnflash/ops_bcm4706.c | 2 +- drivers/mtd/nand/raw/cafe_nand.c | 2 +- drivers/mtd/nand/raw/nand_base.c | 12 ++++++------ include/linux/mtd/rawnand.h | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/mtd/nand/raw/bcm47xxnflash/ops_bcm4706.c b/drivers/mtd/nand/raw/bcm47xxnflash/ops_bcm4706.c index 9b62bc2d25a0..7022ffd271ad 100644 --- a/drivers/mtd/nand/raw/bcm47xxnflash/ops_bcm4706.c +++ b/drivers/mtd/nand/raw/bcm47xxnflash/ops_bcm4706.c @@ -232,7 +232,7 @@ static void bcm47xxnflash_ops_bcm4706_cmdfunc(struct mtd_info *mtd, nand_chip->cmd_ctrl(mtd, command, NAND_CTRL_CLE); ndelay(100); - nand_wait_ready(mtd); + nand_wait_ready(nand_chip); break; case NAND_CMD_READID: ctlcode = NCTL_CSA | 0x01000000 | NCTL_CMD1W | NCTL_CMD0; diff --git a/drivers/mtd/nand/raw/cafe_nand.c b/drivers/mtd/nand/raw/cafe_nand.c index 3304594177c6..94e5f7a56084 100644 --- a/drivers/mtd/nand/raw/cafe_nand.c +++ b/drivers/mtd/nand/raw/cafe_nand.c @@ -313,7 +313,7 @@ static void cafe_nand_cmdfunc(struct mtd_info *mtd, unsigned command, cafe_writel(cafe, cafe->ctl2, NAND_CTRL2); return; } - nand_wait_ready(mtd); + nand_wait_ready(chip); cafe_writel(cafe, cafe->ctl2, NAND_CTRL2); } diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c index f937efe145af..9d684f1d9e26 100644 --- a/drivers/mtd/nand/raw/nand_base.c +++ b/drivers/mtd/nand/raw/nand_base.c @@ -624,13 +624,13 @@ static void panic_nand_wait_ready(struct mtd_info *mtd, unsigned long timeo) /** * nand_wait_ready - [GENERIC] Wait for the ready pin after commands. - * @mtd: MTD device structure + * @chip: NAND chip object * * Wait for the ready pin after a command, and warn if a timeout occurs. */ -void nand_wait_ready(struct mtd_info *mtd) +void nand_wait_ready(struct nand_chip *chip) { - struct nand_chip *chip = mtd_to_nand(mtd); + struct mtd_info *mtd = nand_to_mtd(chip); unsigned long timeo = 400; if (in_interrupt() || oops_in_progress) @@ -852,7 +852,7 @@ static void nand_command(struct mtd_info *mtd, unsigned int command, */ ndelay(100); - nand_wait_ready(mtd); + nand_wait_ready(chip); } static void nand_ccs_delay(struct nand_chip *chip) @@ -1004,7 +1004,7 @@ static void nand_command_lp(struct mtd_info *mtd, unsigned int command, */ ndelay(100); - nand_wait_ready(mtd); + nand_wait_ready(chip); } /** @@ -2251,7 +2251,7 @@ static int nand_wait_rdy_op(struct nand_chip *chip, unsigned int timeout_ms, if (!chip->dev_ready) udelay(chip->chip_delay); else - nand_wait_ready(nand_to_mtd(chip)); + nand_wait_ready(chip); return 0; } diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h index e9c59f0624ad..55014e42912a 100644 --- a/include/linux/mtd/rawnand.h +++ b/include/linux/mtd/rawnand.h @@ -37,7 +37,7 @@ static inline int nand_scan(struct nand_chip *chip, int max_chips) } /* Internal helper for board drivers which need to override command function */ -void nand_wait_ready(struct mtd_info *mtd); +void nand_wait_ready(struct nand_chip *chip); /* The maximum number of NAND chips in an array */ #define NAND_MAX_CHIPS 8 From ec47636cd7e7b0dd53e526ec832ebb21b67ad9c6 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Thu, 6 Sep 2018 14:05:17 +0200 Subject: [PATCH 245/302] mtd: rawnand: Pass a nand_chip object to ecc->hwctl() Let's make the raw NAND API consistent by patching all helpers and hooks to take a nand_chip object instead of an mtd_info one. Now is ecc->hwctl()'s turn. Signed-off-by: Boris Brezillon Signed-off-by: Miquel Raynal --- drivers/mtd/nand/raw/cs553x_nand.c | 3 +-- drivers/mtd/nand/raw/davinci_nand.c | 10 +++++----- drivers/mtd/nand/raw/diskonchip.c | 6 ++---- drivers/mtd/nand/raw/fsmc_nand.c | 6 +++--- drivers/mtd/nand/raw/jz4740_nand.c | 4 ++-- drivers/mtd/nand/raw/jz4780_nand.c | 4 ++-- drivers/mtd/nand/raw/lpc32xx_mlc.c | 2 +- drivers/mtd/nand/raw/lpc32xx_slc.c | 2 +- drivers/mtd/nand/raw/nand_base.c | 14 +++++++------- drivers/mtd/nand/raw/ndfc.c | 3 +-- drivers/mtd/nand/raw/omap2.c | 17 ++++++++--------- drivers/mtd/nand/raw/r852.c | 4 ++-- drivers/mtd/nand/raw/s3c2410.c | 15 +++++++++------ drivers/mtd/nand/raw/sharpsl.c | 4 ++-- drivers/mtd/nand/raw/tmio_nand.c | 4 ++-- drivers/mtd/nand/raw/txx9ndfmc.c | 4 ++-- include/linux/mtd/rawnand.h | 2 +- 17 files changed, 51 insertions(+), 53 deletions(-) diff --git a/drivers/mtd/nand/raw/cs553x_nand.c b/drivers/mtd/nand/raw/cs553x_nand.c index d4be416bb2fa..508bcb3d134f 100644 --- a/drivers/mtd/nand/raw/cs553x_nand.c +++ b/drivers/mtd/nand/raw/cs553x_nand.c @@ -157,9 +157,8 @@ static int cs553x_device_ready(struct mtd_info *mtd) return (foo & CS_NAND_STS_FLASH_RDY) && !(foo & CS_NAND_CTLR_BUSY); } -static void cs_enable_hwecc(struct mtd_info *mtd, int mode) +static void cs_enable_hwecc(struct nand_chip *this, int mode) { - struct nand_chip *this = mtd_to_nand(mtd); void __iomem *mmio_base = this->IO_ADDR_R; writeb(0x07, mmio_base + MM_NAND_ECC_CTL); diff --git a/drivers/mtd/nand/raw/davinci_nand.c b/drivers/mtd/nand/raw/davinci_nand.c index 66d3d5966013..329de266c953 100644 --- a/drivers/mtd/nand/raw/davinci_nand.c +++ b/drivers/mtd/nand/raw/davinci_nand.c @@ -146,16 +146,16 @@ static inline uint32_t nand_davinci_readecc_1bit(struct mtd_info *mtd) + 4 * info->core_chipsel); } -static void nand_davinci_hwctl_1bit(struct mtd_info *mtd, int mode) +static void nand_davinci_hwctl_1bit(struct nand_chip *chip, int mode) { struct davinci_nand_info *info; uint32_t nandcfr; unsigned long flags; - info = to_davinci_nand(mtd); + info = to_davinci_nand(nand_to_mtd(chip)); /* Reset ECC hardware */ - nand_davinci_readecc_1bit(mtd); + nand_davinci_readecc_1bit(nand_to_mtd(chip)); spin_lock_irqsave(&davinci_nand_lock, flags); @@ -231,9 +231,9 @@ static int nand_davinci_correct_1bit(struct mtd_info *mtd, u_char *dat, * OOB without recomputing ECC. */ -static void nand_davinci_hwctl_4bit(struct mtd_info *mtd, int mode) +static void nand_davinci_hwctl_4bit(struct nand_chip *chip, int mode) { - struct davinci_nand_info *info = to_davinci_nand(mtd); + struct davinci_nand_info *info = to_davinci_nand(nand_to_mtd(chip)); unsigned long flags; u32 val; diff --git a/drivers/mtd/nand/raw/diskonchip.c b/drivers/mtd/nand/raw/diskonchip.c index 43d1e08133ce..d007f0704654 100644 --- a/drivers/mtd/nand/raw/diskonchip.c +++ b/drivers/mtd/nand/raw/diskonchip.c @@ -797,9 +797,8 @@ static int doc200x_block_bad(struct mtd_info *mtd, loff_t ofs) return 0; } -static void doc200x_enable_hwecc(struct mtd_info *mtd, int mode) +static void doc200x_enable_hwecc(struct nand_chip *this, int mode) { - struct nand_chip *this = mtd_to_nand(mtd); struct doc_priv *doc = nand_get_controller_data(this); void __iomem *docptr = doc->virtadr; @@ -816,9 +815,8 @@ static void doc200x_enable_hwecc(struct mtd_info *mtd, int mode) } } -static void doc2001plus_enable_hwecc(struct mtd_info *mtd, int mode) +static void doc2001plus_enable_hwecc(struct nand_chip *this, int mode) { - struct nand_chip *this = mtd_to_nand(mtd); struct doc_priv *doc = nand_get_controller_data(this); void __iomem *docptr = doc->virtadr; diff --git a/drivers/mtd/nand/raw/fsmc_nand.c b/drivers/mtd/nand/raw/fsmc_nand.c index 25d354e9448e..0291a43d9f6e 100644 --- a/drivers/mtd/nand/raw/fsmc_nand.c +++ b/drivers/mtd/nand/raw/fsmc_nand.c @@ -368,9 +368,9 @@ static int fsmc_setup_data_interface(struct mtd_info *mtd, int csline, /* * fsmc_enable_hwecc - Enables Hardware ECC through FSMC registers */ -static void fsmc_enable_hwecc(struct mtd_info *mtd, int mode) +static void fsmc_enable_hwecc(struct nand_chip *chip, int mode) { - struct fsmc_nand_data *host = mtd_to_fsmc(mtd); + struct fsmc_nand_data *host = mtd_to_fsmc(nand_to_mtd(chip)); writel_relaxed(readl(host->regs_va + FSMC_PC) & ~FSMC_ECCPLEN_256, host->regs_va + FSMC_PC); @@ -740,7 +740,7 @@ static int fsmc_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, for (i = 0, s = 0; s < eccsteps; s++, i += eccbytes, p += eccsize) { nand_read_page_op(chip, page, s * eccsize, NULL, 0); - chip->ecc.hwctl(mtd, NAND_ECC_READ); + chip->ecc.hwctl(chip, NAND_ECC_READ); nand_read_data_op(chip, p, eccsize, false); for (j = 0; j < eccbytes;) { diff --git a/drivers/mtd/nand/raw/jz4740_nand.c b/drivers/mtd/nand/raw/jz4740_nand.c index 27603d78b157..0bf5d7b7f185 100644 --- a/drivers/mtd/nand/raw/jz4740_nand.c +++ b/drivers/mtd/nand/raw/jz4740_nand.c @@ -134,9 +134,9 @@ static int jz_nand_dev_ready(struct mtd_info *mtd) return gpiod_get_value_cansleep(nand->busy_gpio); } -static void jz_nand_hwctl(struct mtd_info *mtd, int mode) +static void jz_nand_hwctl(struct nand_chip *chip, int mode) { - struct jz_nand *nand = mtd_to_jz_nand(mtd); + struct jz_nand *nand = mtd_to_jz_nand(nand_to_mtd(chip)); uint32_t reg; writel(0, nand->base + JZ_REG_NAND_IRQ_STAT); diff --git a/drivers/mtd/nand/raw/jz4780_nand.c b/drivers/mtd/nand/raw/jz4780_nand.c index 7d008aeae165..1604214ee4b8 100644 --- a/drivers/mtd/nand/raw/jz4780_nand.c +++ b/drivers/mtd/nand/raw/jz4780_nand.c @@ -116,9 +116,9 @@ static int jz4780_nand_dev_ready(struct mtd_info *mtd) return !gpiod_get_value_cansleep(nand->busy_gpio); } -static void jz4780_nand_ecc_hwctl(struct mtd_info *mtd, int mode) +static void jz4780_nand_ecc_hwctl(struct nand_chip *chip, int mode) { - struct jz4780_nand_chip *nand = to_jz4780_nand_chip(mtd); + struct jz4780_nand_chip *nand = to_jz4780_nand_chip(nand_to_mtd(chip)); nand->reading = (mode == NAND_ECC_READ); } diff --git a/drivers/mtd/nand/raw/lpc32xx_mlc.c b/drivers/mtd/nand/raw/lpc32xx_mlc.c index d240b8ff40ca..84e421710297 100644 --- a/drivers/mtd/nand/raw/lpc32xx_mlc.c +++ b/drivers/mtd/nand/raw/lpc32xx_mlc.c @@ -576,7 +576,7 @@ static int lpc32xx_write_oob(struct mtd_info *mtd, struct nand_chip *chip, } /* Prepares MLC for transfers with H/W ECC enabled: always enabled anyway */ -static void lpc32xx_ecc_enable(struct mtd_info *mtd, int mode) +static void lpc32xx_ecc_enable(struct nand_chip *chip, int mode) { /* Always enabled! */ } diff --git a/drivers/mtd/nand/raw/lpc32xx_slc.c b/drivers/mtd/nand/raw/lpc32xx_slc.c index 607e4bdfae03..a6c635053bd5 100644 --- a/drivers/mtd/nand/raw/lpc32xx_slc.c +++ b/drivers/mtd/nand/raw/lpc32xx_slc.c @@ -337,7 +337,7 @@ static void lpc32xx_wp_disable(struct lpc32xx_nand_host *host) /* * Prepares SLC for transfers with H/W ECC enabled */ -static void lpc32xx_nand_ecc_enable(struct mtd_info *mtd, int mode) +static void lpc32xx_nand_ecc_enable(struct nand_chip *chip, int mode) { /* Hardware ECC is enabled automatically in hardware as needed */ } diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c index 9d684f1d9e26..fd0563fc4ad2 100644 --- a/drivers/mtd/nand/raw/nand_base.c +++ b/drivers/mtd/nand/raw/nand_base.c @@ -3272,7 +3272,7 @@ static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, return ret; for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { - chip->ecc.hwctl(mtd, NAND_ECC_READ); + chip->ecc.hwctl(chip, NAND_ECC_READ); ret = nand_read_data_op(chip, p, eccsize, false); if (ret) @@ -3358,7 +3358,7 @@ static int nand_read_page_hwecc_oob_first(struct mtd_info *mtd, for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { int stat; - chip->ecc.hwctl(mtd, NAND_ECC_READ); + chip->ecc.hwctl(chip, NAND_ECC_READ); ret = nand_read_data_op(chip, p, eccsize, false); if (ret) @@ -3415,7 +3415,7 @@ static int nand_read_page_syndrome(struct mtd_info *mtd, struct nand_chip *chip, for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { int stat; - chip->ecc.hwctl(mtd, NAND_ECC_READ); + chip->ecc.hwctl(chip, NAND_ECC_READ); ret = nand_read_data_op(chip, p, eccsize, false); if (ret) @@ -3430,7 +3430,7 @@ static int nand_read_page_syndrome(struct mtd_info *mtd, struct nand_chip *chip, oob += chip->ecc.prepad; } - chip->ecc.hwctl(mtd, NAND_ECC_READSYN); + chip->ecc.hwctl(chip, NAND_ECC_READSYN); ret = nand_read_data_op(chip, oob, eccbytes, false); if (ret) @@ -4151,7 +4151,7 @@ static int nand_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, return ret; for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { - chip->ecc.hwctl(mtd, NAND_ECC_WRITE); + chip->ecc.hwctl(chip, NAND_ECC_WRITE); ret = nand_write_data_op(chip, p, eccsize, false); if (ret) @@ -4204,7 +4204,7 @@ static int nand_write_subpage_hwecc(struct mtd_info *mtd, for (step = 0; step < ecc_steps; step++) { /* configure controller for WRITE access */ - chip->ecc.hwctl(mtd, NAND_ECC_WRITE); + chip->ecc.hwctl(chip, NAND_ECC_WRITE); /* write data (untouched subpages already masked by 0xFF) */ ret = nand_write_data_op(chip, buf, ecc_size, false); @@ -4272,7 +4272,7 @@ static int nand_write_page_syndrome(struct mtd_info *mtd, return ret; for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { - chip->ecc.hwctl(mtd, NAND_ECC_WRITE); + chip->ecc.hwctl(chip, NAND_ECC_WRITE); ret = nand_write_data_op(chip, p, eccsize, false); if (ret) diff --git a/drivers/mtd/nand/raw/ndfc.c b/drivers/mtd/nand/raw/ndfc.c index ab24e9ca769b..f9648d87b2e7 100644 --- a/drivers/mtd/nand/raw/ndfc.c +++ b/drivers/mtd/nand/raw/ndfc.c @@ -81,10 +81,9 @@ static int ndfc_ready(struct mtd_info *mtd) return in_be32(ndfc->ndfcbase + NDFC_STAT) & NDFC_STAT_IS_READY; } -static void ndfc_enable_hwecc(struct mtd_info *mtd, int mode) +static void ndfc_enable_hwecc(struct nand_chip *chip, int mode) { uint32_t ccr; - struct nand_chip *chip = mtd_to_nand(mtd); struct ndfc_controller *ndfc = nand_get_controller_data(chip); ccr = in_be32(ndfc->ndfcbase + NDFC_CCR); diff --git a/drivers/mtd/nand/raw/omap2.c b/drivers/mtd/nand/raw/omap2.c index b243f2ab3622..bba403b4e262 100644 --- a/drivers/mtd/nand/raw/omap2.c +++ b/drivers/mtd/nand/raw/omap2.c @@ -935,10 +935,9 @@ static int omap_calculate_ecc(struct mtd_info *mtd, const u_char *dat, * @mtd: MTD device structure * @mode: Read/Write mode */ -static void omap_enable_hwecc(struct mtd_info *mtd, int mode) +static void omap_enable_hwecc(struct nand_chip *chip, int mode) { - struct omap_nand_info *info = mtd_to_omap(mtd); - struct nand_chip *chip = mtd_to_nand(mtd); + struct omap_nand_info *info = mtd_to_omap(nand_to_mtd(chip)); unsigned int dev_width = (chip->options & NAND_BUSWIDTH_16) ? 1 : 0; u32 val; @@ -1030,13 +1029,13 @@ static int omap_dev_ready(struct mtd_info *mtd) * eccsize0 = 0 (no additional protected byte in spare area) * eccsize1 = 32 (skip 32 nibbles = 16 bytes per sector in spare area) */ -static void __maybe_unused omap_enable_hwecc_bch(struct mtd_info *mtd, int mode) +static void __maybe_unused omap_enable_hwecc_bch(struct nand_chip *chip, + int mode) { unsigned int bch_type; unsigned int dev_width, nsectors; - struct omap_nand_info *info = mtd_to_omap(mtd); + struct omap_nand_info *info = mtd_to_omap(nand_to_mtd(chip)); enum omap_ecc ecc_opt = info->ecc_opt; - struct nand_chip *chip = mtd_to_nand(mtd); u32 val, wr_mode; unsigned int ecc_size1, ecc_size0; @@ -1529,7 +1528,7 @@ static int omap_write_page_bch(struct mtd_info *mtd, struct nand_chip *chip, nand_prog_page_begin_op(chip, page, 0, NULL, 0); /* Enable GPMC ecc engine */ - chip->ecc.hwctl(mtd, NAND_ECC_WRITE); + chip->ecc.hwctl(chip, NAND_ECC_WRITE); /* Write data */ chip->write_buf(mtd, buf, mtd->writesize); @@ -1582,7 +1581,7 @@ static int omap_write_subpage_bch(struct mtd_info *mtd, nand_prog_page_begin_op(chip, page, 0, NULL, 0); /* Enable GPMC ECC engine */ - chip->ecc.hwctl(mtd, NAND_ECC_WRITE); + chip->ecc.hwctl(chip, NAND_ECC_WRITE); /* Write data */ chip->write_buf(mtd, buf, mtd->writesize); @@ -1641,7 +1640,7 @@ static int omap_read_page_bch(struct mtd_info *mtd, struct nand_chip *chip, nand_read_page_op(chip, page, 0, NULL, 0); /* Enable GPMC ecc engine */ - chip->ecc.hwctl(mtd, NAND_ECC_READ); + chip->ecc.hwctl(chip, NAND_ECC_READ); /* Read data */ chip->read_buf(mtd, buf, mtd->writesize); diff --git a/drivers/mtd/nand/raw/r852.c b/drivers/mtd/nand/raw/r852.c index bb74a0ac697e..b5e0cc611b14 100644 --- a/drivers/mtd/nand/raw/r852.c +++ b/drivers/mtd/nand/raw/r852.c @@ -401,9 +401,9 @@ static int r852_ready(struct mtd_info *mtd) * Set ECC engine mode */ -static void r852_ecc_hwctl(struct mtd_info *mtd, int mode) +static void r852_ecc_hwctl(struct nand_chip *chip, int mode) { - struct r852_device *dev = r852_get_dev(mtd); + struct r852_device *dev = r852_get_dev(nand_to_mtd(chip)); if (dev->card_unstable) return; diff --git a/drivers/mtd/nand/raw/s3c2410.c b/drivers/mtd/nand/raw/s3c2410.c index cf045813c160..ca2d006cc846 100644 --- a/drivers/mtd/nand/raw/s3c2410.c +++ b/drivers/mtd/nand/raw/s3c2410.c @@ -591,31 +591,34 @@ static int s3c2410_nand_correct_data(struct mtd_info *mtd, u_char *dat, * generator block to ECC the data as it passes through] */ -static void s3c2410_nand_enable_hwecc(struct mtd_info *mtd, int mode) +static void s3c2410_nand_enable_hwecc(struct nand_chip *chip, int mode) { - struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd); + struct s3c2410_nand_info *info; unsigned long ctrl; + info = s3c2410_nand_mtd_toinfo(nand_to_mtd(chip)); ctrl = readl(info->regs + S3C2410_NFCONF); ctrl |= S3C2410_NFCONF_INITECC; writel(ctrl, info->regs + S3C2410_NFCONF); } -static void s3c2412_nand_enable_hwecc(struct mtd_info *mtd, int mode) +static void s3c2412_nand_enable_hwecc(struct nand_chip *chip, int mode) { - struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd); + struct s3c2410_nand_info *info; unsigned long ctrl; + info = s3c2410_nand_mtd_toinfo(nand_to_mtd(chip)); ctrl = readl(info->regs + S3C2440_NFCONT); writel(ctrl | S3C2412_NFCONT_INIT_MAIN_ECC, info->regs + S3C2440_NFCONT); } -static void s3c2440_nand_enable_hwecc(struct mtd_info *mtd, int mode) +static void s3c2440_nand_enable_hwecc(struct nand_chip *chip, int mode) { - struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd); + struct s3c2410_nand_info *info; unsigned long ctrl; + info = s3c2410_nand_mtd_toinfo(nand_to_mtd(chip)); ctrl = readl(info->regs + S3C2440_NFCONT); writel(ctrl | S3C2440_NFCONT_INITECC, info->regs + S3C2440_NFCONT); } diff --git a/drivers/mtd/nand/raw/sharpsl.c b/drivers/mtd/nand/raw/sharpsl.c index c8eb4654bb1c..37fdaad82f37 100644 --- a/drivers/mtd/nand/raw/sharpsl.c +++ b/drivers/mtd/nand/raw/sharpsl.c @@ -85,9 +85,9 @@ static int sharpsl_nand_dev_ready(struct mtd_info *mtd) return !((readb(sharpsl->io + FLASHCTL) & FLRYBY) == 0); } -static void sharpsl_nand_enable_hwecc(struct mtd_info *mtd, int mode) +static void sharpsl_nand_enable_hwecc(struct nand_chip *chip, int mode) { - struct sharpsl_nand *sharpsl = mtd_to_sharpsl(mtd); + struct sharpsl_nand *sharpsl = mtd_to_sharpsl(nand_to_mtd(chip)); writeb(0, sharpsl->io + ECCCLRR); } diff --git a/drivers/mtd/nand/raw/tmio_nand.c b/drivers/mtd/nand/raw/tmio_nand.c index 39594910e6f0..2578216ff5c0 100644 --- a/drivers/mtd/nand/raw/tmio_nand.c +++ b/drivers/mtd/nand/raw/tmio_nand.c @@ -259,9 +259,9 @@ static void tmio_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len) tmio_ioread16_rep(tmio->fcr + FCR_DATA, buf, len >> 1); } -static void tmio_nand_enable_hwecc(struct mtd_info *mtd, int mode) +static void tmio_nand_enable_hwecc(struct nand_chip *chip, int mode) { - struct tmio_nand *tmio = mtd_to_tmio(mtd); + struct tmio_nand *tmio = mtd_to_tmio(nand_to_mtd(chip)); tmio_iowrite8(FCR_MODE_HWECC_RESET, tmio->fcr + FCR_MODE); tmio_ioread8(tmio->fcr + FCR_DATA); /* dummy read */ diff --git a/drivers/mtd/nand/raw/txx9ndfmc.c b/drivers/mtd/nand/raw/txx9ndfmc.c index f722aae2b244..fea5bc684aa1 100644 --- a/drivers/mtd/nand/raw/txx9ndfmc.c +++ b/drivers/mtd/nand/raw/txx9ndfmc.c @@ -211,9 +211,9 @@ static int txx9ndfmc_correct_data(struct mtd_info *mtd, unsigned char *buf, return corrected; } -static void txx9ndfmc_enable_hwecc(struct mtd_info *mtd, int mode) +static void txx9ndfmc_enable_hwecc(struct nand_chip *chip, int mode) { - struct platform_device *dev = mtd_to_platdev(mtd); + struct platform_device *dev = mtd_to_platdev(nand_to_mtd(chip)); u32 mcr = txx9ndfmc_read(dev, TXX9_NDFMCR); mcr &= ~TXX9_NDFMCR_ECC_ALL; diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h index 55014e42912a..029fef900f33 100644 --- a/include/linux/mtd/rawnand.h +++ b/include/linux/mtd/rawnand.h @@ -647,7 +647,7 @@ struct nand_ecc_ctrl { void *priv; u8 *calc_buf; u8 *code_buf; - void (*hwctl)(struct mtd_info *mtd, int mode); + void (*hwctl)(struct nand_chip *chip, int mode); int (*calculate)(struct mtd_info *mtd, const uint8_t *dat, uint8_t *ecc_code); int (*correct)(struct mtd_info *mtd, uint8_t *dat, uint8_t *read_ecc, From af37d2c3a8c7a05cf5b0fe6b61e2a6b9e357928b Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Thu, 6 Sep 2018 14:05:18 +0200 Subject: [PATCH 246/302] mtd: rawnand: Pass a nand_chip object to ecc->calculate() Let's make the raw NAND API consistent by patching all helpers and hooks to take a nand_chip object instead of an mtd_info one. Now is ecc->calculate()'s turn. Signed-off-by: Boris Brezillon Signed-off-by: Miquel Raynal --- drivers/mtd/nand/raw/cs553x_nand.c | 4 ++-- drivers/mtd/nand/raw/davinci_nand.c | 12 ++++++------ drivers/mtd/nand/raw/diskonchip.c | 4 ++-- drivers/mtd/nand/raw/fsmc_nand.c | 10 +++++----- drivers/mtd/nand/raw/jz4740_nand.c | 6 +++--- drivers/mtd/nand/raw/jz4780_nand.c | 4 ++-- drivers/mtd/nand/raw/lpc32xx_slc.c | 2 +- drivers/mtd/nand/raw/nand_base.c | 16 ++++++++-------- drivers/mtd/nand/raw/nand_bch.c | 5 ++--- drivers/mtd/nand/raw/nand_ecc.c | 5 ++--- drivers/mtd/nand/raw/ndfc.c | 3 +-- drivers/mtd/nand/raw/omap2.c | 14 +++++++------- drivers/mtd/nand/raw/r852.c | 6 +++--- drivers/mtd/nand/raw/s3c2410.c | 15 +++++++++------ drivers/mtd/nand/raw/sharpsl.c | 5 +++-- drivers/mtd/nand/raw/tmio_nand.c | 6 +++--- drivers/mtd/nand/raw/txx9ndfmc.c | 5 ++--- include/linux/mtd/nand_bch.h | 5 +++-- include/linux/mtd/nand_ecc.h | 4 +++- include/linux/mtd/rawnand.h | 4 ++-- 20 files changed, 69 insertions(+), 66 deletions(-) diff --git a/drivers/mtd/nand/raw/cs553x_nand.c b/drivers/mtd/nand/raw/cs553x_nand.c index 508bcb3d134f..193c3e8fa118 100644 --- a/drivers/mtd/nand/raw/cs553x_nand.c +++ b/drivers/mtd/nand/raw/cs553x_nand.c @@ -164,10 +164,10 @@ static void cs_enable_hwecc(struct nand_chip *this, int mode) writeb(0x07, mmio_base + MM_NAND_ECC_CTL); } -static int cs_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code) +static int cs_calculate_ecc(struct nand_chip *this, const u_char *dat, + u_char *ecc_code) { uint32_t ecc; - struct nand_chip *this = mtd_to_nand(mtd); void __iomem *mmio_base = this->IO_ADDR_R; ecc = readl(mmio_base + MM_NAND_STS); diff --git a/drivers/mtd/nand/raw/davinci_nand.c b/drivers/mtd/nand/raw/davinci_nand.c index 329de266c953..af221e1c8a87 100644 --- a/drivers/mtd/nand/raw/davinci_nand.c +++ b/drivers/mtd/nand/raw/davinci_nand.c @@ -170,10 +170,10 @@ static void nand_davinci_hwctl_1bit(struct nand_chip *chip, int mode) /* * Read hardware ECC value and pack into three bytes */ -static int nand_davinci_calculate_1bit(struct mtd_info *mtd, - const u_char *dat, u_char *ecc_code) +static int nand_davinci_calculate_1bit(struct nand_chip *chip, + const u_char *dat, u_char *ecc_code) { - unsigned int ecc_val = nand_davinci_readecc_1bit(mtd); + unsigned int ecc_val = nand_davinci_readecc_1bit(nand_to_mtd(chip)); unsigned int ecc24 = (ecc_val & 0x0fff) | ((ecc_val & 0x0fff0000) >> 4); /* invert so that erased block ecc is correct */ @@ -266,10 +266,10 @@ nand_davinci_readecc_4bit(struct davinci_nand_info *info, u32 code[4]) } /* Terminate read ECC; or return ECC (as bytes) of data written to NAND. */ -static int nand_davinci_calculate_4bit(struct mtd_info *mtd, - const u_char *dat, u_char *ecc_code) +static int nand_davinci_calculate_4bit(struct nand_chip *chip, + const u_char *dat, u_char *ecc_code) { - struct davinci_nand_info *info = to_davinci_nand(mtd); + struct davinci_nand_info *info = to_davinci_nand(nand_to_mtd(chip)); u32 raw_ecc[4], *p; unsigned i; diff --git a/drivers/mtd/nand/raw/diskonchip.c b/drivers/mtd/nand/raw/diskonchip.c index d007f0704654..942a5ee83fbd 100644 --- a/drivers/mtd/nand/raw/diskonchip.c +++ b/drivers/mtd/nand/raw/diskonchip.c @@ -834,9 +834,9 @@ static void doc2001plus_enable_hwecc(struct nand_chip *this, int mode) } /* This code is only called on write */ -static int doc200x_calculate_ecc(struct mtd_info *mtd, const u_char *dat, unsigned char *ecc_code) +static int doc200x_calculate_ecc(struct nand_chip *this, const u_char *dat, + unsigned char *ecc_code) { - struct nand_chip *this = mtd_to_nand(mtd); struct doc_priv *doc = nand_get_controller_data(this); void __iomem *docptr = doc->virtadr; int i; diff --git a/drivers/mtd/nand/raw/fsmc_nand.c b/drivers/mtd/nand/raw/fsmc_nand.c index 0291a43d9f6e..d4e91465042c 100644 --- a/drivers/mtd/nand/raw/fsmc_nand.c +++ b/drivers/mtd/nand/raw/fsmc_nand.c @@ -385,10 +385,10 @@ static void fsmc_enable_hwecc(struct nand_chip *chip, int mode) * FSMC. ECC is 13 bytes for 512 bytes of data (supports error correction up to * max of 8-bits) */ -static int fsmc_read_hwecc_ecc4(struct mtd_info *mtd, const uint8_t *data, +static int fsmc_read_hwecc_ecc4(struct nand_chip *chip, const uint8_t *data, uint8_t *ecc) { - struct fsmc_nand_data *host = mtd_to_fsmc(mtd); + struct fsmc_nand_data *host = mtd_to_fsmc(nand_to_mtd(chip)); uint32_t ecc_tmp; unsigned long deadline = jiffies + FSMC_BUSY_WAIT_TIMEOUT; @@ -433,10 +433,10 @@ static int fsmc_read_hwecc_ecc4(struct mtd_info *mtd, const uint8_t *data, * FSMC. ECC is 3 bytes for 512 bytes of data (supports error correction up to * max of 1-bit) */ -static int fsmc_read_hwecc_ecc1(struct mtd_info *mtd, const uint8_t *data, +static int fsmc_read_hwecc_ecc1(struct nand_chip *chip, const uint8_t *data, uint8_t *ecc) { - struct fsmc_nand_data *host = mtd_to_fsmc(mtd); + struct fsmc_nand_data *host = mtd_to_fsmc(nand_to_mtd(chip)); uint32_t ecc_tmp; ecc_tmp = readl_relaxed(host->regs_va + ECC1); @@ -767,7 +767,7 @@ static int fsmc_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, } memcpy(&ecc_code[i], oob, chip->ecc.bytes); - chip->ecc.calculate(mtd, p, &ecc_calc[i]); + chip->ecc.calculate(chip, p, &ecc_calc[i]); stat = chip->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]); if (stat < 0) { diff --git a/drivers/mtd/nand/raw/jz4740_nand.c b/drivers/mtd/nand/raw/jz4740_nand.c index 0bf5d7b7f185..98ea5172ac74 100644 --- a/drivers/mtd/nand/raw/jz4740_nand.c +++ b/drivers/mtd/nand/raw/jz4740_nand.c @@ -162,10 +162,10 @@ static void jz_nand_hwctl(struct nand_chip *chip, int mode) writel(reg, nand->base + JZ_REG_NAND_ECC_CTRL); } -static int jz_nand_calculate_ecc_rs(struct mtd_info *mtd, const uint8_t *dat, - uint8_t *ecc_code) +static int jz_nand_calculate_ecc_rs(struct nand_chip *chip, const uint8_t *dat, + uint8_t *ecc_code) { - struct jz_nand *nand = mtd_to_jz_nand(mtd); + struct jz_nand *nand = mtd_to_jz_nand(nand_to_mtd(chip)); uint32_t reg, status; int i; unsigned int timeout = 1000; diff --git a/drivers/mtd/nand/raw/jz4780_nand.c b/drivers/mtd/nand/raw/jz4780_nand.c index 1604214ee4b8..e53a2bdfc263 100644 --- a/drivers/mtd/nand/raw/jz4780_nand.c +++ b/drivers/mtd/nand/raw/jz4780_nand.c @@ -123,10 +123,10 @@ static void jz4780_nand_ecc_hwctl(struct nand_chip *chip, int mode) nand->reading = (mode == NAND_ECC_READ); } -static int jz4780_nand_ecc_calculate(struct mtd_info *mtd, const u8 *dat, +static int jz4780_nand_ecc_calculate(struct nand_chip *chip, const u8 *dat, u8 *ecc_code) { - struct jz4780_nand_chip *nand = to_jz4780_nand_chip(mtd); + struct jz4780_nand_chip *nand = to_jz4780_nand_chip(nand_to_mtd(chip)); struct jz4780_nand_controller *nfc = to_jz4780_nand_controller(nand->chip.controller); struct jz4780_bch_params params; diff --git a/drivers/mtd/nand/raw/lpc32xx_slc.c b/drivers/mtd/nand/raw/lpc32xx_slc.c index a6c635053bd5..c35a61c453da 100644 --- a/drivers/mtd/nand/raw/lpc32xx_slc.c +++ b/drivers/mtd/nand/raw/lpc32xx_slc.c @@ -345,7 +345,7 @@ static void lpc32xx_nand_ecc_enable(struct nand_chip *chip, int mode) /* * Calculates the ECC for the data */ -static int lpc32xx_nand_ecc_calculate(struct mtd_info *mtd, +static int lpc32xx_nand_ecc_calculate(struct nand_chip *chip, const unsigned char *buf, unsigned char *code) { diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c index fd0563fc4ad2..f147b7948e64 100644 --- a/drivers/mtd/nand/raw/nand_base.c +++ b/drivers/mtd/nand/raw/nand_base.c @@ -3110,7 +3110,7 @@ static int nand_read_page_swecc(struct mtd_info *mtd, struct nand_chip *chip, chip->ecc.read_page_raw(mtd, chip, buf, 1, page); for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) - chip->ecc.calculate(mtd, p, &ecc_calc[i]); + chip->ecc.calculate(chip, p, &ecc_calc[i]); ret = mtd_ooblayout_get_eccbytes(mtd, ecc_code, chip->oob_poi, 0, chip->ecc.total); @@ -3175,7 +3175,7 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, /* Calculate ECC */ for (i = 0; i < eccfrag_len ; i += chip->ecc.bytes, p += chip->ecc.size) - chip->ecc.calculate(mtd, p, &chip->ecc.calc_buf[i]); + chip->ecc.calculate(chip, p, &chip->ecc.calc_buf[i]); /* * The performance is faster if we position offsets according to @@ -3278,7 +3278,7 @@ static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, if (ret) return ret; - chip->ecc.calculate(mtd, p, &ecc_calc[i]); + chip->ecc.calculate(chip, p, &ecc_calc[i]); } ret = nand_read_data_op(chip, chip->oob_poi, mtd->oobsize, false); @@ -3364,7 +3364,7 @@ static int nand_read_page_hwecc_oob_first(struct mtd_info *mtd, if (ret) return ret; - chip->ecc.calculate(mtd, p, &ecc_calc[i]); + chip->ecc.calculate(chip, p, &ecc_calc[i]); stat = chip->ecc.correct(mtd, p, &ecc_code[i], NULL); if (stat == -EBADMSG && @@ -4118,7 +4118,7 @@ static int nand_write_page_swecc(struct mtd_info *mtd, struct nand_chip *chip, /* Software ECC calculation */ for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) - chip->ecc.calculate(mtd, p, &ecc_calc[i]); + chip->ecc.calculate(chip, p, &ecc_calc[i]); ret = mtd_ooblayout_set_eccbytes(mtd, ecc_calc, chip->oob_poi, 0, chip->ecc.total); @@ -4157,7 +4157,7 @@ static int nand_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, if (ret) return ret; - chip->ecc.calculate(mtd, p, &ecc_calc[i]); + chip->ecc.calculate(chip, p, &ecc_calc[i]); } ret = mtd_ooblayout_set_eccbytes(mtd, ecc_calc, chip->oob_poi, 0, @@ -4215,7 +4215,7 @@ static int nand_write_subpage_hwecc(struct mtd_info *mtd, if ((step < start_step) || (step > end_step)) memset(ecc_calc, 0xff, ecc_bytes); else - chip->ecc.calculate(mtd, buf, ecc_calc); + chip->ecc.calculate(chip, buf, ecc_calc); /* mask OOB of un-touched subpages by padding 0xFF */ /* if oob_required, preserve OOB metadata of written subpage */ @@ -4287,7 +4287,7 @@ static int nand_write_page_syndrome(struct mtd_info *mtd, oob += chip->ecc.prepad; } - chip->ecc.calculate(mtd, p, oob); + chip->ecc.calculate(chip, p, oob); ret = nand_write_data_op(chip, oob, eccbytes, false); if (ret) diff --git a/drivers/mtd/nand/raw/nand_bch.c b/drivers/mtd/nand/raw/nand_bch.c index b7387ace567a..9e3c2da0f3b1 100644 --- a/drivers/mtd/nand/raw/nand_bch.c +++ b/drivers/mtd/nand/raw/nand_bch.c @@ -43,14 +43,13 @@ struct nand_bch_control { /** * nand_bch_calculate_ecc - [NAND Interface] Calculate ECC for data block - * @mtd: MTD block structure + * @chip: NAND chip object * @buf: input buffer with raw data * @code: output buffer with ECC */ -int nand_bch_calculate_ecc(struct mtd_info *mtd, const unsigned char *buf, +int nand_bch_calculate_ecc(struct nand_chip *chip, const unsigned char *buf, unsigned char *code) { - const struct nand_chip *chip = mtd_to_nand(mtd); struct nand_bch_control *nbc = chip->ecc.priv; unsigned int i; diff --git a/drivers/mtd/nand/raw/nand_ecc.c b/drivers/mtd/nand/raw/nand_ecc.c index 8e132edbc5ce..1dbfcaecf8c5 100644 --- a/drivers/mtd/nand/raw/nand_ecc.c +++ b/drivers/mtd/nand/raw/nand_ecc.c @@ -398,11 +398,10 @@ EXPORT_SYMBOL(__nand_calculate_ecc); * @buf: input buffer with raw data * @code: output buffer with ECC */ -int nand_calculate_ecc(struct mtd_info *mtd, const unsigned char *buf, +int nand_calculate_ecc(struct nand_chip *chip, const unsigned char *buf, unsigned char *code) { - __nand_calculate_ecc(buf, - mtd_to_nand(mtd)->ecc.size, code); + __nand_calculate_ecc(buf, chip->ecc.size, code); return 0; } diff --git a/drivers/mtd/nand/raw/ndfc.c b/drivers/mtd/nand/raw/ndfc.c index f9648d87b2e7..9241cfaab5ac 100644 --- a/drivers/mtd/nand/raw/ndfc.c +++ b/drivers/mtd/nand/raw/ndfc.c @@ -92,10 +92,9 @@ static void ndfc_enable_hwecc(struct nand_chip *chip, int mode) wmb(); } -static int ndfc_calculate_ecc(struct mtd_info *mtd, +static int ndfc_calculate_ecc(struct nand_chip *chip, const u_char *dat, u_char *ecc_code) { - struct nand_chip *chip = mtd_to_nand(mtd); struct ndfc_controller *ndfc = nand_get_controller_data(chip); uint32_t ecc; uint8_t *p = (uint8_t *)&ecc; diff --git a/drivers/mtd/nand/raw/omap2.c b/drivers/mtd/nand/raw/omap2.c index bba403b4e262..adc300b6d243 100644 --- a/drivers/mtd/nand/raw/omap2.c +++ b/drivers/mtd/nand/raw/omap2.c @@ -900,7 +900,7 @@ static int omap_correct_data(struct mtd_info *mtd, u_char *dat, /** * omap_calcuate_ecc - Generate non-inverted ECC bytes. - * @mtd: MTD device structure + * @chip: NAND chip object * @dat: The pointer to data on which ecc is computed * @ecc_code: The ecc_code buffer * @@ -910,10 +910,10 @@ static int omap_correct_data(struct mtd_info *mtd, u_char *dat, * an erased page will produce an ECC mismatch between generated and read * ECC bytes that has to be dealt with separately. */ -static int omap_calculate_ecc(struct mtd_info *mtd, const u_char *dat, - u_char *ecc_code) +static int omap_calculate_ecc(struct nand_chip *chip, const u_char *dat, + u_char *ecc_code) { - struct omap_nand_info *info = mtd_to_omap(mtd); + struct omap_nand_info *info = mtd_to_omap(nand_to_mtd(chip)); u32 val; val = readl(info->reg.gpmc_ecc_config); @@ -1255,7 +1255,7 @@ static int _omap_calculate_ecc_bch(struct mtd_info *mtd, /** * omap_calculate_ecc_bch_sw - ECC generator for sector for SW based correction - * @mtd: MTD device structure + * @chip: NAND chip object * @dat: The pointer to data on which ecc is computed * @ecc_code: The ecc_code buffer * @@ -1263,10 +1263,10 @@ static int _omap_calculate_ecc_bch(struct mtd_info *mtd, * when SW based correction is required as ECC is required for one sector * at a time. */ -static int omap_calculate_ecc_bch_sw(struct mtd_info *mtd, +static int omap_calculate_ecc_bch_sw(struct nand_chip *chip, const u_char *dat, u_char *ecc_calc) { - return _omap_calculate_ecc_bch(mtd, dat, ecc_calc, 0); + return _omap_calculate_ecc_bch(nand_to_mtd(chip), dat, ecc_calc, 0); } /** diff --git a/drivers/mtd/nand/raw/r852.c b/drivers/mtd/nand/raw/r852.c index b5e0cc611b14..f58d633ec062 100644 --- a/drivers/mtd/nand/raw/r852.c +++ b/drivers/mtd/nand/raw/r852.c @@ -433,10 +433,10 @@ static void r852_ecc_hwctl(struct nand_chip *chip, int mode) * Calculate ECC, only used for writes */ -static int r852_ecc_calculate(struct mtd_info *mtd, const uint8_t *dat, - uint8_t *ecc_code) +static int r852_ecc_calculate(struct nand_chip *chip, const uint8_t *dat, + uint8_t *ecc_code) { - struct r852_device *dev = r852_get_dev(mtd); + struct r852_device *dev = r852_get_dev(nand_to_mtd(chip)); struct sm_oob *oob = (struct sm_oob *)ecc_code; uint32_t ecc1, ecc2; diff --git a/drivers/mtd/nand/raw/s3c2410.c b/drivers/mtd/nand/raw/s3c2410.c index ca2d006cc846..c94e1f62362f 100644 --- a/drivers/mtd/nand/raw/s3c2410.c +++ b/drivers/mtd/nand/raw/s3c2410.c @@ -623,9 +623,10 @@ static void s3c2440_nand_enable_hwecc(struct nand_chip *chip, int mode) writel(ctrl | S3C2440_NFCONT_INITECC, info->regs + S3C2440_NFCONT); } -static int s3c2410_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, - u_char *ecc_code) +static int s3c2410_nand_calculate_ecc(struct nand_chip *chip, + const u_char *dat, u_char *ecc_code) { + struct mtd_info *mtd = nand_to_mtd(chip); struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd); ecc_code[0] = readb(info->regs + S3C2410_NFECC + 0); @@ -637,9 +638,10 @@ static int s3c2410_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, return 0; } -static int s3c2412_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, - u_char *ecc_code) +static int s3c2412_nand_calculate_ecc(struct nand_chip *chip, + const u_char *dat, u_char *ecc_code) { + struct mtd_info *mtd = nand_to_mtd(chip); struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd); unsigned long ecc = readl(info->regs + S3C2412_NFMECC0); @@ -652,9 +654,10 @@ static int s3c2412_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, return 0; } -static int s3c2440_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, - u_char *ecc_code) +static int s3c2440_nand_calculate_ecc(struct nand_chip *chip, + const u_char *dat, u_char *ecc_code) { + struct mtd_info *mtd = nand_to_mtd(chip); struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd); unsigned long ecc = readl(info->regs + S3C2440_NFMECC0); diff --git a/drivers/mtd/nand/raw/sharpsl.c b/drivers/mtd/nand/raw/sharpsl.c index 37fdaad82f37..4d931ce71af5 100644 --- a/drivers/mtd/nand/raw/sharpsl.c +++ b/drivers/mtd/nand/raw/sharpsl.c @@ -91,9 +91,10 @@ static void sharpsl_nand_enable_hwecc(struct nand_chip *chip, int mode) writeb(0, sharpsl->io + ECCCLRR); } -static int sharpsl_nand_calculate_ecc(struct mtd_info *mtd, const u_char * dat, u_char * ecc_code) +static int sharpsl_nand_calculate_ecc(struct nand_chip *chip, + const u_char * dat, u_char * ecc_code) { - struct sharpsl_nand *sharpsl = mtd_to_sharpsl(mtd); + struct sharpsl_nand *sharpsl = mtd_to_sharpsl(nand_to_mtd(chip)); ecc_code[0] = ~readb(sharpsl->io + ECCLPUB); ecc_code[1] = ~readb(sharpsl->io + ECCLPLB); ecc_code[2] = (~readb(sharpsl->io + ECCCP) << 2) | 0x03; diff --git a/drivers/mtd/nand/raw/tmio_nand.c b/drivers/mtd/nand/raw/tmio_nand.c index 2578216ff5c0..03d6428589c8 100644 --- a/drivers/mtd/nand/raw/tmio_nand.c +++ b/drivers/mtd/nand/raw/tmio_nand.c @@ -268,10 +268,10 @@ static void tmio_nand_enable_hwecc(struct nand_chip *chip, int mode) tmio_iowrite8(FCR_MODE_HWECC_CALC, tmio->fcr + FCR_MODE); } -static int tmio_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, - u_char *ecc_code) +static int tmio_nand_calculate_ecc(struct nand_chip *chip, const u_char *dat, + u_char *ecc_code) { - struct tmio_nand *tmio = mtd_to_tmio(mtd); + struct tmio_nand *tmio = mtd_to_tmio(nand_to_mtd(chip)); unsigned int ecc; tmio_iowrite8(FCR_MODE_HWECC_RESULT, tmio->fcr + FCR_MODE); diff --git a/drivers/mtd/nand/raw/txx9ndfmc.c b/drivers/mtd/nand/raw/txx9ndfmc.c index fea5bc684aa1..55a5c4d42a81 100644 --- a/drivers/mtd/nand/raw/txx9ndfmc.c +++ b/drivers/mtd/nand/raw/txx9ndfmc.c @@ -170,11 +170,10 @@ static int txx9ndfmc_dev_ready(struct mtd_info *mtd) return !(txx9ndfmc_read(dev, TXX9_NDFSR) & TXX9_NDFSR_BUSY); } -static int txx9ndfmc_calculate_ecc(struct mtd_info *mtd, const uint8_t *dat, +static int txx9ndfmc_calculate_ecc(struct nand_chip *chip, const uint8_t *dat, uint8_t *ecc_code) { - struct platform_device *dev = mtd_to_platdev(mtd); - struct nand_chip *chip = mtd_to_nand(mtd); + struct platform_device *dev = mtd_to_platdev(nand_to_mtd(chip)); int eccbytes; u32 mcr = txx9ndfmc_read(dev, TXX9_NDFMCR); diff --git a/include/linux/mtd/nand_bch.h b/include/linux/mtd/nand_bch.h index 98f20ef05d60..6db133508960 100644 --- a/include/linux/mtd/nand_bch.h +++ b/include/linux/mtd/nand_bch.h @@ -12,6 +12,7 @@ #define __MTD_NAND_BCH_H__ struct mtd_info; +struct nand_chip; struct nand_bch_control; #if defined(CONFIG_MTD_NAND_ECC_BCH) @@ -21,7 +22,7 @@ static inline int mtd_nand_has_bch(void) { return 1; } /* * Calculate BCH ecc code */ -int nand_bch_calculate_ecc(struct mtd_info *mtd, const u_char *dat, +int nand_bch_calculate_ecc(struct nand_chip *chip, const u_char *dat, u_char *ecc_code); /* @@ -43,7 +44,7 @@ void nand_bch_free(struct nand_bch_control *nbc); static inline int mtd_nand_has_bch(void) { return 0; } static inline int -nand_bch_calculate_ecc(struct mtd_info *mtd, const u_char *dat, +nand_bch_calculate_ecc(struct nand_chip *chip, const u_char *dat, u_char *ecc_code) { return -1; diff --git a/include/linux/mtd/nand_ecc.h b/include/linux/mtd/nand_ecc.h index 8a2decf7462c..a514e62ff54f 100644 --- a/include/linux/mtd/nand_ecc.h +++ b/include/linux/mtd/nand_ecc.h @@ -14,6 +14,7 @@ #define __MTD_NAND_ECC_H__ struct mtd_info; +struct nand_chip; /* * Calculate 3 byte ECC code for eccsize byte block @@ -24,7 +25,8 @@ void __nand_calculate_ecc(const u_char *dat, unsigned int eccsize, /* * Calculate 3 byte ECC code for 256/512 byte block */ -int nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code); +int nand_calculate_ecc(struct nand_chip *chip, const u_char *dat, + u_char *ecc_code); /* * Detect and correct a 1 bit error for eccsize byte block diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h index 029fef900f33..b2f51b2fb110 100644 --- a/include/linux/mtd/rawnand.h +++ b/include/linux/mtd/rawnand.h @@ -648,8 +648,8 @@ struct nand_ecc_ctrl { u8 *calc_buf; u8 *code_buf; void (*hwctl)(struct nand_chip *chip, int mode); - int (*calculate)(struct mtd_info *mtd, const uint8_t *dat, - uint8_t *ecc_code); + int (*calculate)(struct nand_chip *chip, const uint8_t *dat, + uint8_t *ecc_code); int (*correct)(struct mtd_info *mtd, uint8_t *dat, uint8_t *read_ecc, uint8_t *calc_ecc); int (*read_page_raw)(struct mtd_info *mtd, struct nand_chip *chip, From 00da2ea97229946450c8145d680db480b5da1f94 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Thu, 6 Sep 2018 14:05:19 +0200 Subject: [PATCH 247/302] mtd: rawnand: Pass a nand_chip object to ecc->correct() Let's make the raw NAND API consistent by patching all helpers and hooks to take a nand_chip object instead of an mtd_info one. Now is ecc->correct()'s turn. Signed-off-by: Boris Brezillon Signed-off-by: Miquel Raynal --- drivers/mtd/nand/raw/davinci_nand.c | 9 ++++----- drivers/mtd/nand/raw/diskonchip.c | 3 +-- drivers/mtd/nand/raw/fsmc_nand.c | 9 ++++----- drivers/mtd/nand/raw/jz4740_nand.c | 6 +++--- drivers/mtd/nand/raw/jz4780_nand.c | 4 ++-- drivers/mtd/nand/raw/lpc32xx_slc.c | 2 +- drivers/mtd/nand/raw/nand_base.c | 10 +++++----- drivers/mtd/nand/raw/nand_bch.c | 5 ++--- drivers/mtd/nand/raw/nand_ecc.c | 7 +++---- drivers/mtd/nand/raw/omap2.c | 18 +++++++++--------- drivers/mtd/nand/raw/r852.c | 6 +++--- drivers/mtd/nand/raw/s3c2410.c | 3 ++- drivers/mtd/nand/raw/tmio_nand.c | 5 +++-- drivers/mtd/nand/raw/txx9ndfmc.c | 6 +++--- include/linux/mtd/nand_bch.h | 6 +++--- include/linux/mtd/nand_ecc.h | 4 ++-- include/linux/mtd/rawnand.h | 4 ++-- 17 files changed, 52 insertions(+), 55 deletions(-) diff --git a/drivers/mtd/nand/raw/davinci_nand.c b/drivers/mtd/nand/raw/davinci_nand.c index af221e1c8a87..c80b6c6da4aa 100644 --- a/drivers/mtd/nand/raw/davinci_nand.c +++ b/drivers/mtd/nand/raw/davinci_nand.c @@ -185,10 +185,9 @@ static int nand_davinci_calculate_1bit(struct nand_chip *chip, return 0; } -static int nand_davinci_correct_1bit(struct mtd_info *mtd, u_char *dat, +static int nand_davinci_correct_1bit(struct nand_chip *chip, u_char *dat, u_char *read_ecc, u_char *calc_ecc) { - struct nand_chip *chip = mtd_to_nand(mtd); uint32_t eccNand = read_ecc[0] | (read_ecc[1] << 8) | (read_ecc[2] << 16); uint32_t eccCalc = calc_ecc[0] | (calc_ecc[1] << 8) | @@ -303,11 +302,11 @@ static int nand_davinci_calculate_4bit(struct nand_chip *chip, /* Correct up to 4 bits in data we just read, using state left in the * hardware plus the ecc_code computed when it was first written. */ -static int nand_davinci_correct_4bit(struct mtd_info *mtd, - u_char *data, u_char *ecc_code, u_char *null) +static int nand_davinci_correct_4bit(struct nand_chip *chip, u_char *data, + u_char *ecc_code, u_char *null) { int i; - struct davinci_nand_info *info = to_davinci_nand(mtd); + struct davinci_nand_info *info = to_davinci_nand(nand_to_mtd(chip)); unsigned short ecc10[8]; unsigned short *ecc16; u32 syndrome[4]; diff --git a/drivers/mtd/nand/raw/diskonchip.c b/drivers/mtd/nand/raw/diskonchip.c index 942a5ee83fbd..142d21be874e 100644 --- a/drivers/mtd/nand/raw/diskonchip.c +++ b/drivers/mtd/nand/raw/diskonchip.c @@ -893,11 +893,10 @@ static int doc200x_calculate_ecc(struct nand_chip *this, const u_char *dat, return 0; } -static int doc200x_correct_data(struct mtd_info *mtd, u_char *dat, +static int doc200x_correct_data(struct nand_chip *this, u_char *dat, u_char *read_ecc, u_char *isnull) { int i, ret = 0; - struct nand_chip *this = mtd_to_nand(mtd); struct doc_priv *doc = nand_get_controller_data(this); void __iomem *docptr = doc->virtadr; uint8_t calc_ecc[6]; diff --git a/drivers/mtd/nand/raw/fsmc_nand.c b/drivers/mtd/nand/raw/fsmc_nand.c index d4e91465042c..b41fd09fa389 100644 --- a/drivers/mtd/nand/raw/fsmc_nand.c +++ b/drivers/mtd/nand/raw/fsmc_nand.c @@ -769,7 +769,7 @@ static int fsmc_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, memcpy(&ecc_code[i], oob, chip->ecc.bytes); chip->ecc.calculate(chip, p, &ecc_calc[i]); - stat = chip->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]); + stat = chip->ecc.correct(chip, p, &ecc_code[i], &ecc_calc[i]); if (stat < 0) { mtd->ecc_stats.failed++; } else { @@ -791,11 +791,10 @@ static int fsmc_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, * calc_ecc is a 104 bit information containing maximum of 8 error * offset informations of 13 bits each in 512 bytes of read data. */ -static int fsmc_bch8_correct_data(struct mtd_info *mtd, uint8_t *dat, - uint8_t *read_ecc, uint8_t *calc_ecc) +static int fsmc_bch8_correct_data(struct nand_chip *chip, uint8_t *dat, + uint8_t *read_ecc, uint8_t *calc_ecc) { - struct nand_chip *chip = mtd_to_nand(mtd); - struct fsmc_nand_data *host = mtd_to_fsmc(mtd); + struct fsmc_nand_data *host = mtd_to_fsmc(nand_to_mtd(chip)); uint32_t err_idx[8]; uint32_t num_err, i; uint32_t ecc1, ecc2, ecc3, ecc4; diff --git a/drivers/mtd/nand/raw/jz4740_nand.c b/drivers/mtd/nand/raw/jz4740_nand.c index 98ea5172ac74..e926ed6ed296 100644 --- a/drivers/mtd/nand/raw/jz4740_nand.c +++ b/drivers/mtd/nand/raw/jz4740_nand.c @@ -215,10 +215,10 @@ static void jz_nand_correct_data(uint8_t *dat, int index, int mask) dat[index+1] = (data >> 8) & 0xff; } -static int jz_nand_correct_ecc_rs(struct mtd_info *mtd, uint8_t *dat, - uint8_t *read_ecc, uint8_t *calc_ecc) +static int jz_nand_correct_ecc_rs(struct nand_chip *chip, uint8_t *dat, + uint8_t *read_ecc, uint8_t *calc_ecc) { - struct jz_nand *nand = mtd_to_jz_nand(mtd); + struct jz_nand *nand = mtd_to_jz_nand(nand_to_mtd(chip)); int i, error_count, index; uint32_t reg, status, error; unsigned int timeout = 1000; diff --git a/drivers/mtd/nand/raw/jz4780_nand.c b/drivers/mtd/nand/raw/jz4780_nand.c index e53a2bdfc263..42c5dcdea4a9 100644 --- a/drivers/mtd/nand/raw/jz4780_nand.c +++ b/drivers/mtd/nand/raw/jz4780_nand.c @@ -144,10 +144,10 @@ static int jz4780_nand_ecc_calculate(struct nand_chip *chip, const u8 *dat, return jz4780_bch_calculate(nfc->bch, ¶ms, dat, ecc_code); } -static int jz4780_nand_ecc_correct(struct mtd_info *mtd, u8 *dat, +static int jz4780_nand_ecc_correct(struct nand_chip *chip, u8 *dat, u8 *read_ecc, u8 *calc_ecc) { - struct jz4780_nand_chip *nand = to_jz4780_nand_chip(mtd); + struct jz4780_nand_chip *nand = to_jz4780_nand_chip(nand_to_mtd(chip)); struct jz4780_nand_controller *nfc = to_jz4780_nand_controller(nand->chip.controller); struct jz4780_bch_params params; diff --git a/drivers/mtd/nand/raw/lpc32xx_slc.c b/drivers/mtd/nand/raw/lpc32xx_slc.c index c35a61c453da..d5cb1b40a235 100644 --- a/drivers/mtd/nand/raw/lpc32xx_slc.c +++ b/drivers/mtd/nand/raw/lpc32xx_slc.c @@ -639,7 +639,7 @@ static int lpc32xx_nand_read_page_syndrome(struct mtd_info *mtd, oobecc = chip->oob_poi + oobregion.offset; for (i = 0; i < chip->ecc.steps; i++) { - stat = chip->ecc.correct(mtd, buf, oobecc, + stat = chip->ecc.correct(chip, buf, oobecc, &tmpecc[i * chip->ecc.bytes]); if (stat < 0) mtd->ecc_stats.failed++; diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c index f147b7948e64..0444bd23c84b 100644 --- a/drivers/mtd/nand/raw/nand_base.c +++ b/drivers/mtd/nand/raw/nand_base.c @@ -3123,7 +3123,7 @@ static int nand_read_page_swecc(struct mtd_info *mtd, struct nand_chip *chip, for (i = 0 ; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { int stat; - stat = chip->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]); + stat = chip->ecc.correct(chip, p, &ecc_code[i], &ecc_calc[i]); if (stat < 0) { mtd->ecc_stats.failed++; } else { @@ -3224,7 +3224,7 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, for (i = 0; i < eccfrag_len ; i += chip->ecc.bytes, p += chip->ecc.size) { int stat; - stat = chip->ecc.correct(mtd, p, &chip->ecc.code_buf[i], + stat = chip->ecc.correct(chip, p, &chip->ecc.code_buf[i], &chip->ecc.calc_buf[i]); if (stat == -EBADMSG && (chip->ecc.options & NAND_ECC_GENERIC_ERASED_CHECK)) { @@ -3296,7 +3296,7 @@ static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, for (i = 0 ; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { int stat; - stat = chip->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]); + stat = chip->ecc.correct(chip, p, &ecc_code[i], &ecc_calc[i]); if (stat == -EBADMSG && (chip->ecc.options & NAND_ECC_GENERIC_ERASED_CHECK)) { /* check for empty pages with bitflips */ @@ -3366,7 +3366,7 @@ static int nand_read_page_hwecc_oob_first(struct mtd_info *mtd, chip->ecc.calculate(chip, p, &ecc_calc[i]); - stat = chip->ecc.correct(mtd, p, &ecc_code[i], NULL); + stat = chip->ecc.correct(chip, p, &ecc_code[i], NULL); if (stat == -EBADMSG && (chip->ecc.options & NAND_ECC_GENERIC_ERASED_CHECK)) { /* check for empty pages with bitflips */ @@ -3436,7 +3436,7 @@ static int nand_read_page_syndrome(struct mtd_info *mtd, struct nand_chip *chip, if (ret) return ret; - stat = chip->ecc.correct(mtd, p, oob, NULL); + stat = chip->ecc.correct(chip, p, oob, NULL); oob += eccbytes; diff --git a/drivers/mtd/nand/raw/nand_bch.c b/drivers/mtd/nand/raw/nand_bch.c index 9e3c2da0f3b1..574c0ca16160 100644 --- a/drivers/mtd/nand/raw/nand_bch.c +++ b/drivers/mtd/nand/raw/nand_bch.c @@ -66,17 +66,16 @@ EXPORT_SYMBOL(nand_bch_calculate_ecc); /** * nand_bch_correct_data - [NAND Interface] Detect and correct bit error(s) - * @mtd: MTD block structure + * @chip: NAND chip object * @buf: raw data read from the chip * @read_ecc: ECC from the chip * @calc_ecc: the ECC calculated from raw data * * Detect and correct bit errors for a data byte block */ -int nand_bch_correct_data(struct mtd_info *mtd, unsigned char *buf, +int nand_bch_correct_data(struct nand_chip *chip, unsigned char *buf, unsigned char *read_ecc, unsigned char *calc_ecc) { - const struct nand_chip *chip = mtd_to_nand(mtd); struct nand_bch_control *nbc = chip->ecc.priv; unsigned int *errloc = nbc->errloc; int i, count; diff --git a/drivers/mtd/nand/raw/nand_ecc.c b/drivers/mtd/nand/raw/nand_ecc.c index 1dbfcaecf8c5..8f86eed40b70 100644 --- a/drivers/mtd/nand/raw/nand_ecc.c +++ b/drivers/mtd/nand/raw/nand_ecc.c @@ -490,18 +490,17 @@ EXPORT_SYMBOL(__nand_correct_data); /** * nand_correct_data - [NAND Interface] Detect and correct bit error(s) - * @mtd: MTD block structure + * @chip: NAND chip object * @buf: raw data read from the chip * @read_ecc: ECC from the chip * @calc_ecc: the ECC calculated from raw data * * Detect and correct a 1 bit error for 256/512 byte block */ -int nand_correct_data(struct mtd_info *mtd, unsigned char *buf, +int nand_correct_data(struct nand_chip *chip, unsigned char *buf, unsigned char *read_ecc, unsigned char *calc_ecc) { - return __nand_correct_data(buf, read_ecc, calc_ecc, - mtd_to_nand(mtd)->ecc.size); + return __nand_correct_data(buf, read_ecc, calc_ecc, chip->ecc.size); } EXPORT_SYMBOL(nand_correct_data); diff --git a/drivers/mtd/nand/raw/omap2.c b/drivers/mtd/nand/raw/omap2.c index adc300b6d243..4e0bc2da63fd 100644 --- a/drivers/mtd/nand/raw/omap2.c +++ b/drivers/mtd/nand/raw/omap2.c @@ -857,7 +857,7 @@ static int omap_compare_ecc(u8 *ecc_data1, /* read from NAND memory */ /** * omap_correct_data - Compares the ECC read with HW generated ECC - * @mtd: MTD device structure + * @chip: NAND chip object * @dat: page data * @read_ecc: ecc read from nand flash * @calc_ecc: ecc read from HW ECC registers @@ -869,10 +869,10 @@ static int omap_compare_ecc(u8 *ecc_data1, /* read from NAND memory */ * corrected errors is returned. If uncorrectable errors exist, %-1 is * returned. */ -static int omap_correct_data(struct mtd_info *mtd, u_char *dat, - u_char *read_ecc, u_char *calc_ecc) +static int omap_correct_data(struct nand_chip *chip, u_char *dat, + u_char *read_ecc, u_char *calc_ecc) { - struct omap_nand_info *info = mtd_to_omap(mtd); + struct omap_nand_info *info = mtd_to_omap(nand_to_mtd(chip)); int blockCnt = 0, i = 0, ret = 0; int stat = 0; @@ -1338,7 +1338,7 @@ static int erased_sector_bitflips(u_char *data, u_char *oob, /** * omap_elm_correct_data - corrects page data area in case error reported - * @mtd: MTD device structure + * @chip: NAND chip object * @data: page data * @read_ecc: ecc read from nand flash * @calc_ecc: ecc read from HW ECC registers @@ -1347,10 +1347,10 @@ static int erased_sector_bitflips(u_char *data, u_char *oob, * In case of non-zero ecc vector, first filter out erased-pages, and * then process data via ELM to detect bit-flips. */ -static int omap_elm_correct_data(struct mtd_info *mtd, u_char *data, - u_char *read_ecc, u_char *calc_ecc) +static int omap_elm_correct_data(struct nand_chip *chip, u_char *data, + u_char *read_ecc, u_char *calc_ecc) { - struct omap_nand_info *info = mtd_to_omap(mtd); + struct omap_nand_info *info = mtd_to_omap(nand_to_mtd(chip)); struct nand_ecc_ctrl *ecc = &info->nand.ecc; int eccsteps = info->nand.ecc.steps; int i , j, stat = 0; @@ -1659,7 +1659,7 @@ static int omap_read_page_bch(struct mtd_info *mtd, struct nand_chip *chip, if (ret) return ret; - stat = chip->ecc.correct(mtd, buf, ecc_code, ecc_calc); + stat = chip->ecc.correct(chip, buf, ecc_code, ecc_calc); if (stat < 0) { mtd->ecc_stats.failed++; diff --git a/drivers/mtd/nand/raw/r852.c b/drivers/mtd/nand/raw/r852.c index f58d633ec062..7673aa140009 100644 --- a/drivers/mtd/nand/raw/r852.c +++ b/drivers/mtd/nand/raw/r852.c @@ -465,14 +465,14 @@ static int r852_ecc_calculate(struct nand_chip *chip, const uint8_t *dat, * Correct the data using ECC, hw did almost everything for us */ -static int r852_ecc_correct(struct mtd_info *mtd, uint8_t *dat, - uint8_t *read_ecc, uint8_t *calc_ecc) +static int r852_ecc_correct(struct nand_chip *chip, uint8_t *dat, + uint8_t *read_ecc, uint8_t *calc_ecc) { uint32_t ecc_reg; uint8_t ecc_status, err_byte; int i, error = 0; - struct r852_device *dev = r852_get_dev(mtd); + struct r852_device *dev = r852_get_dev(nand_to_mtd(chip)); if (dev->card_unstable) return 0; diff --git a/drivers/mtd/nand/raw/s3c2410.c b/drivers/mtd/nand/raw/s3c2410.c index c94e1f62362f..d57201d118d8 100644 --- a/drivers/mtd/nand/raw/s3c2410.c +++ b/drivers/mtd/nand/raw/s3c2410.c @@ -512,9 +512,10 @@ static int s3c2412_nand_devready(struct mtd_info *mtd) /* ECC handling functions */ -static int s3c2410_nand_correct_data(struct mtd_info *mtd, u_char *dat, +static int s3c2410_nand_correct_data(struct nand_chip *chip, u_char *dat, u_char *read_ecc, u_char *calc_ecc) { + struct mtd_info *mtd = nand_to_mtd(chip); struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd); unsigned int diff0, diff1, diff2; unsigned int bit, byte; diff --git a/drivers/mtd/nand/raw/tmio_nand.c b/drivers/mtd/nand/raw/tmio_nand.c index 03d6428589c8..734ff29705ce 100644 --- a/drivers/mtd/nand/raw/tmio_nand.c +++ b/drivers/mtd/nand/raw/tmio_nand.c @@ -290,8 +290,9 @@ static int tmio_nand_calculate_ecc(struct nand_chip *chip, const u_char *dat, return 0; } -static int tmio_nand_correct_data(struct mtd_info *mtd, unsigned char *buf, - unsigned char *read_ecc, unsigned char *calc_ecc) +static int tmio_nand_correct_data(struct nand_chip *chip, unsigned char *buf, + unsigned char *read_ecc, + unsigned char *calc_ecc) { int r0, r1; diff --git a/drivers/mtd/nand/raw/txx9ndfmc.c b/drivers/mtd/nand/raw/txx9ndfmc.c index 55a5c4d42a81..3c69d834de62 100644 --- a/drivers/mtd/nand/raw/txx9ndfmc.c +++ b/drivers/mtd/nand/raw/txx9ndfmc.c @@ -190,10 +190,10 @@ static int txx9ndfmc_calculate_ecc(struct nand_chip *chip, const uint8_t *dat, return 0; } -static int txx9ndfmc_correct_data(struct mtd_info *mtd, unsigned char *buf, - unsigned char *read_ecc, unsigned char *calc_ecc) +static int txx9ndfmc_correct_data(struct nand_chip *chip, unsigned char *buf, + unsigned char *read_ecc, + unsigned char *calc_ecc) { - struct nand_chip *chip = mtd_to_nand(mtd); int eccsize; int corrected = 0; int stat; diff --git a/include/linux/mtd/nand_bch.h b/include/linux/mtd/nand_bch.h index 6db133508960..b8106651f807 100644 --- a/include/linux/mtd/nand_bch.h +++ b/include/linux/mtd/nand_bch.h @@ -28,8 +28,8 @@ int nand_bch_calculate_ecc(struct nand_chip *chip, const u_char *dat, /* * Detect and correct bit errors */ -int nand_bch_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, - u_char *calc_ecc); +int nand_bch_correct_data(struct nand_chip *chip, u_char *dat, + u_char *read_ecc, u_char *calc_ecc); /* * Initialize BCH encoder/decoder */ @@ -51,7 +51,7 @@ nand_bch_calculate_ecc(struct nand_chip *chip, const u_char *dat, } static inline int -nand_bch_correct_data(struct mtd_info *mtd, unsigned char *buf, +nand_bch_correct_data(struct nand_chip *chip, unsigned char *buf, unsigned char *read_ecc, unsigned char *calc_ecc) { return -ENOTSUPP; diff --git a/include/linux/mtd/nand_ecc.h b/include/linux/mtd/nand_ecc.h index a514e62ff54f..b81fecd5e719 100644 --- a/include/linux/mtd/nand_ecc.h +++ b/include/linux/mtd/nand_ecc.h @@ -13,7 +13,6 @@ #ifndef __MTD_NAND_ECC_H__ #define __MTD_NAND_ECC_H__ -struct mtd_info; struct nand_chip; /* @@ -37,6 +36,7 @@ int __nand_correct_data(u_char *dat, u_char *read_ecc, u_char *calc_ecc, /* * Detect and correct a 1 bit error for 256/512 byte block */ -int nand_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc); +int nand_correct_data(struct nand_chip *chip, u_char *dat, u_char *read_ecc, + u_char *calc_ecc); #endif /* __MTD_NAND_ECC_H__ */ diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h index b2f51b2fb110..24434310d126 100644 --- a/include/linux/mtd/rawnand.h +++ b/include/linux/mtd/rawnand.h @@ -650,8 +650,8 @@ struct nand_ecc_ctrl { void (*hwctl)(struct nand_chip *chip, int mode); int (*calculate)(struct nand_chip *chip, const uint8_t *dat, uint8_t *ecc_code); - int (*correct)(struct mtd_info *mtd, uint8_t *dat, uint8_t *read_ecc, - uint8_t *calc_ecc); + int (*correct)(struct nand_chip *chip, uint8_t *dat, uint8_t *read_ecc, + uint8_t *calc_ecc); int (*read_page_raw)(struct mtd_info *mtd, struct nand_chip *chip, uint8_t *buf, int oob_required, int page); int (*write_page_raw)(struct mtd_info *mtd, struct nand_chip *chip, From b976168757f7f4adf05215884e8557aaa9f6792c Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Thu, 6 Sep 2018 14:05:20 +0200 Subject: [PATCH 248/302] mtd: rawnand: Pass a nand_chip object to ecc->read_xxx() hooks Let's make the raw NAND API consistent by patching all helpers and hooks to take a nand_chip object instead of an mtd_info one or remove the mtd_info object when both are passed. Let's tackle all ecc->read_xxx() hooks at once. Signed-off-by: Boris Brezillon Acked-by: Stefan Agner Signed-off-by: Miquel Raynal --- drivers/mtd/nand/raw/atmel/nand-controller.c | 12 +-- drivers/mtd/nand/raw/brcmnand/brcmnand.c | 21 +++--- drivers/mtd/nand/raw/cafe_nand.c | 10 ++- drivers/mtd/nand/raw/denali.c | 17 +++-- drivers/mtd/nand/raw/docg4.c | 20 ++--- drivers/mtd/nand/raw/fsl_elbc_nand.c | 5 +- drivers/mtd/nand/raw/fsl_ifc_nand.c | 5 +- drivers/mtd/nand/raw/fsmc_nand.c | 6 +- drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c | 23 +++--- drivers/mtd/nand/raw/hisi504_nand.c | 9 ++- drivers/mtd/nand/raw/lpc32xx_mlc.c | 10 +-- drivers/mtd/nand/raw/lpc32xx_slc.c | 14 ++-- drivers/mtd/nand/raw/marvell_nand.c | 30 +++----- drivers/mtd/nand/raw/mtk_nand.c | 23 +++--- drivers/mtd/nand/raw/mxc_nand.c | 11 ++- drivers/mtd/nand/raw/nand_base.c | 74 +++++++++---------- drivers/mtd/nand/raw/nand_micron.c | 6 +- drivers/mtd/nand/raw/nand_toshiba.c | 10 +-- drivers/mtd/nand/raw/omap2.c | 6 +- drivers/mtd/nand/raw/qcom_nandc.c | 11 ++- drivers/mtd/nand/raw/r852.c | 5 +- drivers/mtd/nand/raw/sh_flctl.c | 6 +- drivers/mtd/nand/raw/sunxi_nand.c | 26 +++---- drivers/mtd/nand/raw/tango_nand.c | 16 ++-- drivers/mtd/nand/raw/tegra_nand.c | 15 ++-- drivers/mtd/nand/raw/vf610_nfc.c | 18 ++--- drivers/staging/mt29f_spinand/mt29f_spinand.c | 5 +- include/linux/mtd/rawnand.h | 30 ++++---- 28 files changed, 221 insertions(+), 223 deletions(-) diff --git a/drivers/mtd/nand/raw/atmel/nand-controller.c b/drivers/mtd/nand/raw/atmel/nand-controller.c index cef22a79f3a6..45061b591346 100644 --- a/drivers/mtd/nand/raw/atmel/nand-controller.c +++ b/drivers/mtd/nand/raw/atmel/nand-controller.c @@ -895,15 +895,13 @@ static int atmel_nand_pmecc_read_pg(struct nand_chip *chip, u8 *buf, return ret; } -static int atmel_nand_pmecc_read_page(struct mtd_info *mtd, - struct nand_chip *chip, u8 *buf, +static int atmel_nand_pmecc_read_page(struct nand_chip *chip, u8 *buf, int oob_required, int page) { return atmel_nand_pmecc_read_pg(chip, buf, oob_required, page, false); } -static int atmel_nand_pmecc_read_page_raw(struct mtd_info *mtd, - struct nand_chip *chip, u8 *buf, +static int atmel_nand_pmecc_read_page_raw(struct nand_chip *chip, u8 *buf, int oob_required, int page) { return atmel_nand_pmecc_read_pg(chip, buf, oob_required, page, true); @@ -1037,16 +1035,14 @@ static int atmel_hsmc_nand_pmecc_read_pg(struct nand_chip *chip, u8 *buf, return ret; } -static int atmel_hsmc_nand_pmecc_read_page(struct mtd_info *mtd, - struct nand_chip *chip, u8 *buf, +static int atmel_hsmc_nand_pmecc_read_page(struct nand_chip *chip, u8 *buf, int oob_required, int page) { return atmel_hsmc_nand_pmecc_read_pg(chip, buf, oob_required, page, false); } -static int atmel_hsmc_nand_pmecc_read_page_raw(struct mtd_info *mtd, - struct nand_chip *chip, +static int atmel_hsmc_nand_pmecc_read_page_raw(struct nand_chip *chip, u8 *buf, int oob_required, int page) { diff --git a/drivers/mtd/nand/raw/brcmnand/brcmnand.c b/drivers/mtd/nand/raw/brcmnand/brcmnand.c index 19e6e918f896..a17ae692aee9 100644 --- a/drivers/mtd/nand/raw/brcmnand/brcmnand.c +++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c @@ -1689,7 +1689,7 @@ static int brcmstb_nand_verify_erased_page(struct mtd_info *mtd, sas = mtd->oobsize / chip->ecc.steps; /* read without ecc for verification */ - ret = chip->ecc.read_page_raw(mtd, chip, buf, true, page); + ret = chip->ecc.read_page_raw(chip, buf, true, page); if (ret) return ret; @@ -1786,9 +1786,10 @@ static int brcmnand_read(struct mtd_info *mtd, struct nand_chip *chip, return 0; } -static int brcmnand_read_page(struct mtd_info *mtd, struct nand_chip *chip, - uint8_t *buf, int oob_required, int page) +static int brcmnand_read_page(struct nand_chip *chip, uint8_t *buf, + int oob_required, int page) { + struct mtd_info *mtd = nand_to_mtd(chip); struct brcmnand_host *host = nand_get_controller_data(chip); u8 *oob = oob_required ? (u8 *)chip->oob_poi : NULL; @@ -1798,10 +1799,11 @@ static int brcmnand_read_page(struct mtd_info *mtd, struct nand_chip *chip, mtd->writesize >> FC_SHIFT, (u32 *)buf, oob); } -static int brcmnand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip, - uint8_t *buf, int oob_required, int page) +static int brcmnand_read_page_raw(struct nand_chip *chip, uint8_t *buf, + int oob_required, int page) { struct brcmnand_host *host = nand_get_controller_data(chip); + struct mtd_info *mtd = nand_to_mtd(chip); u8 *oob = oob_required ? (u8 *)chip->oob_poi : NULL; int ret; @@ -1814,17 +1816,18 @@ static int brcmnand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip, return ret; } -static int brcmnand_read_oob(struct mtd_info *mtd, struct nand_chip *chip, - int page) +static int brcmnand_read_oob(struct nand_chip *chip, int page) { + struct mtd_info *mtd = nand_to_mtd(chip); + return brcmnand_read(mtd, chip, (u64)page << chip->page_shift, mtd->writesize >> FC_SHIFT, NULL, (u8 *)chip->oob_poi); } -static int brcmnand_read_oob_raw(struct mtd_info *mtd, struct nand_chip *chip, - int page) +static int brcmnand_read_oob_raw(struct nand_chip *chip, int page) { + struct mtd_info *mtd = nand_to_mtd(chip); struct brcmnand_host *host = nand_get_controller_data(chip); brcmnand_set_ecc_enabled(host, 0); diff --git a/drivers/mtd/nand/raw/cafe_nand.c b/drivers/mtd/nand/raw/cafe_nand.c index 94e5f7a56084..c6071d71cc1b 100644 --- a/drivers/mtd/nand/raw/cafe_nand.c +++ b/drivers/mtd/nand/raw/cafe_nand.c @@ -354,9 +354,10 @@ static int cafe_nand_write_oob(struct mtd_info *mtd, } /* Don't use -- use nand_read_oob_std for now */ -static int cafe_nand_read_oob(struct mtd_info *mtd, struct nand_chip *chip, - int page) +static int cafe_nand_read_oob(struct nand_chip *chip, int page) { + struct mtd_info *mtd = nand_to_mtd(chip); + return nand_read_oob_op(chip, page, 0, chip->oob_poi, mtd->oobsize); } /** @@ -369,9 +370,10 @@ static int cafe_nand_read_oob(struct mtd_info *mtd, struct nand_chip *chip, * The hw generator calculates the error syndrome automatically. Therefore * we need a special oob layout and handling. */ -static int cafe_nand_read_page(struct mtd_info *mtd, struct nand_chip *chip, - uint8_t *buf, int oob_required, int page) +static int cafe_nand_read_page(struct nand_chip *chip, uint8_t *buf, + int oob_required, int page) { + struct mtd_info *mtd = nand_to_mtd(chip); struct cafe_priv *cafe = nand_get_controller_data(chip); unsigned int max_bitflips = 0; diff --git a/drivers/mtd/nand/raw/denali.c b/drivers/mtd/nand/raw/denali.c index 958619fd4d1b..994921814d76 100644 --- a/drivers/mtd/nand/raw/denali.c +++ b/drivers/mtd/nand/raw/denali.c @@ -676,9 +676,10 @@ static void denali_oob_xfer(struct mtd_info *mtd, struct nand_chip *chip, false); } -static int denali_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip, - uint8_t *buf, int oob_required, int page) +static int denali_read_page_raw(struct nand_chip *chip, uint8_t *buf, + int oob_required, int page) { + struct mtd_info *mtd = nand_to_mtd(chip); struct denali_nand_info *denali = mtd_to_denali(mtd); int writesize = mtd->writesize; int oobsize = mtd->oobsize; @@ -751,9 +752,10 @@ static int denali_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip, return 0; } -static int denali_read_oob(struct mtd_info *mtd, struct nand_chip *chip, - int page) +static int denali_read_oob(struct nand_chip *chip, int page) { + struct mtd_info *mtd = nand_to_mtd(chip); + denali_oob_xfer(mtd, chip, page, 0); return 0; @@ -771,9 +773,10 @@ static int denali_write_oob(struct mtd_info *mtd, struct nand_chip *chip, return nand_prog_page_end_op(chip); } -static int denali_read_page(struct mtd_info *mtd, struct nand_chip *chip, - uint8_t *buf, int oob_required, int page) +static int denali_read_page(struct nand_chip *chip, uint8_t *buf, + int oob_required, int page) { + struct mtd_info *mtd = nand_to_mtd(chip); struct denali_nand_info *denali = mtd_to_denali(mtd); unsigned long uncor_ecc_flags = 0; int stat = 0; @@ -792,7 +795,7 @@ static int denali_read_page(struct mtd_info *mtd, struct nand_chip *chip, return stat; if (uncor_ecc_flags) { - ret = denali_read_oob(mtd, chip, page); + ret = denali_read_oob(chip, page); if (ret) return ret; diff --git a/drivers/mtd/nand/raw/docg4.c b/drivers/mtd/nand/raw/docg4.c index 2d86bc5a886d..ebaa479ffcb2 100644 --- a/drivers/mtd/nand/raw/docg4.c +++ b/drivers/mtd/nand/raw/docg4.c @@ -845,21 +845,21 @@ static int read_page(struct mtd_info *mtd, struct nand_chip *nand, } -static int docg4_read_page_raw(struct mtd_info *mtd, struct nand_chip *nand, - uint8_t *buf, int oob_required, int page) +static int docg4_read_page_raw(struct nand_chip *nand, uint8_t *buf, + int oob_required, int page) { - return read_page(mtd, nand, buf, page, false); + return read_page(nand_to_mtd(nand), nand, buf, page, false); } -static int docg4_read_page(struct mtd_info *mtd, struct nand_chip *nand, - uint8_t *buf, int oob_required, int page) +static int docg4_read_page(struct nand_chip *nand, uint8_t *buf, + int oob_required, int page) { - return read_page(mtd, nand, buf, page, true); + return read_page(nand_to_mtd(nand), nand, buf, page, true); } -static int docg4_read_oob(struct mtd_info *mtd, struct nand_chip *nand, - int page) +static int docg4_read_oob(struct nand_chip *nand, int page) { + struct mtd_info *mtd = nand_to_mtd(nand); struct docg4_priv *doc = nand_get_controller_data(nand); void __iomem *docptr = doc->virtadr; uint16_t status; @@ -1059,7 +1059,7 @@ static int __init read_factory_bbt(struct mtd_info *mtd) return -ENOMEM; read_page_prologue(mtd, g4_addr); - docg4_read_page(mtd, nand, buf, 0, DOCG4_FACTORY_BBT_PAGE); + docg4_read_page(nand, buf, 0, DOCG4_FACTORY_BBT_PAGE); /* * If no memory-based bbt was created, exit. This will happen if module @@ -1077,7 +1077,7 @@ static int __init read_factory_bbt(struct mtd_info *mtd) * It is stored redundantly, so we get another chance. */ eccfailed_stats = mtd->ecc_stats.failed; - docg4_read_page(mtd, nand, buf, 0, DOCG4_REDUNDANT_BBT_PAGE); + docg4_read_page(nand, buf, 0, DOCG4_REDUNDANT_BBT_PAGE); if (mtd->ecc_stats.failed > eccfailed_stats) { dev_warn(doc->dev, "The factory bbt could not be read!\n"); diff --git a/drivers/mtd/nand/raw/fsl_elbc_nand.c b/drivers/mtd/nand/raw/fsl_elbc_nand.c index 22bcd64a66c8..26fcb8ea0c2e 100644 --- a/drivers/mtd/nand/raw/fsl_elbc_nand.c +++ b/drivers/mtd/nand/raw/fsl_elbc_nand.c @@ -710,9 +710,10 @@ static const struct nand_controller_ops fsl_elbc_controller_ops = { .attach_chip = fsl_elbc_attach_chip, }; -static int fsl_elbc_read_page(struct mtd_info *mtd, struct nand_chip *chip, - uint8_t *buf, int oob_required, int page) +static int fsl_elbc_read_page(struct nand_chip *chip, uint8_t *buf, + int oob_required, int page) { + struct mtd_info *mtd = nand_to_mtd(chip); struct fsl_elbc_mtd *priv = nand_get_controller_data(chip); struct fsl_lbc_ctrl *ctrl = priv->ctrl; struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand; diff --git a/drivers/mtd/nand/raw/fsl_ifc_nand.c b/drivers/mtd/nand/raw/fsl_ifc_nand.c index 70bf8e1552a5..8c6016932aaa 100644 --- a/drivers/mtd/nand/raw/fsl_ifc_nand.c +++ b/drivers/mtd/nand/raw/fsl_ifc_nand.c @@ -679,9 +679,10 @@ static int check_erased_page(struct nand_chip *chip, u8 *buf) return bitflips; } -static int fsl_ifc_read_page(struct mtd_info *mtd, struct nand_chip *chip, - uint8_t *buf, int oob_required, int page) +static int fsl_ifc_read_page(struct nand_chip *chip, uint8_t *buf, + int oob_required, int page) { + struct mtd_info *mtd = nand_to_mtd(chip); struct fsl_ifc_mtd *priv = nand_get_controller_data(chip); struct fsl_ifc_ctrl *ctrl = priv->ctrl; struct fsl_ifc_nand_ctrl *nctrl = ifc_nand_ctrl; diff --git a/drivers/mtd/nand/raw/fsmc_nand.c b/drivers/mtd/nand/raw/fsmc_nand.c index b41fd09fa389..5fc036c89cc8 100644 --- a/drivers/mtd/nand/raw/fsmc_nand.c +++ b/drivers/mtd/nand/raw/fsmc_nand.c @@ -707,7 +707,6 @@ static int fsmc_exec_op(struct nand_chip *chip, const struct nand_operation *op, /* * fsmc_read_page_hwecc - * @mtd: mtd info structure * @chip: nand chip info structure * @buf: buffer to store read data * @oob_required: caller expects OOB data read to chip->oob_poi @@ -719,9 +718,10 @@ static int fsmc_exec_op(struct nand_chip *chip, const struct nand_operation *op, * After this read, fsmc hardware generates and reports error data bits(up to a * max of 8 bits) */ -static int fsmc_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, - uint8_t *buf, int oob_required, int page) +static int fsmc_read_page_hwecc(struct nand_chip *chip, uint8_t *buf, + int oob_required, int page) { + struct mtd_info *mtd = nand_to_mtd(chip); int i, j, s, stat, eccsize = chip->ecc.size; int eccbytes = chip->ecc.bytes; int eccsteps = chip->ecc.steps; diff --git a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c index fe99d9323d4a..5650ebf28903 100644 --- a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c +++ b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c @@ -1085,8 +1085,8 @@ static int gpmi_ecc_read_page_data(struct nand_chip *chip, return max_bitflips; } -static int gpmi_ecc_read_page(struct mtd_info *mtd, struct nand_chip *chip, - uint8_t *buf, int oob_required, int page) +static int gpmi_ecc_read_page(struct nand_chip *chip, uint8_t *buf, + int oob_required, int page) { nand_read_page_op(chip, page, 0, NULL, 0); @@ -1094,8 +1094,8 @@ static int gpmi_ecc_read_page(struct mtd_info *mtd, struct nand_chip *chip, } /* Fake a virtual small page for the subpage read */ -static int gpmi_ecc_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, - uint32_t offs, uint32_t len, uint8_t *buf, int page) +static int gpmi_ecc_read_subpage(struct nand_chip *chip, uint32_t offs, + uint32_t len, uint8_t *buf, int page) { struct gpmi_nand_data *this = nand_get_controller_data(chip); void __iomem *bch_regs = this->resources.bch_regs; @@ -1130,7 +1130,7 @@ static int gpmi_ecc_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, dev_dbg(this->dev, "page:%d, first:%d, last:%d, marker at:%d\n", page, first, last, marker_pos); - return gpmi_ecc_read_page(mtd, chip, buf, 0, page); + return gpmi_ecc_read_page(chip, buf, 0, page); } } @@ -1324,9 +1324,9 @@ static int gpmi_ecc_write_page(struct mtd_info *mtd, struct nand_chip *chip, * ECC-based or raw view of the page is implicit in which function it calls * (there is a similar pair of ECC-based/raw functions for writing). */ -static int gpmi_ecc_read_oob(struct mtd_info *mtd, struct nand_chip *chip, - int page) +static int gpmi_ecc_read_oob(struct nand_chip *chip, int page) { + struct mtd_info *mtd = nand_to_mtd(chip); struct gpmi_nand_data *this = nand_get_controller_data(chip); dev_dbg(this->dev, "page number is %d\n", page); @@ -1380,10 +1380,10 @@ gpmi_ecc_write_oob(struct mtd_info *mtd, struct nand_chip *chip, int page) * See set_geometry_by_ecc_info inline comments to have a full description * of the layout used by the GPMI controller. */ -static int gpmi_ecc_read_page_raw(struct mtd_info *mtd, - struct nand_chip *chip, uint8_t *buf, +static int gpmi_ecc_read_page_raw(struct nand_chip *chip, uint8_t *buf, int oob_required, int page) { + struct mtd_info *mtd = nand_to_mtd(chip); struct gpmi_nand_data *this = nand_get_controller_data(chip); struct bch_geometry *nfc_geo = &this->bch_geometry; int eccsize = nfc_geo->ecc_chunk_size; @@ -1536,10 +1536,9 @@ static int gpmi_ecc_write_page_raw(struct mtd_info *mtd, mtd->writesize + mtd->oobsize); } -static int gpmi_ecc_read_oob_raw(struct mtd_info *mtd, struct nand_chip *chip, - int page) +static int gpmi_ecc_read_oob_raw(struct nand_chip *chip, int page) { - return gpmi_ecc_read_page_raw(mtd, chip, NULL, 1, page); + return gpmi_ecc_read_page_raw(chip, NULL, 1, page); } static int gpmi_ecc_write_oob_raw(struct mtd_info *mtd, struct nand_chip *chip, diff --git a/drivers/mtd/nand/raw/hisi504_nand.c b/drivers/mtd/nand/raw/hisi504_nand.c index 9106a1d60bca..f4078086c14c 100644 --- a/drivers/mtd/nand/raw/hisi504_nand.c +++ b/drivers/mtd/nand/raw/hisi504_nand.c @@ -528,9 +528,10 @@ static irqreturn_t hinfc_irq_handle(int irq, void *devid) return IRQ_HANDLED; } -static int hisi_nand_read_page_hwecc(struct mtd_info *mtd, - struct nand_chip *chip, uint8_t *buf, int oob_required, int page) +static int hisi_nand_read_page_hwecc(struct nand_chip *chip, uint8_t *buf, + int oob_required, int page) { + struct mtd_info *mtd = nand_to_mtd(chip); struct hinfc_host *host = nand_get_controller_data(chip); int max_bitflips = 0, stat = 0, stat_max = 0, status_ecc; int stat_1, stat_2; @@ -560,9 +561,9 @@ static int hisi_nand_read_page_hwecc(struct mtd_info *mtd, return max_bitflips; } -static int hisi_nand_read_oob(struct mtd_info *mtd, struct nand_chip *chip, - int page) +static int hisi_nand_read_oob(struct nand_chip *chip, int page) { + struct mtd_info *mtd = nand_to_mtd(chip); struct hinfc_host *host = nand_get_controller_data(chip); nand_read_oob_op(chip, page, 0, chip->oob_poi, mtd->oobsize); diff --git a/drivers/mtd/nand/raw/lpc32xx_mlc.c b/drivers/mtd/nand/raw/lpc32xx_mlc.c index 84e421710297..1849e9858d45 100644 --- a/drivers/mtd/nand/raw/lpc32xx_mlc.c +++ b/drivers/mtd/nand/raw/lpc32xx_mlc.c @@ -442,9 +442,10 @@ static int lpc32xx_xmit_dma(struct mtd_info *mtd, void *mem, int len, return -ENXIO; } -static int lpc32xx_read_page(struct mtd_info *mtd, struct nand_chip *chip, - uint8_t *buf, int oob_required, int page) +static int lpc32xx_read_page(struct nand_chip *chip, uint8_t *buf, + int oob_required, int page) { + struct mtd_info *mtd = nand_to_mtd(chip); struct lpc32xx_nand_host *host = nand_get_controller_data(chip); int i, j; uint8_t *oobbuf = chip->oob_poi; @@ -557,13 +558,12 @@ static int lpc32xx_write_page_lowlevel(struct mtd_info *mtd, return nand_prog_page_end_op(chip); } -static int lpc32xx_read_oob(struct mtd_info *mtd, struct nand_chip *chip, - int page) +static int lpc32xx_read_oob(struct nand_chip *chip, int page) { struct lpc32xx_nand_host *host = nand_get_controller_data(chip); /* Read whole page - necessary with MLC controller! */ - lpc32xx_read_page(mtd, chip, host->dummy_buf, 1, page); + lpc32xx_read_page(chip, host->dummy_buf, 1, page); return 0; } diff --git a/drivers/mtd/nand/raw/lpc32xx_slc.c b/drivers/mtd/nand/raw/lpc32xx_slc.c index d5cb1b40a235..a9cb089923be 100644 --- a/drivers/mtd/nand/raw/lpc32xx_slc.c +++ b/drivers/mtd/nand/raw/lpc32xx_slc.c @@ -396,9 +396,10 @@ static void lpc32xx_nand_write_buf(struct mtd_info *mtd, const uint8_t *buf, int /* * Read the OOB data from the device without ECC using FIFO method */ -static int lpc32xx_nand_read_oob_syndrome(struct mtd_info *mtd, - struct nand_chip *chip, int page) +static int lpc32xx_nand_read_oob_syndrome(struct nand_chip *chip, int page) { + struct mtd_info *mtd = nand_to_mtd(chip); + return nand_read_oob_op(chip, page, 0, chip->oob_poi, mtd->oobsize); } @@ -610,10 +611,10 @@ static int lpc32xx_xfer(struct mtd_info *mtd, uint8_t *buf, int eccsubpages, * Read the data and OOB data from the device, use ECC correction with the * data, disable ECC for the OOB data */ -static int lpc32xx_nand_read_page_syndrome(struct mtd_info *mtd, - struct nand_chip *chip, uint8_t *buf, +static int lpc32xx_nand_read_page_syndrome(struct nand_chip *chip, uint8_t *buf, int oob_required, int page) { + struct mtd_info *mtd = nand_to_mtd(chip); struct lpc32xx_nand_host *host = nand_get_controller_data(chip); struct mtd_oob_region oobregion = { }; int stat, i, status, error; @@ -657,11 +658,12 @@ static int lpc32xx_nand_read_page_syndrome(struct mtd_info *mtd, * Read the data and OOB data from the device, no ECC correction with the * data or OOB data */ -static int lpc32xx_nand_read_page_raw_syndrome(struct mtd_info *mtd, - struct nand_chip *chip, +static int lpc32xx_nand_read_page_raw_syndrome(struct nand_chip *chip, uint8_t *buf, int oob_required, int page) { + struct mtd_info *mtd = nand_to_mtd(chip); + /* Issue read command */ nand_read_page_op(chip, page, 0, NULL, 0); diff --git a/drivers/mtd/nand/raw/marvell_nand.c b/drivers/mtd/nand/raw/marvell_nand.c index 5a9836c5093c..a81018f3a2f4 100644 --- a/drivers/mtd/nand/raw/marvell_nand.c +++ b/drivers/mtd/nand/raw/marvell_nand.c @@ -1026,18 +1026,15 @@ static int marvell_nfc_hw_ecc_hmg_do_read_page(struct nand_chip *chip, return ret; } -static int marvell_nfc_hw_ecc_hmg_read_page_raw(struct mtd_info *mtd, - struct nand_chip *chip, u8 *buf, +static int marvell_nfc_hw_ecc_hmg_read_page_raw(struct nand_chip *chip, u8 *buf, int oob_required, int page) { return marvell_nfc_hw_ecc_hmg_do_read_page(chip, buf, chip->oob_poi, true, page); } -static int marvell_nfc_hw_ecc_hmg_read_page(struct mtd_info *mtd, - struct nand_chip *chip, - u8 *buf, int oob_required, - int page) +static int marvell_nfc_hw_ecc_hmg_read_page(struct nand_chip *chip, u8 *buf, + int oob_required, int page) { const struct marvell_hw_ecc_layout *lt = to_marvell_nand(chip)->layout; unsigned int full_sz = lt->data_bytes + lt->spare_bytes + lt->ecc_bytes; @@ -1075,8 +1072,7 @@ static int marvell_nfc_hw_ecc_hmg_read_page(struct mtd_info *mtd, * it appears before the ECC bytes when reading), the ->read_oob_raw() function * also stands for ->read_oob(). */ -static int marvell_nfc_hw_ecc_hmg_read_oob_raw(struct mtd_info *mtd, - struct nand_chip *chip, int page) +static int marvell_nfc_hw_ecc_hmg_read_oob_raw(struct nand_chip *chip, int page) { /* Invalidate page cache */ chip->pagebuf = -1; @@ -1183,10 +1179,10 @@ static int marvell_nfc_hw_ecc_hmg_write_oob_raw(struct mtd_info *mtd, } /* BCH read helpers */ -static int marvell_nfc_hw_ecc_bch_read_page_raw(struct mtd_info *mtd, - struct nand_chip *chip, u8 *buf, +static int marvell_nfc_hw_ecc_bch_read_page_raw(struct nand_chip *chip, u8 *buf, int oob_required, int page) { + struct mtd_info *mtd = nand_to_mtd(chip); const struct marvell_hw_ecc_layout *lt = to_marvell_nand(chip)->layout; u8 *oob = chip->oob_poi; int chunk_size = lt->data_bytes + lt->spare_bytes + lt->ecc_bytes; @@ -1295,11 +1291,11 @@ static void marvell_nfc_hw_ecc_bch_read_chunk(struct nand_chip *chip, int chunk, } } -static int marvell_nfc_hw_ecc_bch_read_page(struct mtd_info *mtd, - struct nand_chip *chip, +static int marvell_nfc_hw_ecc_bch_read_page(struct nand_chip *chip, u8 *buf, int oob_required, int page) { + struct mtd_info *mtd = nand_to_mtd(chip); const struct marvell_hw_ecc_layout *lt = to_marvell_nand(chip)->layout; int data_len = lt->data_bytes, spare_len = lt->spare_bytes, ecc_len; u8 *data = buf, *spare = chip->oob_poi, *ecc; @@ -1392,22 +1388,20 @@ static int marvell_nfc_hw_ecc_bch_read_page(struct mtd_info *mtd, return max_bitflips; } -static int marvell_nfc_hw_ecc_bch_read_oob_raw(struct mtd_info *mtd, - struct nand_chip *chip, int page) +static int marvell_nfc_hw_ecc_bch_read_oob_raw(struct nand_chip *chip, int page) { /* Invalidate page cache */ chip->pagebuf = -1; - return chip->ecc.read_page_raw(mtd, chip, chip->data_buf, true, page); + return chip->ecc.read_page_raw(chip, chip->data_buf, true, page); } -static int marvell_nfc_hw_ecc_bch_read_oob(struct mtd_info *mtd, - struct nand_chip *chip, int page) +static int marvell_nfc_hw_ecc_bch_read_oob(struct nand_chip *chip, int page) { /* Invalidate page cache */ chip->pagebuf = -1; - return chip->ecc.read_page(mtd, chip, chip->data_buf, true, page); + return chip->ecc.read_page(chip, chip->data_buf, true, page); } /* BCH write helpers */ diff --git a/drivers/mtd/nand/raw/mtk_nand.c b/drivers/mtd/nand/raw/mtk_nand.c index 46d447f148f1..32d5b59eb879 100644 --- a/drivers/mtd/nand/raw/mtk_nand.c +++ b/drivers/mtd/nand/raw/mtk_nand.c @@ -969,23 +969,25 @@ static int mtk_nfc_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, return bitflips; } -static int mtk_nfc_read_subpage_hwecc(struct mtd_info *mtd, - struct nand_chip *chip, u32 off, +static int mtk_nfc_read_subpage_hwecc(struct nand_chip *chip, u32 off, u32 len, u8 *p, int pg) { - return mtk_nfc_read_subpage(mtd, chip, off, len, p, pg, 0); + return mtk_nfc_read_subpage(nand_to_mtd(chip), chip, off, len, p, pg, + 0); } -static int mtk_nfc_read_page_hwecc(struct mtd_info *mtd, - struct nand_chip *chip, u8 *p, - int oob_on, int pg) +static int mtk_nfc_read_page_hwecc(struct nand_chip *chip, u8 *p, int oob_on, + int pg) { + struct mtd_info *mtd = nand_to_mtd(chip); + return mtk_nfc_read_subpage(mtd, chip, 0, mtd->writesize, p, pg, 0); } -static int mtk_nfc_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip, - u8 *buf, int oob_on, int page) +static int mtk_nfc_read_page_raw(struct nand_chip *chip, u8 *buf, int oob_on, + int page) { + struct mtd_info *mtd = nand_to_mtd(chip); struct mtk_nfc_nand_chip *mtk_nand = to_mtk_nand(chip); struct mtk_nfc *nfc = nand_get_controller_data(chip); struct mtk_nfc_fdm *fdm = &mtk_nand->fdm; @@ -1011,10 +1013,9 @@ static int mtk_nfc_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip, return ret; } -static int mtk_nfc_read_oob_std(struct mtd_info *mtd, struct nand_chip *chip, - int page) +static int mtk_nfc_read_oob_std(struct nand_chip *chip, int page) { - return mtk_nfc_read_page_raw(mtd, chip, NULL, 1, page); + return mtk_nfc_read_page_raw(chip, NULL, 1, page); } static inline void mtk_nfc_hw_init(struct mtk_nfc *nfc) diff --git a/drivers/mtd/nand/raw/mxc_nand.c b/drivers/mtd/nand/raw/mxc_nand.c index 3c57e14e1c7c..35fcec595c3e 100644 --- a/drivers/mtd/nand/raw/mxc_nand.c +++ b/drivers/mtd/nand/raw/mxc_nand.c @@ -816,8 +816,8 @@ static int mxc_nand_read_page_v2_v3(struct nand_chip *chip, void *buf, return max_bitflips; } -static int mxc_nand_read_page(struct mtd_info *mtd, struct nand_chip *chip, - uint8_t *buf, int oob_required, int page) +static int mxc_nand_read_page(struct nand_chip *chip, uint8_t *buf, + int oob_required, int page) { struct mxc_nand_host *host = nand_get_controller_data(chip); void *oob_buf; @@ -830,8 +830,8 @@ static int mxc_nand_read_page(struct mtd_info *mtd, struct nand_chip *chip, return host->devtype_data->read_page(chip, buf, oob_buf, 1, page); } -static int mxc_nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip, - uint8_t *buf, int oob_required, int page) +static int mxc_nand_read_page_raw(struct nand_chip *chip, uint8_t *buf, + int oob_required, int page) { struct mxc_nand_host *host = nand_get_controller_data(chip); void *oob_buf; @@ -844,8 +844,7 @@ static int mxc_nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip, return host->devtype_data->read_page(chip, buf, oob_buf, 0, page); } -static int mxc_nand_read_oob(struct mtd_info *mtd, struct nand_chip *chip, - int page) +static int mxc_nand_read_oob(struct nand_chip *chip, int page) { struct mxc_nand_host *host = nand_get_controller_data(chip); diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c index 0444bd23c84b..e1f60c841348 100644 --- a/drivers/mtd/nand/raw/nand_base.c +++ b/drivers/mtd/nand/raw/nand_base.c @@ -427,7 +427,7 @@ static int nand_block_bad(struct mtd_info *mtd, loff_t ofs) page_end = page + (chip->bbt_options & NAND_BBT_SCAN2NDPAGE ? 2 : 1); for (; page < page_end; page++) { - res = chip->ecc.read_oob(mtd, chip, page); + res = chip->ecc.read_oob(chip, page); if (res < 0) return res; @@ -2978,7 +2978,6 @@ EXPORT_SYMBOL(nand_check_erased_ecc_chunk); /** * nand_read_page_raw_notsupp - dummy read raw page function - * @mtd: mtd info structure * @chip: nand chip info structure * @buf: buffer to store read data * @oob_required: caller requires OOB data read to chip->oob_poi @@ -2986,8 +2985,8 @@ EXPORT_SYMBOL(nand_check_erased_ecc_chunk); * * Returns -ENOTSUPP unconditionally. */ -int nand_read_page_raw_notsupp(struct mtd_info *mtd, struct nand_chip *chip, - u8 *buf, int oob_required, int page) +int nand_read_page_raw_notsupp(struct nand_chip *chip, u8 *buf, + int oob_required, int page) { return -ENOTSUPP; } @@ -2995,7 +2994,6 @@ EXPORT_SYMBOL(nand_read_page_raw_notsupp); /** * nand_read_page_raw - [INTERN] read raw page data without ecc - * @mtd: mtd info structure * @chip: nand chip info structure * @buf: buffer to store read data * @oob_required: caller requires OOB data read to chip->oob_poi @@ -3003,9 +3001,10 @@ EXPORT_SYMBOL(nand_read_page_raw_notsupp); * * Not for syndrome calculating ECC controllers, which use a special oob layout. */ -int nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip, - uint8_t *buf, int oob_required, int page) +int nand_read_page_raw(struct nand_chip *chip, uint8_t *buf, int oob_required, + int page) { + struct mtd_info *mtd = nand_to_mtd(chip); int ret; ret = nand_read_page_op(chip, page, 0, buf, mtd->writesize); @@ -3025,7 +3024,6 @@ EXPORT_SYMBOL(nand_read_page_raw); /** * nand_read_page_raw_syndrome - [INTERN] read raw page data without ecc - * @mtd: mtd info structure * @chip: nand chip info structure * @buf: buffer to store read data * @oob_required: caller requires OOB data read to chip->oob_poi @@ -3033,10 +3031,10 @@ EXPORT_SYMBOL(nand_read_page_raw); * * We need a special oob layout and handling even when OOB isn't used. */ -static int nand_read_page_raw_syndrome(struct mtd_info *mtd, - struct nand_chip *chip, uint8_t *buf, +static int nand_read_page_raw_syndrome(struct nand_chip *chip, uint8_t *buf, int oob_required, int page) { + struct mtd_info *mtd = nand_to_mtd(chip); int eccsize = chip->ecc.size; int eccbytes = chip->ecc.bytes; uint8_t *oob = chip->oob_poi; @@ -3090,15 +3088,15 @@ static int nand_read_page_raw_syndrome(struct mtd_info *mtd, /** * nand_read_page_swecc - [REPLACEABLE] software ECC based page read function - * @mtd: mtd info structure * @chip: nand chip info structure * @buf: buffer to store read data * @oob_required: caller requires OOB data read to chip->oob_poi * @page: page number to read */ -static int nand_read_page_swecc(struct mtd_info *mtd, struct nand_chip *chip, - uint8_t *buf, int oob_required, int page) +static int nand_read_page_swecc(struct nand_chip *chip, uint8_t *buf, + int oob_required, int page) { + struct mtd_info *mtd = nand_to_mtd(chip); int i, eccsize = chip->ecc.size, ret; int eccbytes = chip->ecc.bytes; int eccsteps = chip->ecc.steps; @@ -3107,7 +3105,7 @@ static int nand_read_page_swecc(struct mtd_info *mtd, struct nand_chip *chip, uint8_t *ecc_code = chip->ecc.code_buf; unsigned int max_bitflips = 0; - chip->ecc.read_page_raw(mtd, chip, buf, 1, page); + chip->ecc.read_page_raw(chip, buf, 1, page); for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) chip->ecc.calculate(chip, p, &ecc_calc[i]); @@ -3136,17 +3134,16 @@ static int nand_read_page_swecc(struct mtd_info *mtd, struct nand_chip *chip, /** * nand_read_subpage - [REPLACEABLE] ECC based sub-page read function - * @mtd: mtd info structure * @chip: nand chip info structure * @data_offs: offset of requested data within the page * @readlen: data length * @bufpoi: buffer to store read data * @page: page number to read */ -static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, - uint32_t data_offs, uint32_t readlen, uint8_t *bufpoi, - int page) +static int nand_read_subpage(struct nand_chip *chip, uint32_t data_offs, + uint32_t readlen, uint8_t *bufpoi, int page) { + struct mtd_info *mtd = nand_to_mtd(chip); int start_step, end_step, num_steps, ret; uint8_t *p; int data_col_addr, i, gaps = 0; @@ -3248,7 +3245,6 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, /** * nand_read_page_hwecc - [REPLACEABLE] hardware ECC based page read function - * @mtd: mtd info structure * @chip: nand chip info structure * @buf: buffer to store read data * @oob_required: caller requires OOB data read to chip->oob_poi @@ -3256,9 +3252,10 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, * * Not for syndrome calculating ECC controllers which need a special oob layout. */ -static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, - uint8_t *buf, int oob_required, int page) +static int nand_read_page_hwecc(struct nand_chip *chip, uint8_t *buf, + int oob_required, int page) { + struct mtd_info *mtd = nand_to_mtd(chip); int i, eccsize = chip->ecc.size, ret; int eccbytes = chip->ecc.bytes; int eccsteps = chip->ecc.steps; @@ -3318,7 +3315,6 @@ static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, /** * nand_read_page_hwecc_oob_first - [REPLACEABLE] hw ecc, read oob first - * @mtd: mtd info structure * @chip: nand chip info structure * @buf: buffer to store read data * @oob_required: caller requires OOB data read to chip->oob_poi @@ -3330,9 +3326,10 @@ static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, * multiple ECC steps, follows the "infix ECC" scheme and reads/writes ECC from * the data area, by overwriting the NAND manufacturer bad block markings. */ -static int nand_read_page_hwecc_oob_first(struct mtd_info *mtd, - struct nand_chip *chip, uint8_t *buf, int oob_required, int page) +static int nand_read_page_hwecc_oob_first(struct nand_chip *chip, uint8_t *buf, + int oob_required, int page) { + struct mtd_info *mtd = nand_to_mtd(chip); int i, eccsize = chip->ecc.size, ret; int eccbytes = chip->ecc.bytes; int eccsteps = chip->ecc.steps; @@ -3388,7 +3385,6 @@ static int nand_read_page_hwecc_oob_first(struct mtd_info *mtd, /** * nand_read_page_syndrome - [REPLACEABLE] hardware ECC syndrome based page read - * @mtd: mtd info structure * @chip: nand chip info structure * @buf: buffer to store read data * @oob_required: caller requires OOB data read to chip->oob_poi @@ -3397,9 +3393,10 @@ static int nand_read_page_hwecc_oob_first(struct mtd_info *mtd, * The hw generator calculates the error syndrome automatically. Therefore we * need a special oob layout and handling. */ -static int nand_read_page_syndrome(struct mtd_info *mtd, struct nand_chip *chip, - uint8_t *buf, int oob_required, int page) +static int nand_read_page_syndrome(struct nand_chip *chip, uint8_t *buf, + int oob_required, int page) { + struct mtd_info *mtd = nand_to_mtd(chip); int ret, i, eccsize = chip->ecc.size; int eccbytes = chip->ecc.bytes; int eccsteps = chip->ecc.steps; @@ -3610,16 +3607,15 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from, * the read methods return max bitflips per ecc step. */ if (unlikely(ops->mode == MTD_OPS_RAW)) - ret = chip->ecc.read_page_raw(mtd, chip, bufpoi, + ret = chip->ecc.read_page_raw(chip, bufpoi, oob_required, page); else if (!aligned && NAND_HAS_SUBPAGE_READ(chip) && !oob) - ret = chip->ecc.read_subpage(mtd, chip, - col, bytes, bufpoi, - page); + ret = chip->ecc.read_subpage(chip, col, bytes, + bufpoi, page); else - ret = chip->ecc.read_page(mtd, chip, bufpoi, + ret = chip->ecc.read_page(chip, bufpoi, oob_required, page); if (ret < 0) { if (use_bufpoi) @@ -3723,12 +3719,13 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from, /** * nand_read_oob_std - [REPLACEABLE] the most common OOB data read function - * @mtd: mtd info structure * @chip: nand chip info structure * @page: page number to read */ -int nand_read_oob_std(struct mtd_info *mtd, struct nand_chip *chip, int page) +int nand_read_oob_std(struct nand_chip *chip, int page) { + struct mtd_info *mtd = nand_to_mtd(chip); + return nand_read_oob_op(chip, page, 0, chip->oob_poi, mtd->oobsize); } EXPORT_SYMBOL(nand_read_oob_std); @@ -3736,13 +3733,12 @@ EXPORT_SYMBOL(nand_read_oob_std); /** * nand_read_oob_syndrome - [REPLACEABLE] OOB data read function for HW ECC * with syndromes - * @mtd: mtd info structure * @chip: nand chip info structure * @page: page number to read */ -int nand_read_oob_syndrome(struct mtd_info *mtd, struct nand_chip *chip, - int page) +int nand_read_oob_syndrome(struct nand_chip *chip, int page) { + struct mtd_info *mtd = nand_to_mtd(chip); int length = mtd->oobsize; int chunk = chip->ecc.bytes + chip->ecc.prepad + chip->ecc.postpad; int eccsize = chip->ecc.size; @@ -3913,9 +3909,9 @@ static int nand_do_read_oob(struct mtd_info *mtd, loff_t from, while (1) { if (ops->mode == MTD_OPS_RAW) - ret = chip->ecc.read_oob_raw(mtd, chip, page); + ret = chip->ecc.read_oob_raw(chip, page); else - ret = chip->ecc.read_oob(mtd, chip, page); + ret = chip->ecc.read_oob(chip, page); if (ret < 0) break; diff --git a/drivers/mtd/nand/raw/nand_micron.c b/drivers/mtd/nand/raw/nand_micron.c index f5dc0a7a2456..d83a86ba9d09 100644 --- a/drivers/mtd/nand/raw/nand_micron.c +++ b/drivers/mtd/nand/raw/nand_micron.c @@ -290,10 +290,10 @@ static int micron_nand_on_die_ecc_status_8(struct nand_chip *chip, u8 status) } static int -micron_nand_read_page_on_die_ecc(struct mtd_info *mtd, struct nand_chip *chip, - uint8_t *buf, int oob_required, - int page) +micron_nand_read_page_on_die_ecc(struct nand_chip *chip, uint8_t *buf, + int oob_required, int page) { + struct mtd_info *mtd = nand_to_mtd(chip); u8 status; int ret, max_bitflips = 0; diff --git a/drivers/mtd/nand/raw/nand_toshiba.c b/drivers/mtd/nand/raw/nand_toshiba.c index 8aec3fa6c5d9..952fe9e62ab4 100644 --- a/drivers/mtd/nand/raw/nand_toshiba.c +++ b/drivers/mtd/nand/raw/nand_toshiba.c @@ -48,13 +48,13 @@ static int toshiba_nand_benand_eccstatus(struct mtd_info *mtd, } static int -toshiba_nand_read_page_benand(struct mtd_info *mtd, - struct nand_chip *chip, uint8_t *buf, +toshiba_nand_read_page_benand(struct nand_chip *chip, uint8_t *buf, int oob_required, int page) { + struct mtd_info *mtd = nand_to_mtd(chip); int ret; - ret = nand_read_page_raw(mtd, chip, buf, oob_required, page); + ret = nand_read_page_raw(chip, buf, oob_required, page); if (ret) return ret; @@ -62,10 +62,10 @@ toshiba_nand_read_page_benand(struct mtd_info *mtd, } static int -toshiba_nand_read_subpage_benand(struct mtd_info *mtd, - struct nand_chip *chip, uint32_t data_offs, +toshiba_nand_read_subpage_benand(struct nand_chip *chip, uint32_t data_offs, uint32_t readlen, uint8_t *bufpoi, int page) { + struct mtd_info *mtd = nand_to_mtd(chip); int ret; ret = nand_read_page_op(chip, page, data_offs, diff --git a/drivers/mtd/nand/raw/omap2.c b/drivers/mtd/nand/raw/omap2.c index 4e0bc2da63fd..dfe96098f3f6 100644 --- a/drivers/mtd/nand/raw/omap2.c +++ b/drivers/mtd/nand/raw/omap2.c @@ -1616,7 +1616,6 @@ static int omap_write_subpage_bch(struct mtd_info *mtd, /** * omap_read_page_bch - BCH ecc based page read function for entire page - * @mtd: mtd info structure * @chip: nand chip info structure * @buf: buffer to store read data * @oob_required: caller requires OOB data read to chip->oob_poi @@ -1629,9 +1628,10 @@ static int omap_write_subpage_bch(struct mtd_info *mtd, * ecc engine enabled. ecc vector updated after read of OOB data. * For non error pages ecc vector reported as zero. */ -static int omap_read_page_bch(struct mtd_info *mtd, struct nand_chip *chip, - uint8_t *buf, int oob_required, int page) +static int omap_read_page_bch(struct nand_chip *chip, uint8_t *buf, + int oob_required, int page) { + struct mtd_info *mtd = nand_to_mtd(chip); uint8_t *ecc_calc = chip->ecc.calc_buf; uint8_t *ecc_code = chip->ecc.code_buf; int stat, ret; diff --git a/drivers/mtd/nand/raw/qcom_nandc.c b/drivers/mtd/nand/raw/qcom_nandc.c index 312cfd786b0f..49113d4cee10 100644 --- a/drivers/mtd/nand/raw/qcom_nandc.c +++ b/drivers/mtd/nand/raw/qcom_nandc.c @@ -1948,8 +1948,8 @@ static int copy_last_cw(struct qcom_nand_host *host, int page) } /* implements ecc->read_page() */ -static int qcom_nandc_read_page(struct mtd_info *mtd, struct nand_chip *chip, - uint8_t *buf, int oob_required, int page) +static int qcom_nandc_read_page(struct nand_chip *chip, uint8_t *buf, + int oob_required, int page) { struct qcom_nand_host *host = to_qcom_nand_host(chip); struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip); @@ -1965,10 +1965,10 @@ static int qcom_nandc_read_page(struct mtd_info *mtd, struct nand_chip *chip, } /* implements ecc->read_page_raw() */ -static int qcom_nandc_read_page_raw(struct mtd_info *mtd, - struct nand_chip *chip, uint8_t *buf, +static int qcom_nandc_read_page_raw(struct nand_chip *chip, uint8_t *buf, int oob_required, int page) { + struct mtd_info *mtd = nand_to_mtd(chip); struct qcom_nand_host *host = to_qcom_nand_host(chip); struct nand_ecc_ctrl *ecc = &chip->ecc; int cw, ret; @@ -1988,8 +1988,7 @@ static int qcom_nandc_read_page_raw(struct mtd_info *mtd, } /* implements ecc->read_oob() */ -static int qcom_nandc_read_oob(struct mtd_info *mtd, struct nand_chip *chip, - int page) +static int qcom_nandc_read_oob(struct nand_chip *chip, int page) { struct qcom_nand_host *host = to_qcom_nand_host(chip); struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip); diff --git a/drivers/mtd/nand/raw/r852.c b/drivers/mtd/nand/raw/r852.c index 7673aa140009..aa5516b3b45f 100644 --- a/drivers/mtd/nand/raw/r852.c +++ b/drivers/mtd/nand/raw/r852.c @@ -521,9 +521,10 @@ static int r852_ecc_correct(struct nand_chip *chip, uint8_t *dat, * This is copy of nand_read_oob_std * nand_read_oob_syndrome assumes we can send column address - we can't */ -static int r852_read_oob(struct mtd_info *mtd, struct nand_chip *chip, - int page) +static int r852_read_oob(struct nand_chip *chip, int page) { + struct mtd_info *mtd = nand_to_mtd(chip); + return nand_read_oob_op(chip, page, 0, chip->oob_poi, mtd->oobsize); } diff --git a/drivers/mtd/nand/raw/sh_flctl.c b/drivers/mtd/nand/raw/sh_flctl.c index 2580fd981077..fb5df6099d7b 100644 --- a/drivers/mtd/nand/raw/sh_flctl.c +++ b/drivers/mtd/nand/raw/sh_flctl.c @@ -611,9 +611,11 @@ static void set_cmd_regs(struct mtd_info *mtd, uint32_t cmd, uint32_t flcmcdr_va writel(flcmcdr_val, FLCMCDR(flctl)); } -static int flctl_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, - uint8_t *buf, int oob_required, int page) +static int flctl_read_page_hwecc(struct nand_chip *chip, uint8_t *buf, + int oob_required, int page) { + struct mtd_info *mtd = nand_to_mtd(chip); + nand_read_page_op(chip, page, 0, buf, mtd->writesize); if (oob_required) chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c index e31ab86bebee..26d5c6c41c49 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -1189,10 +1189,10 @@ static void sunxi_nfc_hw_ecc_write_extra_oob(struct mtd_info *mtd, *cur_off = mtd->oobsize + mtd->writesize; } -static int sunxi_nfc_hw_ecc_read_page(struct mtd_info *mtd, - struct nand_chip *chip, uint8_t *buf, +static int sunxi_nfc_hw_ecc_read_page(struct nand_chip *chip, uint8_t *buf, int oob_required, int page) { + struct mtd_info *mtd = nand_to_mtd(chip); struct nand_ecc_ctrl *ecc = &chip->ecc; unsigned int max_bitflips = 0; int ret, i, cur_off = 0; @@ -1227,10 +1227,10 @@ static int sunxi_nfc_hw_ecc_read_page(struct mtd_info *mtd, return max_bitflips; } -static int sunxi_nfc_hw_ecc_read_page_dma(struct mtd_info *mtd, - struct nand_chip *chip, u8 *buf, +static int sunxi_nfc_hw_ecc_read_page_dma(struct nand_chip *chip, u8 *buf, int oob_required, int page) { + struct mtd_info *mtd = nand_to_mtd(chip); int ret; nand_read_page_op(chip, page, 0, NULL, 0); @@ -1241,14 +1241,14 @@ static int sunxi_nfc_hw_ecc_read_page_dma(struct mtd_info *mtd, return ret; /* Fallback to PIO mode */ - return sunxi_nfc_hw_ecc_read_page(mtd, chip, buf, oob_required, page); + return sunxi_nfc_hw_ecc_read_page(chip, buf, oob_required, page); } -static int sunxi_nfc_hw_ecc_read_subpage(struct mtd_info *mtd, - struct nand_chip *chip, +static int sunxi_nfc_hw_ecc_read_subpage(struct nand_chip *chip, u32 data_offs, u32 readlen, u8 *bufpoi, int page) { + struct mtd_info *mtd = nand_to_mtd(chip); struct nand_ecc_ctrl *ecc = &chip->ecc; int ret, i, cur_off = 0; unsigned int max_bitflips = 0; @@ -1278,11 +1278,11 @@ static int sunxi_nfc_hw_ecc_read_subpage(struct mtd_info *mtd, return max_bitflips; } -static int sunxi_nfc_hw_ecc_read_subpage_dma(struct mtd_info *mtd, - struct nand_chip *chip, +static int sunxi_nfc_hw_ecc_read_subpage_dma(struct nand_chip *chip, u32 data_offs, u32 readlen, u8 *buf, int page) { + struct mtd_info *mtd = nand_to_mtd(chip); int nchunks = DIV_ROUND_UP(data_offs + readlen, chip->ecc.size); int ret; @@ -1293,7 +1293,7 @@ static int sunxi_nfc_hw_ecc_read_subpage_dma(struct mtd_info *mtd, return ret; /* Fallback to PIO mode */ - return sunxi_nfc_hw_ecc_read_subpage(mtd, chip, data_offs, readlen, + return sunxi_nfc_hw_ecc_read_subpage(chip, data_offs, readlen, buf, page); } @@ -1428,13 +1428,11 @@ static int sunxi_nfc_hw_ecc_write_page_dma(struct mtd_info *mtd, return sunxi_nfc_hw_ecc_write_page(mtd, chip, buf, oob_required, page); } -static int sunxi_nfc_hw_ecc_read_oob(struct mtd_info *mtd, - struct nand_chip *chip, - int page) +static int sunxi_nfc_hw_ecc_read_oob(struct nand_chip *chip, int page) { chip->pagebuf = -1; - return chip->ecc.read_page(mtd, chip, chip->data_buf, 1, page); + return chip->ecc.read_page(chip, chip->data_buf, 1, page); } static int sunxi_nfc_hw_ecc_write_oob(struct mtd_info *mtd, diff --git a/drivers/mtd/nand/raw/tango_nand.c b/drivers/mtd/nand/raw/tango_nand.c index 1061eb60ee60..c53d47159195 100644 --- a/drivers/mtd/nand/raw/tango_nand.c +++ b/drivers/mtd/nand/raw/tango_nand.c @@ -277,14 +277,15 @@ static int do_dma(struct tango_nfc *nfc, enum dma_data_direction dir, int cmd, return err; } -static int tango_read_page(struct mtd_info *mtd, struct nand_chip *chip, - u8 *buf, int oob_required, int page) +static int tango_read_page(struct nand_chip *chip, u8 *buf, + int oob_required, int page) { + struct mtd_info *mtd = nand_to_mtd(chip); struct tango_nfc *nfc = to_tango_nfc(chip->controller); int err, res, len = mtd->writesize; if (oob_required) - chip->ecc.read_oob(mtd, chip, page); + chip->ecc.read_oob(chip, page); err = do_dma(nfc, DMA_FROM_DEVICE, NFC_READ, buf, len, page); if (err) @@ -292,7 +293,7 @@ static int tango_read_page(struct mtd_info *mtd, struct nand_chip *chip, res = decode_error_report(chip); if (res < 0) { - chip->ecc.read_oob_raw(mtd, chip, page); + chip->ecc.read_oob_raw(chip, page); res = check_erased_page(chip, buf); } @@ -424,8 +425,8 @@ static void raw_write(struct nand_chip *chip, const u8 *buf, const u8 *oob) aux_write(chip, &oob, ecc_size, &pos); } -static int tango_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip, - u8 *buf, int oob_required, int page) +static int tango_read_page_raw(struct nand_chip *chip, u8 *buf, + int oob_required, int page) { nand_read_page_op(chip, page, 0, NULL, 0); raw_read(chip, buf, chip->oob_poi); @@ -440,8 +441,7 @@ static int tango_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip, return nand_prog_page_end_op(chip); } -static int tango_read_oob(struct mtd_info *mtd, struct nand_chip *chip, - int page) +static int tango_read_oob(struct nand_chip *chip, int page) { nand_read_page_op(chip, page, 0, NULL, 0); raw_read(chip, NULL, chip->oob_poi); diff --git a/drivers/mtd/nand/raw/tegra_nand.c b/drivers/mtd/nand/raw/tegra_nand.c index 5dcee20e2a8c..bcc3a2888c4f 100644 --- a/drivers/mtd/nand/raw/tegra_nand.c +++ b/drivers/mtd/nand/raw/tegra_nand.c @@ -615,10 +615,10 @@ static int tegra_nand_page_xfer(struct mtd_info *mtd, struct nand_chip *chip, return ret; } -static int tegra_nand_read_page_raw(struct mtd_info *mtd, - struct nand_chip *chip, u8 *buf, +static int tegra_nand_read_page_raw(struct nand_chip *chip, u8 *buf, int oob_required, int page) { + struct mtd_info *mtd = nand_to_mtd(chip); void *oob_buf = oob_required ? chip->oob_poi : NULL; return tegra_nand_page_xfer(mtd, chip, buf, oob_buf, @@ -635,9 +635,10 @@ static int tegra_nand_write_page_raw(struct mtd_info *mtd, mtd->oobsize, page, false); } -static int tegra_nand_read_oob(struct mtd_info *mtd, struct nand_chip *chip, - int page) +static int tegra_nand_read_oob(struct nand_chip *chip, int page) { + struct mtd_info *mtd = nand_to_mtd(chip); + return tegra_nand_page_xfer(mtd, chip, NULL, chip->oob_poi, mtd->oobsize, page, true); } @@ -649,10 +650,10 @@ static int tegra_nand_write_oob(struct mtd_info *mtd, struct nand_chip *chip, mtd->oobsize, page, false); } -static int tegra_nand_read_page_hwecc(struct mtd_info *mtd, - struct nand_chip *chip, u8 *buf, +static int tegra_nand_read_page_hwecc(struct nand_chip *chip, u8 *buf, int oob_required, int page) { + struct mtd_info *mtd = nand_to_mtd(chip); struct tegra_nand_controller *ctrl = to_tegra_ctrl(chip->controller); struct tegra_nand_chip *nand = to_tegra_chip(chip); void *oob_buf = oob_required ? chip->oob_poi : NULL; @@ -716,7 +717,7 @@ static int tegra_nand_read_page_hwecc(struct mtd_info *mtd, * erased or if error correction just failed for all sub- * pages. */ - ret = tegra_nand_read_oob(mtd, chip, page); + ret = tegra_nand_read_oob(chip, page); if (ret < 0) return ret; diff --git a/drivers/mtd/nand/raw/vf610_nfc.c b/drivers/mtd/nand/raw/vf610_nfc.c index a73213c835a5..7cbcc41cea95 100644 --- a/drivers/mtd/nand/raw/vf610_nfc.c +++ b/drivers/mtd/nand/raw/vf610_nfc.c @@ -557,9 +557,10 @@ static void vf610_nfc_fill_row(struct nand_chip *chip, int page, u32 *code, } } -static int vf610_nfc_read_page(struct mtd_info *mtd, struct nand_chip *chip, - uint8_t *buf, int oob_required, int page) +static int vf610_nfc_read_page(struct nand_chip *chip, uint8_t *buf, + int oob_required, int page) { + struct mtd_info *mtd = nand_to_mtd(chip); struct vf610_nfc *nfc = mtd_to_nfc(mtd); int trfr_sz = mtd->writesize + mtd->oobsize; u32 row = 0, cmd1 = 0, cmd2 = 0, code = 0; @@ -643,15 +644,15 @@ static int vf610_nfc_write_page(struct mtd_info *mtd, struct nand_chip *chip, return 0; } -static int vf610_nfc_read_page_raw(struct mtd_info *mtd, - struct nand_chip *chip, u8 *buf, +static int vf610_nfc_read_page_raw(struct nand_chip *chip, u8 *buf, int oob_required, int page) { + struct mtd_info *mtd = nand_to_mtd(chip); struct vf610_nfc *nfc = mtd_to_nfc(mtd); int ret; nfc->data_access = true; - ret = nand_read_page_raw(mtd, chip, buf, oob_required, page); + ret = nand_read_page_raw(chip, buf, oob_required, page); nfc->data_access = false; return ret; @@ -677,14 +678,13 @@ static int vf610_nfc_write_page_raw(struct mtd_info *mtd, return nand_prog_page_end_op(chip); } -static int vf610_nfc_read_oob(struct mtd_info *mtd, struct nand_chip *chip, - int page) +static int vf610_nfc_read_oob(struct nand_chip *chip, int page) { - struct vf610_nfc *nfc = mtd_to_nfc(mtd); + struct vf610_nfc *nfc = mtd_to_nfc(nand_to_mtd(chip)); int ret; nfc->data_access = true; - ret = nand_read_oob_std(mtd, chip, page); + ret = nand_read_oob_std(chip, page); nfc->data_access = false; return ret; diff --git a/drivers/staging/mt29f_spinand/mt29f_spinand.c b/drivers/staging/mt29f_spinand/mt29f_spinand.c index b50788b2d1d9..0776d38d4498 100644 --- a/drivers/staging/mt29f_spinand/mt29f_spinand.c +++ b/drivers/staging/mt29f_spinand/mt29f_spinand.c @@ -643,14 +643,15 @@ static int spinand_write_page_hwecc(struct mtd_info *mtd, return nand_prog_page_op(chip, page, 0, p, eccsize * eccsteps); } -static int spinand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, - u8 *buf, int oob_required, int page) +static int spinand_read_page_hwecc(struct nand_chip *chip, u8 *buf, + int oob_required, int page) { int retval; u8 status; u8 *p = buf; int eccsize = chip->ecc.size; int eccsteps = chip->ecc.steps; + struct mtd_info *mtd = nand_to_mtd(chip); struct spinand_info *info = nand_get_controller_data(chip); enable_read_hw_ecc = 1; diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h index 24434310d126..a5f4a585f749 100644 --- a/include/linux/mtd/rawnand.h +++ b/include/linux/mtd/rawnand.h @@ -652,14 +652,14 @@ struct nand_ecc_ctrl { uint8_t *ecc_code); int (*correct)(struct nand_chip *chip, uint8_t *dat, uint8_t *read_ecc, uint8_t *calc_ecc); - int (*read_page_raw)(struct mtd_info *mtd, struct nand_chip *chip, - uint8_t *buf, int oob_required, int page); + int (*read_page_raw)(struct nand_chip *chip, uint8_t *buf, + int oob_required, int page); int (*write_page_raw)(struct mtd_info *mtd, struct nand_chip *chip, const uint8_t *buf, int oob_required, int page); - int (*read_page)(struct mtd_info *mtd, struct nand_chip *chip, - uint8_t *buf, int oob_required, int page); - int (*read_subpage)(struct mtd_info *mtd, struct nand_chip *chip, - uint32_t offs, uint32_t len, uint8_t *buf, int page); + int (*read_page)(struct nand_chip *chip, uint8_t *buf, + int oob_required, int page); + int (*read_subpage)(struct nand_chip *chip, uint32_t offs, + uint32_t len, uint8_t *buf, int page); int (*write_subpage)(struct mtd_info *mtd, struct nand_chip *chip, uint32_t offset, uint32_t data_len, const uint8_t *data_buf, int oob_required, int page); @@ -667,9 +667,8 @@ struct nand_ecc_ctrl { const uint8_t *buf, int oob_required, int page); int (*write_oob_raw)(struct mtd_info *mtd, struct nand_chip *chip, int page); - int (*read_oob_raw)(struct mtd_info *mtd, struct nand_chip *chip, - int page); - int (*read_oob)(struct mtd_info *mtd, struct nand_chip *chip, int page); + int (*read_oob_raw)(struct nand_chip *chip, int page); + int (*read_oob)(struct nand_chip *chip, int page); int (*write_oob)(struct mtd_info *mtd, struct nand_chip *chip, int page); }; @@ -1676,11 +1675,10 @@ int nand_write_oob_syndrome(struct mtd_info *mtd, struct nand_chip *chip, int page); /* Default read_oob implementation */ -int nand_read_oob_std(struct mtd_info *mtd, struct nand_chip *chip, int page); +int nand_read_oob_std(struct nand_chip *chip, int page); /* Default read_oob syndrome implementation */ -int nand_read_oob_syndrome(struct mtd_info *mtd, struct nand_chip *chip, - int page); +int nand_read_oob_syndrome(struct nand_chip *chip, int page); /* Wrapper to use in order for controllers/vendors to GET/SET FEATURES */ int nand_get_features(struct nand_chip *chip, int addr, u8 *subfeature_param); @@ -1690,10 +1688,10 @@ int nand_get_set_features_notsupp(struct mtd_info *mtd, struct nand_chip *chip, int addr, u8 *subfeature_param); /* Default read_page_raw implementation */ -int nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip, - uint8_t *buf, int oob_required, int page); -int nand_read_page_raw_notsupp(struct mtd_info *mtd, struct nand_chip *chip, - u8 *buf, int oob_required, int page); +int nand_read_page_raw(struct nand_chip *chip, uint8_t *buf, int oob_required, + int page); +int nand_read_page_raw_notsupp(struct nand_chip *chip, u8 *buf, + int oob_required, int page); /* Default write_page_raw implementation */ int nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip, From 767eb6fbdedb7d8b9c7a87d640a8bc8091eba002 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Thu, 6 Sep 2018 14:05:21 +0200 Subject: [PATCH 249/302] mtd: rawnand: Pass a nand_chip object to ecc->write_xxx() hooks Let's make the raw NAND API consistent by patching all helpers and hooks to take a nand_chip object instead of an mtd_info one or remove the mtd_info object when both are passed. Let's tackle all ecc->write_xxx() hooks at once. Signed-off-by: Boris Brezillon Signed-off-by: Miquel Raynal --- drivers/mtd/nand/raw/atmel/nand-controller.c | 12 +-- drivers/mtd/nand/raw/brcmnand/brcmnand.c | 21 +++--- drivers/mtd/nand/raw/cafe_nand.c | 13 ++-- drivers/mtd/nand/raw/denali.c | 14 ++-- drivers/mtd/nand/raw/docg4.c | 17 ++--- drivers/mtd/nand/raw/fsl_elbc_nand.c | 14 ++-- drivers/mtd/nand/raw/fsl_ifc_nand.c | 6 +- drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c | 21 +++--- drivers/mtd/nand/raw/hisi504_nand.c | 8 +- drivers/mtd/nand/raw/lpc32xx_mlc.c | 7 +- drivers/mtd/nand/raw/lpc32xx_slc.c | 14 ++-- drivers/mtd/nand/raw/marvell_nand.c | 32 ++++---- drivers/mtd/nand/raw/mtk_nand.c | 19 +++-- drivers/mtd/nand/raw/mxc_nand.c | 13 ++-- drivers/mtd/nand/raw/nand_base.c | 74 +++++++++---------- drivers/mtd/nand/raw/nand_ecc.c | 2 +- drivers/mtd/nand/raw/nand_micron.c | 7 +- drivers/mtd/nand/raw/omap2.c | 11 ++- drivers/mtd/nand/raw/qcom_nandc.c | 15 ++-- drivers/mtd/nand/raw/sh_flctl.c | 7 +- drivers/mtd/nand/raw/sunxi_nand.c | 21 +++--- drivers/mtd/nand/raw/tango_nand.c | 12 +-- drivers/mtd/nand/raw/tegra_nand.c | 13 ++-- drivers/mtd/nand/raw/vf610_nfc.c | 13 ++-- drivers/staging/mt29f_spinand/mt29f_spinand.c | 3 +- include/linux/mtd/rawnand.h | 33 ++++----- 26 files changed, 208 insertions(+), 214 deletions(-) diff --git a/drivers/mtd/nand/raw/atmel/nand-controller.c b/drivers/mtd/nand/raw/atmel/nand-controller.c index 45061b591346..3ebe9b727315 100644 --- a/drivers/mtd/nand/raw/atmel/nand-controller.c +++ b/drivers/mtd/nand/raw/atmel/nand-controller.c @@ -858,15 +858,13 @@ static int atmel_nand_pmecc_write_pg(struct nand_chip *chip, const u8 *buf, return nand_prog_page_end_op(chip); } -static int atmel_nand_pmecc_write_page(struct mtd_info *mtd, - struct nand_chip *chip, const u8 *buf, +static int atmel_nand_pmecc_write_page(struct nand_chip *chip, const u8 *buf, int oob_required, int page) { return atmel_nand_pmecc_write_pg(chip, buf, oob_required, page, false); } -static int atmel_nand_pmecc_write_page_raw(struct mtd_info *mtd, - struct nand_chip *chip, +static int atmel_nand_pmecc_write_page_raw(struct nand_chip *chip, const u8 *buf, int oob_required, int page) { @@ -963,8 +961,7 @@ static int atmel_hsmc_nand_pmecc_write_pg(struct nand_chip *chip, return ret; } -static int atmel_hsmc_nand_pmecc_write_page(struct mtd_info *mtd, - struct nand_chip *chip, +static int atmel_hsmc_nand_pmecc_write_page(struct nand_chip *chip, const u8 *buf, int oob_required, int page) { @@ -972,8 +969,7 @@ static int atmel_hsmc_nand_pmecc_write_page(struct mtd_info *mtd, false); } -static int atmel_hsmc_nand_pmecc_write_page_raw(struct mtd_info *mtd, - struct nand_chip *chip, +static int atmel_hsmc_nand_pmecc_write_page_raw(struct nand_chip *chip, const u8 *buf, int oob_required, int page) { diff --git a/drivers/mtd/nand/raw/brcmnand/brcmnand.c b/drivers/mtd/nand/raw/brcmnand/brcmnand.c index a17ae692aee9..d8fb2b5c19c9 100644 --- a/drivers/mtd/nand/raw/brcmnand/brcmnand.c +++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c @@ -1909,9 +1909,10 @@ static int brcmnand_write(struct mtd_info *mtd, struct nand_chip *chip, return ret; } -static int brcmnand_write_page(struct mtd_info *mtd, struct nand_chip *chip, - const uint8_t *buf, int oob_required, int page) +static int brcmnand_write_page(struct nand_chip *chip, const uint8_t *buf, + int oob_required, int page) { + struct mtd_info *mtd = nand_to_mtd(chip); struct brcmnand_host *host = nand_get_controller_data(chip); void *oob = oob_required ? chip->oob_poi : NULL; @@ -1921,10 +1922,10 @@ static int brcmnand_write_page(struct mtd_info *mtd, struct nand_chip *chip, return nand_prog_page_end_op(chip); } -static int brcmnand_write_page_raw(struct mtd_info *mtd, - struct nand_chip *chip, const uint8_t *buf, +static int brcmnand_write_page_raw(struct nand_chip *chip, const uint8_t *buf, int oob_required, int page) { + struct mtd_info *mtd = nand_to_mtd(chip); struct brcmnand_host *host = nand_get_controller_data(chip); void *oob = oob_required ? chip->oob_poi : NULL; @@ -1936,16 +1937,16 @@ static int brcmnand_write_page_raw(struct mtd_info *mtd, return nand_prog_page_end_op(chip); } -static int brcmnand_write_oob(struct mtd_info *mtd, struct nand_chip *chip, - int page) +static int brcmnand_write_oob(struct nand_chip *chip, int page) { - return brcmnand_write(mtd, chip, (u64)page << chip->page_shift, - NULL, chip->oob_poi); + return brcmnand_write(nand_to_mtd(chip), chip, + (u64)page << chip->page_shift, NULL, + chip->oob_poi); } -static int brcmnand_write_oob_raw(struct mtd_info *mtd, struct nand_chip *chip, - int page) +static int brcmnand_write_oob_raw(struct nand_chip *chip, int page) { + struct mtd_info *mtd = nand_to_mtd(chip); struct brcmnand_host *host = nand_get_controller_data(chip); int ret; diff --git a/drivers/mtd/nand/raw/cafe_nand.c b/drivers/mtd/nand/raw/cafe_nand.c index c6071d71cc1b..fe7c7db3cfe7 100644 --- a/drivers/mtd/nand/raw/cafe_nand.c +++ b/drivers/mtd/nand/raw/cafe_nand.c @@ -346,9 +346,10 @@ static irqreturn_t cafe_nand_interrupt(int irq, void *id) return IRQ_HANDLED; } -static int cafe_nand_write_oob(struct mtd_info *mtd, - struct nand_chip *chip, int page) +static int cafe_nand_write_oob(struct nand_chip *chip, int page) { + struct mtd_info *mtd = nand_to_mtd(chip); + return nand_prog_page_op(chip, page, mtd->writesize, chip->oob_poi, mtd->oobsize); } @@ -533,11 +534,11 @@ static struct nand_bbt_descr cafe_bbt_mirror_descr_512 = { }; -static int cafe_nand_write_page_lowlevel(struct mtd_info *mtd, - struct nand_chip *chip, - const uint8_t *buf, int oob_required, - int page) +static int cafe_nand_write_page_lowlevel(struct nand_chip *chip, + const uint8_t *buf, int oob_required, + int page) { + struct mtd_info *mtd = nand_to_mtd(chip); struct cafe_priv *cafe = nand_get_controller_data(chip); nand_prog_page_begin_op(chip, page, 0, buf, mtd->writesize); diff --git a/drivers/mtd/nand/raw/denali.c b/drivers/mtd/nand/raw/denali.c index 994921814d76..52fe5115ed6e 100644 --- a/drivers/mtd/nand/raw/denali.c +++ b/drivers/mtd/nand/raw/denali.c @@ -761,9 +761,9 @@ static int denali_read_oob(struct nand_chip *chip, int page) return 0; } -static int denali_write_oob(struct mtd_info *mtd, struct nand_chip *chip, - int page) +static int denali_write_oob(struct nand_chip *chip, int page) { + struct mtd_info *mtd = nand_to_mtd(chip); struct denali_nand_info *denali = mtd_to_denali(mtd); denali_reset_irq(denali); @@ -806,9 +806,10 @@ static int denali_read_page(struct nand_chip *chip, uint8_t *buf, return stat; } -static int denali_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip, - const uint8_t *buf, int oob_required, int page) +static int denali_write_page_raw(struct nand_chip *chip, const uint8_t *buf, + int oob_required, int page) { + struct mtd_info *mtd = nand_to_mtd(chip); struct denali_nand_info *denali = mtd_to_denali(mtd); int writesize = mtd->writesize; int oobsize = mtd->oobsize; @@ -884,9 +885,10 @@ static int denali_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip, return denali_data_xfer(denali, tmp_buf, size, page, 1, 1); } -static int denali_write_page(struct mtd_info *mtd, struct nand_chip *chip, - const uint8_t *buf, int oob_required, int page) +static int denali_write_page(struct nand_chip *chip, const uint8_t *buf, + int oob_required, int page) { + struct mtd_info *mtd = nand_to_mtd(chip); struct denali_nand_info *denali = mtd_to_denali(mtd); return denali_data_xfer(denali, (void *)buf, mtd->writesize, diff --git a/drivers/mtd/nand/raw/docg4.c b/drivers/mtd/nand/raw/docg4.c index ebaa479ffcb2..37935fd04020 100644 --- a/drivers/mtd/nand/raw/docg4.c +++ b/drivers/mtd/nand/raw/docg4.c @@ -1007,20 +1007,19 @@ static int write_page(struct mtd_info *mtd, struct nand_chip *nand, return nand_prog_page_end_op(nand); } -static int docg4_write_page_raw(struct mtd_info *mtd, struct nand_chip *nand, - const uint8_t *buf, int oob_required, int page) +static int docg4_write_page_raw(struct nand_chip *nand, const uint8_t *buf, + int oob_required, int page) { - return write_page(mtd, nand, buf, page, false); + return write_page(nand_to_mtd(nand), nand, buf, page, false); } -static int docg4_write_page(struct mtd_info *mtd, struct nand_chip *nand, - const uint8_t *buf, int oob_required, int page) +static int docg4_write_page(struct nand_chip *nand, const uint8_t *buf, + int oob_required, int page) { - return write_page(mtd, nand, buf, page, true); + return write_page(nand_to_mtd(nand), nand, buf, page, true); } -static int docg4_write_oob(struct mtd_info *mtd, struct nand_chip *nand, - int page) +static int docg4_write_oob(struct nand_chip *nand, int page) { /* * Writing oob-only is not really supported, because MLC nand must write @@ -1144,7 +1143,7 @@ static int docg4_block_markbad(struct mtd_info *mtd, loff_t ofs) /* write first page of block */ write_page_prologue(mtd, g4_addr); - docg4_write_page(mtd, nand, buf, 1, page); + docg4_write_page(nand, buf, 1, page); ret = pageprog(mtd); kfree(buf); diff --git a/drivers/mtd/nand/raw/fsl_elbc_nand.c b/drivers/mtd/nand/raw/fsl_elbc_nand.c index 26fcb8ea0c2e..c992d7ad39d9 100644 --- a/drivers/mtd/nand/raw/fsl_elbc_nand.c +++ b/drivers/mtd/nand/raw/fsl_elbc_nand.c @@ -731,9 +731,11 @@ static int fsl_elbc_read_page(struct nand_chip *chip, uint8_t *buf, /* ECC will be calculated automatically, and errors will be detected in * waitfunc. */ -static int fsl_elbc_write_page(struct mtd_info *mtd, struct nand_chip *chip, - const uint8_t *buf, int oob_required, int page) +static int fsl_elbc_write_page(struct nand_chip *chip, const uint8_t *buf, + int oob_required, int page) { + struct mtd_info *mtd = nand_to_mtd(chip); + nand_prog_page_begin_op(chip, page, 0, buf, mtd->writesize); fsl_elbc_write_buf(mtd, chip->oob_poi, mtd->oobsize); @@ -743,10 +745,12 @@ static int fsl_elbc_write_page(struct mtd_info *mtd, struct nand_chip *chip, /* ECC will be calculated automatically, and errors will be detected in * waitfunc. */ -static int fsl_elbc_write_subpage(struct mtd_info *mtd, struct nand_chip *chip, - uint32_t offset, uint32_t data_len, - const uint8_t *buf, int oob_required, int page) +static int fsl_elbc_write_subpage(struct nand_chip *chip, uint32_t offset, + uint32_t data_len, const uint8_t *buf, + int oob_required, int page) { + struct mtd_info *mtd = nand_to_mtd(chip); + nand_prog_page_begin_op(chip, page, 0, NULL, 0); fsl_elbc_write_buf(mtd, buf, mtd->writesize); fsl_elbc_write_buf(mtd, chip->oob_poi, mtd->oobsize); diff --git a/drivers/mtd/nand/raw/fsl_ifc_nand.c b/drivers/mtd/nand/raw/fsl_ifc_nand.c index 8c6016932aaa..945f3dab7ebf 100644 --- a/drivers/mtd/nand/raw/fsl_ifc_nand.c +++ b/drivers/mtd/nand/raw/fsl_ifc_nand.c @@ -707,9 +707,11 @@ static int fsl_ifc_read_page(struct nand_chip *chip, uint8_t *buf, /* ECC will be calculated automatically, and errors will be detected in * waitfunc. */ -static int fsl_ifc_write_page(struct mtd_info *mtd, struct nand_chip *chip, - const uint8_t *buf, int oob_required, int page) +static int fsl_ifc_write_page(struct nand_chip *chip, const uint8_t *buf, + int oob_required, int page) { + struct mtd_info *mtd = nand_to_mtd(chip); + nand_prog_page_begin_op(chip, page, 0, buf, mtd->writesize); fsl_ifc_write_buf(mtd, chip->oob_poi, mtd->oobsize); diff --git a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c index 5650ebf28903..09f33f6006a3 100644 --- a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c +++ b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c @@ -1182,9 +1182,10 @@ static int gpmi_ecc_read_subpage(struct nand_chip *chip, uint32_t offs, return max_bitflips; } -static int gpmi_ecc_write_page(struct mtd_info *mtd, struct nand_chip *chip, - const uint8_t *buf, int oob_required, int page) +static int gpmi_ecc_write_page(struct nand_chip *chip, const uint8_t *buf, + int oob_required, int page) { + struct mtd_info *mtd = nand_to_mtd(chip); struct gpmi_nand_data *this = nand_get_controller_data(chip); struct bch_geometry *nfc_geo = &this->bch_geometry; const void *payload_virt; @@ -1351,9 +1352,9 @@ static int gpmi_ecc_read_oob(struct nand_chip *chip, int page) return 0; } -static int -gpmi_ecc_write_oob(struct mtd_info *mtd, struct nand_chip *chip, int page) +static int gpmi_ecc_write_oob(struct nand_chip *chip, int page) { + struct mtd_info *mtd = nand_to_mtd(chip); struct mtd_oob_region of = { }; /* Do we have available oob area? */ @@ -1464,11 +1465,10 @@ static int gpmi_ecc_read_page_raw(struct nand_chip *chip, uint8_t *buf, * See set_geometry_by_ecc_info inline comments to have a full description * of the layout used by the GPMI controller. */ -static int gpmi_ecc_write_page_raw(struct mtd_info *mtd, - struct nand_chip *chip, - const uint8_t *buf, +static int gpmi_ecc_write_page_raw(struct nand_chip *chip, const uint8_t *buf, int oob_required, int page) { + struct mtd_info *mtd = nand_to_mtd(chip); struct gpmi_nand_data *this = nand_get_controller_data(chip); struct bch_geometry *nfc_geo = &this->bch_geometry; int eccsize = nfc_geo->ecc_chunk_size; @@ -1541,10 +1541,9 @@ static int gpmi_ecc_read_oob_raw(struct nand_chip *chip, int page) return gpmi_ecc_read_page_raw(chip, NULL, 1, page); } -static int gpmi_ecc_write_oob_raw(struct mtd_info *mtd, struct nand_chip *chip, - int page) +static int gpmi_ecc_write_oob_raw(struct nand_chip *chip, int page) { - return gpmi_ecc_write_page_raw(mtd, chip, NULL, 1, page); + return gpmi_ecc_write_page_raw(chip, NULL, 1, page); } static int gpmi_block_markbad(struct mtd_info *mtd, loff_t ofs) @@ -1715,7 +1714,7 @@ static int mx23_write_transcription_stamp(struct gpmi_nand_data *this) /* Write the first page of the current stride. */ dev_dbg(dev, "Writing an NCB fingerprint in page 0x%x\n", page); - status = chip->ecc.write_page_raw(mtd, chip, buffer, 0, page); + status = chip->ecc.write_page_raw(chip, buffer, 0, page); if (status) dev_err(dev, "[%s] Write failed.\n", __func__); } diff --git a/drivers/mtd/nand/raw/hisi504_nand.c b/drivers/mtd/nand/raw/hisi504_nand.c index f4078086c14c..fab3c7fcf77b 100644 --- a/drivers/mtd/nand/raw/hisi504_nand.c +++ b/drivers/mtd/nand/raw/hisi504_nand.c @@ -577,10 +577,12 @@ static int hisi_nand_read_oob(struct nand_chip *chip, int page) return 0; } -static int hisi_nand_write_page_hwecc(struct mtd_info *mtd, - struct nand_chip *chip, const uint8_t *buf, int oob_required, - int page) +static int hisi_nand_write_page_hwecc(struct nand_chip *chip, + const uint8_t *buf, int oob_required, + int page) { + struct mtd_info *mtd = nand_to_mtd(chip); + nand_prog_page_begin_op(chip, page, 0, buf, mtd->writesize); if (oob_required) chip->write_buf(mtd, chip->oob_poi, mtd->oobsize); diff --git a/drivers/mtd/nand/raw/lpc32xx_mlc.c b/drivers/mtd/nand/raw/lpc32xx_mlc.c index 1849e9858d45..79a02acb0517 100644 --- a/drivers/mtd/nand/raw/lpc32xx_mlc.c +++ b/drivers/mtd/nand/raw/lpc32xx_mlc.c @@ -508,11 +508,11 @@ static int lpc32xx_read_page(struct nand_chip *chip, uint8_t *buf, return 0; } -static int lpc32xx_write_page_lowlevel(struct mtd_info *mtd, - struct nand_chip *chip, +static int lpc32xx_write_page_lowlevel(struct nand_chip *chip, const uint8_t *buf, int oob_required, int page) { + struct mtd_info *mtd = nand_to_mtd(chip); struct lpc32xx_nand_host *host = nand_get_controller_data(chip); const uint8_t *oobbuf = chip->oob_poi; uint8_t *dma_buf = (uint8_t *)buf; @@ -568,8 +568,7 @@ static int lpc32xx_read_oob(struct nand_chip *chip, int page) return 0; } -static int lpc32xx_write_oob(struct mtd_info *mtd, struct nand_chip *chip, - int page) +static int lpc32xx_write_oob(struct nand_chip *chip, int page) { /* None, write_oob conflicts with the automatic LPC MLC ECC decoder! */ return 0; diff --git a/drivers/mtd/nand/raw/lpc32xx_slc.c b/drivers/mtd/nand/raw/lpc32xx_slc.c index a9cb089923be..6e4017ddacad 100644 --- a/drivers/mtd/nand/raw/lpc32xx_slc.c +++ b/drivers/mtd/nand/raw/lpc32xx_slc.c @@ -406,9 +406,10 @@ static int lpc32xx_nand_read_oob_syndrome(struct nand_chip *chip, int page) /* * Write the OOB data to the device without ECC using FIFO method */ -static int lpc32xx_nand_write_oob_syndrome(struct mtd_info *mtd, - struct nand_chip *chip, int page) +static int lpc32xx_nand_write_oob_syndrome(struct nand_chip *chip, int page) { + struct mtd_info *mtd = nand_to_mtd(chip); + return nand_prog_page_op(chip, page, mtd->writesize, chip->oob_poi, mtd->oobsize); } @@ -678,11 +679,11 @@ static int lpc32xx_nand_read_page_raw_syndrome(struct nand_chip *chip, * Write the data and OOB data to the device, use ECC with the data, * disable ECC for the OOB data */ -static int lpc32xx_nand_write_page_syndrome(struct mtd_info *mtd, - struct nand_chip *chip, +static int lpc32xx_nand_write_page_syndrome(struct nand_chip *chip, const uint8_t *buf, int oob_required, int page) { + struct mtd_info *mtd = nand_to_mtd(chip); struct lpc32xx_nand_host *host = nand_get_controller_data(chip); struct mtd_oob_region oobregion = { }; uint8_t *pb; @@ -716,11 +717,12 @@ static int lpc32xx_nand_write_page_syndrome(struct mtd_info *mtd, * Write the data and OOB data to the device, no ECC correction with the * data or OOB data */ -static int lpc32xx_nand_write_page_raw_syndrome(struct mtd_info *mtd, - struct nand_chip *chip, +static int lpc32xx_nand_write_page_raw_syndrome(struct nand_chip *chip, const uint8_t *buf, int oob_required, int page) { + struct mtd_info *mtd = nand_to_mtd(chip); + /* Raw writes can just use the FIFO interface */ nand_prog_page_begin_op(chip, page, 0, buf, chip->ecc.size * chip->ecc.steps); diff --git a/drivers/mtd/nand/raw/marvell_nand.c b/drivers/mtd/nand/raw/marvell_nand.c index a81018f3a2f4..5f5709c2e58e 100644 --- a/drivers/mtd/nand/raw/marvell_nand.c +++ b/drivers/mtd/nand/raw/marvell_nand.c @@ -1136,8 +1136,7 @@ static int marvell_nfc_hw_ecc_hmg_do_write_page(struct nand_chip *chip, return ret; } -static int marvell_nfc_hw_ecc_hmg_write_page_raw(struct mtd_info *mtd, - struct nand_chip *chip, +static int marvell_nfc_hw_ecc_hmg_write_page_raw(struct nand_chip *chip, const u8 *buf, int oob_required, int page) { @@ -1145,8 +1144,7 @@ static int marvell_nfc_hw_ecc_hmg_write_page_raw(struct mtd_info *mtd, true, page); } -static int marvell_nfc_hw_ecc_hmg_write_page(struct mtd_info *mtd, - struct nand_chip *chip, +static int marvell_nfc_hw_ecc_hmg_write_page(struct nand_chip *chip, const u8 *buf, int oob_required, int page) { @@ -1165,10 +1163,11 @@ static int marvell_nfc_hw_ecc_hmg_write_page(struct mtd_info *mtd, * it appears before the ECC bytes when reading), the ->write_oob_raw() function * also stands for ->write_oob(). */ -static int marvell_nfc_hw_ecc_hmg_write_oob_raw(struct mtd_info *mtd, - struct nand_chip *chip, +static int marvell_nfc_hw_ecc_hmg_write_oob_raw(struct nand_chip *chip, int page) { + struct mtd_info *mtd = nand_to_mtd(chip); + /* Invalidate page cache */ chip->pagebuf = -1; @@ -1405,8 +1404,7 @@ static int marvell_nfc_hw_ecc_bch_read_oob(struct nand_chip *chip, int page) } /* BCH write helpers */ -static int marvell_nfc_hw_ecc_bch_write_page_raw(struct mtd_info *mtd, - struct nand_chip *chip, +static int marvell_nfc_hw_ecc_bch_write_page_raw(struct nand_chip *chip, const u8 *buf, int oob_required, int page) { @@ -1519,11 +1517,11 @@ marvell_nfc_hw_ecc_bch_write_chunk(struct nand_chip *chip, int chunk, return 0; } -static int marvell_nfc_hw_ecc_bch_write_page(struct mtd_info *mtd, - struct nand_chip *chip, +static int marvell_nfc_hw_ecc_bch_write_page(struct nand_chip *chip, const u8 *buf, int oob_required, int page) { + struct mtd_info *mtd = nand_to_mtd(chip); const struct marvell_hw_ecc_layout *lt = to_marvell_nand(chip)->layout; const u8 *data = buf; const u8 *spare = chip->oob_poi; @@ -1568,27 +1566,29 @@ static int marvell_nfc_hw_ecc_bch_write_page(struct mtd_info *mtd, return 0; } -static int marvell_nfc_hw_ecc_bch_write_oob_raw(struct mtd_info *mtd, - struct nand_chip *chip, +static int marvell_nfc_hw_ecc_bch_write_oob_raw(struct nand_chip *chip, int page) { + struct mtd_info *mtd = nand_to_mtd(chip); + /* Invalidate page cache */ chip->pagebuf = -1; memset(chip->data_buf, 0xFF, mtd->writesize); - return chip->ecc.write_page_raw(mtd, chip, chip->data_buf, true, page); + return chip->ecc.write_page_raw(chip, chip->data_buf, true, page); } -static int marvell_nfc_hw_ecc_bch_write_oob(struct mtd_info *mtd, - struct nand_chip *chip, int page) +static int marvell_nfc_hw_ecc_bch_write_oob(struct nand_chip *chip, int page) { + struct mtd_info *mtd = nand_to_mtd(chip); + /* Invalidate page cache */ chip->pagebuf = -1; memset(chip->data_buf, 0xFF, mtd->writesize); - return chip->ecc.write_page(mtd, chip, chip->data_buf, true, page); + return chip->ecc.write_page(chip, chip->data_buf, true, page); } /* NAND framework ->exec_op() hooks and related helpers */ diff --git a/drivers/mtd/nand/raw/mtk_nand.c b/drivers/mtd/nand/raw/mtk_nand.c index 32d5b59eb879..c338a9646433 100644 --- a/drivers/mtd/nand/raw/mtk_nand.c +++ b/drivers/mtd/nand/raw/mtk_nand.c @@ -807,27 +807,27 @@ static int mtk_nfc_write_page(struct mtd_info *mtd, struct nand_chip *chip, return nand_prog_page_end_op(chip); } -static int mtk_nfc_write_page_hwecc(struct mtd_info *mtd, - struct nand_chip *chip, const u8 *buf, +static int mtk_nfc_write_page_hwecc(struct nand_chip *chip, const u8 *buf, int oob_on, int page) { - return mtk_nfc_write_page(mtd, chip, buf, page, 0); + return mtk_nfc_write_page(nand_to_mtd(chip), chip, buf, page, 0); } -static int mtk_nfc_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip, - const u8 *buf, int oob_on, int pg) +static int mtk_nfc_write_page_raw(struct nand_chip *chip, const u8 *buf, + int oob_on, int pg) { + struct mtd_info *mtd = nand_to_mtd(chip); struct mtk_nfc *nfc = nand_get_controller_data(chip); mtk_nfc_format_page(mtd, buf); return mtk_nfc_write_page(mtd, chip, nfc->buffer, pg, 1); } -static int mtk_nfc_write_subpage_hwecc(struct mtd_info *mtd, - struct nand_chip *chip, u32 offset, +static int mtk_nfc_write_subpage_hwecc(struct nand_chip *chip, u32 offset, u32 data_len, const u8 *buf, int oob_on, int page) { + struct mtd_info *mtd = nand_to_mtd(chip); struct mtk_nfc *nfc = nand_get_controller_data(chip); int ret; @@ -839,10 +839,9 @@ static int mtk_nfc_write_subpage_hwecc(struct mtd_info *mtd, return mtk_nfc_write_page(mtd, chip, nfc->buffer, page, 1); } -static int mtk_nfc_write_oob_std(struct mtd_info *mtd, struct nand_chip *chip, - int page) +static int mtk_nfc_write_oob_std(struct nand_chip *chip, int page) { - return mtk_nfc_write_page_raw(mtd, chip, NULL, 1, page); + return mtk_nfc_write_page_raw(chip, NULL, 1, page); } static int mtk_nfc_update_ecc_stats(struct mtd_info *mtd, u8 *buf, u32 sectors) diff --git a/drivers/mtd/nand/raw/mxc_nand.c b/drivers/mtd/nand/raw/mxc_nand.c index 35fcec595c3e..597c74ea7e5e 100644 --- a/drivers/mtd/nand/raw/mxc_nand.c +++ b/drivers/mtd/nand/raw/mxc_nand.c @@ -873,22 +873,21 @@ static int mxc_nand_write_page(struct nand_chip *chip, const uint8_t *buf, return 0; } -static int mxc_nand_write_page_ecc(struct mtd_info *mtd, struct nand_chip *chip, - const uint8_t *buf, int oob_required, - int page) +static int mxc_nand_write_page_ecc(struct nand_chip *chip, const uint8_t *buf, + int oob_required, int page) { return mxc_nand_write_page(chip, buf, true, page); } -static int mxc_nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip, - const uint8_t *buf, int oob_required, int page) +static int mxc_nand_write_page_raw(struct nand_chip *chip, const uint8_t *buf, + int oob_required, int page) { return mxc_nand_write_page(chip, buf, false, page); } -static int mxc_nand_write_oob(struct mtd_info *mtd, struct nand_chip *chip, - int page) +static int mxc_nand_write_oob(struct nand_chip *chip, int page) { + struct mtd_info *mtd = nand_to_mtd(chip); struct mxc_nand_host *host = nand_get_controller_data(chip); memset(host->data_buf, 0xff, mtd->writesize); diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c index e1f60c841348..cc386ee64a1b 100644 --- a/drivers/mtd/nand/raw/nand_base.c +++ b/drivers/mtd/nand/raw/nand_base.c @@ -3787,12 +3787,13 @@ EXPORT_SYMBOL(nand_read_oob_syndrome); /** * nand_write_oob_std - [REPLACEABLE] the most common OOB data write function - * @mtd: mtd info structure * @chip: nand chip info structure * @page: page number to write */ -int nand_write_oob_std(struct mtd_info *mtd, struct nand_chip *chip, int page) +int nand_write_oob_std(struct nand_chip *chip, int page) { + struct mtd_info *mtd = nand_to_mtd(chip); + return nand_prog_page_op(chip, page, mtd->writesize, chip->oob_poi, mtd->oobsize); } @@ -3801,13 +3802,12 @@ EXPORT_SYMBOL(nand_write_oob_std); /** * nand_write_oob_syndrome - [REPLACEABLE] OOB data write function for HW ECC * with syndrome - only for large page flash - * @mtd: mtd info structure * @chip: nand chip info structure * @page: page number to write */ -int nand_write_oob_syndrome(struct mtd_info *mtd, struct nand_chip *chip, - int page) +int nand_write_oob_syndrome(struct nand_chip *chip, int page) { + struct mtd_info *mtd = nand_to_mtd(chip); int chunk = chip->ecc.bytes + chip->ecc.prepad + chip->ecc.postpad; int eccsize = chip->ecc.size, length = mtd->oobsize; int ret, i, len, pos, sndcmd = 0, steps = chip->ecc.steps; @@ -3984,7 +3984,6 @@ static int nand_read_oob(struct mtd_info *mtd, loff_t from, /** * nand_write_page_raw_notsupp - dummy raw page write function - * @mtd: mtd info structure * @chip: nand chip info structure * @buf: data buffer * @oob_required: must write chip->oob_poi to OOB @@ -3992,8 +3991,8 @@ static int nand_read_oob(struct mtd_info *mtd, loff_t from, * * Returns -ENOTSUPP unconditionally. */ -int nand_write_page_raw_notsupp(struct mtd_info *mtd, struct nand_chip *chip, - const u8 *buf, int oob_required, int page) +int nand_write_page_raw_notsupp(struct nand_chip *chip, const u8 *buf, + int oob_required, int page) { return -ENOTSUPP; } @@ -4001,7 +4000,6 @@ EXPORT_SYMBOL(nand_write_page_raw_notsupp); /** * nand_write_page_raw - [INTERN] raw page write function - * @mtd: mtd info structure * @chip: nand chip info structure * @buf: data buffer * @oob_required: must write chip->oob_poi to OOB @@ -4009,9 +4007,10 @@ EXPORT_SYMBOL(nand_write_page_raw_notsupp); * * Not for syndrome calculating ECC controllers, which use a special oob layout. */ -int nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip, - const uint8_t *buf, int oob_required, int page) +int nand_write_page_raw(struct nand_chip *chip, const uint8_t *buf, + int oob_required, int page) { + struct mtd_info *mtd = nand_to_mtd(chip); int ret; ret = nand_prog_page_begin_op(chip, page, 0, buf, mtd->writesize); @@ -4031,7 +4030,6 @@ EXPORT_SYMBOL(nand_write_page_raw); /** * nand_write_page_raw_syndrome - [INTERN] raw page write function - * @mtd: mtd info structure * @chip: nand chip info structure * @buf: data buffer * @oob_required: must write chip->oob_poi to OOB @@ -4039,11 +4037,11 @@ EXPORT_SYMBOL(nand_write_page_raw); * * We need a special oob layout and handling even when ECC isn't checked. */ -static int nand_write_page_raw_syndrome(struct mtd_info *mtd, - struct nand_chip *chip, +static int nand_write_page_raw_syndrome(struct nand_chip *chip, const uint8_t *buf, int oob_required, int page) { + struct mtd_info *mtd = nand_to_mtd(chip); int eccsize = chip->ecc.size; int eccbytes = chip->ecc.bytes; uint8_t *oob = chip->oob_poi; @@ -4096,16 +4094,15 @@ static int nand_write_page_raw_syndrome(struct mtd_info *mtd, } /** * nand_write_page_swecc - [REPLACEABLE] software ECC based page write function - * @mtd: mtd info structure * @chip: nand chip info structure * @buf: data buffer * @oob_required: must write chip->oob_poi to OOB * @page: page number to write */ -static int nand_write_page_swecc(struct mtd_info *mtd, struct nand_chip *chip, - const uint8_t *buf, int oob_required, - int page) +static int nand_write_page_swecc(struct nand_chip *chip, const uint8_t *buf, + int oob_required, int page) { + struct mtd_info *mtd = nand_to_mtd(chip); int i, eccsize = chip->ecc.size, ret; int eccbytes = chip->ecc.bytes; int eccsteps = chip->ecc.steps; @@ -4121,21 +4118,20 @@ static int nand_write_page_swecc(struct mtd_info *mtd, struct nand_chip *chip, if (ret) return ret; - return chip->ecc.write_page_raw(mtd, chip, buf, 1, page); + return chip->ecc.write_page_raw(chip, buf, 1, page); } /** * nand_write_page_hwecc - [REPLACEABLE] hardware ECC based page write function - * @mtd: mtd info structure * @chip: nand chip info structure * @buf: data buffer * @oob_required: must write chip->oob_poi to OOB * @page: page number to write */ -static int nand_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, - const uint8_t *buf, int oob_required, - int page) +static int nand_write_page_hwecc(struct nand_chip *chip, const uint8_t *buf, + int oob_required, int page) { + struct mtd_info *mtd = nand_to_mtd(chip); int i, eccsize = chip->ecc.size, ret; int eccbytes = chip->ecc.bytes; int eccsteps = chip->ecc.steps; @@ -4171,7 +4167,6 @@ static int nand_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, /** * nand_write_subpage_hwecc - [REPLACEABLE] hardware ECC based subpage write - * @mtd: mtd info structure * @chip: nand chip info structure * @offset: column address of subpage within the page * @data_len: data length @@ -4179,11 +4174,11 @@ static int nand_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, * @oob_required: must write chip->oob_poi to OOB * @page: page number to write */ -static int nand_write_subpage_hwecc(struct mtd_info *mtd, - struct nand_chip *chip, uint32_t offset, - uint32_t data_len, const uint8_t *buf, - int oob_required, int page) +static int nand_write_subpage_hwecc(struct nand_chip *chip, uint32_t offset, + uint32_t data_len, const uint8_t *buf, + int oob_required, int page) { + struct mtd_info *mtd = nand_to_mtd(chip); uint8_t *oob_buf = chip->oob_poi; uint8_t *ecc_calc = chip->ecc.calc_buf; int ecc_size = chip->ecc.size; @@ -4242,7 +4237,6 @@ static int nand_write_subpage_hwecc(struct mtd_info *mtd, /** * nand_write_page_syndrome - [REPLACEABLE] hardware ECC syndrome based page write - * @mtd: mtd info structure * @chip: nand chip info structure * @buf: data buffer * @oob_required: must write chip->oob_poi to OOB @@ -4251,11 +4245,10 @@ static int nand_write_subpage_hwecc(struct mtd_info *mtd, * The hw generator calculates the error syndrome automatically. Therefore we * need a special oob layout and handling. */ -static int nand_write_page_syndrome(struct mtd_info *mtd, - struct nand_chip *chip, - const uint8_t *buf, int oob_required, - int page) +static int nand_write_page_syndrome(struct nand_chip *chip, const uint8_t *buf, + int oob_required, int page) { + struct mtd_info *mtd = nand_to_mtd(chip); int i, eccsize = chip->ecc.size; int eccbytes = chip->ecc.bytes; int eccsteps = chip->ecc.steps; @@ -4336,14 +4329,13 @@ static int nand_write_page(struct mtd_info *mtd, struct nand_chip *chip, subpage = 0; if (unlikely(raw)) - status = chip->ecc.write_page_raw(mtd, chip, buf, - oob_required, page); + status = chip->ecc.write_page_raw(chip, buf, oob_required, + page); else if (subpage) - status = chip->ecc.write_subpage(mtd, chip, offset, data_len, - buf, oob_required, page); + status = chip->ecc.write_subpage(chip, offset, data_len, buf, + oob_required, page); else - status = chip->ecc.write_page(mtd, chip, buf, oob_required, - page); + status = chip->ecc.write_page(chip, buf, oob_required, page); if (status < 0) return status; @@ -4610,9 +4602,9 @@ static int nand_do_write_oob(struct mtd_info *mtd, loff_t to, nand_fill_oob(mtd, ops->oobbuf, ops->ooblen, ops); if (ops->mode == MTD_OPS_RAW) - status = chip->ecc.write_oob_raw(mtd, chip, page & chip->pagemask); + status = chip->ecc.write_oob_raw(chip, page & chip->pagemask); else - status = chip->ecc.write_oob(mtd, chip, page & chip->pagemask); + status = chip->ecc.write_oob(chip, page & chip->pagemask); chip->select_chip(mtd, -1); diff --git a/drivers/mtd/nand/raw/nand_ecc.c b/drivers/mtd/nand/raw/nand_ecc.c index 8f86eed40b70..93df8e73f577 100644 --- a/drivers/mtd/nand/raw/nand_ecc.c +++ b/drivers/mtd/nand/raw/nand_ecc.c @@ -394,7 +394,7 @@ EXPORT_SYMBOL(__nand_calculate_ecc); /** * nand_calculate_ecc - [NAND Interface] Calculate 3-byte ECC for 256/512-byte * block - * @mtd: MTD block structure + * @chip: NAND chip object * @buf: input buffer with raw data * @code: output buffer with ECC */ diff --git a/drivers/mtd/nand/raw/nand_micron.c b/drivers/mtd/nand/raw/nand_micron.c index d83a86ba9d09..2f26dbeb5428 100644 --- a/drivers/mtd/nand/raw/nand_micron.c +++ b/drivers/mtd/nand/raw/nand_micron.c @@ -332,9 +332,8 @@ micron_nand_read_page_on_die_ecc(struct nand_chip *chip, uint8_t *buf, } static int -micron_nand_write_page_on_die_ecc(struct mtd_info *mtd, struct nand_chip *chip, - const uint8_t *buf, int oob_required, - int page) +micron_nand_write_page_on_die_ecc(struct nand_chip *chip, const uint8_t *buf, + int oob_required, int page) { int ret; @@ -342,7 +341,7 @@ micron_nand_write_page_on_die_ecc(struct mtd_info *mtd, struct nand_chip *chip, if (ret) return ret; - ret = nand_write_page_raw(mtd, chip, buf, oob_required, page); + ret = nand_write_page_raw(chip, buf, oob_required, page); micron_nand_on_die_ecc_setup(chip, false); return ret; diff --git a/drivers/mtd/nand/raw/omap2.c b/drivers/mtd/nand/raw/omap2.c index dfe96098f3f6..f1f8b6c1d654 100644 --- a/drivers/mtd/nand/raw/omap2.c +++ b/drivers/mtd/nand/raw/omap2.c @@ -1511,7 +1511,6 @@ static int omap_elm_correct_data(struct nand_chip *chip, u_char *data, /** * omap_write_page_bch - BCH ecc based write page function for entire page - * @mtd: mtd info structure * @chip: nand chip info structure * @buf: data buffer * @oob_required: must write chip->oob_poi to OOB @@ -1519,9 +1518,10 @@ static int omap_elm_correct_data(struct nand_chip *chip, u_char *data, * * Custom write page method evolved to support multi sector writing in one shot */ -static int omap_write_page_bch(struct mtd_info *mtd, struct nand_chip *chip, - const uint8_t *buf, int oob_required, int page) +static int omap_write_page_bch(struct nand_chip *chip, const uint8_t *buf, + int oob_required, int page) { + struct mtd_info *mtd = nand_to_mtd(chip); int ret; uint8_t *ecc_calc = chip->ecc.calc_buf; @@ -1549,7 +1549,6 @@ static int omap_write_page_bch(struct mtd_info *mtd, struct nand_chip *chip, /** * omap_write_subpage_bch - BCH hardware ECC based subpage write - * @mtd: mtd info structure * @chip: nand chip info structure * @offset: column address of subpage within the page * @data_len: data length @@ -1559,11 +1558,11 @@ static int omap_write_page_bch(struct mtd_info *mtd, struct nand_chip *chip, * * OMAP optimized subpage write method. */ -static int omap_write_subpage_bch(struct mtd_info *mtd, - struct nand_chip *chip, u32 offset, +static int omap_write_subpage_bch(struct nand_chip *chip, u32 offset, u32 data_len, const u8 *buf, int oob_required, int page) { + struct mtd_info *mtd = nand_to_mtd(chip); u8 *ecc_calc = chip->ecc.calc_buf; int ecc_size = chip->ecc.size; int ecc_bytes = chip->ecc.bytes; diff --git a/drivers/mtd/nand/raw/qcom_nandc.c b/drivers/mtd/nand/raw/qcom_nandc.c index 49113d4cee10..e0cec027572c 100644 --- a/drivers/mtd/nand/raw/qcom_nandc.c +++ b/drivers/mtd/nand/raw/qcom_nandc.c @@ -2005,8 +2005,8 @@ static int qcom_nandc_read_oob(struct nand_chip *chip, int page) } /* implements ecc->write_page() */ -static int qcom_nandc_write_page(struct mtd_info *mtd, struct nand_chip *chip, - const uint8_t *buf, int oob_required, int page) +static int qcom_nandc_write_page(struct nand_chip *chip, const uint8_t *buf, + int oob_required, int page) { struct qcom_nand_host *host = to_qcom_nand_host(chip); struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip); @@ -2075,10 +2075,11 @@ static int qcom_nandc_write_page(struct mtd_info *mtd, struct nand_chip *chip, } /* implements ecc->write_page_raw() */ -static int qcom_nandc_write_page_raw(struct mtd_info *mtd, - struct nand_chip *chip, const uint8_t *buf, - int oob_required, int page) +static int qcom_nandc_write_page_raw(struct nand_chip *chip, + const uint8_t *buf, int oob_required, + int page) { + struct mtd_info *mtd = nand_to_mtd(chip); struct qcom_nand_host *host = to_qcom_nand_host(chip); struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip); struct nand_ecc_ctrl *ecc = &chip->ecc; @@ -2153,9 +2154,9 @@ static int qcom_nandc_write_page_raw(struct mtd_info *mtd, * since ECC is calculated for the combined codeword. So update the OOB from * chip->oob_poi, and pad the data area with OxFF before writing. */ -static int qcom_nandc_write_oob(struct mtd_info *mtd, struct nand_chip *chip, - int page) +static int qcom_nandc_write_oob(struct nand_chip *chip, int page) { + struct mtd_info *mtd = nand_to_mtd(chip); struct qcom_nand_host *host = to_qcom_nand_host(chip); struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip); struct nand_ecc_ctrl *ecc = &chip->ecc; diff --git a/drivers/mtd/nand/raw/sh_flctl.c b/drivers/mtd/nand/raw/sh_flctl.c index fb5df6099d7b..bb58edd2bdf0 100644 --- a/drivers/mtd/nand/raw/sh_flctl.c +++ b/drivers/mtd/nand/raw/sh_flctl.c @@ -622,10 +622,11 @@ static int flctl_read_page_hwecc(struct nand_chip *chip, uint8_t *buf, return 0; } -static int flctl_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, - const uint8_t *buf, int oob_required, - int page) +static int flctl_write_page_hwecc(struct nand_chip *chip, const uint8_t *buf, + int oob_required, int page) { + struct mtd_info *mtd = nand_to_mtd(chip); + nand_prog_page_begin_op(chip, page, 0, buf, mtd->writesize); chip->write_buf(mtd, chip->oob_poi, mtd->oobsize); return nand_prog_page_end_op(chip); diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c index 26d5c6c41c49..86d666c0c03c 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -1297,11 +1297,11 @@ static int sunxi_nfc_hw_ecc_read_subpage_dma(struct nand_chip *chip, buf, page); } -static int sunxi_nfc_hw_ecc_write_page(struct mtd_info *mtd, - struct nand_chip *chip, +static int sunxi_nfc_hw_ecc_write_page(struct nand_chip *chip, const uint8_t *buf, int oob_required, int page) { + struct mtd_info *mtd = nand_to_mtd(chip); struct nand_ecc_ctrl *ecc = &chip->ecc; int ret, i, cur_off = 0; @@ -1331,12 +1331,12 @@ static int sunxi_nfc_hw_ecc_write_page(struct mtd_info *mtd, return nand_prog_page_end_op(chip); } -static int sunxi_nfc_hw_ecc_write_subpage(struct mtd_info *mtd, - struct nand_chip *chip, +static int sunxi_nfc_hw_ecc_write_subpage(struct nand_chip *chip, u32 data_offs, u32 data_len, const u8 *buf, int oob_required, int page) { + struct mtd_info *mtd = nand_to_mtd(chip); struct nand_ecc_ctrl *ecc = &chip->ecc; int ret, i, cur_off = 0; @@ -1363,12 +1363,12 @@ static int sunxi_nfc_hw_ecc_write_subpage(struct mtd_info *mtd, return nand_prog_page_end_op(chip); } -static int sunxi_nfc_hw_ecc_write_page_dma(struct mtd_info *mtd, - struct nand_chip *chip, +static int sunxi_nfc_hw_ecc_write_page_dma(struct nand_chip *chip, const u8 *buf, int oob_required, int page) { + struct mtd_info *mtd = nand_to_mtd(chip); struct nand_chip *nand = mtd_to_nand(mtd); struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); struct nand_ecc_ctrl *ecc = &nand->ecc; @@ -1425,7 +1425,7 @@ static int sunxi_nfc_hw_ecc_write_page_dma(struct mtd_info *mtd, return nand_prog_page_end_op(chip); pio_fallback: - return sunxi_nfc_hw_ecc_write_page(mtd, chip, buf, oob_required, page); + return sunxi_nfc_hw_ecc_write_page(chip, buf, oob_required, page); } static int sunxi_nfc_hw_ecc_read_oob(struct nand_chip *chip, int page) @@ -1435,16 +1435,15 @@ static int sunxi_nfc_hw_ecc_read_oob(struct nand_chip *chip, int page) return chip->ecc.read_page(chip, chip->data_buf, 1, page); } -static int sunxi_nfc_hw_ecc_write_oob(struct mtd_info *mtd, - struct nand_chip *chip, - int page) +static int sunxi_nfc_hw_ecc_write_oob(struct nand_chip *chip, int page) { + struct mtd_info *mtd = nand_to_mtd(chip); int ret; chip->pagebuf = -1; memset(chip->data_buf, 0xff, mtd->writesize); - ret = chip->ecc.write_page(mtd, chip, chip->data_buf, 1, page); + ret = chip->ecc.write_page(chip, chip->data_buf, 1, page); if (ret) return ret; diff --git a/drivers/mtd/nand/raw/tango_nand.c b/drivers/mtd/nand/raw/tango_nand.c index c53d47159195..7c8f47546002 100644 --- a/drivers/mtd/nand/raw/tango_nand.c +++ b/drivers/mtd/nand/raw/tango_nand.c @@ -300,9 +300,10 @@ static int tango_read_page(struct nand_chip *chip, u8 *buf, return res; } -static int tango_write_page(struct mtd_info *mtd, struct nand_chip *chip, - const u8 *buf, int oob_required, int page) +static int tango_write_page(struct nand_chip *chip, const u8 *buf, + int oob_required, int page) { + struct mtd_info *mtd = nand_to_mtd(chip); struct tango_nfc *nfc = to_tango_nfc(chip->controller); int err, status, len = mtd->writesize; @@ -433,8 +434,8 @@ static int tango_read_page_raw(struct nand_chip *chip, u8 *buf, return 0; } -static int tango_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip, - const u8 *buf, int oob_required, int page) +static int tango_write_page_raw(struct nand_chip *chip, const u8 *buf, + int oob_required, int page) { nand_prog_page_begin_op(chip, page, 0, NULL, 0); raw_write(chip, buf, chip->oob_poi); @@ -448,8 +449,7 @@ static int tango_read_oob(struct nand_chip *chip, int page) return 0; } -static int tango_write_oob(struct mtd_info *mtd, struct nand_chip *chip, - int page) +static int tango_write_oob(struct nand_chip *chip, int page) { nand_prog_page_begin_op(chip, page, 0, NULL, 0); raw_write(chip, NULL, chip->oob_poi); diff --git a/drivers/mtd/nand/raw/tegra_nand.c b/drivers/mtd/nand/raw/tegra_nand.c index bcc3a2888c4f..df8e78814a08 100644 --- a/drivers/mtd/nand/raw/tegra_nand.c +++ b/drivers/mtd/nand/raw/tegra_nand.c @@ -625,10 +625,10 @@ static int tegra_nand_read_page_raw(struct nand_chip *chip, u8 *buf, mtd->oobsize, page, true); } -static int tegra_nand_write_page_raw(struct mtd_info *mtd, - struct nand_chip *chip, const u8 *buf, +static int tegra_nand_write_page_raw(struct nand_chip *chip, const u8 *buf, int oob_required, int page) { + struct mtd_info *mtd = nand_to_mtd(chip); void *oob_buf = oob_required ? chip->oob_poi : NULL; return tegra_nand_page_xfer(mtd, chip, (void *)buf, oob_buf, @@ -643,9 +643,10 @@ static int tegra_nand_read_oob(struct nand_chip *chip, int page) mtd->oobsize, page, true); } -static int tegra_nand_write_oob(struct mtd_info *mtd, struct nand_chip *chip, - int page) +static int tegra_nand_write_oob(struct nand_chip *chip, int page) { + struct mtd_info *mtd = nand_to_mtd(chip); + return tegra_nand_page_xfer(mtd, chip, NULL, chip->oob_poi, mtd->oobsize, page, false); } @@ -760,10 +761,10 @@ static int tegra_nand_read_page_hwecc(struct nand_chip *chip, u8 *buf, } } -static int tegra_nand_write_page_hwecc(struct mtd_info *mtd, - struct nand_chip *chip, const u8 *buf, +static int tegra_nand_write_page_hwecc(struct nand_chip *chip, const u8 *buf, int oob_required, int page) { + struct mtd_info *mtd = nand_to_mtd(chip); struct tegra_nand_controller *ctrl = to_tegra_ctrl(chip->controller); void *oob_buf = oob_required ? chip->oob_poi : NULL; int ret; diff --git a/drivers/mtd/nand/raw/vf610_nfc.c b/drivers/mtd/nand/raw/vf610_nfc.c index 7cbcc41cea95..bce6f6769cd6 100644 --- a/drivers/mtd/nand/raw/vf610_nfc.c +++ b/drivers/mtd/nand/raw/vf610_nfc.c @@ -603,9 +603,10 @@ static int vf610_nfc_read_page(struct nand_chip *chip, uint8_t *buf, } } -static int vf610_nfc_write_page(struct mtd_info *mtd, struct nand_chip *chip, - const uint8_t *buf, int oob_required, int page) +static int vf610_nfc_write_page(struct nand_chip *chip, const uint8_t *buf, + int oob_required, int page) { + struct mtd_info *mtd = nand_to_mtd(chip); struct vf610_nfc *nfc = mtd_to_nfc(mtd); int trfr_sz = mtd->writesize + mtd->oobsize; u32 row = 0, cmd1 = 0, cmd2 = 0, code = 0; @@ -658,10 +659,10 @@ static int vf610_nfc_read_page_raw(struct nand_chip *chip, u8 *buf, return ret; } -static int vf610_nfc_write_page_raw(struct mtd_info *mtd, - struct nand_chip *chip, const u8 *buf, +static int vf610_nfc_write_page_raw(struct nand_chip *chip, const u8 *buf, int oob_required, int page) { + struct mtd_info *mtd = nand_to_mtd(chip); struct vf610_nfc *nfc = mtd_to_nfc(mtd); int ret; @@ -690,9 +691,9 @@ static int vf610_nfc_read_oob(struct nand_chip *chip, int page) return ret; } -static int vf610_nfc_write_oob(struct mtd_info *mtd, struct nand_chip *chip, - int page) +static int vf610_nfc_write_oob(struct nand_chip *chip, int page) { + struct mtd_info *mtd = nand_to_mtd(chip); struct vf610_nfc *nfc = mtd_to_nfc(mtd); int ret; diff --git a/drivers/staging/mt29f_spinand/mt29f_spinand.c b/drivers/staging/mt29f_spinand/mt29f_spinand.c index 0776d38d4498..2b2f98efdb54 100644 --- a/drivers/staging/mt29f_spinand/mt29f_spinand.c +++ b/drivers/staging/mt29f_spinand/mt29f_spinand.c @@ -630,8 +630,7 @@ static int spinand_erase_block(struct spi_device *spi_nand, u16 block_id) } #ifdef CONFIG_MTD_SPINAND_ONDIEECC -static int spinand_write_page_hwecc(struct mtd_info *mtd, - struct nand_chip *chip, +static int spinand_write_page_hwecc(struct nand_chip *chip, const u8 *buf, int oob_required, int page) { diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h index a5f4a585f749..527947e81447 100644 --- a/include/linux/mtd/rawnand.h +++ b/include/linux/mtd/rawnand.h @@ -654,23 +654,21 @@ struct nand_ecc_ctrl { uint8_t *calc_ecc); int (*read_page_raw)(struct nand_chip *chip, uint8_t *buf, int oob_required, int page); - int (*write_page_raw)(struct mtd_info *mtd, struct nand_chip *chip, - const uint8_t *buf, int oob_required, int page); + int (*write_page_raw)(struct nand_chip *chip, const uint8_t *buf, + int oob_required, int page); int (*read_page)(struct nand_chip *chip, uint8_t *buf, int oob_required, int page); int (*read_subpage)(struct nand_chip *chip, uint32_t offs, uint32_t len, uint8_t *buf, int page); - int (*write_subpage)(struct mtd_info *mtd, struct nand_chip *chip, - uint32_t offset, uint32_t data_len, - const uint8_t *data_buf, int oob_required, int page); - int (*write_page)(struct mtd_info *mtd, struct nand_chip *chip, - const uint8_t *buf, int oob_required, int page); - int (*write_oob_raw)(struct mtd_info *mtd, struct nand_chip *chip, - int page); + int (*write_subpage)(struct nand_chip *chip, uint32_t offset, + uint32_t data_len, const uint8_t *data_buf, + int oob_required, int page); + int (*write_page)(struct nand_chip *chip, const uint8_t *buf, + int oob_required, int page); + int (*write_oob_raw)(struct nand_chip *chip, int page); int (*read_oob_raw)(struct nand_chip *chip, int page); int (*read_oob)(struct nand_chip *chip, int page); - int (*write_oob)(struct mtd_info *mtd, struct nand_chip *chip, - int page); + int (*write_oob)(struct nand_chip *chip, int page); }; /** @@ -1668,11 +1666,10 @@ int nand_ecc_choose_conf(struct nand_chip *chip, const struct nand_ecc_caps *caps, int oobavail); /* Default write_oob implementation */ -int nand_write_oob_std(struct mtd_info *mtd, struct nand_chip *chip, int page); +int nand_write_oob_std(struct nand_chip *chip, int page); /* Default write_oob syndrome implementation */ -int nand_write_oob_syndrome(struct mtd_info *mtd, struct nand_chip *chip, - int page); +int nand_write_oob_syndrome(struct nand_chip *chip, int page); /* Default read_oob implementation */ int nand_read_oob_std(struct nand_chip *chip, int page); @@ -1694,10 +1691,10 @@ int nand_read_page_raw_notsupp(struct nand_chip *chip, u8 *buf, int oob_required, int page); /* Default write_page_raw implementation */ -int nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip, - const uint8_t *buf, int oob_required, int page); -int nand_write_page_raw_notsupp(struct mtd_info *mtd, struct nand_chip *chip, - const u8 *buf, int oob_required, int page); +int nand_write_page_raw(struct nand_chip *chip, const uint8_t *buf, + int oob_required, int page); +int nand_write_page_raw_notsupp(struct nand_chip *chip, const u8 *buf, + int oob_required, int page); /* Reset and initialize a NAND device */ int nand_reset(struct nand_chip *chip, int chipnr); From 7e534323c416216e8ac45b5633fb0a5e5137e5b5 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Thu, 6 Sep 2018 14:05:22 +0200 Subject: [PATCH 250/302] mtd: rawnand: Pass a nand_chip object to chip->read_xxx() hooks Let's make the raw NAND API consistent by patching all helpers and hooks to take a nand_chip object instead of an mtd_info one or remove the mtd_info object when both are passed. Let's tackle all chip->read_xxx() hooks at once. Signed-off-by: Boris Brezillon Signed-off-by: Miquel Raynal --- drivers/mtd/nand/raw/ams-delta.c | 7 ++-- drivers/mtd/nand/raw/atmel/nand-controller.c | 10 ++--- drivers/mtd/nand/raw/au1550nd.c | 15 +++---- .../mtd/nand/raw/bcm47xxnflash/ops_bcm4706.c | 10 ++--- drivers/mtd/nand/raw/brcmnand/brcmnand.c | 7 ++-- drivers/mtd/nand/raw/cafe_nand.c | 10 ++--- drivers/mtd/nand/raw/cmx270_nand.c | 7 +--- drivers/mtd/nand/raw/cs553x_nand.c | 7 +--- drivers/mtd/nand/raw/davinci_nand.c | 5 +-- drivers/mtd/nand/raw/denali.c | 11 ++--- drivers/mtd/nand/raw/diskonchip.c | 32 ++++++--------- drivers/mtd/nand/raw/docg4.c | 13 +++--- drivers/mtd/nand/raw/fsl_elbc_nand.c | 8 ++-- drivers/mtd/nand/raw/fsl_ifc_nand.c | 13 +++--- drivers/mtd/nand/raw/fsl_upm.c | 8 ++-- drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c | 16 ++++---- drivers/mtd/nand/raw/hisi504_nand.c | 8 ++-- drivers/mtd/nand/raw/lpc32xx_slc.c | 12 +++--- drivers/mtd/nand/raw/mpc5121_nfc.c | 8 ++-- drivers/mtd/nand/raw/mtk_nand.c | 7 ++-- drivers/mtd/nand/raw/mxc_nand.c | 10 ++--- drivers/mtd/nand/raw/nand_base.c | 41 ++++++++----------- drivers/mtd/nand/raw/nandsim.c | 8 ++-- drivers/mtd/nand/raw/ndfc.c | 3 +- drivers/mtd/nand/raw/nuc900_nand.c | 8 ++-- drivers/mtd/nand/raw/omap2.c | 24 +++++++---- drivers/mtd/nand/raw/orion_nand.c | 3 +- drivers/mtd/nand/raw/oxnas_nand.c | 6 +-- drivers/mtd/nand/raw/pasemi_nand.c | 4 +- drivers/mtd/nand/raw/plat_nand.c | 11 +---- drivers/mtd/nand/raw/qcom_nandc.c | 6 +-- drivers/mtd/nand/raw/r852.c | 8 ++-- drivers/mtd/nand/raw/s3c2410.c | 6 +-- drivers/mtd/nand/raw/sh_flctl.c | 10 ++--- drivers/mtd/nand/raw/socrates_nand.c | 10 ++--- drivers/mtd/nand/raw/sunxi_nand.c | 11 +++-- drivers/mtd/nand/raw/tango_nand.c | 12 +++--- drivers/mtd/nand/raw/tmio_nand.c | 8 ++-- drivers/mtd/nand/raw/txx9ndfmc.c | 8 ++-- drivers/mtd/nand/raw/xway_nand.c | 8 ++-- drivers/staging/mt29f_spinand/mt29f_spinand.c | 10 ++--- include/linux/mtd/rawnand.h | 4 +- 42 files changed, 186 insertions(+), 247 deletions(-) diff --git a/drivers/mtd/nand/raw/ams-delta.c b/drivers/mtd/nand/raw/ams-delta.c index acf7971e815d..eb48c939c4ae 100644 --- a/drivers/mtd/nand/raw/ams-delta.c +++ b/drivers/mtd/nand/raw/ams-delta.c @@ -75,10 +75,9 @@ static void ams_delta_write_byte(struct mtd_info *mtd, u_char byte) gpio_set_value(AMS_DELTA_GPIO_PIN_NAND_NWE, 1); } -static u_char ams_delta_read_byte(struct mtd_info *mtd) +static u_char ams_delta_read_byte(struct nand_chip *this) { u_char res; - struct nand_chip *this = mtd_to_nand(mtd); void __iomem *io_base = (void __iomem *)nand_get_controller_data(this); gpio_set_value(AMS_DELTA_GPIO_PIN_NAND_NRE, 0); @@ -99,12 +98,12 @@ static void ams_delta_write_buf(struct mtd_info *mtd, const u_char *buf, ams_delta_write_byte(mtd, buf[i]); } -static void ams_delta_read_buf(struct mtd_info *mtd, u_char *buf, int len) +static void ams_delta_read_buf(struct nand_chip *this, u_char *buf, int len) { int i; for (i=0; iactivecs->io.virt); @@ -429,9 +428,8 @@ static void atmel_nand_write_byte(struct mtd_info *mtd, u8 byte) iowrite8(byte, nand->activecs->io.virt); } -static void atmel_nand_read_buf(struct mtd_info *mtd, u8 *buf, int len) +static void atmel_nand_read_buf(struct nand_chip *chip, u8 *buf, int len) { - struct nand_chip *chip = mtd_to_nand(mtd); struct atmel_nand *nand = to_atmel_nand(chip); struct atmel_nand_controller *nc; @@ -883,8 +881,8 @@ static int atmel_nand_pmecc_read_pg(struct nand_chip *chip, u8 *buf, if (ret) return ret; - atmel_nand_read_buf(mtd, buf, mtd->writesize); - atmel_nand_read_buf(mtd, chip->oob_poi, mtd->oobsize); + atmel_nand_read_buf(chip, buf, mtd->writesize); + atmel_nand_read_buf(chip, chip->oob_poi, mtd->oobsize); ret = atmel_nand_pmecc_correct_data(chip, buf, raw); diff --git a/drivers/mtd/nand/raw/au1550nd.c b/drivers/mtd/nand/raw/au1550nd.c index d277a141c7d3..76ea4141eb10 100644 --- a/drivers/mtd/nand/raw/au1550nd.c +++ b/drivers/mtd/nand/raw/au1550nd.c @@ -29,13 +29,12 @@ struct au1550nd_ctx { /** * au_read_byte - read one byte from the chip - * @mtd: MTD device structure + * @this: NAND chip object * * read function for 8bit buswidth */ -static u_char au_read_byte(struct mtd_info *mtd) +static u_char au_read_byte(struct nand_chip *this) { - struct nand_chip *this = mtd_to_nand(mtd); u_char ret = readb(this->IO_ADDR_R); wmb(); /* drain writebuffer */ return ret; @@ -57,13 +56,12 @@ static void au_write_byte(struct mtd_info *mtd, u_char byte) /** * au_read_byte16 - read one byte endianness aware from the chip - * @mtd: MTD device structure + * @this: NAND chip object * * read function for 16bit buswidth with endianness conversion */ -static u_char au_read_byte16(struct mtd_info *mtd) +static u_char au_read_byte16(struct nand_chip *this) { - struct nand_chip *this = mtd_to_nand(mtd); u_char ret = (u_char) cpu_to_le16(readw(this->IO_ADDR_R)); wmb(); /* drain writebuffer */ return ret; @@ -104,16 +102,15 @@ static void au_write_buf(struct mtd_info *mtd, const u_char *buf, int len) /** * au_read_buf - read chip data into buffer - * @mtd: MTD device structure + * @this: NAND chip object * @buf: buffer to store date * @len: number of bytes to read * * read function for 8bit buswidth */ -static void au_read_buf(struct mtd_info *mtd, u_char *buf, int len) +static void au_read_buf(struct nand_chip *this, u_char *buf, int len) { int i; - struct nand_chip *this = mtd_to_nand(mtd); for (i = 0; i < len; i++) { buf[i] = readb(this->IO_ADDR_R); diff --git a/drivers/mtd/nand/raw/bcm47xxnflash/ops_bcm4706.c b/drivers/mtd/nand/raw/bcm47xxnflash/ops_bcm4706.c index 7022ffd271ad..cf3e45358c60 100644 --- a/drivers/mtd/nand/raw/bcm47xxnflash/ops_bcm4706.c +++ b/drivers/mtd/nand/raw/bcm47xxnflash/ops_bcm4706.c @@ -310,9 +310,9 @@ static void bcm47xxnflash_ops_bcm4706_cmdfunc(struct mtd_info *mtd, b47n->curr_command = command; } -static u8 bcm47xxnflash_ops_bcm4706_read_byte(struct mtd_info *mtd) +static u8 bcm47xxnflash_ops_bcm4706_read_byte(struct nand_chip *nand_chip) { - struct nand_chip *nand_chip = mtd_to_nand(mtd); + struct mtd_info *mtd = nand_to_mtd(nand_chip); struct bcm47xxnflash *b47n = nand_get_controller_data(nand_chip); struct bcma_drv_cc *cc = b47n->cc; u32 tmp = 0; @@ -338,16 +338,16 @@ static u8 bcm47xxnflash_ops_bcm4706_read_byte(struct mtd_info *mtd) return 0; } -static void bcm47xxnflash_ops_bcm4706_read_buf(struct mtd_info *mtd, +static void bcm47xxnflash_ops_bcm4706_read_buf(struct nand_chip *nand_chip, uint8_t *buf, int len) { - struct nand_chip *nand_chip = mtd_to_nand(mtd); struct bcm47xxnflash *b47n = nand_get_controller_data(nand_chip); switch (b47n->curr_command) { case NAND_CMD_READ0: case NAND_CMD_READOOB: - bcm47xxnflash_ops_bcm4706_read(mtd, buf, len); + bcm47xxnflash_ops_bcm4706_read(nand_to_mtd(nand_chip), buf, + len); return; } diff --git a/drivers/mtd/nand/raw/brcmnand/brcmnand.c b/drivers/mtd/nand/raw/brcmnand/brcmnand.c index d8fb2b5c19c9..7cbc6045f16d 100644 --- a/drivers/mtd/nand/raw/brcmnand/brcmnand.c +++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c @@ -1417,9 +1417,8 @@ static void brcmnand_cmdfunc(struct mtd_info *mtd, unsigned command, brcmnand_wp(mtd, 1); } -static uint8_t brcmnand_read_byte(struct mtd_info *mtd) +static uint8_t brcmnand_read_byte(struct nand_chip *chip) { - struct nand_chip *chip = mtd_to_nand(mtd); struct brcmnand_host *host = nand_get_controller_data(chip); struct brcmnand_controller *ctrl = host->ctrl; uint8_t ret = 0; @@ -1474,12 +1473,12 @@ static uint8_t brcmnand_read_byte(struct mtd_info *mtd) return ret; } -static void brcmnand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) +static void brcmnand_read_buf(struct nand_chip *chip, uint8_t *buf, int len) { int i; for (i = 0; i < len; i++, buf++) - *buf = brcmnand_read_byte(mtd); + *buf = brcmnand_read_byte(chip); } static void brcmnand_write_buf(struct mtd_info *mtd, const uint8_t *buf, diff --git a/drivers/mtd/nand/raw/cafe_nand.c b/drivers/mtd/nand/raw/cafe_nand.c index fe7c7db3cfe7..97d835f88b86 100644 --- a/drivers/mtd/nand/raw/cafe_nand.c +++ b/drivers/mtd/nand/raw/cafe_nand.c @@ -133,9 +133,8 @@ static void cafe_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len) len, cafe->datalen); } -static void cafe_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) +static void cafe_read_buf(struct nand_chip *chip, uint8_t *buf, int len) { - struct nand_chip *chip = mtd_to_nand(mtd); struct cafe_priv *cafe = nand_get_controller_data(chip); if (cafe->usedma) @@ -148,13 +147,12 @@ static void cafe_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) cafe->datalen += len; } -static uint8_t cafe_read_byte(struct mtd_info *mtd) +static uint8_t cafe_read_byte(struct nand_chip *chip) { - struct nand_chip *chip = mtd_to_nand(mtd); struct cafe_priv *cafe = nand_get_controller_data(chip); uint8_t d; - cafe_read_buf(mtd, &d, 1); + cafe_read_buf(chip, &d, 1); cafe_dev_dbg(&cafe->pdev->dev, "Read %02x\n", d); return d; @@ -383,7 +381,7 @@ static int cafe_nand_read_page(struct nand_chip *chip, uint8_t *buf, cafe_readl(cafe, NAND_ECC_SYN01)); nand_read_page_op(chip, page, 0, buf, mtd->writesize); - chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); + chip->read_buf(chip, chip->oob_poi, mtd->oobsize); if (checkecc && cafe_readl(cafe, NAND_ECC_RESULT) & (1<<18)) { unsigned short syn[8], pat[4]; diff --git a/drivers/mtd/nand/raw/cmx270_nand.c b/drivers/mtd/nand/raw/cmx270_nand.c index 2eb933a8f99e..232d32391b1f 100644 --- a/drivers/mtd/nand/raw/cmx270_nand.c +++ b/drivers/mtd/nand/raw/cmx270_nand.c @@ -49,10 +49,8 @@ static const struct mtd_partition partition_info[] = { }; #define NUM_PARTITIONS (ARRAY_SIZE(partition_info)) -static u_char cmx270_read_byte(struct mtd_info *mtd) +static u_char cmx270_read_byte(struct nand_chip *this) { - struct nand_chip *this = mtd_to_nand(mtd); - return (readl(this->IO_ADDR_R) >> 16); } @@ -65,10 +63,9 @@ static void cmx270_write_buf(struct mtd_info *mtd, const u_char *buf, int len) writel((*buf++ << 16), this->IO_ADDR_W); } -static void cmx270_read_buf(struct mtd_info *mtd, u_char *buf, int len) +static void cmx270_read_buf(struct nand_chip *this, u_char *buf, int len) { int i; - struct nand_chip *this = mtd_to_nand(mtd); for (i=0; iIO_ADDR_R) >> 16; diff --git a/drivers/mtd/nand/raw/cs553x_nand.c b/drivers/mtd/nand/raw/cs553x_nand.c index 193c3e8fa118..4394eeebec7f 100644 --- a/drivers/mtd/nand/raw/cs553x_nand.c +++ b/drivers/mtd/nand/raw/cs553x_nand.c @@ -93,10 +93,8 @@ #define CS_NAND_ECC_CLRECC (1<<1) #define CS_NAND_ECC_ENECC (1<<0) -static void cs553x_read_buf(struct mtd_info *mtd, u_char *buf, int len) +static void cs553x_read_buf(struct nand_chip *this, u_char *buf, int len) { - struct nand_chip *this = mtd_to_nand(mtd); - while (unlikely(len > 0x800)) { memcpy_fromio(buf, this->IO_ADDR_R, 0x800); buf += 0x800; @@ -117,9 +115,8 @@ static void cs553x_write_buf(struct mtd_info *mtd, const u_char *buf, int len) memcpy_toio(this->IO_ADDR_R, buf, len); } -static unsigned char cs553x_read_byte(struct mtd_info *mtd) +static unsigned char cs553x_read_byte(struct nand_chip *this) { - struct nand_chip *this = mtd_to_nand(mtd); return readb(this->IO_ADDR_R); } diff --git a/drivers/mtd/nand/raw/davinci_nand.c b/drivers/mtd/nand/raw/davinci_nand.c index c80b6c6da4aa..b879049e51c6 100644 --- a/drivers/mtd/nand/raw/davinci_nand.c +++ b/drivers/mtd/nand/raw/davinci_nand.c @@ -435,10 +435,9 @@ static int nand_davinci_correct_4bit(struct nand_chip *chip, u_char *data, * the two LSBs for NAND access ... so we can issue 32-bit reads/writes * and have that transparently morphed into multiple NAND operations. */ -static void nand_davinci_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) +static void nand_davinci_read_buf(struct nand_chip *chip, uint8_t *buf, + int len) { - struct nand_chip *chip = mtd_to_nand(mtd); - if ((0x03 & ((uintptr_t)buf)) == 0 && (0x03 & len) == 0) ioread32_rep(chip->IO_ADDR_R, buf, len >> 2); else if ((0x01 & ((uintptr_t)buf)) == 0 && (0x01 & len) == 0) diff --git a/drivers/mtd/nand/raw/denali.c b/drivers/mtd/nand/raw/denali.c index 52fe5115ed6e..6e5be3efcb5d 100644 --- a/drivers/mtd/nand/raw/denali.c +++ b/drivers/mtd/nand/raw/denali.c @@ -215,8 +215,9 @@ static uint32_t denali_check_irq(struct denali_nand_info *denali) return irq_status; } -static void denali_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) +static void denali_read_buf(struct nand_chip *chip, uint8_t *buf, int len) { + struct mtd_info *mtd = nand_to_mtd(chip); struct denali_nand_info *denali = mtd_to_denali(mtd); u32 addr = DENALI_MAP11_DATA | DENALI_BANK(denali); int i; @@ -235,9 +236,9 @@ static void denali_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len) denali->host_write(denali, addr, buf[i]); } -static void denali_read_buf16(struct mtd_info *mtd, uint8_t *buf, int len) +static void denali_read_buf16(struct nand_chip *chip, uint8_t *buf, int len) { - struct denali_nand_info *denali = mtd_to_denali(mtd); + struct denali_nand_info *denali = mtd_to_denali(nand_to_mtd(chip)); u32 addr = DENALI_MAP11_DATA | DENALI_BANK(denali); uint16_t *buf16 = (uint16_t *)buf; int i; @@ -258,11 +259,11 @@ static void denali_write_buf16(struct mtd_info *mtd, const uint8_t *buf, denali->host_write(denali, addr, buf16[i]); } -static uint8_t denali_read_byte(struct mtd_info *mtd) +static uint8_t denali_read_byte(struct nand_chip *chip) { uint8_t byte; - denali_read_buf(mtd, &byte, 1); + denali_read_buf(chip, &byte, 1); return byte; } diff --git a/drivers/mtd/nand/raw/diskonchip.c b/drivers/mtd/nand/raw/diskonchip.c index 142d21be874e..de1059069e8f 100644 --- a/drivers/mtd/nand/raw/diskonchip.c +++ b/drivers/mtd/nand/raw/diskonchip.c @@ -302,9 +302,8 @@ static void doc2000_write_byte(struct mtd_info *mtd, u_char datum) WriteDOC(datum, docptr, 2k_CDSN_IO); } -static u_char doc2000_read_byte(struct mtd_info *mtd) +static u_char doc2000_read_byte(struct nand_chip *this) { - struct nand_chip *this = mtd_to_nand(mtd); struct doc_priv *doc = nand_get_controller_data(this); void __iomem *docptr = doc->virtadr; u_char ret; @@ -334,9 +333,8 @@ static void doc2000_writebuf(struct mtd_info *mtd, const u_char *buf, int len) printk("\n"); } -static void doc2000_readbuf(struct mtd_info *mtd, u_char *buf, int len) +static void doc2000_readbuf(struct nand_chip *this, u_char *buf, int len) { - struct nand_chip *this = mtd_to_nand(mtd); struct doc_priv *doc = nand_get_controller_data(this); void __iomem *docptr = doc->virtadr; int i; @@ -344,14 +342,12 @@ static void doc2000_readbuf(struct mtd_info *mtd, u_char *buf, int len) if (debug) printk("readbuf of %d bytes: ", len); - for (i = 0; i < len; i++) { + for (i = 0; i < len; i++) buf[i] = ReadDOC(docptr, 2k_CDSN_IO + i); - } } -static void doc2000_readbuf_dword(struct mtd_info *mtd, u_char *buf, int len) +static void doc2000_readbuf_dword(struct nand_chip *this, u_char *buf, int len) { - struct nand_chip *this = mtd_to_nand(mtd); struct doc_priv *doc = nand_get_controller_data(this); void __iomem *docptr = doc->virtadr; int i; @@ -387,8 +383,8 @@ static uint16_t __init doc200x_ident_chip(struct mtd_info *mtd, int nr) */ udelay(50); - ret = this->read_byte(mtd) << 8; - ret |= this->read_byte(mtd); + ret = this->read_byte(this) << 8; + ret |= this->read_byte(this); if (doc->ChipID == DOC_ChipID_Doc2k && try_dword && !nr) { /* First chip probe. See if we get same results by 32-bit access */ @@ -447,7 +443,7 @@ static int doc200x_wait(struct mtd_info *mtd, struct nand_chip *this) DoC_WaitReady(doc); nand_status_op(this, NULL); DoC_WaitReady(doc); - status = (int)this->read_byte(mtd); + status = (int)this->read_byte(this); return status; } @@ -463,9 +459,8 @@ static void doc2001_write_byte(struct mtd_info *mtd, u_char datum) WriteDOC(datum, docptr, WritePipeTerm); } -static u_char doc2001_read_byte(struct mtd_info *mtd) +static u_char doc2001_read_byte(struct nand_chip *this) { - struct nand_chip *this = mtd_to_nand(mtd); struct doc_priv *doc = nand_get_controller_data(this); void __iomem *docptr = doc->virtadr; @@ -490,9 +485,8 @@ static void doc2001_writebuf(struct mtd_info *mtd, const u_char *buf, int len) WriteDOC(0x00, docptr, WritePipeTerm); } -static void doc2001_readbuf(struct mtd_info *mtd, u_char *buf, int len) +static void doc2001_readbuf(struct nand_chip *this, u_char *buf, int len) { - struct nand_chip *this = mtd_to_nand(mtd); struct doc_priv *doc = nand_get_controller_data(this); void __iomem *docptr = doc->virtadr; int i; @@ -507,9 +501,8 @@ static void doc2001_readbuf(struct mtd_info *mtd, u_char *buf, int len) buf[i] = ReadDOC(docptr, LastDataRead); } -static u_char doc2001plus_read_byte(struct mtd_info *mtd) +static u_char doc2001plus_read_byte(struct nand_chip *this) { - struct nand_chip *this = mtd_to_nand(mtd); struct doc_priv *doc = nand_get_controller_data(this); void __iomem *docptr = doc->virtadr; u_char ret; @@ -540,9 +533,8 @@ static void doc2001plus_writebuf(struct mtd_info *mtd, const u_char *buf, int le printk("\n"); } -static void doc2001plus_readbuf(struct mtd_info *mtd, u_char *buf, int len) +static void doc2001plus_readbuf(struct nand_chip *this, u_char *buf, int len) { - struct nand_chip *this = mtd_to_nand(mtd); struct doc_priv *doc = nand_get_controller_data(this); void __iomem *docptr = doc->virtadr; int i; @@ -735,7 +727,7 @@ static void doc2001plus_command(struct mtd_info *mtd, unsigned command, int colu WriteDOC(NAND_CMD_STATUS, docptr, Mplus_FlashCmd); WriteDOC(0, docptr, Mplus_WritePipeTerm); WriteDOC(0, docptr, Mplus_WritePipeTerm); - while (!(this->read_byte(mtd) & 0x40)) ; + while (!(this->read_byte(this) & 0x40)) ; return; /* This applies to read commands */ diff --git a/drivers/mtd/nand/raw/docg4.c b/drivers/mtd/nand/raw/docg4.c index 37935fd04020..284bc96dacd3 100644 --- a/drivers/mtd/nand/raw/docg4.c +++ b/drivers/mtd/nand/raw/docg4.c @@ -261,10 +261,9 @@ static inline void write_nop(void __iomem *docptr) writew(0, docptr + DOC_NOP); } -static void docg4_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) +static void docg4_read_buf(struct nand_chip *nand, uint8_t *buf, int len) { int i; - struct nand_chip *nand = mtd_to_nand(mtd); uint16_t *p = (uint16_t *) buf; len >>= 1; @@ -484,9 +483,8 @@ static int correct_data(struct mtd_info *mtd, uint8_t *buf, int page) return numerrs; } -static uint8_t docg4_read_byte(struct mtd_info *mtd) +static uint8_t docg4_read_byte(struct nand_chip *nand) { - struct nand_chip *nand = mtd_to_nand(mtd); struct docg4_priv *doc = nand_get_controller_data(nand); dev_dbg(doc->dev, "%s\n", __func__); @@ -809,11 +807,11 @@ static int read_page(struct mtd_info *mtd, struct nand_chip *nand, dev_dbg(doc->dev, "%s: status = 0x%x\n", __func__, status); - docg4_read_buf(mtd, buf, DOCG4_PAGE_SIZE); /* read the page data */ + docg4_read_buf(nand, buf, DOCG4_PAGE_SIZE); /* read the page data */ /* this device always reads oob after page data */ /* first 14 oob bytes read from I/O reg */ - docg4_read_buf(mtd, nand->oob_poi, 14); + docg4_read_buf(nand, nand->oob_poi, 14); /* last 2 read from another reg */ buf16 = (uint16_t *)(nand->oob_poi + 14); @@ -859,7 +857,6 @@ static int docg4_read_page(struct nand_chip *nand, uint8_t *buf, static int docg4_read_oob(struct nand_chip *nand, int page) { - struct mtd_info *mtd = nand_to_mtd(nand); struct docg4_priv *doc = nand_get_controller_data(nand); void __iomem *docptr = doc->virtadr; uint16_t status; @@ -885,7 +882,7 @@ static int docg4_read_oob(struct nand_chip *nand, int page) dev_dbg(doc->dev, "%s: status = 0x%x\n", __func__, status); - docg4_read_buf(mtd, nand->oob_poi, 16); + docg4_read_buf(nand, nand->oob_poi, 16); write_nop(docptr); write_nop(docptr); diff --git a/drivers/mtd/nand/raw/fsl_elbc_nand.c b/drivers/mtd/nand/raw/fsl_elbc_nand.c index c992d7ad39d9..22326bcb8b62 100644 --- a/drivers/mtd/nand/raw/fsl_elbc_nand.c +++ b/drivers/mtd/nand/raw/fsl_elbc_nand.c @@ -581,9 +581,8 @@ static void fsl_elbc_write_buf(struct mtd_info *mtd, const u8 *buf, int len) * read a byte from either the FCM hardware buffer if it has any data left * otherwise issue a command to read a single byte. */ -static u8 fsl_elbc_read_byte(struct mtd_info *mtd) +static u8 fsl_elbc_read_byte(struct nand_chip *chip) { - struct nand_chip *chip = mtd_to_nand(mtd); struct fsl_elbc_mtd *priv = nand_get_controller_data(chip); struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand; @@ -598,9 +597,8 @@ static u8 fsl_elbc_read_byte(struct mtd_info *mtd) /* * Read from the FCM Controller Data Buffer */ -static void fsl_elbc_read_buf(struct mtd_info *mtd, u8 *buf, int len) +static void fsl_elbc_read_buf(struct nand_chip *chip, u8 *buf, int len) { - struct nand_chip *chip = mtd_to_nand(mtd); struct fsl_elbc_mtd *priv = nand_get_controller_data(chip); struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand; int avail; @@ -720,7 +718,7 @@ static int fsl_elbc_read_page(struct nand_chip *chip, uint8_t *buf, nand_read_page_op(chip, page, 0, buf, mtd->writesize); if (oob_required) - fsl_elbc_read_buf(mtd, chip->oob_poi, mtd->oobsize); + fsl_elbc_read_buf(chip, chip->oob_poi, mtd->oobsize); if (fsl_elbc_wait(mtd, chip) & NAND_STATUS_FAIL) mtd->ecc_stats.failed++; diff --git a/drivers/mtd/nand/raw/fsl_ifc_nand.c b/drivers/mtd/nand/raw/fsl_ifc_nand.c index 945f3dab7ebf..7b6d0913a5bb 100644 --- a/drivers/mtd/nand/raw/fsl_ifc_nand.c +++ b/drivers/mtd/nand/raw/fsl_ifc_nand.c @@ -545,9 +545,8 @@ static void fsl_ifc_write_buf(struct mtd_info *mtd, const u8 *buf, int len) * Read a byte from either the IFC hardware buffer * read function for 8-bit buswidth */ -static uint8_t fsl_ifc_read_byte(struct mtd_info *mtd) +static uint8_t fsl_ifc_read_byte(struct nand_chip *chip) { - struct nand_chip *chip = mtd_to_nand(mtd); struct fsl_ifc_mtd *priv = nand_get_controller_data(chip); unsigned int offset; @@ -568,9 +567,8 @@ static uint8_t fsl_ifc_read_byte(struct mtd_info *mtd) * Read two bytes from the IFC hardware buffer * read function for 16-bit buswith */ -static uint8_t fsl_ifc_read_byte16(struct mtd_info *mtd) +static uint8_t fsl_ifc_read_byte16(struct nand_chip *chip) { - struct nand_chip *chip = mtd_to_nand(mtd); struct fsl_ifc_mtd *priv = nand_get_controller_data(chip); uint16_t data; @@ -591,9 +589,8 @@ static uint8_t fsl_ifc_read_byte16(struct mtd_info *mtd) /* * Read from the IFC Controller Data Buffer */ -static void fsl_ifc_read_buf(struct mtd_info *mtd, u8 *buf, int len) +static void fsl_ifc_read_buf(struct nand_chip *chip, u8 *buf, int len) { - struct nand_chip *chip = mtd_to_nand(mtd); struct fsl_ifc_mtd *priv = nand_get_controller_data(chip); int avail; @@ -689,11 +686,11 @@ static int fsl_ifc_read_page(struct nand_chip *chip, uint8_t *buf, nand_read_page_op(chip, page, 0, buf, mtd->writesize); if (oob_required) - fsl_ifc_read_buf(mtd, chip->oob_poi, mtd->oobsize); + fsl_ifc_read_buf(chip, chip->oob_poi, mtd->oobsize); if (ctrl->nand_stat & IFC_NAND_EVTER_STAT_ECCER) { if (!oob_required) - fsl_ifc_read_buf(mtd, chip->oob_poi, mtd->oobsize); + fsl_ifc_read_buf(chip, chip->oob_poi, mtd->oobsize); return check_erased_page(chip, buf); } diff --git a/drivers/mtd/nand/raw/fsl_upm.c b/drivers/mtd/nand/raw/fsl_upm.c index ffddfc9721ac..340547f1b6c7 100644 --- a/drivers/mtd/nand/raw/fsl_upm.c +++ b/drivers/mtd/nand/raw/fsl_upm.c @@ -124,16 +124,16 @@ static void fun_select_chip(struct mtd_info *mtd, int mchip_nr) } } -static uint8_t fun_read_byte(struct mtd_info *mtd) +static uint8_t fun_read_byte(struct nand_chip *chip) { - struct fsl_upm_nand *fun = to_fsl_upm_nand(mtd); + struct fsl_upm_nand *fun = to_fsl_upm_nand(nand_to_mtd(chip)); return in_8(fun->chip.IO_ADDR_R); } -static void fun_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) +static void fun_read_buf(struct nand_chip *chip, uint8_t *buf, int len) { - struct fsl_upm_nand *fun = to_fsl_upm_nand(mtd); + struct fsl_upm_nand *fun = to_fsl_upm_nand(nand_to_mtd(chip)); int i; for (i = 0; i < len; i++) diff --git a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c index 09f33f6006a3..d0d5caa1b7a6 100644 --- a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c +++ b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c @@ -859,9 +859,8 @@ static void gpmi_select_chip(struct mtd_info *mtd, int chipnr) this->current_chip = chipnr; } -static void gpmi_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) +static void gpmi_read_buf(struct nand_chip *chip, uint8_t *buf, int len) { - struct nand_chip *chip = mtd_to_nand(mtd); struct gpmi_nand_data *this = nand_get_controller_data(chip); dev_dbg(this->dev, "len is %d\n", len); @@ -879,13 +878,12 @@ static void gpmi_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len) gpmi_send_data(this, buf, len); } -static uint8_t gpmi_read_byte(struct mtd_info *mtd) +static uint8_t gpmi_read_byte(struct nand_chip *chip) { - struct nand_chip *chip = mtd_to_nand(mtd); struct gpmi_nand_data *this = nand_get_controller_data(chip); uint8_t *buf = this->data_buffer_dma; - gpmi_read_buf(mtd, buf, 1); + gpmi_read_buf(chip, buf, 1); return buf[0]; } @@ -1336,7 +1334,7 @@ static int gpmi_ecc_read_oob(struct nand_chip *chip, int page) /* Read out the conventional OOB. */ nand_read_page_op(chip, page, mtd->writesize, NULL, 0); - chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); + chip->read_buf(chip, chip->oob_poi, mtd->oobsize); /* * Now, we want to make sure the block mark is correct. In the @@ -1346,7 +1344,7 @@ static int gpmi_ecc_read_oob(struct nand_chip *chip, int page) if (GPMI_IS_MX23(this)) { /* Read the block mark into the first byte of the OOB buffer. */ nand_read_page_op(chip, page, 0, NULL, 0); - chip->oob_poi[0] = chip->read_byte(mtd); + chip->oob_poi[0] = chip->read_byte(chip); } return 0; @@ -1635,7 +1633,7 @@ static int mx23_check_transcription_stamp(struct gpmi_nand_data *this) * and starts in the 12th byte of the page. */ nand_read_page_op(chip, page, 12, NULL, 0); - chip->read_buf(mtd, buffer, strlen(fingerprint)); + chip->read_buf(chip, buffer, strlen(fingerprint)); /* Look for the fingerprint. */ if (!memcmp(buffer, fingerprint, strlen(fingerprint))) { @@ -1771,7 +1769,7 @@ static int mx23_boot_init(struct gpmi_nand_data *this) /* Send the command to read the conventional block mark. */ chip->select_chip(mtd, chipnr); nand_read_page_op(chip, page, mtd->writesize, NULL, 0); - block_mark = chip->read_byte(mtd); + block_mark = chip->read_byte(chip); chip->select_chip(mtd, -1); /* diff --git a/drivers/mtd/nand/raw/hisi504_nand.c b/drivers/mtd/nand/raw/hisi504_nand.c index fab3c7fcf77b..e1fe6963c908 100644 --- a/drivers/mtd/nand/raw/hisi504_nand.c +++ b/drivers/mtd/nand/raw/hisi504_nand.c @@ -364,9 +364,8 @@ static void hisi_nfc_select_chip(struct mtd_info *mtd, int chipselect) host->chipselect = chipselect; } -static uint8_t hisi_nfc_read_byte(struct mtd_info *mtd) +static uint8_t hisi_nfc_read_byte(struct nand_chip *chip) { - struct nand_chip *chip = mtd_to_nand(mtd); struct hinfc_host *host = nand_get_controller_data(chip); if (host->command == NAND_CMD_STATUS) @@ -390,9 +389,8 @@ hisi_nfc_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len) host->offset += len; } -static void hisi_nfc_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) +static void hisi_nfc_read_buf(struct nand_chip *chip, uint8_t *buf, int len) { - struct nand_chip *chip = mtd_to_nand(mtd); struct hinfc_host *host = nand_get_controller_data(chip); memcpy(buf, host->buffer + host->offset, len); @@ -537,7 +535,7 @@ static int hisi_nand_read_page_hwecc(struct nand_chip *chip, uint8_t *buf, int stat_1, stat_2; nand_read_page_op(chip, page, 0, buf, mtd->writesize); - chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); + chip->read_buf(chip, chip->oob_poi, mtd->oobsize); /* errors which can not be corrected by ECC */ if (host->irq_status & HINFC504_INTS_UE) { diff --git a/drivers/mtd/nand/raw/lpc32xx_slc.c b/drivers/mtd/nand/raw/lpc32xx_slc.c index 6e4017ddacad..5820c86cb1f1 100644 --- a/drivers/mtd/nand/raw/lpc32xx_slc.c +++ b/drivers/mtd/nand/raw/lpc32xx_slc.c @@ -359,9 +359,8 @@ static int lpc32xx_nand_ecc_calculate(struct nand_chip *chip, /* * Read a single byte from NAND device */ -static uint8_t lpc32xx_nand_read_byte(struct mtd_info *mtd) +static uint8_t lpc32xx_nand_read_byte(struct nand_chip *chip) { - struct nand_chip *chip = mtd_to_nand(mtd); struct lpc32xx_nand_host *host = nand_get_controller_data(chip); return (uint8_t)readl(SLC_DATA(host->io_base)); @@ -370,9 +369,8 @@ static uint8_t lpc32xx_nand_read_byte(struct mtd_info *mtd) /* * Simple device read without ECC */ -static void lpc32xx_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len) +static void lpc32xx_nand_read_buf(struct nand_chip *chip, u_char *buf, int len) { - struct nand_chip *chip = mtd_to_nand(mtd); struct lpc32xx_nand_host *host = nand_get_controller_data(chip); /* Direct device read with no ECC */ @@ -628,7 +626,7 @@ static int lpc32xx_nand_read_page_syndrome(struct nand_chip *chip, uint8_t *buf, status = lpc32xx_xfer(mtd, buf, chip->ecc.steps, 1); /* Get OOB data */ - chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); + chip->read_buf(chip, chip->oob_poi, mtd->oobsize); /* Convert to stored ECC format */ lpc32xx_slc_ecc_copy(tmpecc, (uint32_t *) host->ecc_buf, chip->ecc.steps); @@ -669,8 +667,8 @@ static int lpc32xx_nand_read_page_raw_syndrome(struct nand_chip *chip, nand_read_page_op(chip, page, 0, NULL, 0); /* Raw reads can just use the FIFO interface */ - chip->read_buf(mtd, buf, chip->ecc.size * chip->ecc.steps); - chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); + chip->read_buf(chip, buf, chip->ecc.size * chip->ecc.steps); + chip->read_buf(chip, chip->oob_poi, mtd->oobsize); return 0; } diff --git a/drivers/mtd/nand/raw/mpc5121_nfc.c b/drivers/mtd/nand/raw/mpc5121_nfc.c index 3c90d6955476..49031f5a3b6d 100644 --- a/drivers/mtd/nand/raw/mpc5121_nfc.c +++ b/drivers/mtd/nand/raw/mpc5121_nfc.c @@ -493,9 +493,9 @@ static void mpc5121_nfc_buf_copy(struct mtd_info *mtd, u_char *buf, int len, } /* Read data from NFC buffers */ -static void mpc5121_nfc_read_buf(struct mtd_info *mtd, u_char *buf, int len) +static void mpc5121_nfc_read_buf(struct nand_chip *chip, u_char *buf, int len) { - mpc5121_nfc_buf_copy(mtd, buf, len, 0); + mpc5121_nfc_buf_copy(nand_to_mtd(chip), buf, len, 0); } /* Write data to NFC buffers */ @@ -506,11 +506,11 @@ static void mpc5121_nfc_write_buf(struct mtd_info *mtd, } /* Read byte from NFC buffers */ -static u8 mpc5121_nfc_read_byte(struct mtd_info *mtd) +static u8 mpc5121_nfc_read_byte(struct nand_chip *chip) { u8 tmp; - mpc5121_nfc_read_buf(mtd, &tmp, sizeof(tmp)); + mpc5121_nfc_read_buf(chip, &tmp, sizeof(tmp)); return tmp; } diff --git a/drivers/mtd/nand/raw/mtk_nand.c b/drivers/mtd/nand/raw/mtk_nand.c index c338a9646433..1c7392242d4d 100644 --- a/drivers/mtd/nand/raw/mtk_nand.c +++ b/drivers/mtd/nand/raw/mtk_nand.c @@ -438,9 +438,8 @@ static inline void mtk_nfc_wait_ioready(struct mtk_nfc *nfc) dev_err(nfc->dev, "data not ready\n"); } -static inline u8 mtk_nfc_read_byte(struct mtd_info *mtd) +static inline u8 mtk_nfc_read_byte(struct nand_chip *chip) { - struct nand_chip *chip = mtd_to_nand(mtd); struct mtk_nfc *nfc = nand_get_controller_data(chip); u32 reg; @@ -467,12 +466,12 @@ static inline u8 mtk_nfc_read_byte(struct mtd_info *mtd) return nfi_readb(nfc, NFI_DATAR); } -static void mtk_nfc_read_buf(struct mtd_info *mtd, u8 *buf, int len) +static void mtk_nfc_read_buf(struct nand_chip *chip, u8 *buf, int len) { int i; for (i = 0; i < len; i++) - buf[i] = mtk_nfc_read_byte(mtd); + buf[i] = mtk_nfc_read_byte(chip); } static void mtk_nfc_write_byte(struct mtd_info *mtd, u8 byte) diff --git a/drivers/mtd/nand/raw/mxc_nand.c b/drivers/mtd/nand/raw/mxc_nand.c index 597c74ea7e5e..8fed2919f35e 100644 --- a/drivers/mtd/nand/raw/mxc_nand.c +++ b/drivers/mtd/nand/raw/mxc_nand.c @@ -895,9 +895,8 @@ static int mxc_nand_write_oob(struct nand_chip *chip, int page) return mxc_nand_write_page(chip, host->data_buf, false, page); } -static u_char mxc_nand_read_byte(struct mtd_info *mtd) +static u_char mxc_nand_read_byte(struct nand_chip *nand_chip) { - struct nand_chip *nand_chip = mtd_to_nand(mtd); struct mxc_nand_host *host = nand_get_controller_data(nand_chip); uint8_t ret; @@ -941,9 +940,10 @@ static void mxc_nand_write_buf(struct mtd_info *mtd, * Flash first the data output cycle is initiated by the NFC, which copies * the data to RAMbuffer. This data of length len is then copied to buffer buf. */ -static void mxc_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len) +static void mxc_nand_read_buf(struct nand_chip *nand_chip, u_char *buf, + int len) { - struct nand_chip *nand_chip = mtd_to_nand(mtd); + struct mtd_info *mtd = nand_to_mtd(nand_chip); struct mxc_nand_host *host = nand_get_controller_data(nand_chip); u16 col = host->buf_start; int n = mtd->oobsize + mtd->writesize - col; @@ -1429,7 +1429,7 @@ static int mxc_nand_get_features(struct mtd_info *mtd, struct nand_chip *chip, host->buf_start = 0; for (i = 0; i < ONFI_SUBFEATURE_PARAM_LEN; ++i) - *subfeature_param++ = chip->read_byte(mtd); + *subfeature_param++ = chip->read_byte(chip); return 0; } diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c index cc386ee64a1b..e4686078011d 100644 --- a/drivers/mtd/nand/raw/nand_base.c +++ b/drivers/mtd/nand/raw/nand_base.c @@ -254,26 +254,24 @@ static void nand_release_device(struct mtd_info *mtd) /** * nand_read_byte - [DEFAULT] read one byte from the chip - * @mtd: MTD device structure + * @chip: NAND chip object * * Default read function for 8bit buswidth */ -static uint8_t nand_read_byte(struct mtd_info *mtd) +static uint8_t nand_read_byte(struct nand_chip *chip) { - struct nand_chip *chip = mtd_to_nand(mtd); return readb(chip->IO_ADDR_R); } /** * nand_read_byte16 - [DEFAULT] read one byte endianness aware from the chip - * @mtd: MTD device structure + * @chip: NAND chip object * * Default read function for 16bit buswidth with endianness conversion. * */ -static uint8_t nand_read_byte16(struct mtd_info *mtd) +static uint8_t nand_read_byte16(struct nand_chip *chip) { - struct nand_chip *chip = mtd_to_nand(mtd); return (uint8_t) cpu_to_le16(readw(chip->IO_ADDR_R)); } @@ -362,16 +360,14 @@ static void nand_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len) /** * nand_read_buf - [DEFAULT] read chip data into buffer - * @mtd: MTD device structure + * @chip: NAND chip object * @buf: buffer to store date * @len: number of bytes to read * * Default read function for 8bit buswidth. */ -static void nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) +static void nand_read_buf(struct nand_chip *chip, uint8_t *buf, int len) { - struct nand_chip *chip = mtd_to_nand(mtd); - ioread8_rep(chip->IO_ADDR_R, buf, len); } @@ -393,15 +389,14 @@ static void nand_write_buf16(struct mtd_info *mtd, const uint8_t *buf, int len) /** * nand_read_buf16 - [DEFAULT] read chip data into buffer - * @mtd: MTD device structure + * @chip: NAND chip object * @buf: buffer to store date * @len: number of bytes to read * * Default read function for 16bit buswidth. */ -static void nand_read_buf16(struct mtd_info *mtd, uint8_t *buf, int len) +static void nand_read_buf16(struct nand_chip *chip, uint8_t *buf, int len) { - struct nand_chip *chip = mtd_to_nand(mtd); u16 *p = (u16 *) buf; ioread16_rep(chip->IO_ADDR_R, p, len >> 1); @@ -1544,7 +1539,7 @@ int nand_read_page_op(struct nand_chip *chip, unsigned int page, chip->cmdfunc(mtd, NAND_CMD_READ0, offset_in_page, page); if (len) - chip->read_buf(mtd, buf, len); + chip->read_buf(chip, buf, len); return 0; } @@ -1593,7 +1588,7 @@ static int nand_read_param_page_op(struct nand_chip *chip, u8 page, void *buf, chip->cmdfunc(mtd, NAND_CMD_PARAM, page, -1); for (i = 0; i < len; i++) - p[i] = chip->read_byte(mtd); + p[i] = chip->read_byte(chip); return 0; } @@ -1656,7 +1651,7 @@ int nand_change_read_column_op(struct nand_chip *chip, chip->cmdfunc(mtd, NAND_CMD_RNDOUT, offset_in_page, -1); if (len) - chip->read_buf(mtd, buf, len); + chip->read_buf(chip, buf, len); return 0; } @@ -1693,7 +1688,7 @@ int nand_read_oob_op(struct nand_chip *chip, unsigned int page, chip->cmdfunc(mtd, NAND_CMD_READOOB, offset_in_oob, page); if (len) - chip->read_buf(mtd, buf, len); + chip->read_buf(chip, buf, len); return 0; } @@ -2009,7 +2004,7 @@ int nand_readid_op(struct nand_chip *chip, u8 addr, void *buf, chip->cmdfunc(mtd, NAND_CMD_READID, addr, -1); for (i = 0; i < len; i++) - id[i] = chip->read_byte(mtd); + id[i] = chip->read_byte(chip); return 0; } @@ -2048,7 +2043,7 @@ int nand_status_op(struct nand_chip *chip, u8 *status) chip->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1); if (status) - *status = chip->read_byte(mtd); + *status = chip->read_byte(chip); return 0; } @@ -2229,7 +2224,7 @@ static int nand_get_features_op(struct nand_chip *chip, u8 feature, chip->cmdfunc(mtd, NAND_CMD_GET_FEATURES, feature, -1); for (i = 0; i < ONFI_SUBFEATURE_PARAM_LEN; ++i) - params[i] = chip->read_byte(mtd); + params[i] = chip->read_byte(chip); return 0; } @@ -2304,8 +2299,6 @@ EXPORT_SYMBOL_GPL(nand_reset_op); int nand_read_data_op(struct nand_chip *chip, void *buf, unsigned int len, bool force_8bit) { - struct mtd_info *mtd = nand_to_mtd(chip); - if (!len || !buf) return -EINVAL; @@ -2325,9 +2318,9 @@ int nand_read_data_op(struct nand_chip *chip, void *buf, unsigned int len, unsigned int i; for (i = 0; i < len; i++) - p[i] = chip->read_byte(mtd); + p[i] = chip->read_byte(chip); } else { - chip->read_buf(mtd, buf, len); + chip->read_buf(chip, buf, len); } return 0; diff --git a/drivers/mtd/nand/raw/nandsim.c b/drivers/mtd/nand/raw/nandsim.c index e9f7b9e1aead..04feb4e8d112 100644 --- a/drivers/mtd/nand/raw/nandsim.c +++ b/drivers/mtd/nand/raw/nandsim.c @@ -1872,9 +1872,8 @@ static void switch_state(struct nandsim *ns) } } -static u_char ns_nand_read_byte(struct mtd_info *mtd) +static u_char ns_nand_read_byte(struct nand_chip *chip) { - struct nand_chip *chip = mtd_to_nand(mtd); struct nandsim *ns = nand_get_controller_data(chip); u_char outb = 0x00; @@ -2136,9 +2135,8 @@ static void ns_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len) } } -static void ns_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len) +static void ns_nand_read_buf(struct nand_chip *chip, u_char *buf, int len) { - struct nand_chip *chip = mtd_to_nand(mtd); struct nandsim *ns = nand_get_controller_data(chip); /* Sanity and correctness checks */ @@ -2160,7 +2158,7 @@ static void ns_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len) int i; for (i = 0; i < len; i++) - buf[i] = mtd_to_nand(mtd)->read_byte(mtd); + buf[i] = chip->read_byte(chip); return; } diff --git a/drivers/mtd/nand/raw/ndfc.c b/drivers/mtd/nand/raw/ndfc.c index 9241cfaab5ac..56bb1eaa5ef3 100644 --- a/drivers/mtd/nand/raw/ndfc.c +++ b/drivers/mtd/nand/raw/ndfc.c @@ -116,9 +116,8 @@ static int ndfc_calculate_ecc(struct nand_chip *chip, * functions. No further checking, as nand_base will always read/write * page aligned. */ -static void ndfc_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) +static void ndfc_read_buf(struct nand_chip *chip, uint8_t *buf, int len) { - struct nand_chip *chip = mtd_to_nand(mtd); struct ndfc_controller *ndfc = nand_get_controller_data(chip); uint32_t *p = (uint32_t *) buf; diff --git a/drivers/mtd/nand/raw/nuc900_nand.c b/drivers/mtd/nand/raw/nuc900_nand.c index 0c675b6c0b6e..3a88da5ec97f 100644 --- a/drivers/mtd/nand/raw/nuc900_nand.c +++ b/drivers/mtd/nand/raw/nuc900_nand.c @@ -79,21 +79,21 @@ static const struct mtd_partition partitions[] = { } }; -static unsigned char nuc900_nand_read_byte(struct mtd_info *mtd) +static unsigned char nuc900_nand_read_byte(struct nand_chip *chip) { unsigned char ret; - struct nuc900_nand *nand = mtd_to_nuc900(mtd); + struct nuc900_nand *nand = mtd_to_nuc900(nand_to_mtd(chip)); ret = (unsigned char)read_data_reg(nand); return ret; } -static void nuc900_nand_read_buf(struct mtd_info *mtd, +static void nuc900_nand_read_buf(struct nand_chip *chip, unsigned char *buf, int len) { int i; - struct nuc900_nand *nand = mtd_to_nuc900(mtd); + struct nuc900_nand *nand = mtd_to_nuc900(nand_to_mtd(chip)); for (i = 0; i < len; i++) buf[i] = (unsigned char)read_data_reg(nand); diff --git a/drivers/mtd/nand/raw/omap2.c b/drivers/mtd/nand/raw/omap2.c index f1f8b6c1d654..4f2e5cd86050 100644 --- a/drivers/mtd/nand/raw/omap2.c +++ b/drivers/mtd/nand/raw/omap2.c @@ -337,12 +337,13 @@ static void omap_write_buf16(struct mtd_info *mtd, const u_char * buf, int len) /** * omap_read_buf_pref - read data from NAND controller into buffer - * @mtd: MTD device structure + * @chip: NAND chip object * @buf: buffer to store date * @len: number of bytes to read */ -static void omap_read_buf_pref(struct mtd_info *mtd, u_char *buf, int len) +static void omap_read_buf_pref(struct nand_chip *chip, u_char *buf, int len) { + struct mtd_info *mtd = nand_to_mtd(chip); struct omap_nand_info *info = mtd_to_omap(mtd); uint32_t r_count = 0; int ret = 0; @@ -528,14 +529,17 @@ static inline int omap_nand_dma_transfer(struct mtd_info *mtd, void *addr, /** * omap_read_buf_dma_pref - read data from NAND controller into buffer - * @mtd: MTD device structure + * @chip: NAND chip object * @buf: buffer to store date * @len: number of bytes to read */ -static void omap_read_buf_dma_pref(struct mtd_info *mtd, u_char *buf, int len) +static void omap_read_buf_dma_pref(struct nand_chip *chip, u_char *buf, + int len) { + struct mtd_info *mtd = nand_to_mtd(chip); + if (len <= mtd->oobsize) - omap_read_buf_pref(mtd, buf, len); + omap_read_buf_pref(chip, buf, len); else /* start transfer in DMA mode */ omap_nand_dma_transfer(mtd, buf, len, 0x0); @@ -605,17 +609,19 @@ static irqreturn_t omap_nand_irq(int this_irq, void *dev) /* * omap_read_buf_irq_pref - read data from NAND controller into buffer - * @mtd: MTD device structure + * @chip: NAND chip object * @buf: buffer to store date * @len: number of bytes to read */ -static void omap_read_buf_irq_pref(struct mtd_info *mtd, u_char *buf, int len) +static void omap_read_buf_irq_pref(struct nand_chip *chip, u_char *buf, + int len) { + struct mtd_info *mtd = nand_to_mtd(chip); struct omap_nand_info *info = mtd_to_omap(mtd); int ret = 0; if (len <= mtd->oobsize) { - omap_read_buf_pref(mtd, buf, len); + omap_read_buf_pref(chip, buf, len); return; } @@ -1642,7 +1648,7 @@ static int omap_read_page_bch(struct nand_chip *chip, uint8_t *buf, chip->ecc.hwctl(chip, NAND_ECC_READ); /* Read data */ - chip->read_buf(mtd, buf, mtd->writesize); + chip->read_buf(chip, buf, mtd->writesize); /* Read oob bytes */ nand_change_read_column_op(chip, diff --git a/drivers/mtd/nand/raw/orion_nand.c b/drivers/mtd/nand/raw/orion_nand.c index 5c58d91ffaee..870eabe6fff8 100644 --- a/drivers/mtd/nand/raw/orion_nand.c +++ b/drivers/mtd/nand/raw/orion_nand.c @@ -48,9 +48,8 @@ static void orion_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl writeb(cmd, nc->IO_ADDR_W + offs); } -static void orion_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) +static void orion_nand_read_buf(struct nand_chip *chip, uint8_t *buf, int len) { - struct nand_chip *chip = mtd_to_nand(mtd); void __iomem *io_base = chip->IO_ADDR_R; #if defined(__LINUX_ARM_ARCH__) && __LINUX_ARM_ARCH__ >= 5 uint64_t *buf64; diff --git a/drivers/mtd/nand/raw/oxnas_nand.c b/drivers/mtd/nand/raw/oxnas_nand.c index 5bc180536320..6156abb30b7a 100644 --- a/drivers/mtd/nand/raw/oxnas_nand.c +++ b/drivers/mtd/nand/raw/oxnas_nand.c @@ -38,17 +38,15 @@ struct oxnas_nand_ctrl { struct nand_chip *chips[OXNAS_NAND_MAX_CHIPS]; }; -static uint8_t oxnas_nand_read_byte(struct mtd_info *mtd) +static uint8_t oxnas_nand_read_byte(struct nand_chip *chip) { - struct nand_chip *chip = mtd_to_nand(mtd); struct oxnas_nand_ctrl *oxnas = nand_get_controller_data(chip); return readb(oxnas->io_base); } -static void oxnas_nand_read_buf(struct mtd_info *mtd, u8 *buf, int len) +static void oxnas_nand_read_buf(struct nand_chip *chip, u8 *buf, int len) { - struct nand_chip *chip = mtd_to_nand(mtd); struct oxnas_nand_ctrl *oxnas = nand_get_controller_data(chip); ioread8_rep(oxnas->io_base, buf, len); diff --git a/drivers/mtd/nand/raw/pasemi_nand.c b/drivers/mtd/nand/raw/pasemi_nand.c index c8e2ac04fb86..551e5db670be 100644 --- a/drivers/mtd/nand/raw/pasemi_nand.c +++ b/drivers/mtd/nand/raw/pasemi_nand.c @@ -43,10 +43,8 @@ static unsigned int lpcctl; static struct mtd_info *pasemi_nand_mtd; static const char driver_name[] = "pasemi-nand"; -static void pasemi_read_buf(struct mtd_info *mtd, u_char *buf, int len) +static void pasemi_read_buf(struct nand_chip *chip, u_char *buf, int len) { - struct nand_chip *chip = mtd_to_nand(mtd); - while (len > 0x800) { memcpy_fromio(buf, chip->IO_ADDR_R, 0x800); buf += 0x800; diff --git a/drivers/mtd/nand/raw/plat_nand.c b/drivers/mtd/nand/raw/plat_nand.c index 80e1a44f0465..5193806923ba 100644 --- a/drivers/mtd/nand/raw/plat_nand.c +++ b/drivers/mtd/nand/raw/plat_nand.c @@ -52,13 +52,6 @@ static void plat_nand_write_buf(struct mtd_info *mtd, const uint8_t *buf, pdata->ctrl.write_buf(mtd_to_nand(mtd), buf, len); } -static void plat_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) -{ - struct platform_nand_data *pdata = dev_get_platdata(mtd->dev.parent); - - pdata->ctrl.read_buf(mtd_to_nand(mtd), buf, len); -} - /* * Probe for the NAND device. */ @@ -111,9 +104,7 @@ static int plat_nand_probe(struct platform_device *pdev) if (pdata->ctrl.write_buf) data->chip.write_buf = plat_nand_write_buf; - if (pdata->ctrl.read_buf) - data->chip.read_buf = plat_nand_read_buf; - + data->chip.read_buf = pdata->ctrl.read_buf; data->chip.chip_delay = pdata->chip.chip_delay; data->chip.options |= pdata->chip.options; data->chip.bbt_options |= pdata->chip.bbt_options; diff --git a/drivers/mtd/nand/raw/qcom_nandc.c b/drivers/mtd/nand/raw/qcom_nandc.c index e0cec027572c..63bb9f3fe23b 100644 --- a/drivers/mtd/nand/raw/qcom_nandc.c +++ b/drivers/mtd/nand/raw/qcom_nandc.c @@ -2282,9 +2282,8 @@ static int qcom_nandc_block_markbad(struct mtd_info *mtd, loff_t ofs) * reading/writing page data, they are used for smaller data like reading * id, status etc */ -static uint8_t qcom_nandc_read_byte(struct mtd_info *mtd) +static uint8_t qcom_nandc_read_byte(struct nand_chip *chip) { - struct nand_chip *chip = mtd_to_nand(mtd); struct qcom_nand_host *host = to_qcom_nand_host(chip); struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip); u8 *buf = nandc->data_buffer; @@ -2304,9 +2303,8 @@ static uint8_t qcom_nandc_read_byte(struct mtd_info *mtd) return ret; } -static void qcom_nandc_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) +static void qcom_nandc_read_buf(struct nand_chip *chip, uint8_t *buf, int len) { - struct nand_chip *chip = mtd_to_nand(mtd); struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip); int real_len = min_t(size_t, len, nandc->buf_count - nandc->buf_start); diff --git a/drivers/mtd/nand/raw/r852.c b/drivers/mtd/nand/raw/r852.c index aa5516b3b45f..07055bd657cd 100644 --- a/drivers/mtd/nand/raw/r852.c +++ b/drivers/mtd/nand/raw/r852.c @@ -266,9 +266,9 @@ static void r852_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len) /* * Read data lines of the nand chip to retrieve data */ -static void r852_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) +static void r852_read_buf(struct nand_chip *chip, uint8_t *buf, int len) { - struct r852_device *dev = r852_get_dev(mtd); + struct r852_device *dev = r852_get_dev(nand_to_mtd(chip)); uint32_t reg; if (dev->card_unstable) { @@ -303,9 +303,9 @@ static void r852_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) /* * Read one byte from nand chip */ -static uint8_t r852_read_byte(struct mtd_info *mtd) +static uint8_t r852_read_byte(struct nand_chip *chip) { - struct r852_device *dev = r852_get_dev(mtd); + struct r852_device *dev = r852_get_dev(nand_to_mtd(chip)); /* Same problem as in r852_read_buf.... */ if (dev->card_unstable) diff --git a/drivers/mtd/nand/raw/s3c2410.c b/drivers/mtd/nand/raw/s3c2410.c index d57201d118d8..54c86ec612dd 100644 --- a/drivers/mtd/nand/raw/s3c2410.c +++ b/drivers/mtd/nand/raw/s3c2410.c @@ -675,14 +675,14 @@ static int s3c2440_nand_calculate_ecc(struct nand_chip *chip, * use read/write block to move the data buffers to/from the controller */ -static void s3c2410_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len) +static void s3c2410_nand_read_buf(struct nand_chip *this, u_char *buf, int len) { - struct nand_chip *this = mtd_to_nand(mtd); readsb(this->IO_ADDR_R, buf, len); } -static void s3c2440_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len) +static void s3c2440_nand_read_buf(struct nand_chip *this, u_char *buf, int len) { + struct mtd_info *mtd = nand_to_mtd(this); struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd); readsl(info->regs + S3C2440_NFDATA, buf, len >> 2); diff --git a/drivers/mtd/nand/raw/sh_flctl.c b/drivers/mtd/nand/raw/sh_flctl.c index bb58edd2bdf0..6966a18f8ac4 100644 --- a/drivers/mtd/nand/raw/sh_flctl.c +++ b/drivers/mtd/nand/raw/sh_flctl.c @@ -618,7 +618,7 @@ static int flctl_read_page_hwecc(struct nand_chip *chip, uint8_t *buf, nand_read_page_op(chip, page, 0, buf, mtd->writesize); if (oob_required) - chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); + chip->read_buf(chip, chip->oob_poi, mtd->oobsize); return 0; } @@ -978,9 +978,9 @@ static void flctl_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len) flctl->index += len; } -static uint8_t flctl_read_byte(struct mtd_info *mtd) +static uint8_t flctl_read_byte(struct nand_chip *chip) { - struct sh_flctl *flctl = mtd_to_flctl(mtd); + struct sh_flctl *flctl = mtd_to_flctl(nand_to_mtd(chip)); uint8_t data; data = flctl->done_buff[flctl->index]; @@ -988,9 +988,9 @@ static uint8_t flctl_read_byte(struct mtd_info *mtd) return data; } -static void flctl_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) +static void flctl_read_buf(struct nand_chip *chip, uint8_t *buf, int len) { - struct sh_flctl *flctl = mtd_to_flctl(mtd); + struct sh_flctl *flctl = mtd_to_flctl(nand_to_mtd(chip)); memcpy(buf, &flctl->done_buff[flctl->index], len); flctl->index += len; diff --git a/drivers/mtd/nand/raw/socrates_nand.c b/drivers/mtd/nand/raw/socrates_nand.c index 82ba371a8e18..007e37680b88 100644 --- a/drivers/mtd/nand/raw/socrates_nand.c +++ b/drivers/mtd/nand/raw/socrates_nand.c @@ -54,14 +54,14 @@ static void socrates_nand_write_buf(struct mtd_info *mtd, /** * socrates_nand_read_buf - read chip data into buffer - * @mtd: MTD device structure + * @this: NAND chip object * @buf: buffer to store date * @len: number of bytes to read */ -static void socrates_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) +static void socrates_nand_read_buf(struct nand_chip *this, uint8_t *buf, + int len) { int i; - struct nand_chip *this = mtd_to_nand(mtd); struct socrates_nand_host *host = nand_get_controller_data(this); uint32_t val; @@ -78,10 +78,10 @@ static void socrates_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) * socrates_nand_read_byte - read one byte from the chip * @mtd: MTD device structure */ -static uint8_t socrates_nand_read_byte(struct mtd_info *mtd) +static uint8_t socrates_nand_read_byte(struct nand_chip *this) { uint8_t byte; - socrates_nand_read_buf(mtd, &byte, sizeof(byte)); + socrates_nand_read_buf(this, &byte, sizeof(byte)); return byte; } diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c index 86d666c0c03c..2a0e624eca6c 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -464,9 +464,8 @@ static void sunxi_nfc_select_chip(struct mtd_info *mtd, int chip) sunxi_nand->selected = chip; } -static void sunxi_nfc_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) +static void sunxi_nfc_read_buf(struct nand_chip *nand, uint8_t *buf, int len) { - struct nand_chip *nand = mtd_to_nand(mtd); struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand); struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller); int ret; @@ -540,11 +539,11 @@ static void sunxi_nfc_write_buf(struct mtd_info *mtd, const uint8_t *buf, } } -static uint8_t sunxi_nfc_read_byte(struct mtd_info *mtd) +static uint8_t sunxi_nfc_read_byte(struct nand_chip *nand) { uint8_t ret = 0; - sunxi_nfc_read_buf(mtd, &ret, 1); + sunxi_nfc_read_buf(nand, &ret, 1); return ret; } @@ -770,7 +769,7 @@ static void sunxi_nfc_randomizer_read_buf(struct mtd_info *mtd, uint8_t *buf, { sunxi_nfc_randomizer_config(mtd, page, ecc); sunxi_nfc_randomizer_enable(mtd); - sunxi_nfc_read_buf(mtd, buf, len); + sunxi_nfc_read_buf(mtd_to_nand(mtd), buf, len); sunxi_nfc_randomizer_disable(mtd); } @@ -995,7 +994,7 @@ static void sunxi_nfc_hw_ecc_read_extra_oob(struct mtd_info *mtd, false); if (!randomize) - sunxi_nfc_read_buf(mtd, oob + offset, len); + sunxi_nfc_read_buf(nand, oob + offset, len); else sunxi_nfc_randomizer_read_buf(mtd, oob + offset, len, false, page); diff --git a/drivers/mtd/nand/raw/tango_nand.c b/drivers/mtd/nand/raw/tango_nand.c index 7c8f47546002..20d6fa983a6b 100644 --- a/drivers/mtd/nand/raw/tango_nand.c +++ b/drivers/mtd/nand/raw/tango_nand.c @@ -135,16 +135,16 @@ static int tango_dev_ready(struct mtd_info *mtd) return readl_relaxed(nfc->pbus_base + PBUS_CS_CTRL) & PBUS_IORDY; } -static u8 tango_read_byte(struct mtd_info *mtd) +static u8 tango_read_byte(struct nand_chip *chip) { - struct tango_chip *tchip = to_tango_chip(mtd_to_nand(mtd)); + struct tango_chip *tchip = to_tango_chip(chip); return readb_relaxed(tchip->base + PBUS_DATA); } -static void tango_read_buf(struct mtd_info *mtd, u8 *buf, int len) +static void tango_read_buf(struct nand_chip *chip, u8 *buf, int len) { - struct tango_chip *tchip = to_tango_chip(mtd_to_nand(mtd)); + struct tango_chip *tchip = to_tango_chip(chip); ioread8_rep(tchip->base + PBUS_DATA, buf, len); } @@ -325,15 +325,13 @@ static int tango_write_page(struct nand_chip *chip, const u8 *buf, static void aux_read(struct nand_chip *chip, u8 **buf, int len, int *pos) { - struct mtd_info *mtd = nand_to_mtd(chip); - *pos += len; if (!*buf) { /* skip over "len" bytes */ nand_change_read_column_op(chip, *pos, NULL, 0, false); } else { - tango_read_buf(mtd, *buf, len); + tango_read_buf(chip, *buf, len); *buf += len; } } diff --git a/drivers/mtd/nand/raw/tmio_nand.c b/drivers/mtd/nand/raw/tmio_nand.c index 734ff29705ce..570ea045fbce 100644 --- a/drivers/mtd/nand/raw/tmio_nand.c +++ b/drivers/mtd/nand/raw/tmio_nand.c @@ -225,9 +225,9 @@ tmio_nand_wait(struct mtd_info *mtd, struct nand_chip *nand_chip) *To prevent stale data from being read, tmio_nand_hwcontrol() clears *tmio->read_good. */ -static u_char tmio_nand_read_byte(struct mtd_info *mtd) +static u_char tmio_nand_read_byte(struct nand_chip *chip) { - struct tmio_nand *tmio = mtd_to_tmio(mtd); + struct tmio_nand *tmio = mtd_to_tmio(nand_to_mtd(chip)); unsigned int data; if (tmio->read_good--) @@ -252,9 +252,9 @@ tmio_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len) tmio_iowrite16_rep(tmio->fcr + FCR_DATA, buf, len >> 1); } -static void tmio_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len) +static void tmio_nand_read_buf(struct nand_chip *chip, u_char *buf, int len) { - struct tmio_nand *tmio = mtd_to_tmio(mtd); + struct tmio_nand *tmio = mtd_to_tmio(nand_to_mtd(chip)); tmio_ioread16_rep(tmio->fcr + FCR_DATA, buf, len >> 1); } diff --git a/drivers/mtd/nand/raw/txx9ndfmc.c b/drivers/mtd/nand/raw/txx9ndfmc.c index 3c69d834de62..c68b638c4fe8 100644 --- a/drivers/mtd/nand/raw/txx9ndfmc.c +++ b/drivers/mtd/nand/raw/txx9ndfmc.c @@ -102,9 +102,9 @@ static void txx9ndfmc_write(struct platform_device *dev, __raw_writel(val, ndregaddr(dev, reg)); } -static uint8_t txx9ndfmc_read_byte(struct mtd_info *mtd) +static uint8_t txx9ndfmc_read_byte(struct nand_chip *chip) { - struct platform_device *dev = mtd_to_platdev(mtd); + struct platform_device *dev = mtd_to_platdev(nand_to_mtd(chip)); return txx9ndfmc_read(dev, TXX9_NDFDTR); } @@ -122,9 +122,9 @@ static void txx9ndfmc_write_buf(struct mtd_info *mtd, const uint8_t *buf, txx9ndfmc_write(dev, mcr, TXX9_NDFMCR); } -static void txx9ndfmc_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) +static void txx9ndfmc_read_buf(struct nand_chip *chip, uint8_t *buf, int len) { - struct platform_device *dev = mtd_to_platdev(mtd); + struct platform_device *dev = mtd_to_platdev(nand_to_mtd(chip)); void __iomem *ndfdtr = ndregaddr(dev, TXX9_NDFDTR); while (len--) diff --git a/drivers/mtd/nand/raw/xway_nand.c b/drivers/mtd/nand/raw/xway_nand.c index 1adb41acebfc..edbcfaa85ed8 100644 --- a/drivers/mtd/nand/raw/xway_nand.c +++ b/drivers/mtd/nand/raw/xway_nand.c @@ -125,17 +125,17 @@ static int xway_dev_ready(struct mtd_info *mtd) return ltq_ebu_r32(EBU_NAND_WAIT) & NAND_WAIT_RD; } -static unsigned char xway_read_byte(struct mtd_info *mtd) +static unsigned char xway_read_byte(struct nand_chip *chip) { - return xway_readb(mtd, NAND_READ_DATA); + return xway_readb(nand_to_mtd(chip), NAND_READ_DATA); } -static void xway_read_buf(struct mtd_info *mtd, u_char *buf, int len) +static void xway_read_buf(struct nand_chip *chip, u_char *buf, int len) { int i; for (i = 0; i < len; i++) - buf[i] = xway_readb(mtd, NAND_WRITE_DATA); + buf[i] = xway_readb(nand_to_mtd(chip), NAND_WRITE_DATA); } static void xway_write_buf(struct mtd_info *mtd, const u_char *buf, int len) diff --git a/drivers/staging/mt29f_spinand/mt29f_spinand.c b/drivers/staging/mt29f_spinand/mt29f_spinand.c index 2b2f98efdb54..644c91ff2734 100644 --- a/drivers/staging/mt29f_spinand/mt29f_spinand.c +++ b/drivers/staging/mt29f_spinand/mt29f_spinand.c @@ -657,7 +657,7 @@ static int spinand_read_page_hwecc(struct nand_chip *chip, u8 *buf, nand_read_page_op(chip, page, 0, p, eccsize * eccsteps); if (oob_required) - chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); + chip->read_buf(chip, chip->oob_poi, mtd->oobsize); while (1) { retval = spinand_read_status(info->spi, &status); @@ -685,9 +685,9 @@ static void spinand_select_chip(struct mtd_info *mtd, int dev) { } -static u8 spinand_read_byte(struct mtd_info *mtd) +static u8 spinand_read_byte(struct nand_chip *chip) { - struct spinand_state *state = mtd_to_state(mtd); + struct spinand_state *state = mtd_to_state(nand_to_mtd(chip)); u8 data; data = state->buf[state->buf_ptr]; @@ -732,9 +732,9 @@ static void spinand_write_buf(struct mtd_info *mtd, const u8 *buf, int len) state->buf_ptr += len; } -static void spinand_read_buf(struct mtd_info *mtd, u8 *buf, int len) +static void spinand_read_buf(struct nand_chip *chip, u8 *buf, int len) { - struct spinand_state *state = mtd_to_state(mtd); + struct spinand_state *state = mtd_to_state(nand_to_mtd(chip)); memcpy(buf, state->buf + state->buf_ptr, len); state->buf_ptr += len; diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h index 527947e81447..f324a82fe6a2 100644 --- a/include/linux/mtd/rawnand.h +++ b/include/linux/mtd/rawnand.h @@ -1283,10 +1283,10 @@ struct nand_chip { void __iomem *IO_ADDR_R; void __iomem *IO_ADDR_W; - uint8_t (*read_byte)(struct mtd_info *mtd); + uint8_t (*read_byte)(struct nand_chip *chip); void (*write_byte)(struct mtd_info *mtd, uint8_t byte); void (*write_buf)(struct mtd_info *mtd, const uint8_t *buf, int len); - void (*read_buf)(struct mtd_info *mtd, uint8_t *buf, int len); + void (*read_buf)(struct nand_chip *chip, uint8_t *buf, int len); void (*select_chip)(struct mtd_info *mtd, int chip); int (*block_bad)(struct mtd_info *mtd, loff_t ofs); int (*block_markbad)(struct mtd_info *mtd, loff_t ofs); From c0739d85723a381302907f9613392d7ac8515176 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Thu, 6 Sep 2018 14:05:23 +0200 Subject: [PATCH 251/302] mtd: rawnand: Pass a nand_chip object to chip->write_xxx() hooks Let's make the raw NAND API consistent by patching all helpers and hooks to take a nand_chip object instead of an mtd_info one or remove the mtd_info object when both are passed. Let's tackle all chip->write_xxx() hooks at once. Signed-off-by: Boris Brezillon Signed-off-by: Miquel Raynal --- drivers/mtd/nand/raw/ams-delta.c | 9 ++-- drivers/mtd/nand/raw/atmel/nand-controller.c | 12 +++--- drivers/mtd/nand/raw/au1550nd.c | 34 +++++++-------- .../mtd/nand/raw/bcm47xxnflash/ops_bcm4706.c | 6 +-- drivers/mtd/nand/raw/brcmnand/brcmnand.c | 5 +-- drivers/mtd/nand/raw/cafe_nand.c | 5 +-- drivers/mtd/nand/raw/cmx270_nand.c | 4 +- drivers/mtd/nand/raw/cs553x_nand.c | 9 ++-- drivers/mtd/nand/raw/davinci_nand.c | 6 +-- drivers/mtd/nand/raw/denali.c | 13 +++--- drivers/mtd/nand/raw/diskonchip.c | 20 ++++----- drivers/mtd/nand/raw/docg4.c | 10 ++--- drivers/mtd/nand/raw/fsl_elbc_nand.c | 10 ++--- drivers/mtd/nand/raw/fsl_ifc_nand.c | 6 +-- drivers/mtd/nand/raw/fsl_upm.c | 4 +- drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c | 3 +- drivers/mtd/nand/raw/hisi504_nand.c | 5 +-- drivers/mtd/nand/raw/lpc32xx_slc.c | 8 ++-- drivers/mtd/nand/raw/mpc5121_nfc.c | 6 +-- drivers/mtd/nand/raw/mtk_nand.c | 8 ++-- drivers/mtd/nand/raw/mxc_nand.c | 8 ++-- drivers/mtd/nand/raw/nand_base.c | 41 ++++++++----------- drivers/mtd/nand/raw/nand_hynix.c | 2 +- drivers/mtd/nand/raw/nandsim.c | 9 ++-- drivers/mtd/nand/raw/ndfc.c | 3 +- drivers/mtd/nand/raw/nuc900_nand.c | 4 +- drivers/mtd/nand/raw/omap2.c | 36 ++++++++-------- drivers/mtd/nand/raw/oxnas_nand.c | 4 +- drivers/mtd/nand/raw/pasemi_nand.c | 5 +-- drivers/mtd/nand/raw/plat_nand.c | 12 +----- drivers/mtd/nand/raw/qcom_nandc.c | 3 +- drivers/mtd/nand/raw/r852.c | 4 +- drivers/mtd/nand/raw/s3c2410.c | 6 +-- drivers/mtd/nand/raw/sh_flctl.c | 6 +-- drivers/mtd/nand/raw/socrates_nand.c | 7 ++-- drivers/mtd/nand/raw/sunxi_nand.c | 5 +-- drivers/mtd/nand/raw/tango_nand.c | 8 ++-- drivers/mtd/nand/raw/tmio_nand.c | 4 +- drivers/mtd/nand/raw/txx9ndfmc.c | 4 +- drivers/mtd/nand/raw/xway_nand.c | 4 +- drivers/staging/mt29f_spinand/mt29f_spinand.c | 4 +- include/linux/mtd/rawnand.h | 4 +- 42 files changed, 163 insertions(+), 203 deletions(-) diff --git a/drivers/mtd/nand/raw/ams-delta.c b/drivers/mtd/nand/raw/ams-delta.c index eb48c939c4ae..d742b9444429 100644 --- a/drivers/mtd/nand/raw/ams-delta.c +++ b/drivers/mtd/nand/raw/ams-delta.c @@ -63,9 +63,8 @@ static const struct mtd_partition partition_info[] = { .size = 3 * SZ_256K }, }; -static void ams_delta_write_byte(struct mtd_info *mtd, u_char byte) +static void ams_delta_write_byte(struct nand_chip *this, u_char byte) { - struct nand_chip *this = mtd_to_nand(mtd); void __iomem *io_base = (void __iomem *)nand_get_controller_data(this); writew(0, io_base + OMAP_MPUIO_IO_CNTL); @@ -89,13 +88,13 @@ static u_char ams_delta_read_byte(struct nand_chip *this) return res; } -static void ams_delta_write_buf(struct mtd_info *mtd, const u_char *buf, +static void ams_delta_write_buf(struct nand_chip *this, const u_char *buf, int len) { int i; for (i=0; iactivecs->io.virt); } -static void atmel_nand_write_byte(struct mtd_info *mtd, u8 byte) +static void atmel_nand_write_byte(struct nand_chip *chip, u8 byte) { - struct nand_chip *chip = mtd_to_nand(mtd); struct atmel_nand *nand = to_atmel_nand(chip); if (chip->options & NAND_BUSWIDTH_16) @@ -452,9 +451,8 @@ static void atmel_nand_read_buf(struct nand_chip *chip, u8 *buf, int len) ioread8_rep(nand->activecs->io.virt, buf, len); } -static void atmel_nand_write_buf(struct mtd_info *mtd, const u8 *buf, int len) +static void atmel_nand_write_buf(struct nand_chip *chip, const u8 *buf, int len) { - struct nand_chip *chip = mtd_to_nand(mtd); struct atmel_nand *nand = to_atmel_nand(chip); struct atmel_nand_controller *nc; @@ -841,7 +839,7 @@ static int atmel_nand_pmecc_write_pg(struct nand_chip *chip, const u8 *buf, if (ret) return ret; - atmel_nand_write_buf(mtd, buf, mtd->writesize); + atmel_nand_write_buf(chip, buf, mtd->writesize); ret = atmel_nand_pmecc_generate_eccbytes(chip, raw); if (ret) { @@ -851,7 +849,7 @@ static int atmel_nand_pmecc_write_pg(struct nand_chip *chip, const u8 *buf, atmel_nand_pmecc_disable(chip, raw); - atmel_nand_write_buf(mtd, chip->oob_poi, mtd->oobsize); + atmel_nand_write_buf(chip, chip->oob_poi, mtd->oobsize); return nand_prog_page_end_op(chip); } @@ -942,7 +940,7 @@ static int atmel_hsmc_nand_pmecc_write_pg(struct nand_chip *chip, if (ret) return ret; - atmel_nand_write_buf(mtd, chip->oob_poi, mtd->oobsize); + atmel_nand_write_buf(chip, chip->oob_poi, mtd->oobsize); nc->op.cmds[0] = NAND_CMD_PAGEPROG; nc->op.ncmds = 1; diff --git a/drivers/mtd/nand/raw/au1550nd.c b/drivers/mtd/nand/raw/au1550nd.c index 76ea4141eb10..f1cc9f672262 100644 --- a/drivers/mtd/nand/raw/au1550nd.c +++ b/drivers/mtd/nand/raw/au1550nd.c @@ -24,7 +24,7 @@ struct au1550nd_ctx { int cs; void __iomem *base; - void (*write_byte)(struct mtd_info *, u_char); + void (*write_byte)(struct nand_chip *, u_char); }; /** @@ -42,14 +42,13 @@ static u_char au_read_byte(struct nand_chip *this) /** * au_write_byte - write one byte to the chip - * @mtd: MTD device structure + * @this: NAND chip object * @byte: pointer to data byte to write * * write function for 8it buswidth */ -static void au_write_byte(struct mtd_info *mtd, u_char byte) +static void au_write_byte(struct nand_chip *this, u_char byte) { - struct nand_chip *this = mtd_to_nand(mtd); writeb(byte, this->IO_ADDR_W); wmb(); /* drain writebuffer */ } @@ -69,30 +68,28 @@ static u_char au_read_byte16(struct nand_chip *this) /** * au_write_byte16 - write one byte endianness aware to the chip - * @mtd: MTD device structure + * @this: NAND chip object * @byte: pointer to data byte to write * * write function for 16bit buswidth with endianness conversion */ -static void au_write_byte16(struct mtd_info *mtd, u_char byte) +static void au_write_byte16(struct nand_chip *this, u_char byte) { - struct nand_chip *this = mtd_to_nand(mtd); writew(le16_to_cpu((u16) byte), this->IO_ADDR_W); wmb(); /* drain writebuffer */ } /** * au_write_buf - write buffer to chip - * @mtd: MTD device structure + * @this: NAND chip object * @buf: data buffer * @len: number of bytes to write * * write function for 8bit buswidth */ -static void au_write_buf(struct mtd_info *mtd, const u_char *buf, int len) +static void au_write_buf(struct nand_chip *this, const u_char *buf, int len) { int i; - struct nand_chip *this = mtd_to_nand(mtd); for (i = 0; i < len; i++) { writeb(buf[i], this->IO_ADDR_W); @@ -120,16 +117,15 @@ static void au_read_buf(struct nand_chip *this, u_char *buf, int len) /** * au_write_buf16 - write buffer to chip - * @mtd: MTD device structure + * @this: NAND chip object * @buf: data buffer * @len: number of bytes to write * * write function for 16bit buswidth */ -static void au_write_buf16(struct mtd_info *mtd, const u_char *buf, int len) +static void au_write_buf16(struct nand_chip *this, const u_char *buf, int len) { int i; - struct nand_chip *this = mtd_to_nand(mtd); u16 *p = (u16 *) buf; len >>= 1; @@ -272,9 +268,9 @@ static void au1550_command(struct mtd_info *mtd, unsigned command, int column, i column -= 256; readcmd = NAND_CMD_READ1; } - ctx->write_byte(mtd, readcmd); + ctx->write_byte(this, readcmd); } - ctx->write_byte(mtd, command); + ctx->write_byte(this, command); /* Set ALE and clear CLE to start address cycle */ au1550_hwcontrol(mtd, NAND_CTL_CLRCLE); @@ -288,10 +284,10 @@ static void au1550_command(struct mtd_info *mtd, unsigned command, int column, i if (this->options & NAND_BUSWIDTH_16 && !nand_opcode_8bits(command)) column >>= 1; - ctx->write_byte(mtd, column); + ctx->write_byte(this, column); } if (page_addr != -1) { - ctx->write_byte(mtd, (u8)(page_addr & 0xff)); + ctx->write_byte(this, (u8)(page_addr & 0xff)); if (command == NAND_CMD_READ0 || command == NAND_CMD_READ1 || @@ -309,10 +305,10 @@ static void au1550_command(struct mtd_info *mtd, unsigned command, int column, i au1550_hwcontrol(mtd, NAND_CTL_SETNCE); } - ctx->write_byte(mtd, (u8)(page_addr >> 8)); + ctx->write_byte(this, (u8)(page_addr >> 8)); if (this->options & NAND_ROW_ADDR_3) - ctx->write_byte(mtd, + ctx->write_byte(this, ((page_addr >> 16) & 0x0f)); } /* Latch in address */ diff --git a/drivers/mtd/nand/raw/bcm47xxnflash/ops_bcm4706.c b/drivers/mtd/nand/raw/bcm47xxnflash/ops_bcm4706.c index cf3e45358c60..83eec2812aa0 100644 --- a/drivers/mtd/nand/raw/bcm47xxnflash/ops_bcm4706.c +++ b/drivers/mtd/nand/raw/bcm47xxnflash/ops_bcm4706.c @@ -354,15 +354,15 @@ static void bcm47xxnflash_ops_bcm4706_read_buf(struct nand_chip *nand_chip, pr_err("Invalid command for buf read: 0x%X\n", b47n->curr_command); } -static void bcm47xxnflash_ops_bcm4706_write_buf(struct mtd_info *mtd, +static void bcm47xxnflash_ops_bcm4706_write_buf(struct nand_chip *nand_chip, const uint8_t *buf, int len) { - struct nand_chip *nand_chip = mtd_to_nand(mtd); struct bcm47xxnflash *b47n = nand_get_controller_data(nand_chip); switch (b47n->curr_command) { case NAND_CMD_SEQIN: - bcm47xxnflash_ops_bcm4706_write(mtd, buf, len); + bcm47xxnflash_ops_bcm4706_write(nand_to_mtd(nand_chip), buf, + len); return; } diff --git a/drivers/mtd/nand/raw/brcmnand/brcmnand.c b/drivers/mtd/nand/raw/brcmnand/brcmnand.c index 7cbc6045f16d..e24e77b27618 100644 --- a/drivers/mtd/nand/raw/brcmnand/brcmnand.c +++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c @@ -1481,11 +1481,10 @@ static void brcmnand_read_buf(struct nand_chip *chip, uint8_t *buf, int len) *buf = brcmnand_read_byte(chip); } -static void brcmnand_write_buf(struct mtd_info *mtd, const uint8_t *buf, - int len) +static void brcmnand_write_buf(struct nand_chip *chip, const uint8_t *buf, + int len) { int i; - struct nand_chip *chip = mtd_to_nand(mtd); struct brcmnand_host *host = nand_get_controller_data(chip); switch (host->last_cmd) { diff --git a/drivers/mtd/nand/raw/cafe_nand.c b/drivers/mtd/nand/raw/cafe_nand.c index 97d835f88b86..f801333161c9 100644 --- a/drivers/mtd/nand/raw/cafe_nand.c +++ b/drivers/mtd/nand/raw/cafe_nand.c @@ -117,9 +117,8 @@ static int cafe_device_ready(struct mtd_info *mtd) } -static void cafe_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len) +static void cafe_write_buf(struct nand_chip *chip, const uint8_t *buf, int len) { - struct nand_chip *chip = mtd_to_nand(mtd); struct cafe_priv *cafe = nand_get_controller_data(chip); if (cafe->usedma) @@ -540,7 +539,7 @@ static int cafe_nand_write_page_lowlevel(struct nand_chip *chip, struct cafe_priv *cafe = nand_get_controller_data(chip); nand_prog_page_begin_op(chip, page, 0, buf, mtd->writesize); - chip->write_buf(mtd, chip->oob_poi, mtd->oobsize); + chip->write_buf(chip, chip->oob_poi, mtd->oobsize); /* Set up ECC autogeneration */ cafe->ctl2 |= (1<<30); diff --git a/drivers/mtd/nand/raw/cmx270_nand.c b/drivers/mtd/nand/raw/cmx270_nand.c index 232d32391b1f..4e5c8b7721ab 100644 --- a/drivers/mtd/nand/raw/cmx270_nand.c +++ b/drivers/mtd/nand/raw/cmx270_nand.c @@ -54,10 +54,10 @@ static u_char cmx270_read_byte(struct nand_chip *this) return (readl(this->IO_ADDR_R) >> 16); } -static void cmx270_write_buf(struct mtd_info *mtd, const u_char *buf, int len) +static void cmx270_write_buf(struct nand_chip *this, const u_char *buf, + int len) { int i; - struct nand_chip *this = mtd_to_nand(mtd); for (i=0; iIO_ADDR_W); diff --git a/drivers/mtd/nand/raw/cs553x_nand.c b/drivers/mtd/nand/raw/cs553x_nand.c index 4394eeebec7f..442fa583db44 100644 --- a/drivers/mtd/nand/raw/cs553x_nand.c +++ b/drivers/mtd/nand/raw/cs553x_nand.c @@ -103,10 +103,8 @@ static void cs553x_read_buf(struct nand_chip *this, u_char *buf, int len) memcpy_fromio(buf, this->IO_ADDR_R, len); } -static void cs553x_write_buf(struct mtd_info *mtd, const u_char *buf, int len) +static void cs553x_write_buf(struct nand_chip *this, const u_char *buf, int len) { - struct nand_chip *this = mtd_to_nand(mtd); - while (unlikely(len > 0x800)) { memcpy_toio(this->IO_ADDR_R, buf, 0x800); buf += 0x800; @@ -120,9 +118,8 @@ static unsigned char cs553x_read_byte(struct nand_chip *this) return readb(this->IO_ADDR_R); } -static void cs553x_write_byte(struct mtd_info *mtd, u_char byte) +static void cs553x_write_byte(struct nand_chip *this, u_char byte) { - struct nand_chip *this = mtd_to_nand(mtd); int i = 100000; while (i && readb(this->IO_ADDR_R + MM_NAND_STS) & CS_NAND_CTLR_BUSY) { @@ -142,7 +139,7 @@ static void cs553x_hwcontrol(struct mtd_info *mtd, int cmd, writeb(ctl, mmio_base + MM_NAND_CTL); } if (cmd != NAND_CMD_NONE) - cs553x_write_byte(mtd, cmd); + cs553x_write_byte(this, cmd); } static int cs553x_device_ready(struct mtd_info *mtd) diff --git a/drivers/mtd/nand/raw/davinci_nand.c b/drivers/mtd/nand/raw/davinci_nand.c index b879049e51c6..02a2d3b05e34 100644 --- a/drivers/mtd/nand/raw/davinci_nand.c +++ b/drivers/mtd/nand/raw/davinci_nand.c @@ -446,11 +446,9 @@ static void nand_davinci_read_buf(struct nand_chip *chip, uint8_t *buf, ioread8_rep(chip->IO_ADDR_R, buf, len); } -static void nand_davinci_write_buf(struct mtd_info *mtd, - const uint8_t *buf, int len) +static void nand_davinci_write_buf(struct nand_chip *chip, const uint8_t *buf, + int len) { - struct nand_chip *chip = mtd_to_nand(mtd); - if ((0x03 & ((uintptr_t)buf)) == 0 && (0x03 & len) == 0) iowrite32_rep(chip->IO_ADDR_R, buf, len >> 2); else if ((0x01 & ((uintptr_t)buf)) == 0 && (0x01 & len) == 0) diff --git a/drivers/mtd/nand/raw/denali.c b/drivers/mtd/nand/raw/denali.c index 6e5be3efcb5d..101ffa11b606 100644 --- a/drivers/mtd/nand/raw/denali.c +++ b/drivers/mtd/nand/raw/denali.c @@ -226,9 +226,10 @@ static void denali_read_buf(struct nand_chip *chip, uint8_t *buf, int len) buf[i] = denali->host_read(denali, addr); } -static void denali_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len) +static void denali_write_buf(struct nand_chip *chip, const uint8_t *buf, + int len) { - struct denali_nand_info *denali = mtd_to_denali(mtd); + struct denali_nand_info *denali = mtd_to_denali(nand_to_mtd(chip)); u32 addr = DENALI_MAP11_DATA | DENALI_BANK(denali); int i; @@ -247,10 +248,10 @@ static void denali_read_buf16(struct nand_chip *chip, uint8_t *buf, int len) buf16[i] = denali->host_read(denali, addr); } -static void denali_write_buf16(struct mtd_info *mtd, const uint8_t *buf, +static void denali_write_buf16(struct nand_chip *chip, const uint8_t *buf, int len) { - struct denali_nand_info *denali = mtd_to_denali(mtd); + struct denali_nand_info *denali = mtd_to_denali(nand_to_mtd(chip)); u32 addr = DENALI_MAP11_DATA | DENALI_BANK(denali); const uint16_t *buf16 = (const uint16_t *)buf; int i; @@ -268,9 +269,9 @@ static uint8_t denali_read_byte(struct nand_chip *chip) return byte; } -static void denali_write_byte(struct mtd_info *mtd, uint8_t byte) +static void denali_write_byte(struct nand_chip *chip, uint8_t byte) { - denali_write_buf(mtd, &byte, 1); + denali_write_buf(chip, &byte, 1); } static void denali_cmd_ctrl(struct mtd_info *mtd, int dat, unsigned int ctrl) diff --git a/drivers/mtd/nand/raw/diskonchip.c b/drivers/mtd/nand/raw/diskonchip.c index de1059069e8f..a1bc2f7436db 100644 --- a/drivers/mtd/nand/raw/diskonchip.c +++ b/drivers/mtd/nand/raw/diskonchip.c @@ -290,9 +290,8 @@ static inline int DoC_WaitReady(struct doc_priv *doc) return ret; } -static void doc2000_write_byte(struct mtd_info *mtd, u_char datum) +static void doc2000_write_byte(struct nand_chip *this, u_char datum) { - struct nand_chip *this = mtd_to_nand(mtd); struct doc_priv *doc = nand_get_controller_data(this); void __iomem *docptr = doc->virtadr; @@ -316,9 +315,9 @@ static u_char doc2000_read_byte(struct nand_chip *this) return ret; } -static void doc2000_writebuf(struct mtd_info *mtd, const u_char *buf, int len) +static void doc2000_writebuf(struct nand_chip *this, const u_char *buf, + int len) { - struct nand_chip *this = mtd_to_nand(mtd); struct doc_priv *doc = nand_get_controller_data(this); void __iomem *docptr = doc->virtadr; int i; @@ -448,9 +447,8 @@ static int doc200x_wait(struct mtd_info *mtd, struct nand_chip *this) return status; } -static void doc2001_write_byte(struct mtd_info *mtd, u_char datum) +static void doc2001_write_byte(struct nand_chip *this, u_char datum) { - struct nand_chip *this = mtd_to_nand(mtd); struct doc_priv *doc = nand_get_controller_data(this); void __iomem *docptr = doc->virtadr; @@ -472,9 +470,8 @@ static u_char doc2001_read_byte(struct nand_chip *this) return ReadDOC(docptr, LastDataRead); } -static void doc2001_writebuf(struct mtd_info *mtd, const u_char *buf, int len) +static void doc2001_writebuf(struct nand_chip *this, const u_char *buf, int len) { - struct nand_chip *this = mtd_to_nand(mtd); struct doc_priv *doc = nand_get_controller_data(this); void __iomem *docptr = doc->virtadr; int i; @@ -515,9 +512,8 @@ static u_char doc2001plus_read_byte(struct nand_chip *this) return ret; } -static void doc2001plus_writebuf(struct mtd_info *mtd, const u_char *buf, int len) +static void doc2001plus_writebuf(struct nand_chip *this, const u_char *buf, int len) { - struct nand_chip *this = mtd_to_nand(mtd); struct doc_priv *doc = nand_get_controller_data(this); void __iomem *docptr = doc->virtadr; int i; @@ -638,9 +634,9 @@ static void doc200x_hwcontrol(struct mtd_info *mtd, int cmd, } if (cmd != NAND_CMD_NONE) { if (DoC_is_2000(doc)) - doc2000_write_byte(mtd, cmd); + doc2000_write_byte(this, cmd); else - doc2001_write_byte(mtd, cmd); + doc2001_write_byte(this, cmd); } } diff --git a/drivers/mtd/nand/raw/docg4.c b/drivers/mtd/nand/raw/docg4.c index 284bc96dacd3..9cbe87448e77 100644 --- a/drivers/mtd/nand/raw/docg4.c +++ b/drivers/mtd/nand/raw/docg4.c @@ -271,10 +271,10 @@ static void docg4_read_buf(struct nand_chip *nand, uint8_t *buf, int len) p[i] = readw(nand->IO_ADDR_R); } -static void docg4_write_buf16(struct mtd_info *mtd, const uint8_t *buf, int len) +static void docg4_write_buf16(struct nand_chip *nand, const uint8_t *buf, + int len) { int i; - struct nand_chip *nand = mtd_to_nand(mtd); uint16_t *p = (uint16_t *) buf; len >>= 1; @@ -964,10 +964,10 @@ static int write_page(struct mtd_info *mtd, struct nand_chip *nand, write_nop(docptr); /* write the page data */ - docg4_write_buf16(mtd, buf, DOCG4_PAGE_SIZE); + docg4_write_buf16(nand, buf, DOCG4_PAGE_SIZE); /* oob bytes 0 through 5 are written to I/O reg */ - docg4_write_buf16(mtd, nand->oob_poi, 6); + docg4_write_buf16(nand, nand->oob_poi, 6); /* oob byte 6 written to a separate reg */ writew(nand->oob_poi[6], docptr + DOCG4_OOB_6_7); @@ -995,7 +995,7 @@ static int write_page(struct mtd_info *mtd, struct nand_chip *nand, memcpy(ecc_buf, &nand->oob_poi[8], 8); } - docg4_write_buf16(mtd, ecc_buf, 8); + docg4_write_buf16(nand, ecc_buf, 8); write_nop(docptr); write_nop(docptr); writew(0, docptr + DOC_DATAEND); diff --git a/drivers/mtd/nand/raw/fsl_elbc_nand.c b/drivers/mtd/nand/raw/fsl_elbc_nand.c index 22326bcb8b62..14d246323e94 100644 --- a/drivers/mtd/nand/raw/fsl_elbc_nand.c +++ b/drivers/mtd/nand/raw/fsl_elbc_nand.c @@ -543,9 +543,9 @@ static void fsl_elbc_select_chip(struct mtd_info *mtd, int chip) /* * Write buf to the FCM Controller Data Buffer */ -static void fsl_elbc_write_buf(struct mtd_info *mtd, const u8 *buf, int len) +static void fsl_elbc_write_buf(struct nand_chip *chip, const u8 *buf, int len) { - struct nand_chip *chip = mtd_to_nand(mtd); + struct mtd_info *mtd = nand_to_mtd(chip); struct fsl_elbc_mtd *priv = nand_get_controller_data(chip); struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand; unsigned int bufsize = mtd->writesize + mtd->oobsize; @@ -735,7 +735,7 @@ static int fsl_elbc_write_page(struct nand_chip *chip, const uint8_t *buf, struct mtd_info *mtd = nand_to_mtd(chip); nand_prog_page_begin_op(chip, page, 0, buf, mtd->writesize); - fsl_elbc_write_buf(mtd, chip->oob_poi, mtd->oobsize); + fsl_elbc_write_buf(chip, chip->oob_poi, mtd->oobsize); return nand_prog_page_end_op(chip); } @@ -750,8 +750,8 @@ static int fsl_elbc_write_subpage(struct nand_chip *chip, uint32_t offset, struct mtd_info *mtd = nand_to_mtd(chip); nand_prog_page_begin_op(chip, page, 0, NULL, 0); - fsl_elbc_write_buf(mtd, buf, mtd->writesize); - fsl_elbc_write_buf(mtd, chip->oob_poi, mtd->oobsize); + fsl_elbc_write_buf(chip, buf, mtd->writesize); + fsl_elbc_write_buf(chip, chip->oob_poi, mtd->oobsize); return nand_prog_page_end_op(chip); } diff --git a/drivers/mtd/nand/raw/fsl_ifc_nand.c b/drivers/mtd/nand/raw/fsl_ifc_nand.c index 7b6d0913a5bb..2e032db997a5 100644 --- a/drivers/mtd/nand/raw/fsl_ifc_nand.c +++ b/drivers/mtd/nand/raw/fsl_ifc_nand.c @@ -519,9 +519,9 @@ static void fsl_ifc_select_chip(struct mtd_info *mtd, int chip) /* * Write buf to the IFC NAND Controller Data Buffer */ -static void fsl_ifc_write_buf(struct mtd_info *mtd, const u8 *buf, int len) +static void fsl_ifc_write_buf(struct nand_chip *chip, const u8 *buf, int len) { - struct nand_chip *chip = mtd_to_nand(mtd); + struct mtd_info *mtd = nand_to_mtd(chip); struct fsl_ifc_mtd *priv = nand_get_controller_data(chip); unsigned int bufsize = mtd->writesize + mtd->oobsize; @@ -710,7 +710,7 @@ static int fsl_ifc_write_page(struct nand_chip *chip, const uint8_t *buf, struct mtd_info *mtd = nand_to_mtd(chip); nand_prog_page_begin_op(chip, page, 0, buf, mtd->writesize); - fsl_ifc_write_buf(mtd, chip->oob_poi, mtd->oobsize); + fsl_ifc_write_buf(chip, chip->oob_poi, mtd->oobsize); return nand_prog_page_end_op(chip); } diff --git a/drivers/mtd/nand/raw/fsl_upm.c b/drivers/mtd/nand/raw/fsl_upm.c index 340547f1b6c7..d3d3adcb7282 100644 --- a/drivers/mtd/nand/raw/fsl_upm.c +++ b/drivers/mtd/nand/raw/fsl_upm.c @@ -140,9 +140,9 @@ static void fun_read_buf(struct nand_chip *chip, uint8_t *buf, int len) buf[i] = in_8(fun->chip.IO_ADDR_R); } -static void fun_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len) +static void fun_write_buf(struct nand_chip *chip, const uint8_t *buf, int len) { - struct fsl_upm_nand *fun = to_fsl_upm_nand(mtd); + struct fsl_upm_nand *fun = to_fsl_upm_nand(nand_to_mtd(chip)); int i; for (i = 0; i < len; i++) { diff --git a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c index d0d5caa1b7a6..bd1b8445b358 100644 --- a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c +++ b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c @@ -868,9 +868,8 @@ static void gpmi_read_buf(struct nand_chip *chip, uint8_t *buf, int len) gpmi_read_data(this, buf, len); } -static void gpmi_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len) +static void gpmi_write_buf(struct nand_chip *chip, const uint8_t *buf, int len) { - struct nand_chip *chip = mtd_to_nand(mtd); struct gpmi_nand_data *this = nand_get_controller_data(chip); dev_dbg(this->dev, "len is %d\n", len); diff --git a/drivers/mtd/nand/raw/hisi504_nand.c b/drivers/mtd/nand/raw/hisi504_nand.c index e1fe6963c908..b4e5bfd30022 100644 --- a/drivers/mtd/nand/raw/hisi504_nand.c +++ b/drivers/mtd/nand/raw/hisi504_nand.c @@ -380,9 +380,8 @@ static uint8_t hisi_nfc_read_byte(struct nand_chip *chip) } static void -hisi_nfc_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len) +hisi_nfc_write_buf(struct nand_chip *chip, const uint8_t *buf, int len) { - struct nand_chip *chip = mtd_to_nand(mtd); struct hinfc_host *host = nand_get_controller_data(chip); memcpy(host->buffer + host->offset, buf, len); @@ -583,7 +582,7 @@ static int hisi_nand_write_page_hwecc(struct nand_chip *chip, nand_prog_page_begin_op(chip, page, 0, buf, mtd->writesize); if (oob_required) - chip->write_buf(mtd, chip->oob_poi, mtd->oobsize); + chip->write_buf(chip, chip->oob_poi, mtd->oobsize); return nand_prog_page_end_op(chip); } diff --git a/drivers/mtd/nand/raw/lpc32xx_slc.c b/drivers/mtd/nand/raw/lpc32xx_slc.c index 5820c86cb1f1..d04b30989041 100644 --- a/drivers/mtd/nand/raw/lpc32xx_slc.c +++ b/drivers/mtd/nand/raw/lpc32xx_slc.c @@ -381,9 +381,9 @@ static void lpc32xx_nand_read_buf(struct nand_chip *chip, u_char *buf, int len) /* * Simple device write without ECC */ -static void lpc32xx_nand_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len) +static void lpc32xx_nand_write_buf(struct nand_chip *chip, const uint8_t *buf, + int len) { - struct nand_chip *chip = mtd_to_nand(mtd); struct lpc32xx_nand_host *host = nand_get_controller_data(chip); /* Direct device write with no ECC */ @@ -706,7 +706,7 @@ static int lpc32xx_nand_write_page_syndrome(struct nand_chip *chip, lpc32xx_slc_ecc_copy(pb, (uint32_t *)host->ecc_buf, chip->ecc.steps); /* Write ECC data to device */ - chip->write_buf(mtd, chip->oob_poi, mtd->oobsize); + chip->write_buf(chip, chip->oob_poi, mtd->oobsize); return nand_prog_page_end_op(chip); } @@ -724,7 +724,7 @@ static int lpc32xx_nand_write_page_raw_syndrome(struct nand_chip *chip, /* Raw writes can just use the FIFO interface */ nand_prog_page_begin_op(chip, page, 0, buf, chip->ecc.size * chip->ecc.steps); - chip->write_buf(mtd, chip->oob_poi, mtd->oobsize); + chip->write_buf(chip, chip->oob_poi, mtd->oobsize); return nand_prog_page_end_op(chip); } diff --git a/drivers/mtd/nand/raw/mpc5121_nfc.c b/drivers/mtd/nand/raw/mpc5121_nfc.c index 49031f5a3b6d..dc573a0b5fe1 100644 --- a/drivers/mtd/nand/raw/mpc5121_nfc.c +++ b/drivers/mtd/nand/raw/mpc5121_nfc.c @@ -499,10 +499,10 @@ static void mpc5121_nfc_read_buf(struct nand_chip *chip, u_char *buf, int len) } /* Write data to NFC buffers */ -static void mpc5121_nfc_write_buf(struct mtd_info *mtd, - const u_char *buf, int len) +static void mpc5121_nfc_write_buf(struct nand_chip *chip, const u_char *buf, + int len) { - mpc5121_nfc_buf_copy(mtd, (u_char *)buf, len, 1); + mpc5121_nfc_buf_copy(nand_to_mtd(chip), (u_char *)buf, len, 1); } /* Read byte from NFC buffers */ diff --git a/drivers/mtd/nand/raw/mtk_nand.c b/drivers/mtd/nand/raw/mtk_nand.c index 1c7392242d4d..bd2002a1fabd 100644 --- a/drivers/mtd/nand/raw/mtk_nand.c +++ b/drivers/mtd/nand/raw/mtk_nand.c @@ -474,9 +474,9 @@ static void mtk_nfc_read_buf(struct nand_chip *chip, u8 *buf, int len) buf[i] = mtk_nfc_read_byte(chip); } -static void mtk_nfc_write_byte(struct mtd_info *mtd, u8 byte) +static void mtk_nfc_write_byte(struct nand_chip *chip, u8 byte) { - struct mtk_nfc *nfc = nand_get_controller_data(mtd_to_nand(mtd)); + struct mtk_nfc *nfc = nand_get_controller_data(chip); u32 reg; reg = nfi_readl(nfc, NFI_STA) & NFI_FSM_MASK; @@ -495,12 +495,12 @@ static void mtk_nfc_write_byte(struct mtd_info *mtd, u8 byte) nfi_writeb(nfc, byte, NFI_DATAW); } -static void mtk_nfc_write_buf(struct mtd_info *mtd, const u8 *buf, int len) +static void mtk_nfc_write_buf(struct nand_chip *chip, const u8 *buf, int len) { int i; for (i = 0; i < len; i++) - mtk_nfc_write_byte(mtd, buf[i]); + mtk_nfc_write_byte(chip, buf[i]); } static int mtk_nfc_setup_data_interface(struct mtd_info *mtd, int csline, diff --git a/drivers/mtd/nand/raw/mxc_nand.c b/drivers/mtd/nand/raw/mxc_nand.c index 8fed2919f35e..d5d8f8c16b60 100644 --- a/drivers/mtd/nand/raw/mxc_nand.c +++ b/drivers/mtd/nand/raw/mxc_nand.c @@ -921,10 +921,10 @@ static u_char mxc_nand_read_byte(struct nand_chip *nand_chip) /* Write data of length len to buffer buf. The data to be * written on NAND Flash is first copied to RAMbuffer. After the Data Input * Operation by the NFC, the data is written to NAND Flash */ -static void mxc_nand_write_buf(struct mtd_info *mtd, - const u_char *buf, int len) +static void mxc_nand_write_buf(struct nand_chip *nand_chip, const u_char *buf, + int len) { - struct nand_chip *nand_chip = mtd_to_nand(mtd); + struct mtd_info *mtd = nand_to_mtd(nand_chip); struct mxc_nand_host *host = nand_get_controller_data(nand_chip); u16 col = host->buf_start; int n = mtd->oobsize + mtd->writesize - col; @@ -1405,7 +1405,7 @@ static int mxc_nand_set_features(struct mtd_info *mtd, struct nand_chip *chip, host->buf_start = 0; for (i = 0; i < ONFI_SUBFEATURE_PARAM_LEN; ++i) - chip->write_byte(mtd, subfeature_param[i]); + chip->write_byte(chip, subfeature_param[i]); memcpy32_toio(host->main_area0, host->data_buf, mtd->writesize); host->devtype_data->send_cmd(host, NAND_CMD_SET_FEATURES, false); diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c index e4686078011d..6c20c0b805a3 100644 --- a/drivers/mtd/nand/raw/nand_base.c +++ b/drivers/mtd/nand/raw/nand_base.c @@ -300,28 +300,25 @@ static void nand_select_chip(struct mtd_info *mtd, int chipnr) /** * nand_write_byte - [DEFAULT] write single byte to chip - * @mtd: MTD device structure + * @chip: NAND chip object * @byte: value to write * * Default function to write a byte to I/O[7:0] */ -static void nand_write_byte(struct mtd_info *mtd, uint8_t byte) +static void nand_write_byte(struct nand_chip *chip, uint8_t byte) { - struct nand_chip *chip = mtd_to_nand(mtd); - - chip->write_buf(mtd, &byte, 1); + chip->write_buf(chip, &byte, 1); } /** * nand_write_byte16 - [DEFAULT] write single byte to a chip with width 16 - * @mtd: MTD device structure + * @chip: NAND chip object * @byte: value to write * * Default function to write a byte to I/O[7:0] on a 16-bit wide chip. */ -static void nand_write_byte16(struct mtd_info *mtd, uint8_t byte) +static void nand_write_byte16(struct nand_chip *chip, uint8_t byte) { - struct nand_chip *chip = mtd_to_nand(mtd); uint16_t word = byte; /* @@ -340,21 +337,19 @@ static void nand_write_byte16(struct mtd_info *mtd, uint8_t byte) * neither an address nor a command transfer. Let's assume a 0 on the * upper I/O lines is OK. */ - chip->write_buf(mtd, (uint8_t *)&word, 2); + chip->write_buf(chip, (uint8_t *)&word, 2); } /** * nand_write_buf - [DEFAULT] write buffer to chip - * @mtd: MTD device structure + * @chip: NAND chip object * @buf: data buffer * @len: number of bytes to write * * Default write function for 8bit buswidth. */ -static void nand_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len) +static void nand_write_buf(struct nand_chip *chip, const uint8_t *buf, int len) { - struct nand_chip *chip = mtd_to_nand(mtd); - iowrite8_rep(chip->IO_ADDR_W, buf, len); } @@ -373,15 +368,15 @@ static void nand_read_buf(struct nand_chip *chip, uint8_t *buf, int len) /** * nand_write_buf16 - [DEFAULT] write buffer to chip - * @mtd: MTD device structure + * @chip: NAND chip object * @buf: data buffer * @len: number of bytes to write * * Default write function for 16bit buswidth. */ -static void nand_write_buf16(struct mtd_info *mtd, const uint8_t *buf, int len) +static void nand_write_buf16(struct nand_chip *chip, const uint8_t *buf, + int len) { - struct nand_chip *chip = mtd_to_nand(mtd); u16 *p = (u16 *) buf; iowrite16_rep(chip->IO_ADDR_W, p, len >> 1); @@ -1801,7 +1796,7 @@ int nand_prog_page_begin_op(struct nand_chip *chip, unsigned int page, chip->cmdfunc(mtd, NAND_CMD_SEQIN, offset_in_page, page); if (buf) - chip->write_buf(mtd, buf, len); + chip->write_buf(chip, buf, len); return 0; } @@ -1886,7 +1881,7 @@ int nand_prog_page_op(struct nand_chip *chip, unsigned int page, len, true); } else { chip->cmdfunc(mtd, NAND_CMD_SEQIN, offset_in_page, page); - chip->write_buf(mtd, buf, len); + chip->write_buf(chip, buf, len); chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1); status = chip->waitfunc(mtd, chip); } @@ -1955,7 +1950,7 @@ int nand_change_write_column_op(struct nand_chip *chip, chip->cmdfunc(mtd, NAND_CMD_RNDIN, offset_in_page, -1); if (len) - chip->write_buf(mtd, buf, len); + chip->write_buf(chip, buf, len); return 0; } @@ -2175,7 +2170,7 @@ static int nand_set_features_op(struct nand_chip *chip, u8 feature, chip->cmdfunc(mtd, NAND_CMD_SET_FEATURES, feature, -1); for (i = 0; i < ONFI_SUBFEATURE_PARAM_LEN; ++i) - chip->write_byte(mtd, params[i]); + chip->write_byte(chip, params[i]); ret = chip->waitfunc(mtd, chip); if (ret < 0) @@ -2343,8 +2338,6 @@ EXPORT_SYMBOL_GPL(nand_read_data_op); int nand_write_data_op(struct nand_chip *chip, const void *buf, unsigned int len, bool force_8bit) { - struct mtd_info *mtd = nand_to_mtd(chip); - if (!len || !buf) return -EINVAL; @@ -2364,9 +2357,9 @@ int nand_write_data_op(struct nand_chip *chip, const void *buf, unsigned int i; for (i = 0; i < len; i++) - chip->write_byte(mtd, p[i]); + chip->write_byte(chip, p[i]); } else { - chip->write_buf(mtd, buf, len); + chip->write_buf(chip, buf, len); } return 0; diff --git a/drivers/mtd/nand/raw/nand_hynix.c b/drivers/mtd/nand/raw/nand_hynix.c index 4ffbb26e76d6..197256c2e1ee 100644 --- a/drivers/mtd/nand/raw/nand_hynix.c +++ b/drivers/mtd/nand/raw/nand_hynix.c @@ -111,7 +111,7 @@ static int hynix_nand_reg_write_op(struct nand_chip *chip, u8 addr, u8 val) } chip->cmdfunc(mtd, NAND_CMD_NONE, column, -1); - chip->write_byte(mtd, val); + chip->write_byte(chip, val); return 0; } diff --git a/drivers/mtd/nand/raw/nandsim.c b/drivers/mtd/nand/raw/nandsim.c index 04feb4e8d112..880ba12e07ba 100644 --- a/drivers/mtd/nand/raw/nandsim.c +++ b/drivers/mtd/nand/raw/nandsim.c @@ -1933,9 +1933,8 @@ static u_char ns_nand_read_byte(struct nand_chip *chip) return outb; } -static void ns_nand_write_byte(struct mtd_info *mtd, u_char byte) +static void ns_nand_write_byte(struct nand_chip *chip, u_char byte) { - struct nand_chip *chip = mtd_to_nand(mtd); struct nandsim *ns = nand_get_controller_data(chip); /* Sanity and correctness checks */ @@ -2098,7 +2097,7 @@ static void ns_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int bitmask) ns->lines.ce = bitmask & NAND_NCE ? 1 : 0; if (cmd != NAND_CMD_NONE) - ns_nand_write_byte(mtd, cmd); + ns_nand_write_byte(chip, cmd); } static int ns_device_ready(struct mtd_info *mtd) @@ -2107,9 +2106,9 @@ static int ns_device_ready(struct mtd_info *mtd) return 1; } -static void ns_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len) +static void ns_nand_write_buf(struct nand_chip *chip, const u_char *buf, + int len) { - struct nand_chip *chip = mtd_to_nand(mtd); struct nandsim *ns = nand_get_controller_data(chip); /* Check that chip is expecting data input */ diff --git a/drivers/mtd/nand/raw/ndfc.c b/drivers/mtd/nand/raw/ndfc.c index 56bb1eaa5ef3..02b102addeb5 100644 --- a/drivers/mtd/nand/raw/ndfc.c +++ b/drivers/mtd/nand/raw/ndfc.c @@ -125,9 +125,8 @@ static void ndfc_read_buf(struct nand_chip *chip, uint8_t *buf, int len) *p++ = in_be32(ndfc->ndfcbase + NDFC_DATA); } -static void ndfc_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len) +static void ndfc_write_buf(struct nand_chip *chip, const uint8_t *buf, int len) { - struct nand_chip *chip = mtd_to_nand(mtd); struct ndfc_controller *ndfc = nand_get_controller_data(chip); uint32_t *p = (uint32_t *) buf; diff --git a/drivers/mtd/nand/raw/nuc900_nand.c b/drivers/mtd/nand/raw/nuc900_nand.c index 3a88da5ec97f..357b3cf03195 100644 --- a/drivers/mtd/nand/raw/nuc900_nand.c +++ b/drivers/mtd/nand/raw/nuc900_nand.c @@ -99,11 +99,11 @@ static void nuc900_nand_read_buf(struct nand_chip *chip, buf[i] = (unsigned char)read_data_reg(nand); } -static void nuc900_nand_write_buf(struct mtd_info *mtd, +static void nuc900_nand_write_buf(struct nand_chip *chip, const unsigned char *buf, int len) { int i; - struct nuc900_nand *nand = mtd_to_nuc900(mtd); + struct nuc900_nand *nand = mtd_to_nuc900(nand_to_mtd(chip)); for (i = 0; i < len; i++) write_data_reg(nand, buf[i]); diff --git a/drivers/mtd/nand/raw/omap2.c b/drivers/mtd/nand/raw/omap2.c index 4f2e5cd86050..5a2bf1ed9c86 100644 --- a/drivers/mtd/nand/raw/omap2.c +++ b/drivers/mtd/nand/raw/omap2.c @@ -384,13 +384,14 @@ static void omap_read_buf_pref(struct nand_chip *chip, u_char *buf, int len) /** * omap_write_buf_pref - write buffer to NAND controller - * @mtd: MTD device structure + * @chip: NAND chip object * @buf: data buffer * @len: number of bytes to write */ -static void omap_write_buf_pref(struct mtd_info *mtd, - const u_char *buf, int len) +static void omap_write_buf_pref(struct nand_chip *chip, const u_char *buf, + int len) { + struct mtd_info *mtd = nand_to_mtd(chip); struct omap_nand_info *info = mtd_to_omap(mtd); uint32_t w_count = 0; int i = 0, ret = 0; @@ -547,18 +548,20 @@ static void omap_read_buf_dma_pref(struct nand_chip *chip, u_char *buf, /** * omap_write_buf_dma_pref - write buffer to NAND controller - * @mtd: MTD device structure + * @chip: NAND chip object * @buf: data buffer * @len: number of bytes to write */ -static void omap_write_buf_dma_pref(struct mtd_info *mtd, - const u_char *buf, int len) +static void omap_write_buf_dma_pref(struct nand_chip *chip, const u_char *buf, + int len) { + struct mtd_info *mtd = nand_to_mtd(chip); + if (len <= mtd->oobsize) - omap_write_buf_pref(mtd, buf, len); + omap_write_buf_pref(chip, buf, len); else /* start transfer in DMA mode */ - omap_nand_dma_transfer(mtd, (u_char *) buf, len, 0x1); + omap_nand_dma_transfer(mtd, (u_char *)buf, len, 0x1); } /* @@ -657,20 +660,21 @@ static void omap_read_buf_irq_pref(struct nand_chip *chip, u_char *buf, /* * omap_write_buf_irq_pref - write buffer to NAND controller - * @mtd: MTD device structure + * @chip: NAND chip object * @buf: data buffer * @len: number of bytes to write */ -static void omap_write_buf_irq_pref(struct mtd_info *mtd, - const u_char *buf, int len) +static void omap_write_buf_irq_pref(struct nand_chip *chip, const u_char *buf, + int len) { + struct mtd_info *mtd = nand_to_mtd(chip); struct omap_nand_info *info = mtd_to_omap(mtd); int ret = 0; unsigned long tim, limit; u32 val; if (len <= mtd->oobsize) { - omap_write_buf_pref(mtd, buf, len); + omap_write_buf_pref(chip, buf, len); return; } @@ -1537,7 +1541,7 @@ static int omap_write_page_bch(struct nand_chip *chip, const uint8_t *buf, chip->ecc.hwctl(chip, NAND_ECC_WRITE); /* Write data */ - chip->write_buf(mtd, buf, mtd->writesize); + chip->write_buf(chip, buf, mtd->writesize); /* Update ecc vector from GPMC result registers */ omap_calculate_ecc_bch_multi(mtd, buf, &ecc_calc[0]); @@ -1548,7 +1552,7 @@ static int omap_write_page_bch(struct nand_chip *chip, const uint8_t *buf, return ret; /* Write ecc vector to OOB area */ - chip->write_buf(mtd, chip->oob_poi, mtd->oobsize); + chip->write_buf(chip, chip->oob_poi, mtd->oobsize); return nand_prog_page_end_op(chip); } @@ -1589,7 +1593,7 @@ static int omap_write_subpage_bch(struct nand_chip *chip, u32 offset, chip->ecc.hwctl(chip, NAND_ECC_WRITE); /* Write data */ - chip->write_buf(mtd, buf, mtd->writesize); + chip->write_buf(chip, buf, mtd->writesize); for (step = 0; step < ecc_steps; step++) { /* mask ECC of un-touched subpages by padding 0xFF */ @@ -1614,7 +1618,7 @@ static int omap_write_subpage_bch(struct nand_chip *chip, u32 offset, return ret; /* write OOB buffer to NAND device */ - chip->write_buf(mtd, chip->oob_poi, mtd->oobsize); + chip->write_buf(chip, chip->oob_poi, mtd->oobsize); return nand_prog_page_end_op(chip); } diff --git a/drivers/mtd/nand/raw/oxnas_nand.c b/drivers/mtd/nand/raw/oxnas_nand.c index 6156abb30b7a..93c04bec471d 100644 --- a/drivers/mtd/nand/raw/oxnas_nand.c +++ b/drivers/mtd/nand/raw/oxnas_nand.c @@ -52,9 +52,9 @@ static void oxnas_nand_read_buf(struct nand_chip *chip, u8 *buf, int len) ioread8_rep(oxnas->io_base, buf, len); } -static void oxnas_nand_write_buf(struct mtd_info *mtd, const u8 *buf, int len) +static void oxnas_nand_write_buf(struct nand_chip *chip, const u8 *buf, + int len) { - struct nand_chip *chip = mtd_to_nand(mtd); struct oxnas_nand_ctrl *oxnas = nand_get_controller_data(chip); iowrite8_rep(oxnas->io_base, buf, len); diff --git a/drivers/mtd/nand/raw/pasemi_nand.c b/drivers/mtd/nand/raw/pasemi_nand.c index 551e5db670be..70aff4180ab7 100644 --- a/drivers/mtd/nand/raw/pasemi_nand.c +++ b/drivers/mtd/nand/raw/pasemi_nand.c @@ -53,10 +53,9 @@ static void pasemi_read_buf(struct nand_chip *chip, u_char *buf, int len) memcpy_fromio(buf, chip->IO_ADDR_R, len); } -static void pasemi_write_buf(struct mtd_info *mtd, const u_char *buf, int len) +static void pasemi_write_buf(struct nand_chip *chip, const u_char *buf, + int len) { - struct nand_chip *chip = mtd_to_nand(mtd); - while (len > 0x800) { memcpy_toio(chip->IO_ADDR_R, buf, 0x800); buf += 0x800; diff --git a/drivers/mtd/nand/raw/plat_nand.c b/drivers/mtd/nand/raw/plat_nand.c index 5193806923ba..adfc3f50e8d5 100644 --- a/drivers/mtd/nand/raw/plat_nand.c +++ b/drivers/mtd/nand/raw/plat_nand.c @@ -44,14 +44,6 @@ static void plat_nand_select_chip(struct mtd_info *mtd, int cs) pdata->ctrl.select_chip(mtd_to_nand(mtd), cs); } -static void plat_nand_write_buf(struct mtd_info *mtd, const uint8_t *buf, - int len) -{ - struct platform_nand_data *pdata = dev_get_platdata(mtd->dev.parent); - - pdata->ctrl.write_buf(mtd_to_nand(mtd), buf, len); -} - /* * Probe for the NAND device. */ @@ -101,9 +93,7 @@ static int plat_nand_probe(struct platform_device *pdev) if (pdata->ctrl.select_chip) data->chip.select_chip = plat_nand_select_chip; - if (pdata->ctrl.write_buf) - data->chip.write_buf = plat_nand_write_buf; - + data->chip.write_buf = pdata->ctrl.write_buf; data->chip.read_buf = pdata->ctrl.read_buf; data->chip.chip_delay = pdata->chip.chip_delay; data->chip.options |= pdata->chip.options; diff --git a/drivers/mtd/nand/raw/qcom_nandc.c b/drivers/mtd/nand/raw/qcom_nandc.c index 63bb9f3fe23b..af4908e26766 100644 --- a/drivers/mtd/nand/raw/qcom_nandc.c +++ b/drivers/mtd/nand/raw/qcom_nandc.c @@ -2312,10 +2312,9 @@ static void qcom_nandc_read_buf(struct nand_chip *chip, uint8_t *buf, int len) nandc->buf_start += real_len; } -static void qcom_nandc_write_buf(struct mtd_info *mtd, const uint8_t *buf, +static void qcom_nandc_write_buf(struct nand_chip *chip, const uint8_t *buf, int len) { - struct nand_chip *chip = mtd_to_nand(mtd); struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip); int real_len = min_t(size_t, len, nandc->buf_count - nandc->buf_start); diff --git a/drivers/mtd/nand/raw/r852.c b/drivers/mtd/nand/raw/r852.c index 07055bd657cd..19f49ca1ed5b 100644 --- a/drivers/mtd/nand/raw/r852.c +++ b/drivers/mtd/nand/raw/r852.c @@ -232,9 +232,9 @@ static void r852_do_dma(struct r852_device *dev, uint8_t *buf, int do_read) /* * Program data lines of the nand chip to send data to it */ -static void r852_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len) +static void r852_write_buf(struct nand_chip *chip, const uint8_t *buf, int len) { - struct r852_device *dev = r852_get_dev(mtd); + struct r852_device *dev = r852_get_dev(nand_to_mtd(chip)); uint32_t reg; /* Don't allow any access to hardware if we suspect card removal */ diff --git a/drivers/mtd/nand/raw/s3c2410.c b/drivers/mtd/nand/raw/s3c2410.c index 54c86ec612dd..a420a84eaf51 100644 --- a/drivers/mtd/nand/raw/s3c2410.c +++ b/drivers/mtd/nand/raw/s3c2410.c @@ -696,16 +696,16 @@ static void s3c2440_nand_read_buf(struct nand_chip *this, u_char *buf, int len) } } -static void s3c2410_nand_write_buf(struct mtd_info *mtd, const u_char *buf, +static void s3c2410_nand_write_buf(struct nand_chip *this, const u_char *buf, int len) { - struct nand_chip *this = mtd_to_nand(mtd); writesb(this->IO_ADDR_W, buf, len); } -static void s3c2440_nand_write_buf(struct mtd_info *mtd, const u_char *buf, +static void s3c2440_nand_write_buf(struct nand_chip *this, const u_char *buf, int len) { + struct mtd_info *mtd = nand_to_mtd(this); struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd); writesl(info->regs + S3C2440_NFDATA, buf, len >> 2); diff --git a/drivers/mtd/nand/raw/sh_flctl.c b/drivers/mtd/nand/raw/sh_flctl.c index 6966a18f8ac4..742b7eb82ab7 100644 --- a/drivers/mtd/nand/raw/sh_flctl.c +++ b/drivers/mtd/nand/raw/sh_flctl.c @@ -628,7 +628,7 @@ static int flctl_write_page_hwecc(struct nand_chip *chip, const uint8_t *buf, struct mtd_info *mtd = nand_to_mtd(chip); nand_prog_page_begin_op(chip, page, 0, buf, mtd->writesize); - chip->write_buf(mtd, chip->oob_poi, mtd->oobsize); + chip->write_buf(chip, chip->oob_poi, mtd->oobsize); return nand_prog_page_end_op(chip); } @@ -970,9 +970,9 @@ static void flctl_select_chip(struct mtd_info *mtd, int chipnr) } } -static void flctl_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len) +static void flctl_write_buf(struct nand_chip *chip, const uint8_t *buf, int len) { - struct sh_flctl *flctl = mtd_to_flctl(mtd); + struct sh_flctl *flctl = mtd_to_flctl(nand_to_mtd(chip)); memcpy(&flctl->done_buff[flctl->index], buf, len); flctl->index += len; diff --git a/drivers/mtd/nand/raw/socrates_nand.c b/drivers/mtd/nand/raw/socrates_nand.c index 007e37680b88..deedc1cd4dee 100644 --- a/drivers/mtd/nand/raw/socrates_nand.c +++ b/drivers/mtd/nand/raw/socrates_nand.c @@ -34,15 +34,14 @@ struct socrates_nand_host { /** * socrates_nand_write_buf - write buffer to chip - * @mtd: MTD device structure + * @this: NAND chip object * @buf: data buffer * @len: number of bytes to write */ -static void socrates_nand_write_buf(struct mtd_info *mtd, - const uint8_t *buf, int len) +static void socrates_nand_write_buf(struct nand_chip *this, const uint8_t *buf, + int len) { int i; - struct nand_chip *this = mtd_to_nand(mtd); struct socrates_nand_host *host = nand_get_controller_data(this); for (i = 0; i < len; i++) { diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c index 2a0e624eca6c..80d9d2f8f5de 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -501,10 +501,9 @@ static void sunxi_nfc_read_buf(struct nand_chip *nand, uint8_t *buf, int len) } } -static void sunxi_nfc_write_buf(struct mtd_info *mtd, const uint8_t *buf, +static void sunxi_nfc_write_buf(struct nand_chip *nand, const uint8_t *buf, int len) { - struct nand_chip *nand = mtd_to_nand(mtd); struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand); struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller); int ret; @@ -760,7 +759,7 @@ static void sunxi_nfc_randomizer_write_buf(struct mtd_info *mtd, { sunxi_nfc_randomizer_config(mtd, page, ecc); sunxi_nfc_randomizer_enable(mtd); - sunxi_nfc_write_buf(mtd, buf, len); + sunxi_nfc_write_buf(mtd_to_nand(mtd), buf, len); sunxi_nfc_randomizer_disable(mtd); } diff --git a/drivers/mtd/nand/raw/tango_nand.c b/drivers/mtd/nand/raw/tango_nand.c index 20d6fa983a6b..7fc95c6980a7 100644 --- a/drivers/mtd/nand/raw/tango_nand.c +++ b/drivers/mtd/nand/raw/tango_nand.c @@ -149,9 +149,9 @@ static void tango_read_buf(struct nand_chip *chip, u8 *buf, int len) ioread8_rep(tchip->base + PBUS_DATA, buf, len); } -static void tango_write_buf(struct mtd_info *mtd, const u8 *buf, int len) +static void tango_write_buf(struct nand_chip *chip, const u8 *buf, int len) { - struct tango_chip *tchip = to_tango_chip(mtd_to_nand(mtd)); + struct tango_chip *tchip = to_tango_chip(chip); iowrite8_rep(tchip->base + PBUS_DATA, buf, len); } @@ -338,15 +338,13 @@ static void aux_read(struct nand_chip *chip, u8 **buf, int len, int *pos) static void aux_write(struct nand_chip *chip, const u8 **buf, int len, int *pos) { - struct mtd_info *mtd = nand_to_mtd(chip); - *pos += len; if (!*buf) { /* skip over "len" bytes */ nand_change_write_column_op(chip, *pos, NULL, 0, false); } else { - tango_write_buf(mtd, *buf, len); + tango_write_buf(chip, *buf, len); *buf += len; } } diff --git a/drivers/mtd/nand/raw/tmio_nand.c b/drivers/mtd/nand/raw/tmio_nand.c index 570ea045fbce..d627d855b254 100644 --- a/drivers/mtd/nand/raw/tmio_nand.c +++ b/drivers/mtd/nand/raw/tmio_nand.c @@ -245,9 +245,9 @@ static u_char tmio_nand_read_byte(struct nand_chip *chip) *buffer functions. */ static void -tmio_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len) +tmio_nand_write_buf(struct nand_chip *chip, const u_char *buf, int len) { - struct tmio_nand *tmio = mtd_to_tmio(mtd); + struct tmio_nand *tmio = mtd_to_tmio(nand_to_mtd(chip)); tmio_iowrite16_rep(tmio->fcr + FCR_DATA, buf, len >> 1); } diff --git a/drivers/mtd/nand/raw/txx9ndfmc.c b/drivers/mtd/nand/raw/txx9ndfmc.c index c68b638c4fe8..b7ff8eca441b 100644 --- a/drivers/mtd/nand/raw/txx9ndfmc.c +++ b/drivers/mtd/nand/raw/txx9ndfmc.c @@ -109,10 +109,10 @@ static uint8_t txx9ndfmc_read_byte(struct nand_chip *chip) return txx9ndfmc_read(dev, TXX9_NDFDTR); } -static void txx9ndfmc_write_buf(struct mtd_info *mtd, const uint8_t *buf, +static void txx9ndfmc_write_buf(struct nand_chip *chip, const uint8_t *buf, int len) { - struct platform_device *dev = mtd_to_platdev(mtd); + struct platform_device *dev = mtd_to_platdev(nand_to_mtd(chip)); void __iomem *ndfdtr = ndregaddr(dev, TXX9_NDFDTR); u32 mcr = txx9ndfmc_read(dev, TXX9_NDFMCR); diff --git a/drivers/mtd/nand/raw/xway_nand.c b/drivers/mtd/nand/raw/xway_nand.c index edbcfaa85ed8..77759f27d154 100644 --- a/drivers/mtd/nand/raw/xway_nand.c +++ b/drivers/mtd/nand/raw/xway_nand.c @@ -138,12 +138,12 @@ static void xway_read_buf(struct nand_chip *chip, u_char *buf, int len) buf[i] = xway_readb(nand_to_mtd(chip), NAND_WRITE_DATA); } -static void xway_write_buf(struct mtd_info *mtd, const u_char *buf, int len) +static void xway_write_buf(struct nand_chip *chip, const u_char *buf, int len) { int i; for (i = 0; i < len; i++) - xway_writeb(mtd, NAND_WRITE_DATA, buf[i]); + xway_writeb(nand_to_mtd(chip), NAND_WRITE_DATA, buf[i]); } /* diff --git a/drivers/staging/mt29f_spinand/mt29f_spinand.c b/drivers/staging/mt29f_spinand/mt29f_spinand.c index 644c91ff2734..7e9ee17a389b 100644 --- a/drivers/staging/mt29f_spinand/mt29f_spinand.c +++ b/drivers/staging/mt29f_spinand/mt29f_spinand.c @@ -724,9 +724,9 @@ static int spinand_wait(struct mtd_info *mtd, struct nand_chip *chip) return 0; } -static void spinand_write_buf(struct mtd_info *mtd, const u8 *buf, int len) +static void spinand_write_buf(struct nand_chip *chip, const u8 *buf, int len) { - struct spinand_state *state = mtd_to_state(mtd); + struct spinand_state *state = mtd_to_state(nand_to_mtd(chip)); memcpy(state->buf + state->buf_ptr, buf, len); state->buf_ptr += len; diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h index f324a82fe6a2..cd94cb3b9c2e 100644 --- a/include/linux/mtd/rawnand.h +++ b/include/linux/mtd/rawnand.h @@ -1284,8 +1284,8 @@ struct nand_chip { void __iomem *IO_ADDR_W; uint8_t (*read_byte)(struct nand_chip *chip); - void (*write_byte)(struct mtd_info *mtd, uint8_t byte); - void (*write_buf)(struct mtd_info *mtd, const uint8_t *buf, int len); + void (*write_byte)(struct nand_chip *chip, uint8_t byte); + void (*write_buf)(struct nand_chip *chip, const uint8_t *buf, int len); void (*read_buf)(struct nand_chip *chip, uint8_t *buf, int len); void (*select_chip)(struct mtd_info *mtd, int chip); int (*block_bad)(struct mtd_info *mtd, loff_t ofs); From 758b56f58b66bebc5bc2e0e180e1904aafa2b523 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Thu, 6 Sep 2018 14:05:24 +0200 Subject: [PATCH 252/302] mtd: rawnand: Pass a nand_chip object to chip->select_chip() Let's make the raw NAND API consistent by patching all helpers and hooks to take a nand_chip object instead of an mtd_info one or remove the mtd_info object when both are passed. Let's tackle the chip->select_chip() hook. Signed-off-by: Boris Brezillon Signed-off-by: Miquel Raynal --- drivers/mtd/nand/raw/atmel/nand-controller.c | 9 +- drivers/mtd/nand/raw/au1550nd.c | 4 +- .../mtd/nand/raw/bcm47xxnflash/ops_bcm4706.c | 4 +- drivers/mtd/nand/raw/cafe_nand.c | 3 +- drivers/mtd/nand/raw/davinci_nand.c | 4 +- drivers/mtd/nand/raw/denali.c | 6 +- drivers/mtd/nand/raw/diskonchip.c | 11 ++- drivers/mtd/nand/raw/docg4.c | 3 +- drivers/mtd/nand/raw/fsl_elbc_nand.c | 2 +- drivers/mtd/nand/raw/fsl_ifc_nand.c | 2 +- drivers/mtd/nand/raw/fsl_upm.c | 4 +- drivers/mtd/nand/raw/fsmc_nand.c | 4 +- drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c | 20 ++--- drivers/mtd/nand/raw/hisi504_nand.c | 3 +- drivers/mtd/nand/raw/jz4740_nand.c | 9 +- drivers/mtd/nand/raw/jz4780_nand.c | 4 +- drivers/mtd/nand/raw/marvell_nand.c | 3 +- drivers/mtd/nand/raw/mpc5121_nfc.c | 12 +-- drivers/mtd/nand/raw/mtk_nand.c | 5 +- drivers/mtd/nand/raw/mxc_nand.c | 8 +- drivers/mtd/nand/raw/nand_base.c | 86 +++++++++---------- drivers/mtd/nand/raw/ndfc.c | 3 +- drivers/mtd/nand/raw/plat_nand.c | 11 +-- drivers/mtd/nand/raw/qcom_nandc.c | 3 +- drivers/mtd/nand/raw/r852.c | 5 +- drivers/mtd/nand/raw/s3c2410.c | 5 +- drivers/mtd/nand/raw/sh_flctl.c | 4 +- drivers/mtd/nand/raw/sunxi_nand.c | 4 +- drivers/mtd/nand/raw/tango_nand.c | 3 +- drivers/mtd/nand/raw/tegra_nand.c | 3 +- drivers/mtd/nand/raw/vf610_nfc.c | 8 +- drivers/mtd/nand/raw/xway_nand.c | 3 +- drivers/staging/mt29f_spinand/mt29f_spinand.c | 2 +- include/linux/mtd/rawnand.h | 2 +- 34 files changed, 117 insertions(+), 145 deletions(-) diff --git a/drivers/mtd/nand/raw/atmel/nand-controller.c b/drivers/mtd/nand/raw/atmel/nand-controller.c index 84ddede5ede4..5c8ef476ed47 100644 --- a/drivers/mtd/nand/raw/atmel/nand-controller.c +++ b/drivers/mtd/nand/raw/atmel/nand-controller.c @@ -483,9 +483,8 @@ static int atmel_nand_dev_ready(struct mtd_info *mtd) return gpiod_get_value(nand->activecs->rb.gpio); } -static void atmel_nand_select_chip(struct mtd_info *mtd, int cs) +static void atmel_nand_select_chip(struct nand_chip *chip, int cs) { - struct nand_chip *chip = mtd_to_nand(mtd); struct atmel_nand *nand = to_atmel_nand(chip); if (cs < 0 || cs >= nand->numcs) { @@ -514,15 +513,15 @@ static int atmel_hsmc_nand_dev_ready(struct mtd_info *mtd) return status & ATMEL_HSMC_NFC_SR_RBEDGE(nand->activecs->rb.id); } -static void atmel_hsmc_nand_select_chip(struct mtd_info *mtd, int cs) +static void atmel_hsmc_nand_select_chip(struct nand_chip *chip, int cs) { - struct nand_chip *chip = mtd_to_nand(mtd); + struct mtd_info *mtd = nand_to_mtd(chip); struct atmel_nand *nand = to_atmel_nand(chip); struct atmel_hsmc_nand_controller *nc; nc = to_hsmc_nand_controller(chip->controller); - atmel_nand_select_chip(mtd, cs); + atmel_nand_select_chip(chip, cs); if (!nand->activecs) { regmap_write(nc->base.smc, ATMEL_HSMC_NFC_CTRL, diff --git a/drivers/mtd/nand/raw/au1550nd.c b/drivers/mtd/nand/raw/au1550nd.c index f1cc9f672262..1bae3b2779aa 100644 --- a/drivers/mtd/nand/raw/au1550nd.c +++ b/drivers/mtd/nand/raw/au1550nd.c @@ -227,10 +227,10 @@ int au1550_device_ready(struct mtd_info *mtd) * chip needs it to be asserted during chip not ready time but the NAND * controller keeps it released. * - * @mtd: MTD device structure + * @this: NAND chip object * @chip: chipnumber to select, -1 for deselect */ -static void au1550_select_chip(struct mtd_info *mtd, int chip) +static void au1550_select_chip(struct nand_chip *this, int chip) { } diff --git a/drivers/mtd/nand/raw/bcm47xxnflash/ops_bcm4706.c b/drivers/mtd/nand/raw/bcm47xxnflash/ops_bcm4706.c index 83eec2812aa0..c8e30b0308bc 100644 --- a/drivers/mtd/nand/raw/bcm47xxnflash/ops_bcm4706.c +++ b/drivers/mtd/nand/raw/bcm47xxnflash/ops_bcm4706.c @@ -191,8 +191,8 @@ static void bcm47xxnflash_ops_bcm4706_cmd_ctrl(struct mtd_info *mtd, int cmd, } /* Default nand_select_chip calls cmd_ctrl, which is not used in BCM4706 */ -static void bcm47xxnflash_ops_bcm4706_select_chip(struct mtd_info *mtd, - int chip) +static void bcm47xxnflash_ops_bcm4706_select_chip(struct nand_chip *chip, + int cs) { return; } diff --git a/drivers/mtd/nand/raw/cafe_nand.c b/drivers/mtd/nand/raw/cafe_nand.c index f801333161c9..e70a47aad538 100644 --- a/drivers/mtd/nand/raw/cafe_nand.c +++ b/drivers/mtd/nand/raw/cafe_nand.c @@ -314,9 +314,8 @@ static void cafe_nand_cmdfunc(struct mtd_info *mtd, unsigned command, cafe_writel(cafe, cafe->ctl2, NAND_CTRL2); } -static void cafe_select_chip(struct mtd_info *mtd, int chipnr) +static void cafe_select_chip(struct nand_chip *chip, int chipnr) { - struct nand_chip *chip = mtd_to_nand(mtd); struct cafe_priv *cafe = nand_get_controller_data(chip); cafe_dev_dbg(&cafe->pdev->dev, "select_chip %d\n", chipnr); diff --git a/drivers/mtd/nand/raw/davinci_nand.c b/drivers/mtd/nand/raw/davinci_nand.c index 02a2d3b05e34..85bc801424b0 100644 --- a/drivers/mtd/nand/raw/davinci_nand.c +++ b/drivers/mtd/nand/raw/davinci_nand.c @@ -118,9 +118,9 @@ static void nand_davinci_hwcontrol(struct mtd_info *mtd, int cmd, iowrite8(cmd, nand->IO_ADDR_W); } -static void nand_davinci_select_chip(struct mtd_info *mtd, int chip) +static void nand_davinci_select_chip(struct nand_chip *nand, int chip) { - struct davinci_nand_info *info = to_davinci_nand(mtd); + struct davinci_nand_info *info = to_davinci_nand(nand_to_mtd(nand)); info->current_cs = info->vaddr; diff --git a/drivers/mtd/nand/raw/denali.c b/drivers/mtd/nand/raw/denali.c index 101ffa11b606..e29ec95f24de 100644 --- a/drivers/mtd/nand/raw/denali.c +++ b/drivers/mtd/nand/raw/denali.c @@ -897,11 +897,11 @@ static int denali_write_page(struct nand_chip *chip, const uint8_t *buf, page, 0, 1); } -static void denali_select_chip(struct mtd_info *mtd, int chip) +static void denali_select_chip(struct nand_chip *chip, int cs) { - struct denali_nand_info *denali = mtd_to_denali(mtd); + struct denali_nand_info *denali = mtd_to_denali(nand_to_mtd(chip)); - denali->active_bank = chip; + denali->active_bank = cs; } static int denali_waitfunc(struct mtd_info *mtd, struct nand_chip *chip) diff --git a/drivers/mtd/nand/raw/diskonchip.c b/drivers/mtd/nand/raw/diskonchip.c index a1bc2f7436db..4d7b00d066fe 100644 --- a/drivers/mtd/nand/raw/diskonchip.c +++ b/drivers/mtd/nand/raw/diskonchip.c @@ -85,7 +85,7 @@ static u_char empty_write_ecc[6] = { 0x4b, 0x00, 0xe2, 0x0e, 0x93, 0xf7 }; static void doc200x_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int bitmask); -static void doc200x_select_chip(struct mtd_info *mtd, int chip); +static void doc200x_select_chip(struct nand_chip *this, int chip); static int debug = 0; module_param(debug, int, 0); @@ -371,7 +371,7 @@ static uint16_t __init doc200x_ident_chip(struct mtd_info *mtd, int nr) struct doc_priv *doc = nand_get_controller_data(this); uint16_t ret; - doc200x_select_chip(mtd, nr); + doc200x_select_chip(this, nr); doc200x_hwcontrol(mtd, NAND_CMD_READID, NAND_CTRL_CLE | NAND_CTRL_CHANGE); doc200x_hwcontrol(mtd, 0, NAND_CTRL_ALE | NAND_CTRL_CHANGE); @@ -559,9 +559,8 @@ static void doc2001plus_readbuf(struct nand_chip *this, u_char *buf, int len) printk("\n"); } -static void doc2001plus_select_chip(struct mtd_info *mtd, int chip) +static void doc2001plus_select_chip(struct nand_chip *this, int chip) { - struct nand_chip *this = mtd_to_nand(mtd); struct doc_priv *doc = nand_get_controller_data(this); void __iomem *docptr = doc->virtadr; int floor = 0; @@ -586,9 +585,9 @@ static void doc2001plus_select_chip(struct mtd_info *mtd, int chip) doc->curfloor = floor; } -static void doc200x_select_chip(struct mtd_info *mtd, int chip) +static void doc200x_select_chip(struct nand_chip *this, int chip) { - struct nand_chip *this = mtd_to_nand(mtd); + struct mtd_info *mtd = nand_to_mtd(this); struct doc_priv *doc = nand_get_controller_data(this); void __iomem *docptr = doc->virtadr; int floor = 0; diff --git a/drivers/mtd/nand/raw/docg4.c b/drivers/mtd/nand/raw/docg4.c index 9cbe87448e77..78c1d6fd42b2 100644 --- a/drivers/mtd/nand/raw/docg4.c +++ b/drivers/mtd/nand/raw/docg4.c @@ -333,13 +333,12 @@ static int docg4_wait(struct mtd_info *mtd, struct nand_chip *nand) return status; } -static void docg4_select_chip(struct mtd_info *mtd, int chip) +static void docg4_select_chip(struct nand_chip *nand, int chip) { /* * Select among multiple cascaded chips ("floors"). Multiple floors are * not yet supported, so the only valid non-negative value is 0. */ - struct nand_chip *nand = mtd_to_nand(mtd); struct docg4_priv *doc = nand_get_controller_data(nand); void __iomem *docptr = doc->virtadr; diff --git a/drivers/mtd/nand/raw/fsl_elbc_nand.c b/drivers/mtd/nand/raw/fsl_elbc_nand.c index 14d246323e94..74b804a61f2d 100644 --- a/drivers/mtd/nand/raw/fsl_elbc_nand.c +++ b/drivers/mtd/nand/raw/fsl_elbc_nand.c @@ -533,7 +533,7 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command, } } -static void fsl_elbc_select_chip(struct mtd_info *mtd, int chip) +static void fsl_elbc_select_chip(struct nand_chip *chip, int cs) { /* The hardware does not seem to support multiple * chips per bank. diff --git a/drivers/mtd/nand/raw/fsl_ifc_nand.c b/drivers/mtd/nand/raw/fsl_ifc_nand.c index 2e032db997a5..da846ffa3e5c 100644 --- a/drivers/mtd/nand/raw/fsl_ifc_nand.c +++ b/drivers/mtd/nand/raw/fsl_ifc_nand.c @@ -509,7 +509,7 @@ static void fsl_ifc_cmdfunc(struct mtd_info *mtd, unsigned int command, } } -static void fsl_ifc_select_chip(struct mtd_info *mtd, int chip) +static void fsl_ifc_select_chip(struct nand_chip *chip, int cs) { /* The hardware does not seem to support multiple * chips per bank. diff --git a/drivers/mtd/nand/raw/fsl_upm.c b/drivers/mtd/nand/raw/fsl_upm.c index d3d3adcb7282..ec3553cb737a 100644 --- a/drivers/mtd/nand/raw/fsl_upm.c +++ b/drivers/mtd/nand/raw/fsl_upm.c @@ -108,9 +108,9 @@ static void fun_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl) fun_wait_rnb(fun); } -static void fun_select_chip(struct mtd_info *mtd, int mchip_nr) +static void fun_select_chip(struct nand_chip *chip, int mchip_nr) { - struct nand_chip *chip = mtd_to_nand(mtd); + struct mtd_info *mtd = nand_to_mtd(chip); struct fsl_upm_nand *fun = to_fsl_upm_nand(mtd); if (mchip_nr == -1) { diff --git a/drivers/mtd/nand/raw/fsmc_nand.c b/drivers/mtd/nand/raw/fsmc_nand.c index 5fc036c89cc8..15bf533c907a 100644 --- a/drivers/mtd/nand/raw/fsmc_nand.c +++ b/drivers/mtd/nand/raw/fsmc_nand.c @@ -610,9 +610,9 @@ static void fsmc_write_buf_dma(struct mtd_info *mtd, const uint8_t *buf, } /* fsmc_select_chip - assert or deassert nCE */ -static void fsmc_select_chip(struct mtd_info *mtd, int chipnr) +static void fsmc_select_chip(struct nand_chip *chip, int chipnr) { - struct fsmc_nand_data *host = mtd_to_fsmc(mtd); + struct fsmc_nand_data *host = mtd_to_fsmc(nand_to_mtd(chip)); u32 pc; /* Support only one CS */ diff --git a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c index bd1b8445b358..f5f1aebf0d64 100644 --- a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c +++ b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c @@ -825,9 +825,8 @@ static int gpmi_dev_ready(struct mtd_info *mtd) return gpmi_is_ready(this, this->current_chip); } -static void gpmi_select_chip(struct mtd_info *mtd, int chipnr) +static void gpmi_select_chip(struct nand_chip *chip, int chipnr) { - struct nand_chip *chip = mtd_to_nand(mtd); struct gpmi_nand_data *this = nand_get_controller_data(chip); int ret; @@ -1552,7 +1551,7 @@ static int gpmi_block_markbad(struct mtd_info *mtd, loff_t ofs) int column, page, chipnr; chipnr = (int)(ofs >> chip->chip_shift); - chip->select_chip(mtd, chipnr); + chip->select_chip(chip, chipnr); column = !GPMI_IS_MX23(this) ? mtd->writesize : 0; @@ -1565,7 +1564,7 @@ static int gpmi_block_markbad(struct mtd_info *mtd, loff_t ofs) ret = nand_prog_page_op(chip, page, column, block_mark, 1); - chip->select_chip(mtd, -1); + chip->select_chip(chip, -1); return ret; } @@ -1602,7 +1601,6 @@ static int mx23_check_transcription_stamp(struct gpmi_nand_data *this) struct boot_rom_geometry *rom_geo = &this->rom_geometry; struct device *dev = this->dev; struct nand_chip *chip = &this->nand; - struct mtd_info *mtd = nand_to_mtd(chip); unsigned int search_area_size_in_strides; unsigned int stride; unsigned int page; @@ -1614,7 +1612,7 @@ static int mx23_check_transcription_stamp(struct gpmi_nand_data *this) search_area_size_in_strides = 1 << rom_geo->search_area_stride_exponent; saved_chip_number = this->current_chip; - chip->select_chip(mtd, 0); + chip->select_chip(chip, 0); /* * Loop through the first search area, looking for the NCB fingerprint. @@ -1642,7 +1640,7 @@ static int mx23_check_transcription_stamp(struct gpmi_nand_data *this) } - chip->select_chip(mtd, saved_chip_number); + chip->select_chip(chip, saved_chip_number); if (found_an_ncb_fingerprint) dev_dbg(dev, "\tFound a fingerprint\n"); @@ -1685,7 +1683,7 @@ static int mx23_write_transcription_stamp(struct gpmi_nand_data *this) /* Select chip 0. */ saved_chip_number = this->current_chip; - chip->select_chip(mtd, 0); + chip->select_chip(chip, 0); /* Loop over blocks in the first search area, erasing them. */ dev_dbg(dev, "Erasing the search area...\n"); @@ -1717,7 +1715,7 @@ static int mx23_write_transcription_stamp(struct gpmi_nand_data *this) } /* Deselect chip 0. */ - chip->select_chip(mtd, saved_chip_number); + chip->select_chip(chip, saved_chip_number); return 0; } @@ -1766,10 +1764,10 @@ static int mx23_boot_init(struct gpmi_nand_data *this) byte = block << chip->phys_erase_shift; /* Send the command to read the conventional block mark. */ - chip->select_chip(mtd, chipnr); + chip->select_chip(chip, chipnr); nand_read_page_op(chip, page, mtd->writesize, NULL, 0); block_mark = chip->read_byte(chip); - chip->select_chip(mtd, -1); + chip->select_chip(chip, -1); /* * Check if the block is marked bad. If so, we need to mark it diff --git a/drivers/mtd/nand/raw/hisi504_nand.c b/drivers/mtd/nand/raw/hisi504_nand.c index b4e5bfd30022..86dd7b54159d 100644 --- a/drivers/mtd/nand/raw/hisi504_nand.c +++ b/drivers/mtd/nand/raw/hisi504_nand.c @@ -353,9 +353,8 @@ static int hisi_nfc_send_cmd_reset(struct hinfc_host *host, int chipselect) return 0; } -static void hisi_nfc_select_chip(struct mtd_info *mtd, int chipselect) +static void hisi_nfc_select_chip(struct nand_chip *chip, int chipselect) { - struct nand_chip *chip = mtd_to_nand(mtd); struct hinfc_host *host = nand_get_controller_data(chip); if (chipselect < 0) diff --git a/drivers/mtd/nand/raw/jz4740_nand.c b/drivers/mtd/nand/raw/jz4740_nand.c index e926ed6ed296..b6e68048b83d 100644 --- a/drivers/mtd/nand/raw/jz4740_nand.c +++ b/drivers/mtd/nand/raw/jz4740_nand.c @@ -78,10 +78,9 @@ static inline struct jz_nand *mtd_to_jz_nand(struct mtd_info *mtd) return container_of(mtd_to_nand(mtd), struct jz_nand, chip); } -static void jz_nand_select_chip(struct mtd_info *mtd, int chipnr) +static void jz_nand_select_chip(struct nand_chip *chip, int chipnr) { - struct jz_nand *nand = mtd_to_jz_nand(mtd); - struct nand_chip *chip = mtd_to_nand(mtd); + struct jz_nand *nand = mtd_to_jz_nand(nand_to_mtd(chip)); uint32_t ctrl; int banknr; @@ -336,14 +335,14 @@ static int jz_nand_detect_bank(struct platform_device *pdev, goto notfound_id; /* Retrieve the IDs from the first chip. */ - chip->select_chip(mtd, 0); + chip->select_chip(chip, 0); nand_reset_op(chip); nand_readid_op(chip, 0, id, sizeof(id)); *nand_maf_id = id[0]; *nand_dev_id = id[1]; } else { /* Detect additional chip. */ - chip->select_chip(mtd, chipnr); + chip->select_chip(chip, chipnr); nand_reset_op(chip); nand_readid_op(chip, 0, id, sizeof(id)); if (*nand_maf_id != id[0] || *nand_dev_id != id[1]) { diff --git a/drivers/mtd/nand/raw/jz4780_nand.c b/drivers/mtd/nand/raw/jz4780_nand.c index 42c5dcdea4a9..29e597b0ca59 100644 --- a/drivers/mtd/nand/raw/jz4780_nand.c +++ b/drivers/mtd/nand/raw/jz4780_nand.c @@ -71,9 +71,9 @@ static inline struct jz4780_nand_controller return container_of(ctrl, struct jz4780_nand_controller, controller); } -static void jz4780_nand_select_chip(struct mtd_info *mtd, int chipnr) +static void jz4780_nand_select_chip(struct nand_chip *chip, int chipnr) { - struct jz4780_nand_chip *nand = to_jz4780_nand_chip(mtd); + struct jz4780_nand_chip *nand = to_jz4780_nand_chip(nand_to_mtd(chip)); struct jz4780_nand_controller *nfc = to_jz4780_nand_controller(nand->chip.controller); struct jz4780_nand_cs *cs; diff --git a/drivers/mtd/nand/raw/marvell_nand.c b/drivers/mtd/nand/raw/marvell_nand.c index 5f5709c2e58e..1f4e75f8fa3e 100644 --- a/drivers/mtd/nand/raw/marvell_nand.c +++ b/drivers/mtd/nand/raw/marvell_nand.c @@ -701,9 +701,8 @@ static int marvell_nfc_wait_op(struct nand_chip *chip, unsigned int timeout_ms) return 0; } -static void marvell_nfc_select_chip(struct mtd_info *mtd, int die_nr) +static void marvell_nfc_select_chip(struct nand_chip *chip, int die_nr) { - struct nand_chip *chip = mtd_to_nand(mtd); struct marvell_nand_chip *marvell_nand = to_marvell_nand(chip); struct marvell_nfc *nfc = to_marvell_nfc(chip->controller); u32 ndcr_generic; diff --git a/drivers/mtd/nand/raw/mpc5121_nfc.c b/drivers/mtd/nand/raw/mpc5121_nfc.c index dc573a0b5fe1..c2002c4d467b 100644 --- a/drivers/mtd/nand/raw/mpc5121_nfc.c +++ b/drivers/mtd/nand/raw/mpc5121_nfc.c @@ -263,8 +263,10 @@ static void mpc5121_nfc_addr_cycle(struct mtd_info *mtd, int column, int page) } /* Control chip select signals */ -static void mpc5121_nfc_select_chip(struct mtd_info *mtd, int chip) +static void mpc5121_nfc_select_chip(struct nand_chip *nand, int chip) { + struct mtd_info *mtd = nand_to_mtd(nand); + if (chip < 0) { nfc_clear(mtd, NFC_CONFIG1, NFC_CE); return; @@ -299,9 +301,9 @@ static int ads5121_chipselect_init(struct mtd_info *mtd) } /* Control chips select signal on ADS5121 board */ -static void ads5121_select_chip(struct mtd_info *mtd, int chip) +static void ads5121_select_chip(struct nand_chip *nand, int chip) { - struct nand_chip *nand = mtd_to_nand(mtd); + struct mtd_info *mtd = nand_to_mtd(nand); struct mpc5121_nfc_prv *prv = nand_get_controller_data(nand); u8 v; @@ -309,10 +311,10 @@ static void ads5121_select_chip(struct mtd_info *mtd, int chip) v |= 0x0F; if (chip >= 0) { - mpc5121_nfc_select_chip(mtd, 0); + mpc5121_nfc_select_chip(nand, 0); v &= ~(1 << chip); } else - mpc5121_nfc_select_chip(mtd, -1); + mpc5121_nfc_select_chip(nand, -1); out_8(prv->csreg, v); } diff --git a/drivers/mtd/nand/raw/mtk_nand.c b/drivers/mtd/nand/raw/mtk_nand.c index bd2002a1fabd..6e5d4afd6b1a 100644 --- a/drivers/mtd/nand/raw/mtk_nand.c +++ b/drivers/mtd/nand/raw/mtk_nand.c @@ -389,16 +389,15 @@ static int mtk_nfc_hw_runtime_config(struct mtd_info *mtd) return 0; } -static void mtk_nfc_select_chip(struct mtd_info *mtd, int chip) +static void mtk_nfc_select_chip(struct nand_chip *nand, int chip) { - struct nand_chip *nand = mtd_to_nand(mtd); struct mtk_nfc *nfc = nand_get_controller_data(nand); struct mtk_nfc_nand_chip *mtk_nand = to_mtk_nand(nand); if (chip < 0) return; - mtk_nfc_hw_runtime_config(mtd); + mtk_nfc_hw_runtime_config(nand_to_mtd(nand)); nfi_writel(nfc, mtk_nand->sels[chip], NFI_CSEL); } diff --git a/drivers/mtd/nand/raw/mxc_nand.c b/drivers/mtd/nand/raw/mxc_nand.c index d5d8f8c16b60..d070ce461b69 100644 --- a/drivers/mtd/nand/raw/mxc_nand.c +++ b/drivers/mtd/nand/raw/mxc_nand.c @@ -136,7 +136,7 @@ struct mxc_nand_devtype_data { void (*irq_control)(struct mxc_nand_host *, int); u32 (*get_ecc_status)(struct mxc_nand_host *); const struct mtd_ooblayout_ops *ooblayout; - void (*select_chip)(struct mtd_info *mtd, int chip); + void (*select_chip)(struct nand_chip *chip, int cs); int (*setup_data_interface)(struct mtd_info *mtd, int csline, const struct nand_data_interface *conf); void (*enable_hwecc)(struct nand_chip *chip, bool enable); @@ -957,9 +957,8 @@ static void mxc_nand_read_buf(struct nand_chip *nand_chip, u_char *buf, /* This function is used by upper layer for select and * deselect of the NAND chip */ -static void mxc_nand_select_chip_v1_v3(struct mtd_info *mtd, int chip) +static void mxc_nand_select_chip_v1_v3(struct nand_chip *nand_chip, int chip) { - struct nand_chip *nand_chip = mtd_to_nand(mtd); struct mxc_nand_host *host = nand_get_controller_data(nand_chip); if (chip == -1) { @@ -978,9 +977,8 @@ static void mxc_nand_select_chip_v1_v3(struct mtd_info *mtd, int chip) } } -static void mxc_nand_select_chip_v2(struct mtd_info *mtd, int chip) +static void mxc_nand_select_chip_v2(struct nand_chip *nand_chip, int chip) { - struct nand_chip *nand_chip = mtd_to_nand(mtd); struct mxc_nand_host *host = nand_get_controller_data(nand_chip); if (chip == -1) { diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c index 6c20c0b805a3..3d3e3c704a5a 100644 --- a/drivers/mtd/nand/raw/nand_base.c +++ b/drivers/mtd/nand/raw/nand_base.c @@ -277,18 +277,17 @@ static uint8_t nand_read_byte16(struct nand_chip *chip) /** * nand_select_chip - [DEFAULT] control CE line - * @mtd: MTD device structure + * @chip: NAND chip object * @chipnr: chipnumber to select, -1 for deselect * * Default select function for 1 chip devices. */ -static void nand_select_chip(struct mtd_info *mtd, int chipnr) +static void nand_select_chip(struct nand_chip *chip, int chipnr) { - struct nand_chip *chip = mtd_to_nand(mtd); - switch (chipnr) { case -1: - chip->cmd_ctrl(mtd, NAND_CMD_NONE, 0 | NAND_CTRL_CHANGE); + chip->cmd_ctrl(nand_to_mtd(chip), NAND_CMD_NONE, + 0 | NAND_CTRL_CHANGE); break; case 0: break; @@ -1261,10 +1260,10 @@ static int nand_setup_data_interface(struct nand_chip *chip, int chipnr) /* Change the mode on the chip side (if supported by the NAND chip) */ if (nand_supports_set_features(chip, ONFI_FEATURE_ADDR_TIMING_MODE)) { - chip->select_chip(mtd, chipnr); + chip->select_chip(chip, chipnr); ret = nand_set_features(chip, ONFI_FEATURE_ADDR_TIMING_MODE, tmode_param); - chip->select_chip(mtd, -1); + chip->select_chip(chip, -1); if (ret) return ret; } @@ -1279,10 +1278,10 @@ static int nand_setup_data_interface(struct nand_chip *chip, int chipnr) return 0; memset(tmode_param, 0, ONFI_SUBFEATURE_PARAM_LEN); - chip->select_chip(mtd, chipnr); + chip->select_chip(chip, chipnr); ret = nand_get_features(chip, ONFI_FEATURE_ADDR_TIMING_MODE, tmode_param); - chip->select_chip(mtd, -1); + chip->select_chip(chip, -1); if (ret) goto err_reset_chip; @@ -1300,9 +1299,9 @@ static int nand_setup_data_interface(struct nand_chip *chip, int chipnr) * timing mode. */ nand_reset_data_interface(chip, chipnr); - chip->select_chip(mtd, chipnr); + chip->select_chip(chip, chipnr); nand_reset_op(chip); - chip->select_chip(mtd, -1); + chip->select_chip(chip, -1); return ret; } @@ -2794,7 +2793,6 @@ EXPORT_SYMBOL_GPL(nand_subop_get_data_len); */ int nand_reset(struct nand_chip *chip, int chipnr) { - struct mtd_info *mtd = nand_to_mtd(chip); struct nand_data_interface saved_data_intf = chip->data_interface; int ret; @@ -2806,9 +2804,9 @@ int nand_reset(struct nand_chip *chip, int chipnr) * The CS line has to be released before we can apply the new NAND * interface settings, hence this weird ->select_chip() dance. */ - chip->select_chip(mtd, chipnr); + chip->select_chip(chip, chipnr); ret = nand_reset_op(chip); - chip->select_chip(mtd, -1); + chip->select_chip(chip, -1); if (ret) return ret; @@ -3553,7 +3551,7 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from, bool ecc_fail = false; chipnr = (int)(from >> chip->chip_shift); - chip->select_chip(mtd, chipnr); + chip->select_chip(chip, chipnr); realpage = (int)(from >> chip->page_shift); page = realpage & chip->pagemask; @@ -3684,11 +3682,11 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from, /* Check, if we cross a chip boundary */ if (!page) { chipnr++; - chip->select_chip(mtd, -1); - chip->select_chip(mtd, chipnr); + chip->select_chip(chip, -1); + chip->select_chip(chip, chipnr); } } - chip->select_chip(mtd, -1); + chip->select_chip(chip, -1); ops->retlen = ops->len - (size_t) readlen; if (oob) @@ -3887,7 +3885,7 @@ static int nand_do_read_oob(struct mtd_info *mtd, loff_t from, len = mtd_oobavail(mtd, ops); chipnr = (int)(from >> chip->chip_shift); - chip->select_chip(mtd, chipnr); + chip->select_chip(chip, chipnr); /* Shift to get page */ realpage = (int)(from >> chip->page_shift); @@ -3920,11 +3918,11 @@ static int nand_do_read_oob(struct mtd_info *mtd, loff_t from, /* Check, if we cross a chip boundary */ if (!page) { chipnr++; - chip->select_chip(mtd, -1); - chip->select_chip(mtd, chipnr); + chip->select_chip(chip, -1); + chip->select_chip(chip, chipnr); } } - chip->select_chip(mtd, -1); + chip->select_chip(chip, -1); ops->oobretlen = ops->ooblen - readlen; @@ -4406,7 +4404,7 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to, column = to & (mtd->writesize - 1); chipnr = (int)(to >> chip->chip_shift); - chip->select_chip(mtd, chipnr); + chip->select_chip(chip, chipnr); /* Check, if it is write protected */ if (nand_check_wp(mtd)) { @@ -4482,8 +4480,8 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to, /* Check, if we cross a chip boundary */ if (!page) { chipnr++; - chip->select_chip(mtd, -1); - chip->select_chip(mtd, chipnr); + chip->select_chip(chip, -1); + chip->select_chip(chip, chipnr); } } @@ -4492,7 +4490,7 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to, ops->oobretlen = ops->ooblen; err_out: - chip->select_chip(mtd, -1); + chip->select_chip(chip, -1); return ret; } @@ -4518,7 +4516,7 @@ static int panic_nand_write(struct mtd_info *mtd, loff_t to, size_t len, /* Grab the device */ panic_nand_get_device(chip, mtd, FL_WRITING); - chip->select_chip(mtd, chipnr); + chip->select_chip(chip, chipnr); /* Wait for the device to get ready */ panic_nand_wait(mtd, chip, 400); @@ -4570,14 +4568,14 @@ static int nand_do_write_oob(struct mtd_info *mtd, loff_t to, */ nand_reset(chip, chipnr); - chip->select_chip(mtd, chipnr); + chip->select_chip(chip, chipnr); /* Shift to get page */ page = (int)(to >> chip->page_shift); /* Check, if it is write protected */ if (nand_check_wp(mtd)) { - chip->select_chip(mtd, -1); + chip->select_chip(chip, -1); return -EROFS; } @@ -4592,7 +4590,7 @@ static int nand_do_write_oob(struct mtd_info *mtd, loff_t to, else status = chip->ecc.write_oob(chip, page & chip->pagemask); - chip->select_chip(mtd, -1); + chip->select_chip(chip, -1); if (status) return status; @@ -4700,7 +4698,7 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr, pages_per_block = 1 << (chip->phys_erase_shift - chip->page_shift); /* Select the NAND device */ - chip->select_chip(mtd, chipnr); + chip->select_chip(chip, chipnr); /* Check, if it is write protected */ if (nand_check_wp(mtd)) { @@ -4750,8 +4748,8 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr, /* Check, if we cross a chip boundary */ if (len && !(page & chip->pagemask)) { chipnr++; - chip->select_chip(mtd, -1); - chip->select_chip(mtd, chipnr); + chip->select_chip(chip, -1); + chip->select_chip(chip, chipnr); } } @@ -4759,7 +4757,7 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr, erase_exit: /* Deselect and wake up anyone waiting on the device */ - chip->select_chip(mtd, -1); + chip->select_chip(chip, -1); nand_release_device(mtd); /* Return more or less happy */ @@ -4795,11 +4793,11 @@ static int nand_block_isbad(struct mtd_info *mtd, loff_t offs) /* Select the NAND device */ nand_get_device(mtd, FL_READING); - chip->select_chip(mtd, chipnr); + chip->select_chip(chip, chipnr); ret = nand_block_checkbad(mtd, offs, 0); - chip->select_chip(mtd, -1); + chip->select_chip(chip, -1); nand_release_device(mtd); return ret; @@ -5626,7 +5624,7 @@ static int nand_detect(struct nand_chip *chip, struct nand_flash_dev *type) return ret; /* Select the device */ - chip->select_chip(mtd, 0); + chip->select_chip(chip, 0); /* Send the command for reading device ID */ ret = nand_readid_op(chip, 0, id_data, 2); @@ -5986,14 +5984,14 @@ static int nand_scan_ident(struct nand_chip *chip, int maxchips, if (ret) { if (!(chip->options & NAND_SCAN_SILENT_NODEV)) pr_warn("No NAND device found\n"); - chip->select_chip(mtd, -1); + chip->select_chip(chip, -1); return ret; } nand_maf_id = chip->id.data[0]; nand_dev_id = chip->id.data[1]; - chip->select_chip(mtd, -1); + chip->select_chip(chip, -1); /* Check for a chip array */ for (i = 1; i < maxchips; i++) { @@ -6002,15 +6000,15 @@ static int nand_scan_ident(struct nand_chip *chip, int maxchips, /* See comment in nand_get_flash_type for reset */ nand_reset(chip, i); - chip->select_chip(mtd, i); + chip->select_chip(chip, i); /* Send the command for reading device ID */ nand_readid_op(chip, 0, id, sizeof(id)); /* Read manufacturer and device IDs */ if (nand_maf_id != id[0] || nand_dev_id != id[1]) { - chip->select_chip(mtd, -1); + chip->select_chip(chip, -1); break; } - chip->select_chip(mtd, -1); + chip->select_chip(chip, -1); } if (i > 1) pr_info("%d chips detected\n", i); @@ -6432,9 +6430,9 @@ static int nand_scan_tail(struct nand_chip *chip) * to explictly select the relevant die when interacting with the NAND * chip. */ - chip->select_chip(mtd, 0); + chip->select_chip(chip, 0); ret = nand_manufacturer_init(chip); - chip->select_chip(mtd, -1); + chip->select_chip(chip, -1); if (ret) goto err_free_buf; diff --git a/drivers/mtd/nand/raw/ndfc.c b/drivers/mtd/nand/raw/ndfc.c index 02b102addeb5..addcc736ae1d 100644 --- a/drivers/mtd/nand/raw/ndfc.c +++ b/drivers/mtd/nand/raw/ndfc.c @@ -44,10 +44,9 @@ struct ndfc_controller { static struct ndfc_controller ndfc_ctrl[NDFC_MAX_CS]; -static void ndfc_select_chip(struct mtd_info *mtd, int chip) +static void ndfc_select_chip(struct nand_chip *nchip, int chip) { uint32_t ccr; - struct nand_chip *nchip = mtd_to_nand(mtd); struct ndfc_controller *ndfc = nand_get_controller_data(nchip); ccr = in_be32(ndfc->ndfcbase + NDFC_CCR); diff --git a/drivers/mtd/nand/raw/plat_nand.c b/drivers/mtd/nand/raw/plat_nand.c index adfc3f50e8d5..dd9e241b7584 100644 --- a/drivers/mtd/nand/raw/plat_nand.c +++ b/drivers/mtd/nand/raw/plat_nand.c @@ -37,13 +37,6 @@ static int plat_nand_dev_ready(struct mtd_info *mtd) return pdata->ctrl.dev_ready(mtd_to_nand(mtd)); } -static void plat_nand_select_chip(struct mtd_info *mtd, int cs) -{ - struct platform_nand_data *pdata = dev_get_platdata(mtd->dev.parent); - - pdata->ctrl.select_chip(mtd_to_nand(mtd), cs); -} - /* * Probe for the NAND device. */ @@ -90,9 +83,7 @@ static int plat_nand_probe(struct platform_device *pdev) if (pdata->ctrl.dev_ready) data->chip.dev_ready = plat_nand_dev_ready; - if (pdata->ctrl.select_chip) - data->chip.select_chip = plat_nand_select_chip; - + data->chip.select_chip = pdata->ctrl.select_chip; data->chip.write_buf = pdata->ctrl.write_buf; data->chip.read_buf = pdata->ctrl.read_buf; data->chip.chip_delay = pdata->chip.chip_delay; diff --git a/drivers/mtd/nand/raw/qcom_nandc.c b/drivers/mtd/nand/raw/qcom_nandc.c index af4908e26766..626c9ab8c8db 100644 --- a/drivers/mtd/nand/raw/qcom_nandc.c +++ b/drivers/mtd/nand/raw/qcom_nandc.c @@ -2324,9 +2324,8 @@ static void qcom_nandc_write_buf(struct nand_chip *chip, const uint8_t *buf, } /* we support only one external chip for now */ -static void qcom_nandc_select_chip(struct mtd_info *mtd, int chipnr) +static void qcom_nandc_select_chip(struct nand_chip *chip, int chipnr) { - struct nand_chip *chip = mtd_to_nand(mtd); struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip); if (chipnr <= 0) diff --git a/drivers/mtd/nand/raw/r852.c b/drivers/mtd/nand/raw/r852.c index 19f49ca1ed5b..312a971aa456 100644 --- a/drivers/mtd/nand/raw/r852.c +++ b/drivers/mtd/nand/raw/r852.c @@ -1026,7 +1026,6 @@ static int r852_suspend(struct device *device) static int r852_resume(struct device *device) { struct r852_device *dev = pci_get_drvdata(to_pci_dev(device)); - struct mtd_info *mtd = nand_to_mtd(dev->chip); r852_disable_irqs(dev); r852_card_update_present(dev); @@ -1046,9 +1045,9 @@ static int r852_resume(struct device *device) /* Otherwise, initialize the card */ if (dev->card_registred) { r852_engine_enable(dev); - dev->chip->select_chip(mtd, 0); + dev->chip->select_chip(dev->chip, 0); nand_reset_op(dev->chip); - dev->chip->select_chip(mtd, -1); + dev->chip->select_chip(dev->chip, -1); } /* Program card detection IRQ */ diff --git a/drivers/mtd/nand/raw/s3c2410.c b/drivers/mtd/nand/raw/s3c2410.c index a420a84eaf51..353011e7fb79 100644 --- a/drivers/mtd/nand/raw/s3c2410.c +++ b/drivers/mtd/nand/raw/s3c2410.c @@ -404,7 +404,7 @@ static int s3c2410_nand_inithw(struct s3c2410_nand_info *info) /** * s3c2410_nand_select_chip - select the given nand chip - * @mtd: The MTD instance for this chip. + * @this: NAND chip object. * @chip: The chip number. * * This is called by the MTD layer to either select a given chip for the @@ -415,11 +415,10 @@ static int s3c2410_nand_inithw(struct s3c2410_nand_info *info) * platform specific selection code is called to route nFCE to the specific * chip. */ -static void s3c2410_nand_select_chip(struct mtd_info *mtd, int chip) +static void s3c2410_nand_select_chip(struct nand_chip *this, int chip) { struct s3c2410_nand_info *info; struct s3c2410_nand_mtd *nmtd; - struct nand_chip *this = mtd_to_nand(mtd); unsigned long cur; nmtd = nand_get_controller_data(this); diff --git a/drivers/mtd/nand/raw/sh_flctl.c b/drivers/mtd/nand/raw/sh_flctl.c index 742b7eb82ab7..e2a4939971b5 100644 --- a/drivers/mtd/nand/raw/sh_flctl.c +++ b/drivers/mtd/nand/raw/sh_flctl.c @@ -926,9 +926,9 @@ static void flctl_cmdfunc(struct mtd_info *mtd, unsigned int command, return; } -static void flctl_select_chip(struct mtd_info *mtd, int chipnr) +static void flctl_select_chip(struct nand_chip *chip, int chipnr) { - struct sh_flctl *flctl = mtd_to_flctl(mtd); + struct sh_flctl *flctl = mtd_to_flctl(nand_to_mtd(chip)); int ret; switch (chipnr) { diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c index 80d9d2f8f5de..97a0666df615 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -420,9 +420,9 @@ static int sunxi_nfc_dev_ready(struct mtd_info *mtd) return !!(readl(nfc->regs + NFC_REG_ST) & mask); } -static void sunxi_nfc_select_chip(struct mtd_info *mtd, int chip) +static void sunxi_nfc_select_chip(struct nand_chip *nand, int chip) { - struct nand_chip *nand = mtd_to_nand(mtd); + struct mtd_info *mtd = nand_to_mtd(nand); struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand); struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller); struct sunxi_nand_chip_sel *sel; diff --git a/drivers/mtd/nand/raw/tango_nand.c b/drivers/mtd/nand/raw/tango_nand.c index 7fc95c6980a7..5e0bc2993e5d 100644 --- a/drivers/mtd/nand/raw/tango_nand.c +++ b/drivers/mtd/nand/raw/tango_nand.c @@ -156,9 +156,8 @@ static void tango_write_buf(struct nand_chip *chip, const u8 *buf, int len) iowrite8_rep(tchip->base + PBUS_DATA, buf, len); } -static void tango_select_chip(struct mtd_info *mtd, int idx) +static void tango_select_chip(struct nand_chip *chip, int idx) { - struct nand_chip *chip = mtd_to_nand(mtd); struct tango_nfc *nfc = to_tango_nfc(chip->controller); struct tango_chip *tchip = to_tango_chip(chip); diff --git a/drivers/mtd/nand/raw/tegra_nand.c b/drivers/mtd/nand/raw/tegra_nand.c index df8e78814a08..1088741eed1d 100644 --- a/drivers/mtd/nand/raw/tegra_nand.c +++ b/drivers/mtd/nand/raw/tegra_nand.c @@ -462,9 +462,8 @@ static int tegra_nand_exec_op(struct nand_chip *chip, check_only); } -static void tegra_nand_select_chip(struct mtd_info *mtd, int die_nr) +static void tegra_nand_select_chip(struct nand_chip *chip, int die_nr) { - struct nand_chip *chip = mtd_to_nand(mtd); struct tegra_nand_chip *nand = to_tegra_chip(chip); struct tegra_nand_controller *ctrl = to_tegra_ctrl(chip->controller); diff --git a/drivers/mtd/nand/raw/vf610_nfc.c b/drivers/mtd/nand/raw/vf610_nfc.c index bce6f6769cd6..9814fd4a84cf 100644 --- a/drivers/mtd/nand/raw/vf610_nfc.c +++ b/drivers/mtd/nand/raw/vf610_nfc.c @@ -498,9 +498,9 @@ static int vf610_nfc_exec_op(struct nand_chip *chip, /* * This function supports Vybrid only (MPC5125 would have full RB and four CS) */ -static void vf610_nfc_select_chip(struct mtd_info *mtd, int chip) +static void vf610_nfc_select_chip(struct nand_chip *chip, int cs) { - struct vf610_nfc *nfc = mtd_to_nfc(mtd); + struct vf610_nfc *nfc = mtd_to_nfc(nand_to_mtd(chip)); u32 tmp = vf610_nfc_read(nfc, NFC_ROW_ADDR); /* Vybrid only (MPC5125 would have full RB and four CS) */ @@ -509,9 +509,9 @@ static void vf610_nfc_select_chip(struct mtd_info *mtd, int chip) tmp &= ~(ROW_ADDR_CHIP_SEL_RB_MASK | ROW_ADDR_CHIP_SEL_MASK); - if (chip >= 0) { + if (cs >= 0) { tmp |= 1 << ROW_ADDR_CHIP_SEL_RB_SHIFT; - tmp |= BIT(chip) << ROW_ADDR_CHIP_SEL_SHIFT; + tmp |= BIT(cs) << ROW_ADDR_CHIP_SEL_SHIFT; } vf610_nfc_write(nfc, NFC_ROW_ADDR, tmp); diff --git a/drivers/mtd/nand/raw/xway_nand.c b/drivers/mtd/nand/raw/xway_nand.c index 77759f27d154..a6388fa1dce7 100644 --- a/drivers/mtd/nand/raw/xway_nand.c +++ b/drivers/mtd/nand/raw/xway_nand.c @@ -85,9 +85,8 @@ static void xway_writeb(struct mtd_info *mtd, int op, u8 value) writeb(value, data->nandaddr + op); } -static void xway_select_chip(struct mtd_info *mtd, int select) +static void xway_select_chip(struct nand_chip *chip, int select) { - struct nand_chip *chip = mtd_to_nand(mtd); struct xway_nand_data *data = nand_get_controller_data(chip); switch (select) { diff --git a/drivers/staging/mt29f_spinand/mt29f_spinand.c b/drivers/staging/mt29f_spinand/mt29f_spinand.c index 7e9ee17a389b..c0df8b6ab19b 100644 --- a/drivers/staging/mt29f_spinand/mt29f_spinand.c +++ b/drivers/staging/mt29f_spinand/mt29f_spinand.c @@ -681,7 +681,7 @@ static int spinand_read_page_hwecc(struct nand_chip *chip, u8 *buf, } #endif -static void spinand_select_chip(struct mtd_info *mtd, int dev) +static void spinand_select_chip(struct nand_chip *chip, int dev) { } diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h index cd94cb3b9c2e..65a25e89b426 100644 --- a/include/linux/mtd/rawnand.h +++ b/include/linux/mtd/rawnand.h @@ -1287,7 +1287,7 @@ struct nand_chip { void (*write_byte)(struct nand_chip *chip, uint8_t byte); void (*write_buf)(struct nand_chip *chip, const uint8_t *buf, int len); void (*read_buf)(struct nand_chip *chip, uint8_t *buf, int len); - void (*select_chip)(struct mtd_info *mtd, int chip); + void (*select_chip)(struct nand_chip *chip, int cs); int (*block_bad)(struct mtd_info *mtd, loff_t ofs); int (*block_markbad)(struct mtd_info *mtd, loff_t ofs); void (*cmd_ctrl)(struct mtd_info *mtd, int dat, unsigned int ctrl); From c17556f545c0283f53561c8a38d5cd4e91a35fe5 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Thu, 6 Sep 2018 14:05:25 +0200 Subject: [PATCH 253/302] mtd: rawnand: Pass a nand_chip object to chip->block_xxx() hooks Let's make the raw NAND API consistent by patching all helpers and hooks to take a nand_chip object instead of an mtd_info one or remove the mtd_info object when both are passed. Let's tackle all chip->block_xxx() hooks at once. Signed-off-by: Boris Brezillon Signed-off-by: Miquel Raynal --- drivers/mtd/nand/raw/cafe_nand.c | 2 +- drivers/mtd/nand/raw/diskonchip.c | 2 +- drivers/mtd/nand/raw/docg4.c | 6 +++--- drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c | 6 +++--- drivers/mtd/nand/raw/nand_base.c | 16 ++++++++-------- drivers/mtd/nand/raw/nand_bbt.c | 3 +-- drivers/mtd/nand/raw/qcom_nandc.c | 7 +++---- drivers/mtd/nand/raw/sm_common.c | 3 ++- include/linux/mtd/rawnand.h | 4 ++-- 9 files changed, 24 insertions(+), 25 deletions(-) diff --git a/drivers/mtd/nand/raw/cafe_nand.c b/drivers/mtd/nand/raw/cafe_nand.c index e70a47aad538..af6870269f9c 100644 --- a/drivers/mtd/nand/raw/cafe_nand.c +++ b/drivers/mtd/nand/raw/cafe_nand.c @@ -546,7 +546,7 @@ static int cafe_nand_write_page_lowlevel(struct nand_chip *chip, return nand_prog_page_end_op(chip); } -static int cafe_nand_block_bad(struct mtd_info *mtd, loff_t ofs) +static int cafe_nand_block_bad(struct nand_chip *chip, loff_t ofs) { return 0; } diff --git a/drivers/mtd/nand/raw/diskonchip.c b/drivers/mtd/nand/raw/diskonchip.c index 4d7b00d066fe..9cbcf020cabe 100644 --- a/drivers/mtd/nand/raw/diskonchip.c +++ b/drivers/mtd/nand/raw/diskonchip.c @@ -777,7 +777,7 @@ static int doc200x_dev_ready(struct mtd_info *mtd) } } -static int doc200x_block_bad(struct mtd_info *mtd, loff_t ofs) +static int doc200x_block_bad(struct nand_chip *this, loff_t ofs) { /* This is our last resort if we couldn't find or create a BBT. Just pretend all blocks are good. */ diff --git a/drivers/mtd/nand/raw/docg4.c b/drivers/mtd/nand/raw/docg4.c index 78c1d6fd42b2..9e6255408d49 100644 --- a/drivers/mtd/nand/raw/docg4.c +++ b/drivers/mtd/nand/raw/docg4.c @@ -1102,7 +1102,7 @@ static int __init read_factory_bbt(struct mtd_info *mtd) return 0; } -static int docg4_block_markbad(struct mtd_info *mtd, loff_t ofs) +static int docg4_block_markbad(struct nand_chip *nand, loff_t ofs) { /* * Mark a block as bad. Bad blocks are marked in the oob area of the @@ -1115,7 +1115,7 @@ static int docg4_block_markbad(struct mtd_info *mtd, loff_t ofs) int ret, i; uint8_t *buf; - struct nand_chip *nand = mtd_to_nand(mtd); + struct mtd_info *mtd = nand_to_mtd(nand); struct docg4_priv *doc = nand_get_controller_data(nand); struct nand_bbt_descr *bbtd = nand->badblock_pattern; int page = (int)(ofs >> nand->page_shift); @@ -1147,7 +1147,7 @@ static int docg4_block_markbad(struct mtd_info *mtd, loff_t ofs) return ret; } -static int docg4_block_neverbad(struct mtd_info *mtd, loff_t ofs) +static int docg4_block_neverbad(struct nand_chip *nand, loff_t ofs) { /* only called when module_param ignore_badblocks is set */ return 0; diff --git a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c index f5f1aebf0d64..2dce9b62ebe7 100644 --- a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c +++ b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c @@ -1542,9 +1542,9 @@ static int gpmi_ecc_write_oob_raw(struct nand_chip *chip, int page) return gpmi_ecc_write_page_raw(chip, NULL, 1, page); } -static int gpmi_block_markbad(struct mtd_info *mtd, loff_t ofs) +static int gpmi_block_markbad(struct nand_chip *chip, loff_t ofs) { - struct nand_chip *chip = mtd_to_nand(mtd); + struct mtd_info *mtd = nand_to_mtd(chip); struct gpmi_nand_data *this = nand_get_controller_data(chip); int ret = 0; uint8_t *block_mark; @@ -1776,7 +1776,7 @@ static int mx23_boot_init(struct gpmi_nand_data *this) */ if (block_mark != 0xff) { dev_dbg(dev, "Transcribing mark in block %u\n", block); - ret = chip->block_markbad(mtd, byte); + ret = chip->block_markbad(chip, byte); if (ret) dev_err(dev, "Failed to mark block bad with ret %d\n", diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c index 3d3e3c704a5a..add85235497e 100644 --- a/drivers/mtd/nand/raw/nand_base.c +++ b/drivers/mtd/nand/raw/nand_base.c @@ -398,15 +398,15 @@ static void nand_read_buf16(struct nand_chip *chip, uint8_t *buf, int len) /** * nand_block_bad - [DEFAULT] Read bad block marker from the chip - * @mtd: MTD device structure + * @chip: NAND chip object * @ofs: offset from device start * * Check, if the block is bad. */ -static int nand_block_bad(struct mtd_info *mtd, loff_t ofs) +static int nand_block_bad(struct nand_chip *chip, loff_t ofs) { + struct mtd_info *mtd = nand_to_mtd(chip); int page, page_end, res; - struct nand_chip *chip = mtd_to_nand(mtd); u8 bad; if (chip->bbt_options & NAND_BBT_SCANLASTPAGE) @@ -435,16 +435,16 @@ static int nand_block_bad(struct mtd_info *mtd, loff_t ofs) /** * nand_default_block_markbad - [DEFAULT] mark a block bad via bad block marker - * @mtd: MTD device structure + * @chip: NAND chip object * @ofs: offset from device start * * This is the default implementation, which can be overridden by a hardware * specific driver. It provides the details for writing a bad block marker to a * block. */ -static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs) +static int nand_default_block_markbad(struct nand_chip *chip, loff_t ofs) { - struct nand_chip *chip = mtd_to_nand(mtd); + struct mtd_info *mtd = nand_to_mtd(chip); struct mtd_oob_ops ops; uint8_t buf[2] = { 0, 0 }; int ret = 0, res, i = 0; @@ -510,7 +510,7 @@ static int nand_block_markbad_lowlevel(struct mtd_info *mtd, loff_t ofs) /* Write bad block marker to OOB */ nand_get_device(mtd, FL_WRITING); - ret = chip->block_markbad(mtd, ofs); + ret = chip->block_markbad(chip, ofs); nand_release_device(mtd); } @@ -583,7 +583,7 @@ static int nand_block_checkbad(struct mtd_info *mtd, loff_t ofs, int allowbbt) struct nand_chip *chip = mtd_to_nand(mtd); if (!chip->bbt) - return chip->block_bad(mtd, ofs); + return chip->block_bad(chip, ofs); /* Return info from the table */ return nand_isbad_bbt(mtd, ofs, allowbbt); diff --git a/drivers/mtd/nand/raw/nand_bbt.c b/drivers/mtd/nand/raw/nand_bbt.c index 39db352f8757..76849a441518 100644 --- a/drivers/mtd/nand/raw/nand_bbt.c +++ b/drivers/mtd/nand/raw/nand_bbt.c @@ -683,14 +683,13 @@ static void mark_bbt_block_bad(struct nand_chip *this, struct nand_bbt_descr *td, int chip, int block) { - struct mtd_info *mtd = nand_to_mtd(this); loff_t to; int res; bbt_mark_entry(this, block, BBT_BLOCK_WORN); to = (loff_t)block << this->bbt_erase_shift; - res = this->block_markbad(mtd, to); + res = this->block_markbad(this, to); if (res) pr_warn("nand_bbt: error %d while marking block %d bad\n", res, block); diff --git a/drivers/mtd/nand/raw/qcom_nandc.c b/drivers/mtd/nand/raw/qcom_nandc.c index 626c9ab8c8db..c6eb205e0f76 100644 --- a/drivers/mtd/nand/raw/qcom_nandc.c +++ b/drivers/mtd/nand/raw/qcom_nandc.c @@ -2196,9 +2196,9 @@ static int qcom_nandc_write_oob(struct nand_chip *chip, int page) return nand_prog_page_end_op(chip); } -static int qcom_nandc_block_bad(struct mtd_info *mtd, loff_t ofs) +static int qcom_nandc_block_bad(struct nand_chip *chip, loff_t ofs) { - struct nand_chip *chip = mtd_to_nand(mtd); + struct mtd_info *mtd = nand_to_mtd(chip); struct qcom_nand_host *host = to_qcom_nand_host(chip); struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip); struct nand_ecc_ctrl *ecc = &chip->ecc; @@ -2234,9 +2234,8 @@ static int qcom_nandc_block_bad(struct mtd_info *mtd, loff_t ofs) return bad; } -static int qcom_nandc_block_markbad(struct mtd_info *mtd, loff_t ofs) +static int qcom_nandc_block_markbad(struct nand_chip *chip, loff_t ofs) { - struct nand_chip *chip = mtd_to_nand(mtd); struct qcom_nand_host *host = to_qcom_nand_host(chip); struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip); struct nand_ecc_ctrl *ecc = &chip->ecc; diff --git a/drivers/mtd/nand/raw/sm_common.c b/drivers/mtd/nand/raw/sm_common.c index 02ac6e9b2d16..bf143e0db787 100644 --- a/drivers/mtd/nand/raw/sm_common.c +++ b/drivers/mtd/nand/raw/sm_common.c @@ -99,8 +99,9 @@ static const struct mtd_ooblayout_ops oob_sm_small_ops = { .free = oob_sm_small_ooblayout_free, }; -static int sm_block_markbad(struct mtd_info *mtd, loff_t ofs) +static int sm_block_markbad(struct nand_chip *chip, loff_t ofs) { + struct mtd_info *mtd = nand_to_mtd(chip); struct mtd_oob_ops ops; struct sm_oob oob; int ret; diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h index 65a25e89b426..0d8e2708e125 100644 --- a/include/linux/mtd/rawnand.h +++ b/include/linux/mtd/rawnand.h @@ -1288,8 +1288,8 @@ struct nand_chip { void (*write_buf)(struct nand_chip *chip, const uint8_t *buf, int len); void (*read_buf)(struct nand_chip *chip, uint8_t *buf, int len); void (*select_chip)(struct nand_chip *chip, int cs); - int (*block_bad)(struct mtd_info *mtd, loff_t ofs); - int (*block_markbad)(struct mtd_info *mtd, loff_t ofs); + int (*block_bad)(struct nand_chip *chip, loff_t ofs); + int (*block_markbad)(struct nand_chip *chip, loff_t ofs); void (*cmd_ctrl)(struct mtd_info *mtd, int dat, unsigned int ctrl); int (*dev_ready)(struct mtd_info *mtd); void (*cmdfunc)(struct mtd_info *mtd, unsigned command, int column, From 0f808c1602bc75c74399989d47842197118f7e72 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Thu, 6 Sep 2018 14:05:26 +0200 Subject: [PATCH 254/302] mtd: rawnand: Pass a nand_chip object to chip->cmd_ctrl() Let's make the raw NAND API consistent by patching all helpers and hooks to take a nand_chip object instead of an mtd_info one or remove the mtd_info object when both are passed. Let's tackle the chip->cmd_ctrl() hook. Signed-off-by: Boris Brezillon Signed-off-by: Miquel Raynal --- drivers/mtd/nand/raw/ams-delta.c | 4 +- drivers/mtd/nand/raw/atmel/nand-controller.c | 6 +-- .../mtd/nand/raw/bcm47xxnflash/ops_bcm4706.c | 7 ++- drivers/mtd/nand/raw/brcmnand/brcmnand.c | 4 +- drivers/mtd/nand/raw/cmx270_nand.c | 3 +- drivers/mtd/nand/raw/cs553x_nand.c | 3 +- drivers/mtd/nand/raw/davinci_nand.c | 5 +- drivers/mtd/nand/raw/denali.c | 4 +- drivers/mtd/nand/raw/diskonchip.c | 22 ++++----- drivers/mtd/nand/raw/fsl_upm.c | 10 ++-- drivers/mtd/nand/raw/gpio.c | 5 +- drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c | 3 +- drivers/mtd/nand/raw/jz4740_nand.c | 6 +-- drivers/mtd/nand/raw/jz4780_nand.c | 4 +- drivers/mtd/nand/raw/lpc32xx_mlc.c | 3 +- drivers/mtd/nand/raw/lpc32xx_slc.c | 5 +- drivers/mtd/nand/raw/mtk_nand.c | 5 +- drivers/mtd/nand/raw/nand_base.c | 47 +++++++++---------- drivers/mtd/nand/raw/nandsim.c | 3 +- drivers/mtd/nand/raw/ndfc.c | 3 +- drivers/mtd/nand/raw/omap2.c | 6 +-- drivers/mtd/nand/raw/orion_nand.c | 4 +- drivers/mtd/nand/raw/oxnas_nand.c | 3 +- drivers/mtd/nand/raw/pasemi_nand.c | 4 +- drivers/mtd/nand/raw/plat_nand.c | 11 +---- drivers/mtd/nand/raw/r852.c | 4 +- drivers/mtd/nand/raw/s3c2410.c | 6 ++- drivers/mtd/nand/raw/sharpsl.c | 5 +- drivers/mtd/nand/raw/socrates_nand.c | 5 +- drivers/mtd/nand/raw/sunxi_nand.c | 3 +- drivers/mtd/nand/raw/tango_nand.c | 4 +- drivers/mtd/nand/raw/tmio_nand.c | 7 ++- drivers/mtd/nand/raw/txx9ndfmc.c | 3 +- drivers/mtd/nand/raw/xway_nand.c | 4 +- include/linux/mtd/rawnand.h | 2 +- 35 files changed, 98 insertions(+), 125 deletions(-) diff --git a/drivers/mtd/nand/raw/ams-delta.c b/drivers/mtd/nand/raw/ams-delta.c index d742b9444429..8121d26194cf 100644 --- a/drivers/mtd/nand/raw/ams-delta.c +++ b/drivers/mtd/nand/raw/ams-delta.c @@ -113,7 +113,7 @@ static void ams_delta_read_buf(struct nand_chip *this, u_char *buf, int len) * NAND_CLE: bit 1 -> bit 7 * NAND_ALE: bit 2 -> bit 6 */ -static void ams_delta_hwcontrol(struct mtd_info *mtd, int cmd, +static void ams_delta_hwcontrol(struct nand_chip *this, int cmd, unsigned int ctrl) { @@ -127,7 +127,7 @@ static void ams_delta_hwcontrol(struct mtd_info *mtd, int cmd, } if (cmd != NAND_CMD_NONE) - ams_delta_write_byte(mtd_to_nand(mtd), cmd); + ams_delta_write_byte(this, cmd); } static int ams_delta_nand_ready(struct mtd_info *mtd) diff --git a/drivers/mtd/nand/raw/atmel/nand-controller.c b/drivers/mtd/nand/raw/atmel/nand-controller.c index 5c8ef476ed47..f088bff06723 100644 --- a/drivers/mtd/nand/raw/atmel/nand-controller.c +++ b/drivers/mtd/nand/raw/atmel/nand-controller.c @@ -594,10 +594,9 @@ static int atmel_nfc_exec_op(struct atmel_hsmc_nand_controller *nc, bool poll) return ret; } -static void atmel_hsmc_nand_cmd_ctrl(struct mtd_info *mtd, int dat, +static void atmel_hsmc_nand_cmd_ctrl(struct nand_chip *chip, int dat, unsigned int ctrl) { - struct nand_chip *chip = mtd_to_nand(mtd); struct atmel_nand *nand = to_atmel_nand(chip); struct atmel_hsmc_nand_controller *nc; @@ -621,10 +620,9 @@ static void atmel_hsmc_nand_cmd_ctrl(struct mtd_info *mtd, int dat, } } -static void atmel_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, +static void atmel_nand_cmd_ctrl(struct nand_chip *chip, int cmd, unsigned int ctrl) { - struct nand_chip *chip = mtd_to_nand(mtd); struct atmel_nand *nand = to_atmel_nand(chip); struct atmel_nand_controller *nc; diff --git a/drivers/mtd/nand/raw/bcm47xxnflash/ops_bcm4706.c b/drivers/mtd/nand/raw/bcm47xxnflash/ops_bcm4706.c index c8e30b0308bc..d326f9d3648b 100644 --- a/drivers/mtd/nand/raw/bcm47xxnflash/ops_bcm4706.c +++ b/drivers/mtd/nand/raw/bcm47xxnflash/ops_bcm4706.c @@ -170,10 +170,9 @@ static void bcm47xxnflash_ops_bcm4706_write(struct mtd_info *mtd, * NAND chip ops **************************************************/ -static void bcm47xxnflash_ops_bcm4706_cmd_ctrl(struct mtd_info *mtd, int cmd, - unsigned int ctrl) +static void bcm47xxnflash_ops_bcm4706_cmd_ctrl(struct nand_chip *nand_chip, + int cmd, unsigned int ctrl) { - struct nand_chip *nand_chip = mtd_to_nand(mtd); struct bcm47xxnflash *b47n = nand_get_controller_data(nand_chip); u32 code = 0; @@ -229,7 +228,7 @@ static void bcm47xxnflash_ops_bcm4706_cmdfunc(struct mtd_info *mtd, switch (command) { case NAND_CMD_RESET: - nand_chip->cmd_ctrl(mtd, command, NAND_CTRL_CLE); + nand_chip->cmd_ctrl(nand_chip, command, NAND_CTRL_CLE); ndelay(100); nand_wait_ready(nand_chip); diff --git a/drivers/mtd/nand/raw/brcmnand/brcmnand.c b/drivers/mtd/nand/raw/brcmnand/brcmnand.c index e24e77b27618..80f5b4b9ee75 100644 --- a/drivers/mtd/nand/raw/brcmnand/brcmnand.c +++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c @@ -1231,8 +1231,8 @@ static void brcmnand_send_cmd(struct brcmnand_host *host, int cmd) * NAND MTD API: read/program/erase ***********************************************************************/ -static void brcmnand_cmd_ctrl(struct mtd_info *mtd, int dat, - unsigned int ctrl) +static void brcmnand_cmd_ctrl(struct nand_chip *chip, int dat, + unsigned int ctrl) { /* intentionally left blank */ } diff --git a/drivers/mtd/nand/raw/cmx270_nand.c b/drivers/mtd/nand/raw/cmx270_nand.c index 4e5c8b7721ab..a0f0ad2da6f1 100644 --- a/drivers/mtd/nand/raw/cmx270_nand.c +++ b/drivers/mtd/nand/raw/cmx270_nand.c @@ -86,10 +86,9 @@ static void nand_cs_off(void) /* * hardware specific access to control-lines */ -static void cmx270_hwcontrol(struct mtd_info *mtd, int dat, +static void cmx270_hwcontrol(struct nand_chip *this, int dat, unsigned int ctrl) { - struct nand_chip *this = mtd_to_nand(mtd); unsigned int nandaddr = (unsigned int)this->IO_ADDR_W; dsb(); diff --git a/drivers/mtd/nand/raw/cs553x_nand.c b/drivers/mtd/nand/raw/cs553x_nand.c index 442fa583db44..b7432f086f9b 100644 --- a/drivers/mtd/nand/raw/cs553x_nand.c +++ b/drivers/mtd/nand/raw/cs553x_nand.c @@ -129,10 +129,9 @@ static void cs553x_write_byte(struct nand_chip *this, u_char byte) writeb(byte, this->IO_ADDR_W + 0x801); } -static void cs553x_hwcontrol(struct mtd_info *mtd, int cmd, +static void cs553x_hwcontrol(struct nand_chip *this, int cmd, unsigned int ctrl) { - struct nand_chip *this = mtd_to_nand(mtd); void __iomem *mmio_base = this->IO_ADDR_R; if (ctrl & NAND_CTRL_CHANGE) { unsigned char ctl = (ctrl & ~NAND_CTRL_CHANGE ) ^ 0x01; diff --git a/drivers/mtd/nand/raw/davinci_nand.c b/drivers/mtd/nand/raw/davinci_nand.c index 85bc801424b0..c2a3ad10610c 100644 --- a/drivers/mtd/nand/raw/davinci_nand.c +++ b/drivers/mtd/nand/raw/davinci_nand.c @@ -97,12 +97,11 @@ static inline void davinci_nand_writel(struct davinci_nand_info *info, * Access to hardware control lines: ALE, CLE, secondary chipselect. */ -static void nand_davinci_hwcontrol(struct mtd_info *mtd, int cmd, +static void nand_davinci_hwcontrol(struct nand_chip *nand, int cmd, unsigned int ctrl) { - struct davinci_nand_info *info = to_davinci_nand(mtd); + struct davinci_nand_info *info = to_davinci_nand(nand_to_mtd(nand)); void __iomem *addr = info->current_cs; - struct nand_chip *nand = mtd_to_nand(mtd); /* Did the control lines change? */ if (ctrl & NAND_CTRL_CHANGE) { diff --git a/drivers/mtd/nand/raw/denali.c b/drivers/mtd/nand/raw/denali.c index e29ec95f24de..6529780e31a4 100644 --- a/drivers/mtd/nand/raw/denali.c +++ b/drivers/mtd/nand/raw/denali.c @@ -274,9 +274,9 @@ static void denali_write_byte(struct nand_chip *chip, uint8_t byte) denali_write_buf(chip, &byte, 1); } -static void denali_cmd_ctrl(struct mtd_info *mtd, int dat, unsigned int ctrl) +static void denali_cmd_ctrl(struct nand_chip *chip, int dat, unsigned int ctrl) { - struct denali_nand_info *denali = mtd_to_denali(mtd); + struct denali_nand_info *denali = mtd_to_denali(nand_to_mtd(chip)); uint32_t type; if (ctrl & NAND_CLE) diff --git a/drivers/mtd/nand/raw/diskonchip.c b/drivers/mtd/nand/raw/diskonchip.c index 9cbcf020cabe..16498b277764 100644 --- a/drivers/mtd/nand/raw/diskonchip.c +++ b/drivers/mtd/nand/raw/diskonchip.c @@ -83,7 +83,7 @@ static u_char empty_write_ecc[6] = { 0x4b, 0x00, 0xe2, 0x0e, 0x93, 0xf7 }; #define DoC_is_Millennium(doc) ((doc)->ChipID == DOC_ChipID_DocMil) #define DoC_is_2000(doc) ((doc)->ChipID == DOC_ChipID_Doc2k) -static void doc200x_hwcontrol(struct mtd_info *mtd, int cmd, +static void doc200x_hwcontrol(struct nand_chip *this, int cmd, unsigned int bitmask); static void doc200x_select_chip(struct nand_chip *this, int chip); @@ -372,10 +372,10 @@ static uint16_t __init doc200x_ident_chip(struct mtd_info *mtd, int nr) uint16_t ret; doc200x_select_chip(this, nr); - doc200x_hwcontrol(mtd, NAND_CMD_READID, + doc200x_hwcontrol(this, NAND_CMD_READID, NAND_CTRL_CLE | NAND_CTRL_CHANGE); - doc200x_hwcontrol(mtd, 0, NAND_CTRL_ALE | NAND_CTRL_CHANGE); - doc200x_hwcontrol(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE); + doc200x_hwcontrol(this, 0, NAND_CTRL_ALE | NAND_CTRL_CHANGE); + doc200x_hwcontrol(this, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE); /* We can't use dev_ready here, but at least we wait for the * command to complete @@ -393,10 +393,10 @@ static uint16_t __init doc200x_ident_chip(struct mtd_info *mtd, int nr) } ident; void __iomem *docptr = doc->virtadr; - doc200x_hwcontrol(mtd, NAND_CMD_READID, + doc200x_hwcontrol(this, NAND_CMD_READID, NAND_CTRL_CLE | NAND_CTRL_CHANGE); - doc200x_hwcontrol(mtd, 0, NAND_CTRL_ALE | NAND_CTRL_CHANGE); - doc200x_hwcontrol(mtd, NAND_CMD_NONE, + doc200x_hwcontrol(this, 0, NAND_CTRL_ALE | NAND_CTRL_CHANGE); + doc200x_hwcontrol(this, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE); udelay(50); @@ -587,7 +587,6 @@ static void doc2001plus_select_chip(struct nand_chip *this, int chip) static void doc200x_select_chip(struct nand_chip *this, int chip) { - struct mtd_info *mtd = nand_to_mtd(this); struct doc_priv *doc = nand_get_controller_data(this); void __iomem *docptr = doc->virtadr; int floor = 0; @@ -602,12 +601,12 @@ static void doc200x_select_chip(struct nand_chip *this, int chip) chip -= (floor * doc->chips_per_floor); /* 11.4.4 -- deassert CE before changing chip */ - doc200x_hwcontrol(mtd, NAND_CMD_NONE, 0 | NAND_CTRL_CHANGE); + doc200x_hwcontrol(this, NAND_CMD_NONE, 0 | NAND_CTRL_CHANGE); WriteDOC(floor, docptr, FloorSelect); WriteDOC(chip, docptr, CDSNDeviceSelect); - doc200x_hwcontrol(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE); + doc200x_hwcontrol(this, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE); doc->curchip = chip; doc->curfloor = floor; @@ -615,10 +614,9 @@ static void doc200x_select_chip(struct nand_chip *this, int chip) #define CDSN_CTRL_MSK (CDSN_CTRL_CE | CDSN_CTRL_CLE | CDSN_CTRL_ALE) -static void doc200x_hwcontrol(struct mtd_info *mtd, int cmd, +static void doc200x_hwcontrol(struct nand_chip *this, int cmd, unsigned int ctrl) { - struct nand_chip *this = mtd_to_nand(mtd); struct doc_priv *doc = nand_get_controller_data(this); void __iomem *docptr = doc->virtadr; diff --git a/drivers/mtd/nand/raw/fsl_upm.c b/drivers/mtd/nand/raw/fsl_upm.c index ec3553cb737a..7a2488c6c212 100644 --- a/drivers/mtd/nand/raw/fsl_upm.c +++ b/drivers/mtd/nand/raw/fsl_upm.c @@ -78,10 +78,9 @@ static void fun_wait_rnb(struct fsl_upm_nand *fun) } } -static void fun_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl) +static void fun_cmd_ctrl(struct nand_chip *chip, int cmd, unsigned int ctrl) { - struct nand_chip *chip = mtd_to_nand(mtd); - struct fsl_upm_nand *fun = to_fsl_upm_nand(mtd); + struct fsl_upm_nand *fun = to_fsl_upm_nand(nand_to_mtd(chip)); u32 mar; if (!(ctrl & fun->last_ctrl)) { @@ -110,11 +109,10 @@ static void fun_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl) static void fun_select_chip(struct nand_chip *chip, int mchip_nr) { - struct mtd_info *mtd = nand_to_mtd(chip); - struct fsl_upm_nand *fun = to_fsl_upm_nand(mtd); + struct fsl_upm_nand *fun = to_fsl_upm_nand(nand_to_mtd(chip)); if (mchip_nr == -1) { - chip->cmd_ctrl(mtd, NAND_CMD_NONE, 0 | NAND_CTRL_CHANGE); + chip->cmd_ctrl(chip, NAND_CMD_NONE, 0 | NAND_CTRL_CHANGE); } else if (mchip_nr >= 0 && mchip_nr < NAND_MAX_CHIPS) { fun->mchip_number = mchip_nr; chip->IO_ADDR_R = fun->io_base + fun->mchip_offsets[mchip_nr]; diff --git a/drivers/mtd/nand/raw/gpio.c b/drivers/mtd/nand/raw/gpio.c index 0e7d00faf33c..722a930ac836 100644 --- a/drivers/mtd/nand/raw/gpio.c +++ b/drivers/mtd/nand/raw/gpio.c @@ -73,9 +73,10 @@ static void gpio_nand_dosync(struct gpiomtd *gpiomtd) static inline void gpio_nand_dosync(struct gpiomtd *gpiomtd) {} #endif -static void gpio_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl) +static void gpio_nand_cmd_ctrl(struct nand_chip *chip, int cmd, + unsigned int ctrl) { - struct gpiomtd *gpiomtd = gpio_nand_getpriv(mtd); + struct gpiomtd *gpiomtd = gpio_nand_getpriv(nand_to_mtd(chip)); gpio_nand_dosync(gpiomtd); diff --git a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c index 2dce9b62ebe7..460f2f77a424 100644 --- a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c +++ b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c @@ -783,9 +783,8 @@ static int gpmi_alloc_dma_buffer(struct gpmi_nand_data *this) return -ENOMEM; } -static void gpmi_cmd_ctrl(struct mtd_info *mtd, int data, unsigned int ctrl) +static void gpmi_cmd_ctrl(struct nand_chip *chip, int data, unsigned int ctrl) { - struct nand_chip *chip = mtd_to_nand(mtd); struct gpmi_nand_data *this = nand_get_controller_data(chip); int ret; diff --git a/drivers/mtd/nand/raw/jz4740_nand.c b/drivers/mtd/nand/raw/jz4740_nand.c index b6e68048b83d..7999e691e636 100644 --- a/drivers/mtd/nand/raw/jz4740_nand.c +++ b/drivers/mtd/nand/raw/jz4740_nand.c @@ -99,10 +99,10 @@ static void jz_nand_select_chip(struct nand_chip *chip, int chipnr) nand->selected_bank = banknr; } -static void jz_nand_cmd_ctrl(struct mtd_info *mtd, int dat, unsigned int ctrl) +static void jz_nand_cmd_ctrl(struct nand_chip *chip, int dat, + unsigned int ctrl) { - struct jz_nand *nand = mtd_to_jz_nand(mtd); - struct nand_chip *chip = mtd_to_nand(mtd); + struct jz_nand *nand = mtd_to_jz_nand(nand_to_mtd(chip)); uint32_t reg; void __iomem *bank_base = nand->bank_base[nand->selected_bank]; diff --git a/drivers/mtd/nand/raw/jz4780_nand.c b/drivers/mtd/nand/raw/jz4780_nand.c index 29e597b0ca59..1d2cba546258 100644 --- a/drivers/mtd/nand/raw/jz4780_nand.c +++ b/drivers/mtd/nand/raw/jz4780_nand.c @@ -86,10 +86,10 @@ static void jz4780_nand_select_chip(struct nand_chip *chip, int chipnr) nfc->selected = chipnr; } -static void jz4780_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, +static void jz4780_nand_cmd_ctrl(struct nand_chip *chip, int cmd, unsigned int ctrl) { - struct jz4780_nand_chip *nand = to_jz4780_nand_chip(mtd); + struct jz4780_nand_chip *nand = to_jz4780_nand_chip(nand_to_mtd(chip)); struct jz4780_nand_controller *nfc = to_jz4780_nand_controller(nand->chip.controller); struct jz4780_nand_cs *cs; diff --git a/drivers/mtd/nand/raw/lpc32xx_mlc.c b/drivers/mtd/nand/raw/lpc32xx_mlc.c index 79a02acb0517..0e989d944ddb 100644 --- a/drivers/mtd/nand/raw/lpc32xx_mlc.c +++ b/drivers/mtd/nand/raw/lpc32xx_mlc.c @@ -286,10 +286,9 @@ static void lpc32xx_nand_setup(struct lpc32xx_nand_host *host) /* * Hardware specific access to control lines */ -static void lpc32xx_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, +static void lpc32xx_nand_cmd_ctrl(struct nand_chip *nand_chip, int cmd, unsigned int ctrl) { - struct nand_chip *nand_chip = mtd_to_nand(mtd); struct lpc32xx_nand_host *host = nand_get_controller_data(nand_chip); if (cmd != NAND_CMD_NONE) { diff --git a/drivers/mtd/nand/raw/lpc32xx_slc.c b/drivers/mtd/nand/raw/lpc32xx_slc.c index d04b30989041..e42584de875c 100644 --- a/drivers/mtd/nand/raw/lpc32xx_slc.c +++ b/drivers/mtd/nand/raw/lpc32xx_slc.c @@ -278,11 +278,10 @@ static void lpc32xx_nand_setup(struct lpc32xx_nand_host *host) /* * Hardware specific access to control lines */ -static void lpc32xx_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, - unsigned int ctrl) +static void lpc32xx_nand_cmd_ctrl(struct nand_chip *chip, int cmd, + unsigned int ctrl) { uint32_t tmp; - struct nand_chip *chip = mtd_to_nand(mtd); struct lpc32xx_nand_host *host = nand_get_controller_data(chip); /* Does CE state need to be changed? */ diff --git a/drivers/mtd/nand/raw/mtk_nand.c b/drivers/mtd/nand/raw/mtk_nand.c index 6e5d4afd6b1a..6baa41483931 100644 --- a/drivers/mtd/nand/raw/mtk_nand.c +++ b/drivers/mtd/nand/raw/mtk_nand.c @@ -412,9 +412,10 @@ static int mtk_nfc_dev_ready(struct mtd_info *mtd) return 1; } -static void mtk_nfc_cmd_ctrl(struct mtd_info *mtd, int dat, unsigned int ctrl) +static void mtk_nfc_cmd_ctrl(struct nand_chip *chip, int dat, + unsigned int ctrl) { - struct mtk_nfc *nfc = nand_get_controller_data(mtd_to_nand(mtd)); + struct mtk_nfc *nfc = nand_get_controller_data(chip); if (ctrl & NAND_ALE) { mtk_nfc_send_address(nfc, dat); diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c index add85235497e..f0d70164a2f1 100644 --- a/drivers/mtd/nand/raw/nand_base.c +++ b/drivers/mtd/nand/raw/nand_base.c @@ -286,8 +286,7 @@ static void nand_select_chip(struct nand_chip *chip, int chipnr) { switch (chipnr) { case -1: - chip->cmd_ctrl(nand_to_mtd(chip), NAND_CMD_NONE, - 0 | NAND_CTRL_CHANGE); + chip->cmd_ctrl(chip, NAND_CMD_NONE, 0 | NAND_CTRL_CHANGE); break; case 0: break; @@ -760,11 +759,11 @@ static void nand_command(struct mtd_info *mtd, unsigned int command, column -= 256; readcmd = NAND_CMD_READ1; } - chip->cmd_ctrl(mtd, readcmd, ctrl); + chip->cmd_ctrl(chip, readcmd, ctrl); ctrl &= ~NAND_CTRL_CHANGE; } if (command != NAND_CMD_NONE) - chip->cmd_ctrl(mtd, command, ctrl); + chip->cmd_ctrl(chip, command, ctrl); /* Address cycle, when necessary */ ctrl = NAND_CTRL_ALE | NAND_CTRL_CHANGE; @@ -774,17 +773,17 @@ static void nand_command(struct mtd_info *mtd, unsigned int command, if (chip->options & NAND_BUSWIDTH_16 && !nand_opcode_8bits(command)) column >>= 1; - chip->cmd_ctrl(mtd, column, ctrl); + chip->cmd_ctrl(chip, column, ctrl); ctrl &= ~NAND_CTRL_CHANGE; } if (page_addr != -1) { - chip->cmd_ctrl(mtd, page_addr, ctrl); + chip->cmd_ctrl(chip, page_addr, ctrl); ctrl &= ~NAND_CTRL_CHANGE; - chip->cmd_ctrl(mtd, page_addr >> 8, ctrl); + chip->cmd_ctrl(chip, page_addr >> 8, ctrl); if (chip->options & NAND_ROW_ADDR_3) - chip->cmd_ctrl(mtd, page_addr >> 16, ctrl); + chip->cmd_ctrl(chip, page_addr >> 16, ctrl); } - chip->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE); + chip->cmd_ctrl(chip, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE); /* * Program and erase have their own busy handlers status and sequential @@ -806,9 +805,9 @@ static void nand_command(struct mtd_info *mtd, unsigned int command, if (chip->dev_ready) break; udelay(chip->chip_delay); - chip->cmd_ctrl(mtd, NAND_CMD_STATUS, + chip->cmd_ctrl(chip, NAND_CMD_STATUS, NAND_CTRL_CLE | NAND_CTRL_CHANGE); - chip->cmd_ctrl(mtd, + chip->cmd_ctrl(chip, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE); /* EZ-NAND can take upto 250ms as per ONFi v4.0 */ nand_wait_status_ready(mtd, 250); @@ -887,7 +886,7 @@ static void nand_command_lp(struct mtd_info *mtd, unsigned int command, /* Command latch cycle */ if (command != NAND_CMD_NONE) - chip->cmd_ctrl(mtd, command, + chip->cmd_ctrl(chip, command, NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE); if (column != -1 || page_addr != -1) { @@ -899,23 +898,23 @@ static void nand_command_lp(struct mtd_info *mtd, unsigned int command, if (chip->options & NAND_BUSWIDTH_16 && !nand_opcode_8bits(command)) column >>= 1; - chip->cmd_ctrl(mtd, column, ctrl); + chip->cmd_ctrl(chip, column, ctrl); ctrl &= ~NAND_CTRL_CHANGE; /* Only output a single addr cycle for 8bits opcodes. */ if (!nand_opcode_8bits(command)) - chip->cmd_ctrl(mtd, column >> 8, ctrl); + chip->cmd_ctrl(chip, column >> 8, ctrl); } if (page_addr != -1) { - chip->cmd_ctrl(mtd, page_addr, ctrl); - chip->cmd_ctrl(mtd, page_addr >> 8, + chip->cmd_ctrl(chip, page_addr, ctrl); + chip->cmd_ctrl(chip, page_addr >> 8, NAND_NCE | NAND_ALE); if (chip->options & NAND_ROW_ADDR_3) - chip->cmd_ctrl(mtd, page_addr >> 16, + chip->cmd_ctrl(chip, page_addr >> 16, NAND_NCE | NAND_ALE); } } - chip->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE); + chip->cmd_ctrl(chip, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE); /* * Program and erase have their own busy handlers status, sequential @@ -942,9 +941,9 @@ static void nand_command_lp(struct mtd_info *mtd, unsigned int command, if (chip->dev_ready) break; udelay(chip->chip_delay); - chip->cmd_ctrl(mtd, NAND_CMD_STATUS, + chip->cmd_ctrl(chip, NAND_CMD_STATUS, NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE); - chip->cmd_ctrl(mtd, NAND_CMD_NONE, + chip->cmd_ctrl(chip, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE); /* EZ-NAND can take upto 250ms as per ONFi v4.0 */ nand_wait_status_ready(mtd, 250); @@ -952,9 +951,9 @@ static void nand_command_lp(struct mtd_info *mtd, unsigned int command, case NAND_CMD_RNDOUT: /* No ready / busy check necessary */ - chip->cmd_ctrl(mtd, NAND_CMD_RNDOUTSTART, + chip->cmd_ctrl(chip, NAND_CMD_RNDOUTSTART, NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE); - chip->cmd_ctrl(mtd, NAND_CMD_NONE, + chip->cmd_ctrl(chip, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE); nand_ccs_delay(chip); @@ -970,9 +969,9 @@ static void nand_command_lp(struct mtd_info *mtd, unsigned int command, if (column == -1 && page_addr == -1) return; - chip->cmd_ctrl(mtd, NAND_CMD_READSTART, + chip->cmd_ctrl(chip, NAND_CMD_READSTART, NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE); - chip->cmd_ctrl(mtd, NAND_CMD_NONE, + chip->cmd_ctrl(chip, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE); /* This applies to read commands */ diff --git a/drivers/mtd/nand/raw/nandsim.c b/drivers/mtd/nand/raw/nandsim.c index 880ba12e07ba..a6b626c935a8 100644 --- a/drivers/mtd/nand/raw/nandsim.c +++ b/drivers/mtd/nand/raw/nandsim.c @@ -2087,9 +2087,8 @@ static void ns_nand_write_byte(struct nand_chip *chip, u_char byte) return; } -static void ns_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int bitmask) +static void ns_hwcontrol(struct nand_chip *chip, int cmd, unsigned int bitmask) { - struct nand_chip *chip = mtd_to_nand(mtd); struct nandsim *ns = nand_get_controller_data(chip); ns->lines.cle = bitmask & NAND_CLE ? 1 : 0; diff --git a/drivers/mtd/nand/raw/ndfc.c b/drivers/mtd/nand/raw/ndfc.c index addcc736ae1d..05ac7bf94874 100644 --- a/drivers/mtd/nand/raw/ndfc.c +++ b/drivers/mtd/nand/raw/ndfc.c @@ -58,9 +58,8 @@ static void ndfc_select_chip(struct nand_chip *nchip, int chip) out_be32(ndfc->ndfcbase + NDFC_CCR, ccr); } -static void ndfc_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl) +static void ndfc_hwcontrol(struct nand_chip *chip, int cmd, unsigned int ctrl) { - struct nand_chip *chip = mtd_to_nand(mtd); struct ndfc_controller *ndfc = nand_get_controller_data(chip); if (cmd == NAND_CMD_NONE) diff --git a/drivers/mtd/nand/raw/omap2.c b/drivers/mtd/nand/raw/omap2.c index 5a2bf1ed9c86..4bae782cd877 100644 --- a/drivers/mtd/nand/raw/omap2.c +++ b/drivers/mtd/nand/raw/omap2.c @@ -240,7 +240,7 @@ static int omap_prefetch_reset(int cs, struct omap_nand_info *info) /** * omap_hwcontrol - hardware specific access to control-lines - * @mtd: MTD device structure + * @chip: NAND chip object * @cmd: command to device * @ctrl: * NAND_NCE: bit 0 -> don't care @@ -249,9 +249,9 @@ static int omap_prefetch_reset(int cs, struct omap_nand_info *info) * * NOTE: boards may use different bits for these!! */ -static void omap_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl) +static void omap_hwcontrol(struct nand_chip *chip, int cmd, unsigned int ctrl) { - struct omap_nand_info *info = mtd_to_omap(mtd); + struct omap_nand_info *info = mtd_to_omap(nand_to_mtd(chip)); if (cmd != NAND_CMD_NONE) { if (ctrl & NAND_CLE) diff --git a/drivers/mtd/nand/raw/orion_nand.c b/drivers/mtd/nand/raw/orion_nand.c index 870eabe6fff8..92d8f249ee97 100644 --- a/drivers/mtd/nand/raw/orion_nand.c +++ b/drivers/mtd/nand/raw/orion_nand.c @@ -26,9 +26,9 @@ struct orion_nand_info { struct clk *clk; }; -static void orion_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl) +static void orion_nand_cmd_ctrl(struct nand_chip *nc, int cmd, + unsigned int ctrl) { - struct nand_chip *nc = mtd_to_nand(mtd); struct orion_nand_data *board = nand_get_controller_data(nc); u32 offs; diff --git a/drivers/mtd/nand/raw/oxnas_nand.c b/drivers/mtd/nand/raw/oxnas_nand.c index 93c04bec471d..ab32df146505 100644 --- a/drivers/mtd/nand/raw/oxnas_nand.c +++ b/drivers/mtd/nand/raw/oxnas_nand.c @@ -61,10 +61,9 @@ static void oxnas_nand_write_buf(struct nand_chip *chip, const u8 *buf, } /* Single CS command control */ -static void oxnas_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, +static void oxnas_nand_cmd_ctrl(struct nand_chip *chip, int cmd, unsigned int ctrl) { - struct nand_chip *chip = mtd_to_nand(mtd); struct oxnas_nand_ctrl *oxnas = nand_get_controller_data(chip); if (ctrl & NAND_CLE) diff --git a/drivers/mtd/nand/raw/pasemi_nand.c b/drivers/mtd/nand/raw/pasemi_nand.c index 70aff4180ab7..661ba57f2934 100644 --- a/drivers/mtd/nand/raw/pasemi_nand.c +++ b/drivers/mtd/nand/raw/pasemi_nand.c @@ -64,11 +64,9 @@ static void pasemi_write_buf(struct nand_chip *chip, const u_char *buf, memcpy_toio(chip->IO_ADDR_R, buf, len); } -static void pasemi_hwcontrol(struct mtd_info *mtd, int cmd, +static void pasemi_hwcontrol(struct nand_chip *chip, int cmd, unsigned int ctrl) { - struct nand_chip *chip = mtd_to_nand(mtd); - if (cmd == NAND_CMD_NONE) return; diff --git a/drivers/mtd/nand/raw/plat_nand.c b/drivers/mtd/nand/raw/plat_nand.c index dd9e241b7584..bfb5d8e7b00b 100644 --- a/drivers/mtd/nand/raw/plat_nand.c +++ b/drivers/mtd/nand/raw/plat_nand.c @@ -23,13 +23,6 @@ struct plat_nand_data { void __iomem *io_base; }; -static void plat_nand_cmd_ctrl(struct mtd_info *mtd, int dat, unsigned int ctrl) -{ - struct platform_nand_data *pdata = dev_get_platdata(mtd->dev.parent); - - pdata->ctrl.cmd_ctrl(mtd_to_nand(mtd), dat, ctrl); -} - static int plat_nand_dev_ready(struct mtd_info *mtd) { struct platform_nand_data *pdata = dev_get_platdata(mtd->dev.parent); @@ -76,9 +69,7 @@ static int plat_nand_probe(struct platform_device *pdev) data->chip.IO_ADDR_R = data->io_base; data->chip.IO_ADDR_W = data->io_base; - - if (pdata->ctrl.cmd_ctrl) - data->chip.cmd_ctrl = plat_nand_cmd_ctrl; + data->chip.cmd_ctrl = pdata->ctrl.cmd_ctrl; if (pdata->ctrl.dev_ready) data->chip.dev_ready = plat_nand_dev_ready; diff --git a/drivers/mtd/nand/raw/r852.c b/drivers/mtd/nand/raw/r852.c index 312a971aa456..e90549e031a7 100644 --- a/drivers/mtd/nand/raw/r852.c +++ b/drivers/mtd/nand/raw/r852.c @@ -317,9 +317,9 @@ static uint8_t r852_read_byte(struct nand_chip *chip) /* * Control several chip lines & send commands */ -static void r852_cmdctl(struct mtd_info *mtd, int dat, unsigned int ctrl) +static void r852_cmdctl(struct nand_chip *chip, int dat, unsigned int ctrl) { - struct r852_device *dev = r852_get_dev(mtd); + struct r852_device *dev = r852_get_dev(nand_to_mtd(chip)); if (dev->card_unstable) return; diff --git a/drivers/mtd/nand/raw/s3c2410.c b/drivers/mtd/nand/raw/s3c2410.c index 353011e7fb79..98ba94936631 100644 --- a/drivers/mtd/nand/raw/s3c2410.c +++ b/drivers/mtd/nand/raw/s3c2410.c @@ -456,9 +456,10 @@ static void s3c2410_nand_select_chip(struct nand_chip *this, int chip) * Issue command and address cycles to the chip */ -static void s3c2410_nand_hwcontrol(struct mtd_info *mtd, int cmd, +static void s3c2410_nand_hwcontrol(struct nand_chip *chip, int cmd, unsigned int ctrl) { + struct mtd_info *mtd = nand_to_mtd(chip); struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd); if (cmd == NAND_CMD_NONE) @@ -472,9 +473,10 @@ static void s3c2410_nand_hwcontrol(struct mtd_info *mtd, int cmd, /* command and control functions */ -static void s3c2440_nand_hwcontrol(struct mtd_info *mtd, int cmd, +static void s3c2440_nand_hwcontrol(struct nand_chip *chip, int cmd, unsigned int ctrl) { + struct mtd_info *mtd = nand_to_mtd(chip); struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd); if (cmd == NAND_CMD_NONE) diff --git a/drivers/mtd/nand/raw/sharpsl.c b/drivers/mtd/nand/raw/sharpsl.c index 4d931ce71af5..7486a00b1ae5 100644 --- a/drivers/mtd/nand/raw/sharpsl.c +++ b/drivers/mtd/nand/raw/sharpsl.c @@ -59,11 +59,10 @@ static inline struct sharpsl_nand *mtd_to_sharpsl(struct mtd_info *mtd) * NAND_ALE: bit 2 -> bit 2 * */ -static void sharpsl_nand_hwcontrol(struct mtd_info *mtd, int cmd, +static void sharpsl_nand_hwcontrol(struct nand_chip *chip, int cmd, unsigned int ctrl) { - struct sharpsl_nand *sharpsl = mtd_to_sharpsl(mtd); - struct nand_chip *chip = mtd_to_nand(mtd); + struct sharpsl_nand *sharpsl = mtd_to_sharpsl(nand_to_mtd(chip)); if (ctrl & NAND_CTRL_CHANGE) { unsigned char bits = ctrl & 0x07; diff --git a/drivers/mtd/nand/raw/socrates_nand.c b/drivers/mtd/nand/raw/socrates_nand.c index deedc1cd4dee..c44b19fc1350 100644 --- a/drivers/mtd/nand/raw/socrates_nand.c +++ b/drivers/mtd/nand/raw/socrates_nand.c @@ -87,10 +87,9 @@ static uint8_t socrates_nand_read_byte(struct nand_chip *this) /* * Hardware specific access to control-lines */ -static void socrates_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, - unsigned int ctrl) +static void socrates_nand_cmd_ctrl(struct nand_chip *nand_chip, int cmd, + unsigned int ctrl) { - struct nand_chip *nand_chip = mtd_to_nand(mtd); struct socrates_nand_host *host = nand_get_controller_data(nand_chip); uint32_t val; diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c index 97a0666df615..1d85ff02afdb 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -547,10 +547,9 @@ static uint8_t sunxi_nfc_read_byte(struct nand_chip *nand) return ret; } -static void sunxi_nfc_cmd_ctrl(struct mtd_info *mtd, int dat, +static void sunxi_nfc_cmd_ctrl(struct nand_chip *nand, int dat, unsigned int ctrl) { - struct nand_chip *nand = mtd_to_nand(mtd); struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand); struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller); int ret; diff --git a/drivers/mtd/nand/raw/tango_nand.c b/drivers/mtd/nand/raw/tango_nand.c index 5e0bc2993e5d..c8fb03f71a3b 100644 --- a/drivers/mtd/nand/raw/tango_nand.c +++ b/drivers/mtd/nand/raw/tango_nand.c @@ -116,9 +116,9 @@ struct tango_chip { #define TIMING(t0, t1, t2, t3) ((t0) << 24 | (t1) << 16 | (t2) << 8 | (t3)) -static void tango_cmd_ctrl(struct mtd_info *mtd, int dat, unsigned int ctrl) +static void tango_cmd_ctrl(struct nand_chip *chip, int dat, unsigned int ctrl) { - struct tango_chip *tchip = to_tango_chip(mtd_to_nand(mtd)); + struct tango_chip *tchip = to_tango_chip(chip); if (ctrl & NAND_CLE) writeb_relaxed(dat, tchip->base + PBUS_CMD); diff --git a/drivers/mtd/nand/raw/tmio_nand.c b/drivers/mtd/nand/raw/tmio_nand.c index d627d855b254..1221353b11a7 100644 --- a/drivers/mtd/nand/raw/tmio_nand.c +++ b/drivers/mtd/nand/raw/tmio_nand.c @@ -126,11 +126,10 @@ static inline struct tmio_nand *mtd_to_tmio(struct mtd_info *mtd) /*--------------------------------------------------------------------------*/ -static void tmio_nand_hwcontrol(struct mtd_info *mtd, int cmd, - unsigned int ctrl) +static void tmio_nand_hwcontrol(struct nand_chip *chip, int cmd, + unsigned int ctrl) { - struct tmio_nand *tmio = mtd_to_tmio(mtd); - struct nand_chip *chip = mtd_to_nand(mtd); + struct tmio_nand *tmio = mtd_to_tmio(nand_to_mtd(chip)); if (ctrl & NAND_CTRL_CHANGE) { u8 mode; diff --git a/drivers/mtd/nand/raw/txx9ndfmc.c b/drivers/mtd/nand/raw/txx9ndfmc.c index b7ff8eca441b..f3bce6fb1fac 100644 --- a/drivers/mtd/nand/raw/txx9ndfmc.c +++ b/drivers/mtd/nand/raw/txx9ndfmc.c @@ -131,10 +131,9 @@ static void txx9ndfmc_read_buf(struct nand_chip *chip, uint8_t *buf, int len) *buf++ = __raw_readl(ndfdtr); } -static void txx9ndfmc_cmd_ctrl(struct mtd_info *mtd, int cmd, +static void txx9ndfmc_cmd_ctrl(struct nand_chip *chip, int cmd, unsigned int ctrl) { - struct nand_chip *chip = mtd_to_nand(mtd); struct txx9ndfmc_priv *txx9_priv = nand_get_controller_data(chip); struct platform_device *dev = txx9_priv->dev; struct txx9ndfmc_platform_data *plat = dev_get_platdata(&dev->dev); diff --git a/drivers/mtd/nand/raw/xway_nand.c b/drivers/mtd/nand/raw/xway_nand.c index a6388fa1dce7..3b38d31c59c6 100644 --- a/drivers/mtd/nand/raw/xway_nand.c +++ b/drivers/mtd/nand/raw/xway_nand.c @@ -105,8 +105,10 @@ static void xway_select_chip(struct nand_chip *chip, int select) } } -static void xway_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl) +static void xway_cmd_ctrl(struct nand_chip *chip, int cmd, unsigned int ctrl) { + struct mtd_info *mtd = nand_to_mtd(chip); + if (cmd == NAND_CMD_NONE) return; diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h index 0d8e2708e125..b53ccc7139c2 100644 --- a/include/linux/mtd/rawnand.h +++ b/include/linux/mtd/rawnand.h @@ -1290,7 +1290,7 @@ struct nand_chip { void (*select_chip)(struct nand_chip *chip, int cs); int (*block_bad)(struct nand_chip *chip, loff_t ofs); int (*block_markbad)(struct nand_chip *chip, loff_t ofs); - void (*cmd_ctrl)(struct mtd_info *mtd, int dat, unsigned int ctrl); + void (*cmd_ctrl)(struct nand_chip *chip, int dat, unsigned int ctrl); int (*dev_ready)(struct mtd_info *mtd); void (*cmdfunc)(struct mtd_info *mtd, unsigned command, int column, int page_addr); From 50a487e7719caa07e951dfcfd983b2c5517e2f76 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Thu, 6 Sep 2018 14:05:27 +0200 Subject: [PATCH 255/302] mtd: rawnand: Pass a nand_chip object to chip->dev_ready() Let's make the raw NAND API consistent by patching all helpers and hooks to take a nand_chip object instead of an mtd_info one or remove the mtd_info object when both are passed. Let's tackle the chip->dev_ready() hook. Signed-off-by: Boris Brezillon Signed-off-by: Miquel Raynal --- drivers/mtd/nand/raw/ams-delta.c | 2 +- drivers/mtd/nand/raw/atmel/nand-controller.c | 6 ++---- drivers/mtd/nand/raw/au1550nd.c | 6 +++--- drivers/mtd/nand/raw/bcm47xxnflash/ops_bcm4706.c | 3 +-- drivers/mtd/nand/raw/cafe_nand.c | 3 +-- drivers/mtd/nand/raw/cmx270_nand.c | 2 +- drivers/mtd/nand/raw/cs553x_nand.c | 3 +-- drivers/mtd/nand/raw/davinci_nand.c | 4 ++-- drivers/mtd/nand/raw/denali.c | 4 ++-- drivers/mtd/nand/raw/diskonchip.c | 5 ++--- drivers/mtd/nand/raw/fsl_upm.c | 6 +++--- drivers/mtd/nand/raw/gpio.c | 4 ++-- drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c | 3 +-- drivers/mtd/nand/raw/jz4740_nand.c | 4 ++-- drivers/mtd/nand/raw/jz4780_nand.c | 4 ++-- drivers/mtd/nand/raw/lpc32xx_mlc.c | 3 +-- drivers/mtd/nand/raw/lpc32xx_slc.c | 3 +-- drivers/mtd/nand/raw/mpc5121_nfc.c | 2 +- drivers/mtd/nand/raw/mtk_nand.c | 4 ++-- drivers/mtd/nand/raw/mxc_nand.c | 2 +- drivers/mtd/nand/raw/nand_base.c | 10 +++++----- drivers/mtd/nand/raw/nandsim.c | 2 +- drivers/mtd/nand/raw/ndfc.c | 3 +-- drivers/mtd/nand/raw/nuc900_nand.c | 6 +++--- drivers/mtd/nand/raw/omap2.c | 4 ++-- drivers/mtd/nand/raw/pasemi_nand.c | 2 +- drivers/mtd/nand/raw/plat_nand.c | 12 +----------- drivers/mtd/nand/raw/r852.c | 6 +++--- drivers/mtd/nand/raw/s3c2410.c | 9 ++++++--- drivers/mtd/nand/raw/sharpsl.c | 4 ++-- drivers/mtd/nand/raw/socrates_nand.c | 3 +-- drivers/mtd/nand/raw/sunxi_nand.c | 3 +-- drivers/mtd/nand/raw/tango_nand.c | 3 +-- drivers/mtd/nand/raw/tmio_nand.c | 8 ++++---- drivers/mtd/nand/raw/txx9ndfmc.c | 4 ++-- drivers/mtd/nand/raw/xway_nand.c | 2 +- include/linux/mtd/rawnand.h | 2 +- 37 files changed, 68 insertions(+), 88 deletions(-) diff --git a/drivers/mtd/nand/raw/ams-delta.c b/drivers/mtd/nand/raw/ams-delta.c index 8121d26194cf..48413203dbc2 100644 --- a/drivers/mtd/nand/raw/ams-delta.c +++ b/drivers/mtd/nand/raw/ams-delta.c @@ -130,7 +130,7 @@ static void ams_delta_hwcontrol(struct nand_chip *this, int cmd, ams_delta_write_byte(this, cmd); } -static int ams_delta_nand_ready(struct mtd_info *mtd) +static int ams_delta_nand_ready(struct nand_chip *this) { return gpio_get_value(AMS_DELTA_GPIO_PIN_NAND_RB); } diff --git a/drivers/mtd/nand/raw/atmel/nand-controller.c b/drivers/mtd/nand/raw/atmel/nand-controller.c index f088bff06723..2dcd8aa0ce0b 100644 --- a/drivers/mtd/nand/raw/atmel/nand-controller.c +++ b/drivers/mtd/nand/raw/atmel/nand-controller.c @@ -475,9 +475,8 @@ static void atmel_nand_write_buf(struct nand_chip *chip, const u8 *buf, int len) iowrite8_rep(nand->activecs->io.virt, buf, len); } -static int atmel_nand_dev_ready(struct mtd_info *mtd) +static int atmel_nand_dev_ready(struct nand_chip *chip) { - struct nand_chip *chip = mtd_to_nand(mtd); struct atmel_nand *nand = to_atmel_nand(chip); return gpiod_get_value(nand->activecs->rb.gpio); @@ -499,9 +498,8 @@ static void atmel_nand_select_chip(struct nand_chip *chip, int cs) chip->dev_ready = atmel_nand_dev_ready; } -static int atmel_hsmc_nand_dev_ready(struct mtd_info *mtd) +static int atmel_hsmc_nand_dev_ready(struct nand_chip *chip) { - struct nand_chip *chip = mtd_to_nand(mtd); struct atmel_nand *nand = to_atmel_nand(chip); struct atmel_hsmc_nand_controller *nc; u32 status; diff --git a/drivers/mtd/nand/raw/au1550nd.c b/drivers/mtd/nand/raw/au1550nd.c index 1bae3b2779aa..1f0fba8d87c6 100644 --- a/drivers/mtd/nand/raw/au1550nd.c +++ b/drivers/mtd/nand/raw/au1550nd.c @@ -213,7 +213,7 @@ static void au1550_hwcontrol(struct mtd_info *mtd, int cmd) wmb(); /* Drain the writebuffer */ } -int au1550_device_ready(struct mtd_info *mtd) +int au1550_device_ready(struct nand_chip *this) { return (alchemy_rdsmem(AU1000_MEM_STSTAT) & 0x1) ? 1 : 0; } @@ -341,7 +341,7 @@ static void au1550_command(struct mtd_info *mtd, unsigned command, int column, i /* Apply a short delay always to ensure that we do wait tWB. */ ndelay(100); /* Wait for a chip to become ready... */ - for (i = this->chip_delay; !this->dev_ready(mtd) && i > 0; --i) + for (i = this->chip_delay; !this->dev_ready(this) && i > 0; --i) udelay(1); /* Release -CE and re-enable interrupts. */ @@ -352,7 +352,7 @@ static void au1550_command(struct mtd_info *mtd, unsigned command, int column, i /* Apply this short delay always to ensure that we do wait tWB. */ ndelay(100); - while(!this->dev_ready(mtd)); + while(!this->dev_ready(this)); } static int find_nand_cs(unsigned long nand_base) diff --git a/drivers/mtd/nand/raw/bcm47xxnflash/ops_bcm4706.c b/drivers/mtd/nand/raw/bcm47xxnflash/ops_bcm4706.c index d326f9d3648b..f6f694b3cd8e 100644 --- a/drivers/mtd/nand/raw/bcm47xxnflash/ops_bcm4706.c +++ b/drivers/mtd/nand/raw/bcm47xxnflash/ops_bcm4706.c @@ -196,9 +196,8 @@ static void bcm47xxnflash_ops_bcm4706_select_chip(struct nand_chip *chip, return; } -static int bcm47xxnflash_ops_bcm4706_dev_ready(struct mtd_info *mtd) +static int bcm47xxnflash_ops_bcm4706_dev_ready(struct nand_chip *nand_chip) { - struct nand_chip *nand_chip = mtd_to_nand(mtd); struct bcm47xxnflash *b47n = nand_get_controller_data(nand_chip); return !!(bcma_cc_read32(b47n->cc, BCMA_CC_NFLASH_CTL) & NCTL_READY); diff --git a/drivers/mtd/nand/raw/cafe_nand.c b/drivers/mtd/nand/raw/cafe_nand.c index af6870269f9c..60a2eecc2b2a 100644 --- a/drivers/mtd/nand/raw/cafe_nand.c +++ b/drivers/mtd/nand/raw/cafe_nand.c @@ -100,9 +100,8 @@ static const char *part_probes[] = { "cmdlinepart", "RedBoot", NULL }; #define cafe_readl(cafe, addr) readl((cafe)->mmio + CAFE_##addr) #define cafe_writel(cafe, datum, addr) writel(datum, (cafe)->mmio + CAFE_##addr) -static int cafe_device_ready(struct mtd_info *mtd) +static int cafe_device_ready(struct nand_chip *chip) { - struct nand_chip *chip = mtd_to_nand(mtd); struct cafe_priv *cafe = nand_get_controller_data(chip); int result = !!(cafe_readl(cafe, NAND_STATUS) & 0x40000000); uint32_t irqs = cafe_readl(cafe, NAND_IRQ); diff --git a/drivers/mtd/nand/raw/cmx270_nand.c b/drivers/mtd/nand/raw/cmx270_nand.c index a0f0ad2da6f1..e8458036419b 100644 --- a/drivers/mtd/nand/raw/cmx270_nand.c +++ b/drivers/mtd/nand/raw/cmx270_nand.c @@ -119,7 +119,7 @@ static void cmx270_hwcontrol(struct nand_chip *this, int dat, /* * read device ready pin */ -static int cmx270_device_ready(struct mtd_info *mtd) +static int cmx270_device_ready(struct nand_chip *this) { dsb(); diff --git a/drivers/mtd/nand/raw/cs553x_nand.c b/drivers/mtd/nand/raw/cs553x_nand.c index b7432f086f9b..c1628c03282a 100644 --- a/drivers/mtd/nand/raw/cs553x_nand.c +++ b/drivers/mtd/nand/raw/cs553x_nand.c @@ -141,9 +141,8 @@ static void cs553x_hwcontrol(struct nand_chip *this, int cmd, cs553x_write_byte(this, cmd); } -static int cs553x_device_ready(struct mtd_info *mtd) +static int cs553x_device_ready(struct nand_chip *this) { - struct nand_chip *this = mtd_to_nand(mtd); void __iomem *mmio_base = this->IO_ADDR_R; unsigned char foo = readb(mmio_base + MM_NAND_STS); diff --git a/drivers/mtd/nand/raw/davinci_nand.c b/drivers/mtd/nand/raw/davinci_nand.c index c2a3ad10610c..4b261c73b240 100644 --- a/drivers/mtd/nand/raw/davinci_nand.c +++ b/drivers/mtd/nand/raw/davinci_nand.c @@ -460,9 +460,9 @@ static void nand_davinci_write_buf(struct nand_chip *chip, const uint8_t *buf, * Check hardware register for wait status. Returns 1 if device is ready, * 0 if it is still busy. */ -static int nand_davinci_dev_ready(struct mtd_info *mtd) +static int nand_davinci_dev_ready(struct nand_chip *chip) { - struct davinci_nand_info *info = to_davinci_nand(mtd); + struct davinci_nand_info *info = to_davinci_nand(nand_to_mtd(chip)); return davinci_nand_readl(info, NANDFSR_OFFSET) & BIT(0); } diff --git a/drivers/mtd/nand/raw/denali.c b/drivers/mtd/nand/raw/denali.c index 6529780e31a4..7258dd13b3f9 100644 --- a/drivers/mtd/nand/raw/denali.c +++ b/drivers/mtd/nand/raw/denali.c @@ -296,9 +296,9 @@ static void denali_cmd_ctrl(struct nand_chip *chip, int dat, unsigned int ctrl) denali->host_write(denali, DENALI_BANK(denali) | type, dat); } -static int denali_dev_ready(struct mtd_info *mtd) +static int denali_dev_ready(struct nand_chip *chip) { - struct denali_nand_info *denali = mtd_to_denali(mtd); + struct denali_nand_info *denali = mtd_to_denali(nand_to_mtd(chip)); return !!(denali_check_irq(denali) & INTR__INT_ACT); } diff --git a/drivers/mtd/nand/raw/diskonchip.c b/drivers/mtd/nand/raw/diskonchip.c index 16498b277764..e40a4e120c7b 100644 --- a/drivers/mtd/nand/raw/diskonchip.c +++ b/drivers/mtd/nand/raw/diskonchip.c @@ -739,12 +739,11 @@ static void doc2001plus_command(struct mtd_info *mtd, unsigned command, int colu * any case on any machine. */ ndelay(100); /* wait until command is processed */ - while (!this->dev_ready(mtd)) ; + while (!this->dev_ready(this)) ; } -static int doc200x_dev_ready(struct mtd_info *mtd) +static int doc200x_dev_ready(struct nand_chip *this) { - struct nand_chip *this = mtd_to_nand(mtd); struct doc_priv *doc = nand_get_controller_data(this); void __iomem *docptr = doc->virtadr; diff --git a/drivers/mtd/nand/raw/fsl_upm.c b/drivers/mtd/nand/raw/fsl_upm.c index 7a2488c6c212..48c5215f9a0e 100644 --- a/drivers/mtd/nand/raw/fsl_upm.c +++ b/drivers/mtd/nand/raw/fsl_upm.c @@ -52,9 +52,9 @@ static inline struct fsl_upm_nand *to_fsl_upm_nand(struct mtd_info *mtdinfo) chip); } -static int fun_chip_ready(struct mtd_info *mtd) +static int fun_chip_ready(struct nand_chip *chip) { - struct fsl_upm_nand *fun = to_fsl_upm_nand(mtd); + struct fsl_upm_nand *fun = to_fsl_upm_nand(nand_to_mtd(chip)); if (gpio_get_value(fun->rnb_gpio[fun->mchip_number])) return 1; @@ -69,7 +69,7 @@ static void fun_wait_rnb(struct fsl_upm_nand *fun) struct mtd_info *mtd = nand_to_mtd(&fun->chip); int cnt = 1000000; - while (--cnt && !fun_chip_ready(mtd)) + while (--cnt && !fun_chip_ready(&fun->chip)) cpu_relax(); if (!cnt) dev_err(fun->dev, "tired waiting for RNB\n"); diff --git a/drivers/mtd/nand/raw/gpio.c b/drivers/mtd/nand/raw/gpio.c index 722a930ac836..273437c1ae6c 100644 --- a/drivers/mtd/nand/raw/gpio.c +++ b/drivers/mtd/nand/raw/gpio.c @@ -94,9 +94,9 @@ static void gpio_nand_cmd_ctrl(struct nand_chip *chip, int cmd, gpio_nand_dosync(gpiomtd); } -static int gpio_nand_devready(struct mtd_info *mtd) +static int gpio_nand_devready(struct nand_chip *chip) { - struct gpiomtd *gpiomtd = gpio_nand_getpriv(mtd); + struct gpiomtd *gpiomtd = gpio_nand_getpriv(nand_to_mtd(chip)); return gpiod_get_value(gpiomtd->rdy); } diff --git a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c index 460f2f77a424..1ed594a155ed 100644 --- a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c +++ b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c @@ -816,9 +816,8 @@ static void gpmi_cmd_ctrl(struct nand_chip *chip, int data, unsigned int ctrl) this->command_length = 0; } -static int gpmi_dev_ready(struct mtd_info *mtd) +static int gpmi_dev_ready(struct nand_chip *chip) { - struct nand_chip *chip = mtd_to_nand(mtd); struct gpmi_nand_data *this = nand_get_controller_data(chip); return gpmi_is_ready(this, this->current_chip); diff --git a/drivers/mtd/nand/raw/jz4740_nand.c b/drivers/mtd/nand/raw/jz4740_nand.c index 7999e691e636..946a71cf816d 100644 --- a/drivers/mtd/nand/raw/jz4740_nand.c +++ b/drivers/mtd/nand/raw/jz4740_nand.c @@ -127,9 +127,9 @@ static void jz_nand_cmd_ctrl(struct nand_chip *chip, int dat, writeb(dat, chip->IO_ADDR_W); } -static int jz_nand_dev_ready(struct mtd_info *mtd) +static int jz_nand_dev_ready(struct nand_chip *chip) { - struct jz_nand *nand = mtd_to_jz_nand(mtd); + struct jz_nand *nand = mtd_to_jz_nand(nand_to_mtd(chip)); return gpiod_get_value_cansleep(nand->busy_gpio); } diff --git a/drivers/mtd/nand/raw/jz4780_nand.c b/drivers/mtd/nand/raw/jz4780_nand.c index 1d2cba546258..d54b2774f7f9 100644 --- a/drivers/mtd/nand/raw/jz4780_nand.c +++ b/drivers/mtd/nand/raw/jz4780_nand.c @@ -109,9 +109,9 @@ static void jz4780_nand_cmd_ctrl(struct nand_chip *chip, int cmd, writeb(cmd, cs->base + OFFSET_CMD); } -static int jz4780_nand_dev_ready(struct mtd_info *mtd) +static int jz4780_nand_dev_ready(struct nand_chip *chip) { - struct jz4780_nand_chip *nand = to_jz4780_nand_chip(mtd); + struct jz4780_nand_chip *nand = to_jz4780_nand_chip(nand_to_mtd(chip)); return !gpiod_get_value_cansleep(nand->busy_gpio); } diff --git a/drivers/mtd/nand/raw/lpc32xx_mlc.c b/drivers/mtd/nand/raw/lpc32xx_mlc.c index 0e989d944ddb..726cd8868ac3 100644 --- a/drivers/mtd/nand/raw/lpc32xx_mlc.c +++ b/drivers/mtd/nand/raw/lpc32xx_mlc.c @@ -302,9 +302,8 @@ static void lpc32xx_nand_cmd_ctrl(struct nand_chip *nand_chip, int cmd, /* * Read Device Ready (NAND device _and_ controller ready) */ -static int lpc32xx_nand_device_ready(struct mtd_info *mtd) +static int lpc32xx_nand_device_ready(struct nand_chip *nand_chip) { - struct nand_chip *nand_chip = mtd_to_nand(mtd); struct lpc32xx_nand_host *host = nand_get_controller_data(nand_chip); if ((readb(MLC_ISR(host->io_base)) & diff --git a/drivers/mtd/nand/raw/lpc32xx_slc.c b/drivers/mtd/nand/raw/lpc32xx_slc.c index e42584de875c..26d27a81f814 100644 --- a/drivers/mtd/nand/raw/lpc32xx_slc.c +++ b/drivers/mtd/nand/raw/lpc32xx_slc.c @@ -303,9 +303,8 @@ static void lpc32xx_nand_cmd_ctrl(struct nand_chip *chip, int cmd, /* * Read the Device Ready pin */ -static int lpc32xx_nand_device_ready(struct mtd_info *mtd) +static int lpc32xx_nand_device_ready(struct nand_chip *chip) { - struct nand_chip *chip = mtd_to_nand(mtd); struct lpc32xx_nand_host *host = nand_get_controller_data(chip); int rdy = 0; diff --git a/drivers/mtd/nand/raw/mpc5121_nfc.c b/drivers/mtd/nand/raw/mpc5121_nfc.c index c2002c4d467b..ba7af061c0eb 100644 --- a/drivers/mtd/nand/raw/mpc5121_nfc.c +++ b/drivers/mtd/nand/raw/mpc5121_nfc.c @@ -320,7 +320,7 @@ static void ads5121_select_chip(struct nand_chip *nand, int chip) } /* Read NAND Ready/Busy signal */ -static int mpc5121_nfc_dev_ready(struct mtd_info *mtd) +static int mpc5121_nfc_dev_ready(struct nand_chip *nand) { /* * NFC handles ready/busy signal internally. Therefore, this function diff --git a/drivers/mtd/nand/raw/mtk_nand.c b/drivers/mtd/nand/raw/mtk_nand.c index 6baa41483931..cf8c42fb8feb 100644 --- a/drivers/mtd/nand/raw/mtk_nand.c +++ b/drivers/mtd/nand/raw/mtk_nand.c @@ -402,9 +402,9 @@ static void mtk_nfc_select_chip(struct nand_chip *nand, int chip) nfi_writel(nfc, mtk_nand->sels[chip], NFI_CSEL); } -static int mtk_nfc_dev_ready(struct mtd_info *mtd) +static int mtk_nfc_dev_ready(struct nand_chip *nand) { - struct mtk_nfc *nfc = nand_get_controller_data(mtd_to_nand(mtd)); + struct mtk_nfc *nfc = nand_get_controller_data(nand); if (nfi_readl(nfc, NFI_STA) & STA_BUSY) return 0; diff --git a/drivers/mtd/nand/raw/mxc_nand.c b/drivers/mtd/nand/raw/mxc_nand.c index d070ce461b69..82e5b1864399 100644 --- a/drivers/mtd/nand/raw/mxc_nand.c +++ b/drivers/mtd/nand/raw/mxc_nand.c @@ -701,7 +701,7 @@ static void mxc_nand_enable_hwecc_v3(struct nand_chip *chip, bool enable) } /* This functions is used by upper layer to checks if device is ready */ -static int mxc_nand_dev_ready(struct mtd_info *mtd) +static int mxc_nand_dev_ready(struct nand_chip *chip) { /* * NFC handles R/B internally. Therefore, this function diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c index f0d70164a2f1..66dae8b69fe8 100644 --- a/drivers/mtd/nand/raw/nand_base.c +++ b/drivers/mtd/nand/raw/nand_base.c @@ -603,7 +603,7 @@ static void panic_nand_wait_ready(struct mtd_info *mtd, unsigned long timeo) /* Wait for the device to get ready */ for (i = 0; i < timeo; i++) { - if (chip->dev_ready(mtd)) + if (chip->dev_ready(chip)) break; touch_softlockup_watchdog(); mdelay(1); @@ -627,12 +627,12 @@ void nand_wait_ready(struct nand_chip *chip) /* Wait until command is processed or timeout occurs */ timeo = jiffies + msecs_to_jiffies(timeo); do { - if (chip->dev_ready(mtd)) + if (chip->dev_ready(chip)) return; cond_resched(); } while (time_before(jiffies, timeo)); - if (!chip->dev_ready(mtd)) + if (!chip->dev_ready(chip)) pr_warn_ratelimited("timeout while waiting for chip to become ready\n"); } EXPORT_SYMBOL_GPL(nand_wait_ready); @@ -1068,7 +1068,7 @@ static void panic_nand_wait(struct mtd_info *mtd, struct nand_chip *chip, int i; for (i = 0; i < timeo; i++) { if (chip->dev_ready) { - if (chip->dev_ready(mtd)) + if (chip->dev_ready(chip)) break; } else { int ret; @@ -1116,7 +1116,7 @@ static int nand_wait(struct mtd_info *mtd, struct nand_chip *chip) timeo = jiffies + msecs_to_jiffies(timeo); do { if (chip->dev_ready) { - if (chip->dev_ready(mtd)) + if (chip->dev_ready(chip)) break; } else { ret = nand_read_data_op(chip, &status, diff --git a/drivers/mtd/nand/raw/nandsim.c b/drivers/mtd/nand/raw/nandsim.c index a6b626c935a8..f750783d5d6a 100644 --- a/drivers/mtd/nand/raw/nandsim.c +++ b/drivers/mtd/nand/raw/nandsim.c @@ -2099,7 +2099,7 @@ static void ns_hwcontrol(struct nand_chip *chip, int cmd, unsigned int bitmask) ns_nand_write_byte(chip, cmd); } -static int ns_device_ready(struct mtd_info *mtd) +static int ns_device_ready(struct nand_chip *chip) { NS_DBG("device_ready\n"); return 1; diff --git a/drivers/mtd/nand/raw/ndfc.c b/drivers/mtd/nand/raw/ndfc.c index 05ac7bf94874..b96070a3afff 100644 --- a/drivers/mtd/nand/raw/ndfc.c +++ b/drivers/mtd/nand/raw/ndfc.c @@ -71,9 +71,8 @@ static void ndfc_hwcontrol(struct nand_chip *chip, int cmd, unsigned int ctrl) writel(cmd & 0xFF, ndfc->ndfcbase + NDFC_ALE); } -static int ndfc_ready(struct mtd_info *mtd) +static int ndfc_ready(struct nand_chip *chip) { - struct nand_chip *chip = mtd_to_nand(mtd); struct ndfc_controller *ndfc = nand_get_controller_data(chip); return in_be32(ndfc->ndfcbase + NDFC_STAT) & NDFC_STAT_IS_READY; diff --git a/drivers/mtd/nand/raw/nuc900_nand.c b/drivers/mtd/nand/raw/nuc900_nand.c index 357b3cf03195..4029b802243d 100644 --- a/drivers/mtd/nand/raw/nuc900_nand.c +++ b/drivers/mtd/nand/raw/nuc900_nand.c @@ -120,9 +120,9 @@ static int nuc900_check_rb(struct nuc900_nand *nand) return val; } -static int nuc900_nand_devready(struct mtd_info *mtd) +static int nuc900_nand_devready(struct nand_chip *chip) { - struct nuc900_nand *nand = mtd_to_nuc900(mtd); + struct nuc900_nand *nand = mtd_to_nuc900(nand_to_mtd(chip)); int ready; ready = (nuc900_check_rb(nand)) ? 1 : 0; @@ -205,7 +205,7 @@ static void nuc900_nand_command_lp(struct mtd_info *mtd, unsigned int command, * any case on any machine. */ ndelay(100); - while (!chip->dev_ready(mtd)) + while (!chip->dev_ready(chip)) ; } diff --git a/drivers/mtd/nand/raw/omap2.c b/drivers/mtd/nand/raw/omap2.c index 4bae782cd877..eef9cbadd3c4 100644 --- a/drivers/mtd/nand/raw/omap2.c +++ b/drivers/mtd/nand/raw/omap2.c @@ -1021,9 +1021,9 @@ static int omap_wait(struct mtd_info *mtd, struct nand_chip *chip) * * Returns true if ready and false if busy. */ -static int omap_dev_ready(struct mtd_info *mtd) +static int omap_dev_ready(struct nand_chip *chip) { - struct omap_nand_info *info = mtd_to_omap(mtd); + struct omap_nand_info *info = mtd_to_omap(nand_to_mtd(chip)); return gpiod_get_value(info->ready_gpiod); } diff --git a/drivers/mtd/nand/raw/pasemi_nand.c b/drivers/mtd/nand/raw/pasemi_nand.c index 661ba57f2934..a1e3bf7a276b 100644 --- a/drivers/mtd/nand/raw/pasemi_nand.c +++ b/drivers/mtd/nand/raw/pasemi_nand.c @@ -80,7 +80,7 @@ static void pasemi_hwcontrol(struct nand_chip *chip, int cmd, inl(lpcctl); } -int pasemi_device_ready(struct mtd_info *mtd) +int pasemi_device_ready(struct nand_chip *chip) { return !!(inl(lpcctl) & LBICTRL_LPCCTL_NR); } diff --git a/drivers/mtd/nand/raw/plat_nand.c b/drivers/mtd/nand/raw/plat_nand.c index bfb5d8e7b00b..d65e4084dea4 100644 --- a/drivers/mtd/nand/raw/plat_nand.c +++ b/drivers/mtd/nand/raw/plat_nand.c @@ -23,13 +23,6 @@ struct plat_nand_data { void __iomem *io_base; }; -static int plat_nand_dev_ready(struct mtd_info *mtd) -{ - struct platform_nand_data *pdata = dev_get_platdata(mtd->dev.parent); - - return pdata->ctrl.dev_ready(mtd_to_nand(mtd)); -} - /* * Probe for the NAND device. */ @@ -70,10 +63,7 @@ static int plat_nand_probe(struct platform_device *pdev) data->chip.IO_ADDR_R = data->io_base; data->chip.IO_ADDR_W = data->io_base; data->chip.cmd_ctrl = pdata->ctrl.cmd_ctrl; - - if (pdata->ctrl.dev_ready) - data->chip.dev_ready = plat_nand_dev_ready; - + data->chip.dev_ready = pdata->ctrl.dev_ready; data->chip.select_chip = pdata->ctrl.select_chip; data->chip.write_buf = pdata->ctrl.write_buf; data->chip.read_buf = pdata->ctrl.read_buf; diff --git a/drivers/mtd/nand/raw/r852.c b/drivers/mtd/nand/raw/r852.c index e90549e031a7..4331ff856fa5 100644 --- a/drivers/mtd/nand/raw/r852.c +++ b/drivers/mtd/nand/raw/r852.c @@ -373,7 +373,7 @@ static int r852_wait(struct mtd_info *mtd, struct nand_chip *chip) msecs_to_jiffies(400) : msecs_to_jiffies(20)); while (time_before(jiffies, timeout)) - if (chip->dev_ready(mtd)) + if (chip->dev_ready(chip)) break; nand_status_op(chip, &status); @@ -390,9 +390,9 @@ static int r852_wait(struct mtd_info *mtd, struct nand_chip *chip) * Check if card is ready */ -static int r852_ready(struct mtd_info *mtd) +static int r852_ready(struct nand_chip *chip) { - struct r852_device *dev = r852_get_dev(mtd); + struct r852_device *dev = r852_get_dev(nand_to_mtd(chip)); return !(r852_read_reg(dev, R852_CARD_STA) & R852_CARD_STA_BUSY); } diff --git a/drivers/mtd/nand/raw/s3c2410.c b/drivers/mtd/nand/raw/s3c2410.c index 98ba94936631..1d549f5e53f5 100644 --- a/drivers/mtd/nand/raw/s3c2410.c +++ b/drivers/mtd/nand/raw/s3c2410.c @@ -493,20 +493,23 @@ static void s3c2440_nand_hwcontrol(struct nand_chip *chip, int cmd, * returns 0 if the nand is busy, 1 if it is ready */ -static int s3c2410_nand_devready(struct mtd_info *mtd) +static int s3c2410_nand_devready(struct nand_chip *chip) { + struct mtd_info *mtd = nand_to_mtd(chip); struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd); return readb(info->regs + S3C2410_NFSTAT) & S3C2410_NFSTAT_BUSY; } -static int s3c2440_nand_devready(struct mtd_info *mtd) +static int s3c2440_nand_devready(struct nand_chip *chip) { + struct mtd_info *mtd = nand_to_mtd(chip); struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd); return readb(info->regs + S3C2440_NFSTAT) & S3C2440_NFSTAT_READY; } -static int s3c2412_nand_devready(struct mtd_info *mtd) +static int s3c2412_nand_devready(struct nand_chip *chip) { + struct mtd_info *mtd = nand_to_mtd(chip); struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd); return readb(info->regs + S3C2412_NFSTAT) & S3C2412_NFSTAT_READY; } diff --git a/drivers/mtd/nand/raw/sharpsl.c b/drivers/mtd/nand/raw/sharpsl.c index 7486a00b1ae5..31abbe33798e 100644 --- a/drivers/mtd/nand/raw/sharpsl.c +++ b/drivers/mtd/nand/raw/sharpsl.c @@ -78,9 +78,9 @@ static void sharpsl_nand_hwcontrol(struct nand_chip *chip, int cmd, writeb(cmd, chip->IO_ADDR_W); } -static int sharpsl_nand_dev_ready(struct mtd_info *mtd) +static int sharpsl_nand_dev_ready(struct nand_chip *chip) { - struct sharpsl_nand *sharpsl = mtd_to_sharpsl(mtd); + struct sharpsl_nand *sharpsl = mtd_to_sharpsl(nand_to_mtd(chip)); return !((readb(sharpsl->io + FLASHCTL) & FLRYBY) == 0); } diff --git a/drivers/mtd/nand/raw/socrates_nand.c b/drivers/mtd/nand/raw/socrates_nand.c index c44b19fc1350..64ea9a014054 100644 --- a/drivers/mtd/nand/raw/socrates_nand.c +++ b/drivers/mtd/nand/raw/socrates_nand.c @@ -112,9 +112,8 @@ static void socrates_nand_cmd_ctrl(struct nand_chip *nand_chip, int cmd, /* * Read the Device Ready pin. */ -static int socrates_nand_device_ready(struct mtd_info *mtd) +static int socrates_nand_device_ready(struct nand_chip *nand_chip) { - struct nand_chip *nand_chip = mtd_to_nand(mtd); struct socrates_nand_host *host = nand_get_controller_data(nand_chip); if (in_be32(host->io_base) & FPGA_NAND_BUSY) diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c index 1d85ff02afdb..fe30fb589ffb 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -400,9 +400,8 @@ static void sunxi_nfc_dma_op_cleanup(struct mtd_info *mtd, nfc->regs + NFC_REG_CTL); } -static int sunxi_nfc_dev_ready(struct mtd_info *mtd) +static int sunxi_nfc_dev_ready(struct nand_chip *nand) { - struct nand_chip *nand = mtd_to_nand(mtd); struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand); struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller); u32 mask; diff --git a/drivers/mtd/nand/raw/tango_nand.c b/drivers/mtd/nand/raw/tango_nand.c index c8fb03f71a3b..cc719bc49b68 100644 --- a/drivers/mtd/nand/raw/tango_nand.c +++ b/drivers/mtd/nand/raw/tango_nand.c @@ -127,9 +127,8 @@ static void tango_cmd_ctrl(struct nand_chip *chip, int dat, unsigned int ctrl) writeb_relaxed(dat, tchip->base + PBUS_ADDR); } -static int tango_dev_ready(struct mtd_info *mtd) +static int tango_dev_ready(struct nand_chip *chip) { - struct nand_chip *chip = mtd_to_nand(mtd); struct tango_nfc *nfc = to_tango_nfc(chip->controller); return readl_relaxed(nfc->pbus_base + PBUS_CS_CTRL) & PBUS_IORDY; diff --git a/drivers/mtd/nand/raw/tmio_nand.c b/drivers/mtd/nand/raw/tmio_nand.c index 1221353b11a7..7096fa3d50ab 100644 --- a/drivers/mtd/nand/raw/tmio_nand.c +++ b/drivers/mtd/nand/raw/tmio_nand.c @@ -158,9 +158,9 @@ static void tmio_nand_hwcontrol(struct nand_chip *chip, int cmd, tmio_iowrite8(cmd, chip->IO_ADDR_W); } -static int tmio_nand_dev_ready(struct mtd_info *mtd) +static int tmio_nand_dev_ready(struct nand_chip *chip) { - struct tmio_nand *tmio = mtd_to_tmio(mtd); + struct tmio_nand *tmio = mtd_to_tmio(nand_to_mtd(chip)); return !(tmio_ioread8(tmio->fcr + FCR_STATUS) & FCR_STATUS_BUSY); } @@ -198,10 +198,10 @@ tmio_nand_wait(struct mtd_info *mtd, struct nand_chip *nand_chip) tmio_iowrite8(0x81, tmio->fcr + FCR_IMR); timeout = wait_event_timeout(nand_chip->controller->wq, - tmio_nand_dev_ready(mtd), + tmio_nand_dev_ready(nand_chip), msecs_to_jiffies(nand_chip->state == FL_ERASING ? 400 : 20)); - if (unlikely(!tmio_nand_dev_ready(mtd))) { + if (unlikely(!tmio_nand_dev_ready(nand_chip))) { tmio_iowrite8(0x00, tmio->fcr + FCR_IMR); dev_warn(&tmio->dev->dev, "still busy with %s after %d ms\n", nand_chip->state == FL_ERASING ? "erase" : "program", diff --git a/drivers/mtd/nand/raw/txx9ndfmc.c b/drivers/mtd/nand/raw/txx9ndfmc.c index f3bce6fb1fac..c84b2ad84cf7 100644 --- a/drivers/mtd/nand/raw/txx9ndfmc.c +++ b/drivers/mtd/nand/raw/txx9ndfmc.c @@ -162,9 +162,9 @@ static void txx9ndfmc_cmd_ctrl(struct nand_chip *chip, int cmd, mmiowb(); } -static int txx9ndfmc_dev_ready(struct mtd_info *mtd) +static int txx9ndfmc_dev_ready(struct nand_chip *chip) { - struct platform_device *dev = mtd_to_platdev(mtd); + struct platform_device *dev = mtd_to_platdev(nand_to_mtd(chip)); return !(txx9ndfmc_read(dev, TXX9_NDFSR) & TXX9_NDFSR_BUSY); } diff --git a/drivers/mtd/nand/raw/xway_nand.c b/drivers/mtd/nand/raw/xway_nand.c index 3b38d31c59c6..3d91e98df5a8 100644 --- a/drivers/mtd/nand/raw/xway_nand.c +++ b/drivers/mtd/nand/raw/xway_nand.c @@ -121,7 +121,7 @@ static void xway_cmd_ctrl(struct nand_chip *chip, int cmd, unsigned int ctrl) ; } -static int xway_dev_ready(struct mtd_info *mtd) +static int xway_dev_ready(struct nand_chip *chip) { return ltq_ebu_r32(EBU_NAND_WAIT) & NAND_WAIT_RD; } diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h index b53ccc7139c2..404ac7d4b279 100644 --- a/include/linux/mtd/rawnand.h +++ b/include/linux/mtd/rawnand.h @@ -1291,7 +1291,7 @@ struct nand_chip { int (*block_bad)(struct nand_chip *chip, loff_t ofs); int (*block_markbad)(struct nand_chip *chip, loff_t ofs); void (*cmd_ctrl)(struct nand_chip *chip, int dat, unsigned int ctrl); - int (*dev_ready)(struct mtd_info *mtd); + int (*dev_ready)(struct nand_chip *chip); void (*cmdfunc)(struct mtd_info *mtd, unsigned command, int column, int page_addr); int(*waitfunc)(struct mtd_info *mtd, struct nand_chip *this); From 5295cf2e047cf60ac1e14d4789cdf698af45cf2f Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Thu, 6 Sep 2018 14:05:28 +0200 Subject: [PATCH 256/302] mtd: rawnand: Pass a nand_chip object to chip->cmdfunc() Let's make the raw NAND API consistent by patching all helpers and hooks to take a nand_chip object instead of an mtd_info one or remove the mtd_info object when both are passed. Let's tackle the chip->cmdfunc() hook. Signed-off-by: Boris Brezillon Signed-off-by: Miquel Raynal --- drivers/mtd/nand/raw/au1550nd.c | 7 +-- .../mtd/nand/raw/bcm47xxnflash/ops_bcm4706.c | 4 +- drivers/mtd/nand/raw/brcmnand/brcmnand.c | 4 +- drivers/mtd/nand/raw/cafe_nand.c | 4 +- drivers/mtd/nand/raw/diskonchip.c | 5 +- drivers/mtd/nand/raw/docg4.c | 4 +- drivers/mtd/nand/raw/fsl_elbc_nand.c | 4 +- drivers/mtd/nand/raw/fsl_ifc_nand.c | 6 +-- drivers/mtd/nand/raw/hisi504_nand.c | 6 +-- drivers/mtd/nand/raw/mpc5121_nfc.c | 8 ++-- drivers/mtd/nand/raw/mxc_nand.c | 6 +-- drivers/mtd/nand/raw/nand_base.c | 46 +++++++++---------- drivers/mtd/nand/raw/nand_hynix.c | 7 +-- drivers/mtd/nand/raw/nuc900_nand.c | 5 +- drivers/mtd/nand/raw/qcom_nandc.c | 3 +- drivers/mtd/nand/raw/sh_flctl.c | 3 +- drivers/staging/mt29f_spinand/mt29f_spinand.c | 4 +- include/linux/mtd/rawnand.h | 2 +- 18 files changed, 64 insertions(+), 64 deletions(-) diff --git a/drivers/mtd/nand/raw/au1550nd.c b/drivers/mtd/nand/raw/au1550nd.c index 1f0fba8d87c6..d0ec8606e769 100644 --- a/drivers/mtd/nand/raw/au1550nd.c +++ b/drivers/mtd/nand/raw/au1550nd.c @@ -236,14 +236,15 @@ static void au1550_select_chip(struct nand_chip *this, int chip) /** * au1550_command - Send command to NAND device - * @mtd: MTD device structure + * @this: NAND chip object * @command: the command to be sent * @column: the column address for this command, -1 if none * @page_addr: the page address for this command, -1 if none */ -static void au1550_command(struct mtd_info *mtd, unsigned command, int column, int page_addr) +static void au1550_command(struct nand_chip *this, unsigned command, + int column, int page_addr) { - struct nand_chip *this = mtd_to_nand(mtd); + struct mtd_info *mtd = nand_to_mtd(this); struct au1550nd_ctx *ctx = container_of(this, struct au1550nd_ctx, chip); int ce_override = 0, i; diff --git a/drivers/mtd/nand/raw/bcm47xxnflash/ops_bcm4706.c b/drivers/mtd/nand/raw/bcm47xxnflash/ops_bcm4706.c index f6f694b3cd8e..59e1b88aae38 100644 --- a/drivers/mtd/nand/raw/bcm47xxnflash/ops_bcm4706.c +++ b/drivers/mtd/nand/raw/bcm47xxnflash/ops_bcm4706.c @@ -210,11 +210,11 @@ static int bcm47xxnflash_ops_bcm4706_dev_ready(struct nand_chip *nand_chip) * registers of ChipCommon core. Hacking cmd_ctrl to understand and convert * standard commands would be much more complicated. */ -static void bcm47xxnflash_ops_bcm4706_cmdfunc(struct mtd_info *mtd, +static void bcm47xxnflash_ops_bcm4706_cmdfunc(struct nand_chip *nand_chip, unsigned command, int column, int page_addr) { - struct nand_chip *nand_chip = mtd_to_nand(mtd); + struct mtd_info *mtd = nand_to_mtd(nand_chip); struct bcm47xxnflash *b47n = nand_get_controller_data(nand_chip); struct bcma_drv_cc *cc = b47n->cc; u32 ctlcode; diff --git a/drivers/mtd/nand/raw/brcmnand/brcmnand.c b/drivers/mtd/nand/raw/brcmnand/brcmnand.c index 80f5b4b9ee75..4b814a39b24f 100644 --- a/drivers/mtd/nand/raw/brcmnand/brcmnand.c +++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c @@ -1310,10 +1310,10 @@ static int brcmnand_low_level_op(struct brcmnand_host *host, return brcmnand_waitfunc(mtd, chip); } -static void brcmnand_cmdfunc(struct mtd_info *mtd, unsigned command, +static void brcmnand_cmdfunc(struct nand_chip *chip, unsigned command, int column, int page_addr) { - struct nand_chip *chip = mtd_to_nand(mtd); + struct mtd_info *mtd = nand_to_mtd(chip); struct brcmnand_host *host = nand_get_controller_data(chip); struct brcmnand_controller *ctrl = host->ctrl; u64 addr = (u64)page_addr << chip->page_shift; diff --git a/drivers/mtd/nand/raw/cafe_nand.c b/drivers/mtd/nand/raw/cafe_nand.c index 60a2eecc2b2a..801045d77872 100644 --- a/drivers/mtd/nand/raw/cafe_nand.c +++ b/drivers/mtd/nand/raw/cafe_nand.c @@ -156,10 +156,10 @@ static uint8_t cafe_read_byte(struct nand_chip *chip) return d; } -static void cafe_nand_cmdfunc(struct mtd_info *mtd, unsigned command, +static void cafe_nand_cmdfunc(struct nand_chip *chip, unsigned command, int column, int page_addr) { - struct nand_chip *chip = mtd_to_nand(mtd); + struct mtd_info *mtd = nand_to_mtd(chip); struct cafe_priv *cafe = nand_get_controller_data(chip); int adrbytes = 0; uint32_t ctl1; diff --git a/drivers/mtd/nand/raw/diskonchip.c b/drivers/mtd/nand/raw/diskonchip.c index e40a4e120c7b..64bf0624343d 100644 --- a/drivers/mtd/nand/raw/diskonchip.c +++ b/drivers/mtd/nand/raw/diskonchip.c @@ -637,9 +637,10 @@ static void doc200x_hwcontrol(struct nand_chip *this, int cmd, } } -static void doc2001plus_command(struct mtd_info *mtd, unsigned command, int column, int page_addr) +static void doc2001plus_command(struct nand_chip *this, unsigned command, + int column, int page_addr) { - struct nand_chip *this = mtd_to_nand(mtd); + struct mtd_info *mtd = nand_to_mtd(this); struct doc_priv *doc = nand_get_controller_data(this); void __iomem *docptr = doc->virtadr; diff --git a/drivers/mtd/nand/raw/docg4.c b/drivers/mtd/nand/raw/docg4.c index 9e6255408d49..ba3b949369cb 100644 --- a/drivers/mtd/nand/raw/docg4.c +++ b/drivers/mtd/nand/raw/docg4.c @@ -705,12 +705,12 @@ static uint32_t mtd_to_docg4_address(int page, int column) return (g4_page << 16) | g4_index; /* pack */ } -static void docg4_command(struct mtd_info *mtd, unsigned command, int column, +static void docg4_command(struct nand_chip *nand, unsigned command, int column, int page_addr) { /* handle standard nand commands */ - struct nand_chip *nand = mtd_to_nand(mtd); + struct mtd_info *mtd = nand_to_mtd(nand); struct docg4_priv *doc = nand_get_controller_data(nand); uint32_t g4_addr = mtd_to_docg4_address(page_addr, column); diff --git a/drivers/mtd/nand/raw/fsl_elbc_nand.c b/drivers/mtd/nand/raw/fsl_elbc_nand.c index 74b804a61f2d..93b82af3e518 100644 --- a/drivers/mtd/nand/raw/fsl_elbc_nand.c +++ b/drivers/mtd/nand/raw/fsl_elbc_nand.c @@ -317,10 +317,10 @@ static void fsl_elbc_do_read(struct nand_chip *chip, int oob) } /* cmdfunc send commands to the FCM */ -static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command, +static void fsl_elbc_cmdfunc(struct nand_chip *chip, unsigned int command, int column, int page_addr) { - struct nand_chip *chip = mtd_to_nand(mtd); + struct mtd_info *mtd = nand_to_mtd(chip); struct fsl_elbc_mtd *priv = nand_get_controller_data(chip); struct fsl_lbc_ctrl *ctrl = priv->ctrl; struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand; diff --git a/drivers/mtd/nand/raw/fsl_ifc_nand.c b/drivers/mtd/nand/raw/fsl_ifc_nand.c index da846ffa3e5c..34962da03238 100644 --- a/drivers/mtd/nand/raw/fsl_ifc_nand.c +++ b/drivers/mtd/nand/raw/fsl_ifc_nand.c @@ -301,9 +301,9 @@ static void fsl_ifc_do_read(struct nand_chip *chip, } /* cmdfunc send commands to the IFC NAND Machine */ -static void fsl_ifc_cmdfunc(struct mtd_info *mtd, unsigned int command, - int column, int page_addr) { - struct nand_chip *chip = mtd_to_nand(mtd); +static void fsl_ifc_cmdfunc(struct nand_chip *chip, unsigned int command, + int column, int page_addr) { + struct mtd_info *mtd = nand_to_mtd(chip); struct fsl_ifc_mtd *priv = nand_get_controller_data(chip); struct fsl_ifc_ctrl *ctrl = priv->ctrl; struct fsl_ifc_runtime __iomem *ifc = ctrl->rregs; diff --git a/drivers/mtd/nand/raw/hisi504_nand.c b/drivers/mtd/nand/raw/hisi504_nand.c index 86dd7b54159d..928a320c8517 100644 --- a/drivers/mtd/nand/raw/hisi504_nand.c +++ b/drivers/mtd/nand/raw/hisi504_nand.c @@ -429,10 +429,10 @@ static void set_addr(struct mtd_info *mtd, int column, int page_addr) } } -static void hisi_nfc_cmdfunc(struct mtd_info *mtd, unsigned command, int column, - int page_addr) +static void hisi_nfc_cmdfunc(struct nand_chip *chip, unsigned command, + int column, int page_addr) { - struct nand_chip *chip = mtd_to_nand(mtd); + struct mtd_info *mtd = nand_to_mtd(chip); struct hinfc_host *host = nand_get_controller_data(chip); int is_cache_invalid = 1; unsigned int flag = 0; diff --git a/drivers/mtd/nand/raw/mpc5121_nfc.c b/drivers/mtd/nand/raw/mpc5121_nfc.c index ba7af061c0eb..bd027674898d 100644 --- a/drivers/mtd/nand/raw/mpc5121_nfc.c +++ b/drivers/mtd/nand/raw/mpc5121_nfc.c @@ -330,10 +330,10 @@ static int mpc5121_nfc_dev_ready(struct nand_chip *nand) } /* Write command to NAND flash */ -static void mpc5121_nfc_command(struct mtd_info *mtd, unsigned command, - int column, int page) +static void mpc5121_nfc_command(struct nand_chip *chip, unsigned command, + int column, int page) { - struct nand_chip *chip = mtd_to_nand(mtd); + struct mtd_info *mtd = nand_to_mtd(chip); struct mpc5121_nfc_prv *prv = nand_get_controller_data(chip); prv->column = (column >= 0) ? column : 0; @@ -364,7 +364,7 @@ static void mpc5121_nfc_command(struct mtd_info *mtd, unsigned command, break; case NAND_CMD_SEQIN: - mpc5121_nfc_command(mtd, NAND_CMD_READ0, column, page); + mpc5121_nfc_command(chip, NAND_CMD_READ0, column, page); column = 0; break; diff --git a/drivers/mtd/nand/raw/mxc_nand.c b/drivers/mtd/nand/raw/mxc_nand.c index 82e5b1864399..a03a33656cf4 100644 --- a/drivers/mtd/nand/raw/mxc_nand.c +++ b/drivers/mtd/nand/raw/mxc_nand.c @@ -1333,10 +1333,10 @@ static void preset_v3(struct mtd_info *mtd) /* Used by the upper layer to write command to NAND Flash for * different operations to be carried out on NAND Flash */ -static void mxc_nand_command(struct mtd_info *mtd, unsigned command, - int column, int page_addr) +static void mxc_nand_command(struct nand_chip *nand_chip, unsigned command, + int column, int page_addr) { - struct nand_chip *nand_chip = mtd_to_nand(mtd); + struct mtd_info *mtd = nand_to_mtd(nand_chip); struct mxc_nand_host *host = nand_get_controller_data(nand_chip); dev_dbg(host->dev, "mxc_nand_command (cmd = 0x%x, col = 0x%x, page = 0x%x)\n", diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c index 66dae8b69fe8..a74264f36a70 100644 --- a/drivers/mtd/nand/raw/nand_base.c +++ b/drivers/mtd/nand/raw/nand_base.c @@ -730,7 +730,7 @@ EXPORT_SYMBOL_GPL(nand_soft_waitrdy); /** * nand_command - [DEFAULT] Send command to NAND device - * @mtd: MTD device structure + * @chip: NAND chip object * @command: the command to be sent * @column: the column address for this command, -1 if none * @page_addr: the page address for this command, -1 if none @@ -738,10 +738,10 @@ EXPORT_SYMBOL_GPL(nand_soft_waitrdy); * Send command to NAND device. This function is used for small page devices * (512 Bytes per page). */ -static void nand_command(struct mtd_info *mtd, unsigned int command, +static void nand_command(struct nand_chip *chip, unsigned int command, int column, int page_addr) { - register struct nand_chip *chip = mtd_to_nand(mtd); + struct mtd_info *mtd = nand_to_mtd(chip); int ctrl = NAND_CTRL_CLE | NAND_CTRL_CHANGE; /* Write out the command to the device */ @@ -864,7 +864,7 @@ static void nand_ccs_delay(struct nand_chip *chip) /** * nand_command_lp - [DEFAULT] Send command to NAND large page device - * @mtd: MTD device structure + * @chip: NAND chip object * @command: the command to be sent * @column: the column address for this command, -1 if none * @page_addr: the page address for this command, -1 if none @@ -873,10 +873,10 @@ static void nand_ccs_delay(struct nand_chip *chip) * devices. We don't have the separate regions as we have in the small page * devices. We must emulate NAND_CMD_READOOB to keep the code compatible. */ -static void nand_command_lp(struct mtd_info *mtd, unsigned int command, +static void nand_command_lp(struct nand_chip *chip, unsigned int command, int column, int page_addr) { - register struct nand_chip *chip = mtd_to_nand(mtd); + struct mtd_info *mtd = nand_to_mtd(chip); /* Emulate NAND_CMD_READOOB */ if (command == NAND_CMD_READOOB) { @@ -1530,7 +1530,7 @@ int nand_read_page_op(struct nand_chip *chip, unsigned int page, buf, len); } - chip->cmdfunc(mtd, NAND_CMD_READ0, offset_in_page, page); + chip->cmdfunc(chip, NAND_CMD_READ0, offset_in_page, page); if (len) chip->read_buf(chip, buf, len); @@ -1579,7 +1579,7 @@ static int nand_read_param_page_op(struct nand_chip *chip, u8 page, void *buf, return nand_exec_op(chip, &op); } - chip->cmdfunc(mtd, NAND_CMD_PARAM, page, -1); + chip->cmdfunc(chip, NAND_CMD_PARAM, page, -1); for (i = 0; i < len; i++) p[i] = chip->read_byte(chip); @@ -1642,7 +1642,7 @@ int nand_change_read_column_op(struct nand_chip *chip, return nand_exec_op(chip, &op); } - chip->cmdfunc(mtd, NAND_CMD_RNDOUT, offset_in_page, -1); + chip->cmdfunc(chip, NAND_CMD_RNDOUT, offset_in_page, -1); if (len) chip->read_buf(chip, buf, len); @@ -1679,7 +1679,7 @@ int nand_read_oob_op(struct nand_chip *chip, unsigned int page, mtd->writesize + offset_in_oob, buf, len); - chip->cmdfunc(mtd, NAND_CMD_READOOB, offset_in_oob, page); + chip->cmdfunc(chip, NAND_CMD_READOOB, offset_in_oob, page); if (len) chip->read_buf(chip, buf, len); @@ -1791,7 +1791,7 @@ int nand_prog_page_begin_op(struct nand_chip *chip, unsigned int page, return nand_exec_prog_page_op(chip, page, offset_in_page, buf, len, false); - chip->cmdfunc(mtd, NAND_CMD_SEQIN, offset_in_page, page); + chip->cmdfunc(chip, NAND_CMD_SEQIN, offset_in_page, page); if (buf) chip->write_buf(chip, buf, len); @@ -1833,7 +1833,7 @@ int nand_prog_page_end_op(struct nand_chip *chip) if (ret) return ret; } else { - chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1); + chip->cmdfunc(chip, NAND_CMD_PAGEPROG, -1, -1); ret = chip->waitfunc(mtd, chip); if (ret < 0) return ret; @@ -1878,9 +1878,9 @@ int nand_prog_page_op(struct nand_chip *chip, unsigned int page, status = nand_exec_prog_page_op(chip, page, offset_in_page, buf, len, true); } else { - chip->cmdfunc(mtd, NAND_CMD_SEQIN, offset_in_page, page); + chip->cmdfunc(chip, NAND_CMD_SEQIN, offset_in_page, page); chip->write_buf(chip, buf, len); - chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1); + chip->cmdfunc(chip, NAND_CMD_PAGEPROG, -1, -1); status = chip->waitfunc(mtd, chip); } @@ -1946,7 +1946,7 @@ int nand_change_write_column_op(struct nand_chip *chip, return nand_exec_op(chip, &op); } - chip->cmdfunc(mtd, NAND_CMD_RNDIN, offset_in_page, -1); + chip->cmdfunc(chip, NAND_CMD_RNDIN, offset_in_page, -1); if (len) chip->write_buf(chip, buf, len); @@ -1994,7 +1994,7 @@ int nand_readid_op(struct nand_chip *chip, u8 addr, void *buf, return nand_exec_op(chip, &op); } - chip->cmdfunc(mtd, NAND_CMD_READID, addr, -1); + chip->cmdfunc(chip, NAND_CMD_READID, addr, -1); for (i = 0; i < len; i++) id[i] = chip->read_byte(chip); @@ -2034,7 +2034,7 @@ int nand_status_op(struct nand_chip *chip, u8 *status) return nand_exec_op(chip, &op); } - chip->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1); + chip->cmdfunc(chip, NAND_CMD_STATUS, -1, -1); if (status) *status = chip->read_byte(chip); @@ -2066,7 +2066,7 @@ int nand_exit_status_op(struct nand_chip *chip) return nand_exec_op(chip, &op); } - chip->cmdfunc(mtd, NAND_CMD_READ0, -1, -1); + chip->cmdfunc(chip, NAND_CMD_READ0, -1, -1); return 0; } @@ -2115,8 +2115,8 @@ int nand_erase_op(struct nand_chip *chip, unsigned int eraseblock) if (ret) return ret; } else { - chip->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page); - chip->cmdfunc(mtd, NAND_CMD_ERASE2, -1, -1); + chip->cmdfunc(chip, NAND_CMD_ERASE1, -1, page); + chip->cmdfunc(chip, NAND_CMD_ERASE2, -1, -1); ret = chip->waitfunc(mtd, chip); if (ret < 0) @@ -2166,7 +2166,7 @@ static int nand_set_features_op(struct nand_chip *chip, u8 feature, return nand_exec_op(chip, &op); } - chip->cmdfunc(mtd, NAND_CMD_SET_FEATURES, feature, -1); + chip->cmdfunc(chip, NAND_CMD_SET_FEATURES, feature, -1); for (i = 0; i < ONFI_SUBFEATURE_PARAM_LEN; ++i) chip->write_byte(chip, params[i]); @@ -2215,7 +2215,7 @@ static int nand_get_features_op(struct nand_chip *chip, u8 feature, return nand_exec_op(chip, &op); } - chip->cmdfunc(mtd, NAND_CMD_GET_FEATURES, feature, -1); + chip->cmdfunc(chip, NAND_CMD_GET_FEATURES, feature, -1); for (i = 0; i < ONFI_SUBFEATURE_PARAM_LEN; ++i) params[i] = chip->read_byte(chip); @@ -2270,7 +2270,7 @@ int nand_reset_op(struct nand_chip *chip) return nand_exec_op(chip, &op); } - chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1); + chip->cmdfunc(chip, NAND_CMD_RESET, -1, -1); return 0; } diff --git a/drivers/mtd/nand/raw/nand_hynix.c b/drivers/mtd/nand/raw/nand_hynix.c index 197256c2e1ee..fa873e517131 100644 --- a/drivers/mtd/nand/raw/nand_hynix.c +++ b/drivers/mtd/nand/raw/nand_hynix.c @@ -79,8 +79,6 @@ static bool hynix_nand_has_valid_jedecid(struct nand_chip *chip) static int hynix_nand_cmd_op(struct nand_chip *chip, u8 cmd) { - struct mtd_info *mtd = nand_to_mtd(chip); - if (chip->exec_op) { struct nand_op_instr instrs[] = { NAND_OP_CMD(cmd, 0), @@ -90,14 +88,13 @@ static int hynix_nand_cmd_op(struct nand_chip *chip, u8 cmd) return nand_exec_op(chip, &op); } - chip->cmdfunc(mtd, cmd, -1, -1); + chip->cmdfunc(chip, cmd, -1, -1); return 0; } static int hynix_nand_reg_write_op(struct nand_chip *chip, u8 addr, u8 val) { - struct mtd_info *mtd = nand_to_mtd(chip); u16 column = ((u16)addr << 8) | addr; if (chip->exec_op) { @@ -110,7 +107,7 @@ static int hynix_nand_reg_write_op(struct nand_chip *chip, u8 addr, u8 val) return nand_exec_op(chip, &op); } - chip->cmdfunc(mtd, NAND_CMD_NONE, column, -1); + chip->cmdfunc(chip, NAND_CMD_NONE, column, -1); chip->write_byte(chip, val); return 0; diff --git a/drivers/mtd/nand/raw/nuc900_nand.c b/drivers/mtd/nand/raw/nuc900_nand.c index 4029b802243d..3aae5fda5399 100644 --- a/drivers/mtd/nand/raw/nuc900_nand.c +++ b/drivers/mtd/nand/raw/nuc900_nand.c @@ -129,10 +129,11 @@ static int nuc900_nand_devready(struct nand_chip *chip) return ready; } -static void nuc900_nand_command_lp(struct mtd_info *mtd, unsigned int command, +static void nuc900_nand_command_lp(struct nand_chip *chip, + unsigned int command, int column, int page_addr) { - register struct nand_chip *chip = mtd_to_nand(mtd); + struct mtd_info *mtd = nand_to_mtd(chip); struct nuc900_nand *nand = mtd_to_nuc900(mtd); if (command == NAND_CMD_READOOB) { diff --git a/drivers/mtd/nand/raw/qcom_nandc.c b/drivers/mtd/nand/raw/qcom_nandc.c index c6eb205e0f76..9037dddff99a 100644 --- a/drivers/mtd/nand/raw/qcom_nandc.c +++ b/drivers/mtd/nand/raw/qcom_nandc.c @@ -1440,10 +1440,9 @@ static void post_command(struct qcom_nand_host *host, int command) * NAND_CMD_READOOB would never be called because we have our own versions * of read_oob ops for nand_ecc_ctrl. */ -static void qcom_nandc_command(struct mtd_info *mtd, unsigned int command, +static void qcom_nandc_command(struct nand_chip *chip, unsigned int command, int column, int page_addr) { - struct nand_chip *chip = mtd_to_nand(mtd); struct qcom_nand_host *host = to_qcom_nand_host(chip); struct nand_ecc_ctrl *ecc = &chip->ecc; struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip); diff --git a/drivers/mtd/nand/raw/sh_flctl.c b/drivers/mtd/nand/raw/sh_flctl.c index e2a4939971b5..4b1c7e435937 100644 --- a/drivers/mtd/nand/raw/sh_flctl.c +++ b/drivers/mtd/nand/raw/sh_flctl.c @@ -750,9 +750,10 @@ static void execmd_write_oob(struct mtd_info *mtd) } } -static void flctl_cmdfunc(struct mtd_info *mtd, unsigned int command, +static void flctl_cmdfunc(struct nand_chip *chip, unsigned int command, int column, int page_addr) { + struct mtd_info *mtd = nand_to_mtd(chip); struct sh_flctl *flctl = mtd_to_flctl(mtd); uint32_t read_cmd = 0; diff --git a/drivers/staging/mt29f_spinand/mt29f_spinand.c b/drivers/staging/mt29f_spinand/mt29f_spinand.c index c0df8b6ab19b..724e66c92fd2 100644 --- a/drivers/staging/mt29f_spinand/mt29f_spinand.c +++ b/drivers/staging/mt29f_spinand/mt29f_spinand.c @@ -759,10 +759,10 @@ static void spinand_reset(struct spi_device *spi_nand) dev_err(&spi_nand->dev, "wait timedout!\n"); } -static void spinand_cmdfunc(struct mtd_info *mtd, unsigned int command, +static void spinand_cmdfunc(struct nand_chip *chip, unsigned int command, int column, int page) { - struct nand_chip *chip = mtd_to_nand(mtd); + struct mtd_info *mtd = nand_to_mtd(chip); struct spinand_info *info = nand_get_controller_data(chip); struct spinand_state *state = info->priv; diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h index 404ac7d4b279..2a74de9012c4 100644 --- a/include/linux/mtd/rawnand.h +++ b/include/linux/mtd/rawnand.h @@ -1292,7 +1292,7 @@ struct nand_chip { int (*block_markbad)(struct nand_chip *chip, loff_t ofs); void (*cmd_ctrl)(struct nand_chip *chip, int dat, unsigned int ctrl); int (*dev_ready)(struct nand_chip *chip); - void (*cmdfunc)(struct mtd_info *mtd, unsigned command, int column, + void (*cmdfunc)(struct nand_chip *chip, unsigned command, int column, int page_addr); int(*waitfunc)(struct mtd_info *mtd, struct nand_chip *this); int (*exec_op)(struct nand_chip *chip, From f1d46942e823ffdd8532409c9b1c1f87314bf20f Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Thu, 6 Sep 2018 14:05:29 +0200 Subject: [PATCH 257/302] mtd: rawnand: Pass a nand_chip object to chip->waitfunc() Let's make the raw NAND API consistent by patching all helpers and hooks to take a nand_chip object instead of an mtd_info one or remove the mtd_info object when both are passed. Let's tackle the chip->waitfunc() hook. Signed-off-by: Boris Brezillon Signed-off-by: Miquel Raynal --- drivers/mtd/nand/raw/atmel/nand-controller.c | 2 +- drivers/mtd/nand/raw/brcmnand/brcmnand.c | 12 ++++---- drivers/mtd/nand/raw/denali.c | 4 +-- drivers/mtd/nand/raw/diskonchip.c | 2 +- drivers/mtd/nand/raw/docg4.c | 4 +-- drivers/mtd/nand/raw/fsl_elbc_nand.c | 4 +-- drivers/mtd/nand/raw/fsl_ifc_nand.c | 3 +- drivers/mtd/nand/raw/lpc32xx_mlc.c | 17 ++++++----- drivers/mtd/nand/raw/nand_base.c | 29 +++++-------------- drivers/mtd/nand/raw/omap2.c | 8 ++--- drivers/mtd/nand/raw/r852.c | 2 +- drivers/mtd/nand/raw/tango_nand.c | 2 +- drivers/mtd/nand/raw/tmio_nand.c | 5 ++-- drivers/staging/mt29f_spinand/mt29f_spinand.c | 3 +- include/linux/mtd/rawnand.h | 2 +- 15 files changed, 42 insertions(+), 57 deletions(-) diff --git a/drivers/mtd/nand/raw/atmel/nand-controller.c b/drivers/mtd/nand/raw/atmel/nand-controller.c index 2dcd8aa0ce0b..d5939114f999 100644 --- a/drivers/mtd/nand/raw/atmel/nand-controller.c +++ b/drivers/mtd/nand/raw/atmel/nand-controller.c @@ -945,7 +945,7 @@ static int atmel_hsmc_nand_pmecc_write_pg(struct nand_chip *chip, dev_err(nc->base.dev, "Failed to program NAND page (err = %d)\n", ret); - status = chip->waitfunc(mtd, chip); + status = chip->waitfunc(chip); if (status & NAND_STATUS_FAIL) return -EIO; diff --git a/drivers/mtd/nand/raw/brcmnand/brcmnand.c b/drivers/mtd/nand/raw/brcmnand/brcmnand.c index 4b814a39b24f..fee40a3ce5d2 100644 --- a/drivers/mtd/nand/raw/brcmnand/brcmnand.c +++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c @@ -1237,9 +1237,8 @@ static void brcmnand_cmd_ctrl(struct nand_chip *chip, int dat, /* intentionally left blank */ } -static int brcmnand_waitfunc(struct mtd_info *mtd, struct nand_chip *this) +static int brcmnand_waitfunc(struct nand_chip *chip) { - struct nand_chip *chip = mtd_to_nand(mtd); struct brcmnand_host *host = nand_get_controller_data(chip); struct brcmnand_controller *ctrl = host->ctrl; unsigned long timeo = msecs_to_jiffies(100); @@ -1274,7 +1273,6 @@ static int brcmnand_low_level_op(struct brcmnand_host *host, enum brcmnand_llop_type type, u32 data, bool last_op) { - struct mtd_info *mtd = nand_to_mtd(&host->chip); struct nand_chip *chip = &host->chip; struct brcmnand_controller *ctrl = host->ctrl; u32 tmp; @@ -1307,7 +1305,7 @@ static int brcmnand_low_level_op(struct brcmnand_host *host, (void)brcmnand_read_reg(ctrl, BRCMNAND_LL_OP); brcmnand_send_cmd(host, CMD_LOW_LEVEL_OP); - return brcmnand_waitfunc(mtd, chip); + return brcmnand_waitfunc(chip); } static void brcmnand_cmdfunc(struct nand_chip *chip, unsigned command, @@ -1383,7 +1381,7 @@ static void brcmnand_cmdfunc(struct nand_chip *chip, unsigned command, (void)brcmnand_read_reg(ctrl, BRCMNAND_CMD_ADDRESS); brcmnand_send_cmd(host, native_cmd); - brcmnand_waitfunc(mtd, chip); + brcmnand_waitfunc(chip); if (native_cmd == CMD_PARAMETER_READ || native_cmd == CMD_PARAMETER_CHANGE_COL) { @@ -1615,7 +1613,7 @@ static int brcmnand_read_by_pio(struct mtd_info *mtd, struct nand_chip *chip, (void)brcmnand_read_reg(ctrl, BRCMNAND_CMD_ADDRESS); /* SPARE_AREA_READ does not use ECC, so just use PAGE_READ */ brcmnand_send_cmd(host, CMD_PAGE_READ); - brcmnand_waitfunc(mtd, chip); + brcmnand_waitfunc(chip); if (likely(buf)) { brcmnand_soc_data_bus_prepare(ctrl->soc, false); @@ -1893,7 +1891,7 @@ static int brcmnand_write(struct mtd_info *mtd, struct nand_chip *chip, /* we cannot use SPARE_AREA_PROGRAM when PARTIAL_PAGE_EN=0 */ brcmnand_send_cmd(host, CMD_PROGRAM_PAGE); - status = brcmnand_waitfunc(mtd, chip); + status = brcmnand_waitfunc(chip); if (status & NAND_STATUS_FAIL) { dev_info(ctrl->dev, "program failed at %llx\n", diff --git a/drivers/mtd/nand/raw/denali.c b/drivers/mtd/nand/raw/denali.c index 7258dd13b3f9..0c3fff9d65af 100644 --- a/drivers/mtd/nand/raw/denali.c +++ b/drivers/mtd/nand/raw/denali.c @@ -904,9 +904,9 @@ static void denali_select_chip(struct nand_chip *chip, int cs) denali->active_bank = cs; } -static int denali_waitfunc(struct mtd_info *mtd, struct nand_chip *chip) +static int denali_waitfunc(struct nand_chip *chip) { - struct denali_nand_info *denali = mtd_to_denali(mtd); + struct denali_nand_info *denali = mtd_to_denali(nand_to_mtd(chip)); uint32_t irq_status; /* R/B# pin transitioned from low to high? */ diff --git a/drivers/mtd/nand/raw/diskonchip.c b/drivers/mtd/nand/raw/diskonchip.c index 64bf0624343d..0b305c19a9a3 100644 --- a/drivers/mtd/nand/raw/diskonchip.c +++ b/drivers/mtd/nand/raw/diskonchip.c @@ -433,7 +433,7 @@ static void __init doc2000_count_chips(struct mtd_info *mtd) pr_debug("Detected %d chips per floor.\n", i); } -static int doc200x_wait(struct mtd_info *mtd, struct nand_chip *this) +static int doc200x_wait(struct nand_chip *this) { struct doc_priv *doc = nand_get_controller_data(this); diff --git a/drivers/mtd/nand/raw/docg4.c b/drivers/mtd/nand/raw/docg4.c index ba3b949369cb..ae20172f1b60 100644 --- a/drivers/mtd/nand/raw/docg4.c +++ b/drivers/mtd/nand/raw/docg4.c @@ -315,7 +315,7 @@ static int poll_status(struct docg4_priv *doc) } -static int docg4_wait(struct mtd_info *mtd, struct nand_chip *nand) +static int docg4_wait(struct nand_chip *nand) { struct docg4_priv *doc = nand_get_controller_data(nand); @@ -938,7 +938,7 @@ static int docg4_erase_block(struct mtd_info *mtd, int page) poll_status(doc); write_nop(docptr); - status = nand->waitfunc(mtd, nand); + status = nand->waitfunc(nand); if (status < 0) return status; diff --git a/drivers/mtd/nand/raw/fsl_elbc_nand.c b/drivers/mtd/nand/raw/fsl_elbc_nand.c index 93b82af3e518..98da5f9f04ac 100644 --- a/drivers/mtd/nand/raw/fsl_elbc_nand.c +++ b/drivers/mtd/nand/raw/fsl_elbc_nand.c @@ -621,7 +621,7 @@ static void fsl_elbc_read_buf(struct nand_chip *chip, u8 *buf, int len) /* This function is called after Program and Erase Operations to * check for success or failure. */ -static int fsl_elbc_wait(struct mtd_info *mtd, struct nand_chip *chip) +static int fsl_elbc_wait(struct nand_chip *chip) { struct fsl_elbc_mtd *priv = nand_get_controller_data(chip); struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand; @@ -720,7 +720,7 @@ static int fsl_elbc_read_page(struct nand_chip *chip, uint8_t *buf, if (oob_required) fsl_elbc_read_buf(chip, chip->oob_poi, mtd->oobsize); - if (fsl_elbc_wait(mtd, chip) & NAND_STATUS_FAIL) + if (fsl_elbc_wait(chip) & NAND_STATUS_FAIL) mtd->ecc_stats.failed++; return elbc_fcm_ctrl->max_bitflips; diff --git a/drivers/mtd/nand/raw/fsl_ifc_nand.c b/drivers/mtd/nand/raw/fsl_ifc_nand.c index 34962da03238..cdcd82d1f8bc 100644 --- a/drivers/mtd/nand/raw/fsl_ifc_nand.c +++ b/drivers/mtd/nand/raw/fsl_ifc_nand.c @@ -614,8 +614,9 @@ static void fsl_ifc_read_buf(struct nand_chip *chip, u8 *buf, int len) * This function is called after Program and Erase Operations to * check for success or failure. */ -static int fsl_ifc_wait(struct mtd_info *mtd, struct nand_chip *chip) +static int fsl_ifc_wait(struct nand_chip *chip) { + struct mtd_info *mtd = nand_to_mtd(chip); struct fsl_ifc_mtd *priv = nand_get_controller_data(chip); struct fsl_ifc_ctrl *ctrl = priv->ctrl; struct fsl_ifc_runtime __iomem *ifc = ctrl->rregs; diff --git a/drivers/mtd/nand/raw/lpc32xx_mlc.c b/drivers/mtd/nand/raw/lpc32xx_mlc.c index 726cd8868ac3..ae31f6ccbeb3 100644 --- a/drivers/mtd/nand/raw/lpc32xx_mlc.c +++ b/drivers/mtd/nand/raw/lpc32xx_mlc.c @@ -328,8 +328,9 @@ static irqreturn_t lpc3xxx_nand_irq(int irq, struct lpc32xx_nand_host *host) return IRQ_HANDLED; } -static int lpc32xx_waitfunc_nand(struct mtd_info *mtd, struct nand_chip *chip) +static int lpc32xx_waitfunc_nand(struct nand_chip *chip) { + struct mtd_info *mtd = nand_to_mtd(chip); struct lpc32xx_nand_host *host = nand_get_controller_data(chip); if (readb(MLC_ISR(host->io_base)) & MLCISR_NAND_READY) @@ -347,9 +348,9 @@ static int lpc32xx_waitfunc_nand(struct mtd_info *mtd, struct nand_chip *chip) return NAND_STATUS_READY; } -static int lpc32xx_waitfunc_controller(struct mtd_info *mtd, - struct nand_chip *chip) +static int lpc32xx_waitfunc_controller(struct nand_chip *chip) { + struct mtd_info *mtd = nand_to_mtd(chip); struct lpc32xx_nand_host *host = nand_get_controller_data(chip); if (readb(MLC_ISR(host->io_base)) & MLCISR_CONTROLLER_READY) @@ -367,10 +368,10 @@ static int lpc32xx_waitfunc_controller(struct mtd_info *mtd, return NAND_STATUS_READY; } -static int lpc32xx_waitfunc(struct mtd_info *mtd, struct nand_chip *chip) +static int lpc32xx_waitfunc(struct nand_chip *chip) { - lpc32xx_waitfunc_nand(mtd, chip); - lpc32xx_waitfunc_controller(mtd, chip); + lpc32xx_waitfunc_nand(chip); + lpc32xx_waitfunc_controller(chip); return NAND_STATUS_READY; } @@ -469,7 +470,7 @@ static int lpc32xx_read_page(struct nand_chip *chip, uint8_t *buf, writeb(0x00, MLC_ECC_AUTO_DEC_REG(host->io_base)); /* Wait for Controller Ready */ - lpc32xx_waitfunc_controller(mtd, chip); + lpc32xx_waitfunc_controller(chip); /* Check ECC Error status */ mlc_isr = readl(MLC_ISR(host->io_base)); @@ -550,7 +551,7 @@ static int lpc32xx_write_page_lowlevel(struct nand_chip *chip, writeb(0x00, MLC_ECC_AUTO_ENC_REG(host->io_base)); /* Wait for Controller Ready */ - lpc32xx_waitfunc_controller(mtd, chip); + lpc32xx_waitfunc_controller(chip); } return nand_prog_page_end_op(chip); diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c index a74264f36a70..9be0f98c1244 100644 --- a/drivers/mtd/nand/raw/nand_base.c +++ b/drivers/mtd/nand/raw/nand_base.c @@ -1062,8 +1062,7 @@ nand_get_device(struct mtd_info *mtd, int new_state) * we are in interrupt context. May happen when in panic and trying to write * an oops through mtdoops. */ -static void panic_nand_wait(struct mtd_info *mtd, struct nand_chip *chip, - unsigned long timeo) +static void panic_nand_wait(struct nand_chip *chip, unsigned long timeo) { int i; for (i = 0; i < timeo; i++) { @@ -1093,7 +1092,7 @@ static void panic_nand_wait(struct mtd_info *mtd, struct nand_chip *chip, * * Wait for command done. This applies to erase and program only. */ -static int nand_wait(struct mtd_info *mtd, struct nand_chip *chip) +static int nand_wait(struct nand_chip *chip) { unsigned long timeo = 400; @@ -1111,7 +1110,7 @@ static int nand_wait(struct mtd_info *mtd, struct nand_chip *chip) return ret; if (in_interrupt() || oops_in_progress) - panic_nand_wait(mtd, chip, timeo); + panic_nand_wait(chip, timeo); else { timeo = jiffies + msecs_to_jiffies(timeo); do { @@ -1553,7 +1552,6 @@ EXPORT_SYMBOL_GPL(nand_read_page_op); static int nand_read_param_page_op(struct nand_chip *chip, u8 page, void *buf, unsigned int len) { - struct mtd_info *mtd = nand_to_mtd(chip); unsigned int i; u8 *p = buf; @@ -1811,7 +1809,6 @@ EXPORT_SYMBOL_GPL(nand_prog_page_begin_op); */ int nand_prog_page_end_op(struct nand_chip *chip) { - struct mtd_info *mtd = nand_to_mtd(chip); int ret; u8 status; @@ -1834,7 +1831,7 @@ int nand_prog_page_end_op(struct nand_chip *chip) return ret; } else { chip->cmdfunc(chip, NAND_CMD_PAGEPROG, -1, -1); - ret = chip->waitfunc(mtd, chip); + ret = chip->waitfunc(chip); if (ret < 0) return ret; @@ -1881,7 +1878,7 @@ int nand_prog_page_op(struct nand_chip *chip, unsigned int page, chip->cmdfunc(chip, NAND_CMD_SEQIN, offset_in_page, page); chip->write_buf(chip, buf, len); chip->cmdfunc(chip, NAND_CMD_PAGEPROG, -1, -1); - status = chip->waitfunc(mtd, chip); + status = chip->waitfunc(chip); } if (status & NAND_STATUS_FAIL) @@ -1970,7 +1967,6 @@ EXPORT_SYMBOL_GPL(nand_change_write_column_op); int nand_readid_op(struct nand_chip *chip, u8 addr, void *buf, unsigned int len) { - struct mtd_info *mtd = nand_to_mtd(chip); unsigned int i; u8 *id = buf; @@ -2016,8 +2012,6 @@ EXPORT_SYMBOL_GPL(nand_readid_op); */ int nand_status_op(struct nand_chip *chip, u8 *status) { - struct mtd_info *mtd = nand_to_mtd(chip); - if (chip->exec_op) { const struct nand_sdr_timings *sdr = nand_get_sdr_timings(&chip->data_interface); @@ -2055,8 +2049,6 @@ EXPORT_SYMBOL_GPL(nand_status_op); */ int nand_exit_status_op(struct nand_chip *chip) { - struct mtd_info *mtd = nand_to_mtd(chip); - if (chip->exec_op) { struct nand_op_instr instrs[] = { NAND_OP_CMD(NAND_CMD_READ0, 0), @@ -2085,7 +2077,6 @@ EXPORT_SYMBOL_GPL(nand_exit_status_op); */ int nand_erase_op(struct nand_chip *chip, unsigned int eraseblock) { - struct mtd_info *mtd = nand_to_mtd(chip); unsigned int page = eraseblock << (chip->phys_erase_shift - chip->page_shift); int ret; @@ -2118,7 +2109,7 @@ int nand_erase_op(struct nand_chip *chip, unsigned int eraseblock) chip->cmdfunc(chip, NAND_CMD_ERASE1, -1, page); chip->cmdfunc(chip, NAND_CMD_ERASE2, -1, -1); - ret = chip->waitfunc(mtd, chip); + ret = chip->waitfunc(chip); if (ret < 0) return ret; @@ -2147,7 +2138,6 @@ EXPORT_SYMBOL_GPL(nand_erase_op); static int nand_set_features_op(struct nand_chip *chip, u8 feature, const void *data) { - struct mtd_info *mtd = nand_to_mtd(chip); const u8 *params = data; int i, ret; @@ -2170,7 +2160,7 @@ static int nand_set_features_op(struct nand_chip *chip, u8 feature, for (i = 0; i < ONFI_SUBFEATURE_PARAM_LEN; ++i) chip->write_byte(chip, params[i]); - ret = chip->waitfunc(mtd, chip); + ret = chip->waitfunc(chip); if (ret < 0) return ret; @@ -2195,7 +2185,6 @@ static int nand_set_features_op(struct nand_chip *chip, u8 feature, static int nand_get_features_op(struct nand_chip *chip, u8 feature, void *data) { - struct mtd_info *mtd = nand_to_mtd(chip); u8 *params = data; int i; @@ -2256,8 +2245,6 @@ static int nand_wait_rdy_op(struct nand_chip *chip, unsigned int timeout_ms, */ int nand_reset_op(struct nand_chip *chip) { - struct mtd_info *mtd = nand_to_mtd(chip); - if (chip->exec_op) { const struct nand_sdr_timings *sdr = nand_get_sdr_timings(&chip->data_interface); @@ -4518,7 +4505,7 @@ static int panic_nand_write(struct mtd_info *mtd, loff_t to, size_t len, chip->select_chip(chip, chipnr); /* Wait for the device to get ready */ - panic_nand_wait(mtd, chip, 400); + panic_nand_wait(chip, 400); memset(&ops, 0, sizeof(ops)); ops.len = len; diff --git a/drivers/mtd/nand/raw/omap2.c b/drivers/mtd/nand/raw/omap2.c index eef9cbadd3c4..6f0fec3596cc 100644 --- a/drivers/mtd/nand/raw/omap2.c +++ b/drivers/mtd/nand/raw/omap2.c @@ -981,8 +981,7 @@ static void omap_enable_hwecc(struct nand_chip *chip, int mode) /** * omap_wait - wait until the command is done - * @mtd: MTD device structure - * @chip: NAND Chip structure + * @this: NAND Chip structure * * Wait function is called during Program and erase operations and * the way it is called from MTD layer, we should wait till the NAND @@ -991,10 +990,9 @@ static void omap_enable_hwecc(struct nand_chip *chip, int mode) * Erase can take up to 400ms and program up to 20ms according to * general NAND and SmartMedia specs */ -static int omap_wait(struct mtd_info *mtd, struct nand_chip *chip) +static int omap_wait(struct nand_chip *this) { - struct nand_chip *this = mtd_to_nand(mtd); - struct omap_nand_info *info = mtd_to_omap(mtd); + struct omap_nand_info *info = mtd_to_omap(nand_to_mtd(this)); unsigned long timeo = jiffies; int status, state = this->state; diff --git a/drivers/mtd/nand/raw/r852.c b/drivers/mtd/nand/raw/r852.c index 4331ff856fa5..2c30e97ab2a4 100644 --- a/drivers/mtd/nand/raw/r852.c +++ b/drivers/mtd/nand/raw/r852.c @@ -362,7 +362,7 @@ static void r852_cmdctl(struct nand_chip *chip, int dat, unsigned int ctrl) * Wait till card is ready. * based on nand_wait, but returns errors on DMA error */ -static int r852_wait(struct mtd_info *mtd, struct nand_chip *chip) +static int r852_wait(struct nand_chip *chip) { struct r852_device *dev = nand_get_controller_data(chip); diff --git a/drivers/mtd/nand/raw/tango_nand.c b/drivers/mtd/nand/raw/tango_nand.c index cc719bc49b68..c21a0f2d26fc 100644 --- a/drivers/mtd/nand/raw/tango_nand.c +++ b/drivers/mtd/nand/raw/tango_nand.c @@ -314,7 +314,7 @@ static int tango_write_page(struct nand_chip *chip, const u8 *buf, if (err) return err; - status = chip->waitfunc(mtd, chip); + status = chip->waitfunc(chip); if (status & NAND_STATUS_FAIL) return -EIO; diff --git a/drivers/mtd/nand/raw/tmio_nand.c b/drivers/mtd/nand/raw/tmio_nand.c index 7096fa3d50ab..f44621672779 100644 --- a/drivers/mtd/nand/raw/tmio_nand.c +++ b/drivers/mtd/nand/raw/tmio_nand.c @@ -186,10 +186,9 @@ static irqreturn_t tmio_irq(int irq, void *__tmio) *erase and write, we enable it to wake us up. The irq handler *disables the interrupt. */ -static int -tmio_nand_wait(struct mtd_info *mtd, struct nand_chip *nand_chip) +static int tmio_nand_wait(struct nand_chip *nand_chip) { - struct tmio_nand *tmio = mtd_to_tmio(mtd); + struct tmio_nand *tmio = mtd_to_tmio(nand_to_mtd(nand_chip)); long timeout; u8 status; diff --git a/drivers/staging/mt29f_spinand/mt29f_spinand.c b/drivers/staging/mt29f_spinand/mt29f_spinand.c index 724e66c92fd2..f2e14f972319 100644 --- a/drivers/staging/mt29f_spinand/mt29f_spinand.c +++ b/drivers/staging/mt29f_spinand/mt29f_spinand.c @@ -695,8 +695,9 @@ static u8 spinand_read_byte(struct nand_chip *chip) return data; } -static int spinand_wait(struct mtd_info *mtd, struct nand_chip *chip) +static int spinand_wait(struct nand_chip *chip) { + struct mtd_info *mtd = nand_to_mtd(chip); struct spinand_info *info = nand_get_controller_data(chip); unsigned long timeo = jiffies; diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h index 2a74de9012c4..c00e571d09ca 100644 --- a/include/linux/mtd/rawnand.h +++ b/include/linux/mtd/rawnand.h @@ -1294,7 +1294,7 @@ struct nand_chip { int (*dev_ready)(struct nand_chip *chip); void (*cmdfunc)(struct nand_chip *chip, unsigned command, int column, int page_addr); - int(*waitfunc)(struct mtd_info *mtd, struct nand_chip *this); + int (*waitfunc)(struct nand_chip *chip); int (*exec_op)(struct nand_chip *chip, const struct nand_operation *op, bool check_only); From a2098a9e4f6704471c32230d48b905e51f0cba32 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Thu, 6 Sep 2018 14:05:30 +0200 Subject: [PATCH 258/302] mtd: rawnand: Pass a nand_chip object to chip->erase() Let's make the raw NAND API consistent by patching all helpers and hooks to take a nand_chip object instead of an mtd_info one or remove the mtd_info object when both are passed. Let's tackle the chip->erase() hook. Signed-off-by: Boris Brezillon Signed-off-by: Miquel Raynal --- drivers/mtd/nand/raw/denali.c | 4 ++-- drivers/mtd/nand/raw/docg4.c | 4 ++-- drivers/mtd/nand/raw/nand_base.c | 7 +++---- include/linux/mtd/rawnand.h | 2 +- 4 files changed, 8 insertions(+), 9 deletions(-) diff --git a/drivers/mtd/nand/raw/denali.c b/drivers/mtd/nand/raw/denali.c index 0c3fff9d65af..bb4ad3b822ad 100644 --- a/drivers/mtd/nand/raw/denali.c +++ b/drivers/mtd/nand/raw/denali.c @@ -915,9 +915,9 @@ static int denali_waitfunc(struct nand_chip *chip) return irq_status & INTR__INT_ACT ? 0 : NAND_STATUS_FAIL; } -static int denali_erase(struct mtd_info *mtd, int page) +static int denali_erase(struct nand_chip *chip, int page) { - struct denali_nand_info *denali = mtd_to_denali(mtd); + struct denali_nand_info *denali = mtd_to_denali(nand_to_mtd(chip)); uint32_t irq_status; denali_reset_irq(denali); diff --git a/drivers/mtd/nand/raw/docg4.c b/drivers/mtd/nand/raw/docg4.c index ae20172f1b60..49500cae3d2f 100644 --- a/drivers/mtd/nand/raw/docg4.c +++ b/drivers/mtd/nand/raw/docg4.c @@ -892,9 +892,9 @@ static int docg4_read_oob(struct nand_chip *nand, int page) return 0; } -static int docg4_erase_block(struct mtd_info *mtd, int page) +static int docg4_erase_block(struct nand_chip *nand, int page) { - struct nand_chip *nand = mtd_to_nand(mtd); + struct mtd_info *mtd = nand_to_mtd(nand); struct docg4_priv *doc = nand_get_controller_data(nand); void __iomem *docptr = doc->virtadr; uint16_t g4_page; diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c index 9be0f98c1244..26be436eb8f1 100644 --- a/drivers/mtd/nand/raw/nand_base.c +++ b/drivers/mtd/nand/raw/nand_base.c @@ -4623,14 +4623,13 @@ static int nand_write_oob(struct mtd_info *mtd, loff_t to, /** * single_erase - [GENERIC] NAND standard block erase command function - * @mtd: MTD device structure + * @chip: NAND chip object * @page: the page address of the block which will be erased * * Standard erase command for NAND chips. Returns NAND status. */ -static int single_erase(struct mtd_info *mtd, int page) +static int single_erase(struct nand_chip *chip, int page) { - struct nand_chip *chip = mtd_to_nand(mtd); unsigned int eraseblock; /* Send commands to erase a block */ @@ -4715,7 +4714,7 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr, (page + pages_per_block)) chip->pagebuf = -1; - status = chip->erase(mtd, page & chip->pagemask); + status = chip->erase(chip, page & chip->pagemask); /* See if block erase succeeded */ if (status) { diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h index c00e571d09ca..8c8315d977de 100644 --- a/include/linux/mtd/rawnand.h +++ b/include/linux/mtd/rawnand.h @@ -1298,7 +1298,7 @@ struct nand_chip { int (*exec_op)(struct nand_chip *chip, const struct nand_operation *op, bool check_only); - int (*erase)(struct mtd_info *mtd, int page); + int (*erase)(struct nand_chip *chip, int page); int (*set_features)(struct mtd_info *mtd, struct nand_chip *chip, int feature_addr, uint8_t *subfeature_para); int (*get_features)(struct mtd_info *mtd, struct nand_chip *chip, From aa36ff25ffdea656c3b748a5cf141bc884e6275c Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Thu, 6 Sep 2018 14:05:31 +0200 Subject: [PATCH 259/302] mtd: rawnand: Pass a nand_chip object to chip->{get, set}_features() Let's make the raw NAND API consistent by patching all helpers and hooks to take a nand_chip object instead of an mtd_info one or remove the mtd_info object when both are passed. Let's tackle the chip->{get,set}_features() hooks. Signed-off-by: Boris Brezillon Signed-off-by: Miquel Raynal --- drivers/mtd/nand/raw/mxc_nand.c | 16 ++++++++-------- drivers/mtd/nand/raw/nand_base.c | 21 ++++++--------------- include/linux/mtd/rawnand.h | 12 ++++++------ 3 files changed, 20 insertions(+), 29 deletions(-) diff --git a/drivers/mtd/nand/raw/mxc_nand.c b/drivers/mtd/nand/raw/mxc_nand.c index a03a33656cf4..ec150e19a368 100644 --- a/drivers/mtd/nand/raw/mxc_nand.c +++ b/drivers/mtd/nand/raw/mxc_nand.c @@ -1393,11 +1393,11 @@ static void mxc_nand_command(struct nand_chip *nand_chip, unsigned command, } } -static int mxc_nand_set_features(struct mtd_info *mtd, struct nand_chip *chip, - int addr, u8 *subfeature_param) +static int mxc_nand_set_features(struct nand_chip *chip, int addr, + u8 *subfeature_param) { - struct nand_chip *nand_chip = mtd_to_nand(mtd); - struct mxc_nand_host *host = nand_get_controller_data(nand_chip); + struct mtd_info *mtd = nand_to_mtd(chip); + struct mxc_nand_host *host = nand_get_controller_data(chip); int i; host->buf_start = 0; @@ -1413,11 +1413,11 @@ static int mxc_nand_set_features(struct mtd_info *mtd, struct nand_chip *chip, return 0; } -static int mxc_nand_get_features(struct mtd_info *mtd, struct nand_chip *chip, - int addr, u8 *subfeature_param) +static int mxc_nand_get_features(struct nand_chip *chip, int addr, + u8 *subfeature_param) { - struct nand_chip *nand_chip = mtd_to_nand(mtd); - struct mxc_nand_host *host = nand_get_controller_data(nand_chip); + struct mtd_info *mtd = nand_to_mtd(chip); + struct mxc_nand_host *host = nand_get_controller_data(chip); int i; host->devtype_data->send_cmd(host, NAND_CMD_GET_FEATURES, false); diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c index 26be436eb8f1..0ae597ced5b4 100644 --- a/drivers/mtd/nand/raw/nand_base.c +++ b/drivers/mtd/nand/raw/nand_base.c @@ -1163,12 +1163,10 @@ static bool nand_supports_set_features(struct nand_chip *chip, int addr) int nand_get_features(struct nand_chip *chip, int addr, u8 *subfeature_param) { - struct mtd_info *mtd = nand_to_mtd(chip); - if (!nand_supports_get_features(chip, addr)) return -ENOTSUPP; - return chip->get_features(mtd, chip, addr, subfeature_param); + return chip->get_features(chip, addr, subfeature_param); } EXPORT_SYMBOL_GPL(nand_get_features); @@ -1184,12 +1182,10 @@ EXPORT_SYMBOL_GPL(nand_get_features); int nand_set_features(struct nand_chip *chip, int addr, u8 *subfeature_param) { - struct mtd_info *mtd = nand_to_mtd(chip); - if (!nand_supports_set_features(chip, addr)) return -ENOTSUPP; - return chip->set_features(mtd, chip, addr, subfeature_param); + return chip->set_features(chip, addr, subfeature_param); } EXPORT_SYMBOL_GPL(nand_set_features); @@ -4846,13 +4842,11 @@ static int nand_max_bad_blocks(struct mtd_info *mtd, loff_t ofs, size_t len) /** * nand_default_set_features- [REPLACEABLE] set NAND chip features - * @mtd: MTD device structure * @chip: nand chip info structure * @addr: feature address. * @subfeature_param: the subfeature parameters, a four bytes array. */ -static int nand_default_set_features(struct mtd_info *mtd, - struct nand_chip *chip, int addr, +static int nand_default_set_features(struct nand_chip *chip, int addr, uint8_t *subfeature_param) { return nand_set_features_op(chip, addr, subfeature_param); @@ -4860,13 +4854,11 @@ static int nand_default_set_features(struct mtd_info *mtd, /** * nand_default_get_features- [REPLACEABLE] get NAND chip features - * @mtd: MTD device structure * @chip: nand chip info structure * @addr: feature address. * @subfeature_param: the subfeature parameters, a four bytes array. */ -static int nand_default_get_features(struct mtd_info *mtd, - struct nand_chip *chip, int addr, +static int nand_default_get_features(struct nand_chip *chip, int addr, uint8_t *subfeature_param) { return nand_get_features_op(chip, addr, subfeature_param); @@ -4874,7 +4866,6 @@ static int nand_default_get_features(struct mtd_info *mtd, /** * nand_get_set_features_notsupp - set/get features stub returning -ENOTSUPP - * @mtd: MTD device structure * @chip: nand chip info structure * @addr: feature address. * @subfeature_param: the subfeature parameters, a four bytes array. @@ -4882,8 +4873,8 @@ static int nand_default_get_features(struct mtd_info *mtd, * Should be used by NAND controller drivers that do not support the SET/GET * FEATURES operations. */ -int nand_get_set_features_notsupp(struct mtd_info *mtd, struct nand_chip *chip, - int addr, u8 *subfeature_param) +int nand_get_set_features_notsupp(struct nand_chip *chip, int addr, + u8 *subfeature_param) { return -ENOTSUPP; } diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h index 8c8315d977de..7c639070c512 100644 --- a/include/linux/mtd/rawnand.h +++ b/include/linux/mtd/rawnand.h @@ -1299,10 +1299,10 @@ struct nand_chip { const struct nand_operation *op, bool check_only); int (*erase)(struct nand_chip *chip, int page); - int (*set_features)(struct mtd_info *mtd, struct nand_chip *chip, - int feature_addr, uint8_t *subfeature_para); - int (*get_features)(struct mtd_info *mtd, struct nand_chip *chip, - int feature_addr, uint8_t *subfeature_para); + int (*set_features)(struct nand_chip *chip, int feature_addr, + uint8_t *subfeature_para); + int (*get_features)(struct nand_chip *chip, int feature_addr, + uint8_t *subfeature_para); int (*setup_read_retry)(struct mtd_info *mtd, int retry_mode); int (*setup_data_interface)(struct mtd_info *mtd, int chipnr, const struct nand_data_interface *conf); @@ -1681,8 +1681,8 @@ int nand_read_oob_syndrome(struct nand_chip *chip, int page); int nand_get_features(struct nand_chip *chip, int addr, u8 *subfeature_param); int nand_set_features(struct nand_chip *chip, int addr, u8 *subfeature_param); /* Stub used by drivers that do not support GET/SET FEATURES operations */ -int nand_get_set_features_notsupp(struct mtd_info *mtd, struct nand_chip *chip, - int addr, u8 *subfeature_param); +int nand_get_set_features_notsupp(struct nand_chip *chip, int addr, + u8 *subfeature_param); /* Default read_page_raw implementation */ int nand_read_page_raw(struct nand_chip *chip, uint8_t *buf, int oob_required, From 2e7f1cec271c209128d0535e0cc1c49d3cf03624 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Thu, 6 Sep 2018 14:05:32 +0200 Subject: [PATCH 260/302] mtd: rawnand: Pass a nand_chip object to chip->setup_read_retry() Let's make the raw NAND API consistent by patching all helpers and hooks to take a nand_chip object instead of an mtd_info one or remove the mtd_info object when both are passed. Let's tackle the chip->setup_read_retry() hook. Signed-off-by: Boris Brezillon Signed-off-by: Miquel Raynal --- drivers/mtd/nand/raw/nand_base.c | 12 +++++------- drivers/mtd/nand/raw/nand_hynix.c | 3 +-- drivers/mtd/nand/raw/nand_micron.c | 3 +-- include/linux/mtd/rawnand.h | 2 +- 4 files changed, 8 insertions(+), 12 deletions(-) diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c index 0ae597ced5b4..a7575aa68c48 100644 --- a/drivers/mtd/nand/raw/nand_base.c +++ b/drivers/mtd/nand/raw/nand_base.c @@ -3475,17 +3475,15 @@ static uint8_t *nand_transfer_oob(struct mtd_info *mtd, uint8_t *oob, /** * nand_setup_read_retry - [INTERN] Set the READ RETRY mode - * @mtd: MTD device structure + * @chip: NAND chip object * @retry_mode: the retry mode to use * * Some vendors supply a special command to shift the Vt threshold, to be used * when there are too many bitflips in a page (i.e., ECC error). After setting * a new threshold, the host should retry reading the page. */ -static int nand_setup_read_retry(struct mtd_info *mtd, int retry_mode) +static int nand_setup_read_retry(struct nand_chip *chip, int retry_mode) { - struct nand_chip *chip = mtd_to_nand(mtd); - pr_debug("setting READ RETRY mode %d\n", retry_mode); if (retry_mode >= chip->read_retries) @@ -3494,7 +3492,7 @@ static int nand_setup_read_retry(struct mtd_info *mtd, int retry_mode) if (!chip->setup_read_retry) return -EOPNOTSUPP; - return chip->setup_read_retry(mtd, retry_mode); + return chip->setup_read_retry(chip, retry_mode); } static void nand_wait_readrdy(struct nand_chip *chip) @@ -3619,7 +3617,7 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from, if (mtd->ecc_stats.failed - ecc_failures) { if (retry_mode + 1 < chip->read_retries) { retry_mode++; - ret = nand_setup_read_retry(mtd, + ret = nand_setup_read_retry(chip, retry_mode); if (ret < 0) break; @@ -3646,7 +3644,7 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from, /* Reset to retry mode 0 */ if (retry_mode) { - ret = nand_setup_read_retry(mtd, 0); + ret = nand_setup_read_retry(chip, 0); if (ret < 0) break; retry_mode = 0; diff --git a/drivers/mtd/nand/raw/nand_hynix.c b/drivers/mtd/nand/raw/nand_hynix.c index fa873e517131..bb1c4f8ce785 100644 --- a/drivers/mtd/nand/raw/nand_hynix.c +++ b/drivers/mtd/nand/raw/nand_hynix.c @@ -113,9 +113,8 @@ static int hynix_nand_reg_write_op(struct nand_chip *chip, u8 addr, u8 val) return 0; } -static int hynix_nand_setup_read_retry(struct mtd_info *mtd, int retry_mode) +static int hynix_nand_setup_read_retry(struct nand_chip *chip, int retry_mode) { - struct nand_chip *chip = mtd_to_nand(mtd); struct hynix_nand *hynix = nand_get_manufacturer_data(chip); const u8 *values; int i, ret; diff --git a/drivers/mtd/nand/raw/nand_micron.c b/drivers/mtd/nand/raw/nand_micron.c index 2f26dbeb5428..1a5505ccbe54 100644 --- a/drivers/mtd/nand/raw/nand_micron.c +++ b/drivers/mtd/nand/raw/nand_micron.c @@ -74,9 +74,8 @@ struct micron_nand { struct micron_on_die_ecc ecc; }; -static int micron_nand_setup_read_retry(struct mtd_info *mtd, int retry_mode) +static int micron_nand_setup_read_retry(struct nand_chip *chip, int retry_mode) { - struct nand_chip *chip = mtd_to_nand(mtd); u8 feature[ONFI_SUBFEATURE_PARAM_LEN] = {retry_mode}; return nand_set_features(chip, ONFI_FEATURE_ADDR_READ_RETRY, feature); diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h index 7c639070c512..14ce2b078206 100644 --- a/include/linux/mtd/rawnand.h +++ b/include/linux/mtd/rawnand.h @@ -1303,7 +1303,7 @@ struct nand_chip { uint8_t *subfeature_para); int (*get_features)(struct nand_chip *chip, int feature_addr, uint8_t *subfeature_para); - int (*setup_read_retry)(struct mtd_info *mtd, int retry_mode); + int (*setup_read_retry)(struct nand_chip *chip, int retry_mode); int (*setup_data_interface)(struct mtd_info *mtd, int chipnr, const struct nand_data_interface *conf); From 858838b87ef542c35b5401a6469d162d103d1d8f Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Thu, 6 Sep 2018 14:05:33 +0200 Subject: [PATCH 261/302] mtd: rawnand: Pass a nand_chip object to chip->setup_data_interface() Let's make the raw NAND API consistent by patching all helpers and hooks to take a nand_chip object instead of an mtd_info one or remove the mtd_info object when both are passed. Let's tackle the chip->setup_data_interface() hook. Signed-off-by: Boris Brezillon Signed-off-by: Miquel Raynal --- drivers/mtd/nand/raw/atmel/nand-controller.c | 3 +-- drivers/mtd/nand/raw/denali.c | 4 ++-- drivers/mtd/nand/raw/fsmc_nand.c | 3 +-- drivers/mtd/nand/raw/gpmi-nand/gpmi-lib.c | 3 +-- drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.h | 2 +- drivers/mtd/nand/raw/marvell_nand.c | 3 +-- drivers/mtd/nand/raw/mtk_nand.c | 4 ++-- drivers/mtd/nand/raw/mxc_nand.c | 7 +++---- drivers/mtd/nand/raw/nand_base.c | 9 +++------ drivers/mtd/nand/raw/s3c2410.c | 3 ++- drivers/mtd/nand/raw/sunxi_nand.c | 3 +-- drivers/mtd/nand/raw/tango_nand.c | 3 +-- drivers/mtd/nand/raw/tegra_nand.c | 3 +-- include/linux/mtd/rawnand.h | 2 +- 14 files changed, 21 insertions(+), 31 deletions(-) diff --git a/drivers/mtd/nand/raw/atmel/nand-controller.c b/drivers/mtd/nand/raw/atmel/nand-controller.c index d5939114f999..a38633a67ead 100644 --- a/drivers/mtd/nand/raw/atmel/nand-controller.c +++ b/drivers/mtd/nand/raw/atmel/nand-controller.c @@ -1448,10 +1448,9 @@ static int atmel_hsmc_nand_setup_data_interface(struct atmel_nand *nand, return 0; } -static int atmel_nand_setup_data_interface(struct mtd_info *mtd, int csline, +static int atmel_nand_setup_data_interface(struct nand_chip *chip, int csline, const struct nand_data_interface *conf) { - struct nand_chip *chip = mtd_to_nand(mtd); struct atmel_nand *nand = to_atmel_nand(chip); struct atmel_nand_controller *nc; diff --git a/drivers/mtd/nand/raw/denali.c b/drivers/mtd/nand/raw/denali.c index bb4ad3b822ad..c5e35461d6b3 100644 --- a/drivers/mtd/nand/raw/denali.c +++ b/drivers/mtd/nand/raw/denali.c @@ -932,10 +932,10 @@ static int denali_erase(struct nand_chip *chip, int page) return irq_status & INTR__ERASE_COMP ? 0 : -EIO; } -static int denali_setup_data_interface(struct mtd_info *mtd, int chipnr, +static int denali_setup_data_interface(struct nand_chip *chip, int chipnr, const struct nand_data_interface *conf) { - struct denali_nand_info *denali = mtd_to_denali(mtd); + struct denali_nand_info *denali = mtd_to_denali(nand_to_mtd(chip)); const struct nand_sdr_timings *timings; unsigned long t_x, mult_x; int acc_clks, re_2_we, re_2_re, we_2_re, addr_2_data; diff --git a/drivers/mtd/nand/raw/fsmc_nand.c b/drivers/mtd/nand/raw/fsmc_nand.c index 15bf533c907a..5e06fce4b295 100644 --- a/drivers/mtd/nand/raw/fsmc_nand.c +++ b/drivers/mtd/nand/raw/fsmc_nand.c @@ -340,10 +340,9 @@ static int fsmc_calc_timings(struct fsmc_nand_data *host, return 0; } -static int fsmc_setup_data_interface(struct mtd_info *mtd, int csline, +static int fsmc_setup_data_interface(struct nand_chip *nand, int csline, const struct nand_data_interface *conf) { - struct nand_chip *nand = mtd_to_nand(mtd); struct fsmc_nand_data *host = nand_get_controller_data(nand); struct fsmc_nand_timings tims; const struct nand_sdr_timings *sdrt; diff --git a/drivers/mtd/nand/raw/gpmi-nand/gpmi-lib.c b/drivers/mtd/nand/raw/gpmi-nand/gpmi-lib.c index 88ea2203e263..bd4cfac6b5aa 100644 --- a/drivers/mtd/nand/raw/gpmi-nand/gpmi-lib.c +++ b/drivers/mtd/nand/raw/gpmi-nand/gpmi-lib.c @@ -471,10 +471,9 @@ void gpmi_nfc_apply_timings(struct gpmi_nand_data *this) udelay(dll_wait_time_us); } -int gpmi_setup_data_interface(struct mtd_info *mtd, int chipnr, +int gpmi_setup_data_interface(struct nand_chip *chip, int chipnr, const struct nand_data_interface *conf) { - struct nand_chip *chip = mtd_to_nand(mtd); struct gpmi_nand_data *this = nand_get_controller_data(chip); const struct nand_sdr_timings *sdr; diff --git a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.h b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.h index 69cd0cbde4f2..d0b79bac2728 100644 --- a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.h +++ b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.h @@ -178,7 +178,7 @@ int gpmi_is_ready(struct gpmi_nand_data *, unsigned chip); int gpmi_send_command(struct gpmi_nand_data *); int gpmi_enable_clk(struct gpmi_nand_data *this); int gpmi_disable_clk(struct gpmi_nand_data *this); -int gpmi_setup_data_interface(struct mtd_info *mtd, int chipnr, +int gpmi_setup_data_interface(struct nand_chip *chip, int chipnr, const struct nand_data_interface *conf); void gpmi_nfc_apply_timings(struct gpmi_nand_data *this); int gpmi_read_data(struct gpmi_nand_data *, void *buf, int len); diff --git a/drivers/mtd/nand/raw/marvell_nand.c b/drivers/mtd/nand/raw/marvell_nand.c index 1f4e75f8fa3e..22481e9bfefc 100644 --- a/drivers/mtd/nand/raw/marvell_nand.c +++ b/drivers/mtd/nand/raw/marvell_nand.c @@ -2250,11 +2250,10 @@ static struct nand_bbt_descr bbt_mirror_descr = { .pattern = bbt_mirror_pattern }; -static int marvell_nfc_setup_data_interface(struct mtd_info *mtd, int chipnr, +static int marvell_nfc_setup_data_interface(struct nand_chip *chip, int chipnr, const struct nand_data_interface *conf) { - struct nand_chip *chip = mtd_to_nand(mtd); struct marvell_nand_chip *marvell_nand = to_marvell_nand(chip); struct marvell_nfc *nfc = to_marvell_nfc(chip->controller); unsigned int period_ns = 1000000000 / clk_get_rate(nfc->core_clk) * 2; diff --git a/drivers/mtd/nand/raw/mtk_nand.c b/drivers/mtd/nand/raw/mtk_nand.c index cf8c42fb8feb..42f9dc2cd172 100644 --- a/drivers/mtd/nand/raw/mtk_nand.c +++ b/drivers/mtd/nand/raw/mtk_nand.c @@ -503,10 +503,10 @@ static void mtk_nfc_write_buf(struct nand_chip *chip, const u8 *buf, int len) mtk_nfc_write_byte(chip, buf[i]); } -static int mtk_nfc_setup_data_interface(struct mtd_info *mtd, int csline, +static int mtk_nfc_setup_data_interface(struct nand_chip *chip, int csline, const struct nand_data_interface *conf) { - struct mtk_nfc *nfc = nand_get_controller_data(mtd_to_nand(mtd)); + struct mtk_nfc *nfc = nand_get_controller_data(chip); const struct nand_sdr_timings *timings; u32 rate, tpoecs, tprecs, tc2r, tw2r, twh, twst, trlt; diff --git a/drivers/mtd/nand/raw/mxc_nand.c b/drivers/mtd/nand/raw/mxc_nand.c index ec150e19a368..895f85ee29db 100644 --- a/drivers/mtd/nand/raw/mxc_nand.c +++ b/drivers/mtd/nand/raw/mxc_nand.c @@ -137,7 +137,7 @@ struct mxc_nand_devtype_data { u32 (*get_ecc_status)(struct mxc_nand_host *); const struct mtd_ooblayout_ops *ooblayout; void (*select_chip)(struct nand_chip *chip, int cs); - int (*setup_data_interface)(struct mtd_info *mtd, int csline, + int (*setup_data_interface)(struct nand_chip *chip, int csline, const struct nand_data_interface *conf); void (*enable_hwecc)(struct nand_chip *chip, bool enable); @@ -1139,11 +1139,10 @@ static void preset_v1(struct mtd_info *mtd) writew(0x4, NFC_V1_V2_WRPROT); } -static int mxc_nand_v2_setup_data_interface(struct mtd_info *mtd, int csline, +static int mxc_nand_v2_setup_data_interface(struct nand_chip *chip, int csline, const struct nand_data_interface *conf) { - struct nand_chip *nand_chip = mtd_to_nand(mtd); - struct mxc_nand_host *host = nand_get_controller_data(nand_chip); + struct mxc_nand_host *host = nand_get_controller_data(chip); int tRC_min_ns, tRC_ps, ret; unsigned long rate, rate_round; const struct nand_sdr_timings *timings; diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c index a7575aa68c48..0a89ab663728 100644 --- a/drivers/mtd/nand/raw/nand_base.c +++ b/drivers/mtd/nand/raw/nand_base.c @@ -1200,7 +1200,6 @@ EXPORT_SYMBOL_GPL(nand_set_features); */ static int nand_reset_data_interface(struct nand_chip *chip, int chipnr) { - struct mtd_info *mtd = nand_to_mtd(chip); int ret; if (!chip->setup_data_interface) @@ -1221,7 +1220,7 @@ static int nand_reset_data_interface(struct nand_chip *chip, int chipnr) */ onfi_fill_data_interface(chip, NAND_SDR_IFACE, 0); - ret = chip->setup_data_interface(mtd, chipnr, &chip->data_interface); + ret = chip->setup_data_interface(chip, chipnr, &chip->data_interface); if (ret) pr_err("Failed to configure data interface to SDR timing mode 0\n"); @@ -1243,7 +1242,6 @@ static int nand_reset_data_interface(struct nand_chip *chip, int chipnr) */ static int nand_setup_data_interface(struct nand_chip *chip, int chipnr) { - struct mtd_info *mtd = nand_to_mtd(chip); u8 tmode_param[ONFI_SUBFEATURE_PARAM_LEN] = { chip->onfi_timing_mode_default, }; @@ -1263,7 +1261,7 @@ static int nand_setup_data_interface(struct nand_chip *chip, int chipnr) } /* Change the mode on the controller side */ - ret = chip->setup_data_interface(mtd, chipnr, &chip->data_interface); + ret = chip->setup_data_interface(chip, chipnr, &chip->data_interface); if (ret) return ret; @@ -1316,7 +1314,6 @@ static int nand_setup_data_interface(struct nand_chip *chip, int chipnr) */ static int nand_init_data_interface(struct nand_chip *chip) { - struct mtd_info *mtd = nand_to_mtd(chip); int modes, mode, ret; if (!chip->setup_data_interface) @@ -1345,7 +1342,7 @@ static int nand_init_data_interface(struct nand_chip *chip) * Pass NAND_DATA_IFACE_CHECK_ONLY to only check if the * controller supports the requested timings. */ - ret = chip->setup_data_interface(mtd, + ret = chip->setup_data_interface(chip, NAND_DATA_IFACE_CHECK_ONLY, &chip->data_interface); if (!ret) { diff --git a/drivers/mtd/nand/raw/s3c2410.c b/drivers/mtd/nand/raw/s3c2410.c index 1d549f5e53f5..1f70eb35320b 100644 --- a/drivers/mtd/nand/raw/s3c2410.c +++ b/drivers/mtd/nand/raw/s3c2410.c @@ -820,9 +820,10 @@ static int s3c2410_nand_add_partition(struct s3c2410_nand_info *info, return -ENODEV; } -static int s3c2410_nand_setup_data_interface(struct mtd_info *mtd, int csline, +static int s3c2410_nand_setup_data_interface(struct nand_chip *chip, int csline, const struct nand_data_interface *conf) { + struct mtd_info *mtd = nand_to_mtd(chip); struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd); struct s3c2410_platform_nand *pdata = info->platform; const struct nand_sdr_timings *timings; diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c index fe30fb589ffb..a3700b79bdeb 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -1468,10 +1468,9 @@ static int _sunxi_nand_lookup_timing(const s32 *lut, int lut_size, u32 duration, #define sunxi_nand_lookup_timing(l, p, c) \ _sunxi_nand_lookup_timing(l, ARRAY_SIZE(l), p, c) -static int sunxi_nfc_setup_data_interface(struct mtd_info *mtd, int csline, +static int sunxi_nfc_setup_data_interface(struct nand_chip *nand, int csline, const struct nand_data_interface *conf) { - struct nand_chip *nand = mtd_to_nand(mtd); struct sunxi_nand_chip *chip = to_sunxi_nand(nand); struct sunxi_nfc *nfc = to_sunxi_nfc(chip->nand.controller); const struct nand_sdr_timings *timings; diff --git a/drivers/mtd/nand/raw/tango_nand.c b/drivers/mtd/nand/raw/tango_nand.c index c21a0f2d26fc..bf7012099790 100644 --- a/drivers/mtd/nand/raw/tango_nand.c +++ b/drivers/mtd/nand/raw/tango_nand.c @@ -479,11 +479,10 @@ static u32 to_ticks(int kHz, int ps) return DIV_ROUND_UP_ULL((u64)kHz * ps, NSEC_PER_SEC); } -static int tango_set_timings(struct mtd_info *mtd, int csline, +static int tango_set_timings(struct nand_chip *chip, int csline, const struct nand_data_interface *conf) { const struct nand_sdr_timings *sdr = nand_get_sdr_timings(conf); - struct nand_chip *chip = mtd_to_nand(mtd); struct tango_nfc *nfc = to_tango_nfc(chip->controller); struct tango_chip *tchip = to_tango_chip(chip); u32 Trdy, Textw, Twc, Twpw, Tacc, Thold, Trpw, Textr; diff --git a/drivers/mtd/nand/raw/tegra_nand.c b/drivers/mtd/nand/raw/tegra_nand.c index 1088741eed1d..9767e29d74e2 100644 --- a/drivers/mtd/nand/raw/tegra_nand.c +++ b/drivers/mtd/nand/raw/tegra_nand.c @@ -814,10 +814,9 @@ static void tegra_nand_setup_timing(struct tegra_nand_controller *ctrl, writel_relaxed(reg, ctrl->regs + TIMING_2); } -static int tegra_nand_setup_data_interface(struct mtd_info *mtd, int csline, +static int tegra_nand_setup_data_interface(struct nand_chip *chip, int csline, const struct nand_data_interface *conf) { - struct nand_chip *chip = mtd_to_nand(mtd); struct tegra_nand_controller *ctrl = to_tegra_ctrl(chip->controller); const struct nand_sdr_timings *timings; diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h index 14ce2b078206..5bfb9d543a8a 100644 --- a/include/linux/mtd/rawnand.h +++ b/include/linux/mtd/rawnand.h @@ -1304,7 +1304,7 @@ struct nand_chip { int (*get_features)(struct nand_chip *chip, int feature_addr, uint8_t *subfeature_para); int (*setup_read_retry)(struct nand_chip *chip, int retry_mode); - int (*setup_data_interface)(struct mtd_info *mtd, int chipnr, + int (*setup_data_interface)(struct nand_chip *chip, int chipnr, const struct nand_data_interface *conf); int chip_delay; From 5740d4c4f9bbc97270993147b4756587f92d44c3 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Thu, 6 Sep 2018 14:05:34 +0200 Subject: [PATCH 262/302] mtd: rawnand: Pass a nand_chip object to all nand_xxx_bbt() helpers Let's make the raw NAND API consistent by patching all helpers and hooks to take a nand_chip object instead of an mtd_info one or remove the mtd_info object when both are passed. Let's tackle the nand_xxx_bbt() helpers. Signed-off-by: Boris Brezillon Signed-off-by: Miquel Raynal --- drivers/mtd/nand/raw/nand_base.c | 6 +++--- drivers/mtd/nand/raw/nand_bbt.c | 16 +++++++--------- include/linux/mtd/rawnand.h | 6 +++--- 3 files changed, 13 insertions(+), 15 deletions(-) diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c index 0a89ab663728..074de0c8c9dc 100644 --- a/drivers/mtd/nand/raw/nand_base.c +++ b/drivers/mtd/nand/raw/nand_base.c @@ -515,7 +515,7 @@ static int nand_block_markbad_lowlevel(struct mtd_info *mtd, loff_t ofs) /* Mark block bad in BBT */ if (chip->bbt) { - res = nand_markbad_bbt(mtd, ofs); + res = nand_markbad_bbt(chip, ofs); if (!ret) ret = res; } @@ -565,7 +565,7 @@ static int nand_block_isreserved(struct mtd_info *mtd, loff_t ofs) if (!chip->bbt) return 0; /* Return info from the table */ - return nand_isreserved_bbt(mtd, ofs); + return nand_isreserved_bbt(chip, ofs); } /** @@ -585,7 +585,7 @@ static int nand_block_checkbad(struct mtd_info *mtd, loff_t ofs, int allowbbt) return chip->block_bad(chip, ofs); /* Return info from the table */ - return nand_isbad_bbt(mtd, ofs, allowbbt); + return nand_isbad_bbt(chip, ofs, allowbbt); } /** diff --git a/drivers/mtd/nand/raw/nand_bbt.c b/drivers/mtd/nand/raw/nand_bbt.c index 76849a441518..7424be0547f8 100644 --- a/drivers/mtd/nand/raw/nand_bbt.c +++ b/drivers/mtd/nand/raw/nand_bbt.c @@ -1387,12 +1387,11 @@ EXPORT_SYMBOL(nand_create_bbt); /** * nand_isreserved_bbt - [NAND Interface] Check if a block is reserved - * @mtd: MTD device structure + * @this: NAND chip object * @offs: offset in the device */ -int nand_isreserved_bbt(struct mtd_info *mtd, loff_t offs) +int nand_isreserved_bbt(struct nand_chip *this, loff_t offs) { - struct nand_chip *this = mtd_to_nand(mtd); int block; block = (int)(offs >> this->bbt_erase_shift); @@ -1401,13 +1400,12 @@ int nand_isreserved_bbt(struct mtd_info *mtd, loff_t offs) /** * nand_isbad_bbt - [NAND Interface] Check if a block is bad - * @mtd: MTD device structure + * @this: NAND chip object * @offs: offset in the device * @allowbbt: allow access to bad block table region */ -int nand_isbad_bbt(struct mtd_info *mtd, loff_t offs, int allowbbt) +int nand_isbad_bbt(struct nand_chip *this, loff_t offs, int allowbbt) { - struct nand_chip *this = mtd_to_nand(mtd); int block, res; block = (int)(offs >> this->bbt_erase_shift); @@ -1429,12 +1427,12 @@ int nand_isbad_bbt(struct mtd_info *mtd, loff_t offs, int allowbbt) /** * nand_markbad_bbt - [NAND Interface] Mark a block bad in the BBT - * @mtd: MTD device structure + * @this: NAND chip object * @offs: offset of the bad block */ -int nand_markbad_bbt(struct mtd_info *mtd, loff_t offs) +int nand_markbad_bbt(struct nand_chip *this, loff_t offs) { - struct nand_chip *this = mtd_to_nand(mtd); + struct mtd_info *mtd = nand_to_mtd(this); int block, ret = 0; block = (int)(offs >> this->bbt_erase_shift); diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h index 5bfb9d543a8a..e0d98ca7cb45 100644 --- a/include/linux/mtd/rawnand.h +++ b/include/linux/mtd/rawnand.h @@ -1545,9 +1545,9 @@ extern const struct nand_manufacturer_ops amd_nand_manuf_ops; extern const struct nand_manufacturer_ops macronix_nand_manuf_ops; int nand_create_bbt(struct nand_chip *chip); -int nand_markbad_bbt(struct mtd_info *mtd, loff_t offs); -int nand_isreserved_bbt(struct mtd_info *mtd, loff_t offs); -int nand_isbad_bbt(struct mtd_info *mtd, loff_t offs, int allowbbt); +int nand_markbad_bbt(struct nand_chip *chip, loff_t offs); +int nand_isreserved_bbt(struct nand_chip *chip, loff_t offs); +int nand_isbad_bbt(struct nand_chip *chip, loff_t offs, int allowbbt); int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr, int allowbbt); From e4cdf9cb3254b5b4d9b1064c275d8c40f2d82e03 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Thu, 6 Sep 2018 14:05:35 +0200 Subject: [PATCH 263/302] mtd: rawnand: Pass a nand_chip object nand_erase_nand() Let's make the raw NAND API consistent by patching all helpers and hooks to take a nand_chip object instead of an mtd_info one or remove the mtd_info object when both are passed. Let's tackle the nand_erase_nand() helper. Signed-off-by: Boris Brezillon Signed-off-by: Miquel Raynal --- drivers/mtd/nand/raw/nand_base.c | 10 +++++----- drivers/mtd/nand/raw/nand_bbt.c | 2 +- include/linux/mtd/rawnand.h | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c index 074de0c8c9dc..ef4d90ed896d 100644 --- a/drivers/mtd/nand/raw/nand_base.c +++ b/drivers/mtd/nand/raw/nand_base.c @@ -505,7 +505,7 @@ static int nand_block_markbad_lowlevel(struct mtd_info *mtd, loff_t ofs) memset(&einfo, 0, sizeof(einfo)); einfo.addr = ofs; einfo.len = 1ULL << chip->phys_erase_shift; - nand_erase_nand(mtd, &einfo, 0); + nand_erase_nand(chip, &einfo, 0); /* Write bad block marker to OOB */ nand_get_device(mtd, FL_WRITING); @@ -4638,22 +4638,22 @@ static int single_erase(struct nand_chip *chip, int page) */ static int nand_erase(struct mtd_info *mtd, struct erase_info *instr) { - return nand_erase_nand(mtd, instr, 0); + return nand_erase_nand(mtd_to_nand(mtd), instr, 0); } /** * nand_erase_nand - [INTERN] erase block(s) - * @mtd: MTD device structure + * @chip: NAND chip object * @instr: erase instruction * @allowbbt: allow erasing the bbt area * * Erase one ore more blocks. */ -int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr, +int nand_erase_nand(struct nand_chip *chip, struct erase_info *instr, int allowbbt) { + struct mtd_info *mtd = nand_to_mtd(chip); int page, status, pages_per_block, ret, chipnr; - struct nand_chip *chip = mtd_to_nand(mtd); loff_t len; pr_debug("%s: start = 0x%012llx, len = %llu\n", diff --git a/drivers/mtd/nand/raw/nand_bbt.c b/drivers/mtd/nand/raw/nand_bbt.c index 7424be0547f8..9d73e086c5de 100644 --- a/drivers/mtd/nand/raw/nand_bbt.c +++ b/drivers/mtd/nand/raw/nand_bbt.c @@ -853,7 +853,7 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf, memset(&einfo, 0, sizeof(einfo)); einfo.addr = to; einfo.len = 1 << this->bbt_erase_shift; - res = nand_erase_nand(mtd, &einfo, 1); + res = nand_erase_nand(this, &einfo, 1); if (res < 0) { pr_warn("nand_bbt: error while erasing BBT block %d\n", res); diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h index e0d98ca7cb45..e6360e1156e7 100644 --- a/include/linux/mtd/rawnand.h +++ b/include/linux/mtd/rawnand.h @@ -1548,7 +1548,7 @@ int nand_create_bbt(struct nand_chip *chip); int nand_markbad_bbt(struct nand_chip *chip, loff_t offs); int nand_isreserved_bbt(struct nand_chip *chip, loff_t offs); int nand_isbad_bbt(struct nand_chip *chip, loff_t offs, int allowbbt); -int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr, +int nand_erase_nand(struct nand_chip *chip, struct erase_info *instr, int allowbbt); /** From dbfc671856b349d702d94ccb96d38569991122cf Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Thu, 19 Jul 2018 16:54:23 +0200 Subject: [PATCH 264/302] mtd: rawnand: marvell: rework BCH engine failure path We are about to support a new layout that triggers a faulty mechanism in BCH engine that creates bitflips in erased pages. Before adding the quirk that will workaround this issue, this patch just reworks a bit the section that handles ECC failures in BCH read path. Signed-off-by: Miquel Raynal Reviewed-by: Boris Brezillon --- drivers/mtd/nand/raw/marvell_nand.c | 69 +++++++++++++++++------------ 1 file changed, 40 insertions(+), 29 deletions(-) diff --git a/drivers/mtd/nand/raw/marvell_nand.c b/drivers/mtd/nand/raw/marvell_nand.c index 22481e9bfefc..a08858cca804 100644 --- a/drivers/mtd/nand/raw/marvell_nand.c +++ b/drivers/mtd/nand/raw/marvell_nand.c @@ -1295,11 +1295,11 @@ static int marvell_nfc_hw_ecc_bch_read_page(struct nand_chip *chip, { struct mtd_info *mtd = nand_to_mtd(chip); const struct marvell_hw_ecc_layout *lt = to_marvell_nand(chip)->layout; - int data_len = lt->data_bytes, spare_len = lt->spare_bytes, ecc_len; - u8 *data = buf, *spare = chip->oob_poi, *ecc; + int data_len = lt->data_bytes, spare_len = lt->spare_bytes; + u8 *data = buf, *spare = chip->oob_poi; int max_bitflips = 0; u32 failure_mask = 0; - int chunk, ecc_offset_in_page, ret; + int chunk, ret; /* * With BCH, OOB is not fully used (and thus not read entirely), not @@ -1340,46 +1340,57 @@ static int marvell_nfc_hw_ecc_bch_read_page(struct nand_chip *chip, * the controller in normal mode and must be re-read in raw mode. To * avoid dropping the performances, we prefer not to include them. The * user should re-read the page in raw mode if ECC bytes are required. + */ + + /* + * In case there is any subpage read error reported by ->correct(), we + * usually re-read only ECC bytes in raw mode and check if the whole + * page is empty. In this case, it is normal that the ECC check failed + * and we just ignore the error. * * However, for any subpage read error reported by ->correct(), the ECC * bytes must be read in raw mode and the full subpage must be checked * to see if it is entirely empty of if there was an actual error. */ for (chunk = 0; chunk < lt->nchunks; chunk++) { + int data_off_in_page, spare_off_in_page, ecc_off_in_page; + int data_off, spare_off, ecc_off; + int data_len, spare_len, ecc_len; + /* No failure reported for this chunk, move to the next one */ if (!(failure_mask & BIT(chunk))) continue; - /* Derive ECC bytes positions (in page/buffer) and length */ - ecc = chip->oob_poi + - (lt->full_chunk_cnt * lt->spare_bytes) + - lt->last_spare_bytes + - (chunk * ALIGN(lt->ecc_bytes, 32)); - ecc_offset_in_page = - (chunk * (lt->data_bytes + lt->spare_bytes + - lt->ecc_bytes)) + - (chunk < lt->full_chunk_cnt ? - lt->data_bytes + lt->spare_bytes : - lt->last_data_bytes + lt->last_spare_bytes); - ecc_len = chunk < lt->full_chunk_cnt ? - lt->ecc_bytes : lt->last_ecc_bytes; + data_off_in_page = chunk * (lt->data_bytes + lt->spare_bytes + + lt->ecc_bytes); + spare_off_in_page = data_off_in_page + + (chunk < lt->full_chunk_cnt ? lt->data_bytes : + lt->last_data_bytes); + ecc_off_in_page = spare_off_in_page + + (chunk < lt->full_chunk_cnt ? lt->spare_bytes : + lt->last_spare_bytes); - /* Do the actual raw read of the ECC bytes */ - nand_change_read_column_op(chip, ecc_offset_in_page, - ecc, ecc_len, false); + data_off = chunk * lt->data_bytes; + spare_off = chunk * lt->spare_bytes; + ecc_off = (lt->full_chunk_cnt * lt->spare_bytes) + + lt->last_spare_bytes + + (chunk * (lt->ecc_bytes + 2)); - /* Derive data/spare bytes positions (in buffer) and length */ - data = buf + (chunk * lt->data_bytes); - data_len = chunk < lt->full_chunk_cnt ? - lt->data_bytes : lt->last_data_bytes; - spare = chip->oob_poi + (chunk * (lt->spare_bytes + - lt->ecc_bytes)); - spare_len = chunk < lt->full_chunk_cnt ? - lt->spare_bytes : lt->last_spare_bytes; + data_len = chunk < lt->full_chunk_cnt ? lt->data_bytes : + lt->last_data_bytes; + spare_len = chunk < lt->full_chunk_cnt ? lt->spare_bytes : + lt->last_spare_bytes; + ecc_len = chunk < lt->full_chunk_cnt ? lt->ecc_bytes : + lt->last_ecc_bytes; + + nand_change_read_column_op(chip, ecc_off_in_page, + chip->oob_poi + ecc_off, ecc_len, + false); /* Check the entire chunk (data + spare + ecc) for emptyness */ - marvell_nfc_check_empty_chunk(chip, data, data_len, spare, - spare_len, ecc, ecc_len, + marvell_nfc_check_empty_chunk(chip, buf + data_off, data_len, + chip->oob_poi + spare_off, spare_len, + chip->oob_poi + ecc_off, ecc_len, &max_bitflips); } From 7fd130f7416f1c67c2b976d42c1b64371c3a7bd2 Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Thu, 19 Jul 2018 12:21:19 +0200 Subject: [PATCH 265/302] mtd: rawnand: marvell: support 8b/512B strength for 2kiB pages layout Add support for the layout used by 2kiB page NAND chips requesting at least 8-bit of correction per 512 bytes. This layout requires a bit of handling as: 1/ It can only fit if the NAND chip has at least 128 OOB bytes. 2/ The Bad Block Markers are located in the middle of the data bytes and shall not be used. 3/ It has been experimentally observed that, for certain layouts, the ECC engine tries to correct data while it should not because the errors are uncorrectable. While this is harmless for truly bad pages, it creates bitflips in empty pages. To avoid such scenario that augments artificially the number of bitflips we re-read in raw mode the entire page instead of just the ECC bytes. This is done only for this layout to avoid an unneeded penalty with other setups. Signed-off-by: Miquel Raynal Reviewed-by: Boris Brezillon --- drivers/mtd/nand/raw/marvell_nand.c | 34 ++++++++++++++++++++++++++--- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/drivers/mtd/nand/raw/marvell_nand.c b/drivers/mtd/nand/raw/marvell_nand.c index a08858cca804..6639f2e2cea2 100644 --- a/drivers/mtd/nand/raw/marvell_nand.c +++ b/drivers/mtd/nand/raw/marvell_nand.c @@ -284,6 +284,7 @@ static const struct marvell_hw_ecc_layout marvell_nfc_layouts[] = { MARVELL_LAYOUT( 512, 512, 1, 1, 1, 512, 8, 8, 0, 0, 0), MARVELL_LAYOUT( 2048, 512, 1, 1, 1, 2048, 40, 24, 0, 0, 0), MARVELL_LAYOUT( 2048, 512, 4, 1, 1, 2048, 32, 30, 0, 0, 0), + MARVELL_LAYOUT( 2048, 512, 8, 2, 1, 1024, 0, 30,1024,32, 30), MARVELL_LAYOUT( 4096, 512, 4, 2, 2, 2048, 32, 30, 0, 0, 0), MARVELL_LAYOUT( 4096, 512, 8, 5, 4, 1024, 0, 30, 0, 64, 30), }; @@ -1348,9 +1349,11 @@ static int marvell_nfc_hw_ecc_bch_read_page(struct nand_chip *chip, * page is empty. In this case, it is normal that the ECC check failed * and we just ignore the error. * - * However, for any subpage read error reported by ->correct(), the ECC - * bytes must be read in raw mode and the full subpage must be checked - * to see if it is entirely empty of if there was an actual error. + * However, it has been empirically observed that for some layouts (e.g + * 2k page, 8b strength per 512B chunk), the controller tries to correct + * bits and may create itself bitflips in the erased area. To overcome + * this strange behavior, the whole page is re-read in raw mode, not + * only the ECC bytes. */ for (chunk = 0; chunk < lt->nchunks; chunk++) { int data_off_in_page, spare_off_in_page, ecc_off_in_page; @@ -1383,6 +1386,21 @@ static int marvell_nfc_hw_ecc_bch_read_page(struct nand_chip *chip, ecc_len = chunk < lt->full_chunk_cnt ? lt->ecc_bytes : lt->last_ecc_bytes; + /* + * Only re-read the ECC bytes, unless we are using the 2k/8b + * layout which is buggy in the sense that the ECC engine will + * try to correct data bytes anyway, creating bitflips. In this + * case, re-read the entire page. + */ + if (lt->writesize == 2048 && lt->strength == 8) { + nand_change_read_column_op(chip, data_off_in_page, + buf + data_off, data_len, + false); + nand_change_read_column_op(chip, spare_off_in_page, + chip->oob_poi + spare_off, spare_len, + false); + } + nand_change_read_column_op(chip, ecc_off_in_page, chip->oob_poi + ecc_off, ecc_len, false); @@ -2166,6 +2184,16 @@ static int marvell_nand_hw_ecc_ctrl_init(struct mtd_info *mtd, return -ENOTSUPP; } + /* Special care for the layout 2k/8-bit/512B */ + if (l->writesize == 2048 && l->strength == 8) { + if (mtd->oobsize < 128) { + dev_err(nfc->dev, "Requested layout needs at least 128 OOB bytes\n"); + return -ENOTSUPP; + } else { + chip->bbt_options |= NAND_BBT_NO_OOB_BBM; + } + } + mtd_set_ooblayout(mtd, &marvell_nand_ooblayout_ops); ecc->steps = l->nchunks; ecc->size = l->data_bytes; From 64ddd5d8578f4bd431c3978437cf746bae35756b Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Sat, 4 Aug 2018 22:59:20 +0200 Subject: [PATCH 266/302] mtd: rawnand: Remove docg4 The diskonchip G4 driver does not fit very well in the raw/parallel NAND framework simply because such chips have an internal controller translating DoC-specific commands into NAND ones. Keeping such a driver in the raw NAND framework is a real burden for NAND maintainers. Not to mention that some parts of this driver are a bit worrisome: - writes are done by subpages, even though we're interfacing with an MLC chip which are known to not support subpage writes very well (it might be that the FTL handles the complexity for us though) - some part of the code are simply ignoring return codes of function that can fail in a few occasions - there's a hack to support OOB writes when no data is provided. This operation is not supported by the chip and should have been rejected, and nandwrite and other userspace tools should have been patched to deal with such devices - the driver is apparently broken when ignore_badblocks module param is not set to 1 and nobody noticed that (don't know since when this is the case, but it's not a recent change) http://lists.infradead.org/pipermail/linux-mtd/2018-July/082472.html Add to that the fact that we already have a docg3 driver in drivers/mtd/devices/docg3.c and, looking at the code (and regs), it seems docg3 and docg4 have a lot in common (even the author of this driver seemed to have realized that interfacing with the raw NAND framework might have been a bad idea http://lists.infradead.org/pipermail/linux-mtd/2012-January/039517.html). For all these reasons, I'm proposing to remove this driver. If anyone ever wants to add support for this chip back, I'd suggest extending the docg3 driver instead of adding a completely new driver. Signed-off-by: Boris Brezillon Cc: Mike Dunn Cc: Robert Jarzmik Cc: Sergey Larin Signed-off-by: Miquel Raynal --- drivers/mtd/nand/raw/Kconfig | 20 - drivers/mtd/nand/raw/Makefile | 1 - drivers/mtd/nand/raw/docg4.c | 1437 --------------------------------- 3 files changed, 1458 deletions(-) delete mode 100644 drivers/mtd/nand/raw/docg4.c diff --git a/drivers/mtd/nand/raw/Kconfig b/drivers/mtd/nand/raw/Kconfig index 5fc9a1bde4ac..c7efc31384d5 100644 --- a/drivers/mtd/nand/raw/Kconfig +++ b/drivers/mtd/nand/raw/Kconfig @@ -227,26 +227,6 @@ config MTD_NAND_DISKONCHIP_BBTWRITE load time (assuming you build diskonchip as a module) with the module parameter "inftl_bbt_write=1". -config MTD_NAND_DOCG4 - tristate "Support for DiskOnChip G4" - depends on HAS_IOMEM - select BCH - select BITREVERSE - help - Support for diskonchip G4 nand flash, found in various smartphones and - PDAs, among them the Palm Treo680, HTC Prophet and Wizard, Toshiba - Portege G900, Asus P526, and O2 XDA Zinc. - - With this driver you will be able to use UBI and create a ubifs on the - device, so you may wish to consider enabling UBI and UBIFS as well. - - These devices ship with the Mys/Sandisk SAFTL formatting, for which - there is currently no mtd parser, so you may want to use command line - partitioning to segregate write-protected blocks. On the Treo680, the - first five erase blocks (256KiB each) are write-protected, followed - by the block containing the saftl partition table. This is probably - typical. - config MTD_NAND_SHARPSL tristate "Support for NAND Flash on Sharp SL Series (C7xx + others)" depends on ARCH_PXA || COMPILE_TEST diff --git a/drivers/mtd/nand/raw/Makefile b/drivers/mtd/nand/raw/Makefile index d5a5f9832b88..a6ef0673e29e 100644 --- a/drivers/mtd/nand/raw/Makefile +++ b/drivers/mtd/nand/raw/Makefile @@ -15,7 +15,6 @@ obj-$(CONFIG_MTD_NAND_S3C2410) += s3c2410.o obj-$(CONFIG_MTD_NAND_TANGO) += tango_nand.o obj-$(CONFIG_MTD_NAND_DAVINCI) += davinci_nand.o obj-$(CONFIG_MTD_NAND_DISKONCHIP) += diskonchip.o -obj-$(CONFIG_MTD_NAND_DOCG4) += docg4.o obj-$(CONFIG_MTD_NAND_FSMC) += fsmc_nand.o obj-$(CONFIG_MTD_NAND_SHARPSL) += sharpsl.o obj-$(CONFIG_MTD_NAND_NANDSIM) += nandsim.o diff --git a/drivers/mtd/nand/raw/docg4.c b/drivers/mtd/nand/raw/docg4.c deleted file mode 100644 index 49500cae3d2f..000000000000 --- a/drivers/mtd/nand/raw/docg4.c +++ /dev/null @@ -1,1437 +0,0 @@ -/* - * Copyright © 2012 Mike Dunn - * - * mtd nand driver for M-Systems DiskOnChip G4 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * Tested on the Palm Treo 680. The G4 is also present on Toshiba Portege, Asus - * P526, some HTC smartphones (Wizard, Prophet, ...), O2 XDA Zinc, maybe others. - * Should work on these as well. Let me know! - * - * TODO: - * - * Mechanism for management of password-protected areas - * - * Hamming ecc when reading oob only - * - * According to the M-Sys documentation, this device is also available in a - * "dual-die" configuration having a 256MB capacity, but no mechanism for - * detecting this variant is documented. Currently this driver assumes 128MB - * capacity. - * - * Support for multiple cascaded devices ("floors"). Not sure which gadgets - * contain multiple G4s in a cascaded configuration, if any. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * In "reliable mode" consecutive 2k pages are used in parallel (in some - * fashion) to store the same data. The data can be read back from the - * even-numbered pages in the normal manner; odd-numbered pages will appear to - * contain junk. Systems that boot from the docg4 typically write the secondary - * program loader (SPL) code in this mode. The SPL is loaded by the initial - * program loader (IPL, stored in the docg4's 2k NOR-like region that is mapped - * to the reset vector address). This module parameter enables you to use this - * driver to write the SPL. When in this mode, no more than 2k of data can be - * written at a time, because the addresses do not increment in the normal - * manner, and the starting offset must be within an even-numbered 2k region; - * i.e., invalid starting offsets are 0x800, 0xa00, 0xc00, 0xe00, 0x1800, - * 0x1a00, ... Reliable mode is a special case and should not be used unless - * you know what you're doing. - */ -static bool reliable_mode; -module_param(reliable_mode, bool, 0); -MODULE_PARM_DESC(reliable_mode, "pages are programmed in reliable mode"); - -/* - * You'll want to ignore badblocks if you're reading a partition that contains - * data written by the TrueFFS library (i.e., by PalmOS, Windows, etc), since - * it does not use mtd nand's method for marking bad blocks (using oob area). - * This will also skip the check of the "page written" flag. - */ -static bool ignore_badblocks; -module_param(ignore_badblocks, bool, 0); -MODULE_PARM_DESC(ignore_badblocks, "no badblock checking performed"); - -struct docg4_priv { - struct mtd_info *mtd; - struct device *dev; - void __iomem *virtadr; - int status; - struct { - unsigned int command; - int column; - int page; - } last_command; - uint8_t oob_buf[16]; - uint8_t ecc_buf[7]; - int oob_page; - struct bch_control *bch; -}; - -/* - * Defines prefixed with DOCG4 are unique to the diskonchip G4. All others are - * shared with other diskonchip devices (P3, G3 at least). - * - * Functions with names prefixed with docg4_ are mtd / nand interface functions - * (though they may also be called internally). All others are internal. - */ - -#define DOC_IOSPACE_DATA 0x0800 - -/* register offsets */ -#define DOC_CHIPID 0x1000 -#define DOC_DEVICESELECT 0x100a -#define DOC_ASICMODE 0x100c -#define DOC_DATAEND 0x101e -#define DOC_NOP 0x103e - -#define DOC_FLASHSEQUENCE 0x1032 -#define DOC_FLASHCOMMAND 0x1034 -#define DOC_FLASHADDRESS 0x1036 -#define DOC_FLASHCONTROL 0x1038 -#define DOC_ECCCONF0 0x1040 -#define DOC_ECCCONF1 0x1042 -#define DOC_HAMMINGPARITY 0x1046 -#define DOC_BCH_SYNDROM(idx) (0x1048 + idx) - -#define DOC_ASICMODECONFIRM 0x1072 -#define DOC_CHIPID_INV 0x1074 -#define DOC_POWERMODE 0x107c - -#define DOCG4_MYSTERY_REG 0x1050 - -/* apparently used only to write oob bytes 6 and 7 */ -#define DOCG4_OOB_6_7 0x1052 - -/* DOC_FLASHSEQUENCE register commands */ -#define DOC_SEQ_RESET 0x00 -#define DOCG4_SEQ_PAGE_READ 0x03 -#define DOCG4_SEQ_FLUSH 0x29 -#define DOCG4_SEQ_PAGEWRITE 0x16 -#define DOCG4_SEQ_PAGEPROG 0x1e -#define DOCG4_SEQ_BLOCKERASE 0x24 -#define DOCG4_SEQ_SETMODE 0x45 - -/* DOC_FLASHCOMMAND register commands */ -#define DOCG4_CMD_PAGE_READ 0x00 -#define DOC_CMD_ERASECYCLE2 0xd0 -#define DOCG4_CMD_FLUSH 0x70 -#define DOCG4_CMD_READ2 0x30 -#define DOC_CMD_PROG_BLOCK_ADDR 0x60 -#define DOCG4_CMD_PAGEWRITE 0x80 -#define DOC_CMD_PROG_CYCLE2 0x10 -#define DOCG4_CMD_FAST_MODE 0xa3 /* functionality guessed */ -#define DOC_CMD_RELIABLE_MODE 0x22 -#define DOC_CMD_RESET 0xff - -/* DOC_POWERMODE register bits */ -#define DOC_POWERDOWN_READY 0x80 - -/* DOC_FLASHCONTROL register bits */ -#define DOC_CTRL_CE 0x10 -#define DOC_CTRL_UNKNOWN 0x40 -#define DOC_CTRL_FLASHREADY 0x01 - -/* DOC_ECCCONF0 register bits */ -#define DOC_ECCCONF0_READ_MODE 0x8000 -#define DOC_ECCCONF0_UNKNOWN 0x2000 -#define DOC_ECCCONF0_ECC_ENABLE 0x1000 -#define DOC_ECCCONF0_DATA_BYTES_MASK 0x07ff - -/* DOC_ECCCONF1 register bits */ -#define DOC_ECCCONF1_BCH_SYNDROM_ERR 0x80 -#define DOC_ECCCONF1_ECC_ENABLE 0x07 -#define DOC_ECCCONF1_PAGE_IS_WRITTEN 0x20 - -/* DOC_ASICMODE register bits */ -#define DOC_ASICMODE_RESET 0x00 -#define DOC_ASICMODE_NORMAL 0x01 -#define DOC_ASICMODE_POWERDOWN 0x02 -#define DOC_ASICMODE_MDWREN 0x04 -#define DOC_ASICMODE_BDETCT_RESET 0x08 -#define DOC_ASICMODE_RSTIN_RESET 0x10 -#define DOC_ASICMODE_RAM_WE 0x20 - -/* good status values read after read/write/erase operations */ -#define DOCG4_PROGSTATUS_GOOD 0x51 -#define DOCG4_PROGSTATUS_GOOD_2 0xe0 - -/* - * On read operations (page and oob-only), the first byte read from I/O reg is a - * status. On error, it reads 0x73; otherwise, it reads either 0x71 (first read - * after reset only) or 0x51, so bit 1 is presumed to be an error indicator. - */ -#define DOCG4_READ_ERROR 0x02 /* bit 1 indicates read error */ - -/* anatomy of the device */ -#define DOCG4_CHIP_SIZE 0x8000000 -#define DOCG4_PAGE_SIZE 0x200 -#define DOCG4_PAGES_PER_BLOCK 0x200 -#define DOCG4_BLOCK_SIZE (DOCG4_PAGES_PER_BLOCK * DOCG4_PAGE_SIZE) -#define DOCG4_NUMBLOCKS (DOCG4_CHIP_SIZE / DOCG4_BLOCK_SIZE) -#define DOCG4_OOB_SIZE 0x10 -#define DOCG4_CHIP_SHIFT 27 /* log_2(DOCG4_CHIP_SIZE) */ -#define DOCG4_PAGE_SHIFT 9 /* log_2(DOCG4_PAGE_SIZE) */ -#define DOCG4_ERASE_SHIFT 18 /* log_2(DOCG4_BLOCK_SIZE) */ - -/* all but the last byte is included in ecc calculation */ -#define DOCG4_BCH_SIZE (DOCG4_PAGE_SIZE + DOCG4_OOB_SIZE - 1) - -#define DOCG4_USERDATA_LEN 520 /* 512 byte page plus 8 oob avail to user */ - -/* expected values from the ID registers */ -#define DOCG4_IDREG1_VALUE 0x0400 -#define DOCG4_IDREG2_VALUE 0xfbff - -/* primitive polynomial used to build the Galois field used by hw ecc gen */ -#define DOCG4_PRIMITIVE_POLY 0x4443 - -#define DOCG4_M 14 /* Galois field is of order 2^14 */ -#define DOCG4_T 4 /* BCH alg corrects up to 4 bit errors */ - -#define DOCG4_FACTORY_BBT_PAGE 16 /* page where read-only factory bbt lives */ -#define DOCG4_REDUNDANT_BBT_PAGE 24 /* page where redundant factory bbt lives */ - -/* - * Bytes 0, 1 are used as badblock marker. - * Bytes 2 - 6 are available to the user. - * Byte 7 is hamming ecc for first 7 oob bytes only. - * Bytes 8 - 14 are hw-generated ecc covering entire page + oob bytes 0 - 14. - * Byte 15 (the last) is used by the driver as a "page written" flag. - */ -static int docg4_ooblayout_ecc(struct mtd_info *mtd, int section, - struct mtd_oob_region *oobregion) -{ - if (section) - return -ERANGE; - - oobregion->offset = 7; - oobregion->length = 9; - - return 0; -} - -static int docg4_ooblayout_free(struct mtd_info *mtd, int section, - struct mtd_oob_region *oobregion) -{ - if (section) - return -ERANGE; - - oobregion->offset = 2; - oobregion->length = 5; - - return 0; -} - -static const struct mtd_ooblayout_ops docg4_ooblayout_ops = { - .ecc = docg4_ooblayout_ecc, - .free = docg4_ooblayout_free, -}; - -/* - * The device has a nop register which M-Sys claims is for the purpose of - * inserting precise delays. But beware; at least some operations fail if the - * nop writes are replaced with a generic delay! - */ -static inline void write_nop(void __iomem *docptr) -{ - writew(0, docptr + DOC_NOP); -} - -static void docg4_read_buf(struct nand_chip *nand, uint8_t *buf, int len) -{ - int i; - uint16_t *p = (uint16_t *) buf; - len >>= 1; - - for (i = 0; i < len; i++) - p[i] = readw(nand->IO_ADDR_R); -} - -static void docg4_write_buf16(struct nand_chip *nand, const uint8_t *buf, - int len) -{ - int i; - uint16_t *p = (uint16_t *) buf; - len >>= 1; - - for (i = 0; i < len; i++) - writew(p[i], nand->IO_ADDR_W); -} - -static int poll_status(struct docg4_priv *doc) -{ - /* - * Busy-wait for the FLASHREADY bit to be set in the FLASHCONTROL - * register. Operations known to take a long time (e.g., block erase) - * should sleep for a while before calling this. - */ - - uint16_t flash_status; - unsigned long timeo; - void __iomem *docptr = doc->virtadr; - - dev_dbg(doc->dev, "%s...\n", __func__); - - /* hardware quirk requires reading twice initially */ - flash_status = readw(docptr + DOC_FLASHCONTROL); - - timeo = jiffies + msecs_to_jiffies(200); /* generous timeout */ - do { - cpu_relax(); - flash_status = readb(docptr + DOC_FLASHCONTROL); - } while (!(flash_status & DOC_CTRL_FLASHREADY) && - time_before(jiffies, timeo)); - - if (unlikely(!(flash_status & DOC_CTRL_FLASHREADY))) { - dev_err(doc->dev, "%s: timed out!\n", __func__); - return NAND_STATUS_FAIL; - } - - return 0; -} - - -static int docg4_wait(struct nand_chip *nand) -{ - - struct docg4_priv *doc = nand_get_controller_data(nand); - int status = NAND_STATUS_WP; /* inverse logic?? */ - dev_dbg(doc->dev, "%s...\n", __func__); - - /* report any previously unreported error */ - if (doc->status) { - status |= doc->status; - doc->status = 0; - return status; - } - - status |= poll_status(doc); - return status; -} - -static void docg4_select_chip(struct nand_chip *nand, int chip) -{ - /* - * Select among multiple cascaded chips ("floors"). Multiple floors are - * not yet supported, so the only valid non-negative value is 0. - */ - struct docg4_priv *doc = nand_get_controller_data(nand); - void __iomem *docptr = doc->virtadr; - - dev_dbg(doc->dev, "%s: chip %d\n", __func__, chip); - - if (chip < 0) - return; /* deselected */ - - if (chip > 0) - dev_warn(doc->dev, "multiple floors currently unsupported\n"); - - writew(0, docptr + DOC_DEVICESELECT); -} - -static void reset(struct mtd_info *mtd) -{ - /* full device reset */ - - struct nand_chip *nand = mtd_to_nand(mtd); - struct docg4_priv *doc = nand_get_controller_data(nand); - void __iomem *docptr = doc->virtadr; - - writew(DOC_ASICMODE_RESET | DOC_ASICMODE_MDWREN, - docptr + DOC_ASICMODE); - writew(~(DOC_ASICMODE_RESET | DOC_ASICMODE_MDWREN), - docptr + DOC_ASICMODECONFIRM); - write_nop(docptr); - - writew(DOC_ASICMODE_NORMAL | DOC_ASICMODE_MDWREN, - docptr + DOC_ASICMODE); - writew(~(DOC_ASICMODE_NORMAL | DOC_ASICMODE_MDWREN), - docptr + DOC_ASICMODECONFIRM); - - writew(DOC_ECCCONF1_ECC_ENABLE, docptr + DOC_ECCCONF1); - - poll_status(doc); -} - -static void read_hw_ecc(void __iomem *docptr, uint8_t *ecc_buf) -{ - /* read the 7 hw-generated ecc bytes */ - - int i; - for (i = 0; i < 7; i++) { /* hw quirk; read twice */ - ecc_buf[i] = readb(docptr + DOC_BCH_SYNDROM(i)); - ecc_buf[i] = readb(docptr + DOC_BCH_SYNDROM(i)); - } -} - -static int correct_data(struct mtd_info *mtd, uint8_t *buf, int page) -{ - /* - * Called after a page read when hardware reports bitflips. - * Up to four bitflips can be corrected. - */ - - struct nand_chip *nand = mtd_to_nand(mtd); - struct docg4_priv *doc = nand_get_controller_data(nand); - void __iomem *docptr = doc->virtadr; - int i, numerrs, errpos[4]; - const uint8_t blank_read_hwecc[8] = { - 0xcf, 0x72, 0xfc, 0x1b, 0xa9, 0xc7, 0xb9, 0 }; - - read_hw_ecc(docptr, doc->ecc_buf); /* read 7 hw-generated ecc bytes */ - - /* check if read error is due to a blank page */ - if (!memcmp(doc->ecc_buf, blank_read_hwecc, 7)) - return 0; /* yes */ - - /* skip additional check of "written flag" if ignore_badblocks */ - if (ignore_badblocks == false) { - - /* - * If the hw ecc bytes are not those of a blank page, there's - * still a chance that the page is blank, but was read with - * errors. Check the "written flag" in last oob byte, which - * is set to zero when a page is written. If more than half - * the bits are set, assume a blank page. Unfortunately, the - * bit flips(s) are not reported in stats. - */ - - if (nand->oob_poi[15]) { - int bit, numsetbits = 0; - unsigned long written_flag = nand->oob_poi[15]; - for_each_set_bit(bit, &written_flag, 8) - numsetbits++; - if (numsetbits > 4) { /* assume blank */ - dev_warn(doc->dev, - "error(s) in blank page " - "at offset %08x\n", - page * DOCG4_PAGE_SIZE); - return 0; - } - } - } - - /* - * The hardware ecc unit produces oob_ecc ^ calc_ecc. The kernel's bch - * algorithm is used to decode this. However the hw operates on page - * data in a bit order that is the reverse of that of the bch alg, - * requiring that the bits be reversed on the result. Thanks to Ivan - * Djelic for his analysis! - */ - for (i = 0; i < 7; i++) - doc->ecc_buf[i] = bitrev8(doc->ecc_buf[i]); - - numerrs = decode_bch(doc->bch, NULL, DOCG4_USERDATA_LEN, NULL, - doc->ecc_buf, NULL, errpos); - - if (numerrs == -EBADMSG) { - dev_warn(doc->dev, "uncorrectable errors at offset %08x\n", - page * DOCG4_PAGE_SIZE); - return -EBADMSG; - } - - BUG_ON(numerrs < 0); /* -EINVAL, or anything other than -EBADMSG */ - - /* undo last step in BCH alg (modulo mirroring not needed) */ - for (i = 0; i < numerrs; i++) - errpos[i] = (errpos[i] & ~7)|(7-(errpos[i] & 7)); - - /* fix the errors */ - for (i = 0; i < numerrs; i++) { - - /* ignore if error within oob ecc bytes */ - if (errpos[i] > DOCG4_USERDATA_LEN * 8) - continue; - - /* if error within oob area preceeding ecc bytes... */ - if (errpos[i] > DOCG4_PAGE_SIZE * 8) - change_bit(errpos[i] - DOCG4_PAGE_SIZE * 8, - (unsigned long *)nand->oob_poi); - - else /* error in page data */ - change_bit(errpos[i], (unsigned long *)buf); - } - - dev_notice(doc->dev, "%d error(s) corrected at offset %08x\n", - numerrs, page * DOCG4_PAGE_SIZE); - - return numerrs; -} - -static uint8_t docg4_read_byte(struct nand_chip *nand) -{ - struct docg4_priv *doc = nand_get_controller_data(nand); - - dev_dbg(doc->dev, "%s\n", __func__); - - if (doc->last_command.command == NAND_CMD_STATUS) { - int status; - - /* - * Previous nand command was status request, so nand - * infrastructure code expects to read the status here. If an - * error occurred in a previous operation, report it. - */ - doc->last_command.command = 0; - - if (doc->status) { - status = doc->status; - doc->status = 0; - } - - /* why is NAND_STATUS_WP inverse logic?? */ - else - status = NAND_STATUS_WP | NAND_STATUS_READY; - - return status; - } - - dev_warn(doc->dev, "unexpected call to read_byte()\n"); - - return 0; -} - -static void write_addr(struct docg4_priv *doc, uint32_t docg4_addr) -{ - /* write the four address bytes packed in docg4_addr to the device */ - - void __iomem *docptr = doc->virtadr; - writeb(docg4_addr & 0xff, docptr + DOC_FLASHADDRESS); - docg4_addr >>= 8; - writeb(docg4_addr & 0xff, docptr + DOC_FLASHADDRESS); - docg4_addr >>= 8; - writeb(docg4_addr & 0xff, docptr + DOC_FLASHADDRESS); - docg4_addr >>= 8; - writeb(docg4_addr & 0xff, docptr + DOC_FLASHADDRESS); -} - -static int read_progstatus(struct docg4_priv *doc) -{ - /* - * This apparently checks the status of programming. Done after an - * erasure, and after page data is written. On error, the status is - * saved, to be later retrieved by the nand infrastructure code. - */ - void __iomem *docptr = doc->virtadr; - - /* status is read from the I/O reg */ - uint16_t status1 = readw(docptr + DOC_IOSPACE_DATA); - uint16_t status2 = readw(docptr + DOC_IOSPACE_DATA); - uint16_t status3 = readw(docptr + DOCG4_MYSTERY_REG); - - dev_dbg(doc->dev, "docg4: %s: %02x %02x %02x\n", - __func__, status1, status2, status3); - - if (status1 != DOCG4_PROGSTATUS_GOOD - || status2 != DOCG4_PROGSTATUS_GOOD_2 - || status3 != DOCG4_PROGSTATUS_GOOD_2) { - doc->status = NAND_STATUS_FAIL; - dev_warn(doc->dev, "read_progstatus failed: " - "%02x, %02x, %02x\n", status1, status2, status3); - return -EIO; - } - return 0; -} - -static int pageprog(struct mtd_info *mtd) -{ - /* - * Final step in writing a page. Writes the contents of its - * internal buffer out to the flash array, or some such. - */ - - struct nand_chip *nand = mtd_to_nand(mtd); - struct docg4_priv *doc = nand_get_controller_data(nand); - void __iomem *docptr = doc->virtadr; - int retval = 0; - - dev_dbg(doc->dev, "docg4: %s\n", __func__); - - writew(DOCG4_SEQ_PAGEPROG, docptr + DOC_FLASHSEQUENCE); - writew(DOC_CMD_PROG_CYCLE2, docptr + DOC_FLASHCOMMAND); - write_nop(docptr); - write_nop(docptr); - - /* Just busy-wait; usleep_range() slows things down noticeably. */ - poll_status(doc); - - writew(DOCG4_SEQ_FLUSH, docptr + DOC_FLASHSEQUENCE); - writew(DOCG4_CMD_FLUSH, docptr + DOC_FLASHCOMMAND); - writew(DOC_ECCCONF0_READ_MODE | 4, docptr + DOC_ECCCONF0); - write_nop(docptr); - write_nop(docptr); - write_nop(docptr); - write_nop(docptr); - write_nop(docptr); - - retval = read_progstatus(doc); - writew(0, docptr + DOC_DATAEND); - write_nop(docptr); - poll_status(doc); - write_nop(docptr); - - return retval; -} - -static void sequence_reset(struct mtd_info *mtd) -{ - /* common starting sequence for all operations */ - - struct nand_chip *nand = mtd_to_nand(mtd); - struct docg4_priv *doc = nand_get_controller_data(nand); - void __iomem *docptr = doc->virtadr; - - writew(DOC_CTRL_UNKNOWN | DOC_CTRL_CE, docptr + DOC_FLASHCONTROL); - writew(DOC_SEQ_RESET, docptr + DOC_FLASHSEQUENCE); - writew(DOC_CMD_RESET, docptr + DOC_FLASHCOMMAND); - write_nop(docptr); - write_nop(docptr); - poll_status(doc); - write_nop(docptr); -} - -static void read_page_prologue(struct mtd_info *mtd, uint32_t docg4_addr) -{ - /* first step in reading a page */ - - struct nand_chip *nand = mtd_to_nand(mtd); - struct docg4_priv *doc = nand_get_controller_data(nand); - void __iomem *docptr = doc->virtadr; - - dev_dbg(doc->dev, - "docg4: %s: g4 page %08x\n", __func__, docg4_addr); - - sequence_reset(mtd); - - writew(DOCG4_SEQ_PAGE_READ, docptr + DOC_FLASHSEQUENCE); - writew(DOCG4_CMD_PAGE_READ, docptr + DOC_FLASHCOMMAND); - write_nop(docptr); - - write_addr(doc, docg4_addr); - - write_nop(docptr); - writew(DOCG4_CMD_READ2, docptr + DOC_FLASHCOMMAND); - write_nop(docptr); - write_nop(docptr); - - poll_status(doc); -} - -static void write_page_prologue(struct mtd_info *mtd, uint32_t docg4_addr) -{ - /* first step in writing a page */ - - struct nand_chip *nand = mtd_to_nand(mtd); - struct docg4_priv *doc = nand_get_controller_data(nand); - void __iomem *docptr = doc->virtadr; - - dev_dbg(doc->dev, - "docg4: %s: g4 addr: %x\n", __func__, docg4_addr); - sequence_reset(mtd); - - if (unlikely(reliable_mode)) { - writew(DOCG4_SEQ_SETMODE, docptr + DOC_FLASHSEQUENCE); - writew(DOCG4_CMD_FAST_MODE, docptr + DOC_FLASHCOMMAND); - writew(DOC_CMD_RELIABLE_MODE, docptr + DOC_FLASHCOMMAND); - write_nop(docptr); - } - - writew(DOCG4_SEQ_PAGEWRITE, docptr + DOC_FLASHSEQUENCE); - writew(DOCG4_CMD_PAGEWRITE, docptr + DOC_FLASHCOMMAND); - write_nop(docptr); - write_addr(doc, docg4_addr); - write_nop(docptr); - write_nop(docptr); - poll_status(doc); -} - -static uint32_t mtd_to_docg4_address(int page, int column) -{ - /* - * Convert mtd address to format used by the device, 32 bit packed. - * - * Some notes on G4 addressing... The M-Sys documentation on this device - * claims that pages are 2K in length, and indeed, the format of the - * address used by the device reflects that. But within each page are - * four 512 byte "sub-pages", each with its own oob data that is - * read/written immediately after the 512 bytes of page data. This oob - * data contains the ecc bytes for the preceeding 512 bytes. - * - * Rather than tell the mtd nand infrastructure that page size is 2k, - * with four sub-pages each, we engage in a little subterfuge and tell - * the infrastructure code that pages are 512 bytes in size. This is - * done because during the course of reverse-engineering the device, I - * never observed an instance where an entire 2K "page" was read or - * written as a unit. Each "sub-page" is always addressed individually, - * its data read/written, and ecc handled before the next "sub-page" is - * addressed. - * - * This requires us to convert addresses passed by the mtd nand - * infrastructure code to those used by the device. - * - * The address that is written to the device consists of four bytes: the - * first two are the 2k page number, and the second is the index into - * the page. The index is in terms of 16-bit half-words and includes - * the preceeding oob data, so e.g., the index into the second - * "sub-page" is 0x108, and the full device address of the start of mtd - * page 0x201 is 0x00800108. - */ - int g4_page = page / 4; /* device's 2K page */ - int g4_index = (page % 4) * 0x108 + column/2; /* offset into page */ - return (g4_page << 16) | g4_index; /* pack */ -} - -static void docg4_command(struct nand_chip *nand, unsigned command, int column, - int page_addr) -{ - /* handle standard nand commands */ - - struct mtd_info *mtd = nand_to_mtd(nand); - struct docg4_priv *doc = nand_get_controller_data(nand); - uint32_t g4_addr = mtd_to_docg4_address(page_addr, column); - - dev_dbg(doc->dev, "%s %x, page_addr=%x, column=%x\n", - __func__, command, page_addr, column); - - /* - * Save the command and its arguments. This enables emulation of - * standard flash devices, and also some optimizations. - */ - doc->last_command.command = command; - doc->last_command.column = column; - doc->last_command.page = page_addr; - - switch (command) { - - case NAND_CMD_RESET: - reset(mtd); - break; - - case NAND_CMD_READ0: - read_page_prologue(mtd, g4_addr); - break; - - case NAND_CMD_STATUS: - /* next call to read_byte() will expect a status */ - break; - - case NAND_CMD_SEQIN: - if (unlikely(reliable_mode)) { - uint16_t g4_page = g4_addr >> 16; - - /* writes to odd-numbered 2k pages are invalid */ - if (g4_page & 0x01) - dev_warn(doc->dev, - "invalid reliable mode address\n"); - } - - write_page_prologue(mtd, g4_addr); - - /* hack for deferred write of oob bytes */ - if (doc->oob_page == page_addr) - memcpy(nand->oob_poi, doc->oob_buf, 16); - break; - - case NAND_CMD_PAGEPROG: - pageprog(mtd); - break; - - /* we don't expect these, based on review of nand_base.c */ - case NAND_CMD_READOOB: - case NAND_CMD_READID: - case NAND_CMD_ERASE1: - case NAND_CMD_ERASE2: - dev_warn(doc->dev, "docg4_command: " - "unexpected nand command 0x%x\n", command); - break; - - } -} - -static int read_page(struct mtd_info *mtd, struct nand_chip *nand, - uint8_t *buf, int page, bool use_ecc) -{ - struct docg4_priv *doc = nand_get_controller_data(nand); - void __iomem *docptr = doc->virtadr; - uint16_t status, edc_err, *buf16; - int bits_corrected = 0; - - dev_dbg(doc->dev, "%s: page %08x\n", __func__, page); - - nand_read_page_op(nand, page, 0, NULL, 0); - - writew(DOC_ECCCONF0_READ_MODE | - DOC_ECCCONF0_ECC_ENABLE | - DOC_ECCCONF0_UNKNOWN | - DOCG4_BCH_SIZE, - docptr + DOC_ECCCONF0); - write_nop(docptr); - write_nop(docptr); - write_nop(docptr); - write_nop(docptr); - write_nop(docptr); - - /* the 1st byte from the I/O reg is a status; the rest is page data */ - status = readw(docptr + DOC_IOSPACE_DATA); - if (status & DOCG4_READ_ERROR) { - dev_err(doc->dev, - "docg4_read_page: bad status: 0x%02x\n", status); - writew(0, docptr + DOC_DATAEND); - return -EIO; - } - - dev_dbg(doc->dev, "%s: status = 0x%x\n", __func__, status); - - docg4_read_buf(nand, buf, DOCG4_PAGE_SIZE); /* read the page data */ - - /* this device always reads oob after page data */ - /* first 14 oob bytes read from I/O reg */ - docg4_read_buf(nand, nand->oob_poi, 14); - - /* last 2 read from another reg */ - buf16 = (uint16_t *)(nand->oob_poi + 14); - *buf16 = readw(docptr + DOCG4_MYSTERY_REG); - - write_nop(docptr); - - if (likely(use_ecc == true)) { - - /* read the register that tells us if bitflip(s) detected */ - edc_err = readw(docptr + DOC_ECCCONF1); - edc_err = readw(docptr + DOC_ECCCONF1); - dev_dbg(doc->dev, "%s: edc_err = 0x%02x\n", __func__, edc_err); - - /* If bitflips are reported, attempt to correct with ecc */ - if (edc_err & DOC_ECCCONF1_BCH_SYNDROM_ERR) { - bits_corrected = correct_data(mtd, buf, page); - if (bits_corrected == -EBADMSG) - mtd->ecc_stats.failed++; - else - mtd->ecc_stats.corrected += bits_corrected; - } - } - - writew(0, docptr + DOC_DATAEND); - if (bits_corrected == -EBADMSG) /* uncorrectable errors */ - return 0; - return bits_corrected; -} - - -static int docg4_read_page_raw(struct nand_chip *nand, uint8_t *buf, - int oob_required, int page) -{ - return read_page(nand_to_mtd(nand), nand, buf, page, false); -} - -static int docg4_read_page(struct nand_chip *nand, uint8_t *buf, - int oob_required, int page) -{ - return read_page(nand_to_mtd(nand), nand, buf, page, true); -} - -static int docg4_read_oob(struct nand_chip *nand, int page) -{ - struct docg4_priv *doc = nand_get_controller_data(nand); - void __iomem *docptr = doc->virtadr; - uint16_t status; - - dev_dbg(doc->dev, "%s: page %x\n", __func__, page); - - nand_read_page_op(nand, page, nand->ecc.size, NULL, 0); - - writew(DOC_ECCCONF0_READ_MODE | DOCG4_OOB_SIZE, docptr + DOC_ECCCONF0); - write_nop(docptr); - write_nop(docptr); - write_nop(docptr); - write_nop(docptr); - write_nop(docptr); - - /* the 1st byte from the I/O reg is a status; the rest is oob data */ - status = readw(docptr + DOC_IOSPACE_DATA); - if (status & DOCG4_READ_ERROR) { - dev_warn(doc->dev, - "docg4_read_oob failed: status = 0x%02x\n", status); - return -EIO; - } - - dev_dbg(doc->dev, "%s: status = 0x%x\n", __func__, status); - - docg4_read_buf(nand, nand->oob_poi, 16); - - write_nop(docptr); - write_nop(docptr); - write_nop(docptr); - writew(0, docptr + DOC_DATAEND); - write_nop(docptr); - - return 0; -} - -static int docg4_erase_block(struct nand_chip *nand, int page) -{ - struct mtd_info *mtd = nand_to_mtd(nand); - struct docg4_priv *doc = nand_get_controller_data(nand); - void __iomem *docptr = doc->virtadr; - uint16_t g4_page; - int status; - - dev_dbg(doc->dev, "%s: page %04x\n", __func__, page); - - sequence_reset(mtd); - - writew(DOCG4_SEQ_BLOCKERASE, docptr + DOC_FLASHSEQUENCE); - writew(DOC_CMD_PROG_BLOCK_ADDR, docptr + DOC_FLASHCOMMAND); - write_nop(docptr); - - /* only 2 bytes of address are written to specify erase block */ - g4_page = (uint16_t)(page / 4); /* to g4's 2k page addressing */ - writeb(g4_page & 0xff, docptr + DOC_FLASHADDRESS); - g4_page >>= 8; - writeb(g4_page & 0xff, docptr + DOC_FLASHADDRESS); - write_nop(docptr); - - /* start the erasure */ - writew(DOC_CMD_ERASECYCLE2, docptr + DOC_FLASHCOMMAND); - write_nop(docptr); - write_nop(docptr); - - usleep_range(500, 1000); /* erasure is long; take a snooze */ - poll_status(doc); - writew(DOCG4_SEQ_FLUSH, docptr + DOC_FLASHSEQUENCE); - writew(DOCG4_CMD_FLUSH, docptr + DOC_FLASHCOMMAND); - writew(DOC_ECCCONF0_READ_MODE | 4, docptr + DOC_ECCCONF0); - write_nop(docptr); - write_nop(docptr); - write_nop(docptr); - write_nop(docptr); - write_nop(docptr); - - read_progstatus(doc); - - writew(0, docptr + DOC_DATAEND); - write_nop(docptr); - poll_status(doc); - write_nop(docptr); - - status = nand->waitfunc(nand); - if (status < 0) - return status; - - return status & NAND_STATUS_FAIL ? -EIO : 0; -} - -static int write_page(struct mtd_info *mtd, struct nand_chip *nand, - const uint8_t *buf, int page, bool use_ecc) -{ - struct docg4_priv *doc = nand_get_controller_data(nand); - void __iomem *docptr = doc->virtadr; - uint8_t ecc_buf[8]; - - dev_dbg(doc->dev, "%s...\n", __func__); - - nand_prog_page_begin_op(nand, page, 0, NULL, 0); - - writew(DOC_ECCCONF0_ECC_ENABLE | - DOC_ECCCONF0_UNKNOWN | - DOCG4_BCH_SIZE, - docptr + DOC_ECCCONF0); - write_nop(docptr); - - /* write the page data */ - docg4_write_buf16(nand, buf, DOCG4_PAGE_SIZE); - - /* oob bytes 0 through 5 are written to I/O reg */ - docg4_write_buf16(nand, nand->oob_poi, 6); - - /* oob byte 6 written to a separate reg */ - writew(nand->oob_poi[6], docptr + DOCG4_OOB_6_7); - - write_nop(docptr); - write_nop(docptr); - - /* write hw-generated ecc bytes to oob */ - if (likely(use_ecc == true)) { - /* oob byte 7 is hamming code */ - uint8_t hamming = readb(docptr + DOC_HAMMINGPARITY); - hamming = readb(docptr + DOC_HAMMINGPARITY); /* 2nd read */ - writew(hamming, docptr + DOCG4_OOB_6_7); - write_nop(docptr); - - /* read the 7 bch bytes from ecc regs */ - read_hw_ecc(docptr, ecc_buf); - ecc_buf[7] = 0; /* clear the "page written" flag */ - } - - /* write user-supplied bytes to oob */ - else { - writew(nand->oob_poi[7], docptr + DOCG4_OOB_6_7); - write_nop(docptr); - memcpy(ecc_buf, &nand->oob_poi[8], 8); - } - - docg4_write_buf16(nand, ecc_buf, 8); - write_nop(docptr); - write_nop(docptr); - writew(0, docptr + DOC_DATAEND); - write_nop(docptr); - - return nand_prog_page_end_op(nand); -} - -static int docg4_write_page_raw(struct nand_chip *nand, const uint8_t *buf, - int oob_required, int page) -{ - return write_page(nand_to_mtd(nand), nand, buf, page, false); -} - -static int docg4_write_page(struct nand_chip *nand, const uint8_t *buf, - int oob_required, int page) -{ - return write_page(nand_to_mtd(nand), nand, buf, page, true); -} - -static int docg4_write_oob(struct nand_chip *nand, int page) -{ - /* - * Writing oob-only is not really supported, because MLC nand must write - * oob bytes at the same time as page data. Nonetheless, we save the - * oob buffer contents here, and then write it along with the page data - * if the same page is subsequently written. This allows user space - * utilities that write the oob data prior to the page data to work - * (e.g., nandwrite). The disdvantage is that, if the intention was to - * write oob only, the operation is quietly ignored. Also, oob can get - * corrupted if two concurrent processes are running nandwrite. - */ - - /* note that bytes 7..14 are hw generated hamming/ecc and overwritten */ - struct docg4_priv *doc = nand_get_controller_data(nand); - doc->oob_page = page; - memcpy(doc->oob_buf, nand->oob_poi, 16); - return 0; -} - -static int __init read_factory_bbt(struct mtd_info *mtd) -{ - /* - * The device contains a read-only factory bad block table. Read it and - * update the memory-based bbt accordingly. - */ - - struct nand_chip *nand = mtd_to_nand(mtd); - struct docg4_priv *doc = nand_get_controller_data(nand); - uint32_t g4_addr = mtd_to_docg4_address(DOCG4_FACTORY_BBT_PAGE, 0); - uint8_t *buf; - int i, block; - __u32 eccfailed_stats = mtd->ecc_stats.failed; - - buf = kzalloc(DOCG4_PAGE_SIZE, GFP_KERNEL); - if (buf == NULL) - return -ENOMEM; - - read_page_prologue(mtd, g4_addr); - docg4_read_page(nand, buf, 0, DOCG4_FACTORY_BBT_PAGE); - - /* - * If no memory-based bbt was created, exit. This will happen if module - * parameter ignore_badblocks is set. Then why even call this function? - * For an unknown reason, block erase always fails if it's the first - * operation after device power-up. The above read ensures it never is. - * Ugly, I know. - */ - if (nand->bbt == NULL) /* no memory-based bbt */ - goto exit; - - if (mtd->ecc_stats.failed > eccfailed_stats) { - /* - * Whoops, an ecc failure ocurred reading the factory bbt. - * It is stored redundantly, so we get another chance. - */ - eccfailed_stats = mtd->ecc_stats.failed; - docg4_read_page(nand, buf, 0, DOCG4_REDUNDANT_BBT_PAGE); - if (mtd->ecc_stats.failed > eccfailed_stats) { - dev_warn(doc->dev, - "The factory bbt could not be read!\n"); - goto exit; - } - } - - /* - * Parse factory bbt and update memory-based bbt. Factory bbt format is - * simple: one bit per block, block numbers increase left to right (msb - * to lsb). Bit clear means bad block. - */ - for (i = block = 0; block < DOCG4_NUMBLOCKS; block += 8, i++) { - int bitnum; - unsigned long bits = ~buf[i]; - for_each_set_bit(bitnum, &bits, 8) { - int badblock = block + 7 - bitnum; - nand->bbt[badblock / 4] |= - 0x03 << ((badblock % 4) * 2); - mtd->ecc_stats.badblocks++; - dev_notice(doc->dev, "factory-marked bad block: %d\n", - badblock); - } - } - exit: - kfree(buf); - return 0; -} - -static int docg4_block_markbad(struct nand_chip *nand, loff_t ofs) -{ - /* - * Mark a block as bad. Bad blocks are marked in the oob area of the - * first page of the block. The default scan_bbt() in the nand - * infrastructure code works fine for building the memory-based bbt - * during initialization, as does the nand infrastructure function that - * checks if a block is bad by reading the bbt. This function replaces - * the nand default because writes to oob-only are not supported. - */ - - int ret, i; - uint8_t *buf; - struct mtd_info *mtd = nand_to_mtd(nand); - struct docg4_priv *doc = nand_get_controller_data(nand); - struct nand_bbt_descr *bbtd = nand->badblock_pattern; - int page = (int)(ofs >> nand->page_shift); - uint32_t g4_addr = mtd_to_docg4_address(page, 0); - - dev_dbg(doc->dev, "%s: %08llx\n", __func__, ofs); - - if (unlikely(ofs & (DOCG4_BLOCK_SIZE - 1))) - dev_warn(doc->dev, "%s: ofs %llx not start of block!\n", - __func__, ofs); - - /* allocate blank buffer for page data */ - buf = kzalloc(DOCG4_PAGE_SIZE, GFP_KERNEL); - if (buf == NULL) - return -ENOMEM; - - /* write bit-wise negation of pattern to oob buffer */ - memset(nand->oob_poi, 0xff, mtd->oobsize); - for (i = 0; i < bbtd->len; i++) - nand->oob_poi[bbtd->offs + i] = ~bbtd->pattern[i]; - - /* write first page of block */ - write_page_prologue(mtd, g4_addr); - docg4_write_page(nand, buf, 1, page); - ret = pageprog(mtd); - - kfree(buf); - - return ret; -} - -static int docg4_block_neverbad(struct nand_chip *nand, loff_t ofs) -{ - /* only called when module_param ignore_badblocks is set */ - return 0; -} - -static int docg4_suspend(struct platform_device *pdev, pm_message_t state) -{ - /* - * Put the device into "deep power-down" mode. Note that CE# must be - * deasserted for this to take effect. The xscale, e.g., can be - * configured to float this signal when the processor enters power-down, - * and a suitable pull-up ensures its deassertion. - */ - - int i; - uint8_t pwr_down; - struct docg4_priv *doc = platform_get_drvdata(pdev); - void __iomem *docptr = doc->virtadr; - - dev_dbg(doc->dev, "%s...\n", __func__); - - /* poll the register that tells us we're ready to go to sleep */ - for (i = 0; i < 10; i++) { - pwr_down = readb(docptr + DOC_POWERMODE); - if (pwr_down & DOC_POWERDOWN_READY) - break; - usleep_range(1000, 4000); - } - - if (pwr_down & DOC_POWERDOWN_READY) { - dev_err(doc->dev, "suspend failed; " - "timeout polling DOC_POWERDOWN_READY\n"); - return -EIO; - } - - writew(DOC_ASICMODE_POWERDOWN | DOC_ASICMODE_MDWREN, - docptr + DOC_ASICMODE); - writew(~(DOC_ASICMODE_POWERDOWN | DOC_ASICMODE_MDWREN), - docptr + DOC_ASICMODECONFIRM); - - write_nop(docptr); - - return 0; -} - -static int docg4_resume(struct platform_device *pdev) -{ - - /* - * Exit power-down. Twelve consecutive reads of the address below - * accomplishes this, assuming CE# has been asserted. - */ - - struct docg4_priv *doc = platform_get_drvdata(pdev); - void __iomem *docptr = doc->virtadr; - int i; - - dev_dbg(doc->dev, "%s...\n", __func__); - - for (i = 0; i < 12; i++) - readb(docptr + 0x1fff); - - return 0; -} - -static void init_mtd_structs(struct mtd_info *mtd) -{ - /* initialize mtd and nand data structures */ - - /* - * Note that some of the following initializations are not usually - * required within a nand driver because they are performed by the nand - * infrastructure code as part of nand_scan(). In this case they need - * to be initialized here because we skip call to nand_scan_ident() (the - * first half of nand_scan()). The call to nand_scan_ident() could be - * skipped because for this device the chip id is not read in the manner - * of a standard nand device. - */ - - struct nand_chip *nand = mtd_to_nand(mtd); - struct docg4_priv *doc = nand_get_controller_data(nand); - - mtd->size = DOCG4_CHIP_SIZE; - mtd->name = "Msys_Diskonchip_G4"; - mtd->writesize = DOCG4_PAGE_SIZE; - mtd->erasesize = DOCG4_BLOCK_SIZE; - mtd->oobsize = DOCG4_OOB_SIZE; - mtd_set_ooblayout(mtd, &docg4_ooblayout_ops); - nand->chipsize = DOCG4_CHIP_SIZE; - nand->chip_shift = DOCG4_CHIP_SHIFT; - nand->bbt_erase_shift = nand->phys_erase_shift = DOCG4_ERASE_SHIFT; - nand->chip_delay = 20; - nand->page_shift = DOCG4_PAGE_SHIFT; - nand->pagemask = 0x3ffff; - nand->badblockpos = NAND_LARGE_BADBLOCK_POS; - nand->badblockbits = 8; - nand->ecc.mode = NAND_ECC_HW_SYNDROME; - nand->ecc.size = DOCG4_PAGE_SIZE; - nand->ecc.prepad = 8; - nand->ecc.bytes = 8; - nand->ecc.strength = DOCG4_T; - nand->options = NAND_BUSWIDTH_16 | NAND_NO_SUBPAGE_WRITE; - nand->IO_ADDR_R = nand->IO_ADDR_W = doc->virtadr + DOC_IOSPACE_DATA; - nand->controller = &nand->dummy_controller; - nand_controller_init(nand->controller); - - /* methods */ - nand->cmdfunc = docg4_command; - nand->waitfunc = docg4_wait; - nand->select_chip = docg4_select_chip; - nand->read_byte = docg4_read_byte; - nand->block_markbad = docg4_block_markbad; - nand->read_buf = docg4_read_buf; - nand->write_buf = docg4_write_buf16; - nand->erase = docg4_erase_block; - nand->set_features = nand_get_set_features_notsupp; - nand->get_features = nand_get_set_features_notsupp; - nand->ecc.read_page = docg4_read_page; - nand->ecc.write_page = docg4_write_page; - nand->ecc.read_page_raw = docg4_read_page_raw; - nand->ecc.write_page_raw = docg4_write_page_raw; - nand->ecc.read_oob = docg4_read_oob; - nand->ecc.write_oob = docg4_write_oob; - - /* - * The way the nand infrastructure code is written, a memory-based bbt - * is not created if NAND_SKIP_BBTSCAN is set. With no memory bbt, - * nand->block_bad() is used. So when ignoring bad blocks, we skip the - * scan and define a dummy block_bad() which always returns 0. - */ - if (ignore_badblocks) { - nand->options |= NAND_SKIP_BBTSCAN; - nand->block_bad = docg4_block_neverbad; - } - -} - -static int read_id_reg(struct mtd_info *mtd) -{ - struct nand_chip *nand = mtd_to_nand(mtd); - struct docg4_priv *doc = nand_get_controller_data(nand); - void __iomem *docptr = doc->virtadr; - uint16_t id1, id2; - - /* check for presence of g4 chip by reading id registers */ - id1 = readw(docptr + DOC_CHIPID); - id1 = readw(docptr + DOCG4_MYSTERY_REG); - id2 = readw(docptr + DOC_CHIPID_INV); - id2 = readw(docptr + DOCG4_MYSTERY_REG); - - if (id1 == DOCG4_IDREG1_VALUE && id2 == DOCG4_IDREG2_VALUE) { - dev_info(doc->dev, - "NAND device: 128MiB Diskonchip G4 detected\n"); - return 0; - } - - return -ENODEV; -} - -static char const *part_probes[] = { "cmdlinepart", "saftlpart", NULL }; - -static int docg4_attach_chip(struct nand_chip *chip) -{ - struct mtd_info *mtd = nand_to_mtd(chip); - struct docg4_priv *doc = (struct docg4_priv *)(chip + 1); - int ret; - - init_mtd_structs(mtd); - - /* Initialize kernel BCH algorithm */ - doc->bch = init_bch(DOCG4_M, DOCG4_T, DOCG4_PRIMITIVE_POLY); - if (!doc->bch) - return -EINVAL; - - reset(mtd); - - ret = read_id_reg(mtd); - if (ret) - free_bch(doc->bch); - - return ret; -} - -static void docg4_detach_chip(struct nand_chip *chip) -{ - struct docg4_priv *doc = (struct docg4_priv *)(chip + 1); - - free_bch(doc->bch); -} - -static const struct nand_controller_ops docg4_controller_ops = { - .attach_chip = docg4_attach_chip, - .detach_chip = docg4_detach_chip, -}; - -static int __init probe_docg4(struct platform_device *pdev) -{ - struct mtd_info *mtd; - struct nand_chip *nand; - void __iomem *virtadr; - struct docg4_priv *doc; - int len, retval; - struct resource *r; - struct device *dev = &pdev->dev; - - r = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (r == NULL) { - dev_err(dev, "no io memory resource defined!\n"); - return -ENODEV; - } - - virtadr = ioremap(r->start, resource_size(r)); - if (!virtadr) { - dev_err(dev, "Diskonchip ioremap failed: %pR\n", r); - return -EIO; - } - - len = sizeof(struct nand_chip) + sizeof(struct docg4_priv); - nand = kzalloc(len, GFP_KERNEL); - if (nand == NULL) { - retval = -ENOMEM; - goto unmap; - } - - mtd = nand_to_mtd(nand); - doc = (struct docg4_priv *) (nand + 1); - nand_set_controller_data(nand, doc); - mtd->dev.parent = &pdev->dev; - doc->virtadr = virtadr; - doc->dev = dev; - platform_set_drvdata(pdev, doc); - - /* - * Running nand_scan() with maxchips == 0 will skip nand_scan_ident(), - * which is a specific operation with this driver and done in the - * ->attach_chip callback. - */ - nand->dummy_controller.ops = &docg4_controller_ops; - retval = nand_scan(nand, 0); - if (retval) - goto free_nand; - - retval = read_factory_bbt(mtd); - if (retval) - goto cleanup_nand; - - retval = mtd_device_parse_register(mtd, part_probes, NULL, NULL, 0); - if (retval) - goto cleanup_nand; - - doc->mtd = mtd; - - return 0; - -cleanup_nand: - nand_cleanup(nand); -free_nand: - kfree(nand); -unmap: - iounmap(virtadr); - - return retval; -} - -static int __exit cleanup_docg4(struct platform_device *pdev) -{ - struct docg4_priv *doc = platform_get_drvdata(pdev); - nand_release(mtd_to_nand(doc->mtd)); - kfree(mtd_to_nand(doc->mtd)); - iounmap(doc->virtadr); - return 0; -} - -static struct platform_driver docg4_driver = { - .driver = { - .name = "docg4", - }, - .suspend = docg4_suspend, - .resume = docg4_resume, - .remove = __exit_p(cleanup_docg4), -}; - -module_platform_driver_probe(docg4_driver, probe_docg4); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Mike Dunn"); -MODULE_DESCRIPTION("M-Systems DiskOnChip G4 device driver"); From 480bdd8b7ab6971f15258a73638cc3880ed7256d Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Sat, 4 Aug 2018 22:59:21 +0200 Subject: [PATCH 267/302] ARM: pxa: palmtreo: Drop docg4 specific init The docg4 driver has been removed. Remove the code that was registering a docg4 device. Suggested-by: Miquel Raynal Signed-off-by: Boris Brezillon Acked-by: Robert Jarzmik Signed-off-by: Miquel Raynal --- arch/arm/mach-pxa/palmtreo.c | 31 ------------------------------- 1 file changed, 31 deletions(-) diff --git a/arch/arm/mach-pxa/palmtreo.c b/arch/arm/mach-pxa/palmtreo.c index 4cc05ecce618..b66b0b11d717 100644 --- a/arch/arm/mach-pxa/palmtreo.c +++ b/arch/arm/mach-pxa/palmtreo.c @@ -403,36 +403,6 @@ static void __init palmtreo_leds_init(void) platform_device_register(&palmtreo_leds); } -/****************************************************************************** - * diskonchip docg4 flash - ******************************************************************************/ -#if defined(CONFIG_MACH_TREO680) -/* REVISIT: does the centro have this device also? */ -#if IS_ENABLED(CONFIG_MTD_NAND_DOCG4) -static struct resource docg4_resources[] = { - { - .start = 0x00000000, - .end = 0x00001FFF, - .flags = IORESOURCE_MEM, - }, -}; - -static struct platform_device treo680_docg4_flash = { - .name = "docg4", - .id = -1, - .resource = docg4_resources, - .num_resources = ARRAY_SIZE(docg4_resources), -}; - -static void __init treo680_docg4_flash_init(void) -{ - platform_device_register(&treo680_docg4_flash); -} -#else -static inline void treo680_docg4_flash_init(void) {} -#endif -#endif - /****************************************************************************** * Machine init ******************************************************************************/ @@ -517,7 +487,6 @@ static void __init treo680_init(void) treo680_gpio_init(); palm27x_mmc_init(GPIO_NR_TREO_SD_DETECT_N, GPIO_NR_TREO680_SD_READONLY, GPIO_NR_TREO680_SD_POWER, 0); - treo680_docg4_flash_init(); } #endif From 871a4073f438c61cc4cf7471476d9a8a29ccf620 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Sat, 4 Aug 2018 22:59:22 +0200 Subject: [PATCH 268/302] mtd: rawnand: Make maxchips an unsigned int There's no good reason to make maxchips a signed integer, since only positive values are valid. Make it an unsigned int. Signed-off-by: Boris Brezillon Signed-off-by: Miquel Raynal --- drivers/mtd/nand/raw/nand_base.c | 7 ++++--- include/linux/mtd/rawnand.h | 4 ++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c index ef4d90ed896d..a7e85127c131 100644 --- a/drivers/mtd/nand/raw/nand_base.c +++ b/drivers/mtd/nand/raw/nand_base.c @@ -5915,11 +5915,12 @@ static int nand_dt_init(struct nand_chip *chip) * prevented dynamic allocations during this phase which was unconvenient and * as been banned for the benefit of the ->init_ecc()/cleanup_ecc() hooks. */ -static int nand_scan_ident(struct nand_chip *chip, int maxchips, +static int nand_scan_ident(struct nand_chip *chip, unsigned int maxchips, struct nand_flash_dev *table) { struct mtd_info *mtd = nand_to_mtd(chip); - int i, nand_maf_id, nand_dev_id; + int nand_maf_id, nand_dev_id; + unsigned int i; int ret; /* Enforce the right timings for reset/detection */ @@ -6730,7 +6731,7 @@ static void nand_detach(struct nand_chip *chip) * The flash ID is read and the mtd/chip structures are filled with the * appropriate values. */ -int nand_scan_with_ids(struct nand_chip *chip, int maxchips, +int nand_scan_with_ids(struct nand_chip *chip, unsigned int maxchips, struct nand_flash_dev *ids) { int ret; diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h index e6360e1156e7..e3a96ee7e531 100644 --- a/include/linux/mtd/rawnand.h +++ b/include/linux/mtd/rawnand.h @@ -28,10 +28,10 @@ struct nand_chip; struct nand_flash_dev; /* Scan and identify a NAND device */ -int nand_scan_with_ids(struct nand_chip *chip, int max_chips, +int nand_scan_with_ids(struct nand_chip *chip, unsigned int max_chips, struct nand_flash_dev *ids); -static inline int nand_scan(struct nand_chip *chip, int max_chips) +static inline int nand_scan(struct nand_chip *chip, unsigned int max_chips) { return nand_scan_with_ids(chip, max_chips, NULL); } From 800342de6349b333ef2ab921e590708a43ee4345 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Sat, 4 Aug 2018 22:59:23 +0200 Subject: [PATCH 269/302] mtd: rawnand: Do not treat !maxchips specially in nand_scan_with_ids() The only reason we were skipping nand_scan_ident() when maxchips == 0 was to make the docg4 to work. Now that this driver is gone we can remove this special case and return an error when maxchips is 0. Suggested-by: Miquel Raynal Signed-off-by: Boris Brezillon Signed-off-by: Miquel Raynal --- drivers/mtd/nand/raw/nand_base.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c index a7e85127c131..e63dfad8235b 100644 --- a/drivers/mtd/nand/raw/nand_base.c +++ b/drivers/mtd/nand/raw/nand_base.c @@ -6722,9 +6722,7 @@ static void nand_detach(struct nand_chip *chip) /** * nand_scan_with_ids - [NAND Interface] Scan for the NAND device * @chip: NAND chip object - * @maxchips: number of chips to scan for. @nand_scan_ident() will not be run if - * this parameter is zero (useful for specific drivers that must - * handle this part of the process themselves, e.g docg4). + * @maxchips: number of chips to scan for. * @ids: optional flash IDs table * * This fills out all the uninitialized function pointers with the defaults. @@ -6736,11 +6734,12 @@ int nand_scan_with_ids(struct nand_chip *chip, unsigned int maxchips, { int ret; - if (maxchips) { - ret = nand_scan_ident(chip, maxchips, ids); - if (ret) - return ret; - } + if (!maxchips) + return -EINVAL; + + ret = nand_scan_ident(chip, maxchips, ids); + if (ret) + return ret; ret = nand_attach(chip); if (ret) From 4ae94025171608e0661372cf846e17d062cb9620 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Fri, 7 Sep 2018 00:38:33 +0200 Subject: [PATCH 270/302] mtd: rawnand: Leave chip->IO_ADDR_{R, W} to NULL when unused There's no point in poisoning the ->IO_ADDR_{R,W}, a NULL pointer is just as good to detect unexpected ->IO_ADDR_{R,W} usage. Signed-off-by: Boris Brezillon Signed-off-by: Miquel Raynal --- drivers/mtd/nand/raw/brcmnand/brcmnand.c | 3 --- drivers/mtd/nand/raw/socrates_nand.c | 4 ---- 2 files changed, 7 deletions(-) diff --git a/drivers/mtd/nand/raw/brcmnand/brcmnand.c b/drivers/mtd/nand/raw/brcmnand/brcmnand.c index fee40a3ce5d2..851db4a7d3e4 100644 --- a/drivers/mtd/nand/raw/brcmnand/brcmnand.c +++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c @@ -2270,9 +2270,6 @@ static int brcmnand_init_cs(struct brcmnand_host *host, struct device_node *dn) mtd->owner = THIS_MODULE; mtd->dev.parent = &pdev->dev; - chip->IO_ADDR_R = (void __iomem *)0xdeadbeef; - chip->IO_ADDR_W = (void __iomem *)0xdeadbeef; - chip->cmd_ctrl = brcmnand_cmd_ctrl; chip->cmdfunc = brcmnand_cmdfunc; chip->waitfunc = brcmnand_waitfunc; diff --git a/drivers/mtd/nand/raw/socrates_nand.c b/drivers/mtd/nand/raw/socrates_nand.c index 64ea9a014054..aa42b4ea4d23 100644 --- a/drivers/mtd/nand/raw/socrates_nand.c +++ b/drivers/mtd/nand/raw/socrates_nand.c @@ -152,10 +152,6 @@ static int socrates_nand_probe(struct platform_device *ofdev) mtd->name = "socrates_nand"; mtd->dev.parent = &ofdev->dev; - /*should never be accessed directly */ - nand_chip->IO_ADDR_R = (void *)0xdeadbeef; - nand_chip->IO_ADDR_W = (void *)0xdeadbeef; - nand_chip->cmd_ctrl = socrates_nand_cmd_ctrl; nand_chip->read_byte = socrates_nand_read_byte; nand_chip->write_buf = socrates_nand_write_buf; From 82fc5099744e5f30cd8c9ee13075f28fb37e9518 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Fri, 7 Sep 2018 00:38:34 +0200 Subject: [PATCH 271/302] mtd: rawnand: Create a legacy struct and move ->IO_ADDR_{R, W} there We regularly have new NAND controller drivers that are making use of fields/hooks that we want to get rid of but can't because of all the legacy drivers that we might break if we do. So, instead of removing those fields/hooks, let's move them to a sub-struct which is clearly documented as deprecated. We start with the ->IO_ADDR_{R,W] fields. Signed-off-by: Boris Brezillon Signed-off-by: Miquel Raynal --- Documentation/driver-api/mtdnand.rst | 24 +++++++++++----------- arch/arm/mach-ep93xx/snappercl15.c | 5 +++-- arch/arm/mach-ep93xx/ts72xx.c | 6 +++--- arch/arm/mach-imx/mach-qong.c | 4 ++-- arch/arm/mach-ixp4xx/ixdp425-setup.c | 2 +- arch/arm/mach-omap1/board-nand.c | 2 +- arch/arm/mach-orion5x/ts78xx-setup.c | 6 +++--- arch/arm/mach-pxa/balloon3.c | 2 +- arch/arm/mach-pxa/em-x270.c | 6 +++--- arch/arm/mach-pxa/palmtx.c | 2 +- arch/mips/alchemy/devboards/db1200.c | 6 +++--- arch/mips/alchemy/devboards/db1300.c | 6 +++--- arch/mips/alchemy/devboards/db1550.c | 6 +++--- arch/mips/pnx833x/common/platform.c | 2 +- arch/mips/rb532/devices.c | 2 +- arch/sh/boards/mach-migor/setup.c | 6 +++--- drivers/mtd/nand/raw/ams-delta.c | 8 ++++---- drivers/mtd/nand/raw/au1550nd.c | 26 ++++++++++++------------ drivers/mtd/nand/raw/cmx270_nand.c | 16 +++++++-------- drivers/mtd/nand/raw/cs553x_nand.c | 30 ++++++++++++++-------------- drivers/mtd/nand/raw/davinci_nand.c | 24 +++++++++++----------- drivers/mtd/nand/raw/fsl_upm.c | 16 +++++++-------- drivers/mtd/nand/raw/gpio.c | 10 +++++----- drivers/mtd/nand/raw/jz4740_nand.c | 8 ++++---- drivers/mtd/nand/raw/jz4780_nand.c | 4 ++-- drivers/mtd/nand/raw/lpc32xx_mlc.c | 4 ++-- drivers/mtd/nand/raw/lpc32xx_slc.c | 4 ++-- drivers/mtd/nand/raw/nand_base.c | 12 +++++------ drivers/mtd/nand/raw/ndfc.c | 4 ++-- drivers/mtd/nand/raw/omap2.c | 30 ++++++++++++++-------------- drivers/mtd/nand/raw/orion_nand.c | 6 +++--- drivers/mtd/nand/raw/pasemi_nand.c | 22 ++++++++++---------- drivers/mtd/nand/raw/plat_nand.c | 4 ++-- drivers/mtd/nand/raw/s3c2410.c | 12 +++++------ drivers/mtd/nand/raw/sharpsl.c | 6 +++--- drivers/mtd/nand/raw/tmio_nand.c | 6 +++--- include/linux/mtd/rawnand.h | 26 ++++++++++++++++++------ 37 files changed, 190 insertions(+), 175 deletions(-) diff --git a/Documentation/driver-api/mtdnand.rst b/Documentation/driver-api/mtdnand.rst index 5470a3d6bd9e..1d2403f1d8c5 100644 --- a/Documentation/driver-api/mtdnand.rst +++ b/Documentation/driver-api/mtdnand.rst @@ -180,10 +180,10 @@ by a chip select decoder. { struct nand_chip *this = mtd_to_nand(mtd); switch(cmd){ - case NAND_CTL_SETCLE: this->IO_ADDR_W |= CLE_ADRR_BIT; break; - case NAND_CTL_CLRCLE: this->IO_ADDR_W &= ~CLE_ADRR_BIT; break; - case NAND_CTL_SETALE: this->IO_ADDR_W |= ALE_ADRR_BIT; break; - case NAND_CTL_CLRALE: this->IO_ADDR_W &= ~ALE_ADRR_BIT; break; + case NAND_CTL_SETCLE: this->legacy.IO_ADDR_W |= CLE_ADRR_BIT; break; + case NAND_CTL_CLRCLE: this->legacy.IO_ADDR_W &= ~CLE_ADRR_BIT; break; + case NAND_CTL_SETALE: this->legacy.IO_ADDR_W |= ALE_ADRR_BIT; break; + case NAND_CTL_CLRALE: this->legacy.IO_ADDR_W &= ~ALE_ADRR_BIT; break; } } @@ -235,8 +235,8 @@ necessary information about the device. } /* Set address of NAND IO lines */ - this->IO_ADDR_R = baseaddr; - this->IO_ADDR_W = baseaddr; + this->legacy.IO_ADDR_R = baseaddr; + this->legacy.IO_ADDR_W = baseaddr; /* Reference hardware control function */ this->hwcontrol = board_hwcontrol; /* Set command delay time, see datasheet for correct value */ @@ -336,17 +336,17 @@ connected to an address decoder. struct nand_chip *this = mtd_to_nand(mtd); /* Deselect all chips */ - this->IO_ADDR_R &= ~BOARD_NAND_ADDR_MASK; - this->IO_ADDR_W &= ~BOARD_NAND_ADDR_MASK; + this->legacy.IO_ADDR_R &= ~BOARD_NAND_ADDR_MASK; + this->legacy.IO_ADDR_W &= ~BOARD_NAND_ADDR_MASK; switch (chip) { case 0: - this->IO_ADDR_R |= BOARD_NAND_ADDR_CHIP0; - this->IO_ADDR_W |= BOARD_NAND_ADDR_CHIP0; + this->legacy.IO_ADDR_R |= BOARD_NAND_ADDR_CHIP0; + this->legacy.IO_ADDR_W |= BOARD_NAND_ADDR_CHIP0; break; .... case n: - this->IO_ADDR_R |= BOARD_NAND_ADDR_CHIPn; - this->IO_ADDR_W |= BOARD_NAND_ADDR_CHIPn; + this->legacy.IO_ADDR_R |= BOARD_NAND_ADDR_CHIPn; + this->legacy.IO_ADDR_W |= BOARD_NAND_ADDR_CHIPn; break; } } diff --git a/arch/arm/mach-ep93xx/snappercl15.c b/arch/arm/mach-ep93xx/snappercl15.c index aa03ea79c5f5..1dad83a0bc5b 100644 --- a/arch/arm/mach-ep93xx/snappercl15.c +++ b/arch/arm/mach-ep93xx/snappercl15.c @@ -43,7 +43,7 @@ #define SNAPPERCL15_NAND_CEN (1 << 11) /* Chip enable (active low) */ #define SNAPPERCL15_NAND_RDY (1 << 14) /* Device ready */ -#define NAND_CTRL_ADDR(chip) (chip->IO_ADDR_W + 0x40) +#define NAND_CTRL_ADDR(chip) (chip->legacy.IO_ADDR_W + 0x40) static void snappercl15_nand_cmd_ctrl(struct nand_chip *chip, int cmd, unsigned int ctrl) @@ -69,7 +69,8 @@ static void snappercl15_nand_cmd_ctrl(struct nand_chip *chip, int cmd, } if (cmd != NAND_CMD_NONE) - __raw_writew((cmd & 0xff) | nand_state, chip->IO_ADDR_W); + __raw_writew((cmd & 0xff) | nand_state, + chip->legacy.IO_ADDR_W); } static int snappercl15_nand_dev_ready(struct nand_chip *chip) diff --git a/arch/arm/mach-ep93xx/ts72xx.c b/arch/arm/mach-ep93xx/ts72xx.c index 26259dd9e951..188bf02595c5 100644 --- a/arch/arm/mach-ep93xx/ts72xx.c +++ b/arch/arm/mach-ep93xx/ts72xx.c @@ -80,7 +80,7 @@ static void ts72xx_nand_hwcontrol(struct nand_chip *chip, int cmd, unsigned int ctrl) { if (ctrl & NAND_CTRL_CHANGE) { - void __iomem *addr = chip->IO_ADDR_R; + void __iomem *addr = chip->legacy.IO_ADDR_R; unsigned char bits; addr += (1 << TS72XX_NAND_CONTROL_ADDR_LINE); @@ -94,12 +94,12 @@ static void ts72xx_nand_hwcontrol(struct nand_chip *chip, } if (cmd != NAND_CMD_NONE) - __raw_writeb(cmd, chip->IO_ADDR_W); + __raw_writeb(cmd, chip->legacy.IO_ADDR_W); } static int ts72xx_nand_device_ready(struct nand_chip *chip) { - void __iomem *addr = chip->IO_ADDR_R; + void __iomem *addr = chip->legacy.IO_ADDR_R; addr += (1 << TS72XX_NAND_BUSY_ADDR_LINE); diff --git a/arch/arm/mach-imx/mach-qong.c b/arch/arm/mach-imx/mach-qong.c index ff015f603ac9..48972944bb95 100644 --- a/arch/arm/mach-imx/mach-qong.c +++ b/arch/arm/mach-imx/mach-qong.c @@ -136,9 +136,9 @@ static void qong_nand_cmd_ctrl(struct nand_chip *nand_chip, int cmd, return; if (ctrl & NAND_CLE) - writeb(cmd, nand_chip->IO_ADDR_W + (1 << 24)); + writeb(cmd, nand_chip->legacy.IO_ADDR_W + (1 << 24)); else - writeb(cmd, nand_chip->IO_ADDR_W + (1 << 23)); + writeb(cmd, nand_chip->legacy.IO_ADDR_W + (1 << 23)); } /* diff --git a/arch/arm/mach-ixp4xx/ixdp425-setup.c b/arch/arm/mach-ixp4xx/ixdp425-setup.c index 7c39edc121ba..797e7edc7124 100644 --- a/arch/arm/mach-ixp4xx/ixdp425-setup.c +++ b/arch/arm/mach-ixp4xx/ixdp425-setup.c @@ -92,7 +92,7 @@ ixdp425_flash_nand_cmd_ctrl(struct nand_chip *this, int cmd, unsigned int ctrl) } if (cmd != NAND_CMD_NONE) - writeb(cmd, this->IO_ADDR_W + offset); + writeb(cmd, this->legacy.IO_ADDR_W + offset); } static struct platform_nand_data ixdp425_flash_nand_data = { diff --git a/arch/arm/mach-omap1/board-nand.c b/arch/arm/mach-omap1/board-nand.c index 59d56a30bc63..20923eb2d9b6 100644 --- a/arch/arm/mach-omap1/board-nand.c +++ b/arch/arm/mach-omap1/board-nand.c @@ -31,6 +31,6 @@ void omap1_nand_cmd_ctl(struct nand_chip *this, int cmd, unsigned int ctrl) if (ctrl & NAND_ALE) mask |= 0x04; - writeb(cmd, this->IO_ADDR_W + mask); + writeb(cmd, this->legacy.IO_ADDR_W + mask); } diff --git a/arch/arm/mach-orion5x/ts78xx-setup.c b/arch/arm/mach-orion5x/ts78xx-setup.c index 48d85ddf7c31..aac2c6eb35e2 100644 --- a/arch/arm/mach-orion5x/ts78xx-setup.c +++ b/arch/arm/mach-orion5x/ts78xx-setup.c @@ -145,7 +145,7 @@ static void ts78xx_ts_nand_cmd_ctrl(struct nand_chip *this, int cmd, } if (cmd != NAND_CMD_NONE) - writeb(cmd, this->IO_ADDR_W); + writeb(cmd, this->legacy.IO_ADDR_W); } static int ts78xx_ts_nand_dev_ready(struct nand_chip *chip) @@ -156,7 +156,7 @@ static int ts78xx_ts_nand_dev_ready(struct nand_chip *chip) static void ts78xx_ts_nand_write_buf(struct nand_chip *chip, const uint8_t *buf, int len) { - void __iomem *io_base = chip->IO_ADDR_W; + void __iomem *io_base = chip->legacy.IO_ADDR_W; unsigned long off = ((unsigned long)buf & 3); int sz; @@ -182,7 +182,7 @@ static void ts78xx_ts_nand_write_buf(struct nand_chip *chip, static void ts78xx_ts_nand_read_buf(struct nand_chip *chip, uint8_t *buf, int len) { - void __iomem *io_base = chip->IO_ADDR_R; + void __iomem *io_base = chip->legacy.IO_ADDR_R; unsigned long off = ((unsigned long)buf & 3); int sz; diff --git a/arch/arm/mach-pxa/balloon3.c b/arch/arm/mach-pxa/balloon3.c index 71fda90b9599..256e60c38a6d 100644 --- a/arch/arm/mach-pxa/balloon3.c +++ b/arch/arm/mach-pxa/balloon3.c @@ -597,7 +597,7 @@ static void balloon3_nand_cmd_ctl(struct nand_chip *this, int cmd, } if (cmd != NAND_CMD_NONE) - writeb(cmd, this->IO_ADDR_W); + writeb(cmd, this->legacy.IO_ADDR_W); } static void balloon3_nand_select_chip(struct nand_chip *this, int chip) diff --git a/arch/arm/mach-pxa/em-x270.c b/arch/arm/mach-pxa/em-x270.c index ba1ec9992830..3acb945a2628 100644 --- a/arch/arm/mach-pxa/em-x270.c +++ b/arch/arm/mach-pxa/em-x270.c @@ -288,7 +288,7 @@ static void nand_cs_off(void) static void em_x270_nand_cmd_ctl(struct nand_chip *this, int dat, unsigned int ctrl) { - unsigned long nandaddr = (unsigned long)this->IO_ADDR_W; + unsigned long nandaddr = (unsigned long)this->legacy.IO_ADDR_W; dsb(); @@ -308,9 +308,9 @@ static void em_x270_nand_cmd_ctl(struct nand_chip *this, int dat, } dsb(); - this->IO_ADDR_W = (void __iomem *)nandaddr; + this->legacy.IO_ADDR_W = (void __iomem *)nandaddr; if (dat != NAND_CMD_NONE) - writel(dat, this->IO_ADDR_W); + writel(dat, this->legacy.IO_ADDR_W); dsb(); } diff --git a/arch/arm/mach-pxa/palmtx.c b/arch/arm/mach-pxa/palmtx.c index ed9661e70b83..36ea32c1bbcc 100644 --- a/arch/arm/mach-pxa/palmtx.c +++ b/arch/arm/mach-pxa/palmtx.c @@ -250,7 +250,7 @@ static inline void palmtx_keys_init(void) {} static void palmtx_nand_cmd_ctl(struct nand_chip *this, int cmd, unsigned int ctrl) { - char __iomem *nandaddr = this->IO_ADDR_W; + char __iomem *nandaddr = this->legacy.IO_ADDR_W; if (cmd == NAND_CMD_NONE) return; diff --git a/arch/mips/alchemy/devboards/db1200.c b/arch/mips/alchemy/devboards/db1200.c index f043615c1a99..97dc74f7f41a 100644 --- a/arch/mips/alchemy/devboards/db1200.c +++ b/arch/mips/alchemy/devboards/db1200.c @@ -200,7 +200,7 @@ static struct i2c_board_info db1200_i2c_devs[] __initdata = { static void au1200_nand_cmd_ctrl(struct nand_chip *this, int cmd, unsigned int ctrl) { - unsigned long ioaddr = (unsigned long)this->IO_ADDR_W; + unsigned long ioaddr = (unsigned long)this->legacy.IO_ADDR_W; ioaddr &= 0xffffff00; @@ -212,9 +212,9 @@ static void au1200_nand_cmd_ctrl(struct nand_chip *this, int cmd, /* assume we want to r/w real data by default */ ioaddr += MEM_STNAND_DATA; } - this->IO_ADDR_R = this->IO_ADDR_W = (void __iomem *)ioaddr; + this->legacy.IO_ADDR_R = this->legacy.IO_ADDR_W = (void __iomem *)ioaddr; if (cmd != NAND_CMD_NONE) { - __raw_writeb(cmd, this->IO_ADDR_W); + __raw_writeb(cmd, this->legacy.IO_ADDR_W); wmb(); } } diff --git a/arch/mips/alchemy/devboards/db1300.c b/arch/mips/alchemy/devboards/db1300.c index 1201fa655e78..b813dc1c1682 100644 --- a/arch/mips/alchemy/devboards/db1300.c +++ b/arch/mips/alchemy/devboards/db1300.c @@ -152,7 +152,7 @@ static void __init db1300_gpio_config(void) static void au1300_nand_cmd_ctrl(struct nand_chip *this, int cmd, unsigned int ctrl) { - unsigned long ioaddr = (unsigned long)this->IO_ADDR_W; + unsigned long ioaddr = (unsigned long)this->legacy.IO_ADDR_W; ioaddr &= 0xffffff00; @@ -164,9 +164,9 @@ static void au1300_nand_cmd_ctrl(struct nand_chip *this, int cmd, /* assume we want to r/w real data by default */ ioaddr += MEM_STNAND_DATA; } - this->IO_ADDR_R = this->IO_ADDR_W = (void __iomem *)ioaddr; + this->legacy.IO_ADDR_R = this->legacy.IO_ADDR_W = (void __iomem *)ioaddr; if (cmd != NAND_CMD_NONE) { - __raw_writeb(cmd, this->IO_ADDR_W); + __raw_writeb(cmd, this->legacy.IO_ADDR_W); wmb(); } } diff --git a/arch/mips/alchemy/devboards/db1550.c b/arch/mips/alchemy/devboards/db1550.c index cae39cde5de6..65f6b7184fbe 100644 --- a/arch/mips/alchemy/devboards/db1550.c +++ b/arch/mips/alchemy/devboards/db1550.c @@ -129,7 +129,7 @@ static struct i2c_board_info db1550_i2c_devs[] __initdata = { static void au1550_nand_cmd_ctrl(struct nand_chip *this, int cmd, unsigned int ctrl) { - unsigned long ioaddr = (unsigned long)this->IO_ADDR_W; + unsigned long ioaddr = (unsigned long)this->legacy.IO_ADDR_W; ioaddr &= 0xffffff00; @@ -141,9 +141,9 @@ static void au1550_nand_cmd_ctrl(struct nand_chip *this, int cmd, /* assume we want to r/w real data by default */ ioaddr += MEM_STNAND_DATA; } - this->IO_ADDR_R = this->IO_ADDR_W = (void __iomem *)ioaddr; + this->legacy.IO_ADDR_R = this->legacy.IO_ADDR_W = (void __iomem *)ioaddr; if (cmd != NAND_CMD_NONE) { - __raw_writeb(cmd, this->IO_ADDR_W); + __raw_writeb(cmd, this->legacy.IO_ADDR_W); wmb(); } } diff --git a/arch/mips/pnx833x/common/platform.c b/arch/mips/pnx833x/common/platform.c index ca8a2889431e..33d0f070b33d 100644 --- a/arch/mips/pnx833x/common/platform.c +++ b/arch/mips/pnx833x/common/platform.c @@ -180,7 +180,7 @@ static struct platform_device pnx833x_sata_device = { static void pnx833x_flash_nand_cmd_ctrl(struct nand_chip *this, int cmd, unsigned int ctrl) { - unsigned long nandaddr = (unsigned long)this->IO_ADDR_W; + unsigned long nandaddr = (unsigned long)this->legacy.IO_ADDR_W; if (cmd == NAND_CMD_NONE) return; diff --git a/arch/mips/rb532/devices.c b/arch/mips/rb532/devices.c index 9173949892ed..02a9e042fb44 100644 --- a/arch/mips/rb532/devices.c +++ b/arch/mips/rb532/devices.c @@ -160,7 +160,7 @@ static void rb532_cmd_ctrl(struct nand_chip *chip, int cmd, unsigned int ctrl) set_latch_u5(orbits, nandbits); } if (cmd != NAND_CMD_NONE) - writeb(cmd, chip->IO_ADDR_W); + writeb(cmd, chip->legacy.IO_ADDR_W); } static struct resource nand_slot0_res[] = { diff --git a/arch/sh/boards/mach-migor/setup.c b/arch/sh/boards/mach-migor/setup.c index 833f3e49027b..ebcc4d5a67ce 100644 --- a/arch/sh/boards/mach-migor/setup.c +++ b/arch/sh/boards/mach-migor/setup.c @@ -172,11 +172,11 @@ static void migor_nand_flash_cmd_ctl(struct nand_chip *chip, int cmd, return; if (ctrl & NAND_CLE) - writeb(cmd, chip->IO_ADDR_W + 0x00400000); + writeb(cmd, chip->legacy.IO_ADDR_W + 0x00400000); else if (ctrl & NAND_ALE) - writeb(cmd, chip->IO_ADDR_W + 0x00800000); + writeb(cmd, chip->legacy.IO_ADDR_W + 0x00800000); else - writeb(cmd, chip->IO_ADDR_W); + writeb(cmd, chip->legacy.IO_ADDR_W); } static int migor_nand_flash_ready(struct nand_chip *chip) diff --git a/drivers/mtd/nand/raw/ams-delta.c b/drivers/mtd/nand/raw/ams-delta.c index 48413203dbc2..5bc8b29faf6d 100644 --- a/drivers/mtd/nand/raw/ams-delta.c +++ b/drivers/mtd/nand/raw/ams-delta.c @@ -68,7 +68,7 @@ static void ams_delta_write_byte(struct nand_chip *this, u_char byte) void __iomem *io_base = (void __iomem *)nand_get_controller_data(this); writew(0, io_base + OMAP_MPUIO_IO_CNTL); - writew(byte, this->IO_ADDR_W); + writew(byte, this->legacy.IO_ADDR_W); gpio_set_value(AMS_DELTA_GPIO_PIN_NAND_NWE, 0); ndelay(40); gpio_set_value(AMS_DELTA_GPIO_PIN_NAND_NWE, 1); @@ -82,7 +82,7 @@ static u_char ams_delta_read_byte(struct nand_chip *this) gpio_set_value(AMS_DELTA_GPIO_PIN_NAND_NRE, 0); ndelay(40); writew(~0, io_base + OMAP_MPUIO_IO_CNTL); - res = readw(this->IO_ADDR_R); + res = readw(this->legacy.IO_ADDR_R); gpio_set_value(AMS_DELTA_GPIO_PIN_NAND_NRE, 1); return res; @@ -208,8 +208,8 @@ static int ams_delta_init(struct platform_device *pdev) nand_set_controller_data(this, (void *)io_base); /* Set address of NAND IO lines */ - this->IO_ADDR_R = io_base + OMAP_MPUIO_INPUT_LATCH; - this->IO_ADDR_W = io_base + OMAP_MPUIO_OUTPUT; + this->legacy.IO_ADDR_R = io_base + OMAP_MPUIO_INPUT_LATCH; + this->legacy.IO_ADDR_W = io_base + OMAP_MPUIO_OUTPUT; this->read_byte = ams_delta_read_byte; this->write_buf = ams_delta_write_buf; this->read_buf = ams_delta_read_buf; diff --git a/drivers/mtd/nand/raw/au1550nd.c b/drivers/mtd/nand/raw/au1550nd.c index d0ec8606e769..b7bb2b2af4ef 100644 --- a/drivers/mtd/nand/raw/au1550nd.c +++ b/drivers/mtd/nand/raw/au1550nd.c @@ -35,7 +35,7 @@ struct au1550nd_ctx { */ static u_char au_read_byte(struct nand_chip *this) { - u_char ret = readb(this->IO_ADDR_R); + u_char ret = readb(this->legacy.IO_ADDR_R); wmb(); /* drain writebuffer */ return ret; } @@ -49,7 +49,7 @@ static u_char au_read_byte(struct nand_chip *this) */ static void au_write_byte(struct nand_chip *this, u_char byte) { - writeb(byte, this->IO_ADDR_W); + writeb(byte, this->legacy.IO_ADDR_W); wmb(); /* drain writebuffer */ } @@ -61,7 +61,7 @@ static void au_write_byte(struct nand_chip *this, u_char byte) */ static u_char au_read_byte16(struct nand_chip *this) { - u_char ret = (u_char) cpu_to_le16(readw(this->IO_ADDR_R)); + u_char ret = (u_char) cpu_to_le16(readw(this->legacy.IO_ADDR_R)); wmb(); /* drain writebuffer */ return ret; } @@ -75,7 +75,7 @@ static u_char au_read_byte16(struct nand_chip *this) */ static void au_write_byte16(struct nand_chip *this, u_char byte) { - writew(le16_to_cpu((u16) byte), this->IO_ADDR_W); + writew(le16_to_cpu((u16) byte), this->legacy.IO_ADDR_W); wmb(); /* drain writebuffer */ } @@ -92,7 +92,7 @@ static void au_write_buf(struct nand_chip *this, const u_char *buf, int len) int i; for (i = 0; i < len; i++) { - writeb(buf[i], this->IO_ADDR_W); + writeb(buf[i], this->legacy.IO_ADDR_W); wmb(); /* drain writebuffer */ } } @@ -110,7 +110,7 @@ static void au_read_buf(struct nand_chip *this, u_char *buf, int len) int i; for (i = 0; i < len; i++) { - buf[i] = readb(this->IO_ADDR_R); + buf[i] = readb(this->legacy.IO_ADDR_R); wmb(); /* drain writebuffer */ } } @@ -130,7 +130,7 @@ static void au_write_buf16(struct nand_chip *this, const u_char *buf, int len) len >>= 1; for (i = 0; i < len; i++) { - writew(p[i], this->IO_ADDR_W); + writew(p[i], this->legacy.IO_ADDR_W); wmb(); /* drain writebuffer */ } @@ -152,7 +152,7 @@ static void au_read_buf16(struct mtd_info *mtd, u_char *buf, int len) len >>= 1; for (i = 0; i < len; i++) { - p[i] = readw(this->IO_ADDR_R); + p[i] = readw(this->legacy.IO_ADDR_R); wmb(); /* drain writebuffer */ } } @@ -179,19 +179,19 @@ static void au1550_hwcontrol(struct mtd_info *mtd, int cmd) switch (cmd) { case NAND_CTL_SETCLE: - this->IO_ADDR_W = ctx->base + MEM_STNAND_CMD; + this->legacy.IO_ADDR_W = ctx->base + MEM_STNAND_CMD; break; case NAND_CTL_CLRCLE: - this->IO_ADDR_W = ctx->base + MEM_STNAND_DATA; + this->legacy.IO_ADDR_W = ctx->base + MEM_STNAND_DATA; break; case NAND_CTL_SETALE: - this->IO_ADDR_W = ctx->base + MEM_STNAND_ADDR; + this->legacy.IO_ADDR_W = ctx->base + MEM_STNAND_ADDR; break; case NAND_CTL_CLRALE: - this->IO_ADDR_W = ctx->base + MEM_STNAND_DATA; + this->legacy.IO_ADDR_W = ctx->base + MEM_STNAND_DATA; /* FIXME: Nobody knows why this is necessary, * but it works only that way */ udelay(1); @@ -208,7 +208,7 @@ static void au1550_hwcontrol(struct mtd_info *mtd, int cmd) break; } - this->IO_ADDR_R = this->IO_ADDR_W; + this->legacy.IO_ADDR_R = this->legacy.IO_ADDR_W; wmb(); /* Drain the writebuffer */ } diff --git a/drivers/mtd/nand/raw/cmx270_nand.c b/drivers/mtd/nand/raw/cmx270_nand.c index e8458036419b..b4ed69815bed 100644 --- a/drivers/mtd/nand/raw/cmx270_nand.c +++ b/drivers/mtd/nand/raw/cmx270_nand.c @@ -51,7 +51,7 @@ static const struct mtd_partition partition_info[] = { static u_char cmx270_read_byte(struct nand_chip *this) { - return (readl(this->IO_ADDR_R) >> 16); + return (readl(this->legacy.IO_ADDR_R) >> 16); } static void cmx270_write_buf(struct nand_chip *this, const u_char *buf, @@ -60,7 +60,7 @@ static void cmx270_write_buf(struct nand_chip *this, const u_char *buf, int i; for (i=0; iIO_ADDR_W); + writel((*buf++ << 16), this->legacy.IO_ADDR_W); } static void cmx270_read_buf(struct nand_chip *this, u_char *buf, int len) @@ -68,7 +68,7 @@ static void cmx270_read_buf(struct nand_chip *this, u_char *buf, int len) int i; for (i=0; iIO_ADDR_R) >> 16; + *buf++ = readl(this->legacy.IO_ADDR_R) >> 16; } static inline void nand_cs_on(void) @@ -89,7 +89,7 @@ static void nand_cs_off(void) static void cmx270_hwcontrol(struct nand_chip *this, int dat, unsigned int ctrl) { - unsigned int nandaddr = (unsigned int)this->IO_ADDR_W; + unsigned int nandaddr = (unsigned int)this->legacy.IO_ADDR_W; dsb(); @@ -109,9 +109,9 @@ static void cmx270_hwcontrol(struct nand_chip *this, int dat, } dsb(); - this->IO_ADDR_W = (void __iomem*)nandaddr; + this->legacy.IO_ADDR_W = (void __iomem*)nandaddr; if (dat != NAND_CMD_NONE) - writel((dat << 16), this->IO_ADDR_W); + writel((dat << 16), this->legacy.IO_ADDR_W); dsb(); } @@ -173,8 +173,8 @@ static int __init cmx270_init(void) cmx270_nand_mtd->owner = THIS_MODULE; /* insert callbacks */ - this->IO_ADDR_R = cmx270_nand_io; - this->IO_ADDR_W = cmx270_nand_io; + this->legacy.IO_ADDR_R = cmx270_nand_io; + this->legacy.IO_ADDR_W = cmx270_nand_io; this->cmd_ctrl = cmx270_hwcontrol; this->dev_ready = cmx270_device_ready; diff --git a/drivers/mtd/nand/raw/cs553x_nand.c b/drivers/mtd/nand/raw/cs553x_nand.c index c1628c03282a..b03fb36e9e69 100644 --- a/drivers/mtd/nand/raw/cs553x_nand.c +++ b/drivers/mtd/nand/raw/cs553x_nand.c @@ -96,43 +96,43 @@ static void cs553x_read_buf(struct nand_chip *this, u_char *buf, int len) { while (unlikely(len > 0x800)) { - memcpy_fromio(buf, this->IO_ADDR_R, 0x800); + memcpy_fromio(buf, this->legacy.IO_ADDR_R, 0x800); buf += 0x800; len -= 0x800; } - memcpy_fromio(buf, this->IO_ADDR_R, len); + memcpy_fromio(buf, this->legacy.IO_ADDR_R, len); } static void cs553x_write_buf(struct nand_chip *this, const u_char *buf, int len) { while (unlikely(len > 0x800)) { - memcpy_toio(this->IO_ADDR_R, buf, 0x800); + memcpy_toio(this->legacy.IO_ADDR_R, buf, 0x800); buf += 0x800; len -= 0x800; } - memcpy_toio(this->IO_ADDR_R, buf, len); + memcpy_toio(this->legacy.IO_ADDR_R, buf, len); } static unsigned char cs553x_read_byte(struct nand_chip *this) { - return readb(this->IO_ADDR_R); + return readb(this->legacy.IO_ADDR_R); } static void cs553x_write_byte(struct nand_chip *this, u_char byte) { int i = 100000; - while (i && readb(this->IO_ADDR_R + MM_NAND_STS) & CS_NAND_CTLR_BUSY) { + while (i && readb(this->legacy.IO_ADDR_R + MM_NAND_STS) & CS_NAND_CTLR_BUSY) { udelay(1); i--; } - writeb(byte, this->IO_ADDR_W + 0x801); + writeb(byte, this->legacy.IO_ADDR_W + 0x801); } static void cs553x_hwcontrol(struct nand_chip *this, int cmd, unsigned int ctrl) { - void __iomem *mmio_base = this->IO_ADDR_R; + void __iomem *mmio_base = this->legacy.IO_ADDR_R; if (ctrl & NAND_CTRL_CHANGE) { unsigned char ctl = (ctrl & ~NAND_CTRL_CHANGE ) ^ 0x01; writeb(ctl, mmio_base + MM_NAND_CTL); @@ -143,7 +143,7 @@ static void cs553x_hwcontrol(struct nand_chip *this, int cmd, static int cs553x_device_ready(struct nand_chip *this) { - void __iomem *mmio_base = this->IO_ADDR_R; + void __iomem *mmio_base = this->legacy.IO_ADDR_R; unsigned char foo = readb(mmio_base + MM_NAND_STS); return (foo & CS_NAND_STS_FLASH_RDY) && !(foo & CS_NAND_CTLR_BUSY); @@ -151,7 +151,7 @@ static int cs553x_device_ready(struct nand_chip *this) static void cs_enable_hwecc(struct nand_chip *this, int mode) { - void __iomem *mmio_base = this->IO_ADDR_R; + void __iomem *mmio_base = this->legacy.IO_ADDR_R; writeb(0x07, mmio_base + MM_NAND_ECC_CTL); } @@ -160,7 +160,7 @@ static int cs_calculate_ecc(struct nand_chip *this, const u_char *dat, u_char *ecc_code) { uint32_t ecc; - void __iomem *mmio_base = this->IO_ADDR_R; + void __iomem *mmio_base = this->legacy.IO_ADDR_R; ecc = readl(mmio_base + MM_NAND_STS); @@ -199,8 +199,8 @@ static int __init cs553x_init_one(int cs, int mmio, unsigned long adr) new_mtd->owner = THIS_MODULE; /* map physical address */ - this->IO_ADDR_R = this->IO_ADDR_W = ioremap(adr, 4096); - if (!this->IO_ADDR_R) { + this->legacy.IO_ADDR_R = this->legacy.IO_ADDR_W = ioremap(adr, 4096); + if (!this->legacy.IO_ADDR_R) { pr_warn("ioremap cs553x NAND @0x%08lx failed\n", adr); err = -EIO; goto out_mtd; @@ -242,7 +242,7 @@ static int __init cs553x_init_one(int cs, int mmio, unsigned long adr) out_free: kfree(new_mtd->name); out_ior: - iounmap(this->IO_ADDR_R); + iounmap(this->legacy.IO_ADDR_R); out_mtd: kfree(this); out: @@ -324,7 +324,7 @@ static void __exit cs553x_cleanup(void) continue; this = mtd_to_nand(mtd); - mmio_base = this->IO_ADDR_R; + mmio_base = this->legacy.IO_ADDR_R; /* Release resources, unregister device */ nand_release(this); diff --git a/drivers/mtd/nand/raw/davinci_nand.c b/drivers/mtd/nand/raw/davinci_nand.c index 4b261c73b240..1204b5120176 100644 --- a/drivers/mtd/nand/raw/davinci_nand.c +++ b/drivers/mtd/nand/raw/davinci_nand.c @@ -110,11 +110,11 @@ static void nand_davinci_hwcontrol(struct nand_chip *nand, int cmd, else if ((ctrl & NAND_CTRL_ALE) == NAND_CTRL_ALE) addr += info->mask_ale; - nand->IO_ADDR_W = addr; + nand->legacy.IO_ADDR_W = addr; } if (cmd != NAND_CMD_NONE) - iowrite8(cmd, nand->IO_ADDR_W); + iowrite8(cmd, nand->legacy.IO_ADDR_W); } static void nand_davinci_select_chip(struct nand_chip *nand, int chip) @@ -127,8 +127,8 @@ static void nand_davinci_select_chip(struct nand_chip *nand, int chip) if (chip > 0) info->current_cs += info->mask_chipsel; - info->chip.IO_ADDR_W = info->current_cs; - info->chip.IO_ADDR_R = info->chip.IO_ADDR_W; + info->chip.legacy.IO_ADDR_W = info->current_cs; + info->chip.legacy.IO_ADDR_R = info->chip.legacy.IO_ADDR_W; } /*----------------------------------------------------------------------*/ @@ -438,22 +438,22 @@ static void nand_davinci_read_buf(struct nand_chip *chip, uint8_t *buf, int len) { if ((0x03 & ((uintptr_t)buf)) == 0 && (0x03 & len) == 0) - ioread32_rep(chip->IO_ADDR_R, buf, len >> 2); + ioread32_rep(chip->legacy.IO_ADDR_R, buf, len >> 2); else if ((0x01 & ((uintptr_t)buf)) == 0 && (0x01 & len) == 0) - ioread16_rep(chip->IO_ADDR_R, buf, len >> 1); + ioread16_rep(chip->legacy.IO_ADDR_R, buf, len >> 1); else - ioread8_rep(chip->IO_ADDR_R, buf, len); + ioread8_rep(chip->legacy.IO_ADDR_R, buf, len); } static void nand_davinci_write_buf(struct nand_chip *chip, const uint8_t *buf, int len) { if ((0x03 & ((uintptr_t)buf)) == 0 && (0x03 & len) == 0) - iowrite32_rep(chip->IO_ADDR_R, buf, len >> 2); + iowrite32_rep(chip->legacy.IO_ADDR_R, buf, len >> 2); else if ((0x01 & ((uintptr_t)buf)) == 0 && (0x01 & len) == 0) - iowrite16_rep(chip->IO_ADDR_R, buf, len >> 1); + iowrite16_rep(chip->legacy.IO_ADDR_R, buf, len >> 1); else - iowrite8_rep(chip->IO_ADDR_R, buf, len); + iowrite8_rep(chip->legacy.IO_ADDR_R, buf, len); } /* @@ -759,8 +759,8 @@ static int nand_davinci_probe(struct platform_device *pdev) mtd->dev.parent = &pdev->dev; nand_set_flash_node(&info->chip, pdev->dev.of_node); - info->chip.IO_ADDR_R = vaddr; - info->chip.IO_ADDR_W = vaddr; + info->chip.legacy.IO_ADDR_R = vaddr; + info->chip.legacy.IO_ADDR_W = vaddr; info->chip.chip_delay = 0; info->chip.select_chip = nand_davinci_select_chip; diff --git a/drivers/mtd/nand/raw/fsl_upm.c b/drivers/mtd/nand/raw/fsl_upm.c index 48c5215f9a0e..f59fd57fc529 100644 --- a/drivers/mtd/nand/raw/fsl_upm.c +++ b/drivers/mtd/nand/raw/fsl_upm.c @@ -101,7 +101,7 @@ static void fun_cmd_ctrl(struct nand_chip *chip, int cmd, unsigned int ctrl) mar = (cmd << (32 - fun->upm.width)) | fun->mchip_offsets[fun->mchip_number]; - fsl_upm_run_pattern(&fun->upm, chip->IO_ADDR_R, mar); + fsl_upm_run_pattern(&fun->upm, chip->legacy.IO_ADDR_R, mar); if (fun->wait_flags & FSL_UPM_WAIT_RUN_PATTERN) fun_wait_rnb(fun); @@ -115,8 +115,8 @@ static void fun_select_chip(struct nand_chip *chip, int mchip_nr) chip->cmd_ctrl(chip, NAND_CMD_NONE, 0 | NAND_CTRL_CHANGE); } else if (mchip_nr >= 0 && mchip_nr < NAND_MAX_CHIPS) { fun->mchip_number = mchip_nr; - chip->IO_ADDR_R = fun->io_base + fun->mchip_offsets[mchip_nr]; - chip->IO_ADDR_W = chip->IO_ADDR_R; + chip->legacy.IO_ADDR_R = fun->io_base + fun->mchip_offsets[mchip_nr]; + chip->legacy.IO_ADDR_W = chip->legacy.IO_ADDR_R; } else { BUG(); } @@ -126,7 +126,7 @@ static uint8_t fun_read_byte(struct nand_chip *chip) { struct fsl_upm_nand *fun = to_fsl_upm_nand(nand_to_mtd(chip)); - return in_8(fun->chip.IO_ADDR_R); + return in_8(fun->chip.legacy.IO_ADDR_R); } static void fun_read_buf(struct nand_chip *chip, uint8_t *buf, int len) @@ -135,7 +135,7 @@ static void fun_read_buf(struct nand_chip *chip, uint8_t *buf, int len) int i; for (i = 0; i < len; i++) - buf[i] = in_8(fun->chip.IO_ADDR_R); + buf[i] = in_8(fun->chip.legacy.IO_ADDR_R); } static void fun_write_buf(struct nand_chip *chip, const uint8_t *buf, int len) @@ -144,7 +144,7 @@ static void fun_write_buf(struct nand_chip *chip, const uint8_t *buf, int len) int i; for (i = 0; i < len; i++) { - out_8(fun->chip.IO_ADDR_W, buf[i]); + out_8(fun->chip.legacy.IO_ADDR_W, buf[i]); if (fun->wait_flags & FSL_UPM_WAIT_WRITE_BYTE) fun_wait_rnb(fun); } @@ -160,8 +160,8 @@ static int fun_chip_init(struct fsl_upm_nand *fun, int ret; struct device_node *flash_np; - fun->chip.IO_ADDR_R = fun->io_base; - fun->chip.IO_ADDR_W = fun->io_base; + fun->chip.legacy.IO_ADDR_R = fun->io_base; + fun->chip.legacy.IO_ADDR_W = fun->io_base; fun->chip.cmd_ctrl = fun_cmd_ctrl; fun->chip.chip_delay = fun->chip_delay; fun->chip.read_byte = fun_read_byte; diff --git a/drivers/mtd/nand/raw/gpio.c b/drivers/mtd/nand/raw/gpio.c index 273437c1ae6c..bb43fad65362 100644 --- a/drivers/mtd/nand/raw/gpio.c +++ b/drivers/mtd/nand/raw/gpio.c @@ -90,7 +90,7 @@ static void gpio_nand_cmd_ctrl(struct nand_chip *chip, int cmd, if (cmd == NAND_CMD_NONE) return; - writeb(cmd, gpiomtd->nand_chip.IO_ADDR_W); + writeb(cmd, gpiomtd->nand_chip.legacy.IO_ADDR_W); gpio_nand_dosync(gpiomtd); } @@ -225,9 +225,9 @@ static int gpio_nand_probe(struct platform_device *pdev) chip = &gpiomtd->nand_chip; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - chip->IO_ADDR_R = devm_ioremap_resource(dev, res); - if (IS_ERR(chip->IO_ADDR_R)) - return PTR_ERR(chip->IO_ADDR_R); + chip->legacy.IO_ADDR_R = devm_ioremap_resource(dev, res); + if (IS_ERR(chip->legacy.IO_ADDR_R)) + return PTR_ERR(chip->legacy.IO_ADDR_R); res = gpio_nand_get_io_sync(pdev); if (res) { @@ -274,7 +274,7 @@ static int gpio_nand_probe(struct platform_device *pdev) chip->dev_ready = gpio_nand_devready; nand_set_flash_node(chip, pdev->dev.of_node); - chip->IO_ADDR_W = chip->IO_ADDR_R; + chip->legacy.IO_ADDR_W = chip->legacy.IO_ADDR_R; chip->ecc.mode = NAND_ECC_SOFT; chip->ecc.algo = NAND_ECC_HAMMING; chip->options = gpiomtd->plat.options; diff --git a/drivers/mtd/nand/raw/jz4740_nand.c b/drivers/mtd/nand/raw/jz4740_nand.c index 946a71cf816d..449180de92e2 100644 --- a/drivers/mtd/nand/raw/jz4740_nand.c +++ b/drivers/mtd/nand/raw/jz4740_nand.c @@ -91,8 +91,8 @@ static void jz_nand_select_chip(struct nand_chip *chip, int chipnr) banknr = -1; } else { banknr = nand->banks[chipnr] - 1; - chip->IO_ADDR_R = nand->bank_base[banknr]; - chip->IO_ADDR_W = nand->bank_base[banknr]; + chip->legacy.IO_ADDR_R = nand->bank_base[banknr]; + chip->legacy.IO_ADDR_W = nand->bank_base[banknr]; } writel(ctrl, nand->base + JZ_REG_NAND_CTRL); @@ -114,7 +114,7 @@ static void jz_nand_cmd_ctrl(struct nand_chip *chip, int dat, bank_base += JZ_NAND_MEM_ADDR_OFFSET; else if (ctrl & NAND_CLE) bank_base += JZ_NAND_MEM_CMD_OFFSET; - chip->IO_ADDR_W = bank_base; + chip->legacy.IO_ADDR_W = bank_base; reg = readl(nand->base + JZ_REG_NAND_CTRL); if (ctrl & NAND_NCE) @@ -124,7 +124,7 @@ static void jz_nand_cmd_ctrl(struct nand_chip *chip, int dat, writel(reg, nand->base + JZ_REG_NAND_CTRL); } if (dat != NAND_CMD_NONE) - writeb(dat, chip->IO_ADDR_W); + writeb(dat, chip->legacy.IO_ADDR_W); } static int jz_nand_dev_ready(struct nand_chip *chip) diff --git a/drivers/mtd/nand/raw/jz4780_nand.c b/drivers/mtd/nand/raw/jz4780_nand.c index d54b2774f7f9..89909a17242d 100644 --- a/drivers/mtd/nand/raw/jz4780_nand.c +++ b/drivers/mtd/nand/raw/jz4780_nand.c @@ -275,8 +275,8 @@ static int jz4780_nand_init_chip(struct platform_device *pdev, return -ENOMEM; mtd->dev.parent = dev; - chip->IO_ADDR_R = cs->base + OFFSET_DATA; - chip->IO_ADDR_W = cs->base + OFFSET_DATA; + chip->legacy.IO_ADDR_R = cs->base + OFFSET_DATA; + chip->legacy.IO_ADDR_W = cs->base + OFFSET_DATA; chip->chip_delay = RB_DELAY_US; chip->options = NAND_NO_SUBPAGE_WRITE; chip->select_chip = jz4780_nand_select_chip; diff --git a/drivers/mtd/nand/raw/lpc32xx_mlc.c b/drivers/mtd/nand/raw/lpc32xx_mlc.c index ae31f6ccbeb3..cc1c6e6c59e1 100644 --- a/drivers/mtd/nand/raw/lpc32xx_mlc.c +++ b/drivers/mtd/nand/raw/lpc32xx_mlc.c @@ -742,8 +742,8 @@ static int lpc32xx_nand_probe(struct platform_device *pdev) nand_chip->cmd_ctrl = lpc32xx_nand_cmd_ctrl; nand_chip->dev_ready = lpc32xx_nand_device_ready; nand_chip->chip_delay = 25; /* us */ - nand_chip->IO_ADDR_R = MLC_DATA(host->io_base); - nand_chip->IO_ADDR_W = MLC_DATA(host->io_base); + nand_chip->legacy.IO_ADDR_R = MLC_DATA(host->io_base); + nand_chip->legacy.IO_ADDR_W = MLC_DATA(host->io_base); /* Init NAND controller */ lpc32xx_nand_setup(host); diff --git a/drivers/mtd/nand/raw/lpc32xx_slc.c b/drivers/mtd/nand/raw/lpc32xx_slc.c index 26d27a81f814..8a6f109c43af 100644 --- a/drivers/mtd/nand/raw/lpc32xx_slc.c +++ b/drivers/mtd/nand/raw/lpc32xx_slc.c @@ -878,8 +878,8 @@ static int lpc32xx_nand_probe(struct platform_device *pdev) goto enable_wp; /* Set NAND IO addresses and command/ready functions */ - chip->IO_ADDR_R = SLC_DATA(host->io_base); - chip->IO_ADDR_W = SLC_DATA(host->io_base); + chip->legacy.IO_ADDR_R = SLC_DATA(host->io_base); + chip->legacy.IO_ADDR_W = SLC_DATA(host->io_base); chip->cmd_ctrl = lpc32xx_nand_cmd_ctrl; chip->dev_ready = lpc32xx_nand_device_ready; chip->chip_delay = 20; /* 20us command delay time */ diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c index e63dfad8235b..1edaa9fdbce9 100644 --- a/drivers/mtd/nand/raw/nand_base.c +++ b/drivers/mtd/nand/raw/nand_base.c @@ -260,7 +260,7 @@ static void nand_release_device(struct mtd_info *mtd) */ static uint8_t nand_read_byte(struct nand_chip *chip) { - return readb(chip->IO_ADDR_R); + return readb(chip->legacy.IO_ADDR_R); } /** @@ -272,7 +272,7 @@ static uint8_t nand_read_byte(struct nand_chip *chip) */ static uint8_t nand_read_byte16(struct nand_chip *chip) { - return (uint8_t) cpu_to_le16(readw(chip->IO_ADDR_R)); + return (uint8_t) cpu_to_le16(readw(chip->legacy.IO_ADDR_R)); } /** @@ -348,7 +348,7 @@ static void nand_write_byte16(struct nand_chip *chip, uint8_t byte) */ static void nand_write_buf(struct nand_chip *chip, const uint8_t *buf, int len) { - iowrite8_rep(chip->IO_ADDR_W, buf, len); + iowrite8_rep(chip->legacy.IO_ADDR_W, buf, len); } /** @@ -361,7 +361,7 @@ static void nand_write_buf(struct nand_chip *chip, const uint8_t *buf, int len) */ static void nand_read_buf(struct nand_chip *chip, uint8_t *buf, int len) { - ioread8_rep(chip->IO_ADDR_R, buf, len); + ioread8_rep(chip->legacy.IO_ADDR_R, buf, len); } /** @@ -377,7 +377,7 @@ static void nand_write_buf16(struct nand_chip *chip, const uint8_t *buf, { u16 *p = (u16 *) buf; - iowrite16_rep(chip->IO_ADDR_W, p, len >> 1); + iowrite16_rep(chip->legacy.IO_ADDR_W, p, len >> 1); } /** @@ -392,7 +392,7 @@ static void nand_read_buf16(struct nand_chip *chip, uint8_t *buf, int len) { u16 *p = (u16 *) buf; - ioread16_rep(chip->IO_ADDR_R, p, len >> 1); + ioread16_rep(chip->legacy.IO_ADDR_R, p, len >> 1); } /** diff --git a/drivers/mtd/nand/raw/ndfc.c b/drivers/mtd/nand/raw/ndfc.c index b96070a3afff..adc4060c65ad 100644 --- a/drivers/mtd/nand/raw/ndfc.c +++ b/drivers/mtd/nand/raw/ndfc.c @@ -142,8 +142,8 @@ static int ndfc_chip_init(struct ndfc_controller *ndfc, struct mtd_info *mtd = nand_to_mtd(chip); int ret; - chip->IO_ADDR_R = ndfc->ndfcbase + NDFC_DATA; - chip->IO_ADDR_W = ndfc->ndfcbase + NDFC_DATA; + chip->legacy.IO_ADDR_R = ndfc->ndfcbase + NDFC_DATA; + chip->legacy.IO_ADDR_W = ndfc->ndfcbase + NDFC_DATA; chip->cmd_ctrl = ndfc_hwcontrol; chip->dev_ready = ndfc_ready; chip->select_chip = ndfc_select_chip; diff --git a/drivers/mtd/nand/raw/omap2.c b/drivers/mtd/nand/raw/omap2.c index 6f0fec3596cc..627048886c95 100644 --- a/drivers/mtd/nand/raw/omap2.c +++ b/drivers/mtd/nand/raw/omap2.c @@ -275,7 +275,7 @@ static void omap_read_buf8(struct mtd_info *mtd, u_char *buf, int len) { struct nand_chip *nand = mtd_to_nand(mtd); - ioread8_rep(nand->IO_ADDR_R, buf, len); + ioread8_rep(nand->legacy.IO_ADDR_R, buf, len); } /** @@ -291,7 +291,7 @@ static void omap_write_buf8(struct mtd_info *mtd, const u_char *buf, int len) bool status; while (len--) { - iowrite8(*p++, info->nand.IO_ADDR_W); + iowrite8(*p++, info->nand.legacy.IO_ADDR_W); /* wait until buffer is available for write */ do { status = info->ops->nand_writebuffer_empty(); @@ -309,7 +309,7 @@ static void omap_read_buf16(struct mtd_info *mtd, u_char *buf, int len) { struct nand_chip *nand = mtd_to_nand(mtd); - ioread16_rep(nand->IO_ADDR_R, buf, len / 2); + ioread16_rep(nand->legacy.IO_ADDR_R, buf, len / 2); } /** @@ -327,7 +327,7 @@ static void omap_write_buf16(struct mtd_info *mtd, const u_char * buf, int len) len >>= 1; while (len--) { - iowrite16(*p++, info->nand.IO_ADDR_W); + iowrite16(*p++, info->nand.legacy.IO_ADDR_W); /* wait until buffer is available for write */ do { status = info->ops->nand_writebuffer_empty(); @@ -373,7 +373,7 @@ static void omap_read_buf_pref(struct nand_chip *chip, u_char *buf, int len) r_count = readl(info->reg.gpmc_prefetch_status); r_count = PREFETCH_STATUS_FIFO_CNT(r_count); r_count = r_count >> 2; - ioread32_rep(info->nand.IO_ADDR_R, p, r_count); + ioread32_rep(info->nand.legacy.IO_ADDR_R, p, r_count); p += r_count; len -= r_count << 2; } while (len); @@ -401,7 +401,7 @@ static void omap_write_buf_pref(struct nand_chip *chip, const u_char *buf, /* take care of subpage writes */ if (len % 2 != 0) { - writeb(*buf, info->nand.IO_ADDR_W); + writeb(*buf, info->nand.legacy.IO_ADDR_W); p = (u16 *)(buf + 1); len--; } @@ -421,7 +421,7 @@ static void omap_write_buf_pref(struct nand_chip *chip, const u_char *buf, w_count = PREFETCH_STATUS_FIFO_CNT(w_count); w_count = w_count >> 1; for (i = 0; (i < w_count) && len; i++, len -= 2) - iowrite16(*p++, info->nand.IO_ADDR_W); + iowrite16(*p++, info->nand.legacy.IO_ADDR_W); } /* wait for data to flushed-out before reset the prefetch */ tim = 0; @@ -585,14 +585,14 @@ static irqreturn_t omap_nand_irq(int this_irq, void *dev) bytes = info->buf_len; else if (!info->buf_len) bytes = 0; - iowrite32_rep(info->nand.IO_ADDR_W, - (u32 *)info->buf, bytes >> 2); + iowrite32_rep(info->nand.legacy.IO_ADDR_W, (u32 *)info->buf, + bytes >> 2); info->buf = info->buf + bytes; info->buf_len -= bytes; } else { - ioread32_rep(info->nand.IO_ADDR_R, - (u32 *)info->buf, bytes >> 2); + ioread32_rep(info->nand.legacy.IO_ADDR_R, (u32 *)info->buf, + bytes >> 2); info->buf = info->buf + bytes; if (this_irq == info->gpmc_irq_count) @@ -2221,15 +2221,15 @@ static int omap_nand_probe(struct platform_device *pdev) } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - nand_chip->IO_ADDR_R = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(nand_chip->IO_ADDR_R)) - return PTR_ERR(nand_chip->IO_ADDR_R); + nand_chip->legacy.IO_ADDR_R = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(nand_chip->legacy.IO_ADDR_R)) + return PTR_ERR(nand_chip->legacy.IO_ADDR_R); info->phys_base = res->start; nand_chip->controller = &omap_gpmc_controller; - nand_chip->IO_ADDR_W = nand_chip->IO_ADDR_R; + nand_chip->legacy.IO_ADDR_W = nand_chip->legacy.IO_ADDR_R; nand_chip->cmd_ctrl = omap_hwcontrol; info->ready_gpiod = devm_gpiod_get_optional(&pdev->dev, "rb", diff --git a/drivers/mtd/nand/raw/orion_nand.c b/drivers/mtd/nand/raw/orion_nand.c index 92d8f249ee97..d73e3c7a3f3a 100644 --- a/drivers/mtd/nand/raw/orion_nand.c +++ b/drivers/mtd/nand/raw/orion_nand.c @@ -45,12 +45,12 @@ static void orion_nand_cmd_ctrl(struct nand_chip *nc, int cmd, if (nc->options & NAND_BUSWIDTH_16) offs <<= 1; - writeb(cmd, nc->IO_ADDR_W + offs); + writeb(cmd, nc->legacy.IO_ADDR_W + offs); } static void orion_nand_read_buf(struct nand_chip *chip, uint8_t *buf, int len) { - void __iomem *io_base = chip->IO_ADDR_R; + void __iomem *io_base = chip->legacy.IO_ADDR_R; #if defined(__LINUX_ARM_ARCH__) && __LINUX_ARM_ARCH__ >= 5 uint64_t *buf64; #endif @@ -136,7 +136,7 @@ static int __init orion_nand_probe(struct platform_device *pdev) nand_set_controller_data(nc, board); nand_set_flash_node(nc, pdev->dev.of_node); - nc->IO_ADDR_R = nc->IO_ADDR_W = io_base; + nc->legacy.IO_ADDR_R = nc->legacy.IO_ADDR_W = io_base; nc->cmd_ctrl = orion_nand_cmd_ctrl; nc->read_buf = orion_nand_read_buf; nc->ecc.mode = NAND_ECC_SOFT; diff --git a/drivers/mtd/nand/raw/pasemi_nand.c b/drivers/mtd/nand/raw/pasemi_nand.c index a1e3bf7a276b..1b367bf9ef53 100644 --- a/drivers/mtd/nand/raw/pasemi_nand.c +++ b/drivers/mtd/nand/raw/pasemi_nand.c @@ -46,22 +46,22 @@ static const char driver_name[] = "pasemi-nand"; static void pasemi_read_buf(struct nand_chip *chip, u_char *buf, int len) { while (len > 0x800) { - memcpy_fromio(buf, chip->IO_ADDR_R, 0x800); + memcpy_fromio(buf, chip->legacy.IO_ADDR_R, 0x800); buf += 0x800; len -= 0x800; } - memcpy_fromio(buf, chip->IO_ADDR_R, len); + memcpy_fromio(buf, chip->legacy.IO_ADDR_R, len); } static void pasemi_write_buf(struct nand_chip *chip, const u_char *buf, int len) { while (len > 0x800) { - memcpy_toio(chip->IO_ADDR_R, buf, 0x800); + memcpy_toio(chip->legacy.IO_ADDR_R, buf, 0x800); buf += 0x800; len -= 0x800; } - memcpy_toio(chip->IO_ADDR_R, buf, len); + memcpy_toio(chip->legacy.IO_ADDR_R, buf, len); } static void pasemi_hwcontrol(struct nand_chip *chip, int cmd, @@ -71,9 +71,9 @@ static void pasemi_hwcontrol(struct nand_chip *chip, int cmd, return; if (ctrl & NAND_CLE) - out_8(chip->IO_ADDR_W + (1 << CLE_PIN_CTL), cmd); + out_8(chip->legacy.IO_ADDR_W + (1 << CLE_PIN_CTL), cmd); else - out_8(chip->IO_ADDR_W + (1 << ALE_PIN_CTL), cmd); + out_8(chip->legacy.IO_ADDR_W + (1 << ALE_PIN_CTL), cmd); /* Push out posted writes */ eieio(); @@ -117,10 +117,10 @@ static int pasemi_nand_probe(struct platform_device *ofdev) /* Link the private data with the MTD structure */ pasemi_nand_mtd->dev.parent = dev; - chip->IO_ADDR_R = of_iomap(np, 0); - chip->IO_ADDR_W = chip->IO_ADDR_R; + chip->legacy.IO_ADDR_R = of_iomap(np, 0); + chip->legacy.IO_ADDR_W = chip->legacy.IO_ADDR_R; - if (!chip->IO_ADDR_R) { + if (!chip->legacy.IO_ADDR_R) { err = -EIO; goto out_mtd; } @@ -169,7 +169,7 @@ static int pasemi_nand_probe(struct platform_device *ofdev) out_lpc: release_region(lpcctl, 4); out_ior: - iounmap(chip->IO_ADDR_R); + iounmap(chip->legacy.IO_ADDR_R); out_mtd: kfree(chip); out: @@ -190,7 +190,7 @@ static int pasemi_nand_remove(struct platform_device *ofdev) release_region(lpcctl, 4); - iounmap(chip->IO_ADDR_R); + iounmap(chip->legacy.IO_ADDR_R); /* Free the MTD device structure */ kfree(chip); diff --git a/drivers/mtd/nand/raw/plat_nand.c b/drivers/mtd/nand/raw/plat_nand.c index d65e4084dea4..c06347531d26 100644 --- a/drivers/mtd/nand/raw/plat_nand.c +++ b/drivers/mtd/nand/raw/plat_nand.c @@ -60,8 +60,8 @@ static int plat_nand_probe(struct platform_device *pdev) mtd = nand_to_mtd(&data->chip); mtd->dev.parent = &pdev->dev; - data->chip.IO_ADDR_R = data->io_base; - data->chip.IO_ADDR_W = data->io_base; + data->chip.legacy.IO_ADDR_R = data->io_base; + data->chip.legacy.IO_ADDR_W = data->io_base; data->chip.cmd_ctrl = pdata->ctrl.cmd_ctrl; data->chip.dev_ready = pdata->ctrl.dev_ready; data->chip.select_chip = pdata->ctrl.select_chip; diff --git a/drivers/mtd/nand/raw/s3c2410.c b/drivers/mtd/nand/raw/s3c2410.c index 1f70eb35320b..473abf10eeec 100644 --- a/drivers/mtd/nand/raw/s3c2410.c +++ b/drivers/mtd/nand/raw/s3c2410.c @@ -681,7 +681,7 @@ static int s3c2440_nand_calculate_ecc(struct nand_chip *chip, static void s3c2410_nand_read_buf(struct nand_chip *this, u_char *buf, int len) { - readsb(this->IO_ADDR_R, buf, len); + readsb(this->legacy.IO_ADDR_R, buf, len); } static void s3c2440_nand_read_buf(struct nand_chip *this, u_char *buf, int len) @@ -703,7 +703,7 @@ static void s3c2440_nand_read_buf(struct nand_chip *this, u_char *buf, int len) static void s3c2410_nand_write_buf(struct nand_chip *this, const u_char *buf, int len) { - writesb(this->IO_ADDR_W, buf, len); + writesb(this->legacy.IO_ADDR_W, buf, len); } static void s3c2440_nand_write_buf(struct nand_chip *this, const u_char *buf, @@ -881,7 +881,7 @@ static void s3c2410_nand_init_chip(struct s3c2410_nand_info *info, switch (info->cpu_type) { case TYPE_S3C2410: - chip->IO_ADDR_W = regs + S3C2410_NFDATA; + chip->legacy.IO_ADDR_W = regs + S3C2410_NFDATA; info->sel_reg = regs + S3C2410_NFCONF; info->sel_bit = S3C2410_NFCONF_nFCE; chip->cmd_ctrl = s3c2410_nand_hwcontrol; @@ -889,7 +889,7 @@ static void s3c2410_nand_init_chip(struct s3c2410_nand_info *info, break; case TYPE_S3C2440: - chip->IO_ADDR_W = regs + S3C2440_NFDATA; + chip->legacy.IO_ADDR_W = regs + S3C2440_NFDATA; info->sel_reg = regs + S3C2440_NFCONT; info->sel_bit = S3C2440_NFCONT_nFCE; chip->cmd_ctrl = s3c2440_nand_hwcontrol; @@ -899,7 +899,7 @@ static void s3c2410_nand_init_chip(struct s3c2410_nand_info *info, break; case TYPE_S3C2412: - chip->IO_ADDR_W = regs + S3C2440_NFDATA; + chip->legacy.IO_ADDR_W = regs + S3C2440_NFDATA; info->sel_reg = regs + S3C2440_NFCONT; info->sel_bit = S3C2412_NFCONT_nFCE0; chip->cmd_ctrl = s3c2440_nand_hwcontrol; @@ -911,7 +911,7 @@ static void s3c2410_nand_init_chip(struct s3c2410_nand_info *info, break; } - chip->IO_ADDR_R = chip->IO_ADDR_W; + chip->legacy.IO_ADDR_R = chip->legacy.IO_ADDR_W; nmtd->info = info; nmtd->set = set; diff --git a/drivers/mtd/nand/raw/sharpsl.c b/drivers/mtd/nand/raw/sharpsl.c index 31abbe33798e..d9cdd11fbd3a 100644 --- a/drivers/mtd/nand/raw/sharpsl.c +++ b/drivers/mtd/nand/raw/sharpsl.c @@ -75,7 +75,7 @@ static void sharpsl_nand_hwcontrol(struct nand_chip *chip, int cmd, } if (cmd != NAND_CMD_NONE) - writeb(cmd, chip->IO_ADDR_W); + writeb(cmd, chip->legacy.IO_ADDR_W); } static int sharpsl_nand_dev_ready(struct nand_chip *chip) @@ -153,8 +153,8 @@ static int sharpsl_nand_probe(struct platform_device *pdev) writeb(readb(sharpsl->io + FLASHCTL) | FLWP, sharpsl->io + FLASHCTL); /* Set address of NAND IO lines */ - this->IO_ADDR_R = sharpsl->io + FLASHIO; - this->IO_ADDR_W = sharpsl->io + FLASHIO; + this->legacy.IO_ADDR_R = sharpsl->io + FLASHIO; + this->legacy.IO_ADDR_W = sharpsl->io + FLASHIO; /* Set address of hardware control function */ this->cmd_ctrl = sharpsl_nand_hwcontrol; this->dev_ready = sharpsl_nand_dev_ready; diff --git a/drivers/mtd/nand/raw/tmio_nand.c b/drivers/mtd/nand/raw/tmio_nand.c index f44621672779..0b23587bf47c 100644 --- a/drivers/mtd/nand/raw/tmio_nand.c +++ b/drivers/mtd/nand/raw/tmio_nand.c @@ -155,7 +155,7 @@ static void tmio_nand_hwcontrol(struct nand_chip *chip, int cmd, } if (cmd != NAND_CMD_NONE) - tmio_iowrite8(cmd, chip->IO_ADDR_W); + tmio_iowrite8(cmd, chip->legacy.IO_ADDR_W); } static int tmio_nand_dev_ready(struct nand_chip *chip) @@ -399,8 +399,8 @@ static int tmio_probe(struct platform_device *dev) return retval; /* Set address of NAND IO lines */ - nand_chip->IO_ADDR_R = tmio->fcr; - nand_chip->IO_ADDR_W = tmio->fcr; + nand_chip->legacy.IO_ADDR_R = tmio->fcr; + nand_chip->legacy.IO_ADDR_W = tmio->fcr; /* Set address of hardware control function */ nand_chip->cmd_ctrl = tmio_nand_hwcontrol; diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h index e3a96ee7e531..6b1dc8fef89d 100644 --- a/include/linux/mtd/rawnand.h +++ b/include/linux/mtd/rawnand.h @@ -1172,13 +1172,27 @@ int nand_op_parser_exec_op(struct nand_chip *chip, const struct nand_op_parser *parser, const struct nand_operation *op, bool check_only); +/** + * struct nand_legacy - NAND chip legacy fields/hooks + * @IO_ADDR_R: address to read the 8 I/O lines of the flash device + * @IO_ADDR_W: address to write the 8 I/O lines of the flash device + * + * If you look at this structure you're already wrong. These fields/hooks are + * all deprecated. + */ +struct nand_legacy { + void __iomem *IO_ADDR_R; + void __iomem *IO_ADDR_W; +}; + /** * struct nand_chip - NAND Private Flash Chip Data * @mtd: MTD device registered to the MTD framework - * @IO_ADDR_R: [BOARDSPECIFIC] address to read the 8 I/O lines of the - * flash device - * @IO_ADDR_W: [BOARDSPECIFIC] address to write the 8 I/O lines of the - * flash device. + * @legacy: All legacy fields/hooks. If you develop a new driver, + * don't even try to use any of these fields/hooks, and if + * you're modifying an existing driver that is using those + * fields/hooks, you should consider reworking the driver + * avoid using them. * @read_byte: [REPLACEABLE] read one byte from the chip * @write_byte: [REPLACEABLE] write a single byte to the chip on the * low 8 I/O lines @@ -1280,8 +1294,8 @@ int nand_op_parser_exec_op(struct nand_chip *chip, struct nand_chip { struct mtd_info mtd; - void __iomem *IO_ADDR_R; - void __iomem *IO_ADDR_W; + + struct nand_legacy legacy; uint8_t (*read_byte)(struct nand_chip *chip); void (*write_byte)(struct nand_chip *chip, uint8_t byte); From 716bbbabcc68c2b0e1b805d369c0bd58f4fdea30 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Fri, 7 Sep 2018 00:38:35 +0200 Subject: [PATCH 272/302] mtd: rawnand: Deprecate ->{read, write}_{byte, buf}() hooks All those hooks have been replaced by ->exec_op(). Move them to the nand_legacy struct. Signed-off-by: Boris Brezillon Signed-off-by: Miquel Raynal --- drivers/mtd/nand/raw/ams-delta.c | 6 +-- drivers/mtd/nand/raw/atmel/nand-controller.c | 8 +-- drivers/mtd/nand/raw/au1550nd.c | 6 +-- .../mtd/nand/raw/bcm47xxnflash/ops_bcm4706.c | 6 +-- drivers/mtd/nand/raw/brcmnand/brcmnand.c | 6 +-- drivers/mtd/nand/raw/cafe_nand.c | 10 ++-- drivers/mtd/nand/raw/cmx270_nand.c | 6 +-- drivers/mtd/nand/raw/cs553x_nand.c | 6 +-- drivers/mtd/nand/raw/davinci_nand.c | 4 +- drivers/mtd/nand/raw/denali.c | 12 ++--- drivers/mtd/nand/raw/diskonchip.c | 28 +++++------ drivers/mtd/nand/raw/fsl_elbc_nand.c | 6 +-- drivers/mtd/nand/raw/fsl_ifc_nand.c | 12 ++--- drivers/mtd/nand/raw/fsl_upm.c | 6 +-- drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c | 14 +++--- drivers/mtd/nand/raw/hisi504_nand.c | 10 ++-- drivers/mtd/nand/raw/lpc32xx_slc.c | 16 +++--- drivers/mtd/nand/raw/mpc5121_nfc.c | 6 +-- drivers/mtd/nand/raw/mtk_nand.c | 8 +-- drivers/mtd/nand/raw/mxc_nand.c | 10 ++-- drivers/mtd/nand/raw/nand_base.c | 50 +++++++++---------- drivers/mtd/nand/raw/nand_hynix.c | 2 +- drivers/mtd/nand/raw/nandsim.c | 8 +-- drivers/mtd/nand/raw/ndfc.c | 4 +- drivers/mtd/nand/raw/nuc900_nand.c | 6 +-- drivers/mtd/nand/raw/omap2.c | 22 ++++---- drivers/mtd/nand/raw/orion_nand.c | 2 +- drivers/mtd/nand/raw/oxnas_nand.c | 6 +-- drivers/mtd/nand/raw/pasemi_nand.c | 4 +- drivers/mtd/nand/raw/plat_nand.c | 4 +- drivers/mtd/nand/raw/qcom_nandc.c | 17 ++++--- drivers/mtd/nand/raw/r852.c | 6 +-- drivers/mtd/nand/raw/s3c2410.c | 8 +-- drivers/mtd/nand/raw/sh_flctl.c | 10 ++-- drivers/mtd/nand/raw/socrates_nand.c | 6 +-- drivers/mtd/nand/raw/sunxi_nand.c | 6 +-- drivers/mtd/nand/raw/tango_nand.c | 6 +-- drivers/mtd/nand/raw/tmio_nand.c | 6 +-- drivers/mtd/nand/raw/txx9ndfmc.c | 6 +-- drivers/mtd/nand/raw/xway_nand.c | 6 +-- drivers/staging/mt29f_spinand/mt29f_spinand.c | 8 +-- include/linux/mtd/rawnand.h | 21 ++++---- 42 files changed, 200 insertions(+), 200 deletions(-) diff --git a/drivers/mtd/nand/raw/ams-delta.c b/drivers/mtd/nand/raw/ams-delta.c index 5bc8b29faf6d..6616f473aeb2 100644 --- a/drivers/mtd/nand/raw/ams-delta.c +++ b/drivers/mtd/nand/raw/ams-delta.c @@ -210,9 +210,9 @@ static int ams_delta_init(struct platform_device *pdev) /* Set address of NAND IO lines */ this->legacy.IO_ADDR_R = io_base + OMAP_MPUIO_INPUT_LATCH; this->legacy.IO_ADDR_W = io_base + OMAP_MPUIO_OUTPUT; - this->read_byte = ams_delta_read_byte; - this->write_buf = ams_delta_write_buf; - this->read_buf = ams_delta_read_buf; + this->legacy.read_byte = ams_delta_read_byte; + this->legacy.write_buf = ams_delta_write_buf; + this->legacy.read_buf = ams_delta_read_buf; this->cmd_ctrl = ams_delta_hwcontrol; if (gpio_request(AMS_DELTA_GPIO_PIN_NAND_RB, "nand_rdy") == 0) { this->dev_ready = ams_delta_nand_ready; diff --git a/drivers/mtd/nand/raw/atmel/nand-controller.c b/drivers/mtd/nand/raw/atmel/nand-controller.c index a38633a67ead..9b2876b5a9c2 100644 --- a/drivers/mtd/nand/raw/atmel/nand-controller.c +++ b/drivers/mtd/nand/raw/atmel/nand-controller.c @@ -1473,10 +1473,10 @@ static void atmel_nand_init(struct atmel_nand_controller *nc, nand->base.controller = &nc->base; chip->cmd_ctrl = atmel_nand_cmd_ctrl; - chip->read_byte = atmel_nand_read_byte; - chip->write_byte = atmel_nand_write_byte; - chip->read_buf = atmel_nand_read_buf; - chip->write_buf = atmel_nand_write_buf; + chip->legacy.read_byte = atmel_nand_read_byte; + chip->legacy.write_byte = atmel_nand_write_byte; + chip->legacy.read_buf = atmel_nand_read_buf; + chip->legacy.write_buf = atmel_nand_write_buf; chip->select_chip = atmel_nand_select_chip; if (nc->mck && nc->caps->ops->setup_data_interface) diff --git a/drivers/mtd/nand/raw/au1550nd.c b/drivers/mtd/nand/raw/au1550nd.c index b7bb2b2af4ef..0db5dc61b155 100644 --- a/drivers/mtd/nand/raw/au1550nd.c +++ b/drivers/mtd/nand/raw/au1550nd.c @@ -440,10 +440,10 @@ static int au1550nd_probe(struct platform_device *pdev) if (pd->devwidth) this->options |= NAND_BUSWIDTH_16; - this->read_byte = (pd->devwidth) ? au_read_byte16 : au_read_byte; + this->legacy.read_byte = (pd->devwidth) ? au_read_byte16 : au_read_byte; ctx->write_byte = (pd->devwidth) ? au_write_byte16 : au_write_byte; - this->write_buf = (pd->devwidth) ? au_write_buf16 : au_write_buf; - this->read_buf = (pd->devwidth) ? au_read_buf16 : au_read_buf; + this->legacy.write_buf = (pd->devwidth) ? au_write_buf16 : au_write_buf; + this->legacy.read_buf = (pd->devwidth) ? au_read_buf16 : au_read_buf; ret = nand_scan(this, 1); if (ret) { diff --git a/drivers/mtd/nand/raw/bcm47xxnflash/ops_bcm4706.c b/drivers/mtd/nand/raw/bcm47xxnflash/ops_bcm4706.c index 59e1b88aae38..ea41d1b95c81 100644 --- a/drivers/mtd/nand/raw/bcm47xxnflash/ops_bcm4706.c +++ b/drivers/mtd/nand/raw/bcm47xxnflash/ops_bcm4706.c @@ -387,9 +387,9 @@ int bcm47xxnflash_ops_bcm4706_init(struct bcm47xxnflash *b47n) nand_chip->cmd_ctrl = bcm47xxnflash_ops_bcm4706_cmd_ctrl; nand_chip->dev_ready = bcm47xxnflash_ops_bcm4706_dev_ready; b47n->nand_chip.cmdfunc = bcm47xxnflash_ops_bcm4706_cmdfunc; - b47n->nand_chip.read_byte = bcm47xxnflash_ops_bcm4706_read_byte; - b47n->nand_chip.read_buf = bcm47xxnflash_ops_bcm4706_read_buf; - b47n->nand_chip.write_buf = bcm47xxnflash_ops_bcm4706_write_buf; + b47n->nand_chip.legacy.read_byte = bcm47xxnflash_ops_bcm4706_read_byte; + b47n->nand_chip.legacy.read_buf = bcm47xxnflash_ops_bcm4706_read_buf; + b47n->nand_chip.legacy.write_buf = bcm47xxnflash_ops_bcm4706_write_buf; b47n->nand_chip.set_features = nand_get_set_features_notsupp; b47n->nand_chip.get_features = nand_get_set_features_notsupp; diff --git a/drivers/mtd/nand/raw/brcmnand/brcmnand.c b/drivers/mtd/nand/raw/brcmnand/brcmnand.c index 851db4a7d3e4..4eb9244cc108 100644 --- a/drivers/mtd/nand/raw/brcmnand/brcmnand.c +++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c @@ -2273,9 +2273,9 @@ static int brcmnand_init_cs(struct brcmnand_host *host, struct device_node *dn) chip->cmd_ctrl = brcmnand_cmd_ctrl; chip->cmdfunc = brcmnand_cmdfunc; chip->waitfunc = brcmnand_waitfunc; - chip->read_byte = brcmnand_read_byte; - chip->read_buf = brcmnand_read_buf; - chip->write_buf = brcmnand_write_buf; + chip->legacy.read_byte = brcmnand_read_byte; + chip->legacy.read_buf = brcmnand_read_buf; + chip->legacy.write_buf = brcmnand_write_buf; chip->ecc.mode = NAND_ECC_HW; chip->ecc.read_page = brcmnand_read_page; diff --git a/drivers/mtd/nand/raw/cafe_nand.c b/drivers/mtd/nand/raw/cafe_nand.c index 801045d77872..95754d1f12b8 100644 --- a/drivers/mtd/nand/raw/cafe_nand.c +++ b/drivers/mtd/nand/raw/cafe_nand.c @@ -378,7 +378,7 @@ static int cafe_nand_read_page(struct nand_chip *chip, uint8_t *buf, cafe_readl(cafe, NAND_ECC_SYN01)); nand_read_page_op(chip, page, 0, buf, mtd->writesize); - chip->read_buf(chip, chip->oob_poi, mtd->oobsize); + chip->legacy.read_buf(chip, chip->oob_poi, mtd->oobsize); if (checkecc && cafe_readl(cafe, NAND_ECC_RESULT) & (1<<18)) { unsigned short syn[8], pat[4]; @@ -537,7 +537,7 @@ static int cafe_nand_write_page_lowlevel(struct nand_chip *chip, struct cafe_priv *cafe = nand_get_controller_data(chip); nand_prog_page_begin_op(chip, page, 0, buf, mtd->writesize); - chip->write_buf(chip, chip->oob_poi, mtd->oobsize); + chip->legacy.write_buf(chip, chip->oob_poi, mtd->oobsize); /* Set up ECC autogeneration */ cafe->ctl2 |= (1<<30); @@ -705,9 +705,9 @@ static int cafe_nand_probe(struct pci_dev *pdev, cafe->nand.cmdfunc = cafe_nand_cmdfunc; cafe->nand.dev_ready = cafe_device_ready; - cafe->nand.read_byte = cafe_read_byte; - cafe->nand.read_buf = cafe_read_buf; - cafe->nand.write_buf = cafe_write_buf; + cafe->nand.legacy.read_byte = cafe_read_byte; + cafe->nand.legacy.read_buf = cafe_read_buf; + cafe->nand.legacy.write_buf = cafe_write_buf; cafe->nand.select_chip = cafe_select_chip; cafe->nand.set_features = nand_get_set_features_notsupp; cafe->nand.get_features = nand_get_set_features_notsupp; diff --git a/drivers/mtd/nand/raw/cmx270_nand.c b/drivers/mtd/nand/raw/cmx270_nand.c index b4ed69815bed..18f10ae92dfc 100644 --- a/drivers/mtd/nand/raw/cmx270_nand.c +++ b/drivers/mtd/nand/raw/cmx270_nand.c @@ -184,9 +184,9 @@ static int __init cmx270_init(void) this->ecc.algo = NAND_ECC_HAMMING; /* read/write functions */ - this->read_byte = cmx270_read_byte; - this->read_buf = cmx270_read_buf; - this->write_buf = cmx270_write_buf; + this->legacy.read_byte = cmx270_read_byte; + this->legacy.read_buf = cmx270_read_buf; + this->legacy.write_buf = cmx270_write_buf; /* Scan to find existence of the device */ ret = nand_scan(this, 1); diff --git a/drivers/mtd/nand/raw/cs553x_nand.c b/drivers/mtd/nand/raw/cs553x_nand.c index b03fb36e9e69..8a3230041678 100644 --- a/drivers/mtd/nand/raw/cs553x_nand.c +++ b/drivers/mtd/nand/raw/cs553x_nand.c @@ -208,9 +208,9 @@ static int __init cs553x_init_one(int cs, int mmio, unsigned long adr) this->cmd_ctrl = cs553x_hwcontrol; this->dev_ready = cs553x_device_ready; - this->read_byte = cs553x_read_byte; - this->read_buf = cs553x_read_buf; - this->write_buf = cs553x_write_buf; + this->legacy.read_byte = cs553x_read_byte; + this->legacy.read_buf = cs553x_read_buf; + this->legacy.write_buf = cs553x_write_buf; this->chip_delay = 0; diff --git a/drivers/mtd/nand/raw/davinci_nand.c b/drivers/mtd/nand/raw/davinci_nand.c index 1204b5120176..b7701caa5f94 100644 --- a/drivers/mtd/nand/raw/davinci_nand.c +++ b/drivers/mtd/nand/raw/davinci_nand.c @@ -785,8 +785,8 @@ static int nand_davinci_probe(struct platform_device *pdev) info->chip.dev_ready = nand_davinci_dev_ready; /* Speed up buffer I/O */ - info->chip.read_buf = nand_davinci_read_buf; - info->chip.write_buf = nand_davinci_write_buf; + info->chip.legacy.read_buf = nand_davinci_read_buf; + info->chip.legacy.write_buf = nand_davinci_write_buf; /* Use board-specific ECC config */ info->chip.ecc.mode = pdata->ecc_mode; diff --git a/drivers/mtd/nand/raw/denali.c b/drivers/mtd/nand/raw/denali.c index c5e35461d6b3..2d963ed6643c 100644 --- a/drivers/mtd/nand/raw/denali.c +++ b/drivers/mtd/nand/raw/denali.c @@ -1262,11 +1262,11 @@ static int denali_attach_chip(struct nand_chip *chip) mtd_set_ooblayout(mtd, &denali_ooblayout_ops); if (chip->options & NAND_BUSWIDTH_16) { - chip->read_buf = denali_read_buf16; - chip->write_buf = denali_write_buf16; + chip->legacy.read_buf = denali_read_buf16; + chip->legacy.write_buf = denali_write_buf16; } else { - chip->read_buf = denali_read_buf; - chip->write_buf = denali_write_buf; + chip->legacy.read_buf = denali_read_buf; + chip->legacy.write_buf = denali_write_buf; } chip->ecc.read_page = denali_read_page; chip->ecc.read_page_raw = denali_read_page_raw; @@ -1343,8 +1343,8 @@ int denali_init(struct denali_nand_info *denali) mtd->name = "denali-nand"; chip->select_chip = denali_select_chip; - chip->read_byte = denali_read_byte; - chip->write_byte = denali_write_byte; + chip->legacy.read_byte = denali_read_byte; + chip->legacy.write_byte = denali_write_byte; chip->cmd_ctrl = denali_cmd_ctrl; chip->dev_ready = denali_dev_ready; chip->waitfunc = denali_waitfunc; diff --git a/drivers/mtd/nand/raw/diskonchip.c b/drivers/mtd/nand/raw/diskonchip.c index 0b305c19a9a3..ec3336f071e7 100644 --- a/drivers/mtd/nand/raw/diskonchip.c +++ b/drivers/mtd/nand/raw/diskonchip.c @@ -382,8 +382,8 @@ static uint16_t __init doc200x_ident_chip(struct mtd_info *mtd, int nr) */ udelay(50); - ret = this->read_byte(this) << 8; - ret |= this->read_byte(this); + ret = this->legacy.read_byte(this) << 8; + ret |= this->legacy.read_byte(this); if (doc->ChipID == DOC_ChipID_Doc2k && try_dword && !nr) { /* First chip probe. See if we get same results by 32-bit access */ @@ -404,7 +404,7 @@ static uint16_t __init doc200x_ident_chip(struct mtd_info *mtd, int nr) ident.dword = readl(docptr + DoC_2k_CDSN_IO); if (((ident.byte[0] << 8) | ident.byte[1]) == ret) { pr_info("DiskOnChip 2000 responds to DWORD access\n"); - this->read_buf = &doc2000_readbuf_dword; + this->legacy.read_buf = &doc2000_readbuf_dword; } } @@ -442,7 +442,7 @@ static int doc200x_wait(struct nand_chip *this) DoC_WaitReady(doc); nand_status_op(this, NULL); DoC_WaitReady(doc); - status = (int)this->read_byte(this); + status = (int)this->legacy.read_byte(this); return status; } @@ -721,7 +721,7 @@ static void doc2001plus_command(struct nand_chip *this, unsigned command, WriteDOC(NAND_CMD_STATUS, docptr, Mplus_FlashCmd); WriteDOC(0, docptr, Mplus_WritePipeTerm); WriteDOC(0, docptr, Mplus_WritePipeTerm); - while (!(this->read_byte(this) & 0x40)) ; + while (!(this->legacy.read_byte(this) & 0x40)) ; return; /* This applies to read commands */ @@ -1339,9 +1339,9 @@ static inline int __init doc2000_init(struct mtd_info *mtd) struct nand_chip *this = mtd_to_nand(mtd); struct doc_priv *doc = nand_get_controller_data(this); - this->read_byte = doc2000_read_byte; - this->write_buf = doc2000_writebuf; - this->read_buf = doc2000_readbuf; + this->legacy.read_byte = doc2000_read_byte; + this->legacy.write_buf = doc2000_writebuf; + this->legacy.read_buf = doc2000_readbuf; doc->late_init = nftl_scan_bbt; doc->CDSNControl = CDSN_CTRL_FLASH_IO | CDSN_CTRL_ECC_IO; @@ -1355,9 +1355,9 @@ static inline int __init doc2001_init(struct mtd_info *mtd) struct nand_chip *this = mtd_to_nand(mtd); struct doc_priv *doc = nand_get_controller_data(this); - this->read_byte = doc2001_read_byte; - this->write_buf = doc2001_writebuf; - this->read_buf = doc2001_readbuf; + this->legacy.read_byte = doc2001_read_byte; + this->legacy.write_buf = doc2001_writebuf; + this->legacy.read_buf = doc2001_readbuf; ReadDOC(doc->virtadr, ChipID); ReadDOC(doc->virtadr, ChipID); @@ -1385,9 +1385,9 @@ static inline int __init doc2001plus_init(struct mtd_info *mtd) struct nand_chip *this = mtd_to_nand(mtd); struct doc_priv *doc = nand_get_controller_data(this); - this->read_byte = doc2001plus_read_byte; - this->write_buf = doc2001plus_writebuf; - this->read_buf = doc2001plus_readbuf; + this->legacy.read_byte = doc2001plus_read_byte; + this->legacy.write_buf = doc2001plus_writebuf; + this->legacy.read_buf = doc2001plus_readbuf; doc->late_init = inftl_scan_bbt; this->cmd_ctrl = NULL; this->select_chip = doc2001plus_select_chip; diff --git a/drivers/mtd/nand/raw/fsl_elbc_nand.c b/drivers/mtd/nand/raw/fsl_elbc_nand.c index 98da5f9f04ac..5e7b912f63b3 100644 --- a/drivers/mtd/nand/raw/fsl_elbc_nand.c +++ b/drivers/mtd/nand/raw/fsl_elbc_nand.c @@ -776,9 +776,9 @@ static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv) /* fill in nand_chip structure */ /* set up function call table */ - chip->read_byte = fsl_elbc_read_byte; - chip->write_buf = fsl_elbc_write_buf; - chip->read_buf = fsl_elbc_read_buf; + chip->legacy.read_byte = fsl_elbc_read_byte; + chip->legacy.write_buf = fsl_elbc_write_buf; + chip->legacy.read_buf = fsl_elbc_read_buf; chip->select_chip = fsl_elbc_select_chip; chip->cmdfunc = fsl_elbc_cmdfunc; chip->waitfunc = fsl_elbc_wait; diff --git a/drivers/mtd/nand/raw/fsl_ifc_nand.c b/drivers/mtd/nand/raw/fsl_ifc_nand.c index cdcd82d1f8bc..ed3b90f2fb50 100644 --- a/drivers/mtd/nand/raw/fsl_ifc_nand.c +++ b/drivers/mtd/nand/raw/fsl_ifc_nand.c @@ -858,12 +858,12 @@ static int fsl_ifc_chip_init(struct fsl_ifc_mtd *priv) /* set up function call table */ if ((ifc_in32(&ifc_global->cspr_cs[priv->bank].cspr)) & CSPR_PORT_SIZE_16) - chip->read_byte = fsl_ifc_read_byte16; + chip->legacy.read_byte = fsl_ifc_read_byte16; else - chip->read_byte = fsl_ifc_read_byte; + chip->legacy.read_byte = fsl_ifc_read_byte; - chip->write_buf = fsl_ifc_write_buf; - chip->read_buf = fsl_ifc_read_buf; + chip->legacy.write_buf = fsl_ifc_write_buf; + chip->legacy.read_buf = fsl_ifc_read_buf; chip->select_chip = fsl_ifc_select_chip; chip->cmdfunc = fsl_ifc_cmdfunc; chip->waitfunc = fsl_ifc_wait; @@ -881,10 +881,10 @@ static int fsl_ifc_chip_init(struct fsl_ifc_mtd *priv) if (ifc_in32(&ifc_global->cspr_cs[priv->bank].cspr) & CSPR_PORT_SIZE_16) { - chip->read_byte = fsl_ifc_read_byte16; + chip->legacy.read_byte = fsl_ifc_read_byte16; chip->options |= NAND_BUSWIDTH_16; } else { - chip->read_byte = fsl_ifc_read_byte; + chip->legacy.read_byte = fsl_ifc_read_byte; } chip->controller = &ifc_nand_ctrl->controller; diff --git a/drivers/mtd/nand/raw/fsl_upm.c b/drivers/mtd/nand/raw/fsl_upm.c index f59fd57fc529..db194ad12074 100644 --- a/drivers/mtd/nand/raw/fsl_upm.c +++ b/drivers/mtd/nand/raw/fsl_upm.c @@ -164,9 +164,9 @@ static int fun_chip_init(struct fsl_upm_nand *fun, fun->chip.legacy.IO_ADDR_W = fun->io_base; fun->chip.cmd_ctrl = fun_cmd_ctrl; fun->chip.chip_delay = fun->chip_delay; - fun->chip.read_byte = fun_read_byte; - fun->chip.read_buf = fun_read_buf; - fun->chip.write_buf = fun_write_buf; + fun->chip.legacy.read_byte = fun_read_byte; + fun->chip.legacy.read_buf = fun_read_buf; + fun->chip.legacy.write_buf = fun_write_buf; fun->chip.ecc.mode = NAND_ECC_SOFT; fun->chip.ecc.algo = NAND_ECC_HAMMING; if (fun->mchip_count > 1) diff --git a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c index 1ed594a155ed..54f1a84c6520 100644 --- a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c +++ b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c @@ -1330,7 +1330,7 @@ static int gpmi_ecc_read_oob(struct nand_chip *chip, int page) /* Read out the conventional OOB. */ nand_read_page_op(chip, page, mtd->writesize, NULL, 0); - chip->read_buf(chip, chip->oob_poi, mtd->oobsize); + chip->legacy.read_buf(chip, chip->oob_poi, mtd->oobsize); /* * Now, we want to make sure the block mark is correct. In the @@ -1340,7 +1340,7 @@ static int gpmi_ecc_read_oob(struct nand_chip *chip, int page) if (GPMI_IS_MX23(this)) { /* Read the block mark into the first byte of the OOB buffer. */ nand_read_page_op(chip, page, 0, NULL, 0); - chip->oob_poi[0] = chip->read_byte(chip); + chip->oob_poi[0] = chip->legacy.read_byte(chip); } return 0; @@ -1628,7 +1628,7 @@ static int mx23_check_transcription_stamp(struct gpmi_nand_data *this) * and starts in the 12th byte of the page. */ nand_read_page_op(chip, page, 12, NULL, 0); - chip->read_buf(chip, buffer, strlen(fingerprint)); + chip->legacy.read_buf(chip, buffer, strlen(fingerprint)); /* Look for the fingerprint. */ if (!memcmp(buffer, fingerprint, strlen(fingerprint))) { @@ -1764,7 +1764,7 @@ static int mx23_boot_init(struct gpmi_nand_data *this) /* Send the command to read the conventional block mark. */ chip->select_chip(chip, chipnr); nand_read_page_op(chip, page, mtd->writesize, NULL, 0); - block_mark = chip->read_byte(chip); + block_mark = chip->legacy.read_byte(chip); chip->select_chip(chip, -1); /* @@ -1904,9 +1904,9 @@ static int gpmi_nand_init(struct gpmi_nand_data *this) chip->setup_data_interface = gpmi_setup_data_interface; chip->cmd_ctrl = gpmi_cmd_ctrl; chip->dev_ready = gpmi_dev_ready; - chip->read_byte = gpmi_read_byte; - chip->read_buf = gpmi_read_buf; - chip->write_buf = gpmi_write_buf; + chip->legacy.read_byte = gpmi_read_byte; + chip->legacy.read_buf = gpmi_read_buf; + chip->legacy.write_buf = gpmi_write_buf; chip->badblock_pattern = &gpmi_bbt_descr; chip->block_markbad = gpmi_block_markbad; chip->options |= NAND_NO_SUBPAGE_WRITE; diff --git a/drivers/mtd/nand/raw/hisi504_nand.c b/drivers/mtd/nand/raw/hisi504_nand.c index 928a320c8517..1046f51bbcd2 100644 --- a/drivers/mtd/nand/raw/hisi504_nand.c +++ b/drivers/mtd/nand/raw/hisi504_nand.c @@ -533,7 +533,7 @@ static int hisi_nand_read_page_hwecc(struct nand_chip *chip, uint8_t *buf, int stat_1, stat_2; nand_read_page_op(chip, page, 0, buf, mtd->writesize); - chip->read_buf(chip, chip->oob_poi, mtd->oobsize); + chip->legacy.read_buf(chip, chip->oob_poi, mtd->oobsize); /* errors which can not be corrected by ECC */ if (host->irq_status & HINFC504_INTS_UE) { @@ -581,7 +581,7 @@ static int hisi_nand_write_page_hwecc(struct nand_chip *chip, nand_prog_page_begin_op(chip, page, 0, buf, mtd->writesize); if (oob_required) - chip->write_buf(chip, chip->oob_poi, mtd->oobsize); + chip->legacy.write_buf(chip, chip->oob_poi, mtd->oobsize); return nand_prog_page_end_op(chip); } @@ -784,9 +784,9 @@ static int hisi_nfc_probe(struct platform_device *pdev) nand_set_flash_node(chip, np); chip->cmdfunc = hisi_nfc_cmdfunc; chip->select_chip = hisi_nfc_select_chip; - chip->read_byte = hisi_nfc_read_byte; - chip->write_buf = hisi_nfc_write_buf; - chip->read_buf = hisi_nfc_read_buf; + chip->legacy.read_byte = hisi_nfc_read_byte; + chip->legacy.write_buf = hisi_nfc_write_buf; + chip->legacy.read_buf = hisi_nfc_read_buf; chip->chip_delay = HINFC504_CHIP_DELAY; chip->set_features = nand_get_set_features_notsupp; chip->get_features = nand_get_set_features_notsupp; diff --git a/drivers/mtd/nand/raw/lpc32xx_slc.c b/drivers/mtd/nand/raw/lpc32xx_slc.c index 8a6f109c43af..6dd5348b8f03 100644 --- a/drivers/mtd/nand/raw/lpc32xx_slc.c +++ b/drivers/mtd/nand/raw/lpc32xx_slc.c @@ -624,7 +624,7 @@ static int lpc32xx_nand_read_page_syndrome(struct nand_chip *chip, uint8_t *buf, status = lpc32xx_xfer(mtd, buf, chip->ecc.steps, 1); /* Get OOB data */ - chip->read_buf(chip, chip->oob_poi, mtd->oobsize); + chip->legacy.read_buf(chip, chip->oob_poi, mtd->oobsize); /* Convert to stored ECC format */ lpc32xx_slc_ecc_copy(tmpecc, (uint32_t *) host->ecc_buf, chip->ecc.steps); @@ -665,8 +665,8 @@ static int lpc32xx_nand_read_page_raw_syndrome(struct nand_chip *chip, nand_read_page_op(chip, page, 0, NULL, 0); /* Raw reads can just use the FIFO interface */ - chip->read_buf(chip, buf, chip->ecc.size * chip->ecc.steps); - chip->read_buf(chip, chip->oob_poi, mtd->oobsize); + chip->legacy.read_buf(chip, buf, chip->ecc.size * chip->ecc.steps); + chip->legacy.read_buf(chip, chip->oob_poi, mtd->oobsize); return 0; } @@ -704,7 +704,7 @@ static int lpc32xx_nand_write_page_syndrome(struct nand_chip *chip, lpc32xx_slc_ecc_copy(pb, (uint32_t *)host->ecc_buf, chip->ecc.steps); /* Write ECC data to device */ - chip->write_buf(chip, chip->oob_poi, mtd->oobsize); + chip->legacy.write_buf(chip, chip->oob_poi, mtd->oobsize); return nand_prog_page_end_op(chip); } @@ -722,7 +722,7 @@ static int lpc32xx_nand_write_page_raw_syndrome(struct nand_chip *chip, /* Raw writes can just use the FIFO interface */ nand_prog_page_begin_op(chip, page, 0, buf, chip->ecc.size * chip->ecc.steps); - chip->write_buf(chip, chip->oob_poi, mtd->oobsize); + chip->legacy.write_buf(chip, chip->oob_poi, mtd->oobsize); return nand_prog_page_end_op(chip); } @@ -891,9 +891,9 @@ static int lpc32xx_nand_probe(struct platform_device *pdev) /* NAND callbacks for LPC32xx SLC hardware */ chip->ecc.mode = NAND_ECC_HW_SYNDROME; - chip->read_byte = lpc32xx_nand_read_byte; - chip->read_buf = lpc32xx_nand_read_buf; - chip->write_buf = lpc32xx_nand_write_buf; + chip->legacy.read_byte = lpc32xx_nand_read_byte; + chip->legacy.read_buf = lpc32xx_nand_read_buf; + chip->legacy.write_buf = lpc32xx_nand_write_buf; chip->ecc.read_page_raw = lpc32xx_nand_read_page_raw_syndrome; chip->ecc.read_page = lpc32xx_nand_read_page_syndrome; chip->ecc.write_page_raw = lpc32xx_nand_write_page_raw_syndrome; diff --git a/drivers/mtd/nand/raw/mpc5121_nfc.c b/drivers/mtd/nand/raw/mpc5121_nfc.c index bd027674898d..4c2925e819f1 100644 --- a/drivers/mtd/nand/raw/mpc5121_nfc.c +++ b/drivers/mtd/nand/raw/mpc5121_nfc.c @@ -694,9 +694,9 @@ static int mpc5121_nfc_probe(struct platform_device *op) mtd->name = "MPC5121 NAND"; chip->dev_ready = mpc5121_nfc_dev_ready; chip->cmdfunc = mpc5121_nfc_command; - chip->read_byte = mpc5121_nfc_read_byte; - chip->read_buf = mpc5121_nfc_read_buf; - chip->write_buf = mpc5121_nfc_write_buf; + chip->legacy.read_byte = mpc5121_nfc_read_byte; + chip->legacy.read_buf = mpc5121_nfc_read_buf; + chip->legacy.write_buf = mpc5121_nfc_write_buf; chip->select_chip = mpc5121_nfc_select_chip; chip->set_features = nand_get_set_features_notsupp; chip->get_features = nand_get_set_features_notsupp; diff --git a/drivers/mtd/nand/raw/mtk_nand.c b/drivers/mtd/nand/raw/mtk_nand.c index 42f9dc2cd172..fe150e993acf 100644 --- a/drivers/mtd/nand/raw/mtk_nand.c +++ b/drivers/mtd/nand/raw/mtk_nand.c @@ -1334,10 +1334,10 @@ static int mtk_nfc_nand_chip_init(struct device *dev, struct mtk_nfc *nfc, nand->options |= NAND_USE_BOUNCE_BUFFER | NAND_SUBPAGE_READ; nand->dev_ready = mtk_nfc_dev_ready; nand->select_chip = mtk_nfc_select_chip; - nand->write_byte = mtk_nfc_write_byte; - nand->write_buf = mtk_nfc_write_buf; - nand->read_byte = mtk_nfc_read_byte; - nand->read_buf = mtk_nfc_read_buf; + nand->legacy.write_byte = mtk_nfc_write_byte; + nand->legacy.write_buf = mtk_nfc_write_buf; + nand->legacy.read_byte = mtk_nfc_read_byte; + nand->legacy.read_buf = mtk_nfc_read_buf; nand->cmd_ctrl = mtk_nfc_cmd_ctrl; nand->setup_data_interface = mtk_nfc_setup_data_interface; diff --git a/drivers/mtd/nand/raw/mxc_nand.c b/drivers/mtd/nand/raw/mxc_nand.c index 895f85ee29db..f7e439f578da 100644 --- a/drivers/mtd/nand/raw/mxc_nand.c +++ b/drivers/mtd/nand/raw/mxc_nand.c @@ -1402,7 +1402,7 @@ static int mxc_nand_set_features(struct nand_chip *chip, int addr, host->buf_start = 0; for (i = 0; i < ONFI_SUBFEATURE_PARAM_LEN; ++i) - chip->write_byte(chip, subfeature_param[i]); + chip->legacy.write_byte(chip, subfeature_param[i]); memcpy32_toio(host->main_area0, host->data_buf, mtd->writesize); host->devtype_data->send_cmd(host, NAND_CMD_SET_FEATURES, false); @@ -1426,7 +1426,7 @@ static int mxc_nand_get_features(struct nand_chip *chip, int addr, host->buf_start = 0; for (i = 0; i < ONFI_SUBFEATURE_PARAM_LEN; ++i) - *subfeature_param++ = chip->read_byte(chip); + *subfeature_param++ = chip->legacy.read_byte(chip); return 0; } @@ -1775,9 +1775,9 @@ static int mxcnd_probe(struct platform_device *pdev) nand_set_flash_node(this, pdev->dev.of_node), this->dev_ready = mxc_nand_dev_ready; this->cmdfunc = mxc_nand_command; - this->read_byte = mxc_nand_read_byte; - this->write_buf = mxc_nand_write_buf; - this->read_buf = mxc_nand_read_buf; + this->legacy.read_byte = mxc_nand_read_byte; + this->legacy.write_buf = mxc_nand_write_buf; + this->legacy.read_buf = mxc_nand_read_buf; this->set_features = mxc_nand_set_features; this->get_features = mxc_nand_get_features; diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c index 1edaa9fdbce9..016ef405474c 100644 --- a/drivers/mtd/nand/raw/nand_base.c +++ b/drivers/mtd/nand/raw/nand_base.c @@ -305,7 +305,7 @@ static void nand_select_chip(struct nand_chip *chip, int chipnr) */ static void nand_write_byte(struct nand_chip *chip, uint8_t byte) { - chip->write_buf(chip, &byte, 1); + chip->legacy.write_buf(chip, &byte, 1); } /** @@ -335,7 +335,7 @@ static void nand_write_byte16(struct nand_chip *chip, uint8_t byte) * neither an address nor a command transfer. Let's assume a 0 on the * upper I/O lines is OK. */ - chip->write_buf(chip, (uint8_t *)&word, 2); + chip->legacy.write_buf(chip, (uint8_t *)&word, 2); } /** @@ -1524,7 +1524,7 @@ int nand_read_page_op(struct nand_chip *chip, unsigned int page, chip->cmdfunc(chip, NAND_CMD_READ0, offset_in_page, page); if (len) - chip->read_buf(chip, buf, len); + chip->legacy.read_buf(chip, buf, len); return 0; } @@ -1572,7 +1572,7 @@ static int nand_read_param_page_op(struct nand_chip *chip, u8 page, void *buf, chip->cmdfunc(chip, NAND_CMD_PARAM, page, -1); for (i = 0; i < len; i++) - p[i] = chip->read_byte(chip); + p[i] = chip->legacy.read_byte(chip); return 0; } @@ -1635,7 +1635,7 @@ int nand_change_read_column_op(struct nand_chip *chip, chip->cmdfunc(chip, NAND_CMD_RNDOUT, offset_in_page, -1); if (len) - chip->read_buf(chip, buf, len); + chip->legacy.read_buf(chip, buf, len); return 0; } @@ -1672,7 +1672,7 @@ int nand_read_oob_op(struct nand_chip *chip, unsigned int page, chip->cmdfunc(chip, NAND_CMD_READOOB, offset_in_oob, page); if (len) - chip->read_buf(chip, buf, len); + chip->legacy.read_buf(chip, buf, len); return 0; } @@ -1785,7 +1785,7 @@ int nand_prog_page_begin_op(struct nand_chip *chip, unsigned int page, chip->cmdfunc(chip, NAND_CMD_SEQIN, offset_in_page, page); if (buf) - chip->write_buf(chip, buf, len); + chip->legacy.write_buf(chip, buf, len); return 0; } @@ -1869,7 +1869,7 @@ int nand_prog_page_op(struct nand_chip *chip, unsigned int page, len, true); } else { chip->cmdfunc(chip, NAND_CMD_SEQIN, offset_in_page, page); - chip->write_buf(chip, buf, len); + chip->legacy.write_buf(chip, buf, len); chip->cmdfunc(chip, NAND_CMD_PAGEPROG, -1, -1); status = chip->waitfunc(chip); } @@ -1938,7 +1938,7 @@ int nand_change_write_column_op(struct nand_chip *chip, chip->cmdfunc(chip, NAND_CMD_RNDIN, offset_in_page, -1); if (len) - chip->write_buf(chip, buf, len); + chip->legacy.write_buf(chip, buf, len); return 0; } @@ -1986,7 +1986,7 @@ int nand_readid_op(struct nand_chip *chip, u8 addr, void *buf, chip->cmdfunc(chip, NAND_CMD_READID, addr, -1); for (i = 0; i < len; i++) - id[i] = chip->read_byte(chip); + id[i] = chip->legacy.read_byte(chip); return 0; } @@ -2023,7 +2023,7 @@ int nand_status_op(struct nand_chip *chip, u8 *status) chip->cmdfunc(chip, NAND_CMD_STATUS, -1, -1); if (status) - *status = chip->read_byte(chip); + *status = chip->legacy.read_byte(chip); return 0; } @@ -2151,7 +2151,7 @@ static int nand_set_features_op(struct nand_chip *chip, u8 feature, chip->cmdfunc(chip, NAND_CMD_SET_FEATURES, feature, -1); for (i = 0; i < ONFI_SUBFEATURE_PARAM_LEN; ++i) - chip->write_byte(chip, params[i]); + chip->legacy.write_byte(chip, params[i]); ret = chip->waitfunc(chip); if (ret < 0) @@ -2199,7 +2199,7 @@ static int nand_get_features_op(struct nand_chip *chip, u8 feature, chip->cmdfunc(chip, NAND_CMD_GET_FEATURES, feature, -1); for (i = 0; i < ONFI_SUBFEATURE_PARAM_LEN; ++i) - params[i] = chip->read_byte(chip); + params[i] = chip->legacy.read_byte(chip); return 0; } @@ -2291,9 +2291,9 @@ int nand_read_data_op(struct nand_chip *chip, void *buf, unsigned int len, unsigned int i; for (i = 0; i < len; i++) - p[i] = chip->read_byte(chip); + p[i] = chip->legacy.read_byte(chip); } else { - chip->read_buf(chip, buf, len); + chip->legacy.read_buf(chip, buf, len); } return 0; @@ -2335,9 +2335,9 @@ int nand_write_data_op(struct nand_chip *chip, const void *buf, unsigned int i; for (i = 0; i < len; i++) - chip->write_byte(chip, p[i]); + chip->legacy.write_byte(chip, p[i]); } else { - chip->write_buf(chip, buf, len); + chip->legacy.write_buf(chip, buf, len); } return 0; @@ -4936,18 +4936,18 @@ static void nand_set_defaults(struct nand_chip *chip) chip->get_features = nand_default_get_features; /* If called twice, pointers that depend on busw may need to be reset */ - if (!chip->read_byte || chip->read_byte == nand_read_byte) - chip->read_byte = busw ? nand_read_byte16 : nand_read_byte; + if (!chip->legacy.read_byte || chip->legacy.read_byte == nand_read_byte) + chip->legacy.read_byte = busw ? nand_read_byte16 : nand_read_byte; if (!chip->block_bad) chip->block_bad = nand_block_bad; if (!chip->block_markbad) chip->block_markbad = nand_default_block_markbad; - if (!chip->write_buf || chip->write_buf == nand_write_buf) - chip->write_buf = busw ? nand_write_buf16 : nand_write_buf; - if (!chip->write_byte || chip->write_byte == nand_write_byte) - chip->write_byte = busw ? nand_write_byte16 : nand_write_byte; - if (!chip->read_buf || chip->read_buf == nand_read_buf) - chip->read_buf = busw ? nand_read_buf16 : nand_read_buf; + if (!chip->legacy.write_buf || chip->legacy.write_buf == nand_write_buf) + chip->legacy.write_buf = busw ? nand_write_buf16 : nand_write_buf; + if (!chip->legacy.write_byte || chip->legacy.write_byte == nand_write_byte) + chip->legacy.write_byte = busw ? nand_write_byte16 : nand_write_byte; + if (!chip->legacy.read_buf || chip->legacy.read_buf == nand_read_buf) + chip->legacy.read_buf = busw ? nand_read_buf16 : nand_read_buf; if (!chip->controller) { chip->controller = &chip->dummy_controller; diff --git a/drivers/mtd/nand/raw/nand_hynix.c b/drivers/mtd/nand/raw/nand_hynix.c index bb1c4f8ce785..6a2f3efad153 100644 --- a/drivers/mtd/nand/raw/nand_hynix.c +++ b/drivers/mtd/nand/raw/nand_hynix.c @@ -108,7 +108,7 @@ static int hynix_nand_reg_write_op(struct nand_chip *chip, u8 addr, u8 val) } chip->cmdfunc(chip, NAND_CMD_NONE, column, -1); - chip->write_byte(chip, val); + chip->legacy.write_byte(chip, val); return 0; } diff --git a/drivers/mtd/nand/raw/nandsim.c b/drivers/mtd/nand/raw/nandsim.c index f750783d5d6a..f3219122e311 100644 --- a/drivers/mtd/nand/raw/nandsim.c +++ b/drivers/mtd/nand/raw/nandsim.c @@ -2156,7 +2156,7 @@ static void ns_nand_read_buf(struct nand_chip *chip, u_char *buf, int len) int i; for (i = 0; i < len; i++) - buf[i] = chip->read_byte(chip); + buf[i] = chip->legacy.read_byte(chip); return; } @@ -2250,10 +2250,10 @@ static int __init ns_init_module(void) * Register simulator's callbacks. */ chip->cmd_ctrl = ns_hwcontrol; - chip->read_byte = ns_nand_read_byte; + chip->legacy.read_byte = ns_nand_read_byte; chip->dev_ready = ns_device_ready; - chip->write_buf = ns_nand_write_buf; - chip->read_buf = ns_nand_read_buf; + chip->legacy.write_buf = ns_nand_write_buf; + chip->legacy.read_buf = ns_nand_read_buf; chip->ecc.mode = NAND_ECC_SOFT; chip->ecc.algo = NAND_ECC_HAMMING; /* The NAND_SKIP_BBTSCAN option is necessary for 'overridesize' */ diff --git a/drivers/mtd/nand/raw/ndfc.c b/drivers/mtd/nand/raw/ndfc.c index adc4060c65ad..7377dc752431 100644 --- a/drivers/mtd/nand/raw/ndfc.c +++ b/drivers/mtd/nand/raw/ndfc.c @@ -149,8 +149,8 @@ static int ndfc_chip_init(struct ndfc_controller *ndfc, chip->select_chip = ndfc_select_chip; chip->chip_delay = 50; chip->controller = &ndfc->ndfc_control; - chip->read_buf = ndfc_read_buf; - chip->write_buf = ndfc_write_buf; + chip->legacy.read_buf = ndfc_read_buf; + chip->legacy.write_buf = ndfc_write_buf; chip->ecc.correct = nand_correct_data; chip->ecc.hwctl = ndfc_enable_hwecc; chip->ecc.calculate = ndfc_calculate_ecc; diff --git a/drivers/mtd/nand/raw/nuc900_nand.c b/drivers/mtd/nand/raw/nuc900_nand.c index 3aae5fda5399..71b0a41bc497 100644 --- a/drivers/mtd/nand/raw/nuc900_nand.c +++ b/drivers/mtd/nand/raw/nuc900_nand.c @@ -256,9 +256,9 @@ static int nuc900_nand_probe(struct platform_device *pdev) chip->cmdfunc = nuc900_nand_command_lp; chip->dev_ready = nuc900_nand_devready; - chip->read_byte = nuc900_nand_read_byte; - chip->write_buf = nuc900_nand_write_buf; - chip->read_buf = nuc900_nand_read_buf; + chip->legacy.read_byte = nuc900_nand_read_byte; + chip->legacy.write_buf = nuc900_nand_write_buf; + chip->legacy.read_buf = nuc900_nand_read_buf; chip->chip_delay = 50; chip->options = 0; chip->ecc.mode = NAND_ECC_SOFT; diff --git a/drivers/mtd/nand/raw/omap2.c b/drivers/mtd/nand/raw/omap2.c index 627048886c95..3ab4a2c5fc2d 100644 --- a/drivers/mtd/nand/raw/omap2.c +++ b/drivers/mtd/nand/raw/omap2.c @@ -1539,7 +1539,7 @@ static int omap_write_page_bch(struct nand_chip *chip, const uint8_t *buf, chip->ecc.hwctl(chip, NAND_ECC_WRITE); /* Write data */ - chip->write_buf(chip, buf, mtd->writesize); + chip->legacy.write_buf(chip, buf, mtd->writesize); /* Update ecc vector from GPMC result registers */ omap_calculate_ecc_bch_multi(mtd, buf, &ecc_calc[0]); @@ -1550,7 +1550,7 @@ static int omap_write_page_bch(struct nand_chip *chip, const uint8_t *buf, return ret; /* Write ecc vector to OOB area */ - chip->write_buf(chip, chip->oob_poi, mtd->oobsize); + chip->legacy.write_buf(chip, chip->oob_poi, mtd->oobsize); return nand_prog_page_end_op(chip); } @@ -1591,7 +1591,7 @@ static int omap_write_subpage_bch(struct nand_chip *chip, u32 offset, chip->ecc.hwctl(chip, NAND_ECC_WRITE); /* Write data */ - chip->write_buf(chip, buf, mtd->writesize); + chip->legacy.write_buf(chip, buf, mtd->writesize); for (step = 0; step < ecc_steps; step++) { /* mask ECC of un-touched subpages by padding 0xFF */ @@ -1616,7 +1616,7 @@ static int omap_write_subpage_bch(struct nand_chip *chip, u32 offset, return ret; /* write OOB buffer to NAND device */ - chip->write_buf(chip, chip->oob_poi, mtd->oobsize); + chip->legacy.write_buf(chip, chip->oob_poi, mtd->oobsize); return nand_prog_page_end_op(chip); } @@ -1650,7 +1650,7 @@ static int omap_read_page_bch(struct nand_chip *chip, uint8_t *buf, chip->ecc.hwctl(chip, NAND_ECC_READ); /* Read data */ - chip->read_buf(chip, buf, mtd->writesize); + chip->legacy.read_buf(chip, buf, mtd->writesize); /* Read oob bytes */ nand_change_read_column_op(chip, @@ -1933,8 +1933,8 @@ static int omap_nand_attach_chip(struct nand_chip *chip) /* Re-populate low-level callbacks based on xfer modes */ switch (info->xfer_type) { case NAND_OMAP_PREFETCH_POLLED: - chip->read_buf = omap_read_buf_pref; - chip->write_buf = omap_write_buf_pref; + chip->legacy.read_buf = omap_read_buf_pref; + chip->legacy.write_buf = omap_write_buf_pref; break; case NAND_OMAP_POLLED: @@ -1966,8 +1966,8 @@ static int omap_nand_attach_chip(struct nand_chip *chip) err); return err; } - chip->read_buf = omap_read_buf_dma_pref; - chip->write_buf = omap_write_buf_dma_pref; + chip->legacy.read_buf = omap_read_buf_dma_pref; + chip->legacy.write_buf = omap_write_buf_dma_pref; } break; @@ -2002,8 +2002,8 @@ static int omap_nand_attach_chip(struct nand_chip *chip) return err; } - chip->read_buf = omap_read_buf_irq_pref; - chip->write_buf = omap_write_buf_irq_pref; + chip->legacy.read_buf = omap_read_buf_irq_pref; + chip->legacy.write_buf = omap_write_buf_irq_pref; break; diff --git a/drivers/mtd/nand/raw/orion_nand.c b/drivers/mtd/nand/raw/orion_nand.c index d73e3c7a3f3a..f0d0054b4a7a 100644 --- a/drivers/mtd/nand/raw/orion_nand.c +++ b/drivers/mtd/nand/raw/orion_nand.c @@ -138,7 +138,7 @@ static int __init orion_nand_probe(struct platform_device *pdev) nand_set_flash_node(nc, pdev->dev.of_node); nc->legacy.IO_ADDR_R = nc->legacy.IO_ADDR_W = io_base; nc->cmd_ctrl = orion_nand_cmd_ctrl; - nc->read_buf = orion_nand_read_buf; + nc->legacy.read_buf = orion_nand_read_buf; nc->ecc.mode = NAND_ECC_SOFT; nc->ecc.algo = NAND_ECC_HAMMING; diff --git a/drivers/mtd/nand/raw/oxnas_nand.c b/drivers/mtd/nand/raw/oxnas_nand.c index ab32df146505..16df274f4cd6 100644 --- a/drivers/mtd/nand/raw/oxnas_nand.c +++ b/drivers/mtd/nand/raw/oxnas_nand.c @@ -133,9 +133,9 @@ static int oxnas_nand_probe(struct platform_device *pdev) mtd->priv = chip; chip->cmd_ctrl = oxnas_nand_cmd_ctrl; - chip->read_buf = oxnas_nand_read_buf; - chip->read_byte = oxnas_nand_read_byte; - chip->write_buf = oxnas_nand_write_buf; + chip->legacy.read_buf = oxnas_nand_read_buf; + chip->legacy.read_byte = oxnas_nand_read_byte; + chip->legacy.write_buf = oxnas_nand_write_buf; chip->chip_delay = 30; /* Scan to find existence of the device */ diff --git a/drivers/mtd/nand/raw/pasemi_nand.c b/drivers/mtd/nand/raw/pasemi_nand.c index 1b367bf9ef53..ca158dabe8b9 100644 --- a/drivers/mtd/nand/raw/pasemi_nand.c +++ b/drivers/mtd/nand/raw/pasemi_nand.c @@ -141,8 +141,8 @@ static int pasemi_nand_probe(struct platform_device *ofdev) chip->cmd_ctrl = pasemi_hwcontrol; chip->dev_ready = pasemi_device_ready; - chip->read_buf = pasemi_read_buf; - chip->write_buf = pasemi_write_buf; + chip->legacy.read_buf = pasemi_read_buf; + chip->legacy.write_buf = pasemi_write_buf; chip->chip_delay = 0; chip->ecc.mode = NAND_ECC_SOFT; chip->ecc.algo = NAND_ECC_HAMMING; diff --git a/drivers/mtd/nand/raw/plat_nand.c b/drivers/mtd/nand/raw/plat_nand.c index c06347531d26..971e387a8a75 100644 --- a/drivers/mtd/nand/raw/plat_nand.c +++ b/drivers/mtd/nand/raw/plat_nand.c @@ -65,8 +65,8 @@ static int plat_nand_probe(struct platform_device *pdev) data->chip.cmd_ctrl = pdata->ctrl.cmd_ctrl; data->chip.dev_ready = pdata->ctrl.dev_ready; data->chip.select_chip = pdata->ctrl.select_chip; - data->chip.write_buf = pdata->ctrl.write_buf; - data->chip.read_buf = pdata->ctrl.read_buf; + data->chip.legacy.write_buf = pdata->ctrl.write_buf; + data->chip.legacy.read_buf = pdata->ctrl.read_buf; data->chip.chip_delay = pdata->chip.chip_delay; data->chip.options |= pdata->chip.options; data->chip.bbt_options |= pdata->chip.bbt_options; diff --git a/drivers/mtd/nand/raw/qcom_nandc.c b/drivers/mtd/nand/raw/qcom_nandc.c index 9037dddff99a..7b487a2ffa8e 100644 --- a/drivers/mtd/nand/raw/qcom_nandc.c +++ b/drivers/mtd/nand/raw/qcom_nandc.c @@ -349,7 +349,8 @@ struct nandc_regs { * @data_buffer: our local DMA buffer for page read/writes, * used when we can't use the buffer provided * by upper layers directly - * @buf_size/count/start: markers for chip->read_buf/write_buf functions + * @buf_size/count/start: markers for chip->legacy.read_buf/write_buf + * functions * @reg_read_buf: local buffer for reading back registers via DMA * @reg_read_dma: contains dma address for register read buffer * @reg_read_pos: marker for data read in reg_read_buf @@ -2275,10 +2276,10 @@ static int qcom_nandc_block_markbad(struct nand_chip *chip, loff_t ofs) } /* - * the three functions below implement chip->read_byte(), chip->read_buf() - * and chip->write_buf() respectively. these aren't used for - * reading/writing page data, they are used for smaller data like reading - * id, status etc + * the three functions below implement chip->legacy.read_byte(), + * chip->legacy.read_buf() and chip->legacy.write_buf() respectively. these + * aren't used for reading/writing page data, they are used for smaller data + * like reading id, status etc */ static uint8_t qcom_nandc_read_byte(struct nand_chip *chip) { @@ -2804,9 +2805,9 @@ static int qcom_nand_host_init_and_register(struct qcom_nand_controller *nandc, chip->cmdfunc = qcom_nandc_command; chip->select_chip = qcom_nandc_select_chip; - chip->read_byte = qcom_nandc_read_byte; - chip->read_buf = qcom_nandc_read_buf; - chip->write_buf = qcom_nandc_write_buf; + chip->legacy.read_byte = qcom_nandc_read_byte; + chip->legacy.read_buf = qcom_nandc_read_buf; + chip->legacy.write_buf = qcom_nandc_write_buf; chip->set_features = nand_get_set_features_notsupp; chip->get_features = nand_get_set_features_notsupp; diff --git a/drivers/mtd/nand/raw/r852.c b/drivers/mtd/nand/raw/r852.c index 2c30e97ab2a4..05b669d34cec 100644 --- a/drivers/mtd/nand/raw/r852.c +++ b/drivers/mtd/nand/raw/r852.c @@ -858,9 +858,9 @@ static int r852_probe(struct pci_dev *pci_dev, const struct pci_device_id *id) chip->dev_ready = r852_ready; /* I/O */ - chip->read_byte = r852_read_byte; - chip->read_buf = r852_read_buf; - chip->write_buf = r852_write_buf; + chip->legacy.read_byte = r852_read_byte; + chip->legacy.read_buf = r852_read_buf; + chip->legacy.write_buf = r852_write_buf; /* ecc */ chip->ecc.mode = NAND_ECC_HW_SYNDROME; diff --git a/drivers/mtd/nand/raw/s3c2410.c b/drivers/mtd/nand/raw/s3c2410.c index 473abf10eeec..d0670ebd5b68 100644 --- a/drivers/mtd/nand/raw/s3c2410.c +++ b/drivers/mtd/nand/raw/s3c2410.c @@ -864,8 +864,8 @@ static void s3c2410_nand_init_chip(struct s3c2410_nand_info *info, nand_set_flash_node(chip, set->of_node); - chip->write_buf = s3c2410_nand_write_buf; - chip->read_buf = s3c2410_nand_read_buf; + chip->legacy.write_buf = s3c2410_nand_write_buf; + chip->legacy.read_buf = s3c2410_nand_read_buf; chip->select_chip = s3c2410_nand_select_chip; chip->chip_delay = 50; nand_set_controller_data(chip, nmtd); @@ -894,8 +894,8 @@ static void s3c2410_nand_init_chip(struct s3c2410_nand_info *info, info->sel_bit = S3C2440_NFCONT_nFCE; chip->cmd_ctrl = s3c2440_nand_hwcontrol; chip->dev_ready = s3c2440_nand_devready; - chip->read_buf = s3c2440_nand_read_buf; - chip->write_buf = s3c2440_nand_write_buf; + chip->legacy.read_buf = s3c2440_nand_read_buf; + chip->legacy.write_buf = s3c2440_nand_write_buf; break; case TYPE_S3C2412: diff --git a/drivers/mtd/nand/raw/sh_flctl.c b/drivers/mtd/nand/raw/sh_flctl.c index 4b1c7e435937..d83d53810590 100644 --- a/drivers/mtd/nand/raw/sh_flctl.c +++ b/drivers/mtd/nand/raw/sh_flctl.c @@ -618,7 +618,7 @@ static int flctl_read_page_hwecc(struct nand_chip *chip, uint8_t *buf, nand_read_page_op(chip, page, 0, buf, mtd->writesize); if (oob_required) - chip->read_buf(chip, chip->oob_poi, mtd->oobsize); + chip->legacy.read_buf(chip, chip->oob_poi, mtd->oobsize); return 0; } @@ -628,7 +628,7 @@ static int flctl_write_page_hwecc(struct nand_chip *chip, const uint8_t *buf, struct mtd_info *mtd = nand_to_mtd(chip); nand_prog_page_begin_op(chip, page, 0, buf, mtd->writesize); - chip->write_buf(chip, chip->oob_poi, mtd->oobsize); + chip->legacy.write_buf(chip, chip->oob_poi, mtd->oobsize); return nand_prog_page_end_op(chip); } @@ -1180,9 +1180,9 @@ static int flctl_probe(struct platform_device *pdev) /* 20 us command delay time */ nand->chip_delay = 20; - nand->read_byte = flctl_read_byte; - nand->write_buf = flctl_write_buf; - nand->read_buf = flctl_read_buf; + nand->legacy.read_byte = flctl_read_byte; + nand->legacy.write_buf = flctl_write_buf; + nand->legacy.read_buf = flctl_read_buf; nand->select_chip = flctl_select_chip; nand->cmdfunc = flctl_cmdfunc; nand->set_features = nand_get_set_features_notsupp; diff --git a/drivers/mtd/nand/raw/socrates_nand.c b/drivers/mtd/nand/raw/socrates_nand.c index aa42b4ea4d23..006224a40f3b 100644 --- a/drivers/mtd/nand/raw/socrates_nand.c +++ b/drivers/mtd/nand/raw/socrates_nand.c @@ -153,9 +153,9 @@ static int socrates_nand_probe(struct platform_device *ofdev) mtd->dev.parent = &ofdev->dev; nand_chip->cmd_ctrl = socrates_nand_cmd_ctrl; - nand_chip->read_byte = socrates_nand_read_byte; - nand_chip->write_buf = socrates_nand_write_buf; - nand_chip->read_buf = socrates_nand_read_buf; + nand_chip->legacy.read_byte = socrates_nand_read_byte; + nand_chip->legacy.write_buf = socrates_nand_write_buf; + nand_chip->legacy.read_buf = socrates_nand_read_buf; nand_chip->dev_ready = socrates_nand_device_ready; nand_chip->ecc.mode = NAND_ECC_SOFT; /* enable ECC */ diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c index a3700b79bdeb..6e1317bde1b3 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -1924,9 +1924,9 @@ static int sunxi_nand_chip_init(struct device *dev, struct sunxi_nfc *nfc, nand_set_flash_node(nand, np); nand->select_chip = sunxi_nfc_select_chip; nand->cmd_ctrl = sunxi_nfc_cmd_ctrl; - nand->read_buf = sunxi_nfc_read_buf; - nand->write_buf = sunxi_nfc_write_buf; - nand->read_byte = sunxi_nfc_read_byte; + nand->legacy.read_buf = sunxi_nfc_read_buf; + nand->legacy.write_buf = sunxi_nfc_write_buf; + nand->legacy.read_byte = sunxi_nfc_read_byte; nand->setup_data_interface = sunxi_nfc_setup_data_interface; mtd = nand_to_mtd(nand); diff --git a/drivers/mtd/nand/raw/tango_nand.c b/drivers/mtd/nand/raw/tango_nand.c index bf7012099790..379f2ed284cb 100644 --- a/drivers/mtd/nand/raw/tango_nand.c +++ b/drivers/mtd/nand/raw/tango_nand.c @@ -564,9 +564,9 @@ static int chip_init(struct device *dev, struct device_node *np) ecc = &chip->ecc; mtd = nand_to_mtd(chip); - chip->read_byte = tango_read_byte; - chip->write_buf = tango_write_buf; - chip->read_buf = tango_read_buf; + chip->legacy.read_byte = tango_read_byte; + chip->legacy.write_buf = tango_write_buf; + chip->legacy.read_buf = tango_read_buf; chip->select_chip = tango_select_chip; chip->cmd_ctrl = tango_cmd_ctrl; chip->dev_ready = tango_dev_ready; diff --git a/drivers/mtd/nand/raw/tmio_nand.c b/drivers/mtd/nand/raw/tmio_nand.c index 0b23587bf47c..94e659158f16 100644 --- a/drivers/mtd/nand/raw/tmio_nand.c +++ b/drivers/mtd/nand/raw/tmio_nand.c @@ -405,9 +405,9 @@ static int tmio_probe(struct platform_device *dev) /* Set address of hardware control function */ nand_chip->cmd_ctrl = tmio_nand_hwcontrol; nand_chip->dev_ready = tmio_nand_dev_ready; - nand_chip->read_byte = tmio_nand_read_byte; - nand_chip->write_buf = tmio_nand_write_buf; - nand_chip->read_buf = tmio_nand_read_buf; + nand_chip->legacy.read_byte = tmio_nand_read_byte; + nand_chip->legacy.write_buf = tmio_nand_write_buf; + nand_chip->legacy.read_buf = tmio_nand_read_buf; /* set eccmode using hardware ECC */ nand_chip->ecc.mode = NAND_ECC_HW; diff --git a/drivers/mtd/nand/raw/txx9ndfmc.c b/drivers/mtd/nand/raw/txx9ndfmc.c index c84b2ad84cf7..7fb1575c6e2b 100644 --- a/drivers/mtd/nand/raw/txx9ndfmc.c +++ b/drivers/mtd/nand/raw/txx9ndfmc.c @@ -324,9 +324,9 @@ static int __init txx9ndfmc_probe(struct platform_device *dev) mtd = nand_to_mtd(chip); mtd->dev.parent = &dev->dev; - chip->read_byte = txx9ndfmc_read_byte; - chip->read_buf = txx9ndfmc_read_buf; - chip->write_buf = txx9ndfmc_write_buf; + chip->legacy.read_byte = txx9ndfmc_read_byte; + chip->legacy.read_buf = txx9ndfmc_read_buf; + chip->legacy.write_buf = txx9ndfmc_write_buf; chip->cmd_ctrl = txx9ndfmc_cmd_ctrl; chip->dev_ready = txx9ndfmc_dev_ready; chip->ecc.calculate = txx9ndfmc_calculate_ecc; diff --git a/drivers/mtd/nand/raw/xway_nand.c b/drivers/mtd/nand/raw/xway_nand.c index 3d91e98df5a8..87ec034bdd3e 100644 --- a/drivers/mtd/nand/raw/xway_nand.c +++ b/drivers/mtd/nand/raw/xway_nand.c @@ -177,9 +177,9 @@ static int xway_nand_probe(struct platform_device *pdev) data->chip.cmd_ctrl = xway_cmd_ctrl; data->chip.dev_ready = xway_dev_ready; data->chip.select_chip = xway_select_chip; - data->chip.write_buf = xway_write_buf; - data->chip.read_buf = xway_read_buf; - data->chip.read_byte = xway_read_byte; + data->chip.legacy.write_buf = xway_write_buf; + data->chip.legacy.read_buf = xway_read_buf; + data->chip.legacy.read_byte = xway_read_byte; data->chip.chip_delay = 30; data->chip.ecc.mode = NAND_ECC_SOFT; diff --git a/drivers/staging/mt29f_spinand/mt29f_spinand.c b/drivers/staging/mt29f_spinand/mt29f_spinand.c index f2e14f972319..4856593b626e 100644 --- a/drivers/staging/mt29f_spinand/mt29f_spinand.c +++ b/drivers/staging/mt29f_spinand/mt29f_spinand.c @@ -657,7 +657,7 @@ static int spinand_read_page_hwecc(struct nand_chip *chip, u8 *buf, nand_read_page_op(chip, page, 0, p, eccsize * eccsteps); if (oob_required) - chip->read_buf(chip, chip->oob_poi, mtd->oobsize); + chip->legacy.read_buf(chip, chip->oob_poi, mtd->oobsize); while (1) { retval = spinand_read_status(info->spi, &status); @@ -915,9 +915,9 @@ static int spinand_probe(struct spi_device *spi_nand) nand_set_flash_node(chip, spi_nand->dev.of_node); nand_set_controller_data(chip, info); - chip->read_buf = spinand_read_buf; - chip->write_buf = spinand_write_buf; - chip->read_byte = spinand_read_byte; + chip->legacy.read_buf = spinand_read_buf; + chip->legacy.write_buf = spinand_write_buf; + chip->legacy.read_byte = spinand_read_byte; chip->cmdfunc = spinand_cmdfunc; chip->waitfunc = spinand_wait; chip->options |= NAND_CACHEPRG; diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h index 6b1dc8fef89d..f961efd2eacc 100644 --- a/include/linux/mtd/rawnand.h +++ b/include/linux/mtd/rawnand.h @@ -1176,6 +1176,10 @@ int nand_op_parser_exec_op(struct nand_chip *chip, * struct nand_legacy - NAND chip legacy fields/hooks * @IO_ADDR_R: address to read the 8 I/O lines of the flash device * @IO_ADDR_W: address to write the 8 I/O lines of the flash device + * @read_byte: read one byte from the chip + * @write_byte: write a single byte to the chip on the low 8 I/O lines + * @write_buf: write data from the buffer to the chip + * @read_buf: read data from the chip into the buffer * * If you look at this structure you're already wrong. These fields/hooks are * all deprecated. @@ -1183,6 +1187,10 @@ int nand_op_parser_exec_op(struct nand_chip *chip, struct nand_legacy { void __iomem *IO_ADDR_R; void __iomem *IO_ADDR_W; + u8 (*read_byte)(struct nand_chip *chip); + void (*write_byte)(struct nand_chip *chip, u8 byte); + void (*write_buf)(struct nand_chip *chip, const u8 *buf, int len); + void (*read_buf)(struct nand_chip *chip, u8 *buf, int len); }; /** @@ -1193,11 +1201,6 @@ struct nand_legacy { * you're modifying an existing driver that is using those * fields/hooks, you should consider reworking the driver * avoid using them. - * @read_byte: [REPLACEABLE] read one byte from the chip - * @write_byte: [REPLACEABLE] write a single byte to the chip on the - * low 8 I/O lines - * @write_buf: [REPLACEABLE] write data from the buffer to the chip - * @read_buf: [REPLACEABLE] read data from the chip into the buffer * @select_chip: [REPLACEABLE] select chip nr * @block_bad: [REPLACEABLE] check if a block is bad, using OOB markers * @block_markbad: [REPLACEABLE] mark a block bad @@ -1213,8 +1216,8 @@ struct nand_legacy { * ready. * @exec_op: controller specific method to execute NAND operations. * This method replaces ->cmdfunc(), - * ->{read,write}_{buf,byte,word}(), ->dev_ready() and - * ->waifunc(). + * ->legacy.{read,write}_{buf,byte,word}(), ->dev_ready() + * and ->waifunc(). * @setup_read_retry: [FLASHSPECIFIC] flash (vendor) specific function for * setting the read-retry mode. Mostly needed for MLC NAND. * @ecc: [BOARDSPECIFIC] ECC control structure @@ -1297,10 +1300,6 @@ struct nand_chip { struct nand_legacy legacy; - uint8_t (*read_byte)(struct nand_chip *chip); - void (*write_byte)(struct nand_chip *chip, uint8_t byte); - void (*write_buf)(struct nand_chip *chip, const uint8_t *buf, int len); - void (*read_buf)(struct nand_chip *chip, uint8_t *buf, int len); void (*select_chip)(struct nand_chip *chip, int cs); int (*block_bad)(struct nand_chip *chip, loff_t ofs); int (*block_markbad)(struct nand_chip *chip, loff_t ofs); From bf6065c6c08fa3ed7bdf8d28b8062ce8e58c1543 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Fri, 7 Sep 2018 00:38:36 +0200 Subject: [PATCH 273/302] mtd: rawnand: Deprecate ->cmd_ctrl() and ->cmdfunc() Those hooks have been replaced by ->exec_op(). Move them to the nand_legacy struct. Signed-off-by: Boris Brezillon Signed-off-by: Miquel Raynal --- drivers/mtd/nand/raw/ams-delta.c | 2 +- drivers/mtd/nand/raw/atmel/nand-controller.c | 4 +- drivers/mtd/nand/raw/au1550nd.c | 2 +- .../mtd/nand/raw/bcm47xxnflash/ops_bcm4706.c | 6 +- drivers/mtd/nand/raw/brcmnand/brcmnand.c | 4 +- drivers/mtd/nand/raw/cafe_nand.c | 2 +- drivers/mtd/nand/raw/cmx270_nand.c | 2 +- drivers/mtd/nand/raw/cs553x_nand.c | 2 +- drivers/mtd/nand/raw/davinci_nand.c | 2 +- drivers/mtd/nand/raw/denali.c | 2 +- drivers/mtd/nand/raw/diskonchip.c | 6 +- drivers/mtd/nand/raw/fsl_elbc_nand.c | 2 +- drivers/mtd/nand/raw/fsl_ifc_nand.c | 2 +- drivers/mtd/nand/raw/fsl_upm.c | 4 +- drivers/mtd/nand/raw/gpio.c | 2 +- drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c | 2 +- drivers/mtd/nand/raw/hisi504_nand.c | 2 +- drivers/mtd/nand/raw/jz4740_nand.c | 2 +- drivers/mtd/nand/raw/jz4780_nand.c | 2 +- drivers/mtd/nand/raw/lpc32xx_mlc.c | 2 +- drivers/mtd/nand/raw/lpc32xx_slc.c | 2 +- drivers/mtd/nand/raw/mpc5121_nfc.c | 2 +- drivers/mtd/nand/raw/mtk_nand.c | 2 +- drivers/mtd/nand/raw/mxc_nand.c | 2 +- drivers/mtd/nand/raw/nand_base.c | 138 +++++++++--------- drivers/mtd/nand/raw/nand_hynix.c | 4 +- drivers/mtd/nand/raw/nandsim.c | 2 +- drivers/mtd/nand/raw/ndfc.c | 2 +- drivers/mtd/nand/raw/nuc900_nand.c | 2 +- drivers/mtd/nand/raw/omap2.c | 2 +- drivers/mtd/nand/raw/orion_nand.c | 2 +- drivers/mtd/nand/raw/oxnas_nand.c | 2 +- drivers/mtd/nand/raw/pasemi_nand.c | 2 +- drivers/mtd/nand/raw/plat_nand.c | 2 +- drivers/mtd/nand/raw/qcom_nandc.c | 14 +- drivers/mtd/nand/raw/r852.c | 2 +- drivers/mtd/nand/raw/s3c2410.c | 6 +- drivers/mtd/nand/raw/sh_flctl.c | 2 +- drivers/mtd/nand/raw/sharpsl.c | 2 +- drivers/mtd/nand/raw/socrates_nand.c | 2 +- drivers/mtd/nand/raw/sunxi_nand.c | 2 +- drivers/mtd/nand/raw/tango_nand.c | 2 +- drivers/mtd/nand/raw/tmio_nand.c | 2 +- drivers/mtd/nand/raw/txx9ndfmc.c | 2 +- drivers/mtd/nand/raw/xway_nand.c | 2 +- drivers/staging/mt29f_spinand/mt29f_spinand.c | 2 +- include/linux/mtd/rawnand.h | 21 ++- 47 files changed, 144 insertions(+), 137 deletions(-) diff --git a/drivers/mtd/nand/raw/ams-delta.c b/drivers/mtd/nand/raw/ams-delta.c index 6616f473aeb2..756f6339d457 100644 --- a/drivers/mtd/nand/raw/ams-delta.c +++ b/drivers/mtd/nand/raw/ams-delta.c @@ -213,7 +213,7 @@ static int ams_delta_init(struct platform_device *pdev) this->legacy.read_byte = ams_delta_read_byte; this->legacy.write_buf = ams_delta_write_buf; this->legacy.read_buf = ams_delta_read_buf; - this->cmd_ctrl = ams_delta_hwcontrol; + this->legacy.cmd_ctrl = ams_delta_hwcontrol; if (gpio_request(AMS_DELTA_GPIO_PIN_NAND_RB, "nand_rdy") == 0) { this->dev_ready = ams_delta_nand_ready; } else { diff --git a/drivers/mtd/nand/raw/atmel/nand-controller.c b/drivers/mtd/nand/raw/atmel/nand-controller.c index 9b2876b5a9c2..37f617ec178e 100644 --- a/drivers/mtd/nand/raw/atmel/nand-controller.c +++ b/drivers/mtd/nand/raw/atmel/nand-controller.c @@ -1472,7 +1472,7 @@ static void atmel_nand_init(struct atmel_nand_controller *nc, mtd->dev.parent = nc->dev; nand->base.controller = &nc->base; - chip->cmd_ctrl = atmel_nand_cmd_ctrl; + chip->legacy.cmd_ctrl = atmel_nand_cmd_ctrl; chip->legacy.read_byte = atmel_nand_read_byte; chip->legacy.write_byte = atmel_nand_write_byte; chip->legacy.read_buf = atmel_nand_read_buf; @@ -1524,7 +1524,7 @@ static void atmel_hsmc_nand_init(struct atmel_nand_controller *nc, atmel_nand_init(nc, nand); /* Overload some methods for the HSMC controller. */ - chip->cmd_ctrl = atmel_hsmc_nand_cmd_ctrl; + chip->legacy.cmd_ctrl = atmel_hsmc_nand_cmd_ctrl; chip->select_chip = atmel_hsmc_nand_select_chip; } diff --git a/drivers/mtd/nand/raw/au1550nd.c b/drivers/mtd/nand/raw/au1550nd.c index 0db5dc61b155..5d45f13288fc 100644 --- a/drivers/mtd/nand/raw/au1550nd.c +++ b/drivers/mtd/nand/raw/au1550nd.c @@ -430,7 +430,7 @@ static int au1550nd_probe(struct platform_device *pdev) this->dev_ready = au1550_device_ready; this->select_chip = au1550_select_chip; - this->cmdfunc = au1550_command; + this->legacy.cmdfunc = au1550_command; /* 30 us command delay time */ this->chip_delay = 30; diff --git a/drivers/mtd/nand/raw/bcm47xxnflash/ops_bcm4706.c b/drivers/mtd/nand/raw/bcm47xxnflash/ops_bcm4706.c index ea41d1b95c81..2bd389b49b4a 100644 --- a/drivers/mtd/nand/raw/bcm47xxnflash/ops_bcm4706.c +++ b/drivers/mtd/nand/raw/bcm47xxnflash/ops_bcm4706.c @@ -227,7 +227,7 @@ static void bcm47xxnflash_ops_bcm4706_cmdfunc(struct nand_chip *nand_chip, switch (command) { case NAND_CMD_RESET: - nand_chip->cmd_ctrl(nand_chip, command, NAND_CTRL_CLE); + nand_chip->legacy.cmd_ctrl(nand_chip, command, NAND_CTRL_CLE); ndelay(100); nand_wait_ready(nand_chip); @@ -384,9 +384,9 @@ int bcm47xxnflash_ops_bcm4706_init(struct bcm47xxnflash *b47n) u32 val; b47n->nand_chip.select_chip = bcm47xxnflash_ops_bcm4706_select_chip; - nand_chip->cmd_ctrl = bcm47xxnflash_ops_bcm4706_cmd_ctrl; + nand_chip->legacy.cmd_ctrl = bcm47xxnflash_ops_bcm4706_cmd_ctrl; nand_chip->dev_ready = bcm47xxnflash_ops_bcm4706_dev_ready; - b47n->nand_chip.cmdfunc = bcm47xxnflash_ops_bcm4706_cmdfunc; + b47n->nand_chip.legacy.cmdfunc = bcm47xxnflash_ops_bcm4706_cmdfunc; b47n->nand_chip.legacy.read_byte = bcm47xxnflash_ops_bcm4706_read_byte; b47n->nand_chip.legacy.read_buf = bcm47xxnflash_ops_bcm4706_read_buf; b47n->nand_chip.legacy.write_buf = bcm47xxnflash_ops_bcm4706_write_buf; diff --git a/drivers/mtd/nand/raw/brcmnand/brcmnand.c b/drivers/mtd/nand/raw/brcmnand/brcmnand.c index 4eb9244cc108..162ec11ab251 100644 --- a/drivers/mtd/nand/raw/brcmnand/brcmnand.c +++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c @@ -2270,8 +2270,8 @@ static int brcmnand_init_cs(struct brcmnand_host *host, struct device_node *dn) mtd->owner = THIS_MODULE; mtd->dev.parent = &pdev->dev; - chip->cmd_ctrl = brcmnand_cmd_ctrl; - chip->cmdfunc = brcmnand_cmdfunc; + chip->legacy.cmd_ctrl = brcmnand_cmd_ctrl; + chip->legacy.cmdfunc = brcmnand_cmdfunc; chip->waitfunc = brcmnand_waitfunc; chip->legacy.read_byte = brcmnand_read_byte; chip->legacy.read_buf = brcmnand_read_buf; diff --git a/drivers/mtd/nand/raw/cafe_nand.c b/drivers/mtd/nand/raw/cafe_nand.c index 95754d1f12b8..0f734442fd3d 100644 --- a/drivers/mtd/nand/raw/cafe_nand.c +++ b/drivers/mtd/nand/raw/cafe_nand.c @@ -703,7 +703,7 @@ static int cafe_nand_probe(struct pci_dev *pdev, goto out_ior; } - cafe->nand.cmdfunc = cafe_nand_cmdfunc; + cafe->nand.legacy.cmdfunc = cafe_nand_cmdfunc; cafe->nand.dev_ready = cafe_device_ready; cafe->nand.legacy.read_byte = cafe_read_byte; cafe->nand.legacy.read_buf = cafe_read_buf; diff --git a/drivers/mtd/nand/raw/cmx270_nand.c b/drivers/mtd/nand/raw/cmx270_nand.c index 18f10ae92dfc..c543f073d971 100644 --- a/drivers/mtd/nand/raw/cmx270_nand.c +++ b/drivers/mtd/nand/raw/cmx270_nand.c @@ -175,7 +175,7 @@ static int __init cmx270_init(void) /* insert callbacks */ this->legacy.IO_ADDR_R = cmx270_nand_io; this->legacy.IO_ADDR_W = cmx270_nand_io; - this->cmd_ctrl = cmx270_hwcontrol; + this->legacy.cmd_ctrl = cmx270_hwcontrol; this->dev_ready = cmx270_device_ready; /* 15 us command delay time */ diff --git a/drivers/mtd/nand/raw/cs553x_nand.c b/drivers/mtd/nand/raw/cs553x_nand.c index 8a3230041678..bd75ec4e5508 100644 --- a/drivers/mtd/nand/raw/cs553x_nand.c +++ b/drivers/mtd/nand/raw/cs553x_nand.c @@ -206,7 +206,7 @@ static int __init cs553x_init_one(int cs, int mmio, unsigned long adr) goto out_mtd; } - this->cmd_ctrl = cs553x_hwcontrol; + this->legacy.cmd_ctrl = cs553x_hwcontrol; this->dev_ready = cs553x_device_ready; this->legacy.read_byte = cs553x_read_byte; this->legacy.read_buf = cs553x_read_buf; diff --git a/drivers/mtd/nand/raw/davinci_nand.c b/drivers/mtd/nand/raw/davinci_nand.c index b7701caa5f94..5fcd8c30293a 100644 --- a/drivers/mtd/nand/raw/davinci_nand.c +++ b/drivers/mtd/nand/raw/davinci_nand.c @@ -781,7 +781,7 @@ static int nand_davinci_probe(struct platform_device *pdev) info->mask_cle = pdata->mask_cle ? : MASK_CLE; /* Set address of hardware control function */ - info->chip.cmd_ctrl = nand_davinci_hwcontrol; + info->chip.legacy.cmd_ctrl = nand_davinci_hwcontrol; info->chip.dev_ready = nand_davinci_dev_ready; /* Speed up buffer I/O */ diff --git a/drivers/mtd/nand/raw/denali.c b/drivers/mtd/nand/raw/denali.c index 2d963ed6643c..c11547bfb2e7 100644 --- a/drivers/mtd/nand/raw/denali.c +++ b/drivers/mtd/nand/raw/denali.c @@ -1345,7 +1345,7 @@ int denali_init(struct denali_nand_info *denali) chip->select_chip = denali_select_chip; chip->legacy.read_byte = denali_read_byte; chip->legacy.write_byte = denali_write_byte; - chip->cmd_ctrl = denali_cmd_ctrl; + chip->legacy.cmd_ctrl = denali_cmd_ctrl; chip->dev_ready = denali_dev_ready; chip->waitfunc = denali_waitfunc; diff --git a/drivers/mtd/nand/raw/diskonchip.c b/drivers/mtd/nand/raw/diskonchip.c index ec3336f071e7..2604e80b5475 100644 --- a/drivers/mtd/nand/raw/diskonchip.c +++ b/drivers/mtd/nand/raw/diskonchip.c @@ -1389,9 +1389,9 @@ static inline int __init doc2001plus_init(struct mtd_info *mtd) this->legacy.write_buf = doc2001plus_writebuf; this->legacy.read_buf = doc2001plus_readbuf; doc->late_init = inftl_scan_bbt; - this->cmd_ctrl = NULL; + this->legacy.cmd_ctrl = NULL; this->select_chip = doc2001plus_select_chip; - this->cmdfunc = doc2001plus_command; + this->legacy.cmdfunc = doc2001plus_command; this->ecc.hwctl = doc2001plus_enable_hwecc; doc->chips_per_floor = 1; @@ -1569,7 +1569,7 @@ static int __init doc_probe(unsigned long physadr) nand_set_controller_data(nand, doc); nand->select_chip = doc200x_select_chip; - nand->cmd_ctrl = doc200x_hwcontrol; + nand->legacy.cmd_ctrl = doc200x_hwcontrol; nand->dev_ready = doc200x_dev_ready; nand->waitfunc = doc200x_wait; nand->block_bad = doc200x_block_bad; diff --git a/drivers/mtd/nand/raw/fsl_elbc_nand.c b/drivers/mtd/nand/raw/fsl_elbc_nand.c index 5e7b912f63b3..fa21d00c3443 100644 --- a/drivers/mtd/nand/raw/fsl_elbc_nand.c +++ b/drivers/mtd/nand/raw/fsl_elbc_nand.c @@ -780,7 +780,7 @@ static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv) chip->legacy.write_buf = fsl_elbc_write_buf; chip->legacy.read_buf = fsl_elbc_read_buf; chip->select_chip = fsl_elbc_select_chip; - chip->cmdfunc = fsl_elbc_cmdfunc; + chip->legacy.cmdfunc = fsl_elbc_cmdfunc; chip->waitfunc = fsl_elbc_wait; chip->set_features = nand_get_set_features_notsupp; chip->get_features = nand_get_set_features_notsupp; diff --git a/drivers/mtd/nand/raw/fsl_ifc_nand.c b/drivers/mtd/nand/raw/fsl_ifc_nand.c index ed3b90f2fb50..20c86b6503a8 100644 --- a/drivers/mtd/nand/raw/fsl_ifc_nand.c +++ b/drivers/mtd/nand/raw/fsl_ifc_nand.c @@ -865,7 +865,7 @@ static int fsl_ifc_chip_init(struct fsl_ifc_mtd *priv) chip->legacy.write_buf = fsl_ifc_write_buf; chip->legacy.read_buf = fsl_ifc_read_buf; chip->select_chip = fsl_ifc_select_chip; - chip->cmdfunc = fsl_ifc_cmdfunc; + chip->legacy.cmdfunc = fsl_ifc_cmdfunc; chip->waitfunc = fsl_ifc_wait; chip->set_features = nand_get_set_features_notsupp; chip->get_features = nand_get_set_features_notsupp; diff --git a/drivers/mtd/nand/raw/fsl_upm.c b/drivers/mtd/nand/raw/fsl_upm.c index db194ad12074..23baef375bfb 100644 --- a/drivers/mtd/nand/raw/fsl_upm.c +++ b/drivers/mtd/nand/raw/fsl_upm.c @@ -112,7 +112,7 @@ static void fun_select_chip(struct nand_chip *chip, int mchip_nr) struct fsl_upm_nand *fun = to_fsl_upm_nand(nand_to_mtd(chip)); if (mchip_nr == -1) { - chip->cmd_ctrl(chip, NAND_CMD_NONE, 0 | NAND_CTRL_CHANGE); + chip->legacy.cmd_ctrl(chip, NAND_CMD_NONE, 0 | NAND_CTRL_CHANGE); } else if (mchip_nr >= 0 && mchip_nr < NAND_MAX_CHIPS) { fun->mchip_number = mchip_nr; chip->legacy.IO_ADDR_R = fun->io_base + fun->mchip_offsets[mchip_nr]; @@ -162,7 +162,7 @@ static int fun_chip_init(struct fsl_upm_nand *fun, fun->chip.legacy.IO_ADDR_R = fun->io_base; fun->chip.legacy.IO_ADDR_W = fun->io_base; - fun->chip.cmd_ctrl = fun_cmd_ctrl; + fun->chip.legacy.cmd_ctrl = fun_cmd_ctrl; fun->chip.chip_delay = fun->chip_delay; fun->chip.legacy.read_byte = fun_read_byte; fun->chip.legacy.read_buf = fun_read_buf; diff --git a/drivers/mtd/nand/raw/gpio.c b/drivers/mtd/nand/raw/gpio.c index bb43fad65362..1e6e81047978 100644 --- a/drivers/mtd/nand/raw/gpio.c +++ b/drivers/mtd/nand/raw/gpio.c @@ -279,7 +279,7 @@ static int gpio_nand_probe(struct platform_device *pdev) chip->ecc.algo = NAND_ECC_HAMMING; chip->options = gpiomtd->plat.options; chip->chip_delay = gpiomtd->plat.chip_delay; - chip->cmd_ctrl = gpio_nand_cmd_ctrl; + chip->legacy.cmd_ctrl = gpio_nand_cmd_ctrl; mtd = nand_to_mtd(chip); mtd->dev.parent = dev; diff --git a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c index 54f1a84c6520..fa37d21e5f16 100644 --- a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c +++ b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c @@ -1902,7 +1902,7 @@ static int gpmi_nand_init(struct gpmi_nand_data *this) nand_set_flash_node(chip, this->pdev->dev.of_node); chip->select_chip = gpmi_select_chip; chip->setup_data_interface = gpmi_setup_data_interface; - chip->cmd_ctrl = gpmi_cmd_ctrl; + chip->legacy.cmd_ctrl = gpmi_cmd_ctrl; chip->dev_ready = gpmi_dev_ready; chip->legacy.read_byte = gpmi_read_byte; chip->legacy.read_buf = gpmi_read_buf; diff --git a/drivers/mtd/nand/raw/hisi504_nand.c b/drivers/mtd/nand/raw/hisi504_nand.c index 1046f51bbcd2..6e17239983db 100644 --- a/drivers/mtd/nand/raw/hisi504_nand.c +++ b/drivers/mtd/nand/raw/hisi504_nand.c @@ -782,7 +782,7 @@ static int hisi_nfc_probe(struct platform_device *pdev) nand_set_controller_data(chip, host); nand_set_flash_node(chip, np); - chip->cmdfunc = hisi_nfc_cmdfunc; + chip->legacy.cmdfunc = hisi_nfc_cmdfunc; chip->select_chip = hisi_nfc_select_chip; chip->legacy.read_byte = hisi_nfc_read_byte; chip->legacy.write_buf = hisi_nfc_write_buf; diff --git a/drivers/mtd/nand/raw/jz4740_nand.c b/drivers/mtd/nand/raw/jz4740_nand.c index 449180de92e2..ae0c268a5cb6 100644 --- a/drivers/mtd/nand/raw/jz4740_nand.c +++ b/drivers/mtd/nand/raw/jz4740_nand.c @@ -426,7 +426,7 @@ static int jz_nand_probe(struct platform_device *pdev) chip->ecc.options = NAND_ECC_GENERIC_ERASED_CHECK; chip->chip_delay = 50; - chip->cmd_ctrl = jz_nand_cmd_ctrl; + chip->legacy.cmd_ctrl = jz_nand_cmd_ctrl; chip->select_chip = jz_nand_select_chip; chip->dummy_controller.ops = &jz_nand_controller_ops; diff --git a/drivers/mtd/nand/raw/jz4780_nand.c b/drivers/mtd/nand/raw/jz4780_nand.c index 89909a17242d..7faf5da6f5ea 100644 --- a/drivers/mtd/nand/raw/jz4780_nand.c +++ b/drivers/mtd/nand/raw/jz4780_nand.c @@ -280,7 +280,7 @@ static int jz4780_nand_init_chip(struct platform_device *pdev, chip->chip_delay = RB_DELAY_US; chip->options = NAND_NO_SUBPAGE_WRITE; chip->select_chip = jz4780_nand_select_chip; - chip->cmd_ctrl = jz4780_nand_cmd_ctrl; + chip->legacy.cmd_ctrl = jz4780_nand_cmd_ctrl; chip->ecc.mode = NAND_ECC_HW; chip->controller = &nfc->controller; nand_set_flash_node(chip, np); diff --git a/drivers/mtd/nand/raw/lpc32xx_mlc.c b/drivers/mtd/nand/raw/lpc32xx_mlc.c index cc1c6e6c59e1..bf3b7aa8a401 100644 --- a/drivers/mtd/nand/raw/lpc32xx_mlc.c +++ b/drivers/mtd/nand/raw/lpc32xx_mlc.c @@ -739,7 +739,7 @@ static int lpc32xx_nand_probe(struct platform_device *pdev) if (res) goto put_clk; - nand_chip->cmd_ctrl = lpc32xx_nand_cmd_ctrl; + nand_chip->legacy.cmd_ctrl = lpc32xx_nand_cmd_ctrl; nand_chip->dev_ready = lpc32xx_nand_device_ready; nand_chip->chip_delay = 25; /* us */ nand_chip->legacy.IO_ADDR_R = MLC_DATA(host->io_base); diff --git a/drivers/mtd/nand/raw/lpc32xx_slc.c b/drivers/mtd/nand/raw/lpc32xx_slc.c index 6dd5348b8f03..1c3f437c42a1 100644 --- a/drivers/mtd/nand/raw/lpc32xx_slc.c +++ b/drivers/mtd/nand/raw/lpc32xx_slc.c @@ -880,7 +880,7 @@ static int lpc32xx_nand_probe(struct platform_device *pdev) /* Set NAND IO addresses and command/ready functions */ chip->legacy.IO_ADDR_R = SLC_DATA(host->io_base); chip->legacy.IO_ADDR_W = SLC_DATA(host->io_base); - chip->cmd_ctrl = lpc32xx_nand_cmd_ctrl; + chip->legacy.cmd_ctrl = lpc32xx_nand_cmd_ctrl; chip->dev_ready = lpc32xx_nand_device_ready; chip->chip_delay = 20; /* 20us command delay time */ diff --git a/drivers/mtd/nand/raw/mpc5121_nfc.c b/drivers/mtd/nand/raw/mpc5121_nfc.c index 4c2925e819f1..1af4c777f887 100644 --- a/drivers/mtd/nand/raw/mpc5121_nfc.c +++ b/drivers/mtd/nand/raw/mpc5121_nfc.c @@ -693,7 +693,7 @@ static int mpc5121_nfc_probe(struct platform_device *op) mtd->name = "MPC5121 NAND"; chip->dev_ready = mpc5121_nfc_dev_ready; - chip->cmdfunc = mpc5121_nfc_command; + chip->legacy.cmdfunc = mpc5121_nfc_command; chip->legacy.read_byte = mpc5121_nfc_read_byte; chip->legacy.read_buf = mpc5121_nfc_read_buf; chip->legacy.write_buf = mpc5121_nfc_write_buf; diff --git a/drivers/mtd/nand/raw/mtk_nand.c b/drivers/mtd/nand/raw/mtk_nand.c index fe150e993acf..0cfdca39a269 100644 --- a/drivers/mtd/nand/raw/mtk_nand.c +++ b/drivers/mtd/nand/raw/mtk_nand.c @@ -1338,7 +1338,7 @@ static int mtk_nfc_nand_chip_init(struct device *dev, struct mtk_nfc *nfc, nand->legacy.write_buf = mtk_nfc_write_buf; nand->legacy.read_byte = mtk_nfc_read_byte; nand->legacy.read_buf = mtk_nfc_read_buf; - nand->cmd_ctrl = mtk_nfc_cmd_ctrl; + nand->legacy.cmd_ctrl = mtk_nfc_cmd_ctrl; nand->setup_data_interface = mtk_nfc_setup_data_interface; /* set default mode in case dt entry is missing */ diff --git a/drivers/mtd/nand/raw/mxc_nand.c b/drivers/mtd/nand/raw/mxc_nand.c index f7e439f578da..146e95153289 100644 --- a/drivers/mtd/nand/raw/mxc_nand.c +++ b/drivers/mtd/nand/raw/mxc_nand.c @@ -1774,7 +1774,7 @@ static int mxcnd_probe(struct platform_device *pdev) nand_set_controller_data(this, host); nand_set_flash_node(this, pdev->dev.of_node), this->dev_ready = mxc_nand_dev_ready; - this->cmdfunc = mxc_nand_command; + this->legacy.cmdfunc = mxc_nand_command; this->legacy.read_byte = mxc_nand_read_byte; this->legacy.write_buf = mxc_nand_write_buf; this->legacy.read_buf = mxc_nand_read_buf; diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c index 016ef405474c..f3d6cd52f7eb 100644 --- a/drivers/mtd/nand/raw/nand_base.c +++ b/drivers/mtd/nand/raw/nand_base.c @@ -286,7 +286,8 @@ static void nand_select_chip(struct nand_chip *chip, int chipnr) { switch (chipnr) { case -1: - chip->cmd_ctrl(chip, NAND_CMD_NONE, 0 | NAND_CTRL_CHANGE); + chip->legacy.cmd_ctrl(chip, NAND_CMD_NONE, + 0 | NAND_CTRL_CHANGE); break; case 0: break; @@ -759,11 +760,11 @@ static void nand_command(struct nand_chip *chip, unsigned int command, column -= 256; readcmd = NAND_CMD_READ1; } - chip->cmd_ctrl(chip, readcmd, ctrl); + chip->legacy.cmd_ctrl(chip, readcmd, ctrl); ctrl &= ~NAND_CTRL_CHANGE; } if (command != NAND_CMD_NONE) - chip->cmd_ctrl(chip, command, ctrl); + chip->legacy.cmd_ctrl(chip, command, ctrl); /* Address cycle, when necessary */ ctrl = NAND_CTRL_ALE | NAND_CTRL_CHANGE; @@ -773,17 +774,18 @@ static void nand_command(struct nand_chip *chip, unsigned int command, if (chip->options & NAND_BUSWIDTH_16 && !nand_opcode_8bits(command)) column >>= 1; - chip->cmd_ctrl(chip, column, ctrl); + chip->legacy.cmd_ctrl(chip, column, ctrl); ctrl &= ~NAND_CTRL_CHANGE; } if (page_addr != -1) { - chip->cmd_ctrl(chip, page_addr, ctrl); + chip->legacy.cmd_ctrl(chip, page_addr, ctrl); ctrl &= ~NAND_CTRL_CHANGE; - chip->cmd_ctrl(chip, page_addr >> 8, ctrl); + chip->legacy.cmd_ctrl(chip, page_addr >> 8, ctrl); if (chip->options & NAND_ROW_ADDR_3) - chip->cmd_ctrl(chip, page_addr >> 16, ctrl); + chip->legacy.cmd_ctrl(chip, page_addr >> 16, ctrl); } - chip->cmd_ctrl(chip, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE); + chip->legacy.cmd_ctrl(chip, NAND_CMD_NONE, + NAND_NCE | NAND_CTRL_CHANGE); /* * Program and erase have their own busy handlers status and sequential @@ -805,10 +807,10 @@ static void nand_command(struct nand_chip *chip, unsigned int command, if (chip->dev_ready) break; udelay(chip->chip_delay); - chip->cmd_ctrl(chip, NAND_CMD_STATUS, - NAND_CTRL_CLE | NAND_CTRL_CHANGE); - chip->cmd_ctrl(chip, - NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE); + chip->legacy.cmd_ctrl(chip, NAND_CMD_STATUS, + NAND_CTRL_CLE | NAND_CTRL_CHANGE); + chip->legacy.cmd_ctrl(chip, NAND_CMD_NONE, + NAND_NCE | NAND_CTRL_CHANGE); /* EZ-NAND can take upto 250ms as per ONFi v4.0 */ nand_wait_status_ready(mtd, 250); return; @@ -886,8 +888,8 @@ static void nand_command_lp(struct nand_chip *chip, unsigned int command, /* Command latch cycle */ if (command != NAND_CMD_NONE) - chip->cmd_ctrl(chip, command, - NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE); + chip->legacy.cmd_ctrl(chip, command, + NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE); if (column != -1 || page_addr != -1) { int ctrl = NAND_CTRL_CHANGE | NAND_NCE | NAND_ALE; @@ -898,23 +900,24 @@ static void nand_command_lp(struct nand_chip *chip, unsigned int command, if (chip->options & NAND_BUSWIDTH_16 && !nand_opcode_8bits(command)) column >>= 1; - chip->cmd_ctrl(chip, column, ctrl); + chip->legacy.cmd_ctrl(chip, column, ctrl); ctrl &= ~NAND_CTRL_CHANGE; /* Only output a single addr cycle for 8bits opcodes. */ if (!nand_opcode_8bits(command)) - chip->cmd_ctrl(chip, column >> 8, ctrl); + chip->legacy.cmd_ctrl(chip, column >> 8, ctrl); } if (page_addr != -1) { - chip->cmd_ctrl(chip, page_addr, ctrl); - chip->cmd_ctrl(chip, page_addr >> 8, - NAND_NCE | NAND_ALE); + chip->legacy.cmd_ctrl(chip, page_addr, ctrl); + chip->legacy.cmd_ctrl(chip, page_addr >> 8, + NAND_NCE | NAND_ALE); if (chip->options & NAND_ROW_ADDR_3) - chip->cmd_ctrl(chip, page_addr >> 16, - NAND_NCE | NAND_ALE); + chip->legacy.cmd_ctrl(chip, page_addr >> 16, + NAND_NCE | NAND_ALE); } } - chip->cmd_ctrl(chip, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE); + chip->legacy.cmd_ctrl(chip, NAND_CMD_NONE, + NAND_NCE | NAND_CTRL_CHANGE); /* * Program and erase have their own busy handlers status, sequential @@ -941,20 +944,20 @@ static void nand_command_lp(struct nand_chip *chip, unsigned int command, if (chip->dev_ready) break; udelay(chip->chip_delay); - chip->cmd_ctrl(chip, NAND_CMD_STATUS, - NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE); - chip->cmd_ctrl(chip, NAND_CMD_NONE, - NAND_NCE | NAND_CTRL_CHANGE); + chip->legacy.cmd_ctrl(chip, NAND_CMD_STATUS, + NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE); + chip->legacy.cmd_ctrl(chip, NAND_CMD_NONE, + NAND_NCE | NAND_CTRL_CHANGE); /* EZ-NAND can take upto 250ms as per ONFi v4.0 */ nand_wait_status_ready(mtd, 250); return; case NAND_CMD_RNDOUT: /* No ready / busy check necessary */ - chip->cmd_ctrl(chip, NAND_CMD_RNDOUTSTART, - NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE); - chip->cmd_ctrl(chip, NAND_CMD_NONE, - NAND_NCE | NAND_CTRL_CHANGE); + chip->legacy.cmd_ctrl(chip, NAND_CMD_RNDOUTSTART, + NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE); + chip->legacy.cmd_ctrl(chip, NAND_CMD_NONE, + NAND_NCE | NAND_CTRL_CHANGE); nand_ccs_delay(chip); return; @@ -969,10 +972,10 @@ static void nand_command_lp(struct nand_chip *chip, unsigned int command, if (column == -1 && page_addr == -1) return; - chip->cmd_ctrl(chip, NAND_CMD_READSTART, - NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE); - chip->cmd_ctrl(chip, NAND_CMD_NONE, - NAND_NCE | NAND_CTRL_CHANGE); + chip->legacy.cmd_ctrl(chip, NAND_CMD_READSTART, + NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE); + chip->legacy.cmd_ctrl(chip, NAND_CMD_NONE, + NAND_NCE | NAND_CTRL_CHANGE); /* This applies to read commands */ default: @@ -1522,7 +1525,7 @@ int nand_read_page_op(struct nand_chip *chip, unsigned int page, buf, len); } - chip->cmdfunc(chip, NAND_CMD_READ0, offset_in_page, page); + chip->legacy.cmdfunc(chip, NAND_CMD_READ0, offset_in_page, page); if (len) chip->legacy.read_buf(chip, buf, len); @@ -1570,7 +1573,7 @@ static int nand_read_param_page_op(struct nand_chip *chip, u8 page, void *buf, return nand_exec_op(chip, &op); } - chip->cmdfunc(chip, NAND_CMD_PARAM, page, -1); + chip->legacy.cmdfunc(chip, NAND_CMD_PARAM, page, -1); for (i = 0; i < len; i++) p[i] = chip->legacy.read_byte(chip); @@ -1633,7 +1636,7 @@ int nand_change_read_column_op(struct nand_chip *chip, return nand_exec_op(chip, &op); } - chip->cmdfunc(chip, NAND_CMD_RNDOUT, offset_in_page, -1); + chip->legacy.cmdfunc(chip, NAND_CMD_RNDOUT, offset_in_page, -1); if (len) chip->legacy.read_buf(chip, buf, len); @@ -1670,7 +1673,7 @@ int nand_read_oob_op(struct nand_chip *chip, unsigned int page, mtd->writesize + offset_in_oob, buf, len); - chip->cmdfunc(chip, NAND_CMD_READOOB, offset_in_oob, page); + chip->legacy.cmdfunc(chip, NAND_CMD_READOOB, offset_in_oob, page); if (len) chip->legacy.read_buf(chip, buf, len); @@ -1782,7 +1785,7 @@ int nand_prog_page_begin_op(struct nand_chip *chip, unsigned int page, return nand_exec_prog_page_op(chip, page, offset_in_page, buf, len, false); - chip->cmdfunc(chip, NAND_CMD_SEQIN, offset_in_page, page); + chip->legacy.cmdfunc(chip, NAND_CMD_SEQIN, offset_in_page, page); if (buf) chip->legacy.write_buf(chip, buf, len); @@ -1823,7 +1826,7 @@ int nand_prog_page_end_op(struct nand_chip *chip) if (ret) return ret; } else { - chip->cmdfunc(chip, NAND_CMD_PAGEPROG, -1, -1); + chip->legacy.cmdfunc(chip, NAND_CMD_PAGEPROG, -1, -1); ret = chip->waitfunc(chip); if (ret < 0) return ret; @@ -1868,9 +1871,10 @@ int nand_prog_page_op(struct nand_chip *chip, unsigned int page, status = nand_exec_prog_page_op(chip, page, offset_in_page, buf, len, true); } else { - chip->cmdfunc(chip, NAND_CMD_SEQIN, offset_in_page, page); + chip->legacy.cmdfunc(chip, NAND_CMD_SEQIN, offset_in_page, + page); chip->legacy.write_buf(chip, buf, len); - chip->cmdfunc(chip, NAND_CMD_PAGEPROG, -1, -1); + chip->legacy.cmdfunc(chip, NAND_CMD_PAGEPROG, -1, -1); status = chip->waitfunc(chip); } @@ -1936,7 +1940,7 @@ int nand_change_write_column_op(struct nand_chip *chip, return nand_exec_op(chip, &op); } - chip->cmdfunc(chip, NAND_CMD_RNDIN, offset_in_page, -1); + chip->legacy.cmdfunc(chip, NAND_CMD_RNDIN, offset_in_page, -1); if (len) chip->legacy.write_buf(chip, buf, len); @@ -1983,7 +1987,7 @@ int nand_readid_op(struct nand_chip *chip, u8 addr, void *buf, return nand_exec_op(chip, &op); } - chip->cmdfunc(chip, NAND_CMD_READID, addr, -1); + chip->legacy.cmdfunc(chip, NAND_CMD_READID, addr, -1); for (i = 0; i < len; i++) id[i] = chip->legacy.read_byte(chip); @@ -2021,7 +2025,7 @@ int nand_status_op(struct nand_chip *chip, u8 *status) return nand_exec_op(chip, &op); } - chip->cmdfunc(chip, NAND_CMD_STATUS, -1, -1); + chip->legacy.cmdfunc(chip, NAND_CMD_STATUS, -1, -1); if (status) *status = chip->legacy.read_byte(chip); @@ -2051,7 +2055,7 @@ int nand_exit_status_op(struct nand_chip *chip) return nand_exec_op(chip, &op); } - chip->cmdfunc(chip, NAND_CMD_READ0, -1, -1); + chip->legacy.cmdfunc(chip, NAND_CMD_READ0, -1, -1); return 0; } @@ -2099,8 +2103,8 @@ int nand_erase_op(struct nand_chip *chip, unsigned int eraseblock) if (ret) return ret; } else { - chip->cmdfunc(chip, NAND_CMD_ERASE1, -1, page); - chip->cmdfunc(chip, NAND_CMD_ERASE2, -1, -1); + chip->legacy.cmdfunc(chip, NAND_CMD_ERASE1, -1, page); + chip->legacy.cmdfunc(chip, NAND_CMD_ERASE2, -1, -1); ret = chip->waitfunc(chip); if (ret < 0) @@ -2149,7 +2153,7 @@ static int nand_set_features_op(struct nand_chip *chip, u8 feature, return nand_exec_op(chip, &op); } - chip->cmdfunc(chip, NAND_CMD_SET_FEATURES, feature, -1); + chip->legacy.cmdfunc(chip, NAND_CMD_SET_FEATURES, feature, -1); for (i = 0; i < ONFI_SUBFEATURE_PARAM_LEN; ++i) chip->legacy.write_byte(chip, params[i]); @@ -2197,7 +2201,7 @@ static int nand_get_features_op(struct nand_chip *chip, u8 feature, return nand_exec_op(chip, &op); } - chip->cmdfunc(chip, NAND_CMD_GET_FEATURES, feature, -1); + chip->legacy.cmdfunc(chip, NAND_CMD_GET_FEATURES, feature, -1); for (i = 0; i < ONFI_SUBFEATURE_PARAM_LEN; ++i) params[i] = chip->legacy.read_byte(chip); @@ -2250,7 +2254,7 @@ int nand_reset_op(struct nand_chip *chip) return nand_exec_op(chip, &op); } - chip->cmdfunc(chip, NAND_CMD_RESET, -1, -1); + chip->legacy.cmdfunc(chip, NAND_CMD_RESET, -1, -1); return 0; } @@ -4919,8 +4923,8 @@ static void nand_set_defaults(struct nand_chip *chip) chip->chip_delay = 20; /* check, if a user supplied command function given */ - if (!chip->cmdfunc && !chip->exec_op) - chip->cmdfunc = nand_command; + if (!chip->legacy.cmdfunc && !chip->exec_op) + chip->legacy.cmdfunc = nand_command; /* check, if a user supplied wait function given */ if (chip->waitfunc == NULL) @@ -5213,11 +5217,13 @@ static int nand_flash_detect_onfi(struct nand_chip *chip) /* * The nand_flash_detect_ext_param_page() uses the * Change Read Column command which maybe not supported - * by the chip->cmdfunc. So try to update the chip->cmdfunc - * now. We do not replace user supplied command function. + * by the chip->legacy.cmdfunc. So try to update the + * chip->legacy.cmdfunc now. We do not replace user supplied + * command function. */ - if (mtd->writesize > 512 && chip->cmdfunc == nand_command) - chip->cmdfunc = nand_command_lp; + if (mtd->writesize > 512 && + chip->legacy.cmdfunc == nand_command) + chip->legacy.cmdfunc = nand_command_lp; /* The Extended Parameter Page is supported since ONFI 2.1. */ if (nand_flash_detect_ext_param_page(chip, p)) @@ -5736,8 +5742,8 @@ static int nand_detect(struct nand_chip *chip, struct nand_flash_dev *type) chip->erase = single_erase; /* Do not replace user supplied command function! */ - if (mtd->writesize > 512 && chip->cmdfunc == nand_command) - chip->cmdfunc = nand_command_lp; + if (mtd->writesize > 512 && chip->legacy.cmdfunc == nand_command) + chip->legacy.cmdfunc = nand_command_lp; pr_info("device found, Manufacturer ID: 0x%02x, Chip ID: 0x%02x\n", maf_id, dev_id); @@ -5934,16 +5940,18 @@ static int nand_scan_ident(struct nand_chip *chip, unsigned int maxchips, mtd->name = dev_name(mtd->dev.parent); /* - * ->cmdfunc() is legacy and will only be used if ->exec_op() is not - * populated. + * ->legacy.cmdfunc() is legacy and will only be used if ->exec_op() is + * not populated. */ if (!chip->exec_op) { /* - * Default functions assigned for ->cmdfunc() and - * ->select_chip() both expect ->cmd_ctrl() to be populated. + * Default functions assigned for ->legacy.cmdfunc() and + * ->select_chip() both expect ->legacy.cmd_ctrl() to be + * populated. */ - if ((!chip->cmdfunc || !chip->select_chip) && !chip->cmd_ctrl) { - pr_err("->cmd_ctrl() should be provided\n"); + if ((!chip->legacy.cmdfunc || !chip->select_chip) && + !chip->legacy.cmd_ctrl) { + pr_err("->legacy.cmd_ctrl() should be provided\n"); return -EINVAL; } } diff --git a/drivers/mtd/nand/raw/nand_hynix.c b/drivers/mtd/nand/raw/nand_hynix.c index 6a2f3efad153..7eec0d96909a 100644 --- a/drivers/mtd/nand/raw/nand_hynix.c +++ b/drivers/mtd/nand/raw/nand_hynix.c @@ -88,7 +88,7 @@ static int hynix_nand_cmd_op(struct nand_chip *chip, u8 cmd) return nand_exec_op(chip, &op); } - chip->cmdfunc(chip, cmd, -1, -1); + chip->legacy.cmdfunc(chip, cmd, -1, -1); return 0; } @@ -107,7 +107,7 @@ static int hynix_nand_reg_write_op(struct nand_chip *chip, u8 addr, u8 val) return nand_exec_op(chip, &op); } - chip->cmdfunc(chip, NAND_CMD_NONE, column, -1); + chip->legacy.cmdfunc(chip, NAND_CMD_NONE, column, -1); chip->legacy.write_byte(chip, val); return 0; diff --git a/drivers/mtd/nand/raw/nandsim.c b/drivers/mtd/nand/raw/nandsim.c index f3219122e311..360c3a7c69d7 100644 --- a/drivers/mtd/nand/raw/nandsim.c +++ b/drivers/mtd/nand/raw/nandsim.c @@ -2249,7 +2249,7 @@ static int __init ns_init_module(void) /* * Register simulator's callbacks. */ - chip->cmd_ctrl = ns_hwcontrol; + chip->legacy.cmd_ctrl = ns_hwcontrol; chip->legacy.read_byte = ns_nand_read_byte; chip->dev_ready = ns_device_ready; chip->legacy.write_buf = ns_nand_write_buf; diff --git a/drivers/mtd/nand/raw/ndfc.c b/drivers/mtd/nand/raw/ndfc.c index 7377dc752431..4e58b64ac690 100644 --- a/drivers/mtd/nand/raw/ndfc.c +++ b/drivers/mtd/nand/raw/ndfc.c @@ -144,7 +144,7 @@ static int ndfc_chip_init(struct ndfc_controller *ndfc, chip->legacy.IO_ADDR_R = ndfc->ndfcbase + NDFC_DATA; chip->legacy.IO_ADDR_W = ndfc->ndfcbase + NDFC_DATA; - chip->cmd_ctrl = ndfc_hwcontrol; + chip->legacy.cmd_ctrl = ndfc_hwcontrol; chip->dev_ready = ndfc_ready; chip->select_chip = ndfc_select_chip; chip->chip_delay = 50; diff --git a/drivers/mtd/nand/raw/nuc900_nand.c b/drivers/mtd/nand/raw/nuc900_nand.c index 71b0a41bc497..32946dc5c4b8 100644 --- a/drivers/mtd/nand/raw/nuc900_nand.c +++ b/drivers/mtd/nand/raw/nuc900_nand.c @@ -254,7 +254,7 @@ static int nuc900_nand_probe(struct platform_device *pdev) return -ENOENT; clk_enable(nuc900_nand->clk); - chip->cmdfunc = nuc900_nand_command_lp; + chip->legacy.cmdfunc = nuc900_nand_command_lp; chip->dev_ready = nuc900_nand_devready; chip->legacy.read_byte = nuc900_nand_read_byte; chip->legacy.write_buf = nuc900_nand_write_buf; diff --git a/drivers/mtd/nand/raw/omap2.c b/drivers/mtd/nand/raw/omap2.c index 3ab4a2c5fc2d..af427a72c7ca 100644 --- a/drivers/mtd/nand/raw/omap2.c +++ b/drivers/mtd/nand/raw/omap2.c @@ -2230,7 +2230,7 @@ static int omap_nand_probe(struct platform_device *pdev) nand_chip->controller = &omap_gpmc_controller; nand_chip->legacy.IO_ADDR_W = nand_chip->legacy.IO_ADDR_R; - nand_chip->cmd_ctrl = omap_hwcontrol; + nand_chip->legacy.cmd_ctrl = omap_hwcontrol; info->ready_gpiod = devm_gpiod_get_optional(&pdev->dev, "rb", GPIOD_IN); diff --git a/drivers/mtd/nand/raw/orion_nand.c b/drivers/mtd/nand/raw/orion_nand.c index f0d0054b4a7a..bf288c3c930b 100644 --- a/drivers/mtd/nand/raw/orion_nand.c +++ b/drivers/mtd/nand/raw/orion_nand.c @@ -137,7 +137,7 @@ static int __init orion_nand_probe(struct platform_device *pdev) nand_set_controller_data(nc, board); nand_set_flash_node(nc, pdev->dev.of_node); nc->legacy.IO_ADDR_R = nc->legacy.IO_ADDR_W = io_base; - nc->cmd_ctrl = orion_nand_cmd_ctrl; + nc->legacy.cmd_ctrl = orion_nand_cmd_ctrl; nc->legacy.read_buf = orion_nand_read_buf; nc->ecc.mode = NAND_ECC_SOFT; nc->ecc.algo = NAND_ECC_HAMMING; diff --git a/drivers/mtd/nand/raw/oxnas_nand.c b/drivers/mtd/nand/raw/oxnas_nand.c index 16df274f4cd6..fb0ebb296f6c 100644 --- a/drivers/mtd/nand/raw/oxnas_nand.c +++ b/drivers/mtd/nand/raw/oxnas_nand.c @@ -132,7 +132,7 @@ static int oxnas_nand_probe(struct platform_device *pdev) mtd->dev.parent = &pdev->dev; mtd->priv = chip; - chip->cmd_ctrl = oxnas_nand_cmd_ctrl; + chip->legacy.cmd_ctrl = oxnas_nand_cmd_ctrl; chip->legacy.read_buf = oxnas_nand_read_buf; chip->legacy.read_byte = oxnas_nand_read_byte; chip->legacy.write_buf = oxnas_nand_write_buf; diff --git a/drivers/mtd/nand/raw/pasemi_nand.c b/drivers/mtd/nand/raw/pasemi_nand.c index ca158dabe8b9..d99d7b63e545 100644 --- a/drivers/mtd/nand/raw/pasemi_nand.c +++ b/drivers/mtd/nand/raw/pasemi_nand.c @@ -139,7 +139,7 @@ static int pasemi_nand_probe(struct platform_device *ofdev) goto out_ior; } - chip->cmd_ctrl = pasemi_hwcontrol; + chip->legacy.cmd_ctrl = pasemi_hwcontrol; chip->dev_ready = pasemi_device_ready; chip->legacy.read_buf = pasemi_read_buf; chip->legacy.write_buf = pasemi_write_buf; diff --git a/drivers/mtd/nand/raw/plat_nand.c b/drivers/mtd/nand/raw/plat_nand.c index 971e387a8a75..c66c7f942179 100644 --- a/drivers/mtd/nand/raw/plat_nand.c +++ b/drivers/mtd/nand/raw/plat_nand.c @@ -62,7 +62,7 @@ static int plat_nand_probe(struct platform_device *pdev) data->chip.legacy.IO_ADDR_R = data->io_base; data->chip.legacy.IO_ADDR_W = data->io_base; - data->chip.cmd_ctrl = pdata->ctrl.cmd_ctrl; + data->chip.legacy.cmd_ctrl = pdata->ctrl.cmd_ctrl; data->chip.dev_ready = pdata->ctrl.dev_ready; data->chip.select_chip = pdata->ctrl.select_chip; data->chip.legacy.write_buf = pdata->ctrl.write_buf; diff --git a/drivers/mtd/nand/raw/qcom_nandc.c b/drivers/mtd/nand/raw/qcom_nandc.c index 7b487a2ffa8e..bd187139416f 100644 --- a/drivers/mtd/nand/raw/qcom_nandc.c +++ b/drivers/mtd/nand/raw/qcom_nandc.c @@ -1155,8 +1155,8 @@ static void config_nand_cw_write(struct qcom_nand_controller *nandc) } /* - * the following functions are used within chip->cmdfunc() to perform different - * NAND_CMD_* commands + * the following functions are used within chip->legacy.cmdfunc() to + * perform different NAND_CMD_* commands */ /* sets up descriptors for NAND_CMD_PARAM */ @@ -1436,10 +1436,10 @@ static void post_command(struct qcom_nand_host *host, int command) } /* - * Implements chip->cmdfunc. It's only used for a limited set of commands. - * The rest of the commands wouldn't be called by upper layers. For example, - * NAND_CMD_READOOB would never be called because we have our own versions - * of read_oob ops for nand_ecc_ctrl. + * Implements chip->legacy.cmdfunc. It's only used for a limited set of + * commands. The rest of the commands wouldn't be called by upper layers. + * For example, NAND_CMD_READOOB would never be called because we have our own + * versions of read_oob ops for nand_ecc_ctrl. */ static void qcom_nandc_command(struct nand_chip *chip, unsigned int command, int column, int page_addr) @@ -2803,7 +2803,7 @@ static int qcom_nand_host_init_and_register(struct qcom_nand_controller *nandc, mtd->owner = THIS_MODULE; mtd->dev.parent = dev; - chip->cmdfunc = qcom_nandc_command; + chip->legacy.cmdfunc = qcom_nandc_command; chip->select_chip = qcom_nandc_select_chip; chip->legacy.read_byte = qcom_nandc_read_byte; chip->legacy.read_buf = qcom_nandc_read_buf; diff --git a/drivers/mtd/nand/raw/r852.c b/drivers/mtd/nand/raw/r852.c index 05b669d34cec..6e602586cb14 100644 --- a/drivers/mtd/nand/raw/r852.c +++ b/drivers/mtd/nand/raw/r852.c @@ -853,7 +853,7 @@ static int r852_probe(struct pci_dev *pci_dev, const struct pci_device_id *id) goto error4; /* commands */ - chip->cmd_ctrl = r852_cmdctl; + chip->legacy.cmd_ctrl = r852_cmdctl; chip->waitfunc = r852_wait; chip->dev_ready = r852_ready; diff --git a/drivers/mtd/nand/raw/s3c2410.c b/drivers/mtd/nand/raw/s3c2410.c index d0670ebd5b68..f232d683f32d 100644 --- a/drivers/mtd/nand/raw/s3c2410.c +++ b/drivers/mtd/nand/raw/s3c2410.c @@ -884,7 +884,7 @@ static void s3c2410_nand_init_chip(struct s3c2410_nand_info *info, chip->legacy.IO_ADDR_W = regs + S3C2410_NFDATA; info->sel_reg = regs + S3C2410_NFCONF; info->sel_bit = S3C2410_NFCONF_nFCE; - chip->cmd_ctrl = s3c2410_nand_hwcontrol; + chip->legacy.cmd_ctrl = s3c2410_nand_hwcontrol; chip->dev_ready = s3c2410_nand_devready; break; @@ -892,7 +892,7 @@ static void s3c2410_nand_init_chip(struct s3c2410_nand_info *info, chip->legacy.IO_ADDR_W = regs + S3C2440_NFDATA; info->sel_reg = regs + S3C2440_NFCONT; info->sel_bit = S3C2440_NFCONT_nFCE; - chip->cmd_ctrl = s3c2440_nand_hwcontrol; + chip->legacy.cmd_ctrl = s3c2440_nand_hwcontrol; chip->dev_ready = s3c2440_nand_devready; chip->legacy.read_buf = s3c2440_nand_read_buf; chip->legacy.write_buf = s3c2440_nand_write_buf; @@ -902,7 +902,7 @@ static void s3c2410_nand_init_chip(struct s3c2410_nand_info *info, chip->legacy.IO_ADDR_W = regs + S3C2440_NFDATA; info->sel_reg = regs + S3C2440_NFCONT; info->sel_bit = S3C2412_NFCONT_nFCE0; - chip->cmd_ctrl = s3c2440_nand_hwcontrol; + chip->legacy.cmd_ctrl = s3c2440_nand_hwcontrol; chip->dev_ready = s3c2412_nand_devready; if (readl(regs + S3C2410_NFCONF) & S3C2412_NFCONF_NANDBOOT) diff --git a/drivers/mtd/nand/raw/sh_flctl.c b/drivers/mtd/nand/raw/sh_flctl.c index d83d53810590..71658fbd99a3 100644 --- a/drivers/mtd/nand/raw/sh_flctl.c +++ b/drivers/mtd/nand/raw/sh_flctl.c @@ -1184,7 +1184,7 @@ static int flctl_probe(struct platform_device *pdev) nand->legacy.write_buf = flctl_write_buf; nand->legacy.read_buf = flctl_read_buf; nand->select_chip = flctl_select_chip; - nand->cmdfunc = flctl_cmdfunc; + nand->legacy.cmdfunc = flctl_cmdfunc; nand->set_features = nand_get_set_features_notsupp; nand->get_features = nand_get_set_features_notsupp; diff --git a/drivers/mtd/nand/raw/sharpsl.c b/drivers/mtd/nand/raw/sharpsl.c index d9cdd11fbd3a..a626fb7af8d1 100644 --- a/drivers/mtd/nand/raw/sharpsl.c +++ b/drivers/mtd/nand/raw/sharpsl.c @@ -156,7 +156,7 @@ static int sharpsl_nand_probe(struct platform_device *pdev) this->legacy.IO_ADDR_R = sharpsl->io + FLASHIO; this->legacy.IO_ADDR_W = sharpsl->io + FLASHIO; /* Set address of hardware control function */ - this->cmd_ctrl = sharpsl_nand_hwcontrol; + this->legacy.cmd_ctrl = sharpsl_nand_hwcontrol; this->dev_ready = sharpsl_nand_dev_ready; /* 15 us command delay time */ this->chip_delay = 15; diff --git a/drivers/mtd/nand/raw/socrates_nand.c b/drivers/mtd/nand/raw/socrates_nand.c index 006224a40f3b..0ca81fa956b9 100644 --- a/drivers/mtd/nand/raw/socrates_nand.c +++ b/drivers/mtd/nand/raw/socrates_nand.c @@ -152,7 +152,7 @@ static int socrates_nand_probe(struct platform_device *ofdev) mtd->name = "socrates_nand"; mtd->dev.parent = &ofdev->dev; - nand_chip->cmd_ctrl = socrates_nand_cmd_ctrl; + nand_chip->legacy.cmd_ctrl = socrates_nand_cmd_ctrl; nand_chip->legacy.read_byte = socrates_nand_read_byte; nand_chip->legacy.write_buf = socrates_nand_write_buf; nand_chip->legacy.read_buf = socrates_nand_read_buf; diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c index 6e1317bde1b3..48bb28872298 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -1923,7 +1923,7 @@ static int sunxi_nand_chip_init(struct device *dev, struct sunxi_nfc *nfc, nand->ecc.mode = NAND_ECC_HW; nand_set_flash_node(nand, np); nand->select_chip = sunxi_nfc_select_chip; - nand->cmd_ctrl = sunxi_nfc_cmd_ctrl; + nand->legacy.cmd_ctrl = sunxi_nfc_cmd_ctrl; nand->legacy.read_buf = sunxi_nfc_read_buf; nand->legacy.write_buf = sunxi_nfc_write_buf; nand->legacy.read_byte = sunxi_nfc_read_byte; diff --git a/drivers/mtd/nand/raw/tango_nand.c b/drivers/mtd/nand/raw/tango_nand.c index 379f2ed284cb..f0285c0b3089 100644 --- a/drivers/mtd/nand/raw/tango_nand.c +++ b/drivers/mtd/nand/raw/tango_nand.c @@ -568,7 +568,7 @@ static int chip_init(struct device *dev, struct device_node *np) chip->legacy.write_buf = tango_write_buf; chip->legacy.read_buf = tango_read_buf; chip->select_chip = tango_select_chip; - chip->cmd_ctrl = tango_cmd_ctrl; + chip->legacy.cmd_ctrl = tango_cmd_ctrl; chip->dev_ready = tango_dev_ready; chip->setup_data_interface = tango_set_timings; chip->options = NAND_USE_BOUNCE_BUFFER | diff --git a/drivers/mtd/nand/raw/tmio_nand.c b/drivers/mtd/nand/raw/tmio_nand.c index 94e659158f16..5037359754eb 100644 --- a/drivers/mtd/nand/raw/tmio_nand.c +++ b/drivers/mtd/nand/raw/tmio_nand.c @@ -403,7 +403,7 @@ static int tmio_probe(struct platform_device *dev) nand_chip->legacy.IO_ADDR_W = tmio->fcr; /* Set address of hardware control function */ - nand_chip->cmd_ctrl = tmio_nand_hwcontrol; + nand_chip->legacy.cmd_ctrl = tmio_nand_hwcontrol; nand_chip->dev_ready = tmio_nand_dev_ready; nand_chip->legacy.read_byte = tmio_nand_read_byte; nand_chip->legacy.write_buf = tmio_nand_write_buf; diff --git a/drivers/mtd/nand/raw/txx9ndfmc.c b/drivers/mtd/nand/raw/txx9ndfmc.c index 7fb1575c6e2b..9eab56a45a5e 100644 --- a/drivers/mtd/nand/raw/txx9ndfmc.c +++ b/drivers/mtd/nand/raw/txx9ndfmc.c @@ -327,7 +327,7 @@ static int __init txx9ndfmc_probe(struct platform_device *dev) chip->legacy.read_byte = txx9ndfmc_read_byte; chip->legacy.read_buf = txx9ndfmc_read_buf; chip->legacy.write_buf = txx9ndfmc_write_buf; - chip->cmd_ctrl = txx9ndfmc_cmd_ctrl; + chip->legacy.cmd_ctrl = txx9ndfmc_cmd_ctrl; chip->dev_ready = txx9ndfmc_dev_ready; chip->ecc.calculate = txx9ndfmc_calculate_ecc; chip->ecc.correct = txx9ndfmc_correct_data; diff --git a/drivers/mtd/nand/raw/xway_nand.c b/drivers/mtd/nand/raw/xway_nand.c index 87ec034bdd3e..ef351a4c507f 100644 --- a/drivers/mtd/nand/raw/xway_nand.c +++ b/drivers/mtd/nand/raw/xway_nand.c @@ -174,7 +174,7 @@ static int xway_nand_probe(struct platform_device *pdev) mtd = nand_to_mtd(&data->chip); mtd->dev.parent = &pdev->dev; - data->chip.cmd_ctrl = xway_cmd_ctrl; + data->chip.legacy.cmd_ctrl = xway_cmd_ctrl; data->chip.dev_ready = xway_dev_ready; data->chip.select_chip = xway_select_chip; data->chip.legacy.write_buf = xway_write_buf; diff --git a/drivers/staging/mt29f_spinand/mt29f_spinand.c b/drivers/staging/mt29f_spinand/mt29f_spinand.c index 4856593b626e..fbfa024f683d 100644 --- a/drivers/staging/mt29f_spinand/mt29f_spinand.c +++ b/drivers/staging/mt29f_spinand/mt29f_spinand.c @@ -918,7 +918,7 @@ static int spinand_probe(struct spi_device *spi_nand) chip->legacy.read_buf = spinand_read_buf; chip->legacy.write_buf = spinand_write_buf; chip->legacy.read_byte = spinand_read_byte; - chip->cmdfunc = spinand_cmdfunc; + chip->legacy.cmdfunc = spinand_cmdfunc; chip->waitfunc = spinand_wait; chip->options |= NAND_CACHEPRG; chip->select_chip = spinand_select_chip; diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h index f961efd2eacc..5ef2004a37a2 100644 --- a/include/linux/mtd/rawnand.h +++ b/include/linux/mtd/rawnand.h @@ -199,10 +199,10 @@ enum nand_ecc_algo { #define NAND_USE_BOUNCE_BUFFER 0x00100000 /* - * In case your controller is implementing ->cmd_ctrl() and is relying on the - * default ->cmdfunc() implementation, you may want to let the core handle the - * tCCS delay which is required when a column change (RNDIN or RNDOUT) is - * requested. + * In case your controller is implementing ->legacy.cmd_ctrl() and is relying + * on the default ->cmdfunc() implementation, you may want to let the core + * handle the tCCS delay which is required when a column change (RNDIN or + * RNDOUT) is requested. * If your controller already takes care of this delay, you don't need to set * this flag. */ @@ -1180,6 +1180,9 @@ int nand_op_parser_exec_op(struct nand_chip *chip, * @write_byte: write a single byte to the chip on the low 8 I/O lines * @write_buf: write data from the buffer to the chip * @read_buf: read data from the chip into the buffer + * @cmd_ctrl: hardware specific function for controlling ALE/CLE/nCE. Also used + * to write command and address + * @cmdfunc: hardware specific function for writing commands to the chip. * * If you look at this structure you're already wrong. These fields/hooks are * all deprecated. @@ -1191,6 +1194,9 @@ struct nand_legacy { void (*write_byte)(struct nand_chip *chip, u8 byte); void (*write_buf)(struct nand_chip *chip, const u8 *buf, int len); void (*read_buf)(struct nand_chip *chip, u8 *buf, int len); + void (*cmd_ctrl)(struct nand_chip *chip, int dat, unsigned int ctrl); + void (*cmdfunc)(struct nand_chip *chip, unsigned command, int column, + int page_addr); }; /** @@ -1204,14 +1210,10 @@ struct nand_legacy { * @select_chip: [REPLACEABLE] select chip nr * @block_bad: [REPLACEABLE] check if a block is bad, using OOB markers * @block_markbad: [REPLACEABLE] mark a block bad - * @cmd_ctrl: [BOARDSPECIFIC] hardwarespecific function for controlling - * ALE/CLE/nCE. Also used to write command and address * @dev_ready: [BOARDSPECIFIC] hardwarespecific function for accessing * device ready/busy line. If set to NULL no access to * ready/busy is available and the ready/busy information * is read from the chip status register. - * @cmdfunc: [REPLACEABLE] hardwarespecific function for writing - * commands to the chip. * @waitfunc: [REPLACEABLE] hardwarespecific function for wait on * ready. * @exec_op: controller specific method to execute NAND operations. @@ -1303,10 +1305,7 @@ struct nand_chip { void (*select_chip)(struct nand_chip *chip, int cs); int (*block_bad)(struct nand_chip *chip, loff_t ofs); int (*block_markbad)(struct nand_chip *chip, loff_t ofs); - void (*cmd_ctrl)(struct nand_chip *chip, int dat, unsigned int ctrl); int (*dev_ready)(struct nand_chip *chip); - void (*cmdfunc)(struct nand_chip *chip, unsigned command, int column, - int page_addr); int (*waitfunc)(struct nand_chip *chip); int (*exec_op)(struct nand_chip *chip, const struct nand_operation *op, From 8395b753d7cad2beb03d374621cc8851f1cb4e01 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Fri, 7 Sep 2018 00:38:37 +0200 Subject: [PATCH 274/302] mtd: rawnand: Deprecate ->dev_ready() and ->waitfunc() Those hooks have been replaced by ->exec_op(). Move them to the nand_legacy struct. Signed-off-by: Boris Brezillon Signed-off-by: Miquel Raynal --- Documentation/driver-api/mtdnand.rst | 4 +-- drivers/mtd/nand/raw/ams-delta.c | 4 +-- drivers/mtd/nand/raw/atmel/nand-controller.c | 8 ++--- drivers/mtd/nand/raw/au1550nd.c | 7 ++-- .../mtd/nand/raw/bcm47xxnflash/ops_bcm4706.c | 2 +- drivers/mtd/nand/raw/brcmnand/brcmnand.c | 2 +- drivers/mtd/nand/raw/cafe_nand.c | 2 +- drivers/mtd/nand/raw/cmx270_nand.c | 2 +- drivers/mtd/nand/raw/cs553x_nand.c | 2 +- drivers/mtd/nand/raw/davinci_nand.c | 2 +- drivers/mtd/nand/raw/denali.c | 7 ++-- drivers/mtd/nand/raw/diskonchip.c | 10 +++--- drivers/mtd/nand/raw/fsl_elbc_nand.c | 2 +- drivers/mtd/nand/raw/fsl_ifc_nand.c | 2 +- drivers/mtd/nand/raw/fsl_upm.c | 2 +- drivers/mtd/nand/raw/gpio.c | 2 +- drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c | 2 +- drivers/mtd/nand/raw/jz4740_nand.c | 2 +- drivers/mtd/nand/raw/jz4780_nand.c | 2 +- drivers/mtd/nand/raw/lpc32xx_mlc.c | 4 +-- drivers/mtd/nand/raw/lpc32xx_slc.c | 2 +- drivers/mtd/nand/raw/mpc5121_nfc.c | 2 +- drivers/mtd/nand/raw/mtk_nand.c | 2 +- drivers/mtd/nand/raw/mxc_nand.c | 2 +- drivers/mtd/nand/raw/nand_base.c | 36 +++++++++---------- drivers/mtd/nand/raw/nandsim.c | 2 +- drivers/mtd/nand/raw/ndfc.c | 2 +- drivers/mtd/nand/raw/nuc900_nand.c | 8 ++--- drivers/mtd/nand/raw/omap2.c | 4 +-- drivers/mtd/nand/raw/pasemi_nand.c | 2 +- drivers/mtd/nand/raw/plat_nand.c | 2 +- drivers/mtd/nand/raw/r852.c | 6 ++-- drivers/mtd/nand/raw/s3c2410.c | 6 ++-- drivers/mtd/nand/raw/sharpsl.c | 2 +- drivers/mtd/nand/raw/socrates_nand.c | 2 +- drivers/mtd/nand/raw/sunxi_nand.c | 4 +-- drivers/mtd/nand/raw/tango_nand.c | 4 +-- drivers/mtd/nand/raw/tmio_nand.c | 4 +-- drivers/mtd/nand/raw/txx9ndfmc.c | 2 +- drivers/mtd/nand/raw/xway_nand.c | 2 +- drivers/staging/mt29f_spinand/mt29f_spinand.c | 2 +- include/linux/mtd/rawnand.h | 18 +++++----- 42 files changed, 93 insertions(+), 93 deletions(-) diff --git a/Documentation/driver-api/mtdnand.rst b/Documentation/driver-api/mtdnand.rst index 1d2403f1d8c5..0d3fa4d6576d 100644 --- a/Documentation/driver-api/mtdnand.rst +++ b/Documentation/driver-api/mtdnand.rst @@ -197,7 +197,7 @@ to read back the state of the pin. The function has no arguments and should return 0, if the device is busy (R/B pin is low) and 1, if the device is ready (R/B pin is high). If the hardware interface does not give access to the ready busy pin, then the function must not be defined -and the function pointer this->dev_ready is set to NULL. +and the function pointer this->legacy.dev_ready is set to NULL. Init function ------------- @@ -242,7 +242,7 @@ necessary information about the device. /* Set command delay time, see datasheet for correct value */ this->chip_delay = CHIP_DEPENDEND_COMMAND_DELAY; /* Assign the device ready function, if available */ - this->dev_ready = board_dev_ready; + this->legacy.dev_ready = board_dev_ready; this->eccmode = NAND_ECC_SOFT; /* Scan to find existence of the device */ diff --git a/drivers/mtd/nand/raw/ams-delta.c b/drivers/mtd/nand/raw/ams-delta.c index 756f6339d457..2fa6fa3c7464 100644 --- a/drivers/mtd/nand/raw/ams-delta.c +++ b/drivers/mtd/nand/raw/ams-delta.c @@ -215,9 +215,9 @@ static int ams_delta_init(struct platform_device *pdev) this->legacy.read_buf = ams_delta_read_buf; this->legacy.cmd_ctrl = ams_delta_hwcontrol; if (gpio_request(AMS_DELTA_GPIO_PIN_NAND_RB, "nand_rdy") == 0) { - this->dev_ready = ams_delta_nand_ready; + this->legacy.dev_ready = ams_delta_nand_ready; } else { - this->dev_ready = NULL; + this->legacy.dev_ready = NULL; pr_notice("Couldn't request gpio for Delta NAND ready.\n"); } /* 25 us command delay time */ diff --git a/drivers/mtd/nand/raw/atmel/nand-controller.c b/drivers/mtd/nand/raw/atmel/nand-controller.c index 37f617ec178e..dd022080442d 100644 --- a/drivers/mtd/nand/raw/atmel/nand-controller.c +++ b/drivers/mtd/nand/raw/atmel/nand-controller.c @@ -488,14 +488,14 @@ static void atmel_nand_select_chip(struct nand_chip *chip, int cs) if (cs < 0 || cs >= nand->numcs) { nand->activecs = NULL; - chip->dev_ready = NULL; + chip->legacy.dev_ready = NULL; return; } nand->activecs = &nand->cs[cs]; if (nand->activecs->rb.type == ATMEL_NAND_GPIO_RB) - chip->dev_ready = atmel_nand_dev_ready; + chip->legacy.dev_ready = atmel_nand_dev_ready; } static int atmel_hsmc_nand_dev_ready(struct nand_chip *chip) @@ -528,7 +528,7 @@ static void atmel_hsmc_nand_select_chip(struct nand_chip *chip, int cs) } if (nand->activecs->rb.type == ATMEL_NAND_NATIVE_RB) - chip->dev_ready = atmel_hsmc_nand_dev_ready; + chip->legacy.dev_ready = atmel_hsmc_nand_dev_ready; regmap_update_bits(nc->base.smc, ATMEL_HSMC_NFC_CFG, ATMEL_HSMC_NFC_CFG_PAGESIZE_MASK | @@ -945,7 +945,7 @@ static int atmel_hsmc_nand_pmecc_write_pg(struct nand_chip *chip, dev_err(nc->base.dev, "Failed to program NAND page (err = %d)\n", ret); - status = chip->waitfunc(chip); + status = chip->legacy.waitfunc(chip); if (status & NAND_STATUS_FAIL) return -EIO; diff --git a/drivers/mtd/nand/raw/au1550nd.c b/drivers/mtd/nand/raw/au1550nd.c index 5d45f13288fc..81bba469c0e4 100644 --- a/drivers/mtd/nand/raw/au1550nd.c +++ b/drivers/mtd/nand/raw/au1550nd.c @@ -342,7 +342,8 @@ static void au1550_command(struct nand_chip *this, unsigned command, /* Apply a short delay always to ensure that we do wait tWB. */ ndelay(100); /* Wait for a chip to become ready... */ - for (i = this->chip_delay; !this->dev_ready(this) && i > 0; --i) + for (i = this->chip_delay; + !this->legacy.dev_ready(this) && i > 0; --i) udelay(1); /* Release -CE and re-enable interrupts. */ @@ -353,7 +354,7 @@ static void au1550_command(struct nand_chip *this, unsigned command, /* Apply this short delay always to ensure that we do wait tWB. */ ndelay(100); - while(!this->dev_ready(this)); + while(!this->legacy.dev_ready(this)); } static int find_nand_cs(unsigned long nand_base) @@ -428,7 +429,7 @@ static int au1550nd_probe(struct platform_device *pdev) } ctx->cs = cs; - this->dev_ready = au1550_device_ready; + this->legacy.dev_ready = au1550_device_ready; this->select_chip = au1550_select_chip; this->legacy.cmdfunc = au1550_command; diff --git a/drivers/mtd/nand/raw/bcm47xxnflash/ops_bcm4706.c b/drivers/mtd/nand/raw/bcm47xxnflash/ops_bcm4706.c index 2bd389b49b4a..925d4cd4401e 100644 --- a/drivers/mtd/nand/raw/bcm47xxnflash/ops_bcm4706.c +++ b/drivers/mtd/nand/raw/bcm47xxnflash/ops_bcm4706.c @@ -385,7 +385,7 @@ int bcm47xxnflash_ops_bcm4706_init(struct bcm47xxnflash *b47n) b47n->nand_chip.select_chip = bcm47xxnflash_ops_bcm4706_select_chip; nand_chip->legacy.cmd_ctrl = bcm47xxnflash_ops_bcm4706_cmd_ctrl; - nand_chip->dev_ready = bcm47xxnflash_ops_bcm4706_dev_ready; + nand_chip->legacy.dev_ready = bcm47xxnflash_ops_bcm4706_dev_ready; b47n->nand_chip.legacy.cmdfunc = bcm47xxnflash_ops_bcm4706_cmdfunc; b47n->nand_chip.legacy.read_byte = bcm47xxnflash_ops_bcm4706_read_byte; b47n->nand_chip.legacy.read_buf = bcm47xxnflash_ops_bcm4706_read_buf; diff --git a/drivers/mtd/nand/raw/brcmnand/brcmnand.c b/drivers/mtd/nand/raw/brcmnand/brcmnand.c index 162ec11ab251..482c6f093f99 100644 --- a/drivers/mtd/nand/raw/brcmnand/brcmnand.c +++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c @@ -2272,7 +2272,7 @@ static int brcmnand_init_cs(struct brcmnand_host *host, struct device_node *dn) chip->legacy.cmd_ctrl = brcmnand_cmd_ctrl; chip->legacy.cmdfunc = brcmnand_cmdfunc; - chip->waitfunc = brcmnand_waitfunc; + chip->legacy.waitfunc = brcmnand_waitfunc; chip->legacy.read_byte = brcmnand_read_byte; chip->legacy.read_buf = brcmnand_read_buf; chip->legacy.write_buf = brcmnand_write_buf; diff --git a/drivers/mtd/nand/raw/cafe_nand.c b/drivers/mtd/nand/raw/cafe_nand.c index 0f734442fd3d..738af0f0a48d 100644 --- a/drivers/mtd/nand/raw/cafe_nand.c +++ b/drivers/mtd/nand/raw/cafe_nand.c @@ -704,7 +704,7 @@ static int cafe_nand_probe(struct pci_dev *pdev, } cafe->nand.legacy.cmdfunc = cafe_nand_cmdfunc; - cafe->nand.dev_ready = cafe_device_ready; + cafe->nand.legacy.dev_ready = cafe_device_ready; cafe->nand.legacy.read_byte = cafe_read_byte; cafe->nand.legacy.read_buf = cafe_read_buf; cafe->nand.legacy.write_buf = cafe_write_buf; diff --git a/drivers/mtd/nand/raw/cmx270_nand.c b/drivers/mtd/nand/raw/cmx270_nand.c index c543f073d971..585dbd51d8b1 100644 --- a/drivers/mtd/nand/raw/cmx270_nand.c +++ b/drivers/mtd/nand/raw/cmx270_nand.c @@ -176,7 +176,7 @@ static int __init cmx270_init(void) this->legacy.IO_ADDR_R = cmx270_nand_io; this->legacy.IO_ADDR_W = cmx270_nand_io; this->legacy.cmd_ctrl = cmx270_hwcontrol; - this->dev_ready = cmx270_device_ready; + this->legacy.dev_ready = cmx270_device_ready; /* 15 us command delay time */ this->chip_delay = 20; diff --git a/drivers/mtd/nand/raw/cs553x_nand.c b/drivers/mtd/nand/raw/cs553x_nand.c index bd75ec4e5508..61ae9e60bf0d 100644 --- a/drivers/mtd/nand/raw/cs553x_nand.c +++ b/drivers/mtd/nand/raw/cs553x_nand.c @@ -207,7 +207,7 @@ static int __init cs553x_init_one(int cs, int mmio, unsigned long adr) } this->legacy.cmd_ctrl = cs553x_hwcontrol; - this->dev_ready = cs553x_device_ready; + this->legacy.dev_ready = cs553x_device_ready; this->legacy.read_byte = cs553x_read_byte; this->legacy.read_buf = cs553x_read_buf; this->legacy.write_buf = cs553x_write_buf; diff --git a/drivers/mtd/nand/raw/davinci_nand.c b/drivers/mtd/nand/raw/davinci_nand.c index 5fcd8c30293a..bae568d68432 100644 --- a/drivers/mtd/nand/raw/davinci_nand.c +++ b/drivers/mtd/nand/raw/davinci_nand.c @@ -782,7 +782,7 @@ static int nand_davinci_probe(struct platform_device *pdev) /* Set address of hardware control function */ info->chip.legacy.cmd_ctrl = nand_davinci_hwcontrol; - info->chip.dev_ready = nand_davinci_dev_ready; + info->chip.legacy.dev_ready = nand_davinci_dev_ready; /* Speed up buffer I/O */ info->chip.legacy.read_buf = nand_davinci_read_buf; diff --git a/drivers/mtd/nand/raw/denali.c b/drivers/mtd/nand/raw/denali.c index c11547bfb2e7..c14493ef6126 100644 --- a/drivers/mtd/nand/raw/denali.c +++ b/drivers/mtd/nand/raw/denali.c @@ -287,7 +287,8 @@ static void denali_cmd_ctrl(struct nand_chip *chip, int dat, unsigned int ctrl) return; /* - * Some commands are followed by chip->dev_ready or chip->waitfunc. + * Some commands are followed by chip->legacy.dev_ready or + * chip->legacy.waitfunc. * irq_status must be cleared here to catch the R/B# interrupt later. */ if (ctrl & NAND_CTRL_CHANGE) @@ -1346,8 +1347,8 @@ int denali_init(struct denali_nand_info *denali) chip->legacy.read_byte = denali_read_byte; chip->legacy.write_byte = denali_write_byte; chip->legacy.cmd_ctrl = denali_cmd_ctrl; - chip->dev_ready = denali_dev_ready; - chip->waitfunc = denali_waitfunc; + chip->legacy.dev_ready = denali_dev_ready; + chip->legacy.waitfunc = denali_waitfunc; if (features & FEATURES__INDEX_ADDR) { denali->host_read = denali_indexed_read; diff --git a/drivers/mtd/nand/raw/diskonchip.c b/drivers/mtd/nand/raw/diskonchip.c index 2604e80b5475..c3a79369fbed 100644 --- a/drivers/mtd/nand/raw/diskonchip.c +++ b/drivers/mtd/nand/raw/diskonchip.c @@ -715,7 +715,7 @@ static void doc2001plus_command(struct nand_chip *this, unsigned command, return; case NAND_CMD_RESET: - if (this->dev_ready) + if (this->legacy.dev_ready) break; udelay(this->chip_delay); WriteDOC(NAND_CMD_STATUS, docptr, Mplus_FlashCmd); @@ -730,7 +730,7 @@ static void doc2001plus_command(struct nand_chip *this, unsigned command, * If we don't have access to the busy pin, we apply the given * command delay */ - if (!this->dev_ready) { + if (!this->legacy.dev_ready) { udelay(this->chip_delay); return; } @@ -740,7 +740,7 @@ static void doc2001plus_command(struct nand_chip *this, unsigned command, * any case on any machine. */ ndelay(100); /* wait until command is processed */ - while (!this->dev_ready(this)) ; + while (!this->legacy.dev_ready(this)) ; } static int doc200x_dev_ready(struct nand_chip *this) @@ -1570,8 +1570,8 @@ static int __init doc_probe(unsigned long physadr) nand_set_controller_data(nand, doc); nand->select_chip = doc200x_select_chip; nand->legacy.cmd_ctrl = doc200x_hwcontrol; - nand->dev_ready = doc200x_dev_ready; - nand->waitfunc = doc200x_wait; + nand->legacy.dev_ready = doc200x_dev_ready; + nand->legacy.waitfunc = doc200x_wait; nand->block_bad = doc200x_block_bad; nand->ecc.hwctl = doc200x_enable_hwecc; nand->ecc.calculate = doc200x_calculate_ecc; diff --git a/drivers/mtd/nand/raw/fsl_elbc_nand.c b/drivers/mtd/nand/raw/fsl_elbc_nand.c index fa21d00c3443..29f0832de39b 100644 --- a/drivers/mtd/nand/raw/fsl_elbc_nand.c +++ b/drivers/mtd/nand/raw/fsl_elbc_nand.c @@ -781,7 +781,7 @@ static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv) chip->legacy.read_buf = fsl_elbc_read_buf; chip->select_chip = fsl_elbc_select_chip; chip->legacy.cmdfunc = fsl_elbc_cmdfunc; - chip->waitfunc = fsl_elbc_wait; + chip->legacy.waitfunc = fsl_elbc_wait; chip->set_features = nand_get_set_features_notsupp; chip->get_features = nand_get_set_features_notsupp; diff --git a/drivers/mtd/nand/raw/fsl_ifc_nand.c b/drivers/mtd/nand/raw/fsl_ifc_nand.c index 20c86b6503a8..682ae383c3e9 100644 --- a/drivers/mtd/nand/raw/fsl_ifc_nand.c +++ b/drivers/mtd/nand/raw/fsl_ifc_nand.c @@ -866,7 +866,7 @@ static int fsl_ifc_chip_init(struct fsl_ifc_mtd *priv) chip->legacy.read_buf = fsl_ifc_read_buf; chip->select_chip = fsl_ifc_select_chip; chip->legacy.cmdfunc = fsl_ifc_cmdfunc; - chip->waitfunc = fsl_ifc_wait; + chip->legacy.waitfunc = fsl_ifc_wait; chip->set_features = nand_get_set_features_notsupp; chip->get_features = nand_get_set_features_notsupp; diff --git a/drivers/mtd/nand/raw/fsl_upm.c b/drivers/mtd/nand/raw/fsl_upm.c index 23baef375bfb..fcb79718b6c3 100644 --- a/drivers/mtd/nand/raw/fsl_upm.c +++ b/drivers/mtd/nand/raw/fsl_upm.c @@ -173,7 +173,7 @@ static int fun_chip_init(struct fsl_upm_nand *fun, fun->chip.select_chip = fun_select_chip; if (fun->rnb_gpio[0] >= 0) - fun->chip.dev_ready = fun_chip_ready; + fun->chip.legacy.dev_ready = fun_chip_ready; mtd->dev.parent = fun->dev; diff --git a/drivers/mtd/nand/raw/gpio.c b/drivers/mtd/nand/raw/gpio.c index 1e6e81047978..c4f19067702e 100644 --- a/drivers/mtd/nand/raw/gpio.c +++ b/drivers/mtd/nand/raw/gpio.c @@ -271,7 +271,7 @@ static int gpio_nand_probe(struct platform_device *pdev) } /* Using RDY pin */ if (gpiomtd->rdy) - chip->dev_ready = gpio_nand_devready; + chip->legacy.dev_ready = gpio_nand_devready; nand_set_flash_node(chip, pdev->dev.of_node); chip->legacy.IO_ADDR_W = chip->legacy.IO_ADDR_R; diff --git a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c index fa37d21e5f16..dc6291902acf 100644 --- a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c +++ b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c @@ -1903,7 +1903,7 @@ static int gpmi_nand_init(struct gpmi_nand_data *this) chip->select_chip = gpmi_select_chip; chip->setup_data_interface = gpmi_setup_data_interface; chip->legacy.cmd_ctrl = gpmi_cmd_ctrl; - chip->dev_ready = gpmi_dev_ready; + chip->legacy.dev_ready = gpmi_dev_ready; chip->legacy.read_byte = gpmi_read_byte; chip->legacy.read_buf = gpmi_read_buf; chip->legacy.write_buf = gpmi_write_buf; diff --git a/drivers/mtd/nand/raw/jz4740_nand.c b/drivers/mtd/nand/raw/jz4740_nand.c index ae0c268a5cb6..7a1b4c3ff6fd 100644 --- a/drivers/mtd/nand/raw/jz4740_nand.c +++ b/drivers/mtd/nand/raw/jz4740_nand.c @@ -431,7 +431,7 @@ static int jz_nand_probe(struct platform_device *pdev) chip->dummy_controller.ops = &jz_nand_controller_ops; if (nand->busy_gpio) - chip->dev_ready = jz_nand_dev_ready; + chip->legacy.dev_ready = jz_nand_dev_ready; platform_set_drvdata(pdev, nand); diff --git a/drivers/mtd/nand/raw/jz4780_nand.c b/drivers/mtd/nand/raw/jz4780_nand.c index 7faf5da6f5ea..2a960211b97d 100644 --- a/drivers/mtd/nand/raw/jz4780_nand.c +++ b/drivers/mtd/nand/raw/jz4780_nand.c @@ -256,7 +256,7 @@ static int jz4780_nand_init_chip(struct platform_device *pdev, dev_err(dev, "failed to request busy GPIO: %d\n", ret); return ret; } else if (nand->busy_gpio) { - nand->chip.dev_ready = jz4780_nand_dev_ready; + nand->chip.legacy.dev_ready = jz4780_nand_dev_ready; } nand->wp_gpio = devm_gpiod_get_optional(dev, "wp", GPIOD_OUT_LOW); diff --git a/drivers/mtd/nand/raw/lpc32xx_mlc.c b/drivers/mtd/nand/raw/lpc32xx_mlc.c index bf3b7aa8a401..8a1dfb7ee885 100644 --- a/drivers/mtd/nand/raw/lpc32xx_mlc.c +++ b/drivers/mtd/nand/raw/lpc32xx_mlc.c @@ -740,7 +740,7 @@ static int lpc32xx_nand_probe(struct platform_device *pdev) goto put_clk; nand_chip->legacy.cmd_ctrl = lpc32xx_nand_cmd_ctrl; - nand_chip->dev_ready = lpc32xx_nand_device_ready; + nand_chip->legacy.dev_ready = lpc32xx_nand_device_ready; nand_chip->chip_delay = 25; /* us */ nand_chip->legacy.IO_ADDR_R = MLC_DATA(host->io_base); nand_chip->legacy.IO_ADDR_W = MLC_DATA(host->io_base); @@ -760,7 +760,7 @@ static int lpc32xx_nand_probe(struct platform_device *pdev) nand_chip->ecc.read_oob = lpc32xx_read_oob; nand_chip->ecc.strength = 4; nand_chip->ecc.bytes = 10; - nand_chip->waitfunc = lpc32xx_waitfunc; + nand_chip->legacy.waitfunc = lpc32xx_waitfunc; nand_chip->options = NAND_NO_SUBPAGE_WRITE; nand_chip->bbt_options = NAND_BBT_USE_FLASH | NAND_BBT_NO_OOB; diff --git a/drivers/mtd/nand/raw/lpc32xx_slc.c b/drivers/mtd/nand/raw/lpc32xx_slc.c index 1c3f437c42a1..75d62d6bed7b 100644 --- a/drivers/mtd/nand/raw/lpc32xx_slc.c +++ b/drivers/mtd/nand/raw/lpc32xx_slc.c @@ -881,7 +881,7 @@ static int lpc32xx_nand_probe(struct platform_device *pdev) chip->legacy.IO_ADDR_R = SLC_DATA(host->io_base); chip->legacy.IO_ADDR_W = SLC_DATA(host->io_base); chip->legacy.cmd_ctrl = lpc32xx_nand_cmd_ctrl; - chip->dev_ready = lpc32xx_nand_device_ready; + chip->legacy.dev_ready = lpc32xx_nand_device_ready; chip->chip_delay = 20; /* 20us command delay time */ /* Init NAND controller */ diff --git a/drivers/mtd/nand/raw/mpc5121_nfc.c b/drivers/mtd/nand/raw/mpc5121_nfc.c index 1af4c777f887..9a6dc783689e 100644 --- a/drivers/mtd/nand/raw/mpc5121_nfc.c +++ b/drivers/mtd/nand/raw/mpc5121_nfc.c @@ -692,7 +692,7 @@ static int mpc5121_nfc_probe(struct platform_device *op) } mtd->name = "MPC5121 NAND"; - chip->dev_ready = mpc5121_nfc_dev_ready; + chip->legacy.dev_ready = mpc5121_nfc_dev_ready; chip->legacy.cmdfunc = mpc5121_nfc_command; chip->legacy.read_byte = mpc5121_nfc_read_byte; chip->legacy.read_buf = mpc5121_nfc_read_buf; diff --git a/drivers/mtd/nand/raw/mtk_nand.c b/drivers/mtd/nand/raw/mtk_nand.c index 0cfdca39a269..2bb0df1b7244 100644 --- a/drivers/mtd/nand/raw/mtk_nand.c +++ b/drivers/mtd/nand/raw/mtk_nand.c @@ -1332,7 +1332,7 @@ static int mtk_nfc_nand_chip_init(struct device *dev, struct mtk_nfc *nfc, nand_set_controller_data(nand, nfc); nand->options |= NAND_USE_BOUNCE_BUFFER | NAND_SUBPAGE_READ; - nand->dev_ready = mtk_nfc_dev_ready; + nand->legacy.dev_ready = mtk_nfc_dev_ready; nand->select_chip = mtk_nfc_select_chip; nand->legacy.write_byte = mtk_nfc_write_byte; nand->legacy.write_buf = mtk_nfc_write_buf; diff --git a/drivers/mtd/nand/raw/mxc_nand.c b/drivers/mtd/nand/raw/mxc_nand.c index 146e95153289..ca074c955147 100644 --- a/drivers/mtd/nand/raw/mxc_nand.c +++ b/drivers/mtd/nand/raw/mxc_nand.c @@ -1773,7 +1773,7 @@ static int mxcnd_probe(struct platform_device *pdev) nand_set_controller_data(this, host); nand_set_flash_node(this, pdev->dev.of_node), - this->dev_ready = mxc_nand_dev_ready; + this->legacy.dev_ready = mxc_nand_dev_ready; this->legacy.cmdfunc = mxc_nand_command; this->legacy.read_byte = mxc_nand_read_byte; this->legacy.write_buf = mxc_nand_write_buf; diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c index f3d6cd52f7eb..30b55a4677f9 100644 --- a/drivers/mtd/nand/raw/nand_base.c +++ b/drivers/mtd/nand/raw/nand_base.c @@ -604,7 +604,7 @@ static void panic_nand_wait_ready(struct mtd_info *mtd, unsigned long timeo) /* Wait for the device to get ready */ for (i = 0; i < timeo; i++) { - if (chip->dev_ready(chip)) + if (chip->legacy.dev_ready(chip)) break; touch_softlockup_watchdog(); mdelay(1); @@ -628,12 +628,12 @@ void nand_wait_ready(struct nand_chip *chip) /* Wait until command is processed or timeout occurs */ timeo = jiffies + msecs_to_jiffies(timeo); do { - if (chip->dev_ready(chip)) + if (chip->legacy.dev_ready(chip)) return; cond_resched(); } while (time_before(jiffies, timeo)); - if (!chip->dev_ready(chip)) + if (!chip->legacy.dev_ready(chip)) pr_warn_ratelimited("timeout while waiting for chip to become ready\n"); } EXPORT_SYMBOL_GPL(nand_wait_ready); @@ -804,7 +804,7 @@ static void nand_command(struct nand_chip *chip, unsigned int command, return; case NAND_CMD_RESET: - if (chip->dev_ready) + if (chip->legacy.dev_ready) break; udelay(chip->chip_delay); chip->legacy.cmd_ctrl(chip, NAND_CMD_STATUS, @@ -831,7 +831,7 @@ static void nand_command(struct nand_chip *chip, unsigned int command, * If we don't have access to the busy pin, we apply the given * command delay */ - if (!chip->dev_ready) { + if (!chip->legacy.dev_ready) { udelay(chip->chip_delay); return; } @@ -941,7 +941,7 @@ static void nand_command_lp(struct nand_chip *chip, unsigned int command, return; case NAND_CMD_RESET: - if (chip->dev_ready) + if (chip->legacy.dev_ready) break; udelay(chip->chip_delay); chip->legacy.cmd_ctrl(chip, NAND_CMD_STATUS, @@ -983,7 +983,7 @@ static void nand_command_lp(struct nand_chip *chip, unsigned int command, * If we don't have access to the busy pin, we apply the given * command delay. */ - if (!chip->dev_ready) { + if (!chip->legacy.dev_ready) { udelay(chip->chip_delay); return; } @@ -1069,8 +1069,8 @@ static void panic_nand_wait(struct nand_chip *chip, unsigned long timeo) { int i; for (i = 0; i < timeo; i++) { - if (chip->dev_ready) { - if (chip->dev_ready(chip)) + if (chip->legacy.dev_ready) { + if (chip->legacy.dev_ready(chip)) break; } else { int ret; @@ -1117,8 +1117,8 @@ static int nand_wait(struct nand_chip *chip) else { timeo = jiffies + msecs_to_jiffies(timeo); do { - if (chip->dev_ready) { - if (chip->dev_ready(chip)) + if (chip->legacy.dev_ready) { + if (chip->legacy.dev_ready(chip)) break; } else { ret = nand_read_data_op(chip, &status, @@ -1827,7 +1827,7 @@ int nand_prog_page_end_op(struct nand_chip *chip) return ret; } else { chip->legacy.cmdfunc(chip, NAND_CMD_PAGEPROG, -1, -1); - ret = chip->waitfunc(chip); + ret = chip->legacy.waitfunc(chip); if (ret < 0) return ret; @@ -1875,7 +1875,7 @@ int nand_prog_page_op(struct nand_chip *chip, unsigned int page, page); chip->legacy.write_buf(chip, buf, len); chip->legacy.cmdfunc(chip, NAND_CMD_PAGEPROG, -1, -1); - status = chip->waitfunc(chip); + status = chip->legacy.waitfunc(chip); } if (status & NAND_STATUS_FAIL) @@ -2106,7 +2106,7 @@ int nand_erase_op(struct nand_chip *chip, unsigned int eraseblock) chip->legacy.cmdfunc(chip, NAND_CMD_ERASE1, -1, page); chip->legacy.cmdfunc(chip, NAND_CMD_ERASE2, -1, -1); - ret = chip->waitfunc(chip); + ret = chip->legacy.waitfunc(chip); if (ret < 0) return ret; @@ -2157,7 +2157,7 @@ static int nand_set_features_op(struct nand_chip *chip, u8 feature, for (i = 0; i < ONFI_SUBFEATURE_PARAM_LEN; ++i) chip->legacy.write_byte(chip, params[i]); - ret = chip->waitfunc(chip); + ret = chip->legacy.waitfunc(chip); if (ret < 0) return ret; @@ -2222,7 +2222,7 @@ static int nand_wait_rdy_op(struct nand_chip *chip, unsigned int timeout_ms, } /* Apply delay or wait for ready/busy pin */ - if (!chip->dev_ready) + if (!chip->legacy.dev_ready) udelay(chip->chip_delay); else nand_wait_ready(chip); @@ -4927,8 +4927,8 @@ static void nand_set_defaults(struct nand_chip *chip) chip->legacy.cmdfunc = nand_command; /* check, if a user supplied wait function given */ - if (chip->waitfunc == NULL) - chip->waitfunc = nand_wait; + if (chip->legacy.waitfunc == NULL) + chip->legacy.waitfunc = nand_wait; if (!chip->select_chip) chip->select_chip = nand_select_chip; diff --git a/drivers/mtd/nand/raw/nandsim.c b/drivers/mtd/nand/raw/nandsim.c index 360c3a7c69d7..ff0c372ee288 100644 --- a/drivers/mtd/nand/raw/nandsim.c +++ b/drivers/mtd/nand/raw/nandsim.c @@ -2251,7 +2251,7 @@ static int __init ns_init_module(void) */ chip->legacy.cmd_ctrl = ns_hwcontrol; chip->legacy.read_byte = ns_nand_read_byte; - chip->dev_ready = ns_device_ready; + chip->legacy.dev_ready = ns_device_ready; chip->legacy.write_buf = ns_nand_write_buf; chip->legacy.read_buf = ns_nand_read_buf; chip->ecc.mode = NAND_ECC_SOFT; diff --git a/drivers/mtd/nand/raw/ndfc.c b/drivers/mtd/nand/raw/ndfc.c index 4e58b64ac690..19b4cb2d1c6e 100644 --- a/drivers/mtd/nand/raw/ndfc.c +++ b/drivers/mtd/nand/raw/ndfc.c @@ -145,7 +145,7 @@ static int ndfc_chip_init(struct ndfc_controller *ndfc, chip->legacy.IO_ADDR_R = ndfc->ndfcbase + NDFC_DATA; chip->legacy.IO_ADDR_W = ndfc->ndfcbase + NDFC_DATA; chip->legacy.cmd_ctrl = ndfc_hwcontrol; - chip->dev_ready = ndfc_ready; + chip->legacy.dev_ready = ndfc_ready; chip->select_chip = ndfc_select_chip; chip->chip_delay = 50; chip->controller = &ndfc->ndfc_control; diff --git a/drivers/mtd/nand/raw/nuc900_nand.c b/drivers/mtd/nand/raw/nuc900_nand.c index 32946dc5c4b8..208b6de67510 100644 --- a/drivers/mtd/nand/raw/nuc900_nand.c +++ b/drivers/mtd/nand/raw/nuc900_nand.c @@ -175,7 +175,7 @@ static void nuc900_nand_command_lp(struct nand_chip *chip, return; case NAND_CMD_RESET: - if (chip->dev_ready) + if (chip->legacy.dev_ready) break; udelay(chip->chip_delay); @@ -196,7 +196,7 @@ static void nuc900_nand_command_lp(struct nand_chip *chip, write_cmd_reg(nand, NAND_CMD_READSTART); default: - if (!chip->dev_ready) { + if (!chip->legacy.dev_ready) { udelay(chip->chip_delay); return; } @@ -206,7 +206,7 @@ static void nuc900_nand_command_lp(struct nand_chip *chip, * any case on any machine. */ ndelay(100); - while (!chip->dev_ready(chip)) + while (!chip->legacy.dev_ready(chip)) ; } @@ -255,7 +255,7 @@ static int nuc900_nand_probe(struct platform_device *pdev) clk_enable(nuc900_nand->clk); chip->legacy.cmdfunc = nuc900_nand_command_lp; - chip->dev_ready = nuc900_nand_devready; + chip->legacy.dev_ready = nuc900_nand_devready; chip->legacy.read_byte = nuc900_nand_read_byte; chip->legacy.write_buf = nuc900_nand_write_buf; chip->legacy.read_buf = nuc900_nand_read_buf; diff --git a/drivers/mtd/nand/raw/omap2.c b/drivers/mtd/nand/raw/omap2.c index af427a72c7ca..5e1e7ced0d9e 100644 --- a/drivers/mtd/nand/raw/omap2.c +++ b/drivers/mtd/nand/raw/omap2.c @@ -2247,10 +2247,10 @@ static int omap_nand_probe(struct platform_device *pdev) * device and read status register until you get a failure or success */ if (info->ready_gpiod) { - nand_chip->dev_ready = omap_dev_ready; + nand_chip->legacy.dev_ready = omap_dev_ready; nand_chip->chip_delay = 0; } else { - nand_chip->waitfunc = omap_wait; + nand_chip->legacy.waitfunc = omap_wait; nand_chip->chip_delay = 50; } diff --git a/drivers/mtd/nand/raw/pasemi_nand.c b/drivers/mtd/nand/raw/pasemi_nand.c index d99d7b63e545..e9a4e82bfb34 100644 --- a/drivers/mtd/nand/raw/pasemi_nand.c +++ b/drivers/mtd/nand/raw/pasemi_nand.c @@ -140,7 +140,7 @@ static int pasemi_nand_probe(struct platform_device *ofdev) } chip->legacy.cmd_ctrl = pasemi_hwcontrol; - chip->dev_ready = pasemi_device_ready; + chip->legacy.dev_ready = pasemi_device_ready; chip->legacy.read_buf = pasemi_read_buf; chip->legacy.write_buf = pasemi_write_buf; chip->chip_delay = 0; diff --git a/drivers/mtd/nand/raw/plat_nand.c b/drivers/mtd/nand/raw/plat_nand.c index c66c7f942179..6cce01d09364 100644 --- a/drivers/mtd/nand/raw/plat_nand.c +++ b/drivers/mtd/nand/raw/plat_nand.c @@ -63,7 +63,7 @@ static int plat_nand_probe(struct platform_device *pdev) data->chip.legacy.IO_ADDR_R = data->io_base; data->chip.legacy.IO_ADDR_W = data->io_base; data->chip.legacy.cmd_ctrl = pdata->ctrl.cmd_ctrl; - data->chip.dev_ready = pdata->ctrl.dev_ready; + data->chip.legacy.dev_ready = pdata->ctrl.dev_ready; data->chip.select_chip = pdata->ctrl.select_chip; data->chip.legacy.write_buf = pdata->ctrl.write_buf; data->chip.legacy.read_buf = pdata->ctrl.read_buf; diff --git a/drivers/mtd/nand/raw/r852.c b/drivers/mtd/nand/raw/r852.c index 6e602586cb14..b08aa0a5a074 100644 --- a/drivers/mtd/nand/raw/r852.c +++ b/drivers/mtd/nand/raw/r852.c @@ -373,7 +373,7 @@ static int r852_wait(struct nand_chip *chip) msecs_to_jiffies(400) : msecs_to_jiffies(20)); while (time_before(jiffies, timeout)) - if (chip->dev_ready(chip)) + if (chip->legacy.dev_ready(chip)) break; nand_status_op(chip, &status); @@ -854,8 +854,8 @@ static int r852_probe(struct pci_dev *pci_dev, const struct pci_device_id *id) /* commands */ chip->legacy.cmd_ctrl = r852_cmdctl; - chip->waitfunc = r852_wait; - chip->dev_ready = r852_ready; + chip->legacy.waitfunc = r852_wait; + chip->legacy.dev_ready = r852_ready; /* I/O */ chip->legacy.read_byte = r852_read_byte; diff --git a/drivers/mtd/nand/raw/s3c2410.c b/drivers/mtd/nand/raw/s3c2410.c index f232d683f32d..87b5162857f8 100644 --- a/drivers/mtd/nand/raw/s3c2410.c +++ b/drivers/mtd/nand/raw/s3c2410.c @@ -885,7 +885,7 @@ static void s3c2410_nand_init_chip(struct s3c2410_nand_info *info, info->sel_reg = regs + S3C2410_NFCONF; info->sel_bit = S3C2410_NFCONF_nFCE; chip->legacy.cmd_ctrl = s3c2410_nand_hwcontrol; - chip->dev_ready = s3c2410_nand_devready; + chip->legacy.dev_ready = s3c2410_nand_devready; break; case TYPE_S3C2440: @@ -893,7 +893,7 @@ static void s3c2410_nand_init_chip(struct s3c2410_nand_info *info, info->sel_reg = regs + S3C2440_NFCONT; info->sel_bit = S3C2440_NFCONT_nFCE; chip->legacy.cmd_ctrl = s3c2440_nand_hwcontrol; - chip->dev_ready = s3c2440_nand_devready; + chip->legacy.dev_ready = s3c2440_nand_devready; chip->legacy.read_buf = s3c2440_nand_read_buf; chip->legacy.write_buf = s3c2440_nand_write_buf; break; @@ -903,7 +903,7 @@ static void s3c2410_nand_init_chip(struct s3c2410_nand_info *info, info->sel_reg = regs + S3C2440_NFCONT; info->sel_bit = S3C2412_NFCONT_nFCE0; chip->legacy.cmd_ctrl = s3c2440_nand_hwcontrol; - chip->dev_ready = s3c2412_nand_devready; + chip->legacy.dev_ready = s3c2412_nand_devready; if (readl(regs + S3C2410_NFCONF) & S3C2412_NFCONF_NANDBOOT) dev_info(info->device, "System booted from NAND\n"); diff --git a/drivers/mtd/nand/raw/sharpsl.c b/drivers/mtd/nand/raw/sharpsl.c index a626fb7af8d1..3d14408cbbce 100644 --- a/drivers/mtd/nand/raw/sharpsl.c +++ b/drivers/mtd/nand/raw/sharpsl.c @@ -157,7 +157,7 @@ static int sharpsl_nand_probe(struct platform_device *pdev) this->legacy.IO_ADDR_W = sharpsl->io + FLASHIO; /* Set address of hardware control function */ this->legacy.cmd_ctrl = sharpsl_nand_hwcontrol; - this->dev_ready = sharpsl_nand_dev_ready; + this->legacy.dev_ready = sharpsl_nand_dev_ready; /* 15 us command delay time */ this->chip_delay = 15; /* set eccmode using hardware ECC */ diff --git a/drivers/mtd/nand/raw/socrates_nand.c b/drivers/mtd/nand/raw/socrates_nand.c index 0ca81fa956b9..604ef7508f14 100644 --- a/drivers/mtd/nand/raw/socrates_nand.c +++ b/drivers/mtd/nand/raw/socrates_nand.c @@ -156,7 +156,7 @@ static int socrates_nand_probe(struct platform_device *ofdev) nand_chip->legacy.read_byte = socrates_nand_read_byte; nand_chip->legacy.write_buf = socrates_nand_write_buf; nand_chip->legacy.read_buf = socrates_nand_read_buf; - nand_chip->dev_ready = socrates_nand_device_ready; + nand_chip->legacy.dev_ready = socrates_nand_device_ready; nand_chip->ecc.mode = NAND_ECC_SOFT; /* enable ECC */ nand_chip->ecc.algo = NAND_ECC_HAMMING; diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c index 48bb28872298..37e23aec4bce 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -442,9 +442,9 @@ static void sunxi_nfc_select_chip(struct nand_chip *nand, int chip) ctl |= NFC_CE_SEL(sel->cs) | NFC_EN | NFC_PAGE_SHIFT(nand->page_shift); if (sel->rb < 0) { - nand->dev_ready = NULL; + nand->legacy.dev_ready = NULL; } else { - nand->dev_ready = sunxi_nfc_dev_ready; + nand->legacy.dev_ready = sunxi_nfc_dev_ready; ctl |= NFC_RB_SEL(sel->rb); } diff --git a/drivers/mtd/nand/raw/tango_nand.c b/drivers/mtd/nand/raw/tango_nand.c index f0285c0b3089..8818f893f300 100644 --- a/drivers/mtd/nand/raw/tango_nand.c +++ b/drivers/mtd/nand/raw/tango_nand.c @@ -314,7 +314,7 @@ static int tango_write_page(struct nand_chip *chip, const u8 *buf, if (err) return err; - status = chip->waitfunc(chip); + status = chip->legacy.waitfunc(chip); if (status & NAND_STATUS_FAIL) return -EIO; @@ -569,7 +569,7 @@ static int chip_init(struct device *dev, struct device_node *np) chip->legacy.read_buf = tango_read_buf; chip->select_chip = tango_select_chip; chip->legacy.cmd_ctrl = tango_cmd_ctrl; - chip->dev_ready = tango_dev_ready; + chip->legacy.dev_ready = tango_dev_ready; chip->setup_data_interface = tango_set_timings; chip->options = NAND_USE_BOUNCE_BUFFER | NAND_NO_SUBPAGE_WRITE | diff --git a/drivers/mtd/nand/raw/tmio_nand.c b/drivers/mtd/nand/raw/tmio_nand.c index 5037359754eb..7e49272ecef6 100644 --- a/drivers/mtd/nand/raw/tmio_nand.c +++ b/drivers/mtd/nand/raw/tmio_nand.c @@ -404,7 +404,7 @@ static int tmio_probe(struct platform_device *dev) /* Set address of hardware control function */ nand_chip->legacy.cmd_ctrl = tmio_nand_hwcontrol; - nand_chip->dev_ready = tmio_nand_dev_ready; + nand_chip->legacy.dev_ready = tmio_nand_dev_ready; nand_chip->legacy.read_byte = tmio_nand_read_byte; nand_chip->legacy.write_buf = tmio_nand_write_buf; nand_chip->legacy.read_buf = tmio_nand_read_buf; @@ -432,7 +432,7 @@ static int tmio_probe(struct platform_device *dev) } tmio->irq = irq; - nand_chip->waitfunc = tmio_nand_wait; + nand_chip->legacy.waitfunc = tmio_nand_wait; /* Scan to find existence of the device */ retval = nand_scan(nand_chip, 1); diff --git a/drivers/mtd/nand/raw/txx9ndfmc.c b/drivers/mtd/nand/raw/txx9ndfmc.c index 9eab56a45a5e..46cfb11c5502 100644 --- a/drivers/mtd/nand/raw/txx9ndfmc.c +++ b/drivers/mtd/nand/raw/txx9ndfmc.c @@ -328,7 +328,7 @@ static int __init txx9ndfmc_probe(struct platform_device *dev) chip->legacy.read_buf = txx9ndfmc_read_buf; chip->legacy.write_buf = txx9ndfmc_write_buf; chip->legacy.cmd_ctrl = txx9ndfmc_cmd_ctrl; - chip->dev_ready = txx9ndfmc_dev_ready; + chip->legacy.dev_ready = txx9ndfmc_dev_ready; chip->ecc.calculate = txx9ndfmc_calculate_ecc; chip->ecc.correct = txx9ndfmc_correct_data; chip->ecc.hwctl = txx9ndfmc_enable_hwecc; diff --git a/drivers/mtd/nand/raw/xway_nand.c b/drivers/mtd/nand/raw/xway_nand.c index ef351a4c507f..dcce487f6517 100644 --- a/drivers/mtd/nand/raw/xway_nand.c +++ b/drivers/mtd/nand/raw/xway_nand.c @@ -175,7 +175,7 @@ static int xway_nand_probe(struct platform_device *pdev) mtd->dev.parent = &pdev->dev; data->chip.legacy.cmd_ctrl = xway_cmd_ctrl; - data->chip.dev_ready = xway_dev_ready; + data->chip.legacy.dev_ready = xway_dev_ready; data->chip.select_chip = xway_select_chip; data->chip.legacy.write_buf = xway_write_buf; data->chip.legacy.read_buf = xway_read_buf; diff --git a/drivers/staging/mt29f_spinand/mt29f_spinand.c b/drivers/staging/mt29f_spinand/mt29f_spinand.c index fbfa024f683d..fb28cc6331f2 100644 --- a/drivers/staging/mt29f_spinand/mt29f_spinand.c +++ b/drivers/staging/mt29f_spinand/mt29f_spinand.c @@ -919,7 +919,7 @@ static int spinand_probe(struct spi_device *spi_nand) chip->legacy.write_buf = spinand_write_buf; chip->legacy.read_byte = spinand_read_byte; chip->legacy.cmdfunc = spinand_cmdfunc; - chip->waitfunc = spinand_wait; + chip->legacy.waitfunc = spinand_wait; chip->options |= NAND_CACHEPRG; chip->select_chip = spinand_select_chip; chip->set_features = nand_get_set_features_notsupp; diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h index 5ef2004a37a2..15642c028da2 100644 --- a/include/linux/mtd/rawnand.h +++ b/include/linux/mtd/rawnand.h @@ -1183,6 +1183,10 @@ int nand_op_parser_exec_op(struct nand_chip *chip, * @cmd_ctrl: hardware specific function for controlling ALE/CLE/nCE. Also used * to write command and address * @cmdfunc: hardware specific function for writing commands to the chip. + * @dev_ready: hardware specific function for accessing device ready/busy line. + * If set to NULL no access to ready/busy is available and the + * ready/busy information is read from the chip status register. + * @waitfunc: hardware specific function for wait on ready. * * If you look at this structure you're already wrong. These fields/hooks are * all deprecated. @@ -1197,6 +1201,8 @@ struct nand_legacy { void (*cmd_ctrl)(struct nand_chip *chip, int dat, unsigned int ctrl); void (*cmdfunc)(struct nand_chip *chip, unsigned command, int column, int page_addr); + int (*dev_ready)(struct nand_chip *chip); + int (*waitfunc)(struct nand_chip *chip); }; /** @@ -1210,16 +1216,10 @@ struct nand_legacy { * @select_chip: [REPLACEABLE] select chip nr * @block_bad: [REPLACEABLE] check if a block is bad, using OOB markers * @block_markbad: [REPLACEABLE] mark a block bad - * @dev_ready: [BOARDSPECIFIC] hardwarespecific function for accessing - * device ready/busy line. If set to NULL no access to - * ready/busy is available and the ready/busy information - * is read from the chip status register. - * @waitfunc: [REPLACEABLE] hardwarespecific function for wait on - * ready. * @exec_op: controller specific method to execute NAND operations. * This method replaces ->cmdfunc(), - * ->legacy.{read,write}_{buf,byte,word}(), ->dev_ready() - * and ->waifunc(). + * ->legacy.{read,write}_{buf,byte,word}(), + * ->legacy.dev_ready() and ->waifunc(). * @setup_read_retry: [FLASHSPECIFIC] flash (vendor) specific function for * setting the read-retry mode. Mostly needed for MLC NAND. * @ecc: [BOARDSPECIFIC] ECC control structure @@ -1305,8 +1305,6 @@ struct nand_chip { void (*select_chip)(struct nand_chip *chip, int cs); int (*block_bad)(struct nand_chip *chip, loff_t ofs); int (*block_markbad)(struct nand_chip *chip, loff_t ofs); - int (*dev_ready)(struct nand_chip *chip); - int (*waitfunc)(struct nand_chip *chip); int (*exec_op)(struct nand_chip *chip, const struct nand_operation *op, bool check_only); From cdc784c743945f445a26f4c0bd60a50a1adb39c4 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Fri, 7 Sep 2018 00:38:38 +0200 Subject: [PATCH 275/302] mtd: rawnand: Deprecate ->block_{bad,markbad}() hooks Those hooks have been overloaded by some drivers for bad reasons: either the driver was not fitting in the NAND framework and should have been an MTD driver (docg4), or it was not properly implementing the OOB read/write request or had a weird layout where BBM are trashed. In any case, we should discourage people from overloading those methods and encourage them to fix their driver instead. Move the ->block_{bad,markbad}() hooks to the nand_legacy struct to make it clear. Signed-off-by: Boris Brezillon Signed-off-by: Miquel Raynal --- drivers/mtd/nand/raw/cafe_nand.c | 2 +- drivers/mtd/nand/raw/diskonchip.c | 2 +- drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c | 4 +-- drivers/mtd/nand/raw/nand_base.c | 37 ++++++++++++++++------ drivers/mtd/nand/raw/nand_bbt.c | 2 +- drivers/mtd/nand/raw/qcom_nandc.c | 4 +-- drivers/mtd/nand/raw/sm_common.c | 2 +- include/linux/mtd/rawnand.h | 9 +++--- 8 files changed, 40 insertions(+), 22 deletions(-) diff --git a/drivers/mtd/nand/raw/cafe_nand.c b/drivers/mtd/nand/raw/cafe_nand.c index 738af0f0a48d..db62b12800d3 100644 --- a/drivers/mtd/nand/raw/cafe_nand.c +++ b/drivers/mtd/nand/raw/cafe_nand.c @@ -719,7 +719,7 @@ static int cafe_nand_probe(struct pci_dev *pdev, if (skipbbt) { cafe->nand.options |= NAND_SKIP_BBTSCAN; - cafe->nand.block_bad = cafe_nand_block_bad; + cafe->nand.legacy.block_bad = cafe_nand_block_bad; } if (numtimings && numtimings != 3) { diff --git a/drivers/mtd/nand/raw/diskonchip.c b/drivers/mtd/nand/raw/diskonchip.c index c3a79369fbed..16fdfd06ef25 100644 --- a/drivers/mtd/nand/raw/diskonchip.c +++ b/drivers/mtd/nand/raw/diskonchip.c @@ -1572,7 +1572,7 @@ static int __init doc_probe(unsigned long physadr) nand->legacy.cmd_ctrl = doc200x_hwcontrol; nand->legacy.dev_ready = doc200x_dev_ready; nand->legacy.waitfunc = doc200x_wait; - nand->block_bad = doc200x_block_bad; + nand->legacy.block_bad = doc200x_block_bad; nand->ecc.hwctl = doc200x_enable_hwecc; nand->ecc.calculate = doc200x_calculate_ecc; nand->ecc.correct = doc200x_correct_data; diff --git a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c index dc6291902acf..94c2b7525c85 100644 --- a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c +++ b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c @@ -1774,7 +1774,7 @@ static int mx23_boot_init(struct gpmi_nand_data *this) */ if (block_mark != 0xff) { dev_dbg(dev, "Transcribing mark in block %u\n", block); - ret = chip->block_markbad(chip, byte); + ret = chip->legacy.block_markbad(chip, byte); if (ret) dev_err(dev, "Failed to mark block bad with ret %d\n", @@ -1908,7 +1908,7 @@ static int gpmi_nand_init(struct gpmi_nand_data *this) chip->legacy.read_buf = gpmi_read_buf; chip->legacy.write_buf = gpmi_write_buf; chip->badblock_pattern = &gpmi_bbt_descr; - chip->block_markbad = gpmi_block_markbad; + chip->legacy.block_markbad = gpmi_block_markbad; chip->options |= NAND_NO_SUBPAGE_WRITE; /* Set up swap_block_mark, must be set before the gpmi_set_geometry() */ diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c index 30b55a4677f9..d71a3d303903 100644 --- a/drivers/mtd/nand/raw/nand_base.c +++ b/drivers/mtd/nand/raw/nand_base.c @@ -475,6 +475,27 @@ static int nand_default_block_markbad(struct nand_chip *chip, loff_t ofs) return ret; } +/** + * nand_markbad_bbm - mark a block by updating the BBM + * @chip: NAND chip object + * @ofs: offset of the block to mark bad + */ +int nand_markbad_bbm(struct nand_chip *chip, loff_t ofs) +{ + if (chip->legacy.block_markbad) + return chip->legacy.block_markbad(chip, ofs); + + return nand_default_block_markbad(chip, ofs); +} + +static int nand_isbad_bbm(struct nand_chip *chip, loff_t ofs) +{ + if (chip->legacy.block_bad) + return chip->legacy.block_bad(chip, ofs); + + return nand_block_bad(chip, ofs); +} + /** * nand_block_markbad_lowlevel - mark a block bad * @mtd: MTD device structure @@ -482,7 +503,7 @@ static int nand_default_block_markbad(struct nand_chip *chip, loff_t ofs) * * This function performs the generic NAND bad block marking steps (i.e., bad * block table(s) and/or marker(s)). We only allow the hardware driver to - * specify how to write bad block markers to OOB (chip->block_markbad). + * specify how to write bad block markers to OOB (chip->legacy.block_markbad). * * We try operations in the following order: * @@ -510,7 +531,7 @@ static int nand_block_markbad_lowlevel(struct mtd_info *mtd, loff_t ofs) /* Write bad block marker to OOB */ nand_get_device(mtd, FL_WRITING); - ret = chip->block_markbad(chip, ofs); + ret = nand_markbad_bbm(chip, ofs); nand_release_device(mtd); } @@ -582,11 +603,11 @@ static int nand_block_checkbad(struct mtd_info *mtd, loff_t ofs, int allowbbt) { struct nand_chip *chip = mtd_to_nand(mtd); - if (!chip->bbt) - return chip->block_bad(chip, ofs); - /* Return info from the table */ - return nand_isbad_bbt(chip, ofs, allowbbt); + if (chip->bbt) + return nand_isbad_bbt(chip, ofs, allowbbt); + + return nand_isbad_bbm(chip, ofs); } /** @@ -4942,10 +4963,6 @@ static void nand_set_defaults(struct nand_chip *chip) /* If called twice, pointers that depend on busw may need to be reset */ if (!chip->legacy.read_byte || chip->legacy.read_byte == nand_read_byte) chip->legacy.read_byte = busw ? nand_read_byte16 : nand_read_byte; - if (!chip->block_bad) - chip->block_bad = nand_block_bad; - if (!chip->block_markbad) - chip->block_markbad = nand_default_block_markbad; if (!chip->legacy.write_buf || chip->legacy.write_buf == nand_write_buf) chip->legacy.write_buf = busw ? nand_write_buf16 : nand_write_buf; if (!chip->legacy.write_byte || chip->legacy.write_byte == nand_write_byte) diff --git a/drivers/mtd/nand/raw/nand_bbt.c b/drivers/mtd/nand/raw/nand_bbt.c index 9d73e086c5de..b838ecdde8fb 100644 --- a/drivers/mtd/nand/raw/nand_bbt.c +++ b/drivers/mtd/nand/raw/nand_bbt.c @@ -689,7 +689,7 @@ static void mark_bbt_block_bad(struct nand_chip *this, bbt_mark_entry(this, block, BBT_BLOCK_WORN); to = (loff_t)block << this->bbt_erase_shift; - res = this->block_markbad(this, to); + res = nand_markbad_bbm(this, to); if (res) pr_warn("nand_bbt: error %d while marking block %d bad\n", res, block); diff --git a/drivers/mtd/nand/raw/qcom_nandc.c b/drivers/mtd/nand/raw/qcom_nandc.c index bd187139416f..79342e24ed81 100644 --- a/drivers/mtd/nand/raw/qcom_nandc.c +++ b/drivers/mtd/nand/raw/qcom_nandc.c @@ -2819,8 +2819,8 @@ static int qcom_nand_host_init_and_register(struct qcom_nand_controller *nandc, * and block_markbad helpers until we permanently switch to using * MTD_OPS_RAW for all drivers (with the help of badblockbits) */ - chip->block_bad = qcom_nandc_block_bad; - chip->block_markbad = qcom_nandc_block_markbad; + chip->legacy.block_bad = qcom_nandc_block_bad; + chip->legacy.block_markbad = qcom_nandc_block_markbad; chip->controller = &nandc->controller; chip->options |= NAND_NO_SUBPAGE_WRITE | NAND_USE_BOUNCE_BUFFER | diff --git a/drivers/mtd/nand/raw/sm_common.c b/drivers/mtd/nand/raw/sm_common.c index bf143e0db787..6f063ef57640 100644 --- a/drivers/mtd/nand/raw/sm_common.c +++ b/drivers/mtd/nand/raw/sm_common.c @@ -168,7 +168,7 @@ static int sm_attach_chip(struct nand_chip *chip) /* Bad block marker position */ chip->badblockpos = 0x05; chip->badblockbits = 7; - chip->block_markbad = sm_block_markbad; + chip->legacy.block_markbad = sm_block_markbad; /* ECC layout */ if (mtd->writesize == SM_SECTOR_SIZE) diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h index 15642c028da2..aa3e931d0206 100644 --- a/include/linux/mtd/rawnand.h +++ b/include/linux/mtd/rawnand.h @@ -1187,6 +1187,8 @@ int nand_op_parser_exec_op(struct nand_chip *chip, * If set to NULL no access to ready/busy is available and the * ready/busy information is read from the chip status register. * @waitfunc: hardware specific function for wait on ready. + * @block_bad: check if a block is bad, using OOB markers + * @block_markbad: mark a block bad * * If you look at this structure you're already wrong. These fields/hooks are * all deprecated. @@ -1203,6 +1205,8 @@ struct nand_legacy { int page_addr); int (*dev_ready)(struct nand_chip *chip); int (*waitfunc)(struct nand_chip *chip); + int (*block_bad)(struct nand_chip *chip, loff_t ofs); + int (*block_markbad)(struct nand_chip *chip, loff_t ofs); }; /** @@ -1214,8 +1218,6 @@ struct nand_legacy { * fields/hooks, you should consider reworking the driver * avoid using them. * @select_chip: [REPLACEABLE] select chip nr - * @block_bad: [REPLACEABLE] check if a block is bad, using OOB markers - * @block_markbad: [REPLACEABLE] mark a block bad * @exec_op: controller specific method to execute NAND operations. * This method replaces ->cmdfunc(), * ->legacy.{read,write}_{buf,byte,word}(), @@ -1303,8 +1305,6 @@ struct nand_chip { struct nand_legacy legacy; void (*select_chip)(struct nand_chip *chip, int cs); - int (*block_bad)(struct nand_chip *chip, loff_t ofs); - int (*block_markbad)(struct nand_chip *chip, loff_t ofs); int (*exec_op)(struct nand_chip *chip, const struct nand_operation *op, bool check_only); @@ -1556,6 +1556,7 @@ extern const struct nand_manufacturer_ops macronix_nand_manuf_ops; int nand_create_bbt(struct nand_chip *chip); int nand_markbad_bbt(struct nand_chip *chip, loff_t offs); +int nand_markbad_bbm(struct nand_chip *chip, loff_t ofs); int nand_isreserved_bbt(struct nand_chip *chip, loff_t offs); int nand_isbad_bbt(struct nand_chip *chip, loff_t offs, int allowbbt); int nand_erase_nand(struct nand_chip *chip, struct erase_info *instr, From f9ebd1bb41031afc162e9acda7ad044a35bccf82 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Fri, 7 Sep 2018 00:38:39 +0200 Subject: [PATCH 276/302] mtd: rawnand: Deprecate ->erase() The ->erase() hook have been overloaded by some drivers for bad reasons: either the driver was not fitting in the NAND framework and should have been an MTD driver (docg4), or the driver uses a specific path for the ERASE operation (denali), instead of implementing it generically. In any case, we should discourage people from overloading this method and encourage them to implement ->exec_op() instead. Move the ->erase() hook to the nand_legacy struct to make it clear. Signed-off-by: Boris Brezillon Signed-off-by: Miquel Raynal --- drivers/mtd/nand/raw/denali.c | 2 +- drivers/mtd/nand/raw/nand_base.c | 7 +++++-- include/linux/mtd/rawnand.h | 4 ++-- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/mtd/nand/raw/denali.c b/drivers/mtd/nand/raw/denali.c index c14493ef6126..858358027dc9 100644 --- a/drivers/mtd/nand/raw/denali.c +++ b/drivers/mtd/nand/raw/denali.c @@ -1275,7 +1275,7 @@ static int denali_attach_chip(struct nand_chip *chip) chip->ecc.write_page_raw = denali_write_page_raw; chip->ecc.read_oob = denali_read_oob; chip->ecc.write_oob = denali_write_oob; - chip->erase = denali_erase; + chip->legacy.erase = denali_erase; ret = denali_multidev_fixup(denali); if (ret) diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c index d71a3d303903..57c89e275a3a 100644 --- a/drivers/mtd/nand/raw/nand_base.c +++ b/drivers/mtd/nand/raw/nand_base.c @@ -4730,7 +4730,11 @@ int nand_erase_nand(struct nand_chip *chip, struct erase_info *instr, (page + pages_per_block)) chip->pagebuf = -1; - status = chip->erase(chip, page & chip->pagemask); + if (chip->legacy.erase) + status = chip->legacy.erase(chip, + page & chip->pagemask); + else + status = single_erase(chip, page & chip->pagemask); /* See if block erase succeeded */ if (status) { @@ -5756,7 +5760,6 @@ static int nand_detect(struct nand_chip *chip, struct nand_flash_dev *type) chip->options |= NAND_ROW_ADDR_3; chip->badblockbits = 8; - chip->erase = single_erase; /* Do not replace user supplied command function! */ if (mtd->writesize > 512 && chip->legacy.cmdfunc == nand_command) diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h index aa3e931d0206..97c6ff7d127e 100644 --- a/include/linux/mtd/rawnand.h +++ b/include/linux/mtd/rawnand.h @@ -1189,6 +1189,7 @@ int nand_op_parser_exec_op(struct nand_chip *chip, * @waitfunc: hardware specific function for wait on ready. * @block_bad: check if a block is bad, using OOB markers * @block_markbad: mark a block bad + * @erase: erase function * * If you look at this structure you're already wrong. These fields/hooks are * all deprecated. @@ -1207,6 +1208,7 @@ struct nand_legacy { int (*waitfunc)(struct nand_chip *chip); int (*block_bad)(struct nand_chip *chip, loff_t ofs); int (*block_markbad)(struct nand_chip *chip, loff_t ofs); + int (*erase)(struct nand_chip *chip, int page); }; /** @@ -1228,7 +1230,6 @@ struct nand_legacy { * @buf_align: minimum buffer alignment required by a platform * @dummy_controller: dummy controller implementation for drivers that can * only control a single chip - * @erase: [REPLACEABLE] erase function * @chip_delay: [BOARDSPECIFIC] chip dependent delay for transferring * data from array to read regs (tR). * @state: [INTERN] the current state of the NAND device @@ -1308,7 +1309,6 @@ struct nand_chip { int (*exec_op)(struct nand_chip *chip, const struct nand_operation *op, bool check_only); - int (*erase)(struct nand_chip *chip, int page); int (*set_features)(struct nand_chip *chip, int feature_addr, uint8_t *subfeature_para); int (*get_features)(struct nand_chip *chip, int feature_addr, From 45240367939b071b9957b970379cf64f9a2934ce Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Fri, 7 Sep 2018 00:38:40 +0200 Subject: [PATCH 277/302] mtd: rawnand: Deprecate ->{set,get}_features() hooks Those hooks should be replaced by a proper ->exec_op() implementation. Move them to the nand_legacy struct to make it clear. Signed-off-by: Boris Brezillon Signed-off-by: Miquel Raynal --- .../mtd/nand/raw/bcm47xxnflash/ops_bcm4706.c | 4 +- drivers/mtd/nand/raw/cafe_nand.c | 4 +- drivers/mtd/nand/raw/fsl_elbc_nand.c | 4 +- drivers/mtd/nand/raw/fsl_ifc_nand.c | 4 +- drivers/mtd/nand/raw/hisi504_nand.c | 4 +- drivers/mtd/nand/raw/mpc5121_nfc.c | 4 +- drivers/mtd/nand/raw/mxc_nand.c | 4 +- drivers/mtd/nand/raw/nand_base.c | 112 +++++++----------- drivers/mtd/nand/raw/qcom_nandc.c | 4 +- drivers/mtd/nand/raw/sh_flctl.c | 4 +- drivers/staging/mt29f_spinand/mt29f_spinand.c | 4 +- include/linux/mtd/rawnand.h | 12 +- 12 files changed, 70 insertions(+), 94 deletions(-) diff --git a/drivers/mtd/nand/raw/bcm47xxnflash/ops_bcm4706.c b/drivers/mtd/nand/raw/bcm47xxnflash/ops_bcm4706.c index 925d4cd4401e..357bc75948b0 100644 --- a/drivers/mtd/nand/raw/bcm47xxnflash/ops_bcm4706.c +++ b/drivers/mtd/nand/raw/bcm47xxnflash/ops_bcm4706.c @@ -390,8 +390,8 @@ int bcm47xxnflash_ops_bcm4706_init(struct bcm47xxnflash *b47n) b47n->nand_chip.legacy.read_byte = bcm47xxnflash_ops_bcm4706_read_byte; b47n->nand_chip.legacy.read_buf = bcm47xxnflash_ops_bcm4706_read_buf; b47n->nand_chip.legacy.write_buf = bcm47xxnflash_ops_bcm4706_write_buf; - b47n->nand_chip.set_features = nand_get_set_features_notsupp; - b47n->nand_chip.get_features = nand_get_set_features_notsupp; + b47n->nand_chip.legacy.set_features = nand_get_set_features_notsupp; + b47n->nand_chip.legacy.get_features = nand_get_set_features_notsupp; nand_chip->chip_delay = 50; b47n->nand_chip.bbt_options = NAND_BBT_USE_FLASH; diff --git a/drivers/mtd/nand/raw/cafe_nand.c b/drivers/mtd/nand/raw/cafe_nand.c index db62b12800d3..e3f702bef549 100644 --- a/drivers/mtd/nand/raw/cafe_nand.c +++ b/drivers/mtd/nand/raw/cafe_nand.c @@ -709,8 +709,8 @@ static int cafe_nand_probe(struct pci_dev *pdev, cafe->nand.legacy.read_buf = cafe_read_buf; cafe->nand.legacy.write_buf = cafe_write_buf; cafe->nand.select_chip = cafe_select_chip; - cafe->nand.set_features = nand_get_set_features_notsupp; - cafe->nand.get_features = nand_get_set_features_notsupp; + cafe->nand.legacy.set_features = nand_get_set_features_notsupp; + cafe->nand.legacy.get_features = nand_get_set_features_notsupp; cafe->nand.chip_delay = 0; diff --git a/drivers/mtd/nand/raw/fsl_elbc_nand.c b/drivers/mtd/nand/raw/fsl_elbc_nand.c index 29f0832de39b..c5f3aa908416 100644 --- a/drivers/mtd/nand/raw/fsl_elbc_nand.c +++ b/drivers/mtd/nand/raw/fsl_elbc_nand.c @@ -782,8 +782,8 @@ static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv) chip->select_chip = fsl_elbc_select_chip; chip->legacy.cmdfunc = fsl_elbc_cmdfunc; chip->legacy.waitfunc = fsl_elbc_wait; - chip->set_features = nand_get_set_features_notsupp; - chip->get_features = nand_get_set_features_notsupp; + chip->legacy.set_features = nand_get_set_features_notsupp; + chip->legacy.get_features = nand_get_set_features_notsupp; chip->bbt_td = &bbt_main_descr; chip->bbt_md = &bbt_mirror_descr; diff --git a/drivers/mtd/nand/raw/fsl_ifc_nand.c b/drivers/mtd/nand/raw/fsl_ifc_nand.c index 682ae383c3e9..a303d12079f0 100644 --- a/drivers/mtd/nand/raw/fsl_ifc_nand.c +++ b/drivers/mtd/nand/raw/fsl_ifc_nand.c @@ -867,8 +867,8 @@ static int fsl_ifc_chip_init(struct fsl_ifc_mtd *priv) chip->select_chip = fsl_ifc_select_chip; chip->legacy.cmdfunc = fsl_ifc_cmdfunc; chip->legacy.waitfunc = fsl_ifc_wait; - chip->set_features = nand_get_set_features_notsupp; - chip->get_features = nand_get_set_features_notsupp; + chip->legacy.set_features = nand_get_set_features_notsupp; + chip->legacy.get_features = nand_get_set_features_notsupp; chip->bbt_td = &bbt_main_descr; chip->bbt_md = &bbt_mirror_descr; diff --git a/drivers/mtd/nand/raw/hisi504_nand.c b/drivers/mtd/nand/raw/hisi504_nand.c index 6e17239983db..fee7d63e8de8 100644 --- a/drivers/mtd/nand/raw/hisi504_nand.c +++ b/drivers/mtd/nand/raw/hisi504_nand.c @@ -788,8 +788,8 @@ static int hisi_nfc_probe(struct platform_device *pdev) chip->legacy.write_buf = hisi_nfc_write_buf; chip->legacy.read_buf = hisi_nfc_read_buf; chip->chip_delay = HINFC504_CHIP_DELAY; - chip->set_features = nand_get_set_features_notsupp; - chip->get_features = nand_get_set_features_notsupp; + chip->legacy.set_features = nand_get_set_features_notsupp; + chip->legacy.get_features = nand_get_set_features_notsupp; hisi_nfc_host_init(host); diff --git a/drivers/mtd/nand/raw/mpc5121_nfc.c b/drivers/mtd/nand/raw/mpc5121_nfc.c index 9a6dc783689e..86a0aabe08df 100644 --- a/drivers/mtd/nand/raw/mpc5121_nfc.c +++ b/drivers/mtd/nand/raw/mpc5121_nfc.c @@ -698,8 +698,8 @@ static int mpc5121_nfc_probe(struct platform_device *op) chip->legacy.read_buf = mpc5121_nfc_read_buf; chip->legacy.write_buf = mpc5121_nfc_write_buf; chip->select_chip = mpc5121_nfc_select_chip; - chip->set_features = nand_get_set_features_notsupp; - chip->get_features = nand_get_set_features_notsupp; + chip->legacy.set_features = nand_get_set_features_notsupp; + chip->legacy.get_features = nand_get_set_features_notsupp; chip->bbt_options = NAND_BBT_USE_FLASH; chip->ecc.mode = NAND_ECC_SOFT; chip->ecc.algo = NAND_ECC_HAMMING; diff --git a/drivers/mtd/nand/raw/mxc_nand.c b/drivers/mtd/nand/raw/mxc_nand.c index ca074c955147..b8115100a0b8 100644 --- a/drivers/mtd/nand/raw/mxc_nand.c +++ b/drivers/mtd/nand/raw/mxc_nand.c @@ -1778,8 +1778,8 @@ static int mxcnd_probe(struct platform_device *pdev) this->legacy.read_byte = mxc_nand_read_byte; this->legacy.write_buf = mxc_nand_write_buf; this->legacy.read_buf = mxc_nand_read_buf; - this->set_features = mxc_nand_set_features; - this->get_features = mxc_nand_get_features; + this->legacy.set_features = mxc_nand_set_features; + this->legacy.get_features = mxc_nand_get_features; host->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(host->clk)) diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c index 57c89e275a3a..d4a84a871fc7 100644 --- a/drivers/mtd/nand/raw/nand_base.c +++ b/drivers/mtd/nand/raw/nand_base.c @@ -1175,44 +1175,6 @@ static bool nand_supports_set_features(struct nand_chip *chip, int addr) test_bit(addr, chip->parameters.set_feature_list)); } -/** - * nand_get_features - wrapper to perform a GET_FEATURE - * @chip: NAND chip info structure - * @addr: feature address - * @subfeature_param: the subfeature parameters, a four bytes array - * - * Returns 0 for success, a negative error otherwise. Returns -ENOTSUPP if the - * operation cannot be handled. - */ -int nand_get_features(struct nand_chip *chip, int addr, - u8 *subfeature_param) -{ - if (!nand_supports_get_features(chip, addr)) - return -ENOTSUPP; - - return chip->get_features(chip, addr, subfeature_param); -} -EXPORT_SYMBOL_GPL(nand_get_features); - -/** - * nand_set_features - wrapper to perform a SET_FEATURE - * @chip: NAND chip info structure - * @addr: feature address - * @subfeature_param: the subfeature parameters, a four bytes array - * - * Returns 0 for success, a negative error otherwise. Returns -ENOTSUPP if the - * operation cannot be handled. - */ -int nand_set_features(struct nand_chip *chip, int addr, - u8 *subfeature_param) -{ - if (!nand_supports_set_features(chip, addr)) - return -ENOTSUPP; - - return chip->set_features(chip, addr, subfeature_param); -} -EXPORT_SYMBOL_GPL(nand_set_features); - /** * nand_reset_data_interface - Reset data interface and timings * @chip: The NAND chip @@ -2833,6 +2795,50 @@ int nand_reset(struct nand_chip *chip, int chipnr) } EXPORT_SYMBOL_GPL(nand_reset); +/** + * nand_get_features - wrapper to perform a GET_FEATURE + * @chip: NAND chip info structure + * @addr: feature address + * @subfeature_param: the subfeature parameters, a four bytes array + * + * Returns 0 for success, a negative error otherwise. Returns -ENOTSUPP if the + * operation cannot be handled. + */ +int nand_get_features(struct nand_chip *chip, int addr, + u8 *subfeature_param) +{ + if (!nand_supports_get_features(chip, addr)) + return -ENOTSUPP; + + if (chip->legacy.get_features) + return chip->legacy.get_features(chip, addr, subfeature_param); + + return nand_get_features_op(chip, addr, subfeature_param); +} +EXPORT_SYMBOL_GPL(nand_get_features); + +/** + * nand_set_features - wrapper to perform a SET_FEATURE + * @chip: NAND chip info structure + * @addr: feature address + * @subfeature_param: the subfeature parameters, a four bytes array + * + * Returns 0 for success, a negative error otherwise. Returns -ENOTSUPP if the + * operation cannot be handled. + */ +int nand_set_features(struct nand_chip *chip, int addr, + u8 *subfeature_param) +{ + if (!nand_supports_set_features(chip, addr)) + return -ENOTSUPP; + + if (chip->legacy.set_features) + return chip->legacy.set_features(chip, addr, subfeature_param); + + return nand_set_features_op(chip, addr, subfeature_param); +} +EXPORT_SYMBOL_GPL(nand_set_features); + /** * nand_check_erased_buf - check if a buffer contains (almost) only 0xff data * @buf: buffer to test @@ -4864,30 +4870,6 @@ static int nand_max_bad_blocks(struct mtd_info *mtd, loff_t ofs, size_t len) return chip->max_bb_per_die * (part_end_die - part_start_die + 1); } -/** - * nand_default_set_features- [REPLACEABLE] set NAND chip features - * @chip: nand chip info structure - * @addr: feature address. - * @subfeature_param: the subfeature parameters, a four bytes array. - */ -static int nand_default_set_features(struct nand_chip *chip, int addr, - uint8_t *subfeature_param) -{ - return nand_set_features_op(chip, addr, subfeature_param); -} - -/** - * nand_default_get_features- [REPLACEABLE] get NAND chip features - * @chip: nand chip info structure - * @addr: feature address. - * @subfeature_param: the subfeature parameters, a four bytes array. - */ -static int nand_default_get_features(struct nand_chip *chip, int addr, - uint8_t *subfeature_param) -{ - return nand_get_features_op(chip, addr, subfeature_param); -} - /** * nand_get_set_features_notsupp - set/get features stub returning -ENOTSUPP * @chip: nand chip info structure @@ -4958,12 +4940,6 @@ static void nand_set_defaults(struct nand_chip *chip) if (!chip->select_chip) chip->select_chip = nand_select_chip; - /* set for ONFI nand */ - if (!chip->set_features) - chip->set_features = nand_default_set_features; - if (!chip->get_features) - chip->get_features = nand_default_get_features; - /* If called twice, pointers that depend on busw may need to be reset */ if (!chip->legacy.read_byte || chip->legacy.read_byte == nand_read_byte) chip->legacy.read_byte = busw ? nand_read_byte16 : nand_read_byte; diff --git a/drivers/mtd/nand/raw/qcom_nandc.c b/drivers/mtd/nand/raw/qcom_nandc.c index 79342e24ed81..ef75dfa62a4f 100644 --- a/drivers/mtd/nand/raw/qcom_nandc.c +++ b/drivers/mtd/nand/raw/qcom_nandc.c @@ -2808,8 +2808,8 @@ static int qcom_nand_host_init_and_register(struct qcom_nand_controller *nandc, chip->legacy.read_byte = qcom_nandc_read_byte; chip->legacy.read_buf = qcom_nandc_read_buf; chip->legacy.write_buf = qcom_nandc_write_buf; - chip->set_features = nand_get_set_features_notsupp; - chip->get_features = nand_get_set_features_notsupp; + chip->legacy.set_features = nand_get_set_features_notsupp; + chip->legacy.get_features = nand_get_set_features_notsupp; /* * the bad block marker is readable only when we read the last codeword diff --git a/drivers/mtd/nand/raw/sh_flctl.c b/drivers/mtd/nand/raw/sh_flctl.c index 71658fbd99a3..40a4159924a7 100644 --- a/drivers/mtd/nand/raw/sh_flctl.c +++ b/drivers/mtd/nand/raw/sh_flctl.c @@ -1185,8 +1185,8 @@ static int flctl_probe(struct platform_device *pdev) nand->legacy.read_buf = flctl_read_buf; nand->select_chip = flctl_select_chip; nand->legacy.cmdfunc = flctl_cmdfunc; - nand->set_features = nand_get_set_features_notsupp; - nand->get_features = nand_get_set_features_notsupp; + nand->legacy.set_features = nand_get_set_features_notsupp; + nand->legacy.get_features = nand_get_set_features_notsupp; if (pdata->flcmncr_val & SEL_16BIT) nand->options |= NAND_BUSWIDTH_16; diff --git a/drivers/staging/mt29f_spinand/mt29f_spinand.c b/drivers/staging/mt29f_spinand/mt29f_spinand.c index fb28cc6331f2..def8a1f57d1c 100644 --- a/drivers/staging/mt29f_spinand/mt29f_spinand.c +++ b/drivers/staging/mt29f_spinand/mt29f_spinand.c @@ -922,8 +922,8 @@ static int spinand_probe(struct spi_device *spi_nand) chip->legacy.waitfunc = spinand_wait; chip->options |= NAND_CACHEPRG; chip->select_chip = spinand_select_chip; - chip->set_features = nand_get_set_features_notsupp; - chip->get_features = nand_get_set_features_notsupp; + chip->legacy.set_features = nand_get_set_features_notsupp; + chip->legacy.get_features = nand_get_set_features_notsupp; mtd = nand_to_mtd(chip); diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h index 97c6ff7d127e..02ac70a30c63 100644 --- a/include/linux/mtd/rawnand.h +++ b/include/linux/mtd/rawnand.h @@ -1190,6 +1190,8 @@ int nand_op_parser_exec_op(struct nand_chip *chip, * @block_bad: check if a block is bad, using OOB markers * @block_markbad: mark a block bad * @erase: erase function + * @set_features: set the NAND chip features + * @get_features: get the NAND chip features * * If you look at this structure you're already wrong. These fields/hooks are * all deprecated. @@ -1209,6 +1211,10 @@ struct nand_legacy { int (*block_bad)(struct nand_chip *chip, loff_t ofs); int (*block_markbad)(struct nand_chip *chip, loff_t ofs); int (*erase)(struct nand_chip *chip, int page); + int (*set_features)(struct nand_chip *chip, int feature_addr, + u8 *subfeature_para); + int (*get_features)(struct nand_chip *chip, int feature_addr, + u8 *subfeature_para); }; /** @@ -1279,8 +1285,6 @@ struct nand_legacy { * @blocks_per_die: [INTERN] The number of PEBs in a die * @data_interface: [INTERN] NAND interface timing information * @read_retries: [INTERN] the number of read retry modes supported - * @set_features: [REPLACEABLE] set the NAND chip features - * @get_features: [REPLACEABLE] get the NAND chip features * @setup_data_interface: [OPTIONAL] setup the data interface and timing. If * chipnr is set to %NAND_DATA_IFACE_CHECK_ONLY this * means the configuration should not be applied but @@ -1309,10 +1313,6 @@ struct nand_chip { int (*exec_op)(struct nand_chip *chip, const struct nand_operation *op, bool check_only); - int (*set_features)(struct nand_chip *chip, int feature_addr, - uint8_t *subfeature_para); - int (*get_features)(struct nand_chip *chip, int feature_addr, - uint8_t *subfeature_para); int (*setup_read_retry)(struct nand_chip *chip, int retry_mode); int (*setup_data_interface)(struct nand_chip *chip, int chipnr, const struct nand_data_interface *conf); From 3cece3abebda068e55e19302a6f0fa60cf553737 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Fri, 7 Sep 2018 00:38:41 +0200 Subject: [PATCH 278/302] mtd: rawnand: Deprecate ->chip_delay The wait timeouts and delays are directly extracted from the NAND timings and ->chip_delay is only used in legacy path, so let's move it to the nand_legacy struct to make it clear. Signed-off-by: Boris Brezillon Signed-off-by: Miquel Raynal --- Documentation/driver-api/mtdnand.rst | 2 +- drivers/mtd/nand/raw/ams-delta.c | 2 +- drivers/mtd/nand/raw/atmel/nand-controller.c | 2 +- drivers/mtd/nand/raw/au1550nd.c | 4 ++-- drivers/mtd/nand/raw/bcm47xxnflash/ops_bcm4706.c | 2 +- drivers/mtd/nand/raw/cafe_nand.c | 2 +- drivers/mtd/nand/raw/cmx270_nand.c | 2 +- drivers/mtd/nand/raw/cs553x_nand.c | 2 +- drivers/mtd/nand/raw/davinci_nand.c | 2 +- drivers/mtd/nand/raw/diskonchip.c | 4 ++-- drivers/mtd/nand/raw/fsl_elbc_nand.c | 4 ++-- drivers/mtd/nand/raw/fsl_ifc_nand.c | 4 ++-- drivers/mtd/nand/raw/fsl_upm.c | 2 +- drivers/mtd/nand/raw/fsmc_nand.c | 1 - drivers/mtd/nand/raw/gpio.c | 2 +- drivers/mtd/nand/raw/hisi504_nand.c | 2 +- drivers/mtd/nand/raw/jz4740_nand.c | 2 +- drivers/mtd/nand/raw/jz4780_nand.c | 2 +- drivers/mtd/nand/raw/lpc32xx_mlc.c | 2 +- drivers/mtd/nand/raw/lpc32xx_slc.c | 2 +- drivers/mtd/nand/raw/mxc_nand.c | 2 +- drivers/mtd/nand/raw/nand_base.c | 14 +++++++------- drivers/mtd/nand/raw/nandsim.c | 2 +- drivers/mtd/nand/raw/ndfc.c | 2 +- drivers/mtd/nand/raw/nuc900_nand.c | 6 +++--- drivers/mtd/nand/raw/omap2.c | 4 ++-- drivers/mtd/nand/raw/orion_nand.c | 2 +- drivers/mtd/nand/raw/oxnas_nand.c | 2 +- drivers/mtd/nand/raw/pasemi_nand.c | 2 +- drivers/mtd/nand/raw/plat_nand.c | 2 +- drivers/mtd/nand/raw/s3c2410.c | 2 +- drivers/mtd/nand/raw/sh_flctl.c | 2 +- drivers/mtd/nand/raw/sharpsl.c | 2 +- drivers/mtd/nand/raw/socrates_nand.c | 2 +- drivers/mtd/nand/raw/sunxi_nand.c | 2 +- drivers/mtd/nand/raw/tmio_nand.c | 2 +- drivers/mtd/nand/raw/txx9ndfmc.c | 2 +- drivers/mtd/nand/raw/xway_nand.c | 2 +- include/linux/mtd/rawnand.h | 6 +++--- 39 files changed, 53 insertions(+), 54 deletions(-) diff --git a/Documentation/driver-api/mtdnand.rst b/Documentation/driver-api/mtdnand.rst index 0d3fa4d6576d..55447659b81f 100644 --- a/Documentation/driver-api/mtdnand.rst +++ b/Documentation/driver-api/mtdnand.rst @@ -240,7 +240,7 @@ necessary information about the device. /* Reference hardware control function */ this->hwcontrol = board_hwcontrol; /* Set command delay time, see datasheet for correct value */ - this->chip_delay = CHIP_DEPENDEND_COMMAND_DELAY; + this->legacy.chip_delay = CHIP_DEPENDEND_COMMAND_DELAY; /* Assign the device ready function, if available */ this->legacy.dev_ready = board_dev_ready; this->eccmode = NAND_ECC_SOFT; diff --git a/drivers/mtd/nand/raw/ams-delta.c b/drivers/mtd/nand/raw/ams-delta.c index 2fa6fa3c7464..3d3786dcc5d1 100644 --- a/drivers/mtd/nand/raw/ams-delta.c +++ b/drivers/mtd/nand/raw/ams-delta.c @@ -221,7 +221,7 @@ static int ams_delta_init(struct platform_device *pdev) pr_notice("Couldn't request gpio for Delta NAND ready.\n"); } /* 25 us command delay time */ - this->chip_delay = 30; + this->legacy.chip_delay = 30; this->ecc.mode = NAND_ECC_SOFT; this->ecc.algo = NAND_ECC_HAMMING; diff --git a/drivers/mtd/nand/raw/atmel/nand-controller.c b/drivers/mtd/nand/raw/atmel/nand-controller.c index dd022080442d..ad0245c66892 100644 --- a/drivers/mtd/nand/raw/atmel/nand-controller.c +++ b/drivers/mtd/nand/raw/atmel/nand-controller.c @@ -1483,7 +1483,7 @@ static void atmel_nand_init(struct atmel_nand_controller *nc, chip->setup_data_interface = atmel_nand_setup_data_interface; /* Some NANDs require a longer delay than the default one (20us). */ - chip->chip_delay = 40; + chip->legacy.chip_delay = 40; /* * Use a bounce buffer when the buffer passed by the MTD user is not diff --git a/drivers/mtd/nand/raw/au1550nd.c b/drivers/mtd/nand/raw/au1550nd.c index 81bba469c0e4..9731c1c487f6 100644 --- a/drivers/mtd/nand/raw/au1550nd.c +++ b/drivers/mtd/nand/raw/au1550nd.c @@ -342,7 +342,7 @@ static void au1550_command(struct nand_chip *this, unsigned command, /* Apply a short delay always to ensure that we do wait tWB. */ ndelay(100); /* Wait for a chip to become ready... */ - for (i = this->chip_delay; + for (i = this->legacy.chip_delay; !this->legacy.dev_ready(this) && i > 0; --i) udelay(1); @@ -434,7 +434,7 @@ static int au1550nd_probe(struct platform_device *pdev) this->legacy.cmdfunc = au1550_command; /* 30 us command delay time */ - this->chip_delay = 30; + this->legacy.chip_delay = 30; this->ecc.mode = NAND_ECC_SOFT; this->ecc.algo = NAND_ECC_HAMMING; diff --git a/drivers/mtd/nand/raw/bcm47xxnflash/ops_bcm4706.c b/drivers/mtd/nand/raw/bcm47xxnflash/ops_bcm4706.c index 357bc75948b0..9095a79ebc7d 100644 --- a/drivers/mtd/nand/raw/bcm47xxnflash/ops_bcm4706.c +++ b/drivers/mtd/nand/raw/bcm47xxnflash/ops_bcm4706.c @@ -393,7 +393,7 @@ int bcm47xxnflash_ops_bcm4706_init(struct bcm47xxnflash *b47n) b47n->nand_chip.legacy.set_features = nand_get_set_features_notsupp; b47n->nand_chip.legacy.get_features = nand_get_set_features_notsupp; - nand_chip->chip_delay = 50; + nand_chip->legacy.chip_delay = 50; b47n->nand_chip.bbt_options = NAND_BBT_USE_FLASH; b47n->nand_chip.ecc.mode = NAND_ECC_NONE; /* TODO: implement ECC */ diff --git a/drivers/mtd/nand/raw/cafe_nand.c b/drivers/mtd/nand/raw/cafe_nand.c index e3f702bef549..c1a745940d12 100644 --- a/drivers/mtd/nand/raw/cafe_nand.c +++ b/drivers/mtd/nand/raw/cafe_nand.c @@ -712,7 +712,7 @@ static int cafe_nand_probe(struct pci_dev *pdev, cafe->nand.legacy.set_features = nand_get_set_features_notsupp; cafe->nand.legacy.get_features = nand_get_set_features_notsupp; - cafe->nand.chip_delay = 0; + cafe->nand.legacy.chip_delay = 0; /* Enable the following for a flash based bad block table */ cafe->nand.bbt_options = NAND_BBT_USE_FLASH; diff --git a/drivers/mtd/nand/raw/cmx270_nand.c b/drivers/mtd/nand/raw/cmx270_nand.c index 585dbd51d8b1..143e4acacaae 100644 --- a/drivers/mtd/nand/raw/cmx270_nand.c +++ b/drivers/mtd/nand/raw/cmx270_nand.c @@ -179,7 +179,7 @@ static int __init cmx270_init(void) this->legacy.dev_ready = cmx270_device_ready; /* 15 us command delay time */ - this->chip_delay = 20; + this->legacy.chip_delay = 20; this->ecc.mode = NAND_ECC_SOFT; this->ecc.algo = NAND_ECC_HAMMING; diff --git a/drivers/mtd/nand/raw/cs553x_nand.c b/drivers/mtd/nand/raw/cs553x_nand.c index 61ae9e60bf0d..c6f578aff5d9 100644 --- a/drivers/mtd/nand/raw/cs553x_nand.c +++ b/drivers/mtd/nand/raw/cs553x_nand.c @@ -212,7 +212,7 @@ static int __init cs553x_init_one(int cs, int mmio, unsigned long adr) this->legacy.read_buf = cs553x_read_buf; this->legacy.write_buf = cs553x_write_buf; - this->chip_delay = 0; + this->legacy.chip_delay = 0; this->ecc.mode = NAND_ECC_HW; this->ecc.size = 256; diff --git a/drivers/mtd/nand/raw/davinci_nand.c b/drivers/mtd/nand/raw/davinci_nand.c index bae568d68432..80f228d23cd2 100644 --- a/drivers/mtd/nand/raw/davinci_nand.c +++ b/drivers/mtd/nand/raw/davinci_nand.c @@ -761,7 +761,7 @@ static int nand_davinci_probe(struct platform_device *pdev) info->chip.legacy.IO_ADDR_R = vaddr; info->chip.legacy.IO_ADDR_W = vaddr; - info->chip.chip_delay = 0; + info->chip.legacy.chip_delay = 0; info->chip.select_chip = nand_davinci_select_chip; /* options such as NAND_BBT_USE_FLASH */ diff --git a/drivers/mtd/nand/raw/diskonchip.c b/drivers/mtd/nand/raw/diskonchip.c index 16fdfd06ef25..3a4c373affab 100644 --- a/drivers/mtd/nand/raw/diskonchip.c +++ b/drivers/mtd/nand/raw/diskonchip.c @@ -717,7 +717,7 @@ static void doc2001plus_command(struct nand_chip *this, unsigned command, case NAND_CMD_RESET: if (this->legacy.dev_ready) break; - udelay(this->chip_delay); + udelay(this->legacy.chip_delay); WriteDOC(NAND_CMD_STATUS, docptr, Mplus_FlashCmd); WriteDOC(0, docptr, Mplus_WritePipeTerm); WriteDOC(0, docptr, Mplus_WritePipeTerm); @@ -731,7 +731,7 @@ static void doc2001plus_command(struct nand_chip *this, unsigned command, * command delay */ if (!this->legacy.dev_ready) { - udelay(this->chip_delay); + udelay(this->legacy.chip_delay); return; } } diff --git a/drivers/mtd/nand/raw/fsl_elbc_nand.c b/drivers/mtd/nand/raw/fsl_elbc_nand.c index c5f3aa908416..d6ed697fcfe6 100644 --- a/drivers/mtd/nand/raw/fsl_elbc_nand.c +++ b/drivers/mtd/nand/raw/fsl_elbc_nand.c @@ -658,8 +658,8 @@ static int fsl_elbc_attach_chip(struct nand_chip *chip) chip->chipsize); dev_dbg(priv->dev, "fsl_elbc_init: nand->pagemask = %8x\n", chip->pagemask); - dev_dbg(priv->dev, "fsl_elbc_init: nand->chip_delay = %d\n", - chip->chip_delay); + dev_dbg(priv->dev, "fsl_elbc_init: nand->legacy.chip_delay = %d\n", + chip->legacy.chip_delay); dev_dbg(priv->dev, "fsl_elbc_init: nand->badblockpos = %d\n", chip->badblockpos); dev_dbg(priv->dev, "fsl_elbc_init: nand->chip_shift = %d\n", diff --git a/drivers/mtd/nand/raw/fsl_ifc_nand.c b/drivers/mtd/nand/raw/fsl_ifc_nand.c index a303d12079f0..6f4afc44381a 100644 --- a/drivers/mtd/nand/raw/fsl_ifc_nand.c +++ b/drivers/mtd/nand/raw/fsl_ifc_nand.c @@ -727,8 +727,8 @@ static int fsl_ifc_attach_chip(struct nand_chip *chip) chip->chipsize); dev_dbg(priv->dev, "%s: nand->pagemask = %8x\n", __func__, chip->pagemask); - dev_dbg(priv->dev, "%s: nand->chip_delay = %d\n", __func__, - chip->chip_delay); + dev_dbg(priv->dev, "%s: nand->legacy.chip_delay = %d\n", __func__, + chip->legacy.chip_delay); dev_dbg(priv->dev, "%s: nand->badblockpos = %d\n", __func__, chip->badblockpos); dev_dbg(priv->dev, "%s: nand->chip_shift = %d\n", __func__, diff --git a/drivers/mtd/nand/raw/fsl_upm.c b/drivers/mtd/nand/raw/fsl_upm.c index fcb79718b6c3..673c5a0c9345 100644 --- a/drivers/mtd/nand/raw/fsl_upm.c +++ b/drivers/mtd/nand/raw/fsl_upm.c @@ -163,7 +163,7 @@ static int fun_chip_init(struct fsl_upm_nand *fun, fun->chip.legacy.IO_ADDR_R = fun->io_base; fun->chip.legacy.IO_ADDR_W = fun->io_base; fun->chip.legacy.cmd_ctrl = fun_cmd_ctrl; - fun->chip.chip_delay = fun->chip_delay; + fun->chip.legacy.chip_delay = fun->chip_delay; fun->chip.legacy.read_byte = fun_read_byte; fun->chip.legacy.read_buf = fun_read_buf; fun->chip.legacy.write_buf = fun_write_buf; diff --git a/drivers/mtd/nand/raw/fsmc_nand.c b/drivers/mtd/nand/raw/fsmc_nand.c index 5e06fce4b295..f9874fc72f30 100644 --- a/drivers/mtd/nand/raw/fsmc_nand.c +++ b/drivers/mtd/nand/raw/fsmc_nand.c @@ -1080,7 +1080,6 @@ static int __init fsmc_nand_probe(struct platform_device *pdev) mtd->dev.parent = &pdev->dev; nand->exec_op = fsmc_exec_op; nand->select_chip = fsmc_select_chip; - nand->chip_delay = 30; /* * Setup default ECC mode. nand_dt_init() called from nand_scan_ident() diff --git a/drivers/mtd/nand/raw/gpio.c b/drivers/mtd/nand/raw/gpio.c index c4f19067702e..a6c9a824a7d4 100644 --- a/drivers/mtd/nand/raw/gpio.c +++ b/drivers/mtd/nand/raw/gpio.c @@ -278,7 +278,7 @@ static int gpio_nand_probe(struct platform_device *pdev) chip->ecc.mode = NAND_ECC_SOFT; chip->ecc.algo = NAND_ECC_HAMMING; chip->options = gpiomtd->plat.options; - chip->chip_delay = gpiomtd->plat.chip_delay; + chip->legacy.chip_delay = gpiomtd->plat.chip_delay; chip->legacy.cmd_ctrl = gpio_nand_cmd_ctrl; mtd = nand_to_mtd(chip); diff --git a/drivers/mtd/nand/raw/hisi504_nand.c b/drivers/mtd/nand/raw/hisi504_nand.c index fee7d63e8de8..f043938ee36b 100644 --- a/drivers/mtd/nand/raw/hisi504_nand.c +++ b/drivers/mtd/nand/raw/hisi504_nand.c @@ -787,7 +787,7 @@ static int hisi_nfc_probe(struct platform_device *pdev) chip->legacy.read_byte = hisi_nfc_read_byte; chip->legacy.write_buf = hisi_nfc_write_buf; chip->legacy.read_buf = hisi_nfc_read_buf; - chip->chip_delay = HINFC504_CHIP_DELAY; + chip->legacy.chip_delay = HINFC504_CHIP_DELAY; chip->legacy.set_features = nand_get_set_features_notsupp; chip->legacy.get_features = nand_get_set_features_notsupp; diff --git a/drivers/mtd/nand/raw/jz4740_nand.c b/drivers/mtd/nand/raw/jz4740_nand.c index 7a1b4c3ff6fd..fb59cfca11a7 100644 --- a/drivers/mtd/nand/raw/jz4740_nand.c +++ b/drivers/mtd/nand/raw/jz4740_nand.c @@ -425,7 +425,7 @@ static int jz_nand_probe(struct platform_device *pdev) chip->ecc.strength = 4; chip->ecc.options = NAND_ECC_GENERIC_ERASED_CHECK; - chip->chip_delay = 50; + chip->legacy.chip_delay = 50; chip->legacy.cmd_ctrl = jz_nand_cmd_ctrl; chip->select_chip = jz_nand_select_chip; chip->dummy_controller.ops = &jz_nand_controller_ops; diff --git a/drivers/mtd/nand/raw/jz4780_nand.c b/drivers/mtd/nand/raw/jz4780_nand.c index 2a960211b97d..cdf22100ab77 100644 --- a/drivers/mtd/nand/raw/jz4780_nand.c +++ b/drivers/mtd/nand/raw/jz4780_nand.c @@ -277,7 +277,7 @@ static int jz4780_nand_init_chip(struct platform_device *pdev, chip->legacy.IO_ADDR_R = cs->base + OFFSET_DATA; chip->legacy.IO_ADDR_W = cs->base + OFFSET_DATA; - chip->chip_delay = RB_DELAY_US; + chip->legacy.chip_delay = RB_DELAY_US; chip->options = NAND_NO_SUBPAGE_WRITE; chip->select_chip = jz4780_nand_select_chip; chip->legacy.cmd_ctrl = jz4780_nand_cmd_ctrl; diff --git a/drivers/mtd/nand/raw/lpc32xx_mlc.c b/drivers/mtd/nand/raw/lpc32xx_mlc.c index 8a1dfb7ee885..abbb655fe154 100644 --- a/drivers/mtd/nand/raw/lpc32xx_mlc.c +++ b/drivers/mtd/nand/raw/lpc32xx_mlc.c @@ -741,7 +741,7 @@ static int lpc32xx_nand_probe(struct platform_device *pdev) nand_chip->legacy.cmd_ctrl = lpc32xx_nand_cmd_ctrl; nand_chip->legacy.dev_ready = lpc32xx_nand_device_ready; - nand_chip->chip_delay = 25; /* us */ + nand_chip->legacy.chip_delay = 25; /* us */ nand_chip->legacy.IO_ADDR_R = MLC_DATA(host->io_base); nand_chip->legacy.IO_ADDR_W = MLC_DATA(host->io_base); diff --git a/drivers/mtd/nand/raw/lpc32xx_slc.c b/drivers/mtd/nand/raw/lpc32xx_slc.c index 75d62d6bed7b..f2f2cdbb9d04 100644 --- a/drivers/mtd/nand/raw/lpc32xx_slc.c +++ b/drivers/mtd/nand/raw/lpc32xx_slc.c @@ -882,7 +882,7 @@ static int lpc32xx_nand_probe(struct platform_device *pdev) chip->legacy.IO_ADDR_W = SLC_DATA(host->io_base); chip->legacy.cmd_ctrl = lpc32xx_nand_cmd_ctrl; chip->legacy.dev_ready = lpc32xx_nand_device_ready; - chip->chip_delay = 20; /* 20us command delay time */ + chip->legacy.chip_delay = 20; /* 20us command delay time */ /* Init NAND controller */ lpc32xx_nand_setup(host); diff --git a/drivers/mtd/nand/raw/mxc_nand.c b/drivers/mtd/nand/raw/mxc_nand.c index b8115100a0b8..88bd3f6a499c 100644 --- a/drivers/mtd/nand/raw/mxc_nand.c +++ b/drivers/mtd/nand/raw/mxc_nand.c @@ -1769,7 +1769,7 @@ static int mxcnd_probe(struct platform_device *pdev) mtd->name = DRIVER_NAME; /* 50 us command delay time */ - this->chip_delay = 5; + this->legacy.chip_delay = 5; nand_set_controller_data(this, host); nand_set_flash_node(this, pdev->dev.of_node), diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c index d4a84a871fc7..2f8bbc3bca7a 100644 --- a/drivers/mtd/nand/raw/nand_base.c +++ b/drivers/mtd/nand/raw/nand_base.c @@ -827,7 +827,7 @@ static void nand_command(struct nand_chip *chip, unsigned int command, case NAND_CMD_RESET: if (chip->legacy.dev_ready) break; - udelay(chip->chip_delay); + udelay(chip->legacy.chip_delay); chip->legacy.cmd_ctrl(chip, NAND_CMD_STATUS, NAND_CTRL_CLE | NAND_CTRL_CHANGE); chip->legacy.cmd_ctrl(chip, NAND_CMD_NONE, @@ -853,7 +853,7 @@ static void nand_command(struct nand_chip *chip, unsigned int command, * command delay */ if (!chip->legacy.dev_ready) { - udelay(chip->chip_delay); + udelay(chip->legacy.chip_delay); return; } } @@ -964,7 +964,7 @@ static void nand_command_lp(struct nand_chip *chip, unsigned int command, case NAND_CMD_RESET: if (chip->legacy.dev_ready) break; - udelay(chip->chip_delay); + udelay(chip->legacy.chip_delay); chip->legacy.cmd_ctrl(chip, NAND_CMD_STATUS, NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE); chip->legacy.cmd_ctrl(chip, NAND_CMD_NONE, @@ -1005,7 +1005,7 @@ static void nand_command_lp(struct nand_chip *chip, unsigned int command, * command delay. */ if (!chip->legacy.dev_ready) { - udelay(chip->chip_delay); + udelay(chip->legacy.chip_delay); return; } } @@ -2206,7 +2206,7 @@ static int nand_wait_rdy_op(struct nand_chip *chip, unsigned int timeout_ms, /* Apply delay or wait for ready/busy pin */ if (!chip->legacy.dev_ready) - udelay(chip->chip_delay); + udelay(chip->legacy.chip_delay); else nand_wait_ready(chip); @@ -4926,8 +4926,8 @@ static void nand_set_defaults(struct nand_chip *chip) unsigned int busw = chip->options & NAND_BUSWIDTH_16; /* check for proper chip_delay setup, set 20us if not */ - if (!chip->chip_delay) - chip->chip_delay = 20; + if (!chip->legacy.chip_delay) + chip->legacy.chip_delay = 20; /* check, if a user supplied command function given */ if (!chip->legacy.cmdfunc && !chip->exec_op) diff --git a/drivers/mtd/nand/raw/nandsim.c b/drivers/mtd/nand/raw/nandsim.c index ff0c372ee288..c452819f6123 100644 --- a/drivers/mtd/nand/raw/nandsim.c +++ b/drivers/mtd/nand/raw/nandsim.c @@ -656,7 +656,7 @@ static int __init init_nandsim(struct mtd_info *mtd) } /* Force mtd to not do delays */ - chip->chip_delay = 0; + chip->legacy.chip_delay = 0; /* Initialize the NAND flash parameters */ ns->busw = chip->options & NAND_BUSWIDTH_16 ? 16 : 8; diff --git a/drivers/mtd/nand/raw/ndfc.c b/drivers/mtd/nand/raw/ndfc.c index 19b4cb2d1c6e..d49a7a17146c 100644 --- a/drivers/mtd/nand/raw/ndfc.c +++ b/drivers/mtd/nand/raw/ndfc.c @@ -147,7 +147,7 @@ static int ndfc_chip_init(struct ndfc_controller *ndfc, chip->legacy.cmd_ctrl = ndfc_hwcontrol; chip->legacy.dev_ready = ndfc_ready; chip->select_chip = ndfc_select_chip; - chip->chip_delay = 50; + chip->legacy.chip_delay = 50; chip->controller = &ndfc->ndfc_control; chip->legacy.read_buf = ndfc_read_buf; chip->legacy.write_buf = ndfc_write_buf; diff --git a/drivers/mtd/nand/raw/nuc900_nand.c b/drivers/mtd/nand/raw/nuc900_nand.c index 208b6de67510..38b1994e7ed3 100644 --- a/drivers/mtd/nand/raw/nuc900_nand.c +++ b/drivers/mtd/nand/raw/nuc900_nand.c @@ -177,7 +177,7 @@ static void nuc900_nand_command_lp(struct nand_chip *chip, case NAND_CMD_RESET: if (chip->legacy.dev_ready) break; - udelay(chip->chip_delay); + udelay(chip->legacy.chip_delay); write_cmd_reg(nand, NAND_CMD_STATUS); write_cmd_reg(nand, command); @@ -197,7 +197,7 @@ static void nuc900_nand_command_lp(struct nand_chip *chip, default: if (!chip->legacy.dev_ready) { - udelay(chip->chip_delay); + udelay(chip->legacy.chip_delay); return; } } @@ -259,7 +259,7 @@ static int nuc900_nand_probe(struct platform_device *pdev) chip->legacy.read_byte = nuc900_nand_read_byte; chip->legacy.write_buf = nuc900_nand_write_buf; chip->legacy.read_buf = nuc900_nand_read_buf; - chip->chip_delay = 50; + chip->legacy.chip_delay = 50; chip->options = 0; chip->ecc.mode = NAND_ECC_SOFT; chip->ecc.algo = NAND_ECC_HAMMING; diff --git a/drivers/mtd/nand/raw/omap2.c b/drivers/mtd/nand/raw/omap2.c index 5e1e7ced0d9e..886d05c391ef 100644 --- a/drivers/mtd/nand/raw/omap2.c +++ b/drivers/mtd/nand/raw/omap2.c @@ -2248,10 +2248,10 @@ static int omap_nand_probe(struct platform_device *pdev) */ if (info->ready_gpiod) { nand_chip->legacy.dev_ready = omap_dev_ready; - nand_chip->chip_delay = 0; + nand_chip->legacy.chip_delay = 0; } else { nand_chip->legacy.waitfunc = omap_wait; - nand_chip->chip_delay = 50; + nand_chip->legacy.chip_delay = 50; } if (info->flash_bbt) diff --git a/drivers/mtd/nand/raw/orion_nand.c b/drivers/mtd/nand/raw/orion_nand.c index bf288c3c930b..d27b39a7223c 100644 --- a/drivers/mtd/nand/raw/orion_nand.c +++ b/drivers/mtd/nand/raw/orion_nand.c @@ -143,7 +143,7 @@ static int __init orion_nand_probe(struct platform_device *pdev) nc->ecc.algo = NAND_ECC_HAMMING; if (board->chip_delay) - nc->chip_delay = board->chip_delay; + nc->legacy.chip_delay = board->chip_delay; WARN(board->width > 16, "%d bit bus width out of range", diff --git a/drivers/mtd/nand/raw/oxnas_nand.c b/drivers/mtd/nand/raw/oxnas_nand.c index fb0ebb296f6c..0e52dc29141c 100644 --- a/drivers/mtd/nand/raw/oxnas_nand.c +++ b/drivers/mtd/nand/raw/oxnas_nand.c @@ -136,7 +136,7 @@ static int oxnas_nand_probe(struct platform_device *pdev) chip->legacy.read_buf = oxnas_nand_read_buf; chip->legacy.read_byte = oxnas_nand_read_byte; chip->legacy.write_buf = oxnas_nand_write_buf; - chip->chip_delay = 30; + chip->legacy.chip_delay = 30; /* Scan to find existence of the device */ err = nand_scan(chip, 1); diff --git a/drivers/mtd/nand/raw/pasemi_nand.c b/drivers/mtd/nand/raw/pasemi_nand.c index e9a4e82bfb34..643cd22af009 100644 --- a/drivers/mtd/nand/raw/pasemi_nand.c +++ b/drivers/mtd/nand/raw/pasemi_nand.c @@ -143,7 +143,7 @@ static int pasemi_nand_probe(struct platform_device *ofdev) chip->legacy.dev_ready = pasemi_device_ready; chip->legacy.read_buf = pasemi_read_buf; chip->legacy.write_buf = pasemi_write_buf; - chip->chip_delay = 0; + chip->legacy.chip_delay = 0; chip->ecc.mode = NAND_ECC_SOFT; chip->ecc.algo = NAND_ECC_HAMMING; diff --git a/drivers/mtd/nand/raw/plat_nand.c b/drivers/mtd/nand/raw/plat_nand.c index 6cce01d09364..156c9150fec4 100644 --- a/drivers/mtd/nand/raw/plat_nand.c +++ b/drivers/mtd/nand/raw/plat_nand.c @@ -67,7 +67,7 @@ static int plat_nand_probe(struct platform_device *pdev) data->chip.select_chip = pdata->ctrl.select_chip; data->chip.legacy.write_buf = pdata->ctrl.write_buf; data->chip.legacy.read_buf = pdata->ctrl.read_buf; - data->chip.chip_delay = pdata->chip.chip_delay; + data->chip.legacy.chip_delay = pdata->chip.chip_delay; data->chip.options |= pdata->chip.options; data->chip.bbt_options |= pdata->chip.bbt_options; diff --git a/drivers/mtd/nand/raw/s3c2410.c b/drivers/mtd/nand/raw/s3c2410.c index 87b5162857f8..d2e42e9d0e8c 100644 --- a/drivers/mtd/nand/raw/s3c2410.c +++ b/drivers/mtd/nand/raw/s3c2410.c @@ -867,7 +867,7 @@ static void s3c2410_nand_init_chip(struct s3c2410_nand_info *info, chip->legacy.write_buf = s3c2410_nand_write_buf; chip->legacy.read_buf = s3c2410_nand_read_buf; chip->select_chip = s3c2410_nand_select_chip; - chip->chip_delay = 50; + chip->legacy.chip_delay = 50; nand_set_controller_data(chip, nmtd); chip->options = set->options; chip->controller = &info->controller; diff --git a/drivers/mtd/nand/raw/sh_flctl.c b/drivers/mtd/nand/raw/sh_flctl.c index 40a4159924a7..c0c0798f268f 100644 --- a/drivers/mtd/nand/raw/sh_flctl.c +++ b/drivers/mtd/nand/raw/sh_flctl.c @@ -1178,7 +1178,7 @@ static int flctl_probe(struct platform_device *pdev) /* Set address of hardware control function */ /* 20 us command delay time */ - nand->chip_delay = 20; + nand->legacy.chip_delay = 20; nand->legacy.read_byte = flctl_read_byte; nand->legacy.write_buf = flctl_write_buf; diff --git a/drivers/mtd/nand/raw/sharpsl.c b/drivers/mtd/nand/raw/sharpsl.c index 3d14408cbbce..c82f26c8b58c 100644 --- a/drivers/mtd/nand/raw/sharpsl.c +++ b/drivers/mtd/nand/raw/sharpsl.c @@ -159,7 +159,7 @@ static int sharpsl_nand_probe(struct platform_device *pdev) this->legacy.cmd_ctrl = sharpsl_nand_hwcontrol; this->legacy.dev_ready = sharpsl_nand_dev_ready; /* 15 us command delay time */ - this->chip_delay = 15; + this->legacy.chip_delay = 15; /* set eccmode using hardware ECC */ this->ecc.mode = NAND_ECC_HW; this->ecc.size = 256; diff --git a/drivers/mtd/nand/raw/socrates_nand.c b/drivers/mtd/nand/raw/socrates_nand.c index 604ef7508f14..8be9a50c7880 100644 --- a/drivers/mtd/nand/raw/socrates_nand.c +++ b/drivers/mtd/nand/raw/socrates_nand.c @@ -162,7 +162,7 @@ static int socrates_nand_probe(struct platform_device *ofdev) nand_chip->ecc.algo = NAND_ECC_HAMMING; /* TODO: I have no idea what real delay is. */ - nand_chip->chip_delay = 20; /* 20us command delay time */ + nand_chip->legacy.chip_delay = 20; /* 20us command delay time */ dev_set_drvdata(&ofdev->dev, host); diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c index 37e23aec4bce..51b1a548064b 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -1912,7 +1912,7 @@ static int sunxi_nand_chip_init(struct device *dev, struct sunxi_nfc *nfc, nand = &chip->nand; /* Default tR value specified in the ONFI spec (chapter 4.15.1) */ - nand->chip_delay = 200; + nand->legacy.chip_delay = 200; nand->controller = &nfc->controller; nand->controller->ops = &sunxi_nand_controller_ops; diff --git a/drivers/mtd/nand/raw/tmio_nand.c b/drivers/mtd/nand/raw/tmio_nand.c index 7e49272ecef6..3297621241d2 100644 --- a/drivers/mtd/nand/raw/tmio_nand.c +++ b/drivers/mtd/nand/raw/tmio_nand.c @@ -422,7 +422,7 @@ static int tmio_probe(struct platform_device *dev) nand_chip->badblock_pattern = data->badblock_pattern; /* 15 us command delay time */ - nand_chip->chip_delay = 15; + nand_chip->legacy.chip_delay = 15; retval = devm_request_irq(&dev->dev, irq, &tmio_irq, 0, dev_name(&dev->dev), tmio); diff --git a/drivers/mtd/nand/raw/txx9ndfmc.c b/drivers/mtd/nand/raw/txx9ndfmc.c index 46cfb11c5502..3a99c8e3f944 100644 --- a/drivers/mtd/nand/raw/txx9ndfmc.c +++ b/drivers/mtd/nand/raw/txx9ndfmc.c @@ -334,7 +334,7 @@ static int __init txx9ndfmc_probe(struct platform_device *dev) chip->ecc.hwctl = txx9ndfmc_enable_hwecc; chip->ecc.mode = NAND_ECC_HW; chip->ecc.strength = 1; - chip->chip_delay = 100; + chip->legacy.chip_delay = 100; chip->controller = &drvdata->controller; nand_set_controller_data(chip, txx9_priv); diff --git a/drivers/mtd/nand/raw/xway_nand.c b/drivers/mtd/nand/raw/xway_nand.c index dcce487f6517..a234a5cb4868 100644 --- a/drivers/mtd/nand/raw/xway_nand.c +++ b/drivers/mtd/nand/raw/xway_nand.c @@ -180,7 +180,7 @@ static int xway_nand_probe(struct platform_device *pdev) data->chip.legacy.write_buf = xway_write_buf; data->chip.legacy.read_buf = xway_read_buf; data->chip.legacy.read_byte = xway_read_byte; - data->chip.chip_delay = 30; + data->chip.legacy.chip_delay = 30; data->chip.ecc.mode = NAND_ECC_SOFT; data->chip.ecc.algo = NAND_ECC_HAMMING; diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h index 02ac70a30c63..992d78d29674 100644 --- a/include/linux/mtd/rawnand.h +++ b/include/linux/mtd/rawnand.h @@ -1192,6 +1192,8 @@ int nand_op_parser_exec_op(struct nand_chip *chip, * @erase: erase function * @set_features: set the NAND chip features * @get_features: get the NAND chip features + * @chip_delay: chip dependent delay for transferring data from array to read + * regs (tR). * * If you look at this structure you're already wrong. These fields/hooks are * all deprecated. @@ -1215,6 +1217,7 @@ struct nand_legacy { u8 *subfeature_para); int (*get_features)(struct nand_chip *chip, int feature_addr, u8 *subfeature_para); + int chip_delay; }; /** @@ -1236,8 +1239,6 @@ struct nand_legacy { * @buf_align: minimum buffer alignment required by a platform * @dummy_controller: dummy controller implementation for drivers that can * only control a single chip - * @chip_delay: [BOARDSPECIFIC] chip dependent delay for transferring - * data from array to read regs (tR). * @state: [INTERN] the current state of the NAND device * @oob_poi: "poison value buffer," used for laying out OOB data * before writing @@ -1317,7 +1318,6 @@ struct nand_chip { int (*setup_data_interface)(struct nand_chip *chip, int chipnr, const struct nand_data_interface *conf); - int chip_delay; unsigned int options; unsigned int bbt_options; From 0b4e61c1c26e0f34c9a5f6c35edee16cc26a72fd Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Fri, 7 Sep 2018 00:38:42 +0200 Subject: [PATCH 279/302] mtd: rawnand: Move function prototypes after struct declarations Move nand_scan[_with_ids]() and nand_wait_ready() at the end of the file where all function prototype lies. This will also allow us to get rid of the nand_flash_dev forward declaration. Signed-off-by: Boris Brezillon Signed-off-by: Miquel Raynal --- include/linux/mtd/rawnand.h | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h index 992d78d29674..15183b73fed2 100644 --- a/include/linux/mtd/rawnand.h +++ b/include/linux/mtd/rawnand.h @@ -27,18 +27,6 @@ struct nand_chip; struct nand_flash_dev; -/* Scan and identify a NAND device */ -int nand_scan_with_ids(struct nand_chip *chip, unsigned int max_chips, - struct nand_flash_dev *ids); - -static inline int nand_scan(struct nand_chip *chip, unsigned int max_chips) -{ - return nand_scan_with_ids(chip, max_chips, NULL); -} - -/* Internal helper for board drivers which need to override command function */ -void nand_wait_ready(struct nand_chip *chip); - /* The maximum number of NAND chips in an array */ #define NAND_MAX_CHIPS 8 @@ -1739,6 +1727,18 @@ int nand_read_data_op(struct nand_chip *chip, void *buf, unsigned int len, int nand_write_data_op(struct nand_chip *chip, const void *buf, unsigned int len, bool force_8bit); +/* Scan and identify a NAND device */ +int nand_scan_with_ids(struct nand_chip *chip, unsigned int max_chips, + struct nand_flash_dev *ids); + +static inline int nand_scan(struct nand_chip *chip, unsigned int max_chips) +{ + return nand_scan_with_ids(chip, max_chips, NULL); +} + +/* Internal helper for board drivers which need to override command function */ +void nand_wait_ready(struct nand_chip *chip); + /* * Free resources held by the NAND device, must be called on error after a * sucessful nand_scan(). From 394938eadff2b875c099529452ffb7f7303f1547 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Fri, 7 Sep 2018 00:38:43 +0200 Subject: [PATCH 280/302] mtd: rawnand: Get rid of nand_flash_dev forward declation nand_scan[with_ids]() have been moved at the end of the file. We can now get rid of of the nand_flash_dev forward declaration. Signed-off-by: Boris Brezillon Signed-off-by: Miquel Raynal --- include/linux/mtd/rawnand.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h index 15183b73fed2..768415ed1159 100644 --- a/include/linux/mtd/rawnand.h +++ b/include/linux/mtd/rawnand.h @@ -25,7 +25,6 @@ #include struct nand_chip; -struct nand_flash_dev; /* The maximum number of NAND chips in an array */ #define NAND_MAX_CHIPS 8 From d16397d57a90d8c35bef3d8104460bf18e111fa7 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Fri, 7 Sep 2018 00:38:44 +0200 Subject: [PATCH 281/302] mtd: rawnand: Get rid of the duplicate nand_chip forward declaration There's already a forward declaration of nand_chip at the beginning of the file. Get rid of this one. Signed-off-by: Boris Brezillon Signed-off-by: Miquel Raynal --- include/linux/mtd/rawnand.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h index 768415ed1159..608279104aae 100644 --- a/include/linux/mtd/rawnand.h +++ b/include/linux/mtd/rawnand.h @@ -210,9 +210,6 @@ enum nand_ecc_algo { #define NAND_CI_CELLTYPE_MSK 0x0C #define NAND_CI_CELLTYPE_SHIFT 2 -/* Keep gcc happy */ -struct nand_chip; - /* ONFI version bits */ #define ONFI_VERSION_1_0 BIT(1) #define ONFI_VERSION_2_0 BIT(2) From 4114f97c41cd3992724f450f595417e4432737a0 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Fri, 7 Sep 2018 00:38:45 +0200 Subject: [PATCH 282/302] mtd: rawnand: Get rid of a few unused definitions Those definitions are not used, let's remove them. Signed-off-by: Boris Brezillon Signed-off-by: Miquel Raynal --- drivers/mtd/nand/raw/nand_timings.c | 14 -------------- include/linux/mtd/rawnand.h | 8 -------- 2 files changed, 22 deletions(-) diff --git a/drivers/mtd/nand/raw/nand_timings.c b/drivers/mtd/nand/raw/nand_timings.c index ebc7b5f76f77..cb4f0007b65c 100644 --- a/drivers/mtd/nand/raw/nand_timings.c +++ b/drivers/mtd/nand/raw/nand_timings.c @@ -270,20 +270,6 @@ static const struct nand_data_interface onfi_sdr_timings[] = { }, }; -/** - * onfi_async_timing_mode_to_sdr_timings - [NAND Interface] Retrieve NAND - * timings according to the given ONFI timing mode - * @mode: ONFI timing mode - */ -const struct nand_sdr_timings *onfi_async_timing_mode_to_sdr_timings(int mode) -{ - if (mode < 0 || mode >= ARRAY_SIZE(onfi_sdr_timings)) - return ERR_PTR(-EINVAL); - - return &onfi_sdr_timings[mode].timings.sdr; -} -EXPORT_SYMBOL(onfi_async_timing_mode_to_sdr_timings); - /** * onfi_fill_data_interface - [NAND Interface] Initialize a data interface from * given ONFI mode diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h index 608279104aae..8aa8b57ca4b1 100644 --- a/include/linux/mtd/rawnand.h +++ b/include/linux/mtd/rawnand.h @@ -119,10 +119,6 @@ enum nand_ecc_algo { #define NAND_ECC_GENERIC_ERASED_CHECK BIT(0) #define NAND_ECC_MAXIMIZE BIT(1) -/* Bit mask for flags passed to do_nand_read_ecc */ -#define NAND_GET_DEVICE 0x80 - - /* * Option constants for bizarre disfunctionality and real * features. @@ -163,9 +159,7 @@ enum nand_ecc_algo { #define NAND_SAMSUNG_LP_OPTIONS NAND_CACHEPRG /* Macros to identify the above */ -#define NAND_HAS_CACHEPROG(chip) ((chip->options & NAND_CACHEPRG)) #define NAND_HAS_SUBPAGE_READ(chip) ((chip->options & NAND_SUBPAGE_READ)) -#define NAND_HAS_SUBPAGE_WRITE(chip) !((chip)->options & NAND_NO_SUBPAGE_WRITE) /* Non chip related options */ /* This option skips the bbt scan during initialization. */ @@ -1649,8 +1643,6 @@ static inline int nand_opcode_8bits(unsigned int command) return 0; } -/* get timing characteristics from ONFI timing mode. */ -const struct nand_sdr_timings *onfi_async_timing_mode_to_sdr_timings(int mode); int nand_check_erased_ecc_chunk(void *data, int datalen, void *ecc, int ecclen, From c7921bb32ab616462cefb9c2f3dd81d85d32b948 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Fri, 7 Sep 2018 00:38:46 +0200 Subject: [PATCH 283/302] mtd: rawnand: Move platform_nand_xxx definitions out of rawnand.h platform_nand_xxx definitions are just used by the plat_nand driver. Let's move those definitions out of the core/driver-agnostic rawnand.h header. Signed-off-by: Boris Brezillon Signed-off-by: Miquel Raynal --- arch/arm/mach-ep93xx/snappercl15.c | 3 +- arch/arm/mach-ep93xx/ts72xx.c | 3 +- arch/arm/mach-imx/mach-qong.c | 2 +- arch/arm/mach-ixp4xx/ixdp425-setup.c | 1 + arch/arm/mach-omap1/board-fsample.c | 3 +- arch/arm/mach-omap1/board-h2.c | 3 +- arch/arm/mach-omap1/board-h3.c | 2 +- arch/arm/mach-omap1/board-perseus2.c | 3 +- arch/arm/mach-orion5x/ts78xx-setup.c | 3 +- arch/arm/mach-pxa/balloon3.c | 3 +- arch/arm/mach-pxa/em-x270.c | 3 +- arch/arm/mach-pxa/palmtx.c | 3 +- arch/mips/alchemy/devboards/db1200.c | 3 +- arch/mips/alchemy/devboards/db1300.c | 3 +- arch/mips/alchemy/devboards/db1550.c | 3 +- arch/mips/netlogic/xlr/platform-flash.c | 3 +- arch/mips/pnx833x/common/platform.c | 3 +- arch/mips/rb532/devices.c | 3 +- arch/sh/boards/mach-migor/setup.c | 2 +- drivers/mtd/nand/raw/plat_nand.c | 3 +- include/linux/mtd/platnand.h | 74 +++++++++++++++++++++++++ include/linux/mtd/rawnand.h | 60 -------------------- 22 files changed, 94 insertions(+), 95 deletions(-) create mode 100644 include/linux/mtd/platnand.h diff --git a/arch/arm/mach-ep93xx/snappercl15.c b/arch/arm/mach-ep93xx/snappercl15.c index 1dad83a0bc5b..cf0cb58b3454 100644 --- a/arch/arm/mach-ep93xx/snappercl15.c +++ b/arch/arm/mach-ep93xx/snappercl15.c @@ -23,8 +23,7 @@ #include #include -#include -#include +#include #include #include diff --git a/arch/arm/mach-ep93xx/ts72xx.c b/arch/arm/mach-ep93xx/ts72xx.c index 188bf02595c5..c6a533699b00 100644 --- a/arch/arm/mach-ep93xx/ts72xx.c +++ b/arch/arm/mach-ep93xx/ts72xx.c @@ -16,8 +16,7 @@ #include #include #include -#include -#include +#include #include #include #include diff --git a/arch/arm/mach-imx/mach-qong.c b/arch/arm/mach-imx/mach-qong.c index 48972944bb95..5c5df8ca38dd 100644 --- a/arch/arm/mach-imx/mach-qong.c +++ b/arch/arm/mach-imx/mach-qong.c @@ -18,7 +18,7 @@ #include #include #include -#include +#include #include #include diff --git a/arch/arm/mach-ixp4xx/ixdp425-setup.c b/arch/arm/mach-ixp4xx/ixdp425-setup.c index 797e7edc7124..57d7df79d838 100644 --- a/arch/arm/mach-ixp4xx/ixdp425-setup.c +++ b/arch/arm/mach-ixp4xx/ixdp425-setup.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include diff --git a/arch/arm/mach-omap1/board-fsample.c b/arch/arm/mach-omap1/board-fsample.c index e9f512a0602e..4a0a66815ca0 100644 --- a/arch/arm/mach-omap1/board-fsample.c +++ b/arch/arm/mach-omap1/board-fsample.c @@ -16,8 +16,7 @@ #include #include #include -#include -#include +#include #include #include #include diff --git a/arch/arm/mach-omap1/board-h2.c b/arch/arm/mach-omap1/board-h2.c index d5dd2acd6f78..9d9a6ca15df0 100644 --- a/arch/arm/mach-omap1/board-h2.c +++ b/arch/arm/mach-omap1/board-h2.c @@ -24,8 +24,7 @@ #include #include #include -#include -#include +#include #include #include #include diff --git a/arch/arm/mach-omap1/board-h3.c b/arch/arm/mach-omap1/board-h3.c index a75856fe4259..cd6e02c5c01a 100644 --- a/arch/arm/mach-omap1/board-h3.c +++ b/arch/arm/mach-omap1/board-h3.c @@ -23,7 +23,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/arch/arm/mach-omap1/board-perseus2.c b/arch/arm/mach-omap1/board-perseus2.c index c61c7c7520ca..06a584fef5b8 100644 --- a/arch/arm/mach-omap1/board-perseus2.c +++ b/arch/arm/mach-omap1/board-perseus2.c @@ -16,8 +16,7 @@ #include #include #include -#include -#include +#include #include #include #include diff --git a/arch/arm/mach-orion5x/ts78xx-setup.c b/arch/arm/mach-orion5x/ts78xx-setup.c index aac2c6eb35e2..fda9b75c3a33 100644 --- a/arch/arm/mach-orion5x/ts78xx-setup.c +++ b/arch/arm/mach-orion5x/ts78xx-setup.c @@ -16,8 +16,7 @@ #include #include #include -#include -#include +#include #include #include #include diff --git a/arch/arm/mach-pxa/balloon3.c b/arch/arm/mach-pxa/balloon3.c index 256e60c38a6d..c52c081eb6d9 100644 --- a/arch/arm/mach-pxa/balloon3.c +++ b/arch/arm/mach-pxa/balloon3.c @@ -25,11 +25,10 @@ #include #include #include -#include #include #include #include -#include +#include #include #include diff --git a/arch/arm/mach-pxa/em-x270.c b/arch/arm/mach-pxa/em-x270.c index 3acb945a2628..c30d20e1fb7a 100644 --- a/arch/arm/mach-pxa/em-x270.c +++ b/arch/arm/mach-pxa/em-x270.c @@ -15,8 +15,7 @@ #include #include -#include -#include +#include #include #include #include diff --git a/arch/arm/mach-pxa/palmtx.c b/arch/arm/mach-pxa/palmtx.c index 36ea32c1bbcc..1d06a8e91d8f 100644 --- a/arch/arm/mach-pxa/palmtx.c +++ b/arch/arm/mach-pxa/palmtx.c @@ -28,8 +28,7 @@ #include #include #include -#include -#include +#include #include #include diff --git a/arch/mips/alchemy/devboards/db1200.c b/arch/mips/alchemy/devboards/db1200.c index 97dc74f7f41a..4bf02f96ab7f 100644 --- a/arch/mips/alchemy/devboards/db1200.c +++ b/arch/mips/alchemy/devboards/db1200.c @@ -29,8 +29,7 @@ #include #include #include -#include -#include +#include #include #include #include diff --git a/arch/mips/alchemy/devboards/db1300.c b/arch/mips/alchemy/devboards/db1300.c index b813dc1c1682..ad7dd8e89598 100644 --- a/arch/mips/alchemy/devboards/db1300.c +++ b/arch/mips/alchemy/devboards/db1300.c @@ -19,8 +19,7 @@ #include #include #include -#include -#include +#include #include #include #include diff --git a/arch/mips/alchemy/devboards/db1550.c b/arch/mips/alchemy/devboards/db1550.c index 65f6b7184fbe..7700ad0b93b4 100644 --- a/arch/mips/alchemy/devboards/db1550.c +++ b/arch/mips/alchemy/devboards/db1550.c @@ -13,8 +13,7 @@ #include #include #include -#include -#include +#include #include #include #include diff --git a/arch/mips/netlogic/xlr/platform-flash.c b/arch/mips/netlogic/xlr/platform-flash.c index 4f76b85b44c9..cf9162284b07 100644 --- a/arch/mips/netlogic/xlr/platform-flash.c +++ b/arch/mips/netlogic/xlr/platform-flash.c @@ -19,8 +19,7 @@ #include #include -#include -#include +#include #include #include diff --git a/arch/mips/pnx833x/common/platform.c b/arch/mips/pnx833x/common/platform.c index 33d0f070b33d..dafbf027fad0 100644 --- a/arch/mips/pnx833x/common/platform.c +++ b/arch/mips/pnx833x/common/platform.c @@ -30,8 +30,7 @@ #include #include #include -#include -#include +#include #include #include diff --git a/arch/mips/rb532/devices.c b/arch/mips/rb532/devices.c index 02a9e042fb44..2b23ad640f39 100644 --- a/arch/mips/rb532/devices.c +++ b/arch/mips/rb532/devices.c @@ -20,9 +20,8 @@ #include #include #include -#include +#include #include -#include #include #include #include diff --git a/arch/sh/boards/mach-migor/setup.c b/arch/sh/boards/mach-migor/setup.c index ebcc4d5a67ce..f4ad33c6d2aa 100644 --- a/arch/sh/boards/mach-migor/setup.c +++ b/arch/sh/boards/mach-migor/setup.c @@ -14,7 +14,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/drivers/mtd/nand/raw/plat_nand.c b/drivers/mtd/nand/raw/plat_nand.c index 156c9150fec4..86c536ddaf24 100644 --- a/drivers/mtd/nand/raw/plat_nand.c +++ b/drivers/mtd/nand/raw/plat_nand.c @@ -15,8 +15,7 @@ #include #include #include -#include -#include +#include struct plat_nand_data { struct nand_chip chip; diff --git a/include/linux/mtd/platnand.h b/include/linux/mtd/platnand.h new file mode 100644 index 000000000000..bc11eb6b593b --- /dev/null +++ b/include/linux/mtd/platnand.h @@ -0,0 +1,74 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright © 2000-2010 David Woodhouse + * Steven J. Hill + * Thomas Gleixner + * + * Contains all platform NAND related definitions. + */ + +#ifndef __LINUX_MTD_PLATNAND_H +#define __LINUX_MTD_PLATNAND_H + +#include +#include +#include + +/** + * struct platform_nand_chip - chip level device structure + * @nr_chips: max. number of chips to scan for + * @chip_offset: chip number offset + * @nr_partitions: number of partitions pointed to by partitions (or zero) + * @partitions: mtd partition list + * @chip_delay: R/B delay value in us + * @options: Option flags, e.g. 16bit buswidth + * @bbt_options: BBT option flags, e.g. NAND_BBT_USE_FLASH + * @part_probe_types: NULL-terminated array of probe types + */ +struct platform_nand_chip { + int nr_chips; + int chip_offset; + int nr_partitions; + struct mtd_partition *partitions; + int chip_delay; + unsigned int options; + unsigned int bbt_options; + const char **part_probe_types; +}; + +/** + * struct platform_nand_ctrl - controller level device structure + * @probe: platform specific function to probe/setup hardware + * @remove: platform specific function to remove/teardown hardware + * @dev_ready: platform specific function to read ready/busy pin + * @select_chip: platform specific chip select function + * @cmd_ctrl: platform specific function for controlling + * ALE/CLE/nCE. Also used to write command and address + * @write_buf: platform specific function for write buffer + * @read_buf: platform specific function for read buffer + * @priv: private data to transport driver specific settings + * + * All fields are optional and depend on the hardware driver requirements + */ +struct platform_nand_ctrl { + int (*probe)(struct platform_device *pdev); + void (*remove)(struct platform_device *pdev); + int (*dev_ready)(struct nand_chip *chip); + void (*select_chip)(struct nand_chip *chip, int cs); + void (*cmd_ctrl)(struct nand_chip *chip, int dat, unsigned int ctrl); + void (*write_buf)(struct nand_chip *chip, const uint8_t *buf, int len); + void (*read_buf)(struct nand_chip *chip, uint8_t *buf, int len); + void *priv; +}; + +/** + * struct platform_nand_data - container structure for platform-specific data + * @chip: chip level chip structure + * @ctrl: controller level device structure + */ +struct platform_nand_data { + struct platform_nand_chip chip; + struct platform_nand_ctrl ctrl; +}; + +#endif /* __LINUX_MTD_PLATNAND_H */ diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h index 8aa8b57ca4b1..04e11a314e9c 100644 --- a/include/linux/mtd/rawnand.h +++ b/include/linux/mtd/rawnand.h @@ -1540,66 +1540,6 @@ int nand_isbad_bbt(struct nand_chip *chip, loff_t offs, int allowbbt); int nand_erase_nand(struct nand_chip *chip, struct erase_info *instr, int allowbbt); -/** - * struct platform_nand_chip - chip level device structure - * @nr_chips: max. number of chips to scan for - * @chip_offset: chip number offset - * @nr_partitions: number of partitions pointed to by partitions (or zero) - * @partitions: mtd partition list - * @chip_delay: R/B delay value in us - * @options: Option flags, e.g. 16bit buswidth - * @bbt_options: BBT option flags, e.g. NAND_BBT_USE_FLASH - * @part_probe_types: NULL-terminated array of probe types - */ -struct platform_nand_chip { - int nr_chips; - int chip_offset; - int nr_partitions; - struct mtd_partition *partitions; - int chip_delay; - unsigned int options; - unsigned int bbt_options; - const char **part_probe_types; -}; - -/* Keep gcc happy */ -struct platform_device; - -/** - * struct platform_nand_ctrl - controller level device structure - * @probe: platform specific function to probe/setup hardware - * @remove: platform specific function to remove/teardown hardware - * @dev_ready: platform specific function to read ready/busy pin - * @select_chip: platform specific chip select function - * @cmd_ctrl: platform specific function for controlling - * ALE/CLE/nCE. Also used to write command and address - * @write_buf: platform specific function for write buffer - * @read_buf: platform specific function for read buffer - * @priv: private data to transport driver specific settings - * - * All fields are optional and depend on the hardware driver requirements - */ -struct platform_nand_ctrl { - int (*probe)(struct platform_device *pdev); - void (*remove)(struct platform_device *pdev); - int (*dev_ready)(struct nand_chip *chip); - void (*select_chip)(struct nand_chip *chip, int cs); - void (*cmd_ctrl)(struct nand_chip *chip, int dat, unsigned int ctrl); - void (*write_buf)(struct nand_chip *chip, const uint8_t *buf, int len); - void (*read_buf)(struct nand_chip *chip, uint8_t *buf, int len); - void *priv; -}; - -/** - * struct platform_nand_data - container structure for platform-specific data - * @chip: chip level chip structure - * @ctrl: controller level device structure - */ -struct platform_nand_data { - struct platform_nand_chip chip; - struct platform_nand_ctrl ctrl; -}; - /* return the supported asynchronous timing mode. */ static inline int onfi_get_async_timing_mode(struct nand_chip *chip) { From 462f35d3e5e805657b48c76d3e7dd1c37e0ac62c Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Fri, 7 Sep 2018 00:38:47 +0200 Subject: [PATCH 284/302] mtd: rawnand: Inline onfi_get_async_timing_mode() onfi_get_async_timing_mode() is only used in one place inside nand_base.c. Let's inline the code and kill the helper. Signed-off-by: Boris Brezillon Signed-off-by: Miquel Raynal --- drivers/mtd/nand/raw/nand_base.c | 5 +++-- include/linux/mtd/rawnand.h | 9 --------- 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c index 2f8bbc3bca7a..136ccdc61a06 100644 --- a/drivers/mtd/nand/raw/nand_base.c +++ b/drivers/mtd/nand/raw/nand_base.c @@ -1310,8 +1310,9 @@ static int nand_init_data_interface(struct nand_chip *chip) * if the NAND does not support ONFI, fallback to the default ONFI * timing mode. */ - modes = onfi_get_async_timing_mode(chip); - if (modes == ONFI_TIMING_MODE_UNKNOWN) { + if (chip->parameters.onfi) { + modes = chip->parameters.onfi->async_timing_mode; + } else { if (!chip->onfi_timing_mode_default) return 0; diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h index 04e11a314e9c..7f0e3dc222ed 100644 --- a/include/linux/mtd/rawnand.h +++ b/include/linux/mtd/rawnand.h @@ -1540,15 +1540,6 @@ int nand_isbad_bbt(struct nand_chip *chip, loff_t offs, int allowbbt); int nand_erase_nand(struct nand_chip *chip, struct erase_info *instr, int allowbbt); -/* return the supported asynchronous timing mode. */ -static inline int onfi_get_async_timing_mode(struct nand_chip *chip) -{ - if (!chip->parameters.onfi) - return ONFI_TIMING_MODE_UNKNOWN; - - return chip->parameters.onfi->async_timing_mode; -} - int onfi_fill_data_interface(struct nand_chip *chip, enum nand_data_interface_type type, int timing_mode); From 348d56a8c6067f3b2f1799d6f050f3be4bf5904b Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Fri, 7 Sep 2018 00:38:48 +0200 Subject: [PATCH 285/302] mtd: rawnand: Keep all internal stuff private A lot of things defined in rawnand.h should not be exposed to NAND controller drivers and should only be shared by core files. Create the drivers/mtd/nand/raw/internals.h header to store such definitions, and move all private defs to this header. Also remove EXPORT_SYMBOLS() on functions that are not supposed to be exposed. Signed-off-by: Boris Brezillon Signed-off-by: Miquel Raynal --- drivers/mtd/nand/raw/internals.h | 98 ++++++++++++++++++++++++++++ drivers/mtd/nand/raw/nand_amd.c | 2 +- drivers/mtd/nand/raw/nand_base.c | 21 +++--- drivers/mtd/nand/raw/nand_bbt.c | 3 +- drivers/mtd/nand/raw/nand_hynix.c | 3 +- drivers/mtd/nand/raw/nand_ids.c | 4 +- drivers/mtd/nand/raw/nand_macronix.c | 2 +- drivers/mtd/nand/raw/nand_micron.c | 3 +- drivers/mtd/nand/raw/nand_samsung.c | 2 +- drivers/mtd/nand/raw/nand_timings.c | 4 +- drivers/mtd/nand/raw/nand_toshiba.c | 2 +- include/linux/mtd/rawnand.h | 96 --------------------------- 12 files changed, 123 insertions(+), 117 deletions(-) create mode 100644 drivers/mtd/nand/raw/internals.h diff --git a/drivers/mtd/nand/raw/internals.h b/drivers/mtd/nand/raw/internals.h new file mode 100644 index 000000000000..1d2edddb6127 --- /dev/null +++ b/drivers/mtd/nand/raw/internals.h @@ -0,0 +1,98 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2018 - Bootlin + * + * Author: Boris Brezillon + * + * Header containing internal definitions to be used only by core files. + * NAND controller drivers should not include this file. + */ + +#ifndef __LINUX_RAWNAND_INTERNALS +#define __LINUX_RAWNAND_INTERNALS + +#include + +/* + * NAND Flash Manufacturer ID Codes + */ +#define NAND_MFR_TOSHIBA 0x98 +#define NAND_MFR_ESMT 0xc8 +#define NAND_MFR_SAMSUNG 0xec +#define NAND_MFR_FUJITSU 0x04 +#define NAND_MFR_NATIONAL 0x8f +#define NAND_MFR_RENESAS 0x07 +#define NAND_MFR_STMICRO 0x20 +#define NAND_MFR_HYNIX 0xad +#define NAND_MFR_MICRON 0x2c +#define NAND_MFR_AMD 0x01 +#define NAND_MFR_MACRONIX 0xc2 +#define NAND_MFR_EON 0x92 +#define NAND_MFR_SANDISK 0x45 +#define NAND_MFR_INTEL 0x89 +#define NAND_MFR_ATO 0x9b +#define NAND_MFR_WINBOND 0xef + +/** + * struct nand_manufacturer_ops - NAND Manufacturer operations + * @detect: detect the NAND memory organization and capabilities + * @init: initialize all vendor specific fields (like the ->read_retry() + * implementation) if any. + * @cleanup: the ->init() function may have allocated resources, ->cleanup() + * is here to let vendor specific code release those resources. + * @fixup_onfi_param_page: apply vendor specific fixups to the ONFI parameter + * page. This is called after the checksum is verified. + */ +struct nand_manufacturer_ops { + void (*detect)(struct nand_chip *chip); + int (*init)(struct nand_chip *chip); + void (*cleanup)(struct nand_chip *chip); + void (*fixup_onfi_param_page)(struct nand_chip *chip, + struct nand_onfi_params *p); +}; + +/** + * struct nand_manufacturer - NAND Flash Manufacturer structure + * @name: Manufacturer name + * @id: manufacturer ID code of device. + * @ops: manufacturer operations + */ +struct nand_manufacturer { + int id; + char *name; + const struct nand_manufacturer_ops *ops; +}; + + +extern struct nand_flash_dev nand_flash_ids[]; + +extern const struct nand_manufacturer_ops toshiba_nand_manuf_ops; +extern const struct nand_manufacturer_ops samsung_nand_manuf_ops; +extern const struct nand_manufacturer_ops hynix_nand_manuf_ops; +extern const struct nand_manufacturer_ops micron_nand_manuf_ops; +extern const struct nand_manufacturer_ops amd_nand_manuf_ops; +extern const struct nand_manufacturer_ops macronix_nand_manuf_ops; + +/* Core functions */ +const struct nand_manufacturer *nand_get_manufacturer(u8 id); +int nand_markbad_bbm(struct nand_chip *chip, loff_t ofs); +int nand_erase_nand(struct nand_chip *chip, struct erase_info *instr, + int allowbbt); +int onfi_fill_data_interface(struct nand_chip *chip, + enum nand_data_interface_type type, + int timing_mode); +int nand_get_features(struct nand_chip *chip, int addr, u8 *subfeature_param); +int nand_set_features(struct nand_chip *chip, int addr, u8 *subfeature_param); +int nand_read_page_raw_notsupp(struct nand_chip *chip, u8 *buf, + int oob_required, int page); +int nand_write_page_raw_notsupp(struct nand_chip *chip, const u8 *buf, + int oob_required, int page); +int nand_exit_status_op(struct nand_chip *chip); +void nand_decode_ext_id(struct nand_chip *chip); + +/* BBT functions */ +int nand_markbad_bbt(struct nand_chip *chip, loff_t offs); +int nand_isreserved_bbt(struct nand_chip *chip, loff_t offs); +int nand_isbad_bbt(struct nand_chip *chip, loff_t offs, int allowbbt); + +#endif /* __LINUX_RAWNAND_INTERNALS */ diff --git a/drivers/mtd/nand/raw/nand_amd.c b/drivers/mtd/nand/raw/nand_amd.c index 22f060f38123..890c5b43e03c 100644 --- a/drivers/mtd/nand/raw/nand_amd.c +++ b/drivers/mtd/nand/raw/nand_amd.c @@ -15,7 +15,7 @@ * GNU General Public License for more details. */ -#include +#include "internals.h" static void amd_nand_decode_id(struct nand_chip *chip) { diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c index 136ccdc61a06..d48c588d1abe 100644 --- a/drivers/mtd/nand/raw/nand_base.c +++ b/drivers/mtd/nand/raw/nand_base.c @@ -39,7 +39,6 @@ #include #include #include -#include #include #include #include @@ -48,6 +47,8 @@ #include #include +#include "internals.h" + static int nand_get_device(struct mtd_info *mtd, int new_state); static int nand_do_write_oob(struct mtd_info *mtd, loff_t to, @@ -1319,7 +1320,6 @@ static int nand_init_data_interface(struct nand_chip *chip) modes = GENMASK(chip->onfi_timing_mode_default, 0); } - for (mode = fls(modes) - 1; mode >= 0; mode--) { ret = onfi_fill_data_interface(chip, NAND_SDR_IFACE, mode); if (ret) @@ -2043,7 +2043,6 @@ int nand_exit_status_op(struct nand_chip *chip) return 0; } -EXPORT_SYMBOL_GPL(nand_exit_status_op); /** * nand_erase_op - Do an erase operation @@ -2816,7 +2815,6 @@ int nand_get_features(struct nand_chip *chip, int addr, return nand_get_features_op(chip, addr, subfeature_param); } -EXPORT_SYMBOL_GPL(nand_get_features); /** * nand_set_features - wrapper to perform a SET_FEATURE @@ -2838,7 +2836,6 @@ int nand_set_features(struct nand_chip *chip, int addr, return nand_set_features_op(chip, addr, subfeature_param); } -EXPORT_SYMBOL_GPL(nand_set_features); /** * nand_check_erased_buf - check if a buffer contains (almost) only 0xff data @@ -2985,7 +2982,6 @@ int nand_read_page_raw_notsupp(struct nand_chip *chip, u8 *buf, { return -ENOTSUPP; } -EXPORT_SYMBOL(nand_read_page_raw_notsupp); /** * nand_read_page_raw - [INTERN] read raw page data without ecc @@ -3729,7 +3725,7 @@ EXPORT_SYMBOL(nand_read_oob_std); * @chip: nand chip info structure * @page: page number to read */ -int nand_read_oob_syndrome(struct nand_chip *chip, int page) +static int nand_read_oob_syndrome(struct nand_chip *chip, int page) { struct mtd_info *mtd = nand_to_mtd(chip); int length = mtd->oobsize; @@ -3776,7 +3772,6 @@ int nand_read_oob_syndrome(struct nand_chip *chip, int page) return 0; } -EXPORT_SYMBOL(nand_read_oob_syndrome); /** * nand_write_oob_std - [REPLACEABLE] the most common OOB data write function @@ -3798,7 +3793,7 @@ EXPORT_SYMBOL(nand_write_oob_std); * @chip: nand chip info structure * @page: page number to write */ -int nand_write_oob_syndrome(struct nand_chip *chip, int page) +static int nand_write_oob_syndrome(struct nand_chip *chip, int page) { struct mtd_info *mtd = nand_to_mtd(chip); int chunk = chip->ecc.bytes + chip->ecc.prepad + chip->ecc.postpad; @@ -3864,7 +3859,6 @@ int nand_write_oob_syndrome(struct nand_chip *chip, int page) return nand_prog_page_end_op(chip); } -EXPORT_SYMBOL(nand_write_oob_syndrome); /** * nand_do_read_oob - [INTERN] NAND read out-of-band @@ -3989,7 +3983,6 @@ int nand_write_page_raw_notsupp(struct nand_chip *chip, const u8 *buf, { return -ENOTSUPP; } -EXPORT_SYMBOL(nand_write_page_raw_notsupp); /** * nand_write_page_raw - [INTERN] raw page write function @@ -5579,6 +5572,12 @@ static void nand_manufacturer_cleanup(struct nand_chip *chip) chip->manufacturer.desc->ops->cleanup(chip); } +static const char * +nand_manufacturer_name(const struct nand_manufacturer *manufacturer) +{ + return manufacturer ? manufacturer->name : "Unknown"; +} + /* * Get the flash and manufacturer id and lookup if the type is supported. */ diff --git a/drivers/mtd/nand/raw/nand_bbt.c b/drivers/mtd/nand/raw/nand_bbt.c index b838ecdde8fb..98a826838b60 100644 --- a/drivers/mtd/nand/raw/nand_bbt.c +++ b/drivers/mtd/nand/raw/nand_bbt.c @@ -61,13 +61,14 @@ #include #include #include -#include #include #include #include #include #include +#include "internals.h" + #define BBT_BLOCK_GOOD 0x00 #define BBT_BLOCK_WORN 0x01 #define BBT_BLOCK_RESERVED 0x02 diff --git a/drivers/mtd/nand/raw/nand_hynix.c b/drivers/mtd/nand/raw/nand_hynix.c index 7eec0d96909a..ac1b5c103968 100644 --- a/drivers/mtd/nand/raw/nand_hynix.c +++ b/drivers/mtd/nand/raw/nand_hynix.c @@ -15,10 +15,11 @@ * GNU General Public License for more details. */ -#include #include #include +#include "internals.h" + #define NAND_HYNIX_CMD_SET_PARAMS 0x36 #define NAND_HYNIX_CMD_APPLY_PARAMS 0x16 diff --git a/drivers/mtd/nand/raw/nand_ids.c b/drivers/mtd/nand/raw/nand_ids.c index 5423c3bb388e..12d39ccd1cff 100644 --- a/drivers/mtd/nand/raw/nand_ids.c +++ b/drivers/mtd/nand/raw/nand_ids.c @@ -6,9 +6,11 @@ * published by the Free Software Foundation. * */ -#include + #include +#include "internals.h" + #define LP_OPTIONS 0 #define LP_OPTIONS16 (LP_OPTIONS | NAND_BUSWIDTH_16) diff --git a/drivers/mtd/nand/raw/nand_macronix.c b/drivers/mtd/nand/raw/nand_macronix.c index 49c546c97c6f..358dcc957bb2 100644 --- a/drivers/mtd/nand/raw/nand_macronix.c +++ b/drivers/mtd/nand/raw/nand_macronix.c @@ -15,7 +15,7 @@ * GNU General Public License for more details. */ -#include +#include "internals.h" /* * Macronix AC series does not support using SET/GET_FEATURES to change diff --git a/drivers/mtd/nand/raw/nand_micron.c b/drivers/mtd/nand/raw/nand_micron.c index 1a5505ccbe54..b85e1c13b79e 100644 --- a/drivers/mtd/nand/raw/nand_micron.c +++ b/drivers/mtd/nand/raw/nand_micron.c @@ -15,9 +15,10 @@ * GNU General Public License for more details. */ -#include #include +#include "internals.h" + /* * Special Micron status bit 3 indicates that the block has been * corrected by on-die ECC and should be rewritten. diff --git a/drivers/mtd/nand/raw/nand_samsung.c b/drivers/mtd/nand/raw/nand_samsung.c index ef022f62f74c..e46d4c492ad8 100644 --- a/drivers/mtd/nand/raw/nand_samsung.c +++ b/drivers/mtd/nand/raw/nand_samsung.c @@ -15,7 +15,7 @@ * GNU General Public License for more details. */ -#include +#include "internals.h" static void samsung_nand_decode_id(struct nand_chip *chip) { diff --git a/drivers/mtd/nand/raw/nand_timings.c b/drivers/mtd/nand/raw/nand_timings.c index cb4f0007b65c..bea3062d71d6 100644 --- a/drivers/mtd/nand/raw/nand_timings.c +++ b/drivers/mtd/nand/raw/nand_timings.c @@ -11,7 +11,8 @@ #include #include #include -#include + +#include "internals.h" #define ONFI_DYN_TIMING_MAX U16_MAX @@ -325,4 +326,3 @@ int onfi_fill_data_interface(struct nand_chip *chip, return 0; } -EXPORT_SYMBOL(onfi_fill_data_interface); diff --git a/drivers/mtd/nand/raw/nand_toshiba.c b/drivers/mtd/nand/raw/nand_toshiba.c index 952fe9e62ab4..941ddc615190 100644 --- a/drivers/mtd/nand/raw/nand_toshiba.c +++ b/drivers/mtd/nand/raw/nand_toshiba.c @@ -15,7 +15,7 @@ * GNU General Public License for more details. */ -#include +#include "internals.h" /* Bit for detecting BENAND */ #define TOSHIBA_NAND_ID4_IS_BENAND BIT(7) diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h index 7f0e3dc222ed..fbe7686cfc59 100644 --- a/include/linux/mtd/rawnand.h +++ b/include/linux/mtd/rawnand.h @@ -775,24 +775,6 @@ nand_get_sdr_timings(const struct nand_data_interface *conf) return &conf->timings.sdr; } -/** - * struct nand_manufacturer_ops - NAND Manufacturer operations - * @detect: detect the NAND memory organization and capabilities - * @init: initialize all vendor specific fields (like the ->read_retry() - * implementation) if any. - * @cleanup: the ->init() function may have allocated resources, ->cleanup() - * is here to let vendor specific code release those resources. - * @fixup_onfi_param_page: apply vendor specific fixups to the ONFI parameter - * page. This is called after the checksum is verified. - */ -struct nand_manufacturer_ops { - void (*detect)(struct nand_chip *chip); - int (*init)(struct nand_chip *chip); - void (*cleanup)(struct nand_chip *chip); - void (*fixup_onfi_param_page)(struct nand_chip *chip, - struct nand_onfi_params *p); -}; - /** * struct nand_op_cmd_instr - Definition of a command instruction * @opcode: the command to issue in one cycle @@ -1403,27 +1385,6 @@ static inline void *nand_get_manufacturer_data(struct nand_chip *chip) return chip->manufacturer.priv; } -/* - * NAND Flash Manufacturer ID Codes - */ -#define NAND_MFR_TOSHIBA 0x98 -#define NAND_MFR_ESMT 0xc8 -#define NAND_MFR_SAMSUNG 0xec -#define NAND_MFR_FUJITSU 0x04 -#define NAND_MFR_NATIONAL 0x8f -#define NAND_MFR_RENESAS 0x07 -#define NAND_MFR_STMICRO 0x20 -#define NAND_MFR_HYNIX 0xad -#define NAND_MFR_MICRON 0x2c -#define NAND_MFR_AMD 0x01 -#define NAND_MFR_MACRONIX 0xc2 -#define NAND_MFR_EON 0x92 -#define NAND_MFR_SANDISK 0x45 -#define NAND_MFR_INTEL 0x89 -#define NAND_MFR_ATO 0x9b -#define NAND_MFR_WINBOND 0xef - - /* * A helper for defining older NAND chips where the second ID byte fully * defined the chip, including the geometry (chip size, eraseblock size, page @@ -1503,46 +1464,7 @@ struct nand_flash_dev { int onfi_timing_mode_default; }; -/** - * struct nand_manufacturer - NAND Flash Manufacturer structure - * @name: Manufacturer name - * @id: manufacturer ID code of device. - * @ops: manufacturer operations -*/ -struct nand_manufacturer { - int id; - char *name; - const struct nand_manufacturer_ops *ops; -}; - -const struct nand_manufacturer *nand_get_manufacturer(u8 id); - -static inline const char * -nand_manufacturer_name(const struct nand_manufacturer *manufacturer) -{ - return manufacturer ? manufacturer->name : "Unknown"; -} - -extern struct nand_flash_dev nand_flash_ids[]; - -extern const struct nand_manufacturer_ops toshiba_nand_manuf_ops; -extern const struct nand_manufacturer_ops samsung_nand_manuf_ops; -extern const struct nand_manufacturer_ops hynix_nand_manuf_ops; -extern const struct nand_manufacturer_ops micron_nand_manuf_ops; -extern const struct nand_manufacturer_ops amd_nand_manuf_ops; -extern const struct nand_manufacturer_ops macronix_nand_manuf_ops; - int nand_create_bbt(struct nand_chip *chip); -int nand_markbad_bbt(struct nand_chip *chip, loff_t offs); -int nand_markbad_bbm(struct nand_chip *chip, loff_t ofs); -int nand_isreserved_bbt(struct nand_chip *chip, loff_t offs); -int nand_isbad_bbt(struct nand_chip *chip, loff_t offs, int allowbbt); -int nand_erase_nand(struct nand_chip *chip, struct erase_info *instr, - int allowbbt); - -int onfi_fill_data_interface(struct nand_chip *chip, - enum nand_data_interface_type type, - int timing_mode); /* * Check if it is a SLC nand. @@ -1574,7 +1496,6 @@ static inline int nand_opcode_8bits(unsigned int command) return 0; } - int nand_check_erased_ecc_chunk(void *data, int datalen, void *ecc, int ecclen, void *extraoob, int extraooblen, @@ -1586,18 +1507,9 @@ int nand_ecc_choose_conf(struct nand_chip *chip, /* Default write_oob implementation */ int nand_write_oob_std(struct nand_chip *chip, int page); -/* Default write_oob syndrome implementation */ -int nand_write_oob_syndrome(struct nand_chip *chip, int page); - /* Default read_oob implementation */ int nand_read_oob_std(struct nand_chip *chip, int page); -/* Default read_oob syndrome implementation */ -int nand_read_oob_syndrome(struct nand_chip *chip, int page); - -/* Wrapper to use in order for controllers/vendors to GET/SET FEATURES */ -int nand_get_features(struct nand_chip *chip, int addr, u8 *subfeature_param); -int nand_set_features(struct nand_chip *chip, int addr, u8 *subfeature_param); /* Stub used by drivers that do not support GET/SET FEATURES operations */ int nand_get_set_features_notsupp(struct nand_chip *chip, int addr, u8 *subfeature_param); @@ -1605,14 +1517,10 @@ int nand_get_set_features_notsupp(struct nand_chip *chip, int addr, /* Default read_page_raw implementation */ int nand_read_page_raw(struct nand_chip *chip, uint8_t *buf, int oob_required, int page); -int nand_read_page_raw_notsupp(struct nand_chip *chip, u8 *buf, - int oob_required, int page); /* Default write_page_raw implementation */ int nand_write_page_raw(struct nand_chip *chip, const uint8_t *buf, int oob_required, int page); -int nand_write_page_raw_notsupp(struct nand_chip *chip, const u8 *buf, - int oob_required, int page); /* Reset and initialize a NAND device */ int nand_reset(struct nand_chip *chip, int chipnr); @@ -1622,7 +1530,6 @@ int nand_reset_op(struct nand_chip *chip); int nand_readid_op(struct nand_chip *chip, u8 addr, void *buf, unsigned int len); int nand_status_op(struct nand_chip *chip, u8 *status); -int nand_exit_status_op(struct nand_chip *chip); int nand_erase_op(struct nand_chip *chip, unsigned int eraseblock); int nand_read_page_op(struct nand_chip *chip, unsigned int page, unsigned int offset_in_page, void *buf, unsigned int len); @@ -1666,9 +1573,6 @@ void nand_cleanup(struct nand_chip *chip); /* Unregister the MTD device and calls nand_cleanup() */ void nand_release(struct nand_chip *chip); -/* Default extended ID decoding function */ -void nand_decode_ext_id(struct nand_chip *chip); - /* * External helper for controller drivers that have to implement the WAITRDY * instruction and have no physical pin to check it. From 3d4af7c195850cfccaddc2cf03b010b95236b695 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Fri, 7 Sep 2018 00:38:49 +0200 Subject: [PATCH 286/302] mtd: rawnand: Move legacy code to nand_legacy.c Allows us to move a few hundred lines of deprecated code out of the core file which is quite big. Signed-off-by: Boris Brezillon Signed-off-by: Miquel Raynal --- drivers/mtd/nand/raw/Makefile | 2 +- drivers/mtd/nand/raw/internals.h | 6 + drivers/mtd/nand/raw/nand_base.c | 618 +-------------------------- drivers/mtd/nand/raw/nand_legacy.c | 642 +++++++++++++++++++++++++++++ 4 files changed, 660 insertions(+), 608 deletions(-) create mode 100644 drivers/mtd/nand/raw/nand_legacy.c diff --git a/drivers/mtd/nand/raw/Makefile b/drivers/mtd/nand/raw/Makefile index a6ef0673e29e..78f67de2e60b 100644 --- a/drivers/mtd/nand/raw/Makefile +++ b/drivers/mtd/nand/raw/Makefile @@ -57,7 +57,7 @@ obj-$(CONFIG_MTD_NAND_QCOM) += qcom_nandc.o obj-$(CONFIG_MTD_NAND_MTK) += mtk_ecc.o mtk_nand.o obj-$(CONFIG_MTD_NAND_TEGRA) += tegra_nand.o -nand-objs := nand_base.o nand_bbt.o nand_timings.o nand_ids.o +nand-objs := nand_base.o nand_legacy.o nand_bbt.o nand_timings.o nand_ids.o nand-objs += nand_amd.o nand-objs += nand_hynix.o nand-objs += nand_macronix.o diff --git a/drivers/mtd/nand/raw/internals.h b/drivers/mtd/nand/raw/internals.h index 1d2edddb6127..289a4b8f7974 100644 --- a/drivers/mtd/nand/raw/internals.h +++ b/drivers/mtd/nand/raw/internals.h @@ -89,10 +89,16 @@ int nand_write_page_raw_notsupp(struct nand_chip *chip, const u8 *buf, int oob_required, int page); int nand_exit_status_op(struct nand_chip *chip); void nand_decode_ext_id(struct nand_chip *chip); +void panic_nand_wait(struct nand_chip *chip, unsigned long timeo); /* BBT functions */ int nand_markbad_bbt(struct nand_chip *chip, loff_t offs); int nand_isreserved_bbt(struct nand_chip *chip, loff_t offs); int nand_isbad_bbt(struct nand_chip *chip, loff_t offs, int allowbbt); +/* Legacy */ +void nand_legacy_set_defaults(struct nand_chip *chip); +void nand_legacy_adjust_cmdfunc(struct nand_chip *chip); +int nand_legacy_check_hooks(struct nand_chip *chip); + #endif /* __LINUX_RAWNAND_INTERNALS */ diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c index d48c588d1abe..4ef00cefd5da 100644 --- a/drivers/mtd/nand/raw/nand_base.c +++ b/drivers/mtd/nand/raw/nand_base.c @@ -36,7 +36,6 @@ #include #include #include -#include #include #include #include @@ -253,150 +252,6 @@ static void nand_release_device(struct mtd_info *mtd) spin_unlock(&chip->controller->lock); } -/** - * nand_read_byte - [DEFAULT] read one byte from the chip - * @chip: NAND chip object - * - * Default read function for 8bit buswidth - */ -static uint8_t nand_read_byte(struct nand_chip *chip) -{ - return readb(chip->legacy.IO_ADDR_R); -} - -/** - * nand_read_byte16 - [DEFAULT] read one byte endianness aware from the chip - * @chip: NAND chip object - * - * Default read function for 16bit buswidth with endianness conversion. - * - */ -static uint8_t nand_read_byte16(struct nand_chip *chip) -{ - return (uint8_t) cpu_to_le16(readw(chip->legacy.IO_ADDR_R)); -} - -/** - * nand_select_chip - [DEFAULT] control CE line - * @chip: NAND chip object - * @chipnr: chipnumber to select, -1 for deselect - * - * Default select function for 1 chip devices. - */ -static void nand_select_chip(struct nand_chip *chip, int chipnr) -{ - switch (chipnr) { - case -1: - chip->legacy.cmd_ctrl(chip, NAND_CMD_NONE, - 0 | NAND_CTRL_CHANGE); - break; - case 0: - break; - - default: - BUG(); - } -} - -/** - * nand_write_byte - [DEFAULT] write single byte to chip - * @chip: NAND chip object - * @byte: value to write - * - * Default function to write a byte to I/O[7:0] - */ -static void nand_write_byte(struct nand_chip *chip, uint8_t byte) -{ - chip->legacy.write_buf(chip, &byte, 1); -} - -/** - * nand_write_byte16 - [DEFAULT] write single byte to a chip with width 16 - * @chip: NAND chip object - * @byte: value to write - * - * Default function to write a byte to I/O[7:0] on a 16-bit wide chip. - */ -static void nand_write_byte16(struct nand_chip *chip, uint8_t byte) -{ - uint16_t word = byte; - - /* - * It's not entirely clear what should happen to I/O[15:8] when writing - * a byte. The ONFi spec (Revision 3.1; 2012-09-19, Section 2.16) reads: - * - * When the host supports a 16-bit bus width, only data is - * transferred at the 16-bit width. All address and command line - * transfers shall use only the lower 8-bits of the data bus. During - * command transfers, the host may place any value on the upper - * 8-bits of the data bus. During address transfers, the host shall - * set the upper 8-bits of the data bus to 00h. - * - * One user of the write_byte callback is nand_set_features. The - * four parameters are specified to be written to I/O[7:0], but this is - * neither an address nor a command transfer. Let's assume a 0 on the - * upper I/O lines is OK. - */ - chip->legacy.write_buf(chip, (uint8_t *)&word, 2); -} - -/** - * nand_write_buf - [DEFAULT] write buffer to chip - * @chip: NAND chip object - * @buf: data buffer - * @len: number of bytes to write - * - * Default write function for 8bit buswidth. - */ -static void nand_write_buf(struct nand_chip *chip, const uint8_t *buf, int len) -{ - iowrite8_rep(chip->legacy.IO_ADDR_W, buf, len); -} - -/** - * nand_read_buf - [DEFAULT] read chip data into buffer - * @chip: NAND chip object - * @buf: buffer to store date - * @len: number of bytes to read - * - * Default read function for 8bit buswidth. - */ -static void nand_read_buf(struct nand_chip *chip, uint8_t *buf, int len) -{ - ioread8_rep(chip->legacy.IO_ADDR_R, buf, len); -} - -/** - * nand_write_buf16 - [DEFAULT] write buffer to chip - * @chip: NAND chip object - * @buf: data buffer - * @len: number of bytes to write - * - * Default write function for 16bit buswidth. - */ -static void nand_write_buf16(struct nand_chip *chip, const uint8_t *buf, - int len) -{ - u16 *p = (u16 *) buf; - - iowrite16_rep(chip->legacy.IO_ADDR_W, p, len >> 1); -} - -/** - * nand_read_buf16 - [DEFAULT] read chip data into buffer - * @chip: NAND chip object - * @buf: buffer to store date - * @len: number of bytes to read - * - * Default read function for 16bit buswidth. - */ -static void nand_read_buf16(struct nand_chip *chip, uint8_t *buf, int len) -{ - u16 *p = (u16 *) buf; - - ioread16_rep(chip->legacy.IO_ADDR_R, p, len >> 1); -} - /** * nand_block_bad - [DEFAULT] Read bad block marker from the chip * @chip: NAND chip object @@ -611,81 +466,6 @@ static int nand_block_checkbad(struct mtd_info *mtd, loff_t ofs, int allowbbt) return nand_isbad_bbm(chip, ofs); } -/** - * panic_nand_wait_ready - [GENERIC] Wait for the ready pin after commands. - * @mtd: MTD device structure - * @timeo: Timeout - * - * Helper function for nand_wait_ready used when needing to wait in interrupt - * context. - */ -static void panic_nand_wait_ready(struct mtd_info *mtd, unsigned long timeo) -{ - struct nand_chip *chip = mtd_to_nand(mtd); - int i; - - /* Wait for the device to get ready */ - for (i = 0; i < timeo; i++) { - if (chip->legacy.dev_ready(chip)) - break; - touch_softlockup_watchdog(); - mdelay(1); - } -} - -/** - * nand_wait_ready - [GENERIC] Wait for the ready pin after commands. - * @chip: NAND chip object - * - * Wait for the ready pin after a command, and warn if a timeout occurs. - */ -void nand_wait_ready(struct nand_chip *chip) -{ - struct mtd_info *mtd = nand_to_mtd(chip); - unsigned long timeo = 400; - - if (in_interrupt() || oops_in_progress) - return panic_nand_wait_ready(mtd, timeo); - - /* Wait until command is processed or timeout occurs */ - timeo = jiffies + msecs_to_jiffies(timeo); - do { - if (chip->legacy.dev_ready(chip)) - return; - cond_resched(); - } while (time_before(jiffies, timeo)); - - if (!chip->legacy.dev_ready(chip)) - pr_warn_ratelimited("timeout while waiting for chip to become ready\n"); -} -EXPORT_SYMBOL_GPL(nand_wait_ready); - -/** - * nand_wait_status_ready - [GENERIC] Wait for the ready status after commands. - * @mtd: MTD device structure - * @timeo: Timeout in ms - * - * Wait for status ready (i.e. command done) or timeout. - */ -static void nand_wait_status_ready(struct mtd_info *mtd, unsigned long timeo) -{ - register struct nand_chip *chip = mtd_to_nand(mtd); - int ret; - - timeo = jiffies + msecs_to_jiffies(timeo); - do { - u8 status; - - ret = nand_read_data_op(chip, &status, sizeof(status), true); - if (ret) - return; - - if (status & NAND_STATUS_READY) - break; - touch_softlockup_watchdog(); - } while (time_before(jiffies, timeo)); -}; - /** * nand_soft_waitrdy - Poll STATUS reg until RDY bit is set to 1 * @chip: NAND chip structure @@ -751,275 +531,6 @@ int nand_soft_waitrdy(struct nand_chip *chip, unsigned long timeout_ms) }; EXPORT_SYMBOL_GPL(nand_soft_waitrdy); -/** - * nand_command - [DEFAULT] Send command to NAND device - * @chip: NAND chip object - * @command: the command to be sent - * @column: the column address for this command, -1 if none - * @page_addr: the page address for this command, -1 if none - * - * Send command to NAND device. This function is used for small page devices - * (512 Bytes per page). - */ -static void nand_command(struct nand_chip *chip, unsigned int command, - int column, int page_addr) -{ - struct mtd_info *mtd = nand_to_mtd(chip); - int ctrl = NAND_CTRL_CLE | NAND_CTRL_CHANGE; - - /* Write out the command to the device */ - if (command == NAND_CMD_SEQIN) { - int readcmd; - - if (column >= mtd->writesize) { - /* OOB area */ - column -= mtd->writesize; - readcmd = NAND_CMD_READOOB; - } else if (column < 256) { - /* First 256 bytes --> READ0 */ - readcmd = NAND_CMD_READ0; - } else { - column -= 256; - readcmd = NAND_CMD_READ1; - } - chip->legacy.cmd_ctrl(chip, readcmd, ctrl); - ctrl &= ~NAND_CTRL_CHANGE; - } - if (command != NAND_CMD_NONE) - chip->legacy.cmd_ctrl(chip, command, ctrl); - - /* Address cycle, when necessary */ - ctrl = NAND_CTRL_ALE | NAND_CTRL_CHANGE; - /* Serially input address */ - if (column != -1) { - /* Adjust columns for 16 bit buswidth */ - if (chip->options & NAND_BUSWIDTH_16 && - !nand_opcode_8bits(command)) - column >>= 1; - chip->legacy.cmd_ctrl(chip, column, ctrl); - ctrl &= ~NAND_CTRL_CHANGE; - } - if (page_addr != -1) { - chip->legacy.cmd_ctrl(chip, page_addr, ctrl); - ctrl &= ~NAND_CTRL_CHANGE; - chip->legacy.cmd_ctrl(chip, page_addr >> 8, ctrl); - if (chip->options & NAND_ROW_ADDR_3) - chip->legacy.cmd_ctrl(chip, page_addr >> 16, ctrl); - } - chip->legacy.cmd_ctrl(chip, NAND_CMD_NONE, - NAND_NCE | NAND_CTRL_CHANGE); - - /* - * Program and erase have their own busy handlers status and sequential - * in needs no delay - */ - switch (command) { - - case NAND_CMD_NONE: - case NAND_CMD_PAGEPROG: - case NAND_CMD_ERASE1: - case NAND_CMD_ERASE2: - case NAND_CMD_SEQIN: - case NAND_CMD_STATUS: - case NAND_CMD_READID: - case NAND_CMD_SET_FEATURES: - return; - - case NAND_CMD_RESET: - if (chip->legacy.dev_ready) - break; - udelay(chip->legacy.chip_delay); - chip->legacy.cmd_ctrl(chip, NAND_CMD_STATUS, - NAND_CTRL_CLE | NAND_CTRL_CHANGE); - chip->legacy.cmd_ctrl(chip, NAND_CMD_NONE, - NAND_NCE | NAND_CTRL_CHANGE); - /* EZ-NAND can take upto 250ms as per ONFi v4.0 */ - nand_wait_status_ready(mtd, 250); - return; - - /* This applies to read commands */ - case NAND_CMD_READ0: - /* - * READ0 is sometimes used to exit GET STATUS mode. When this - * is the case no address cycles are requested, and we can use - * this information to detect that we should not wait for the - * device to be ready. - */ - if (column == -1 && page_addr == -1) - return; - - default: - /* - * If we don't have access to the busy pin, we apply the given - * command delay - */ - if (!chip->legacy.dev_ready) { - udelay(chip->legacy.chip_delay); - return; - } - } - /* - * Apply this short delay always to ensure that we do wait tWB in - * any case on any machine. - */ - ndelay(100); - - nand_wait_ready(chip); -} - -static void nand_ccs_delay(struct nand_chip *chip) -{ - /* - * The controller already takes care of waiting for tCCS when the RNDIN - * or RNDOUT command is sent, return directly. - */ - if (!(chip->options & NAND_WAIT_TCCS)) - return; - - /* - * Wait tCCS_min if it is correctly defined, otherwise wait 500ns - * (which should be safe for all NANDs). - */ - if (chip->setup_data_interface) - ndelay(chip->data_interface.timings.sdr.tCCS_min / 1000); - else - ndelay(500); -} - -/** - * nand_command_lp - [DEFAULT] Send command to NAND large page device - * @chip: NAND chip object - * @command: the command to be sent - * @column: the column address for this command, -1 if none - * @page_addr: the page address for this command, -1 if none - * - * Send command to NAND device. This is the version for the new large page - * devices. We don't have the separate regions as we have in the small page - * devices. We must emulate NAND_CMD_READOOB to keep the code compatible. - */ -static void nand_command_lp(struct nand_chip *chip, unsigned int command, - int column, int page_addr) -{ - struct mtd_info *mtd = nand_to_mtd(chip); - - /* Emulate NAND_CMD_READOOB */ - if (command == NAND_CMD_READOOB) { - column += mtd->writesize; - command = NAND_CMD_READ0; - } - - /* Command latch cycle */ - if (command != NAND_CMD_NONE) - chip->legacy.cmd_ctrl(chip, command, - NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE); - - if (column != -1 || page_addr != -1) { - int ctrl = NAND_CTRL_CHANGE | NAND_NCE | NAND_ALE; - - /* Serially input address */ - if (column != -1) { - /* Adjust columns for 16 bit buswidth */ - if (chip->options & NAND_BUSWIDTH_16 && - !nand_opcode_8bits(command)) - column >>= 1; - chip->legacy.cmd_ctrl(chip, column, ctrl); - ctrl &= ~NAND_CTRL_CHANGE; - - /* Only output a single addr cycle for 8bits opcodes. */ - if (!nand_opcode_8bits(command)) - chip->legacy.cmd_ctrl(chip, column >> 8, ctrl); - } - if (page_addr != -1) { - chip->legacy.cmd_ctrl(chip, page_addr, ctrl); - chip->legacy.cmd_ctrl(chip, page_addr >> 8, - NAND_NCE | NAND_ALE); - if (chip->options & NAND_ROW_ADDR_3) - chip->legacy.cmd_ctrl(chip, page_addr >> 16, - NAND_NCE | NAND_ALE); - } - } - chip->legacy.cmd_ctrl(chip, NAND_CMD_NONE, - NAND_NCE | NAND_CTRL_CHANGE); - - /* - * Program and erase have their own busy handlers status, sequential - * in and status need no delay. - */ - switch (command) { - - case NAND_CMD_NONE: - case NAND_CMD_CACHEDPROG: - case NAND_CMD_PAGEPROG: - case NAND_CMD_ERASE1: - case NAND_CMD_ERASE2: - case NAND_CMD_SEQIN: - case NAND_CMD_STATUS: - case NAND_CMD_READID: - case NAND_CMD_SET_FEATURES: - return; - - case NAND_CMD_RNDIN: - nand_ccs_delay(chip); - return; - - case NAND_CMD_RESET: - if (chip->legacy.dev_ready) - break; - udelay(chip->legacy.chip_delay); - chip->legacy.cmd_ctrl(chip, NAND_CMD_STATUS, - NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE); - chip->legacy.cmd_ctrl(chip, NAND_CMD_NONE, - NAND_NCE | NAND_CTRL_CHANGE); - /* EZ-NAND can take upto 250ms as per ONFi v4.0 */ - nand_wait_status_ready(mtd, 250); - return; - - case NAND_CMD_RNDOUT: - /* No ready / busy check necessary */ - chip->legacy.cmd_ctrl(chip, NAND_CMD_RNDOUTSTART, - NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE); - chip->legacy.cmd_ctrl(chip, NAND_CMD_NONE, - NAND_NCE | NAND_CTRL_CHANGE); - - nand_ccs_delay(chip); - return; - - case NAND_CMD_READ0: - /* - * READ0 is sometimes used to exit GET STATUS mode. When this - * is the case no address cycles are requested, and we can use - * this information to detect that READSTART should not be - * issued. - */ - if (column == -1 && page_addr == -1) - return; - - chip->legacy.cmd_ctrl(chip, NAND_CMD_READSTART, - NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE); - chip->legacy.cmd_ctrl(chip, NAND_CMD_NONE, - NAND_NCE | NAND_CTRL_CHANGE); - - /* This applies to read commands */ - default: - /* - * If we don't have access to the busy pin, we apply the given - * command delay. - */ - if (!chip->legacy.dev_ready) { - udelay(chip->legacy.chip_delay); - return; - } - } - - /* - * Apply this short delay always to ensure that we do wait tWB in - * any case on any machine. - */ - ndelay(100); - - nand_wait_ready(chip); -} - /** * panic_nand_get_device - [GENERIC] Get chip for selected access * @chip: the nand chip descriptor @@ -1087,7 +598,7 @@ nand_get_device(struct mtd_info *mtd, int new_state) * we are in interrupt context. May happen when in panic and trying to write * an oops through mtdoops. */ -static void panic_nand_wait(struct nand_chip *chip, unsigned long timeo) +void panic_nand_wait(struct nand_chip *chip, unsigned long timeo) { int i; for (i = 0; i < timeo; i++) { @@ -1110,60 +621,6 @@ static void panic_nand_wait(struct nand_chip *chip, unsigned long timeo) } } -/** - * nand_wait - [DEFAULT] wait until the command is done - * @mtd: MTD device structure - * @chip: NAND chip structure - * - * Wait for command done. This applies to erase and program only. - */ -static int nand_wait(struct nand_chip *chip) -{ - - unsigned long timeo = 400; - u8 status; - int ret; - - /* - * Apply this short delay always to ensure that we do wait tWB in any - * case on any machine. - */ - ndelay(100); - - ret = nand_status_op(chip, NULL); - if (ret) - return ret; - - if (in_interrupt() || oops_in_progress) - panic_nand_wait(chip, timeo); - else { - timeo = jiffies + msecs_to_jiffies(timeo); - do { - if (chip->legacy.dev_ready) { - if (chip->legacy.dev_ready(chip)) - break; - } else { - ret = nand_read_data_op(chip, &status, - sizeof(status), true); - if (ret) - return ret; - - if (status & NAND_STATUS_READY) - break; - } - cond_resched(); - } while (time_before(jiffies, timeo)); - } - - ret = nand_read_data_op(chip, &status, sizeof(status), true); - if (ret) - return ret; - - /* This can happen if in case of timeout or buggy dev_ready */ - WARN_ON(!(status & NAND_STATUS_READY)); - return status; -} - static bool nand_supports_get_features(struct nand_chip *chip, int addr) { return (chip->parameters.supports_set_get_features && @@ -4864,22 +4321,6 @@ static int nand_max_bad_blocks(struct mtd_info *mtd, loff_t ofs, size_t len) return chip->max_bb_per_die * (part_end_die - part_start_die + 1); } -/** - * nand_get_set_features_notsupp - set/get features stub returning -ENOTSUPP - * @chip: nand chip info structure - * @addr: feature address. - * @subfeature_param: the subfeature parameters, a four bytes array. - * - * Should be used by NAND controller drivers that do not support the SET/GET - * FEATURES operations. - */ -int nand_get_set_features_notsupp(struct nand_chip *chip, int addr, - u8 *subfeature_param) -{ - return -ENOTSUPP; -} -EXPORT_SYMBOL(nand_get_set_features_notsupp); - /** * nand_suspend - [MTD Interface] Suspend the NAND flash * @mtd: MTD device structure @@ -4917,32 +4358,7 @@ static void nand_shutdown(struct mtd_info *mtd) /* Set default functions */ static void nand_set_defaults(struct nand_chip *chip) { - unsigned int busw = chip->options & NAND_BUSWIDTH_16; - - /* check for proper chip_delay setup, set 20us if not */ - if (!chip->legacy.chip_delay) - chip->legacy.chip_delay = 20; - - /* check, if a user supplied command function given */ - if (!chip->legacy.cmdfunc && !chip->exec_op) - chip->legacy.cmdfunc = nand_command; - - /* check, if a user supplied wait function given */ - if (chip->legacy.waitfunc == NULL) - chip->legacy.waitfunc = nand_wait; - - if (!chip->select_chip) - chip->select_chip = nand_select_chip; - - /* If called twice, pointers that depend on busw may need to be reset */ - if (!chip->legacy.read_byte || chip->legacy.read_byte == nand_read_byte) - chip->legacy.read_byte = busw ? nand_read_byte16 : nand_read_byte; - if (!chip->legacy.write_buf || chip->legacy.write_buf == nand_write_buf) - chip->legacy.write_buf = busw ? nand_write_buf16 : nand_write_buf; - if (!chip->legacy.write_byte || chip->legacy.write_byte == nand_write_byte) - chip->legacy.write_byte = busw ? nand_write_byte16 : nand_write_byte; - if (!chip->legacy.read_buf || chip->legacy.read_buf == nand_read_buf) - chip->legacy.read_buf = busw ? nand_read_buf16 : nand_read_buf; + nand_legacy_set_defaults(chip); if (!chip->controller) { chip->controller = &chip->dummy_controller; @@ -5212,9 +4628,7 @@ static int nand_flash_detect_onfi(struct nand_chip *chip) * chip->legacy.cmdfunc now. We do not replace user supplied * command function. */ - if (mtd->writesize > 512 && - chip->legacy.cmdfunc == nand_command) - chip->legacy.cmdfunc = nand_command_lp; + nand_legacy_adjust_cmdfunc(chip); /* The Extended Parameter Page is supported since ONFI 2.1. */ if (nand_flash_detect_ext_param_page(chip, p)) @@ -5737,9 +5151,7 @@ static int nand_detect(struct nand_chip *chip, struct nand_flash_dev *type) chip->badblockbits = 8; - /* Do not replace user supplied command function! */ - if (mtd->writesize > 512 && chip->legacy.cmdfunc == nand_command) - chip->legacy.cmdfunc = nand_command_lp; + nand_legacy_adjust_cmdfunc(chip); pr_info("device found, Manufacturer ID: 0x%02x, Chip ID: 0x%02x\n", maf_id, dev_id); @@ -5935,23 +5347,15 @@ static int nand_scan_ident(struct nand_chip *chip, unsigned int maxchips, if (!mtd->name && mtd->dev.parent) mtd->name = dev_name(mtd->dev.parent); - /* - * ->legacy.cmdfunc() is legacy and will only be used if ->exec_op() is - * not populated. - */ - if (!chip->exec_op) { - /* - * Default functions assigned for ->legacy.cmdfunc() and - * ->select_chip() both expect ->legacy.cmd_ctrl() to be - * populated. - */ - if ((!chip->legacy.cmdfunc || !chip->select_chip) && - !chip->legacy.cmd_ctrl) { - pr_err("->legacy.cmd_ctrl() should be provided\n"); - return -EINVAL; - } + if (chip->exec_op && !chip->select_chip) { + pr_err("->select_chip() is mandatory when implementing ->exec_op()\n"); + return -EINVAL; } + ret = nand_legacy_check_hooks(chip); + if (ret) + return ret; + /* Set the default functions */ nand_set_defaults(chip); diff --git a/drivers/mtd/nand/raw/nand_legacy.c b/drivers/mtd/nand/raw/nand_legacy.c new file mode 100644 index 000000000000..c5ddc86cd98c --- /dev/null +++ b/drivers/mtd/nand/raw/nand_legacy.c @@ -0,0 +1,642 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com) + * 2002-2006 Thomas Gleixner (tglx@linutronix.de) + * + * Credits: + * David Woodhouse for adding multichip support + * + * Aleph One Ltd. and Toby Churchill Ltd. for supporting the + * rework for 2K page size chips + * + * This file contains all legacy helpers/code that should be removed + * at some point. + */ + +#include +#include +#include + +#include "internals.h" + +/** + * nand_read_byte - [DEFAULT] read one byte from the chip + * @chip: NAND chip object + * + * Default read function for 8bit buswidth + */ +static uint8_t nand_read_byte(struct nand_chip *chip) +{ + return readb(chip->legacy.IO_ADDR_R); +} + +/** + * nand_read_byte16 - [DEFAULT] read one byte endianness aware from the chip + * @chip: NAND chip object + * + * Default read function for 16bit buswidth with endianness conversion. + * + */ +static uint8_t nand_read_byte16(struct nand_chip *chip) +{ + return (uint8_t) cpu_to_le16(readw(chip->legacy.IO_ADDR_R)); +} + +/** + * nand_select_chip - [DEFAULT] control CE line + * @chip: NAND chip object + * @chipnr: chipnumber to select, -1 for deselect + * + * Default select function for 1 chip devices. + */ +static void nand_select_chip(struct nand_chip *chip, int chipnr) +{ + switch (chipnr) { + case -1: + chip->legacy.cmd_ctrl(chip, NAND_CMD_NONE, + 0 | NAND_CTRL_CHANGE); + break; + case 0: + break; + + default: + BUG(); + } +} + +/** + * nand_write_byte - [DEFAULT] write single byte to chip + * @chip: NAND chip object + * @byte: value to write + * + * Default function to write a byte to I/O[7:0] + */ +static void nand_write_byte(struct nand_chip *chip, uint8_t byte) +{ + chip->legacy.write_buf(chip, &byte, 1); +} + +/** + * nand_write_byte16 - [DEFAULT] write single byte to a chip with width 16 + * @chip: NAND chip object + * @byte: value to write + * + * Default function to write a byte to I/O[7:0] on a 16-bit wide chip. + */ +static void nand_write_byte16(struct nand_chip *chip, uint8_t byte) +{ + uint16_t word = byte; + + /* + * It's not entirely clear what should happen to I/O[15:8] when writing + * a byte. The ONFi spec (Revision 3.1; 2012-09-19, Section 2.16) reads: + * + * When the host supports a 16-bit bus width, only data is + * transferred at the 16-bit width. All address and command line + * transfers shall use only the lower 8-bits of the data bus. During + * command transfers, the host may place any value on the upper + * 8-bits of the data bus. During address transfers, the host shall + * set the upper 8-bits of the data bus to 00h. + * + * One user of the write_byte callback is nand_set_features. The + * four parameters are specified to be written to I/O[7:0], but this is + * neither an address nor a command transfer. Let's assume a 0 on the + * upper I/O lines is OK. + */ + chip->legacy.write_buf(chip, (uint8_t *)&word, 2); +} + +/** + * nand_write_buf - [DEFAULT] write buffer to chip + * @chip: NAND chip object + * @buf: data buffer + * @len: number of bytes to write + * + * Default write function for 8bit buswidth. + */ +static void nand_write_buf(struct nand_chip *chip, const uint8_t *buf, int len) +{ + iowrite8_rep(chip->legacy.IO_ADDR_W, buf, len); +} + +/** + * nand_read_buf - [DEFAULT] read chip data into buffer + * @chip: NAND chip object + * @buf: buffer to store date + * @len: number of bytes to read + * + * Default read function for 8bit buswidth. + */ +static void nand_read_buf(struct nand_chip *chip, uint8_t *buf, int len) +{ + ioread8_rep(chip->legacy.IO_ADDR_R, buf, len); +} + +/** + * nand_write_buf16 - [DEFAULT] write buffer to chip + * @chip: NAND chip object + * @buf: data buffer + * @len: number of bytes to write + * + * Default write function for 16bit buswidth. + */ +static void nand_write_buf16(struct nand_chip *chip, const uint8_t *buf, + int len) +{ + u16 *p = (u16 *) buf; + + iowrite16_rep(chip->legacy.IO_ADDR_W, p, len >> 1); +} + +/** + * nand_read_buf16 - [DEFAULT] read chip data into buffer + * @chip: NAND chip object + * @buf: buffer to store date + * @len: number of bytes to read + * + * Default read function for 16bit buswidth. + */ +static void nand_read_buf16(struct nand_chip *chip, uint8_t *buf, int len) +{ + u16 *p = (u16 *) buf; + + ioread16_rep(chip->legacy.IO_ADDR_R, p, len >> 1); +} + +/** + * panic_nand_wait_ready - [GENERIC] Wait for the ready pin after commands. + * @mtd: MTD device structure + * @timeo: Timeout + * + * Helper function for nand_wait_ready used when needing to wait in interrupt + * context. + */ +static void panic_nand_wait_ready(struct mtd_info *mtd, unsigned long timeo) +{ + struct nand_chip *chip = mtd_to_nand(mtd); + int i; + + /* Wait for the device to get ready */ + for (i = 0; i < timeo; i++) { + if (chip->legacy.dev_ready(chip)) + break; + touch_softlockup_watchdog(); + mdelay(1); + } +} + +/** + * nand_wait_ready - [GENERIC] Wait for the ready pin after commands. + * @chip: NAND chip object + * + * Wait for the ready pin after a command, and warn if a timeout occurs. + */ +void nand_wait_ready(struct nand_chip *chip) +{ + struct mtd_info *mtd = nand_to_mtd(chip); + unsigned long timeo = 400; + + if (in_interrupt() || oops_in_progress) + return panic_nand_wait_ready(mtd, timeo); + + /* Wait until command is processed or timeout occurs */ + timeo = jiffies + msecs_to_jiffies(timeo); + do { + if (chip->legacy.dev_ready(chip)) + return; + cond_resched(); + } while (time_before(jiffies, timeo)); + + if (!chip->legacy.dev_ready(chip)) + pr_warn_ratelimited("timeout while waiting for chip to become ready\n"); +} +EXPORT_SYMBOL_GPL(nand_wait_ready); + +/** + * nand_wait_status_ready - [GENERIC] Wait for the ready status after commands. + * @mtd: MTD device structure + * @timeo: Timeout in ms + * + * Wait for status ready (i.e. command done) or timeout. + */ +static void nand_wait_status_ready(struct mtd_info *mtd, unsigned long timeo) +{ + register struct nand_chip *chip = mtd_to_nand(mtd); + int ret; + + timeo = jiffies + msecs_to_jiffies(timeo); + do { + u8 status; + + ret = nand_read_data_op(chip, &status, sizeof(status), true); + if (ret) + return; + + if (status & NAND_STATUS_READY) + break; + touch_softlockup_watchdog(); + } while (time_before(jiffies, timeo)); +}; + +/** + * nand_command - [DEFAULT] Send command to NAND device + * @chip: NAND chip object + * @command: the command to be sent + * @column: the column address for this command, -1 if none + * @page_addr: the page address for this command, -1 if none + * + * Send command to NAND device. This function is used for small page devices + * (512 Bytes per page). + */ +static void nand_command(struct nand_chip *chip, unsigned int command, + int column, int page_addr) +{ + struct mtd_info *mtd = nand_to_mtd(chip); + int ctrl = NAND_CTRL_CLE | NAND_CTRL_CHANGE; + + /* Write out the command to the device */ + if (command == NAND_CMD_SEQIN) { + int readcmd; + + if (column >= mtd->writesize) { + /* OOB area */ + column -= mtd->writesize; + readcmd = NAND_CMD_READOOB; + } else if (column < 256) { + /* First 256 bytes --> READ0 */ + readcmd = NAND_CMD_READ0; + } else { + column -= 256; + readcmd = NAND_CMD_READ1; + } + chip->legacy.cmd_ctrl(chip, readcmd, ctrl); + ctrl &= ~NAND_CTRL_CHANGE; + } + if (command != NAND_CMD_NONE) + chip->legacy.cmd_ctrl(chip, command, ctrl); + + /* Address cycle, when necessary */ + ctrl = NAND_CTRL_ALE | NAND_CTRL_CHANGE; + /* Serially input address */ + if (column != -1) { + /* Adjust columns for 16 bit buswidth */ + if (chip->options & NAND_BUSWIDTH_16 && + !nand_opcode_8bits(command)) + column >>= 1; + chip->legacy.cmd_ctrl(chip, column, ctrl); + ctrl &= ~NAND_CTRL_CHANGE; + } + if (page_addr != -1) { + chip->legacy.cmd_ctrl(chip, page_addr, ctrl); + ctrl &= ~NAND_CTRL_CHANGE; + chip->legacy.cmd_ctrl(chip, page_addr >> 8, ctrl); + if (chip->options & NAND_ROW_ADDR_3) + chip->legacy.cmd_ctrl(chip, page_addr >> 16, ctrl); + } + chip->legacy.cmd_ctrl(chip, NAND_CMD_NONE, + NAND_NCE | NAND_CTRL_CHANGE); + + /* + * Program and erase have their own busy handlers status and sequential + * in needs no delay + */ + switch (command) { + + case NAND_CMD_NONE: + case NAND_CMD_PAGEPROG: + case NAND_CMD_ERASE1: + case NAND_CMD_ERASE2: + case NAND_CMD_SEQIN: + case NAND_CMD_STATUS: + case NAND_CMD_READID: + case NAND_CMD_SET_FEATURES: + return; + + case NAND_CMD_RESET: + if (chip->legacy.dev_ready) + break; + udelay(chip->legacy.chip_delay); + chip->legacy.cmd_ctrl(chip, NAND_CMD_STATUS, + NAND_CTRL_CLE | NAND_CTRL_CHANGE); + chip->legacy.cmd_ctrl(chip, NAND_CMD_NONE, + NAND_NCE | NAND_CTRL_CHANGE); + /* EZ-NAND can take upto 250ms as per ONFi v4.0 */ + nand_wait_status_ready(mtd, 250); + return; + + /* This applies to read commands */ + case NAND_CMD_READ0: + /* + * READ0 is sometimes used to exit GET STATUS mode. When this + * is the case no address cycles are requested, and we can use + * this information to detect that we should not wait for the + * device to be ready. + */ + if (column == -1 && page_addr == -1) + return; + + default: + /* + * If we don't have access to the busy pin, we apply the given + * command delay + */ + if (!chip->legacy.dev_ready) { + udelay(chip->legacy.chip_delay); + return; + } + } + /* + * Apply this short delay always to ensure that we do wait tWB in + * any case on any machine. + */ + ndelay(100); + + nand_wait_ready(chip); +} + +static void nand_ccs_delay(struct nand_chip *chip) +{ + /* + * The controller already takes care of waiting for tCCS when the RNDIN + * or RNDOUT command is sent, return directly. + */ + if (!(chip->options & NAND_WAIT_TCCS)) + return; + + /* + * Wait tCCS_min if it is correctly defined, otherwise wait 500ns + * (which should be safe for all NANDs). + */ + if (chip->setup_data_interface) + ndelay(chip->data_interface.timings.sdr.tCCS_min / 1000); + else + ndelay(500); +} + +/** + * nand_command_lp - [DEFAULT] Send command to NAND large page device + * @chip: NAND chip object + * @command: the command to be sent + * @column: the column address for this command, -1 if none + * @page_addr: the page address for this command, -1 if none + * + * Send command to NAND device. This is the version for the new large page + * devices. We don't have the separate regions as we have in the small page + * devices. We must emulate NAND_CMD_READOOB to keep the code compatible. + */ +static void nand_command_lp(struct nand_chip *chip, unsigned int command, + int column, int page_addr) +{ + struct mtd_info *mtd = nand_to_mtd(chip); + + /* Emulate NAND_CMD_READOOB */ + if (command == NAND_CMD_READOOB) { + column += mtd->writesize; + command = NAND_CMD_READ0; + } + + /* Command latch cycle */ + if (command != NAND_CMD_NONE) + chip->legacy.cmd_ctrl(chip, command, + NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE); + + if (column != -1 || page_addr != -1) { + int ctrl = NAND_CTRL_CHANGE | NAND_NCE | NAND_ALE; + + /* Serially input address */ + if (column != -1) { + /* Adjust columns for 16 bit buswidth */ + if (chip->options & NAND_BUSWIDTH_16 && + !nand_opcode_8bits(command)) + column >>= 1; + chip->legacy.cmd_ctrl(chip, column, ctrl); + ctrl &= ~NAND_CTRL_CHANGE; + + /* Only output a single addr cycle for 8bits opcodes. */ + if (!nand_opcode_8bits(command)) + chip->legacy.cmd_ctrl(chip, column >> 8, ctrl); + } + if (page_addr != -1) { + chip->legacy.cmd_ctrl(chip, page_addr, ctrl); + chip->legacy.cmd_ctrl(chip, page_addr >> 8, + NAND_NCE | NAND_ALE); + if (chip->options & NAND_ROW_ADDR_3) + chip->legacy.cmd_ctrl(chip, page_addr >> 16, + NAND_NCE | NAND_ALE); + } + } + chip->legacy.cmd_ctrl(chip, NAND_CMD_NONE, + NAND_NCE | NAND_CTRL_CHANGE); + + /* + * Program and erase have their own busy handlers status, sequential + * in and status need no delay. + */ + switch (command) { + + case NAND_CMD_NONE: + case NAND_CMD_CACHEDPROG: + case NAND_CMD_PAGEPROG: + case NAND_CMD_ERASE1: + case NAND_CMD_ERASE2: + case NAND_CMD_SEQIN: + case NAND_CMD_STATUS: + case NAND_CMD_READID: + case NAND_CMD_SET_FEATURES: + return; + + case NAND_CMD_RNDIN: + nand_ccs_delay(chip); + return; + + case NAND_CMD_RESET: + if (chip->legacy.dev_ready) + break; + udelay(chip->legacy.chip_delay); + chip->legacy.cmd_ctrl(chip, NAND_CMD_STATUS, + NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE); + chip->legacy.cmd_ctrl(chip, NAND_CMD_NONE, + NAND_NCE | NAND_CTRL_CHANGE); + /* EZ-NAND can take upto 250ms as per ONFi v4.0 */ + nand_wait_status_ready(mtd, 250); + return; + + case NAND_CMD_RNDOUT: + /* No ready / busy check necessary */ + chip->legacy.cmd_ctrl(chip, NAND_CMD_RNDOUTSTART, + NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE); + chip->legacy.cmd_ctrl(chip, NAND_CMD_NONE, + NAND_NCE | NAND_CTRL_CHANGE); + + nand_ccs_delay(chip); + return; + + case NAND_CMD_READ0: + /* + * READ0 is sometimes used to exit GET STATUS mode. When this + * is the case no address cycles are requested, and we can use + * this information to detect that READSTART should not be + * issued. + */ + if (column == -1 && page_addr == -1) + return; + + chip->legacy.cmd_ctrl(chip, NAND_CMD_READSTART, + NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE); + chip->legacy.cmd_ctrl(chip, NAND_CMD_NONE, + NAND_NCE | NAND_CTRL_CHANGE); + + /* This applies to read commands */ + default: + /* + * If we don't have access to the busy pin, we apply the given + * command delay. + */ + if (!chip->legacy.dev_ready) { + udelay(chip->legacy.chip_delay); + return; + } + } + + /* + * Apply this short delay always to ensure that we do wait tWB in + * any case on any machine. + */ + ndelay(100); + + nand_wait_ready(chip); +} + +/** + * nand_get_set_features_notsupp - set/get features stub returning -ENOTSUPP + * @chip: nand chip info structure + * @addr: feature address. + * @subfeature_param: the subfeature parameters, a four bytes array. + * + * Should be used by NAND controller drivers that do not support the SET/GET + * FEATURES operations. + */ +int nand_get_set_features_notsupp(struct nand_chip *chip, int addr, + u8 *subfeature_param) +{ + return -ENOTSUPP; +} +EXPORT_SYMBOL(nand_get_set_features_notsupp); + +/** + * nand_wait - [DEFAULT] wait until the command is done + * @mtd: MTD device structure + * @chip: NAND chip structure + * + * Wait for command done. This applies to erase and program only. + */ +static int nand_wait(struct nand_chip *chip) +{ + + unsigned long timeo = 400; + u8 status; + int ret; + + /* + * Apply this short delay always to ensure that we do wait tWB in any + * case on any machine. + */ + ndelay(100); + + ret = nand_status_op(chip, NULL); + if (ret) + return ret; + + if (in_interrupt() || oops_in_progress) + panic_nand_wait(chip, timeo); + else { + timeo = jiffies + msecs_to_jiffies(timeo); + do { + if (chip->legacy.dev_ready) { + if (chip->legacy.dev_ready(chip)) + break; + } else { + ret = nand_read_data_op(chip, &status, + sizeof(status), true); + if (ret) + return ret; + + if (status & NAND_STATUS_READY) + break; + } + cond_resched(); + } while (time_before(jiffies, timeo)); + } + + ret = nand_read_data_op(chip, &status, sizeof(status), true); + if (ret) + return ret; + + /* This can happen if in case of timeout or buggy dev_ready */ + WARN_ON(!(status & NAND_STATUS_READY)); + return status; +} + +void nand_legacy_set_defaults(struct nand_chip *chip) +{ + unsigned int busw = chip->options & NAND_BUSWIDTH_16; + + if (chip->exec_op) + return; + + /* check for proper chip_delay setup, set 20us if not */ + if (!chip->legacy.chip_delay) + chip->legacy.chip_delay = 20; + + /* check, if a user supplied command function given */ + if (!chip->legacy.cmdfunc && !chip->exec_op) + chip->legacy.cmdfunc = nand_command; + + /* check, if a user supplied wait function given */ + if (chip->legacy.waitfunc == NULL) + chip->legacy.waitfunc = nand_wait; + + if (!chip->select_chip) + chip->select_chip = nand_select_chip; + + /* If called twice, pointers that depend on busw may need to be reset */ + if (!chip->legacy.read_byte || chip->legacy.read_byte == nand_read_byte) + chip->legacy.read_byte = busw ? nand_read_byte16 : nand_read_byte; + if (!chip->legacy.write_buf || chip->legacy.write_buf == nand_write_buf) + chip->legacy.write_buf = busw ? nand_write_buf16 : nand_write_buf; + if (!chip->legacy.write_byte || chip->legacy.write_byte == nand_write_byte) + chip->legacy.write_byte = busw ? nand_write_byte16 : nand_write_byte; + if (!chip->legacy.read_buf || chip->legacy.read_buf == nand_read_buf) + chip->legacy.read_buf = busw ? nand_read_buf16 : nand_read_buf; +} + +void nand_legacy_adjust_cmdfunc(struct nand_chip *chip) +{ + struct mtd_info *mtd = nand_to_mtd(chip); + + /* Do not replace user supplied command function! */ + if (mtd->writesize > 512 && chip->legacy.cmdfunc == nand_command) + chip->legacy.cmdfunc = nand_command_lp; +} + +int nand_legacy_check_hooks(struct nand_chip *chip) +{ + /* + * ->legacy.cmdfunc() is legacy and will only be used if ->exec_op() is + * not populated. + */ + if (chip->exec_op) + return 0; + + /* + * Default functions assigned for ->legacy.cmdfunc() and + * ->select_chip() both expect ->legacy.cmd_ctrl() to be populated. + */ + if ((!chip->legacy.cmdfunc || !chip->select_chip) && + !chip->legacy.cmd_ctrl) { + pr_err("->legacy.cmd_ctrl() should be provided\n"); + return -EINVAL; + } + + return 0; +} From 1c325cc5077a88510afc08b1d2c75bcf18681f21 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Fri, 7 Sep 2018 00:38:50 +0200 Subject: [PATCH 287/302] mtd: rawnand: Move ONFI code to nand_onfi.c This moves ONFI related code to nand_onfi.c and ONFI related struct/macros to include/linux/mtd/onfi.h. Signed-off-by: Boris Brezillon Signed-off-by: Miquel Raynal --- drivers/mtd/nand/raw/Makefile | 1 + drivers/mtd/nand/raw/internals.h | 7 + drivers/mtd/nand/raw/nand_base.c | 296 +----------------------------- drivers/mtd/nand/raw/nand_onfi.c | 305 +++++++++++++++++++++++++++++++ include/linux/mtd/onfi.h | 178 ++++++++++++++++++ include/linux/mtd/rawnand.h | 164 +---------------- 6 files changed, 496 insertions(+), 455 deletions(-) create mode 100644 drivers/mtd/nand/raw/nand_onfi.c create mode 100644 include/linux/mtd/onfi.h diff --git a/drivers/mtd/nand/raw/Makefile b/drivers/mtd/nand/raw/Makefile index 78f67de2e60b..cc9f50f3ad1b 100644 --- a/drivers/mtd/nand/raw/Makefile +++ b/drivers/mtd/nand/raw/Makefile @@ -58,6 +58,7 @@ obj-$(CONFIG_MTD_NAND_MTK) += mtk_ecc.o mtk_nand.o obj-$(CONFIG_MTD_NAND_TEGRA) += tegra_nand.o nand-objs := nand_base.o nand_legacy.o nand_bbt.o nand_timings.o nand_ids.o +nand-objs += nand_onfi.o nand-objs += nand_amd.o nand-objs += nand_hynix.o nand-objs += nand_macronix.o diff --git a/drivers/mtd/nand/raw/internals.h b/drivers/mtd/nand/raw/internals.h index 289a4b8f7974..1ce720a8d756 100644 --- a/drivers/mtd/nand/raw/internals.h +++ b/drivers/mtd/nand/raw/internals.h @@ -88,8 +88,11 @@ int nand_read_page_raw_notsupp(struct nand_chip *chip, u8 *buf, int nand_write_page_raw_notsupp(struct nand_chip *chip, const u8 *buf, int oob_required, int page); int nand_exit_status_op(struct nand_chip *chip); +int nand_read_param_page_op(struct nand_chip *chip, u8 page, void *buf, + unsigned int len); void nand_decode_ext_id(struct nand_chip *chip); void panic_nand_wait(struct nand_chip *chip, unsigned long timeo); +void sanitize_string(uint8_t *s, size_t len); /* BBT functions */ int nand_markbad_bbt(struct nand_chip *chip, loff_t offs); @@ -101,4 +104,8 @@ void nand_legacy_set_defaults(struct nand_chip *chip); void nand_legacy_adjust_cmdfunc(struct nand_chip *chip); int nand_legacy_check_hooks(struct nand_chip *chip); +/* ONFI functions */ +u16 onfi_crc16(u16 crc, u8 const *p, size_t len); +int nand_onfi_detect(struct nand_chip *chip); + #endif /* __LINUX_RAWNAND_INTERNALS */ diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c index 4ef00cefd5da..812e8bd6ad82 100644 --- a/drivers/mtd/nand/raw/nand_base.c +++ b/drivers/mtd/nand/raw/nand_base.c @@ -986,8 +986,8 @@ EXPORT_SYMBOL_GPL(nand_read_page_op); * * Returns 0 on success, a negative error code otherwise. */ -static int nand_read_param_page_op(struct nand_chip *chip, u8 page, void *buf, - unsigned int len) +int nand_read_param_page_op(struct nand_chip *chip, u8 page, void *buf, + unsigned int len) { unsigned int i; u8 *p = buf; @@ -4370,7 +4370,7 @@ static void nand_set_defaults(struct nand_chip *chip) } /* Sanitize ONFI strings so we can safely print them */ -static void sanitize_string(uint8_t *s, size_t len) +void sanitize_string(uint8_t *s, size_t len) { ssize_t i; @@ -4387,294 +4387,6 @@ static void sanitize_string(uint8_t *s, size_t len) strim(s); } -static u16 onfi_crc16(u16 crc, u8 const *p, size_t len) -{ - int i; - while (len--) { - crc ^= *p++ << 8; - for (i = 0; i < 8; i++) - crc = (crc << 1) ^ ((crc & 0x8000) ? 0x8005 : 0); - } - - return crc; -} - -/* Parse the Extended Parameter Page. */ -static int nand_flash_detect_ext_param_page(struct nand_chip *chip, - struct nand_onfi_params *p) -{ - struct onfi_ext_param_page *ep; - struct onfi_ext_section *s; - struct onfi_ext_ecc_info *ecc; - uint8_t *cursor; - int ret; - int len; - int i; - - len = le16_to_cpu(p->ext_param_page_length) * 16; - ep = kmalloc(len, GFP_KERNEL); - if (!ep) - return -ENOMEM; - - /* Send our own NAND_CMD_PARAM. */ - ret = nand_read_param_page_op(chip, 0, NULL, 0); - if (ret) - goto ext_out; - - /* Use the Change Read Column command to skip the ONFI param pages. */ - ret = nand_change_read_column_op(chip, - sizeof(*p) * p->num_of_param_pages, - ep, len, true); - if (ret) - goto ext_out; - - ret = -EINVAL; - if ((onfi_crc16(ONFI_CRC_BASE, ((uint8_t *)ep) + 2, len - 2) - != le16_to_cpu(ep->crc))) { - pr_debug("fail in the CRC.\n"); - goto ext_out; - } - - /* - * Check the signature. - * Do not strictly follow the ONFI spec, maybe changed in future. - */ - if (strncmp(ep->sig, "EPPS", 4)) { - pr_debug("The signature is invalid.\n"); - goto ext_out; - } - - /* find the ECC section. */ - cursor = (uint8_t *)(ep + 1); - for (i = 0; i < ONFI_EXT_SECTION_MAX; i++) { - s = ep->sections + i; - if (s->type == ONFI_SECTION_TYPE_2) - break; - cursor += s->length * 16; - } - if (i == ONFI_EXT_SECTION_MAX) { - pr_debug("We can not find the ECC section.\n"); - goto ext_out; - } - - /* get the info we want. */ - ecc = (struct onfi_ext_ecc_info *)cursor; - - if (!ecc->codeword_size) { - pr_debug("Invalid codeword size\n"); - goto ext_out; - } - - chip->ecc_strength_ds = ecc->ecc_bits; - chip->ecc_step_ds = 1 << ecc->codeword_size; - ret = 0; - -ext_out: - kfree(ep); - return ret; -} - -/* - * Recover data with bit-wise majority - */ -static void nand_bit_wise_majority(const void **srcbufs, - unsigned int nsrcbufs, - void *dstbuf, - unsigned int bufsize) -{ - int i, j, k; - - for (i = 0; i < bufsize; i++) { - u8 val = 0; - - for (j = 0; j < 8; j++) { - unsigned int cnt = 0; - - for (k = 0; k < nsrcbufs; k++) { - const u8 *srcbuf = srcbufs[k]; - - if (srcbuf[i] & BIT(j)) - cnt++; - } - - if (cnt > nsrcbufs / 2) - val |= BIT(j); - } - - ((u8 *)dstbuf)[i] = val; - } -} - -/* - * Check if the NAND chip is ONFI compliant, returns 1 if it is, 0 otherwise. - */ -static int nand_flash_detect_onfi(struct nand_chip *chip) -{ - struct mtd_info *mtd = nand_to_mtd(chip); - struct nand_onfi_params *p; - struct onfi_params *onfi; - int onfi_version = 0; - char id[4]; - int i, ret, val; - - /* Try ONFI for unknown chip or LP */ - ret = nand_readid_op(chip, 0x20, id, sizeof(id)); - if (ret || strncmp(id, "ONFI", 4)) - return 0; - - /* ONFI chip: allocate a buffer to hold its parameter page */ - p = kzalloc((sizeof(*p) * 3), GFP_KERNEL); - if (!p) - return -ENOMEM; - - ret = nand_read_param_page_op(chip, 0, NULL, 0); - if (ret) { - ret = 0; - goto free_onfi_param_page; - } - - for (i = 0; i < 3; i++) { - ret = nand_read_data_op(chip, &p[i], sizeof(*p), true); - if (ret) { - ret = 0; - goto free_onfi_param_page; - } - - if (onfi_crc16(ONFI_CRC_BASE, (u8 *)&p[i], 254) == - le16_to_cpu(p->crc)) { - if (i) - memcpy(p, &p[i], sizeof(*p)); - break; - } - } - - if (i == 3) { - const void *srcbufs[3] = {p, p + 1, p + 2}; - - pr_warn("Could not find a valid ONFI parameter page, trying bit-wise majority to recover it\n"); - nand_bit_wise_majority(srcbufs, ARRAY_SIZE(srcbufs), p, - sizeof(*p)); - - if (onfi_crc16(ONFI_CRC_BASE, (u8 *)p, 254) != - le16_to_cpu(p->crc)) { - pr_err("ONFI parameter recovery failed, aborting\n"); - goto free_onfi_param_page; - } - } - - if (chip->manufacturer.desc && chip->manufacturer.desc->ops && - chip->manufacturer.desc->ops->fixup_onfi_param_page) - chip->manufacturer.desc->ops->fixup_onfi_param_page(chip, p); - - /* Check version */ - val = le16_to_cpu(p->revision); - if (val & ONFI_VERSION_2_3) - onfi_version = 23; - else if (val & ONFI_VERSION_2_2) - onfi_version = 22; - else if (val & ONFI_VERSION_2_1) - onfi_version = 21; - else if (val & ONFI_VERSION_2_0) - onfi_version = 20; - else if (val & ONFI_VERSION_1_0) - onfi_version = 10; - - if (!onfi_version) { - pr_info("unsupported ONFI version: %d\n", val); - goto free_onfi_param_page; - } - - sanitize_string(p->manufacturer, sizeof(p->manufacturer)); - sanitize_string(p->model, sizeof(p->model)); - chip->parameters.model = kstrdup(p->model, GFP_KERNEL); - if (!chip->parameters.model) { - ret = -ENOMEM; - goto free_onfi_param_page; - } - - mtd->writesize = le32_to_cpu(p->byte_per_page); - - /* - * pages_per_block and blocks_per_lun may not be a power-of-2 size - * (don't ask me who thought of this...). MTD assumes that these - * dimensions will be power-of-2, so just truncate the remaining area. - */ - mtd->erasesize = 1 << (fls(le32_to_cpu(p->pages_per_block)) - 1); - mtd->erasesize *= mtd->writesize; - - mtd->oobsize = le16_to_cpu(p->spare_bytes_per_page); - - /* See erasesize comment */ - chip->chipsize = 1 << (fls(le32_to_cpu(p->blocks_per_lun)) - 1); - chip->chipsize *= (uint64_t)mtd->erasesize * p->lun_count; - chip->bits_per_cell = p->bits_per_cell; - - chip->max_bb_per_die = le16_to_cpu(p->bb_per_lun); - chip->blocks_per_die = le32_to_cpu(p->blocks_per_lun); - - if (le16_to_cpu(p->features) & ONFI_FEATURE_16_BIT_BUS) - chip->options |= NAND_BUSWIDTH_16; - - if (p->ecc_bits != 0xff) { - chip->ecc_strength_ds = p->ecc_bits; - chip->ecc_step_ds = 512; - } else if (onfi_version >= 21 && - (le16_to_cpu(p->features) & ONFI_FEATURE_EXT_PARAM_PAGE)) { - - /* - * The nand_flash_detect_ext_param_page() uses the - * Change Read Column command which maybe not supported - * by the chip->legacy.cmdfunc. So try to update the - * chip->legacy.cmdfunc now. We do not replace user supplied - * command function. - */ - nand_legacy_adjust_cmdfunc(chip); - - /* The Extended Parameter Page is supported since ONFI 2.1. */ - if (nand_flash_detect_ext_param_page(chip, p)) - pr_warn("Failed to detect ONFI extended param page\n"); - } else { - pr_warn("Could not retrieve ONFI ECC requirements\n"); - } - - /* Save some parameters from the parameter page for future use */ - if (le16_to_cpu(p->opt_cmd) & ONFI_OPT_CMD_SET_GET_FEATURES) { - chip->parameters.supports_set_get_features = true; - bitmap_set(chip->parameters.get_feature_list, - ONFI_FEATURE_ADDR_TIMING_MODE, 1); - bitmap_set(chip->parameters.set_feature_list, - ONFI_FEATURE_ADDR_TIMING_MODE, 1); - } - - onfi = kzalloc(sizeof(*onfi), GFP_KERNEL); - if (!onfi) { - ret = -ENOMEM; - goto free_model; - } - - onfi->version = onfi_version; - onfi->tPROG = le16_to_cpu(p->t_prog); - onfi->tBERS = le16_to_cpu(p->t_bers); - onfi->tR = le16_to_cpu(p->t_r); - onfi->tCCS = le16_to_cpu(p->t_ccs); - onfi->async_timing_mode = le16_to_cpu(p->async_timing_mode); - onfi->vendor_revision = le16_to_cpu(p->vendor_revision); - memcpy(onfi->vendor, p->vendor, sizeof(p->vendor)); - chip->parameters.onfi = onfi; - - /* Identification done, free the full ONFI parameter page and exit */ - kfree(p); - - return 1; - -free_model: - kfree(chip->parameters.model); -free_onfi_param_page: - kfree(p); - - return ret; -} - /* * Check if the NAND chip is JEDEC compliant, returns 1 if it is, 0 otherwise. */ @@ -5076,7 +4788,7 @@ static int nand_detect(struct nand_chip *chip, struct nand_flash_dev *type) if (!type->name || !type->pagesize) { /* Check if the chip is ONFI compliant */ - ret = nand_flash_detect_onfi(chip); + ret = nand_onfi_detect(chip); if (ret < 0) return ret; else if (ret) diff --git a/drivers/mtd/nand/raw/nand_onfi.c b/drivers/mtd/nand/raw/nand_onfi.c new file mode 100644 index 000000000000..d8184cf591ad --- /dev/null +++ b/drivers/mtd/nand/raw/nand_onfi.c @@ -0,0 +1,305 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com) + * 2002-2006 Thomas Gleixner (tglx@linutronix.de) + * + * Credits: + * David Woodhouse for adding multichip support + * + * Aleph One Ltd. and Toby Churchill Ltd. for supporting the + * rework for 2K page size chips + * + * This file contains all ONFI helpers. + */ + +#include + +#include "internals.h" + +u16 onfi_crc16(u16 crc, u8 const *p, size_t len) +{ + int i; + while (len--) { + crc ^= *p++ << 8; + for (i = 0; i < 8; i++) + crc = (crc << 1) ^ ((crc & 0x8000) ? 0x8005 : 0); + } + + return crc; +} + +/* Parse the Extended Parameter Page. */ +static int nand_flash_detect_ext_param_page(struct nand_chip *chip, + struct nand_onfi_params *p) +{ + struct onfi_ext_param_page *ep; + struct onfi_ext_section *s; + struct onfi_ext_ecc_info *ecc; + uint8_t *cursor; + int ret; + int len; + int i; + + len = le16_to_cpu(p->ext_param_page_length) * 16; + ep = kmalloc(len, GFP_KERNEL); + if (!ep) + return -ENOMEM; + + /* Send our own NAND_CMD_PARAM. */ + ret = nand_read_param_page_op(chip, 0, NULL, 0); + if (ret) + goto ext_out; + + /* Use the Change Read Column command to skip the ONFI param pages. */ + ret = nand_change_read_column_op(chip, + sizeof(*p) * p->num_of_param_pages, + ep, len, true); + if (ret) + goto ext_out; + + ret = -EINVAL; + if ((onfi_crc16(ONFI_CRC_BASE, ((uint8_t *)ep) + 2, len - 2) + != le16_to_cpu(ep->crc))) { + pr_debug("fail in the CRC.\n"); + goto ext_out; + } + + /* + * Check the signature. + * Do not strictly follow the ONFI spec, maybe changed in future. + */ + if (strncmp(ep->sig, "EPPS", 4)) { + pr_debug("The signature is invalid.\n"); + goto ext_out; + } + + /* find the ECC section. */ + cursor = (uint8_t *)(ep + 1); + for (i = 0; i < ONFI_EXT_SECTION_MAX; i++) { + s = ep->sections + i; + if (s->type == ONFI_SECTION_TYPE_2) + break; + cursor += s->length * 16; + } + if (i == ONFI_EXT_SECTION_MAX) { + pr_debug("We can not find the ECC section.\n"); + goto ext_out; + } + + /* get the info we want. */ + ecc = (struct onfi_ext_ecc_info *)cursor; + + if (!ecc->codeword_size) { + pr_debug("Invalid codeword size\n"); + goto ext_out; + } + + chip->ecc_strength_ds = ecc->ecc_bits; + chip->ecc_step_ds = 1 << ecc->codeword_size; + ret = 0; + +ext_out: + kfree(ep); + return ret; +} + +/* + * Recover data with bit-wise majority + */ +static void nand_bit_wise_majority(const void **srcbufs, + unsigned int nsrcbufs, + void *dstbuf, + unsigned int bufsize) +{ + int i, j, k; + + for (i = 0; i < bufsize; i++) { + u8 val = 0; + + for (j = 0; j < 8; j++) { + unsigned int cnt = 0; + + for (k = 0; k < nsrcbufs; k++) { + const u8 *srcbuf = srcbufs[k]; + + if (srcbuf[i] & BIT(j)) + cnt++; + } + + if (cnt > nsrcbufs / 2) + val |= BIT(j); + } + + ((u8 *)dstbuf)[i] = val; + } +} + +/* + * Check if the NAND chip is ONFI compliant, returns 1 if it is, 0 otherwise. + */ +int nand_onfi_detect(struct nand_chip *chip) +{ + struct mtd_info *mtd = nand_to_mtd(chip); + struct nand_onfi_params *p; + struct onfi_params *onfi; + int onfi_version = 0; + char id[4]; + int i, ret, val; + + /* Try ONFI for unknown chip or LP */ + ret = nand_readid_op(chip, 0x20, id, sizeof(id)); + if (ret || strncmp(id, "ONFI", 4)) + return 0; + + /* ONFI chip: allocate a buffer to hold its parameter page */ + p = kzalloc((sizeof(*p) * 3), GFP_KERNEL); + if (!p) + return -ENOMEM; + + ret = nand_read_param_page_op(chip, 0, NULL, 0); + if (ret) { + ret = 0; + goto free_onfi_param_page; + } + + for (i = 0; i < 3; i++) { + ret = nand_read_data_op(chip, &p[i], sizeof(*p), true); + if (ret) { + ret = 0; + goto free_onfi_param_page; + } + + if (onfi_crc16(ONFI_CRC_BASE, (u8 *)&p[i], 254) == + le16_to_cpu(p->crc)) { + if (i) + memcpy(p, &p[i], sizeof(*p)); + break; + } + } + + if (i == 3) { + const void *srcbufs[3] = {p, p + 1, p + 2}; + + pr_warn("Could not find a valid ONFI parameter page, trying bit-wise majority to recover it\n"); + nand_bit_wise_majority(srcbufs, ARRAY_SIZE(srcbufs), p, + sizeof(*p)); + + if (onfi_crc16(ONFI_CRC_BASE, (u8 *)p, 254) != + le16_to_cpu(p->crc)) { + pr_err("ONFI parameter recovery failed, aborting\n"); + goto free_onfi_param_page; + } + } + + if (chip->manufacturer.desc && chip->manufacturer.desc->ops && + chip->manufacturer.desc->ops->fixup_onfi_param_page) + chip->manufacturer.desc->ops->fixup_onfi_param_page(chip, p); + + /* Check version */ + val = le16_to_cpu(p->revision); + if (val & ONFI_VERSION_2_3) + onfi_version = 23; + else if (val & ONFI_VERSION_2_2) + onfi_version = 22; + else if (val & ONFI_VERSION_2_1) + onfi_version = 21; + else if (val & ONFI_VERSION_2_0) + onfi_version = 20; + else if (val & ONFI_VERSION_1_0) + onfi_version = 10; + + if (!onfi_version) { + pr_info("unsupported ONFI version: %d\n", val); + goto free_onfi_param_page; + } + + sanitize_string(p->manufacturer, sizeof(p->manufacturer)); + sanitize_string(p->model, sizeof(p->model)); + chip->parameters.model = kstrdup(p->model, GFP_KERNEL); + if (!chip->parameters.model) { + ret = -ENOMEM; + goto free_onfi_param_page; + } + + mtd->writesize = le32_to_cpu(p->byte_per_page); + + /* + * pages_per_block and blocks_per_lun may not be a power-of-2 size + * (don't ask me who thought of this...). MTD assumes that these + * dimensions will be power-of-2, so just truncate the remaining area. + */ + mtd->erasesize = 1 << (fls(le32_to_cpu(p->pages_per_block)) - 1); + mtd->erasesize *= mtd->writesize; + + mtd->oobsize = le16_to_cpu(p->spare_bytes_per_page); + + /* See erasesize comment */ + chip->chipsize = 1 << (fls(le32_to_cpu(p->blocks_per_lun)) - 1); + chip->chipsize *= (uint64_t)mtd->erasesize * p->lun_count; + chip->bits_per_cell = p->bits_per_cell; + + chip->max_bb_per_die = le16_to_cpu(p->bb_per_lun); + chip->blocks_per_die = le32_to_cpu(p->blocks_per_lun); + + if (le16_to_cpu(p->features) & ONFI_FEATURE_16_BIT_BUS) + chip->options |= NAND_BUSWIDTH_16; + + if (p->ecc_bits != 0xff) { + chip->ecc_strength_ds = p->ecc_bits; + chip->ecc_step_ds = 512; + } else if (onfi_version >= 21 && + (le16_to_cpu(p->features) & ONFI_FEATURE_EXT_PARAM_PAGE)) { + + /* + * The nand_flash_detect_ext_param_page() uses the + * Change Read Column command which maybe not supported + * by the chip->legacy.cmdfunc. So try to update the + * chip->legacy.cmdfunc now. We do not replace user supplied + * command function. + */ + nand_legacy_adjust_cmdfunc(chip); + + /* The Extended Parameter Page is supported since ONFI 2.1. */ + if (nand_flash_detect_ext_param_page(chip, p)) + pr_warn("Failed to detect ONFI extended param page\n"); + } else { + pr_warn("Could not retrieve ONFI ECC requirements\n"); + } + + /* Save some parameters from the parameter page for future use */ + if (le16_to_cpu(p->opt_cmd) & ONFI_OPT_CMD_SET_GET_FEATURES) { + chip->parameters.supports_set_get_features = true; + bitmap_set(chip->parameters.get_feature_list, + ONFI_FEATURE_ADDR_TIMING_MODE, 1); + bitmap_set(chip->parameters.set_feature_list, + ONFI_FEATURE_ADDR_TIMING_MODE, 1); + } + + onfi = kzalloc(sizeof(*onfi), GFP_KERNEL); + if (!onfi) { + ret = -ENOMEM; + goto free_model; + } + + onfi->version = onfi_version; + onfi->tPROG = le16_to_cpu(p->t_prog); + onfi->tBERS = le16_to_cpu(p->t_bers); + onfi->tR = le16_to_cpu(p->t_r); + onfi->tCCS = le16_to_cpu(p->t_ccs); + onfi->async_timing_mode = le16_to_cpu(p->async_timing_mode); + onfi->vendor_revision = le16_to_cpu(p->vendor_revision); + memcpy(onfi->vendor, p->vendor, sizeof(p->vendor)); + chip->parameters.onfi = onfi; + + /* Identification done, free the full ONFI parameter page and exit */ + kfree(p); + + return 1; + +free_model: + kfree(chip->parameters.model); +free_onfi_param_page: + kfree(p); + + return ret; +} diff --git a/include/linux/mtd/onfi.h b/include/linux/mtd/onfi.h new file mode 100644 index 000000000000..339ac798568e --- /dev/null +++ b/include/linux/mtd/onfi.h @@ -0,0 +1,178 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright © 2000-2010 David Woodhouse + * Steven J. Hill + * Thomas Gleixner + * + * Contains all ONFI related definitions + */ + +#ifndef __LINUX_MTD_ONFI_H +#define __LINUX_MTD_ONFI_H + +#include + +/* ONFI version bits */ +#define ONFI_VERSION_1_0 BIT(1) +#define ONFI_VERSION_2_0 BIT(2) +#define ONFI_VERSION_2_1 BIT(3) +#define ONFI_VERSION_2_2 BIT(4) +#define ONFI_VERSION_2_3 BIT(5) +#define ONFI_VERSION_3_0 BIT(6) +#define ONFI_VERSION_3_1 BIT(7) +#define ONFI_VERSION_3_2 BIT(8) +#define ONFI_VERSION_4_0 BIT(9) + +/* ONFI features */ +#define ONFI_FEATURE_16_BIT_BUS (1 << 0) +#define ONFI_FEATURE_EXT_PARAM_PAGE (1 << 7) + +/* ONFI timing mode, used in both asynchronous and synchronous mode */ +#define ONFI_TIMING_MODE_0 (1 << 0) +#define ONFI_TIMING_MODE_1 (1 << 1) +#define ONFI_TIMING_MODE_2 (1 << 2) +#define ONFI_TIMING_MODE_3 (1 << 3) +#define ONFI_TIMING_MODE_4 (1 << 4) +#define ONFI_TIMING_MODE_5 (1 << 5) +#define ONFI_TIMING_MODE_UNKNOWN (1 << 6) + +/* ONFI feature number/address */ +#define ONFI_FEATURE_NUMBER 256 +#define ONFI_FEATURE_ADDR_TIMING_MODE 0x1 + +/* Vendor-specific feature address (Micron) */ +#define ONFI_FEATURE_ADDR_READ_RETRY 0x89 +#define ONFI_FEATURE_ON_DIE_ECC 0x90 +#define ONFI_FEATURE_ON_DIE_ECC_EN BIT(3) + +/* ONFI subfeature parameters length */ +#define ONFI_SUBFEATURE_PARAM_LEN 4 + +/* ONFI optional commands SET/GET FEATURES supported? */ +#define ONFI_OPT_CMD_SET_GET_FEATURES (1 << 2) + +struct nand_onfi_params { + /* rev info and features block */ + /* 'O' 'N' 'F' 'I' */ + u8 sig[4]; + __le16 revision; + __le16 features; + __le16 opt_cmd; + u8 reserved0[2]; + __le16 ext_param_page_length; /* since ONFI 2.1 */ + u8 num_of_param_pages; /* since ONFI 2.1 */ + u8 reserved1[17]; + + /* manufacturer information block */ + char manufacturer[12]; + char model[20]; + u8 jedec_id; + __le16 date_code; + u8 reserved2[13]; + + /* memory organization block */ + __le32 byte_per_page; + __le16 spare_bytes_per_page; + __le32 data_bytes_per_ppage; + __le16 spare_bytes_per_ppage; + __le32 pages_per_block; + __le32 blocks_per_lun; + u8 lun_count; + u8 addr_cycles; + u8 bits_per_cell; + __le16 bb_per_lun; + __le16 block_endurance; + u8 guaranteed_good_blocks; + __le16 guaranteed_block_endurance; + u8 programs_per_page; + u8 ppage_attr; + u8 ecc_bits; + u8 interleaved_bits; + u8 interleaved_ops; + u8 reserved3[13]; + + /* electrical parameter block */ + u8 io_pin_capacitance_max; + __le16 async_timing_mode; + __le16 program_cache_timing_mode; + __le16 t_prog; + __le16 t_bers; + __le16 t_r; + __le16 t_ccs; + __le16 src_sync_timing_mode; + u8 src_ssync_features; + __le16 clk_pin_capacitance_typ; + __le16 io_pin_capacitance_typ; + __le16 input_pin_capacitance_typ; + u8 input_pin_capacitance_max; + u8 driver_strength_support; + __le16 t_int_r; + __le16 t_adl; + u8 reserved4[8]; + + /* vendor */ + __le16 vendor_revision; + u8 vendor[88]; + + __le16 crc; +} __packed; + +#define ONFI_CRC_BASE 0x4F4E + +/* Extended ECC information Block Definition (since ONFI 2.1) */ +struct onfi_ext_ecc_info { + u8 ecc_bits; + u8 codeword_size; + __le16 bb_per_lun; + __le16 block_endurance; + u8 reserved[2]; +} __packed; + +#define ONFI_SECTION_TYPE_0 0 /* Unused section. */ +#define ONFI_SECTION_TYPE_1 1 /* for additional sections. */ +#define ONFI_SECTION_TYPE_2 2 /* for ECC information. */ +struct onfi_ext_section { + u8 type; + u8 length; +} __packed; + +#define ONFI_EXT_SECTION_MAX 8 + +/* Extended Parameter Page Definition (since ONFI 2.1) */ +struct onfi_ext_param_page { + __le16 crc; + u8 sig[4]; /* 'E' 'P' 'P' 'S' */ + u8 reserved0[10]; + struct onfi_ext_section sections[ONFI_EXT_SECTION_MAX]; + + /* + * The actual size of the Extended Parameter Page is in + * @ext_param_page_length of nand_onfi_params{}. + * The following are the variable length sections. + * So we do not add any fields below. Please see the ONFI spec. + */ +} __packed; + +/** + * struct onfi_params - ONFI specific parameters that will be reused + * @version: ONFI version (BCD encoded), 0 if ONFI is not supported + * @tPROG: Page program time + * @tBERS: Block erase time + * @tR: Page read time + * @tCCS: Change column setup time + * @async_timing_mode: Supported asynchronous timing mode + * @vendor_revision: Vendor specific revision number + * @vendor: Vendor specific data + */ +struct onfi_params { + int version; + u16 tPROG; + u16 tBERS; + u16 tR; + u16 tCCS; + u16 async_timing_mode; + u16 vendor_revision; + u8 vendor[88]; +}; + +#endif /* __LINUX_MTD_ONFI_H */ diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h index fbe7686cfc59..f4fc0cce7c55 100644 --- a/include/linux/mtd/rawnand.h +++ b/include/linux/mtd/rawnand.h @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -204,147 +205,6 @@ enum nand_ecc_algo { #define NAND_CI_CELLTYPE_MSK 0x0C #define NAND_CI_CELLTYPE_SHIFT 2 -/* ONFI version bits */ -#define ONFI_VERSION_1_0 BIT(1) -#define ONFI_VERSION_2_0 BIT(2) -#define ONFI_VERSION_2_1 BIT(3) -#define ONFI_VERSION_2_2 BIT(4) -#define ONFI_VERSION_2_3 BIT(5) -#define ONFI_VERSION_3_0 BIT(6) -#define ONFI_VERSION_3_1 BIT(7) -#define ONFI_VERSION_3_2 BIT(8) -#define ONFI_VERSION_4_0 BIT(9) - -/* ONFI features */ -#define ONFI_FEATURE_16_BIT_BUS (1 << 0) -#define ONFI_FEATURE_EXT_PARAM_PAGE (1 << 7) - -/* ONFI timing mode, used in both asynchronous and synchronous mode */ -#define ONFI_TIMING_MODE_0 (1 << 0) -#define ONFI_TIMING_MODE_1 (1 << 1) -#define ONFI_TIMING_MODE_2 (1 << 2) -#define ONFI_TIMING_MODE_3 (1 << 3) -#define ONFI_TIMING_MODE_4 (1 << 4) -#define ONFI_TIMING_MODE_5 (1 << 5) -#define ONFI_TIMING_MODE_UNKNOWN (1 << 6) - -/* ONFI feature number/address */ -#define ONFI_FEATURE_NUMBER 256 -#define ONFI_FEATURE_ADDR_TIMING_MODE 0x1 - -/* Vendor-specific feature address (Micron) */ -#define ONFI_FEATURE_ADDR_READ_RETRY 0x89 -#define ONFI_FEATURE_ON_DIE_ECC 0x90 -#define ONFI_FEATURE_ON_DIE_ECC_EN BIT(3) - -/* ONFI subfeature parameters length */ -#define ONFI_SUBFEATURE_PARAM_LEN 4 - -/* ONFI optional commands SET/GET FEATURES supported? */ -#define ONFI_OPT_CMD_SET_GET_FEATURES (1 << 2) - -struct nand_onfi_params { - /* rev info and features block */ - /* 'O' 'N' 'F' 'I' */ - u8 sig[4]; - __le16 revision; - __le16 features; - __le16 opt_cmd; - u8 reserved0[2]; - __le16 ext_param_page_length; /* since ONFI 2.1 */ - u8 num_of_param_pages; /* since ONFI 2.1 */ - u8 reserved1[17]; - - /* manufacturer information block */ - char manufacturer[12]; - char model[20]; - u8 jedec_id; - __le16 date_code; - u8 reserved2[13]; - - /* memory organization block */ - __le32 byte_per_page; - __le16 spare_bytes_per_page; - __le32 data_bytes_per_ppage; - __le16 spare_bytes_per_ppage; - __le32 pages_per_block; - __le32 blocks_per_lun; - u8 lun_count; - u8 addr_cycles; - u8 bits_per_cell; - __le16 bb_per_lun; - __le16 block_endurance; - u8 guaranteed_good_blocks; - __le16 guaranteed_block_endurance; - u8 programs_per_page; - u8 ppage_attr; - u8 ecc_bits; - u8 interleaved_bits; - u8 interleaved_ops; - u8 reserved3[13]; - - /* electrical parameter block */ - u8 io_pin_capacitance_max; - __le16 async_timing_mode; - __le16 program_cache_timing_mode; - __le16 t_prog; - __le16 t_bers; - __le16 t_r; - __le16 t_ccs; - __le16 src_sync_timing_mode; - u8 src_ssync_features; - __le16 clk_pin_capacitance_typ; - __le16 io_pin_capacitance_typ; - __le16 input_pin_capacitance_typ; - u8 input_pin_capacitance_max; - u8 driver_strength_support; - __le16 t_int_r; - __le16 t_adl; - u8 reserved4[8]; - - /* vendor */ - __le16 vendor_revision; - u8 vendor[88]; - - __le16 crc; -} __packed; - -#define ONFI_CRC_BASE 0x4F4E - -/* Extended ECC information Block Definition (since ONFI 2.1) */ -struct onfi_ext_ecc_info { - u8 ecc_bits; - u8 codeword_size; - __le16 bb_per_lun; - __le16 block_endurance; - u8 reserved[2]; -} __packed; - -#define ONFI_SECTION_TYPE_0 0 /* Unused section. */ -#define ONFI_SECTION_TYPE_1 1 /* for additional sections. */ -#define ONFI_SECTION_TYPE_2 2 /* for ECC information. */ -struct onfi_ext_section { - u8 type; - u8 length; -} __packed; - -#define ONFI_EXT_SECTION_MAX 8 - -/* Extended Parameter Page Definition (since ONFI 2.1) */ -struct onfi_ext_param_page { - __le16 crc; - u8 sig[4]; /* 'E' 'P' 'P' 'S' */ - u8 reserved0[10]; - struct onfi_ext_section sections[ONFI_EXT_SECTION_MAX]; - - /* - * The actual size of the Extended Parameter Page is in - * @ext_param_page_length of nand_onfi_params{}. - * The following are the variable length sections. - * So we do not add any fields below. Please see the ONFI spec. - */ -} __packed; - struct jedec_ecc_info { u8 ecc_bits; u8 codeword_size; @@ -423,28 +283,6 @@ struct nand_jedec_params { __le16 crc; } __packed; -/** - * struct onfi_params - ONFI specific parameters that will be reused - * @version: ONFI version (BCD encoded), 0 if ONFI is not supported - * @tPROG: Page program time - * @tBERS: Block erase time - * @tR: Page read time - * @tCCS: Change column setup time - * @async_timing_mode: Supported asynchronous timing mode - * @vendor_revision: Vendor specific revision number - * @vendor: Vendor specific data - */ -struct onfi_params { - int version; - u16 tPROG; - u16 tBERS; - u16 tR; - u16 tCCS; - u16 async_timing_mode; - u16 vendor_revision; - u8 vendor[88]; -}; - /** * struct nand_parameters - NAND generic parameters from the parameter page * @model: Model name From 8ae3fbf81b9cfdd1fec0451181213742b73fdf1a Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Fri, 7 Sep 2018 00:38:51 +0200 Subject: [PATCH 288/302] mtd: rawnand: Move JEDEC code to nand_jedec.c This moves JEDEC related code to nand_jedec.c and JEDEC related struct/macros to include/linux/mtd/jedec.h. Signed-off-by: Boris Brezillon Signed-off-by: Miquel Raynal --- drivers/mtd/nand/raw/Makefile | 1 + drivers/mtd/nand/raw/internals.h | 3 + drivers/mtd/nand/raw/nand_base.c | 98 +------------------------- drivers/mtd/nand/raw/nand_jedec.c | 113 ++++++++++++++++++++++++++++++ include/linux/mtd/jedec.h | 91 ++++++++++++++++++++++++ include/linux/mtd/rawnand.h | 79 +-------------------- 6 files changed, 210 insertions(+), 175 deletions(-) create mode 100644 drivers/mtd/nand/raw/nand_jedec.c create mode 100644 include/linux/mtd/jedec.h diff --git a/drivers/mtd/nand/raw/Makefile b/drivers/mtd/nand/raw/Makefile index cc9f50f3ad1b..be2c17863ee5 100644 --- a/drivers/mtd/nand/raw/Makefile +++ b/drivers/mtd/nand/raw/Makefile @@ -59,6 +59,7 @@ obj-$(CONFIG_MTD_NAND_TEGRA) += tegra_nand.o nand-objs := nand_base.o nand_legacy.o nand_bbt.o nand_timings.o nand_ids.o nand-objs += nand_onfi.o +nand-objs += nand_jedec.o nand-objs += nand_amd.o nand-objs += nand_hynix.o nand-objs += nand_macronix.o diff --git a/drivers/mtd/nand/raw/internals.h b/drivers/mtd/nand/raw/internals.h index 1ce720a8d756..88b5da620e7d 100644 --- a/drivers/mtd/nand/raw/internals.h +++ b/drivers/mtd/nand/raw/internals.h @@ -108,4 +108,7 @@ int nand_legacy_check_hooks(struct nand_chip *chip); u16 onfi_crc16(u16 crc, u8 const *p, size_t len); int nand_onfi_detect(struct nand_chip *chip); +/* JEDEC functions */ +int nand_jedec_detect(struct nand_chip *chip); + #endif /* __LINUX_RAWNAND_INTERNALS */ diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c index 812e8bd6ad82..dc3955da0426 100644 --- a/drivers/mtd/nand/raw/nand_base.c +++ b/drivers/mtd/nand/raw/nand_base.c @@ -4387,102 +4387,6 @@ void sanitize_string(uint8_t *s, size_t len) strim(s); } -/* - * Check if the NAND chip is JEDEC compliant, returns 1 if it is, 0 otherwise. - */ -static int nand_flash_detect_jedec(struct nand_chip *chip) -{ - struct mtd_info *mtd = nand_to_mtd(chip); - struct nand_jedec_params *p; - struct jedec_ecc_info *ecc; - int jedec_version = 0; - char id[5]; - int i, val, ret; - - /* Try JEDEC for unknown chip or LP */ - ret = nand_readid_op(chip, 0x40, id, sizeof(id)); - if (ret || strncmp(id, "JEDEC", sizeof(id))) - return 0; - - /* JEDEC chip: allocate a buffer to hold its parameter page */ - p = kzalloc(sizeof(*p), GFP_KERNEL); - if (!p) - return -ENOMEM; - - ret = nand_read_param_page_op(chip, 0x40, NULL, 0); - if (ret) { - ret = 0; - goto free_jedec_param_page; - } - - for (i = 0; i < 3; i++) { - ret = nand_read_data_op(chip, p, sizeof(*p), true); - if (ret) { - ret = 0; - goto free_jedec_param_page; - } - - if (onfi_crc16(ONFI_CRC_BASE, (uint8_t *)p, 510) == - le16_to_cpu(p->crc)) - break; - } - - if (i == 3) { - pr_err("Could not find valid JEDEC parameter page; aborting\n"); - goto free_jedec_param_page; - } - - /* Check version */ - val = le16_to_cpu(p->revision); - if (val & (1 << 2)) - jedec_version = 10; - else if (val & (1 << 1)) - jedec_version = 1; /* vendor specific version */ - - if (!jedec_version) { - pr_info("unsupported JEDEC version: %d\n", val); - goto free_jedec_param_page; - } - - sanitize_string(p->manufacturer, sizeof(p->manufacturer)); - sanitize_string(p->model, sizeof(p->model)); - chip->parameters.model = kstrdup(p->model, GFP_KERNEL); - if (!chip->parameters.model) { - ret = -ENOMEM; - goto free_jedec_param_page; - } - - mtd->writesize = le32_to_cpu(p->byte_per_page); - - /* Please reference to the comment for nand_flash_detect_onfi. */ - mtd->erasesize = 1 << (fls(le32_to_cpu(p->pages_per_block)) - 1); - mtd->erasesize *= mtd->writesize; - - mtd->oobsize = le16_to_cpu(p->spare_bytes_per_page); - - /* Please reference to the comment for nand_flash_detect_onfi. */ - chip->chipsize = 1 << (fls(le32_to_cpu(p->blocks_per_lun)) - 1); - chip->chipsize *= (uint64_t)mtd->erasesize * p->lun_count; - chip->bits_per_cell = p->bits_per_cell; - - if (le16_to_cpu(p->features) & JEDEC_FEATURE_16_BIT_BUS) - chip->options |= NAND_BUSWIDTH_16; - - /* ECC info */ - ecc = &p->ecc_info[0]; - - if (ecc->codeword_size >= 9) { - chip->ecc_strength_ds = ecc->ecc_bits; - chip->ecc_step_ds = 1 << ecc->codeword_size; - } else { - pr_warn("Invalid codeword size\n"); - } - -free_jedec_param_page: - kfree(p); - return ret; -} - /* * nand_id_has_period - Check if an ID string has a given wraparound period * @id_data: the ID string @@ -4795,7 +4699,7 @@ static int nand_detect(struct nand_chip *chip, struct nand_flash_dev *type) goto ident_done; /* Check if the chip is JEDEC compliant */ - ret = nand_flash_detect_jedec(chip); + ret = nand_jedec_detect(chip); if (ret < 0) return ret; else if (ret) diff --git a/drivers/mtd/nand/raw/nand_jedec.c b/drivers/mtd/nand/raw/nand_jedec.c new file mode 100644 index 000000000000..5c26492c841d --- /dev/null +++ b/drivers/mtd/nand/raw/nand_jedec.c @@ -0,0 +1,113 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com) + * 2002-2006 Thomas Gleixner (tglx@linutronix.de) + * + * Credits: + * David Woodhouse for adding multichip support + * + * Aleph One Ltd. and Toby Churchill Ltd. for supporting the + * rework for 2K page size chips + * + * This file contains all ONFI helpers. + */ + +#include + +#include "internals.h" + +/* + * Check if the NAND chip is JEDEC compliant, returns 1 if it is, 0 otherwise. + */ +int nand_jedec_detect(struct nand_chip *chip) +{ + struct mtd_info *mtd = nand_to_mtd(chip); + struct nand_jedec_params *p; + struct jedec_ecc_info *ecc; + int jedec_version = 0; + char id[5]; + int i, val, ret; + + /* Try JEDEC for unknown chip or LP */ + ret = nand_readid_op(chip, 0x40, id, sizeof(id)); + if (ret || strncmp(id, "JEDEC", sizeof(id))) + return 0; + + /* JEDEC chip: allocate a buffer to hold its parameter page */ + p = kzalloc(sizeof(*p), GFP_KERNEL); + if (!p) + return -ENOMEM; + + ret = nand_read_param_page_op(chip, 0x40, NULL, 0); + if (ret) { + ret = 0; + goto free_jedec_param_page; + } + + for (i = 0; i < 3; i++) { + ret = nand_read_data_op(chip, p, sizeof(*p), true); + if (ret) { + ret = 0; + goto free_jedec_param_page; + } + + if (onfi_crc16(ONFI_CRC_BASE, (uint8_t *)p, 510) == + le16_to_cpu(p->crc)) + break; + } + + if (i == 3) { + pr_err("Could not find valid JEDEC parameter page; aborting\n"); + goto free_jedec_param_page; + } + + /* Check version */ + val = le16_to_cpu(p->revision); + if (val & (1 << 2)) + jedec_version = 10; + else if (val & (1 << 1)) + jedec_version = 1; /* vendor specific version */ + + if (!jedec_version) { + pr_info("unsupported JEDEC version: %d\n", val); + goto free_jedec_param_page; + } + + sanitize_string(p->manufacturer, sizeof(p->manufacturer)); + sanitize_string(p->model, sizeof(p->model)); + chip->parameters.model = kstrdup(p->model, GFP_KERNEL); + if (!chip->parameters.model) { + ret = -ENOMEM; + goto free_jedec_param_page; + } + + mtd->writesize = le32_to_cpu(p->byte_per_page); + + /* Please reference to the comment for nand_flash_detect_onfi. */ + mtd->erasesize = 1 << (fls(le32_to_cpu(p->pages_per_block)) - 1); + mtd->erasesize *= mtd->writesize; + + mtd->oobsize = le16_to_cpu(p->spare_bytes_per_page); + + /* Please reference to the comment for nand_flash_detect_onfi. */ + chip->chipsize = 1 << (fls(le32_to_cpu(p->blocks_per_lun)) - 1); + chip->chipsize *= (uint64_t)mtd->erasesize * p->lun_count; + chip->bits_per_cell = p->bits_per_cell; + + if (le16_to_cpu(p->features) & JEDEC_FEATURE_16_BIT_BUS) + chip->options |= NAND_BUSWIDTH_16; + + /* ECC info */ + ecc = &p->ecc_info[0]; + + if (ecc->codeword_size >= 9) { + chip->ecc_strength_ds = ecc->ecc_bits; + chip->ecc_step_ds = 1 << ecc->codeword_size; + } else { + pr_warn("Invalid codeword size\n"); + } + +free_jedec_param_page: + kfree(p); + return ret; +} diff --git a/include/linux/mtd/jedec.h b/include/linux/mtd/jedec.h new file mode 100644 index 000000000000..0b6b59f7cfbd --- /dev/null +++ b/include/linux/mtd/jedec.h @@ -0,0 +1,91 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright © 2000-2010 David Woodhouse + * Steven J. Hill + * Thomas Gleixner + * + * Contains all JEDEC related definitions + */ + +#ifndef __LINUX_MTD_JEDEC_H +#define __LINUX_MTD_JEDEC_H + +struct jedec_ecc_info { + u8 ecc_bits; + u8 codeword_size; + __le16 bb_per_lun; + __le16 block_endurance; + u8 reserved[2]; +} __packed; + +/* JEDEC features */ +#define JEDEC_FEATURE_16_BIT_BUS (1 << 0) + +struct nand_jedec_params { + /* rev info and features block */ + /* 'J' 'E' 'S' 'D' */ + u8 sig[4]; + __le16 revision; + __le16 features; + u8 opt_cmd[3]; + __le16 sec_cmd; + u8 num_of_param_pages; + u8 reserved0[18]; + + /* manufacturer information block */ + char manufacturer[12]; + char model[20]; + u8 jedec_id[6]; + u8 reserved1[10]; + + /* memory organization block */ + __le32 byte_per_page; + __le16 spare_bytes_per_page; + u8 reserved2[6]; + __le32 pages_per_block; + __le32 blocks_per_lun; + u8 lun_count; + u8 addr_cycles; + u8 bits_per_cell; + u8 programs_per_page; + u8 multi_plane_addr; + u8 multi_plane_op_attr; + u8 reserved3[38]; + + /* electrical parameter block */ + __le16 async_sdr_speed_grade; + __le16 toggle_ddr_speed_grade; + __le16 sync_ddr_speed_grade; + u8 async_sdr_features; + u8 toggle_ddr_features; + u8 sync_ddr_features; + __le16 t_prog; + __le16 t_bers; + __le16 t_r; + __le16 t_r_multi_plane; + __le16 t_ccs; + __le16 io_pin_capacitance_typ; + __le16 input_pin_capacitance_typ; + __le16 clk_pin_capacitance_typ; + u8 driver_strength_support; + __le16 t_adl; + u8 reserved4[36]; + + /* ECC and endurance block */ + u8 guaranteed_good_blocks; + __le16 guaranteed_block_endurance; + struct jedec_ecc_info ecc_info[4]; + u8 reserved5[29]; + + /* reserved */ + u8 reserved6[148]; + + /* vendor */ + __le16 vendor_rev_num; + u8 reserved7[88]; + + /* CRC for Parameter Page */ + __le16 crc; +} __packed; + +#endif /* __LINUX_MTD_JEDEC_H */ diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h index f4fc0cce7c55..68d09e01fa56 100644 --- a/include/linux/mtd/rawnand.h +++ b/include/linux/mtd/rawnand.h @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -205,84 +206,6 @@ enum nand_ecc_algo { #define NAND_CI_CELLTYPE_MSK 0x0C #define NAND_CI_CELLTYPE_SHIFT 2 -struct jedec_ecc_info { - u8 ecc_bits; - u8 codeword_size; - __le16 bb_per_lun; - __le16 block_endurance; - u8 reserved[2]; -} __packed; - -/* JEDEC features */ -#define JEDEC_FEATURE_16_BIT_BUS (1 << 0) - -struct nand_jedec_params { - /* rev info and features block */ - /* 'J' 'E' 'S' 'D' */ - u8 sig[4]; - __le16 revision; - __le16 features; - u8 opt_cmd[3]; - __le16 sec_cmd; - u8 num_of_param_pages; - u8 reserved0[18]; - - /* manufacturer information block */ - char manufacturer[12]; - char model[20]; - u8 jedec_id[6]; - u8 reserved1[10]; - - /* memory organization block */ - __le32 byte_per_page; - __le16 spare_bytes_per_page; - u8 reserved2[6]; - __le32 pages_per_block; - __le32 blocks_per_lun; - u8 lun_count; - u8 addr_cycles; - u8 bits_per_cell; - u8 programs_per_page; - u8 multi_plane_addr; - u8 multi_plane_op_attr; - u8 reserved3[38]; - - /* electrical parameter block */ - __le16 async_sdr_speed_grade; - __le16 toggle_ddr_speed_grade; - __le16 sync_ddr_speed_grade; - u8 async_sdr_features; - u8 toggle_ddr_features; - u8 sync_ddr_features; - __le16 t_prog; - __le16 t_bers; - __le16 t_r; - __le16 t_r_multi_plane; - __le16 t_ccs; - __le16 io_pin_capacitance_typ; - __le16 input_pin_capacitance_typ; - __le16 clk_pin_capacitance_typ; - u8 driver_strength_support; - __le16 t_adl; - u8 reserved4[36]; - - /* ECC and endurance block */ - u8 guaranteed_good_blocks; - __le16 guaranteed_block_endurance; - struct jedec_ecc_info ecc_info[4]; - u8 reserved5[29]; - - /* reserved */ - u8 reserved6[148]; - - /* vendor */ - __le16 vendor_rev_num; - u8 reserved7[88]; - - /* CRC for Parameter Page */ - __le16 crc; -} __packed; - /** * struct nand_parameters - NAND generic parameters from the parameter page * @model: Model name From 727d37826bd19905424d6f5cf8351fcb4be71206 Mon Sep 17 00:00:00 2001 From: Marcel Ziswiler Date: Thu, 6 Sep 2018 23:30:19 +0200 Subject: [PATCH 289/302] mtd: rawnand: reorder NAND manufacturer IDs Reorder NAND manufacturer IDs for clarity. Signed-off-by: Marcel Ziswiler Signed-off-by: Miquel Raynal --- drivers/mtd/nand/raw/internals.h | 28 ++++++++++++++-------------- drivers/mtd/nand/raw/nand_ids.c | 20 ++++++++++---------- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/drivers/mtd/nand/raw/internals.h b/drivers/mtd/nand/raw/internals.h index 88b5da620e7d..f624b7b80413 100644 --- a/drivers/mtd/nand/raw/internals.h +++ b/drivers/mtd/nand/raw/internals.h @@ -16,21 +16,21 @@ /* * NAND Flash Manufacturer ID Codes */ -#define NAND_MFR_TOSHIBA 0x98 +#define NAND_MFR_AMD 0x01 +#define NAND_MFR_ATO 0x9b +#define NAND_MFR_EON 0x92 #define NAND_MFR_ESMT 0xc8 -#define NAND_MFR_SAMSUNG 0xec #define NAND_MFR_FUJITSU 0x04 +#define NAND_MFR_HYNIX 0xad +#define NAND_MFR_INTEL 0x89 +#define NAND_MFR_MACRONIX 0xc2 +#define NAND_MFR_MICRON 0x2c #define NAND_MFR_NATIONAL 0x8f #define NAND_MFR_RENESAS 0x07 -#define NAND_MFR_STMICRO 0x20 -#define NAND_MFR_HYNIX 0xad -#define NAND_MFR_MICRON 0x2c -#define NAND_MFR_AMD 0x01 -#define NAND_MFR_MACRONIX 0xc2 -#define NAND_MFR_EON 0x92 +#define NAND_MFR_SAMSUNG 0xec #define NAND_MFR_SANDISK 0x45 -#define NAND_MFR_INTEL 0x89 -#define NAND_MFR_ATO 0x9b +#define NAND_MFR_STMICRO 0x20 +#define NAND_MFR_TOSHIBA 0x98 #define NAND_MFR_WINBOND 0xef /** @@ -66,12 +66,12 @@ struct nand_manufacturer { extern struct nand_flash_dev nand_flash_ids[]; -extern const struct nand_manufacturer_ops toshiba_nand_manuf_ops; -extern const struct nand_manufacturer_ops samsung_nand_manuf_ops; -extern const struct nand_manufacturer_ops hynix_nand_manuf_ops; -extern const struct nand_manufacturer_ops micron_nand_manuf_ops; extern const struct nand_manufacturer_ops amd_nand_manuf_ops; +extern const struct nand_manufacturer_ops hynix_nand_manuf_ops; extern const struct nand_manufacturer_ops macronix_nand_manuf_ops; +extern const struct nand_manufacturer_ops micron_nand_manuf_ops; +extern const struct nand_manufacturer_ops samsung_nand_manuf_ops; +extern const struct nand_manufacturer_ops toshiba_nand_manuf_ops; /* Core functions */ const struct nand_manufacturer *nand_get_manufacturer(u8 id); diff --git a/drivers/mtd/nand/raw/nand_ids.c b/drivers/mtd/nand/raw/nand_ids.c index 12d39ccd1cff..fd0a7f711100 100644 --- a/drivers/mtd/nand/raw/nand_ids.c +++ b/drivers/mtd/nand/raw/nand_ids.c @@ -171,21 +171,21 @@ struct nand_flash_dev nand_flash_ids[] = { /* Manufacturer IDs */ static const struct nand_manufacturer nand_manufacturers[] = { - {NAND_MFR_TOSHIBA, "Toshiba", &toshiba_nand_manuf_ops}, + {NAND_MFR_AMD, "AMD/Spansion", &amd_nand_manuf_ops}, + {NAND_MFR_ATO, "ATO"}, + {NAND_MFR_EON, "Eon"}, {NAND_MFR_ESMT, "ESMT"}, - {NAND_MFR_SAMSUNG, "Samsung", &samsung_nand_manuf_ops}, {NAND_MFR_FUJITSU, "Fujitsu"}, + {NAND_MFR_HYNIX, "Hynix", &hynix_nand_manuf_ops}, + {NAND_MFR_INTEL, "Intel"}, + {NAND_MFR_MACRONIX, "Macronix", ¯onix_nand_manuf_ops}, + {NAND_MFR_MICRON, "Micron", µn_nand_manuf_ops}, {NAND_MFR_NATIONAL, "National"}, {NAND_MFR_RENESAS, "Renesas"}, - {NAND_MFR_STMICRO, "ST Micro"}, - {NAND_MFR_HYNIX, "Hynix", &hynix_nand_manuf_ops}, - {NAND_MFR_MICRON, "Micron", µn_nand_manuf_ops}, - {NAND_MFR_AMD, "AMD/Spansion", &amd_nand_manuf_ops}, - {NAND_MFR_MACRONIX, "Macronix", ¯onix_nand_manuf_ops}, - {NAND_MFR_EON, "Eon"}, + {NAND_MFR_SAMSUNG, "Samsung", &samsung_nand_manuf_ops}, {NAND_MFR_SANDISK, "SanDisk"}, - {NAND_MFR_INTEL, "Intel"}, - {NAND_MFR_ATO, "ATO"}, + {NAND_MFR_STMICRO, "ST Micro"}, + {NAND_MFR_TOSHIBA, "Toshiba", &toshiba_nand_manuf_ops}, {NAND_MFR_WINBOND, "Winbond"}, }; From a68642adbb1a80d1a70a472d01a8a32aaa1a96c4 Mon Sep 17 00:00:00 2001 From: Marcel Ziswiler Date: Wed, 19 Sep 2018 13:40:49 +0200 Subject: [PATCH 290/302] mtd: rawnand: ESMT: retrieve ECC requirements from 5th id byte This patch enables support to read the ECC level from the NAND flash using ESMT SLC NAND ID byte 5 information as documented e.g. in the following data sheet: https://www.esmt.com.tw/upload/pdf/ESMT/datasheets/F59L1G81LA(2Y).pdf Signed-off-by: Marcel Ziswiler Signed-off-by: Miquel Raynal --- drivers/mtd/nand/raw/Makefile | 1 + drivers/mtd/nand/raw/internals.h | 1 + drivers/mtd/nand/raw/nand_esmt.c | 47 ++++++++++++++++++++++++++++++++ drivers/mtd/nand/raw/nand_ids.c | 2 +- 4 files changed, 50 insertions(+), 1 deletion(-) create mode 100644 drivers/mtd/nand/raw/nand_esmt.c diff --git a/drivers/mtd/nand/raw/Makefile b/drivers/mtd/nand/raw/Makefile index be2c17863ee5..57159b349054 100644 --- a/drivers/mtd/nand/raw/Makefile +++ b/drivers/mtd/nand/raw/Makefile @@ -61,6 +61,7 @@ nand-objs := nand_base.o nand_legacy.o nand_bbt.o nand_timings.o nand_ids.o nand-objs += nand_onfi.o nand-objs += nand_jedec.o nand-objs += nand_amd.o +nand-objs += nand_esmt.o nand-objs += nand_hynix.o nand-objs += nand_macronix.o nand-objs += nand_micron.o diff --git a/drivers/mtd/nand/raw/internals.h b/drivers/mtd/nand/raw/internals.h index f624b7b80413..04c2cf74eff3 100644 --- a/drivers/mtd/nand/raw/internals.h +++ b/drivers/mtd/nand/raw/internals.h @@ -67,6 +67,7 @@ struct nand_manufacturer { extern struct nand_flash_dev nand_flash_ids[]; extern const struct nand_manufacturer_ops amd_nand_manuf_ops; +extern const struct nand_manufacturer_ops esmt_nand_manuf_ops; extern const struct nand_manufacturer_ops hynix_nand_manuf_ops; extern const struct nand_manufacturer_ops macronix_nand_manuf_ops; extern const struct nand_manufacturer_ops micron_nand_manuf_ops; diff --git a/drivers/mtd/nand/raw/nand_esmt.c b/drivers/mtd/nand/raw/nand_esmt.c new file mode 100644 index 000000000000..96f039a83bc8 --- /dev/null +++ b/drivers/mtd/nand/raw/nand_esmt.c @@ -0,0 +1,47 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2018 Toradex AG + * + * Author: Marcel Ziswiler + */ + +#include +#include "internals.h" + +static void esmt_nand_decode_id(struct nand_chip *chip) +{ + nand_decode_ext_id(chip); + + /* Extract ECC requirements from 5th id byte. */ + if (chip->id.len >= 5 && nand_is_slc(chip)) { + chip->ecc_step_ds = 512; + switch (chip->id.data[4] & 0x3) { + case 0x0: + chip->ecc_strength_ds = 4; + break; + case 0x1: + chip->ecc_strength_ds = 2; + break; + case 0x2: + chip->ecc_strength_ds = 1; + break; + default: + WARN(1, "Could not get ECC info"); + chip->ecc_step_ds = 0; + break; + } + } +} + +static int esmt_nand_init(struct nand_chip *chip) +{ + if (nand_is_slc(chip)) + chip->bbt_options |= NAND_BBT_SCAN2NDPAGE; + + return 0; +} + +const struct nand_manufacturer_ops esmt_nand_manuf_ops = { + .detect = esmt_nand_decode_id, + .init = esmt_nand_init, +}; diff --git a/drivers/mtd/nand/raw/nand_ids.c b/drivers/mtd/nand/raw/nand_ids.c index fd0a7f711100..ea5a342cd91e 100644 --- a/drivers/mtd/nand/raw/nand_ids.c +++ b/drivers/mtd/nand/raw/nand_ids.c @@ -174,7 +174,7 @@ static const struct nand_manufacturer nand_manufacturers[] = { {NAND_MFR_AMD, "AMD/Spansion", &amd_nand_manuf_ops}, {NAND_MFR_ATO, "ATO"}, {NAND_MFR_EON, "Eon"}, - {NAND_MFR_ESMT, "ESMT"}, + {NAND_MFR_ESMT, "ESMT", &esmt_nand_manuf_ops}, {NAND_MFR_FUJITSU, "Fujitsu"}, {NAND_MFR_HYNIX, "Hynix", &hynix_nand_manuf_ops}, {NAND_MFR_INTEL, "Intel"}, From e8237bfa21200f7c03a59503964cee47620ff3d7 Mon Sep 17 00:00:00 2001 From: Konstantin Porotchkin Date: Fri, 7 Sep 2018 16:34:36 +0200 Subject: [PATCH 291/302] mtd: rawnand: marvell: Add support for 8kiB pages NAND chips layout Add support for two new layouts: 8kiB pages NAND chips, requesting either 4 or 8 bit of correctability per 512B step. Signed-off-by: Konstantin Porotchkin Reviewed-by: Boris Brezillon Signed-off-by: Miquel Raynal --- drivers/mtd/nand/raw/marvell_nand.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/mtd/nand/raw/marvell_nand.c b/drivers/mtd/nand/raw/marvell_nand.c index 6639f2e2cea2..e63f714f7639 100644 --- a/drivers/mtd/nand/raw/marvell_nand.c +++ b/drivers/mtd/nand/raw/marvell_nand.c @@ -287,6 +287,8 @@ static const struct marvell_hw_ecc_layout marvell_nfc_layouts[] = { MARVELL_LAYOUT( 2048, 512, 8, 2, 1, 1024, 0, 30,1024,32, 30), MARVELL_LAYOUT( 4096, 512, 4, 2, 2, 2048, 32, 30, 0, 0, 0), MARVELL_LAYOUT( 4096, 512, 8, 5, 4, 1024, 0, 30, 0, 64, 30), + MARVELL_LAYOUT( 8192, 512, 4, 4, 4, 2048, 0, 30, 0, 0, 0), + MARVELL_LAYOUT( 8192, 512, 8, 9, 8, 1024, 0, 30, 0, 160, 30), }; /** From fbed20280d912449cfb40c382cb55e3d11502587 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Tue, 18 Sep 2018 08:55:55 -0500 Subject: [PATCH 292/302] mtd: rawnand: atmel: Fix potential NULL pointer dereference There is a potential execution path in which function of_find_compatible_node() returns NULL. In such a case, we end up having a NULL pointer dereference when accessing pointer *nfc_np* in function of_clk_get(). So, we better don't take any chances and fix this by null checking pointer *nfc_np* before calling of_clk_get(). Addresses-Coverity-ID: 1473052 ("Dereference null return value") Fixes: f88fc122cc34 ("mtd: nand: Cleanup/rework the atmel_nand driver") Signed-off-by: Gustavo A. R. Silva Reviewed-by: Boris Brezillon Acked-by: Tudor Ambarus Signed-off-by: Miquel Raynal --- drivers/mtd/nand/raw/atmel/nand-controller.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/mtd/nand/raw/atmel/nand-controller.c b/drivers/mtd/nand/raw/atmel/nand-controller.c index ad0245c66892..fb33f6be7c4f 100644 --- a/drivers/mtd/nand/raw/atmel/nand-controller.c +++ b/drivers/mtd/nand/raw/atmel/nand-controller.c @@ -2034,6 +2034,10 @@ atmel_hsmc_nand_controller_legacy_init(struct atmel_hsmc_nand_controller *nc) nand_np = dev->of_node; nfc_np = of_find_compatible_node(dev->of_node, NULL, "atmel,sama5d3-nfc"); + if (!nfc_np) { + dev_err(dev, "Could not find device node for sama5d3-nfc\n"); + return -ENODEV; + } nc->clk = of_clk_get(nfc_np, 0); if (IS_ERR(nc->clk)) { From f1a97e0b78e378f43660930474113387a2af2aa3 Mon Sep 17 00:00:00 2001 From: Janusz Krzysztofik Date: Thu, 20 Sep 2018 00:17:29 +0200 Subject: [PATCH 293/302] mtd: rawnand: ams-delta: use GPIO lookup table Now as Amstrad Delta board - the only user of this driver - provides GPIO lookup tables, switch from GPIO numbers to GPIO descriptors and use the table to locate required GPIO pins. Declare static variables for storing GPIO descriptors and replace gpio_ function calls with their gpiod_ equivalents. Pin naming used by the driver should be followed while respective GPIO lookup table is initialized by a board init code. Signed-off-by: Janusz Krzysztofik Acked-by: Boris Brezillon Reviewed-by: Linus Walleij Signed-off-by: Miquel Raynal --- drivers/mtd/nand/raw/ams-delta.c | 126 ++++++++++++++++--------------- 1 file changed, 67 insertions(+), 59 deletions(-) diff --git a/drivers/mtd/nand/raw/ams-delta.c b/drivers/mtd/nand/raw/ams-delta.c index 3d3786dcc5d1..a2d2dfc55984 100644 --- a/drivers/mtd/nand/raw/ams-delta.c +++ b/drivers/mtd/nand/raw/ams-delta.c @@ -20,23 +20,28 @@ #include #include #include +#include #include #include #include -#include #include #include #include -#include - #include /* * MTD structure for E3 (Delta) */ static struct mtd_info *ams_delta_mtd = NULL; +static struct gpio_desc *gpiod_rdy; +static struct gpio_desc *gpiod_nce; +static struct gpio_desc *gpiod_nre; +static struct gpio_desc *gpiod_nwp; +static struct gpio_desc *gpiod_nwe; +static struct gpio_desc *gpiod_ale; +static struct gpio_desc *gpiod_cle; /* * Define partitions for flash devices @@ -69,9 +74,9 @@ static void ams_delta_write_byte(struct nand_chip *this, u_char byte) writew(0, io_base + OMAP_MPUIO_IO_CNTL); writew(byte, this->legacy.IO_ADDR_W); - gpio_set_value(AMS_DELTA_GPIO_PIN_NAND_NWE, 0); + gpiod_set_value(gpiod_nwe, 0); ndelay(40); - gpio_set_value(AMS_DELTA_GPIO_PIN_NAND_NWE, 1); + gpiod_set_value(gpiod_nwe, 1); } static u_char ams_delta_read_byte(struct nand_chip *this) @@ -79,11 +84,11 @@ static u_char ams_delta_read_byte(struct nand_chip *this) u_char res; void __iomem *io_base = (void __iomem *)nand_get_controller_data(this); - gpio_set_value(AMS_DELTA_GPIO_PIN_NAND_NRE, 0); + gpiod_set_value(gpiod_nre, 0); ndelay(40); writew(~0, io_base + OMAP_MPUIO_IO_CNTL); res = readw(this->legacy.IO_ADDR_R); - gpio_set_value(AMS_DELTA_GPIO_PIN_NAND_NRE, 1); + gpiod_set_value(gpiod_nre, 1); return res; } @@ -118,12 +123,9 @@ static void ams_delta_hwcontrol(struct nand_chip *this, int cmd, { if (ctrl & NAND_CTRL_CHANGE) { - gpio_set_value(AMS_DELTA_GPIO_PIN_NAND_NCE, - (ctrl & NAND_NCE) == 0); - gpio_set_value(AMS_DELTA_GPIO_PIN_NAND_CLE, - (ctrl & NAND_CLE) != 0); - gpio_set_value(AMS_DELTA_GPIO_PIN_NAND_ALE, - (ctrl & NAND_ALE) != 0); + gpiod_set_value(gpiod_nce, !(ctrl & NAND_NCE)); + gpiod_set_value(gpiod_cle, !!(ctrl & NAND_CLE)); + gpiod_set_value(gpiod_ale, !!(ctrl & NAND_ALE)); } if (cmd != NAND_CMD_NONE) @@ -132,41 +134,9 @@ static void ams_delta_hwcontrol(struct nand_chip *this, int cmd, static int ams_delta_nand_ready(struct nand_chip *this) { - return gpio_get_value(AMS_DELTA_GPIO_PIN_NAND_RB); + return gpiod_get_value(gpiod_rdy); } -static const struct gpio _mandatory_gpio[] = { - { - .gpio = AMS_DELTA_GPIO_PIN_NAND_NCE, - .flags = GPIOF_OUT_INIT_HIGH, - .label = "nand_nce", - }, - { - .gpio = AMS_DELTA_GPIO_PIN_NAND_NRE, - .flags = GPIOF_OUT_INIT_HIGH, - .label = "nand_nre", - }, - { - .gpio = AMS_DELTA_GPIO_PIN_NAND_NWP, - .flags = GPIOF_OUT_INIT_HIGH, - .label = "nand_nwp", - }, - { - .gpio = AMS_DELTA_GPIO_PIN_NAND_NWE, - .flags = GPIOF_OUT_INIT_HIGH, - .label = "nand_nwe", - }, - { - .gpio = AMS_DELTA_GPIO_PIN_NAND_ALE, - .flags = GPIOF_OUT_INIT_LOW, - .label = "nand_ale", - }, - { - .gpio = AMS_DELTA_GPIO_PIN_NAND_CLE, - .flags = GPIOF_OUT_INIT_LOW, - .label = "nand_cle", - }, -}; /* * Main initialization routine @@ -214,12 +184,17 @@ static int ams_delta_init(struct platform_device *pdev) this->legacy.write_buf = ams_delta_write_buf; this->legacy.read_buf = ams_delta_read_buf; this->legacy.cmd_ctrl = ams_delta_hwcontrol; - if (gpio_request(AMS_DELTA_GPIO_PIN_NAND_RB, "nand_rdy") == 0) { - this->legacy.dev_ready = ams_delta_nand_ready; - } else { - this->legacy.dev_ready = NULL; - pr_notice("Couldn't request gpio for Delta NAND ready.\n"); + + gpiod_rdy = devm_gpiod_get_optional(&pdev->dev, "rdy", GPIOD_IN); + if (IS_ERR(gpiod_rdy)) { + err = PTR_ERR(gpiod_rdy); + dev_warn(&pdev->dev, "RDY GPIO request failed (%d)\n", err); + goto out_mtd; } + + if (gpiod_rdy) + this->legacy.dev_ready = ams_delta_nand_ready; + /* 25 us command delay time */ this->legacy.chip_delay = 30; this->ecc.mode = NAND_ECC_SOFT; @@ -228,9 +203,47 @@ static int ams_delta_init(struct platform_device *pdev) platform_set_drvdata(pdev, io_base); /* Set chip enabled, but */ - err = gpio_request_array(_mandatory_gpio, ARRAY_SIZE(_mandatory_gpio)); - if (err) - goto out_gpio; + gpiod_nwp = devm_gpiod_get(&pdev->dev, "nwp", GPIOD_OUT_HIGH); + if (IS_ERR(gpiod_nwp)) { + err = PTR_ERR(gpiod_nwp); + dev_err(&pdev->dev, "NWP GPIO request failed (%d)\n", err); + goto out_mtd; + } + + gpiod_nce = devm_gpiod_get(&pdev->dev, "nce", GPIOD_OUT_HIGH); + if (IS_ERR(gpiod_nce)) { + err = PTR_ERR(gpiod_nce); + dev_err(&pdev->dev, "NCE GPIO request failed (%d)\n", err); + goto out_mtd; + } + + gpiod_nre = devm_gpiod_get(&pdev->dev, "nre", GPIOD_OUT_HIGH); + if (IS_ERR(gpiod_nre)) { + err = PTR_ERR(gpiod_nre); + dev_err(&pdev->dev, "NRE GPIO request failed (%d)\n", err); + goto out_mtd; + } + + gpiod_nwe = devm_gpiod_get(&pdev->dev, "nwe", GPIOD_OUT_HIGH); + if (IS_ERR(gpiod_nwe)) { + err = PTR_ERR(gpiod_nwe); + dev_err(&pdev->dev, "NWE GPIO request failed (%d)\n", err); + goto out_mtd; + } + + gpiod_ale = devm_gpiod_get(&pdev->dev, "ale", GPIOD_OUT_LOW); + if (IS_ERR(gpiod_ale)) { + err = PTR_ERR(gpiod_ale); + dev_err(&pdev->dev, "ALE GPIO request failed (%d)\n", err); + goto out_mtd; + } + + gpiod_cle = devm_gpiod_get(&pdev->dev, "cle", GPIOD_OUT_LOW); + if (IS_ERR(gpiod_cle)) { + err = PTR_ERR(gpiod_cle); + dev_err(&pdev->dev, "CLE GPIO request failed (%d)\n", err); + goto out_mtd; + } /* Scan to find existence of the device */ err = nand_scan(this, 1); @@ -244,9 +257,6 @@ static int ams_delta_init(struct platform_device *pdev) goto out; out_mtd: - gpio_free_array(_mandatory_gpio, ARRAY_SIZE(_mandatory_gpio)); -out_gpio: - gpio_free(AMS_DELTA_GPIO_PIN_NAND_RB); iounmap(io_base); out_free: kfree(this); @@ -264,8 +274,6 @@ static int ams_delta_cleanup(struct platform_device *pdev) /* Release resources, unregister device */ nand_release(mtd_to_nand(ams_delta_mtd)); - gpio_free_array(_mandatory_gpio, ARRAY_SIZE(_mandatory_gpio)); - gpio_free(AMS_DELTA_GPIO_PIN_NAND_RB); iounmap(io_base); /* Free the MTD device structure */ From e5cd979994db7ab0d496fd9ccdf4744da5e2764b Mon Sep 17 00:00:00 2001 From: Janusz Krzysztofik Date: Thu, 20 Sep 2018 00:52:53 +0200 Subject: [PATCH 294/302] mtd: rawnand: ams-delta: show parent device in sysfs Fix a bug where parent device symlinks aren't shown in sysfs. While at it, make use of the default owner set by mtdcore. Signed-off-by: Janusz Krzysztofik Reviewed-by: Boris Brezillon Signed-off-by: Miquel Raynal --- drivers/mtd/nand/raw/ams-delta.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mtd/nand/raw/ams-delta.c b/drivers/mtd/nand/raw/ams-delta.c index a2d2dfc55984..efe12066dfbc 100644 --- a/drivers/mtd/nand/raw/ams-delta.c +++ b/drivers/mtd/nand/raw/ams-delta.c @@ -160,7 +160,7 @@ static int ams_delta_init(struct platform_device *pdev) } ams_delta_mtd = nand_to_mtd(this); - ams_delta_mtd->owner = THIS_MODULE; + ams_delta_mtd->dev.parent = &pdev->dev; /* * Don't try to request the memory region from here, From 2b44af3ad6cc5e39267791215cfef974fb3f7be5 Mon Sep 17 00:00:00 2001 From: Janusz Krzysztofik Date: Thu, 20 Sep 2018 00:52:54 +0200 Subject: [PATCH 295/302] mtd: rawnand: ams-delta: Use private structure Introduce a driver private structure and allocate it on device probe. Use it for storing nand_chip structure, GPIO descriptors prevoiusly stored in static variables as well as io_base pointer previously passed as nand controller data or platform driver data. Subsequent patches may populate the structure with more members as needed. Signed-off-by: Janusz Krzysztofik Reviewed-by: Boris Brezillon Signed-off-by: Miquel Raynal --- drivers/mtd/nand/raw/ams-delta.c | 122 +++++++++++++++++-------------- 1 file changed, 66 insertions(+), 56 deletions(-) diff --git a/drivers/mtd/nand/raw/ams-delta.c b/drivers/mtd/nand/raw/ams-delta.c index efe12066dfbc..eb2aeadc3b65 100644 --- a/drivers/mtd/nand/raw/ams-delta.c +++ b/drivers/mtd/nand/raw/ams-delta.c @@ -34,14 +34,18 @@ /* * MTD structure for E3 (Delta) */ -static struct mtd_info *ams_delta_mtd = NULL; -static struct gpio_desc *gpiod_rdy; -static struct gpio_desc *gpiod_nce; -static struct gpio_desc *gpiod_nre; -static struct gpio_desc *gpiod_nwp; -static struct gpio_desc *gpiod_nwe; -static struct gpio_desc *gpiod_ale; -static struct gpio_desc *gpiod_cle; + +struct ams_delta_nand { + struct nand_chip nand_chip; + struct gpio_desc *gpiod_rdy; + struct gpio_desc *gpiod_nce; + struct gpio_desc *gpiod_nre; + struct gpio_desc *gpiod_nwp; + struct gpio_desc *gpiod_nwe; + struct gpio_desc *gpiod_ale; + struct gpio_desc *gpiod_cle; + void __iomem *io_base; +}; /* * Define partitions for flash devices @@ -70,25 +74,27 @@ static const struct mtd_partition partition_info[] = { static void ams_delta_write_byte(struct nand_chip *this, u_char byte) { - void __iomem *io_base = (void __iomem *)nand_get_controller_data(this); + struct ams_delta_nand *priv = nand_get_controller_data(this); + void __iomem *io_base = priv->io_base; writew(0, io_base + OMAP_MPUIO_IO_CNTL); writew(byte, this->legacy.IO_ADDR_W); - gpiod_set_value(gpiod_nwe, 0); + gpiod_set_value(priv->gpiod_nwe, 0); ndelay(40); - gpiod_set_value(gpiod_nwe, 1); + gpiod_set_value(priv->gpiod_nwe, 1); } static u_char ams_delta_read_byte(struct nand_chip *this) { u_char res; - void __iomem *io_base = (void __iomem *)nand_get_controller_data(this); + struct ams_delta_nand *priv = nand_get_controller_data(this); + void __iomem *io_base = priv->io_base; - gpiod_set_value(gpiod_nre, 0); + gpiod_set_value(priv->gpiod_nre, 0); ndelay(40); writew(~0, io_base + OMAP_MPUIO_IO_CNTL); res = readw(this->legacy.IO_ADDR_R); - gpiod_set_value(gpiod_nre, 1); + gpiod_set_value(priv->gpiod_nre, 1); return res; } @@ -121,11 +127,12 @@ static void ams_delta_read_buf(struct nand_chip *this, u_char *buf, int len) static void ams_delta_hwcontrol(struct nand_chip *this, int cmd, unsigned int ctrl) { + struct ams_delta_nand *priv = nand_get_controller_data(this); if (ctrl & NAND_CTRL_CHANGE) { - gpiod_set_value(gpiod_nce, !(ctrl & NAND_NCE)); - gpiod_set_value(gpiod_cle, !!(ctrl & NAND_CLE)); - gpiod_set_value(gpiod_ale, !!(ctrl & NAND_ALE)); + gpiod_set_value(priv->gpiod_nce, !(ctrl & NAND_NCE)); + gpiod_set_value(priv->gpiod_cle, !!(ctrl & NAND_CLE)); + gpiod_set_value(priv->gpiod_ale, !!(ctrl & NAND_ALE)); } if (cmd != NAND_CMD_NONE) @@ -134,7 +141,9 @@ static void ams_delta_hwcontrol(struct nand_chip *this, int cmd, static int ams_delta_nand_ready(struct nand_chip *this) { - return gpiod_get_value(gpiod_rdy); + struct ams_delta_nand *priv = nand_get_controller_data(this); + + return gpiod_get_value(priv->gpiod_rdy); } @@ -143,7 +152,9 @@ static int ams_delta_nand_ready(struct nand_chip *this) */ static int ams_delta_init(struct platform_device *pdev) { + struct ams_delta_nand *priv; struct nand_chip *this; + struct mtd_info *mtd; struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); void __iomem *io_base; int err = 0; @@ -152,15 +163,16 @@ static int ams_delta_init(struct platform_device *pdev) return -ENXIO; /* Allocate memory for MTD device structure and private data */ - this = kzalloc(sizeof(struct nand_chip), GFP_KERNEL); - if (!this) { + priv = devm_kzalloc(&pdev->dev, sizeof(struct ams_delta_nand), + GFP_KERNEL); + if (!priv) { pr_warn("Unable to allocate E3 NAND MTD device structure.\n"); - err = -ENOMEM; - goto out; + return -ENOMEM; } + this = &priv->nand_chip; - ams_delta_mtd = nand_to_mtd(this); - ams_delta_mtd->dev.parent = &pdev->dev; + mtd = nand_to_mtd(this); + mtd->dev.parent = &pdev->dev; /* * Don't try to request the memory region from here, @@ -175,7 +187,8 @@ static int ams_delta_init(struct platform_device *pdev) goto out_free; } - nand_set_controller_data(this, (void *)io_base); + priv->io_base = io_base; + nand_set_controller_data(this, priv); /* Set address of NAND IO lines */ this->legacy.IO_ADDR_R = io_base + OMAP_MPUIO_INPUT_LATCH; @@ -185,14 +198,14 @@ static int ams_delta_init(struct platform_device *pdev) this->legacy.read_buf = ams_delta_read_buf; this->legacy.cmd_ctrl = ams_delta_hwcontrol; - gpiod_rdy = devm_gpiod_get_optional(&pdev->dev, "rdy", GPIOD_IN); - if (IS_ERR(gpiod_rdy)) { - err = PTR_ERR(gpiod_rdy); + priv->gpiod_rdy = devm_gpiod_get_optional(&pdev->dev, "rdy", GPIOD_IN); + if (IS_ERR(priv->gpiod_rdy)) { + err = PTR_ERR(priv->gpiod_rdy); dev_warn(&pdev->dev, "RDY GPIO request failed (%d)\n", err); goto out_mtd; } - if (gpiod_rdy) + if (priv->gpiod_rdy) this->legacy.dev_ready = ams_delta_nand_ready; /* 25 us command delay time */ @@ -200,47 +213,47 @@ static int ams_delta_init(struct platform_device *pdev) this->ecc.mode = NAND_ECC_SOFT; this->ecc.algo = NAND_ECC_HAMMING; - platform_set_drvdata(pdev, io_base); + platform_set_drvdata(pdev, priv); /* Set chip enabled, but */ - gpiod_nwp = devm_gpiod_get(&pdev->dev, "nwp", GPIOD_OUT_HIGH); - if (IS_ERR(gpiod_nwp)) { - err = PTR_ERR(gpiod_nwp); + priv->gpiod_nwp = devm_gpiod_get(&pdev->dev, "nwp", GPIOD_OUT_HIGH); + if (IS_ERR(priv->gpiod_nwp)) { + err = PTR_ERR(priv->gpiod_nwp); dev_err(&pdev->dev, "NWP GPIO request failed (%d)\n", err); goto out_mtd; } - gpiod_nce = devm_gpiod_get(&pdev->dev, "nce", GPIOD_OUT_HIGH); - if (IS_ERR(gpiod_nce)) { - err = PTR_ERR(gpiod_nce); + priv->gpiod_nce = devm_gpiod_get(&pdev->dev, "nce", GPIOD_OUT_HIGH); + if (IS_ERR(priv->gpiod_nce)) { + err = PTR_ERR(priv->gpiod_nce); dev_err(&pdev->dev, "NCE GPIO request failed (%d)\n", err); goto out_mtd; } - gpiod_nre = devm_gpiod_get(&pdev->dev, "nre", GPIOD_OUT_HIGH); - if (IS_ERR(gpiod_nre)) { - err = PTR_ERR(gpiod_nre); + priv->gpiod_nre = devm_gpiod_get(&pdev->dev, "nre", GPIOD_OUT_HIGH); + if (IS_ERR(priv->gpiod_nre)) { + err = PTR_ERR(priv->gpiod_nre); dev_err(&pdev->dev, "NRE GPIO request failed (%d)\n", err); goto out_mtd; } - gpiod_nwe = devm_gpiod_get(&pdev->dev, "nwe", GPIOD_OUT_HIGH); - if (IS_ERR(gpiod_nwe)) { - err = PTR_ERR(gpiod_nwe); + priv->gpiod_nwe = devm_gpiod_get(&pdev->dev, "nwe", GPIOD_OUT_HIGH); + if (IS_ERR(priv->gpiod_nwe)) { + err = PTR_ERR(priv->gpiod_nwe); dev_err(&pdev->dev, "NWE GPIO request failed (%d)\n", err); goto out_mtd; } - gpiod_ale = devm_gpiod_get(&pdev->dev, "ale", GPIOD_OUT_LOW); - if (IS_ERR(gpiod_ale)) { - err = PTR_ERR(gpiod_ale); + priv->gpiod_ale = devm_gpiod_get(&pdev->dev, "ale", GPIOD_OUT_LOW); + if (IS_ERR(priv->gpiod_ale)) { + err = PTR_ERR(priv->gpiod_ale); dev_err(&pdev->dev, "ALE GPIO request failed (%d)\n", err); goto out_mtd; } - gpiod_cle = devm_gpiod_get(&pdev->dev, "cle", GPIOD_OUT_LOW); - if (IS_ERR(gpiod_cle)) { - err = PTR_ERR(gpiod_cle); + priv->gpiod_cle = devm_gpiod_get(&pdev->dev, "cle", GPIOD_OUT_LOW); + if (IS_ERR(priv->gpiod_cle)) { + err = PTR_ERR(priv->gpiod_cle); dev_err(&pdev->dev, "CLE GPIO request failed (%d)\n", err); goto out_mtd; } @@ -251,15 +264,13 @@ static int ams_delta_init(struct platform_device *pdev) goto out_mtd; /* Register the partitions */ - mtd_device_register(ams_delta_mtd, partition_info, - ARRAY_SIZE(partition_info)); + mtd_device_register(mtd, partition_info, ARRAY_SIZE(partition_info)); goto out; out_mtd: iounmap(io_base); out_free: - kfree(this); out: return err; } @@ -269,16 +280,15 @@ static int ams_delta_init(struct platform_device *pdev) */ static int ams_delta_cleanup(struct platform_device *pdev) { - void __iomem *io_base = platform_get_drvdata(pdev); + struct ams_delta_nand *priv = platform_get_drvdata(pdev); + struct mtd_info *mtd = nand_to_mtd(&priv->nand_chip); + void __iomem *io_base = priv->io_base; /* Release resources, unregister device */ - nand_release(mtd_to_nand(ams_delta_mtd)); + nand_release(mtd_to_nand(mtd)); iounmap(io_base); - /* Free the MTD device structure */ - kfree(mtd_to_nand(ams_delta_mtd)); - return 0; } From 9c076d7e948773ac45cf1ec7ca2c7d6a5bddb8fa Mon Sep 17 00:00:00 2001 From: Janusz Krzysztofik Date: Thu, 20 Sep 2018 00:52:55 +0200 Subject: [PATCH 296/302] mtd: rawnand: ams-delta: Set port direction when needed In its current shape, the driver sets data port direction before each byte read/write operation, even during multi-byte transfers. Improve performance of the driver by setting the port direction only when needed. This optimisation will become particularly important as soon as planned conversion of the driver to GPIO API for data I/O will be implemented. Reviewed-by: Boris Brezillon Signed-off-by: Janusz Krzysztofik Signed-off-by: Miquel Raynal --- drivers/mtd/nand/raw/ams-delta.c | 57 ++++++++++++++++++++++---------- 1 file changed, 40 insertions(+), 17 deletions(-) diff --git a/drivers/mtd/nand/raw/ams-delta.c b/drivers/mtd/nand/raw/ams-delta.c index eb2aeadc3b65..5ba180a291eb 100644 --- a/drivers/mtd/nand/raw/ams-delta.c +++ b/drivers/mtd/nand/raw/ams-delta.c @@ -45,6 +45,7 @@ struct ams_delta_nand { struct gpio_desc *gpiod_ale; struct gpio_desc *gpiod_cle; void __iomem *io_base; + bool data_in; }; /* @@ -72,48 +73,64 @@ static const struct mtd_partition partition_info[] = { .size = 3 * SZ_256K }, }; -static void ams_delta_write_byte(struct nand_chip *this, u_char byte) +static void ams_delta_io_write(struct ams_delta_nand *priv, u_char byte) { - struct ams_delta_nand *priv = nand_get_controller_data(this); - void __iomem *io_base = priv->io_base; - - writew(0, io_base + OMAP_MPUIO_IO_CNTL); - writew(byte, this->legacy.IO_ADDR_W); + writew(byte, priv->nand_chip.legacy.IO_ADDR_W); gpiod_set_value(priv->gpiod_nwe, 0); ndelay(40); gpiod_set_value(priv->gpiod_nwe, 1); } -static u_char ams_delta_read_byte(struct nand_chip *this) +static u_char ams_delta_io_read(struct ams_delta_nand *priv) { u_char res; - struct ams_delta_nand *priv = nand_get_controller_data(this); - void __iomem *io_base = priv->io_base; gpiod_set_value(priv->gpiod_nre, 0); ndelay(40); - writew(~0, io_base + OMAP_MPUIO_IO_CNTL); - res = readw(this->legacy.IO_ADDR_R); + res = readw(priv->nand_chip.legacy.IO_ADDR_R); gpiod_set_value(priv->gpiod_nre, 1); return res; } +static void ams_delta_dir_input(struct ams_delta_nand *priv, bool in) +{ + writew(in ? ~0 : 0, priv->io_base + OMAP_MPUIO_IO_CNTL); + priv->data_in = in; +} + static void ams_delta_write_buf(struct nand_chip *this, const u_char *buf, int len) { + struct ams_delta_nand *priv = nand_get_controller_data(this); int i; - for (i=0; idata_in) + ams_delta_dir_input(priv, false); + + for (i = 0; i < len; i++) + ams_delta_io_write(priv, buf[i]); } static void ams_delta_read_buf(struct nand_chip *this, u_char *buf, int len) { + struct ams_delta_nand *priv = nand_get_controller_data(this); int i; - for (i=0; idata_in) + ams_delta_dir_input(priv, true); + + for (i = 0; i < len; i++) + buf[i] = ams_delta_io_read(priv); +} + +static u_char ams_delta_read_byte(struct nand_chip *this) +{ + u_char res; + + ams_delta_read_buf(this, &res, 1); + + return res; } /* @@ -135,8 +152,11 @@ static void ams_delta_hwcontrol(struct nand_chip *this, int cmd, gpiod_set_value(priv->gpiod_ale, !!(ctrl & NAND_ALE)); } - if (cmd != NAND_CMD_NONE) - ams_delta_write_byte(this, cmd); + if (cmd != NAND_CMD_NONE) { + u_char byte = cmd; + + ams_delta_write_buf(this, &byte, 1); + } } static int ams_delta_nand_ready(struct nand_chip *this) @@ -258,6 +278,9 @@ static int ams_delta_init(struct platform_device *pdev) goto out_mtd; } + /* Initialize data port direction to a known state */ + ams_delta_dir_input(priv, true); + /* Scan to find existence of the device */ err = nand_scan(this, 1); if (err) From e2bfa4ca23d9b5a7bdfcf21319fad9b59e38a05c Mon Sep 17 00:00:00 2001 From: Nathan Chancellor Date: Thu, 20 Sep 2018 16:30:25 -0700 Subject: [PATCH 297/302] mtd: rawnand: sh_flctl: Use proper enum for flctl_dma_fifo0_transfer Clang warns when one enumerated type is converted implicitly to another: drivers/mtd/nand/raw/sh_flctl.c:483:46: warning: implicit conversion from enumeration type 'enum dma_transfer_direction' to different enumeration type 'enum dma_data_direction' [-Wenum-conversion] flctl_dma_fifo0_transfer(flctl, buf, rlen, DMA_DEV_TO_MEM) > 0) ~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~ drivers/mtd/nand/raw/sh_flctl.c:542:46: warning: implicit conversion from enumeration type 'enum dma_transfer_direction' to different enumeration type 'enum dma_data_direction' [-Wenum-conversion] flctl_dma_fifo0_transfer(flctl, buf, rlen, DMA_MEM_TO_DEV) > 0) ~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~ 2 warnings generated. Use the proper enums from dma_data_direction to satisfy Clang. DMA_MEM_TO_DEV = DMA_TO_DEVICE = 1 DMA_DEV_TO_MEM = DMA_FROM_DEVICE = 2 Reported-by: Nick Desaulniers Signed-off-by: Nathan Chancellor Reviewed-by: Nick Desaulniers Signed-off-by: Miquel Raynal --- drivers/mtd/nand/raw/sh_flctl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mtd/nand/raw/sh_flctl.c b/drivers/mtd/nand/raw/sh_flctl.c index c0c0798f268f..4d20d033de7b 100644 --- a/drivers/mtd/nand/raw/sh_flctl.c +++ b/drivers/mtd/nand/raw/sh_flctl.c @@ -480,7 +480,7 @@ static void read_fiforeg(struct sh_flctl *flctl, int rlen, int offset) /* initiate DMA transfer */ if (flctl->chan_fifo0_rx && rlen >= 32 && - flctl_dma_fifo0_transfer(flctl, buf, rlen, DMA_DEV_TO_MEM) > 0) + flctl_dma_fifo0_transfer(flctl, buf, rlen, DMA_FROM_DEVICE) > 0) goto convert; /* DMA success */ /* do polling transfer */ @@ -539,7 +539,7 @@ static void write_ec_fiforeg(struct sh_flctl *flctl, int rlen, /* initiate DMA transfer */ if (flctl->chan_fifo0_tx && rlen >= 32 && - flctl_dma_fifo0_transfer(flctl, buf, rlen, DMA_MEM_TO_DEV) > 0) + flctl_dma_fifo0_transfer(flctl, buf, rlen, DMA_TO_DEVICE) > 0) return; /* DMA success */ /* do polling transfer */ From 309600c14e36d0e78c22fe3df58317965b90f4d1 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Tue, 4 Sep 2018 16:23:28 +0200 Subject: [PATCH 298/302] mtd: rawnand: Allow selection of ECC byte ordering at runtime Currently, the selection of ECC byte ordering for software hamming is done at compilation time, which doesn't make sense when ECC byte calculation is done in hardware and byte ordering is forced by the hardware engine. In this case, only the correction is done in software and we want to force the byte-ordering no matter the value of CONFIG_MTD_NAND_ECC_SMC. This is typically the case for the FSMC (Smart Media ordering), TMIO and TXX9NDFMC (regular byte ordering) blocks. For all other use cases (pure software implementation, SM FTL and nandecctest), we keep selecting the byte ordering based on the CONFIG_MTD_NAND_ECC_SMC value. It might not be ideal for SM FTL (I'd expect Smart Media ordering to be employed by the Smart Media FTL), but this option doesn't seem to be enabled in the existing _defconfig, so I can't tell setting sm_order to true is the right choice. Signed-off-by: Boris Brezillon Signed-off-by: Miquel Raynal --- drivers/mtd/nand/raw/fsmc_nand.c | 1 + drivers/mtd/nand/raw/nand_base.c | 4 ++ drivers/mtd/nand/raw/nand_ecc.c | 89 +++++++++++++---------------- drivers/mtd/nand/raw/tmio_nand.c | 5 +- drivers/mtd/nand/raw/txx9ndfmc.c | 3 +- drivers/mtd/sm_ftl.c | 20 ++++--- drivers/mtd/tests/mtd_nandecctest.c | 21 ++++--- include/linux/mtd/nand_ecc.h | 4 +- include/linux/mtd/rawnand.h | 6 ++ 9 files changed, 84 insertions(+), 69 deletions(-) diff --git a/drivers/mtd/nand/raw/fsmc_nand.c b/drivers/mtd/nand/raw/fsmc_nand.c index f9874fc72f30..70ac8d875218 100644 --- a/drivers/mtd/nand/raw/fsmc_nand.c +++ b/drivers/mtd/nand/raw/fsmc_nand.c @@ -949,6 +949,7 @@ static int fsmc_nand_attach_chip(struct nand_chip *nand) nand->ecc.correct = nand_correct_data; nand->ecc.bytes = 3; nand->ecc.strength = 1; + nand->ecc.options |= NAND_ECC_SOFT_HAMMING_SM_ORDER; break; case NAND_ECC_SOFT: diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c index dc3955da0426..05bd0779fe9b 100644 --- a/drivers/mtd/nand/raw/nand_base.c +++ b/drivers/mtd/nand/raw/nand_base.c @@ -5045,6 +5045,10 @@ static int nand_set_ecc_soft_ops(struct mtd_info *mtd) ecc->size = 256; ecc->bytes = 3; ecc->strength = 1; + + if (IS_ENABLED(CONFIG_MTD_NAND_ECC_SMC)) + ecc->options |= NAND_ECC_SOFT_HAMMING_SM_ORDER; + return 0; case NAND_ECC_BCH: if (!mtd_nand_has_bch()) { diff --git a/drivers/mtd/nand/raw/nand_ecc.c b/drivers/mtd/nand/raw/nand_ecc.c index 93df8e73f577..4f4347533058 100644 --- a/drivers/mtd/nand/raw/nand_ecc.c +++ b/drivers/mtd/nand/raw/nand_ecc.c @@ -132,9 +132,10 @@ static const char addressbits[256] = { * @buf: input buffer with raw data * @eccsize: data bytes per ECC step (256 or 512) * @code: output buffer with ECC + * @sm_order: Smart Media byte ordering */ void __nand_calculate_ecc(const unsigned char *buf, unsigned int eccsize, - unsigned char *code) + unsigned char *code, bool sm_order) { int i; const uint32_t *bp = (uint32_t *)buf; @@ -330,45 +331,26 @@ void __nand_calculate_ecc(const unsigned char *buf, unsigned int eccsize, * possible, but benchmarks showed that on the system this is developed * the code below is the fastest */ -#ifdef CONFIG_MTD_NAND_ECC_SMC - code[0] = - (invparity[rp7] << 7) | - (invparity[rp6] << 6) | - (invparity[rp5] << 5) | - (invparity[rp4] << 4) | - (invparity[rp3] << 3) | - (invparity[rp2] << 2) | - (invparity[rp1] << 1) | - (invparity[rp0]); - code[1] = - (invparity[rp15] << 7) | - (invparity[rp14] << 6) | - (invparity[rp13] << 5) | - (invparity[rp12] << 4) | - (invparity[rp11] << 3) | - (invparity[rp10] << 2) | - (invparity[rp9] << 1) | - (invparity[rp8]); -#else - code[1] = - (invparity[rp7] << 7) | - (invparity[rp6] << 6) | - (invparity[rp5] << 5) | - (invparity[rp4] << 4) | - (invparity[rp3] << 3) | - (invparity[rp2] << 2) | - (invparity[rp1] << 1) | - (invparity[rp0]); - code[0] = - (invparity[rp15] << 7) | - (invparity[rp14] << 6) | - (invparity[rp13] << 5) | - (invparity[rp12] << 4) | - (invparity[rp11] << 3) | - (invparity[rp10] << 2) | - (invparity[rp9] << 1) | - (invparity[rp8]); -#endif + if (sm_order) { + code[0] = (invparity[rp7] << 7) | (invparity[rp6] << 6) | + (invparity[rp5] << 5) | (invparity[rp4] << 4) | + (invparity[rp3] << 3) | (invparity[rp2] << 2) | + (invparity[rp1] << 1) | (invparity[rp0]); + code[1] = (invparity[rp15] << 7) | (invparity[rp14] << 6) | + (invparity[rp13] << 5) | (invparity[rp12] << 4) | + (invparity[rp11] << 3) | (invparity[rp10] << 2) | + (invparity[rp9] << 1) | (invparity[rp8]); + } else { + code[1] = (invparity[rp7] << 7) | (invparity[rp6] << 6) | + (invparity[rp5] << 5) | (invparity[rp4] << 4) | + (invparity[rp3] << 3) | (invparity[rp2] << 2) | + (invparity[rp1] << 1) | (invparity[rp0]); + code[0] = (invparity[rp15] << 7) | (invparity[rp14] << 6) | + (invparity[rp13] << 5) | (invparity[rp12] << 4) | + (invparity[rp11] << 3) | (invparity[rp10] << 2) | + (invparity[rp9] << 1) | (invparity[rp8]); + } + if (eccsize_mult == 1) code[2] = (invparity[par & 0xf0] << 7) | @@ -401,7 +383,9 @@ EXPORT_SYMBOL(__nand_calculate_ecc); int nand_calculate_ecc(struct nand_chip *chip, const unsigned char *buf, unsigned char *code) { - __nand_calculate_ecc(buf, chip->ecc.size, code); + bool sm_order = chip->ecc.options & NAND_ECC_SOFT_HAMMING_SM_ORDER; + + __nand_calculate_ecc(buf, chip->ecc.size, code, sm_order); return 0; } @@ -413,12 +397,13 @@ EXPORT_SYMBOL(nand_calculate_ecc); * @read_ecc: ECC from the chip * @calc_ecc: the ECC calculated from raw data * @eccsize: data bytes per ECC step (256 or 512) + * @sm_order: Smart Media byte order * * Detect and correct a 1 bit error for eccsize byte block */ int __nand_correct_data(unsigned char *buf, unsigned char *read_ecc, unsigned char *calc_ecc, - unsigned int eccsize) + unsigned int eccsize, bool sm_order) { unsigned char b0, b1, b2, bit_addr; unsigned int byte_addr; @@ -430,13 +415,14 @@ int __nand_correct_data(unsigned char *buf, * we might need the xor result more than once, * so keep them in a local var */ -#ifdef CONFIG_MTD_NAND_ECC_SMC - b0 = read_ecc[0] ^ calc_ecc[0]; - b1 = read_ecc[1] ^ calc_ecc[1]; -#else - b0 = read_ecc[1] ^ calc_ecc[1]; - b1 = read_ecc[0] ^ calc_ecc[0]; -#endif + if (sm_order) { + b0 = read_ecc[0] ^ calc_ecc[0]; + b1 = read_ecc[1] ^ calc_ecc[1]; + } else { + b0 = read_ecc[1] ^ calc_ecc[1]; + b1 = read_ecc[0] ^ calc_ecc[0]; + } + b2 = read_ecc[2] ^ calc_ecc[2]; /* check if there are any bitfaults */ @@ -500,7 +486,10 @@ EXPORT_SYMBOL(__nand_correct_data); int nand_correct_data(struct nand_chip *chip, unsigned char *buf, unsigned char *read_ecc, unsigned char *calc_ecc) { - return __nand_correct_data(buf, read_ecc, calc_ecc, chip->ecc.size); + bool sm_order = chip->ecc.options & NAND_ECC_SOFT_HAMMING_SM_ORDER; + + return __nand_correct_data(buf, read_ecc, calc_ecc, chip->ecc.size, + sm_order); } EXPORT_SYMBOL(nand_correct_data); diff --git a/drivers/mtd/nand/raw/tmio_nand.c b/drivers/mtd/nand/raw/tmio_nand.c index 3297621241d2..f3b59e649b7d 100644 --- a/drivers/mtd/nand/raw/tmio_nand.c +++ b/drivers/mtd/nand/raw/tmio_nand.c @@ -295,10 +295,11 @@ static int tmio_nand_correct_data(struct nand_chip *chip, unsigned char *buf, int r0, r1; /* assume ecc.size = 512 and ecc.bytes = 6 */ - r0 = __nand_correct_data(buf, read_ecc, calc_ecc, 256); + r0 = __nand_correct_data(buf, read_ecc, calc_ecc, 256, false); if (r0 < 0) return r0; - r1 = __nand_correct_data(buf + 256, read_ecc + 3, calc_ecc + 3, 256); + r1 = __nand_correct_data(buf + 256, read_ecc + 3, calc_ecc + 3, 256, + false); if (r1 < 0) return r1; return r0 + r1; diff --git a/drivers/mtd/nand/raw/txx9ndfmc.c b/drivers/mtd/nand/raw/txx9ndfmc.c index 3a99c8e3f944..ddf0420c0997 100644 --- a/drivers/mtd/nand/raw/txx9ndfmc.c +++ b/drivers/mtd/nand/raw/txx9ndfmc.c @@ -198,7 +198,8 @@ static int txx9ndfmc_correct_data(struct nand_chip *chip, unsigned char *buf, int stat; for (eccsize = chip->ecc.size; eccsize > 0; eccsize -= 256) { - stat = __nand_correct_data(buf, read_ecc, calc_ecc, 256); + stat = __nand_correct_data(buf, read_ecc, calc_ecc, 256, + false); if (stat < 0) return stat; corrected += stat; diff --git a/drivers/mtd/sm_ftl.c b/drivers/mtd/sm_ftl.c index f3bd86e13603..89227b1d036a 100644 --- a/drivers/mtd/sm_ftl.c +++ b/drivers/mtd/sm_ftl.c @@ -221,14 +221,18 @@ static int sm_correct_sector(uint8_t *buffer, struct sm_oob *oob) { uint8_t ecc[3]; - __nand_calculate_ecc(buffer, SM_SMALL_PAGE, ecc); - if (__nand_correct_data(buffer, ecc, oob->ecc1, SM_SMALL_PAGE) < 0) + __nand_calculate_ecc(buffer, SM_SMALL_PAGE, ecc, + IS_ENABLED(CONFIG_MTD_NAND_ECC_SMC)); + if (__nand_correct_data(buffer, ecc, oob->ecc1, SM_SMALL_PAGE, + IS_ENABLED(CONFIG_MTD_NAND_ECC_SMC)) < 0) return -EIO; buffer += SM_SMALL_PAGE; - __nand_calculate_ecc(buffer, SM_SMALL_PAGE, ecc); - if (__nand_correct_data(buffer, ecc, oob->ecc2, SM_SMALL_PAGE) < 0) + __nand_calculate_ecc(buffer, SM_SMALL_PAGE, ecc, + IS_ENABLED(CONFIG_MTD_NAND_ECC_SMC)); + if (__nand_correct_data(buffer, ecc, oob->ecc2, SM_SMALL_PAGE, + IS_ENABLED(CONFIG_MTD_NAND_ECC_SMC)) < 0) return -EIO; return 0; } @@ -393,11 +397,13 @@ static int sm_write_block(struct sm_ftl *ftl, uint8_t *buf, } if (ftl->smallpagenand) { - __nand_calculate_ecc(buf + boffset, - SM_SMALL_PAGE, oob.ecc1); + __nand_calculate_ecc(buf + boffset, SM_SMALL_PAGE, + oob.ecc1, + IS_ENABLED(CONFIG_MTD_NAND_ECC_SMC)); __nand_calculate_ecc(buf + boffset + SM_SMALL_PAGE, - SM_SMALL_PAGE, oob.ecc2); + SM_SMALL_PAGE, oob.ecc2, + IS_ENABLED(CONFIG_MTD_NAND_ECC_SMC)); } if (!sm_write_sector(ftl, zone, block, boffset, buf + boffset, &oob)) diff --git a/drivers/mtd/tests/mtd_nandecctest.c b/drivers/mtd/tests/mtd_nandecctest.c index 88b6c81cebbe..c71523e94580 100644 --- a/drivers/mtd/tests/mtd_nandecctest.c +++ b/drivers/mtd/tests/mtd_nandecctest.c @@ -121,8 +121,10 @@ static int no_bit_error_verify(void *error_data, void *error_ecc, unsigned char calc_ecc[3]; int ret; - __nand_calculate_ecc(error_data, size, calc_ecc); - ret = __nand_correct_data(error_data, error_ecc, calc_ecc, size); + __nand_calculate_ecc(error_data, size, calc_ecc, + IS_ENABLED(CONFIG_MTD_NAND_ECC_SMC)); + ret = __nand_correct_data(error_data, error_ecc, calc_ecc, size, + IS_ENABLED(CONFIG_MTD_NAND_ECC_SMC)); if (ret == 0 && !memcmp(correct_data, error_data, size)) return 0; @@ -149,8 +151,10 @@ static int single_bit_error_correct(void *error_data, void *error_ecc, unsigned char calc_ecc[3]; int ret; - __nand_calculate_ecc(error_data, size, calc_ecc); - ret = __nand_correct_data(error_data, error_ecc, calc_ecc, size); + __nand_calculate_ecc(error_data, size, calc_ecc, + IS_ENABLED(CONFIG_MTD_NAND_ECC_SMC)); + ret = __nand_correct_data(error_data, error_ecc, calc_ecc, size, + IS_ENABLED(CONFIG_MTD_NAND_ECC_SMC)); if (ret == 1 && !memcmp(correct_data, error_data, size)) return 0; @@ -184,8 +188,10 @@ static int double_bit_error_detect(void *error_data, void *error_ecc, unsigned char calc_ecc[3]; int ret; - __nand_calculate_ecc(error_data, size, calc_ecc); - ret = __nand_correct_data(error_data, error_ecc, calc_ecc, size); + __nand_calculate_ecc(error_data, size, calc_ecc, + IS_ENABLED(CONFIG_MTD_NAND_ECC_SMC)); + ret = __nand_correct_data(error_data, error_ecc, calc_ecc, size, + IS_ENABLED(CONFIG_MTD_NAND_ECC_SMC)); return (ret == -EBADMSG) ? 0 : -EINVAL; } @@ -259,7 +265,8 @@ static int nand_ecc_test_run(const size_t size) } prandom_bytes(correct_data, size); - __nand_calculate_ecc(correct_data, size, correct_ecc); + __nand_calculate_ecc(correct_data, size, correct_ecc, + IS_ENABLED(CONFIG_MTD_NAND_ECC_SMC)); for (i = 0; i < ARRAY_SIZE(nand_ecc_test); i++) { nand_ecc_test[i].prepare(error_data, error_ecc, diff --git a/include/linux/mtd/nand_ecc.h b/include/linux/mtd/nand_ecc.h index b81fecd5e719..0b3bb156c344 100644 --- a/include/linux/mtd/nand_ecc.h +++ b/include/linux/mtd/nand_ecc.h @@ -19,7 +19,7 @@ struct nand_chip; * Calculate 3 byte ECC code for eccsize byte block */ void __nand_calculate_ecc(const u_char *dat, unsigned int eccsize, - u_char *ecc_code); + u_char *ecc_code, bool sm_order); /* * Calculate 3 byte ECC code for 256/512 byte block @@ -31,7 +31,7 @@ int nand_calculate_ecc(struct nand_chip *chip, const u_char *dat, * Detect and correct a 1 bit error for eccsize byte block */ int __nand_correct_data(u_char *dat, u_char *read_ecc, u_char *calc_ecc, - unsigned int eccsize); + unsigned int eccsize, bool sm_order); /* * Detect and correct a 1 bit error for 256/512 byte block diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h index 68d09e01fa56..e10b126e148f 100644 --- a/include/linux/mtd/rawnand.h +++ b/include/linux/mtd/rawnand.h @@ -121,6 +121,12 @@ enum nand_ecc_algo { #define NAND_ECC_GENERIC_ERASED_CHECK BIT(0) #define NAND_ECC_MAXIMIZE BIT(1) +/* + * When using software implementation of Hamming, we can specify which byte + * ordering should be used. + */ +#define NAND_ECC_SOFT_HAMMING_SM_ORDER BIT(2) + /* * Option constants for bizarre disfunctionality and real * features. From e9836761867519e1e5beb7486dc73c3d5b8877f5 Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Mon, 24 Sep 2018 11:35:18 +0200 Subject: [PATCH 299/302] mtd: rawnand: toshiba: Pass a single nand_chip object to the status helper Now that most of the raw NAND API is consistent and has almost all its helpers and hooks using a single nand_chip object instead of an mtd_info one (or both), let's do the same cleanup in the raw NAND vendors drivers. Apply this change to the Toshiba driver so that the internal helper to retrieve the ECC status does only take a nand_chip object. Suggested-by: Boris Brezillon Signed-off-by: Miquel Raynal Reviewed-by: Boris Brezillon --- drivers/mtd/nand/raw/nand_toshiba.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/mtd/nand/raw/nand_toshiba.c b/drivers/mtd/nand/raw/nand_toshiba.c index 941ddc615190..d068163b64b3 100644 --- a/drivers/mtd/nand/raw/nand_toshiba.c +++ b/drivers/mtd/nand/raw/nand_toshiba.c @@ -23,9 +23,9 @@ /* Recommended to rewrite for BENAND */ #define TOSHIBA_NAND_STATUS_REWRITE_RECOMMENDED BIT(3) -static int toshiba_nand_benand_eccstatus(struct mtd_info *mtd, - struct nand_chip *chip) +static int toshiba_nand_benand_eccstatus(struct nand_chip *chip) { + struct mtd_info *mtd = nand_to_mtd(chip); int ret; unsigned int max_bitflips = 0; u8 status; @@ -51,21 +51,19 @@ static int toshiba_nand_read_page_benand(struct nand_chip *chip, uint8_t *buf, int oob_required, int page) { - struct mtd_info *mtd = nand_to_mtd(chip); int ret; ret = nand_read_page_raw(chip, buf, oob_required, page); if (ret) return ret; - return toshiba_nand_benand_eccstatus(mtd, chip); + return toshiba_nand_benand_eccstatus(chip); } static int toshiba_nand_read_subpage_benand(struct nand_chip *chip, uint32_t data_offs, uint32_t readlen, uint8_t *bufpoi, int page) { - struct mtd_info *mtd = nand_to_mtd(chip); int ret; ret = nand_read_page_op(chip, page, data_offs, @@ -73,7 +71,7 @@ toshiba_nand_read_subpage_benand(struct nand_chip *chip, uint32_t data_offs, if (ret) return ret; - return toshiba_nand_benand_eccstatus(mtd, chip); + return toshiba_nand_benand_eccstatus(chip); } static void toshiba_nand_benand_init(struct nand_chip *chip) From ed8f0b23d92606bbc8f027df9164473636ac2b74 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Thu, 27 Sep 2018 16:24:31 +0100 Subject: [PATCH 300/302] mtd: rawnand: r852: fix spelling mistake "card_registred" -> "card_registered" Trivial fix to spelling mistake struct field name, rename it. Signed-off-by: Colin Ian King Signed-off-by: Miquel Raynal --- drivers/mtd/nand/raw/r852.c | 14 +++++++------- drivers/mtd/nand/raw/r852.h | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/mtd/nand/raw/r852.c b/drivers/mtd/nand/raw/r852.c index b08aa0a5a074..39be65b35ac2 100644 --- a/drivers/mtd/nand/raw/r852.c +++ b/drivers/mtd/nand/raw/r852.c @@ -637,7 +637,7 @@ static int r852_register_nand_device(struct r852_device *dev) { struct mtd_info *mtd = nand_to_mtd(dev->chip); - WARN_ON(dev->card_registred); + WARN_ON(dev->card_registered); mtd->dev.parent = &dev->pci_dev->dev; @@ -654,7 +654,7 @@ static int r852_register_nand_device(struct r852_device *dev) goto error3; } - dev->card_registred = 1; + dev->card_registered = 1; return 0; error3: nand_release(dev->chip); @@ -672,13 +672,13 @@ static void r852_unregister_nand_device(struct r852_device *dev) { struct mtd_info *mtd = nand_to_mtd(dev->chip); - if (!dev->card_registred) + if (!dev->card_registered) return; device_remove_file(&mtd->dev, &dev_attr_media_type); nand_release(dev->chip); r852_engine_disable(dev); - dev->card_registred = 0; + dev->card_registered = 0; } /* Card state updater */ @@ -692,7 +692,7 @@ static void r852_card_detect_work(struct work_struct *work) dev->card_unstable = 0; /* False alarm */ - if (dev->card_detected == dev->card_registred) + if (dev->card_detected == dev->card_registered) goto exit; /* Read media properties */ @@ -1033,7 +1033,7 @@ static int r852_resume(struct device *device) /* If card status changed, just do the work */ - if (dev->card_detected != dev->card_registred) { + if (dev->card_detected != dev->card_registered) { dbg("card was %s during low power state", dev->card_detected ? "added" : "removed"); @@ -1043,7 +1043,7 @@ static int r852_resume(struct device *device) } /* Otherwise, initialize the card */ - if (dev->card_registred) { + if (dev->card_registered) { r852_engine_enable(dev); dev->chip->select_chip(dev->chip, 0); nand_reset_op(dev->chip); diff --git a/drivers/mtd/nand/raw/r852.h b/drivers/mtd/nand/raw/r852.h index 1eed2fc2fa42..bc67f5bf67e8 100644 --- a/drivers/mtd/nand/raw/r852.h +++ b/drivers/mtd/nand/raw/r852.h @@ -129,7 +129,7 @@ struct r852_device { /* card status area */ struct delayed_work card_detect_work; struct workqueue_struct *card_workqueue; - int card_registred; /* card registered with mtd */ + int card_registered; /* card registered with mtd */ int card_detected; /* card detected in slot */ int card_unstable; /* whenever the card is inserted, is not known yet */ From 0d55c668b218a1db68b5044bce4de74e1bd0f0c8 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 28 Sep 2018 13:16:01 +0900 Subject: [PATCH 301/302] mtd: rawnand: denali: set SPARE_AREA_SKIP_BYTES register to 8 if unset NAND devices need additional data area (OOB) for error correction, but it is also used for Bad Block Marker (BBM). In many cases, the first byte in OOB is used for BBM, but the location actually depends on chip vendors. The NAND controller should preserve the precious BBM to keep track of bad blocks. In Denali IP, the SPARE_AREA_SKIP_BYTES register is used to specify the number of bytes to skip from the start of OOB. The ECC engine will automatically skip the specified number of bytes when it gets access to OOB area. The same value for SPARE_AREA_SKIP_BYTES should be used between firmware and the operating system if you intend to use the NAND device across the control hand-off. In fact, the current denali.c code expects firmware to have already set the SPARE_AREA_SKIP_BYTES register, then reads the value out. If no firmware (or bootloader) has initialized the controller, the register value is zero, which is the default after power-on-reset. In other words, the Linux driver cannot initialize the controller by itself. Some possible solutions are: [1] Add a DT property to specify the skipped bytes in OOB [2] Associate the preferred value with compatible [3] Hard-code the default value in the driver My first attempt was [1], but in the review process, [3] was suggested as a counter-implementation. (https://lore.kernel.org/patchwork/patch/983055/) The default value 8 was chosen to match to the boot ROM of the UniPhier platform. The preferred value may vary by platform. If so, please trade up to a different solution. Signed-off-by: Masahiro Yamada Reviewed-by: Boris Brezillon Signed-off-by: Miquel Raynal --- drivers/mtd/nand/raw/denali.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/drivers/mtd/nand/raw/denali.c b/drivers/mtd/nand/raw/denali.c index 858358027dc9..07a87717a3ca 100644 --- a/drivers/mtd/nand/raw/denali.c +++ b/drivers/mtd/nand/raw/denali.c @@ -21,6 +21,7 @@ #include "denali.h" #define DENALI_NAND_NAME "denali-nand" +#define DENALI_DEFAULT_OOB_SKIP_BYTES 8 /* for Indexed Addressing */ #define DENALI_INDEXED_CTRL 0x00 @@ -1091,12 +1092,17 @@ static void denali_hw_init(struct denali_nand_info *denali) denali->revision = swab16(ioread32(denali->reg + REVISION)); /* - * tell driver how many bit controller will skip before - * writing ECC code in OOB, this register may be already - * set by firmware. So we read this value out. - * if this value is 0, just let it be. + * Set how many bytes should be skipped before writing data in OOB. + * If a non-zero value has already been set (by firmware or something), + * just use it. Otherwise, set the driver default. */ denali->oob_skip_bytes = ioread32(denali->reg + SPARE_AREA_SKIP_BYTES); + if (!denali->oob_skip_bytes) { + denali->oob_skip_bytes = DENALI_DEFAULT_OOB_SKIP_BYTES; + iowrite32(denali->oob_skip_bytes, + denali->reg + SPARE_AREA_SKIP_BYTES); + } + denali_detect_max_banks(denali); iowrite32(0x0F, denali->reg + RB_PIN_ENABLED); iowrite32(CHIP_EN_DONT_CARE__FLAG, denali->reg + CHIP_ENABLE_DONT_CARE); From 53c83b59759c1ee213f5ffa194909daee8902a28 Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Wed, 3 Oct 2018 11:05:04 +0200 Subject: [PATCH 302/302] mtd: rawnand: marvell: fix the IRQ handler complete() condition With the current implementation, the complete() in the IRQ handler is supposed to be called only if the register status has one or the other RDY bit set. Other events might trigger an interrupt as well if enabled, but should not end-up with a complete() call. For this purpose, the code was checking if the other bits were set, in this case complete() was not called. This is wrong as two events might happen in a very tight time-frame and if the NDSR status read reports two bits set (eg. RDY(0) and RDDREQ) at the same time, complete() was not called. This logic would lead to timeouts in marvell_nfc_wait_op() and has been observed on PXA boards (NFCv1) in the Hamming write path. Fixes: 02f26ecf8c77 ("mtd: nand: add reworked Marvell NAND controller driver") Cc: stable@vger.kernel.org Reported-by: Daniel Mack Signed-off-by: Miquel Raynal Tested-by: Daniel Mack --- drivers/mtd/nand/raw/marvell_nand.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mtd/nand/raw/marvell_nand.c b/drivers/mtd/nand/raw/marvell_nand.c index e63f714f7639..c6e039f362f1 100644 --- a/drivers/mtd/nand/raw/marvell_nand.c +++ b/drivers/mtd/nand/raw/marvell_nand.c @@ -755,7 +755,7 @@ static irqreturn_t marvell_nfc_isr(int irq, void *dev_id) marvell_nfc_disable_int(nfc, st & NDCR_ALL_INT); - if (!(st & (NDSR_RDDREQ | NDSR_WRDREQ | NDSR_WRCMDREQ))) + if (st & (NDSR_RDY(0) | NDSR_RDY(1))) complete(&nfc->complete); return IRQ_HANDLED;