Re: Nokia N900: musb is in wrong state after boot
On Wed 08 June 2016 15:04:02 Sergei Shtylyov wrote: > On 6/8/2016 1:02 PM, Felipe Balbi wrote: > >> * Pali Rohár [160607 05:53]: > Tony, what do you think about that patch? > >>> > >>> Tony, PING > >> > >> Yeah I don't know, AFAIK we don't have a generic way to > >> force MUSB to change mode without ID pin. If you have figured > >> something generic for that which does not actually tinker with > >> the PHY registers directly, that should be the generic > >> musb_set_mode() that we've been wondering about for years. > > > > #define MUSB_TEST_FORCE_HOST0x80 > > > > Can someone confirm on MUSB's docs (and actual running system) that this > > does what's supposed to do? > > The MUSB programmer's guide says the CID (sic) input is ignored when the > Force_Host bit is set. The host mode is entered when the Session bit is > set. But I don't have a MUSB hardware readily available to confirm. > > MBR, Sergei also says: While the FORCE_HOST bit remains set, the core will enter Host mode when the Session bit is set and **remain in Host mode until the Session bit is cleared even if a connected device is disconnected during the session.** The operating speed while in this mode **is determined for the setting of the FORCE_HS and FORCE_FS bits of the Testmode register** in Section 23.1.4.11. see http://talk.maemo.org/showthread.php?p=685367 It's not any fully operational hostmode. /j -- () ascii ribbon campaign /\ against html e-mail - against proprietary attachments http://www.georgedillon.com/web/html_email_is_evil.shtml http://www.nonhtmlmail.org/campaign.html http://www.georgedillon.com/web/html_email_is_evil_still.shtml http://www.gerstbach.at/2004/ascii/ (German)
Re: NVMe over Fabrics target implementation
On Tue, Jun 07, 2016 at 10:21:41PM -0700, Nicholas A. Bellinger wrote: > *) Extensible to multiple types of backend drivers. > > nvme-target needs a way to absorb new backend drivers, that > does not effect existing configfs group layout or attributes. > > Looking at the nvmet/configfs layout as-is, there are no multiple > backend types defined, nor a way to control backend feature bits > exposed to nvme namespaces at runtime. And that's very much intentional. We have a very well working block layer which we're going to use, no need to reivent it. The block layer supports NVMe pass through just fine in case we'll need it, as I spent the last year preparing it for that. > Why does it ever make sense for $SUBSYSTEM_NQN_0 with $PORT_DRIVER_FOO > to block operation of $SUBSYSTEM_NQN_1 with $PORT_DRIVER_BAR..? Because it keeps the code simple. If you had actually participated on our development list you might have seen that until not too long ago we have very fine grainded locks here. In the end Armen convinced me that it's easier to maintain if we don't bother with fine grained locking outside the fast path, especially as it significantly simplifies the discovery implementation. If if it ever turns out to be an issue we can change it easily as the implementation is well encapsulated.
Re: [PATCH v2 2/6] drm/panel: simple: Add support for LG LP097QX1-SPA1 2048x1536 panel
Hi Yakir, On 8 June 2016 at 12:52, Yakir Yang wrote: > The LG LP097QX1-SPA1 is an 9.7", 2048x1536 (QXGA) TFT-LCD panel > connected using eDP interfaces. > > Signed-off-by: Yakir Yang > --- > Changes in v2: None > > drivers/gpu/drm/panel/panel-simple.c | 25 + > 1 file changed, 25 insertions(+) > > diff --git a/drivers/gpu/drm/panel/panel-simple.c > b/drivers/gpu/drm/panel/panel-simple.c > index 3a7bdf1..41020e1 100644 > --- a/drivers/gpu/drm/panel/panel-simple.c > +++ b/drivers/gpu/drm/panel/panel-simple.c > @@ -1040,6 +1040,28 @@ static const struct panel_desc lg_lp120up1 = { > }, > }; > > +static const struct drm_display_mode lg_lp097qx1_spa1_mode = { I believe that lg_lp097qx1_spa1 should be moved/sorted before lg_lp120up1. > +static const struct panel_desc lg_lp097qx1_spa1 = { > + .modes = &lg_lp097qx1_spa1_mode, > + .num_modes = 1, > + .size = { > + .width = 2048, > + .height = 1536, These are the physical dimensions of the panel. From the documentation (at the top of the file) @width: width (in millimeters) of the panel's active display area ... Thierry, perhaps it's worth renaming 'size' it to "physical_{size,dimensions}" and/or alike to make it clearer ? Looks like we have a few cases were people got confused - innolux_zj070na_01p and samsung_ltn101nt05. Regards, Emil
Re: [alsa-devel] [PATCH v4] ASoC: rockchip: Add machine driver for RK3399 GRU Boards
Hi, [auto build test WARNING on rockchip/for-next] [also build test WARNING on v4.7-rc2 next-20160608] [if your patch is applied to the wrong git tree, please drop us a note to help improve the system] url: https://github.com/0day-ci/linux/commits/Xing-Zheng/ASoC-rockchip-Add-machine-driver-for-RK3399-GRU-Boards/20160608-191723 base: https://git.kernel.org/pub/scm/linux/kernel/git/mmind/linux-rockchip.git for-next config: sparc64-allyesconfig (attached as .config) compiler: sparc64-linux-gnu-gcc (Debian 5.3.1-8) 5.3.1 20160205 reproduce: wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # save the attached .config to linux build tree make.cross ARCH=sparc64 All warnings (new ones prefixed by >>): warning: (SND_SOC_RK3399_GRU_SOUND) selects SND_SOC_ROCKCHIP_I2S which has unmet direct dependencies (SOUND && !M68K && !UML && SND && SND_SOC && CLKDEV_LOOKUP && SND_SOC_ROCKCHIP) --- 0-DAY kernel test infrastructureOpen Source Technology Center https://lists.01.org/pipermail/kbuild-all Intel Corporation .config.gz Description: Binary data
[PATCH] Add .set_antenna callback in ath6kl driver to remove wireless core warns
Since add more warnings for inconsistent ops in cfg80211, the wireless core warns if a driver implements a cfg80211 callback but doesn't implements the inverse operation. The ath6kl driver implements a cfg80211 .get_antenna operation handler but doesn't have the inverse .set_antenna callback. So, it makes warning. To remove this warning, add .set_antenna callback in ath6kl driver and also send a cmd to firmware with it's values. Signed-off-by: Prasun Maiti --- drivers/net/wireless/ath/ath6kl/cfg80211.c | 24 drivers/net/wireless/ath/ath6kl/wmi.c | 18 ++ drivers/net/wireless/ath/ath6kl/wmi.h | 6 ++ 3 files changed, 48 insertions(+) diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c index 4e11ba0..0d51228 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.c +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c @@ -3231,6 +3231,29 @@ static int ath6kl_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, wait, buf, len, no_cck); } +static int ath6kl_set_antenna(struct wiphy *wiphy, + u32 tx_ant, u32 rx_ant) +{ + struct ath6kl *ar = wiphy_priv(wiphy); + struct ath6kl_vif *vif = NULL; + + vif = ath6kl_vif_first(ar); + if (!vif) + return -EIO; + + if (!ath6kl_cfg80211_ready(vif)) + return -EIO; + + if (!tx_ant || !rx_ant) + return -EINVAL; + + ar->hw.tx_ant = tx_ant; + ar->hw.rx_ant = rx_ant; + + return ath6kl_wmi_set_antenna(ar->wmi, vif->fw_vif_idx, + tx_ant, rx_ant); +} + static int ath6kl_get_antenna(struct wiphy *wiphy, u32 *tx_ant, u32 *rx_ant) { @@ -3456,6 +3479,7 @@ static struct cfg80211_ops ath6kl_cfg80211_ops = { .cancel_remain_on_channel = ath6kl_cancel_remain_on_channel, .mgmt_tx = ath6kl_mgmt_tx, .mgmt_frame_register = ath6kl_mgmt_frame_register, + .set_antenna = ath6kl_set_antenna, .get_antenna = ath6kl_get_antenna, .sched_scan_start = ath6kl_cfg80211_sscan_start, .sched_scan_stop = ath6kl_cfg80211_sscan_stop, diff --git a/drivers/net/wireless/ath/ath6kl/wmi.c b/drivers/net/wireless/ath/ath6kl/wmi.c index 631c3a0..300ccc6 100644 --- a/drivers/net/wireless/ath/ath6kl/wmi.c +++ b/drivers/net/wireless/ath/ath6kl/wmi.c @@ -1605,6 +1605,24 @@ static int ath6kl_wmi_txe_notify_event_rx(struct wmi *wmi, u8 *datap, int len, return 0; } +int ath6kl_wmi_set_antenna(struct wmi *wmi, u8 idx, + u32 tx_ant, u32 rx_ant) +{ + struct sk_buff *skb; + struct wmi_txe_notify_cmd *cmd; + + skb = ath6kl_wmi_get_new_buf(sizeof(*cmd)); + if (!skb) + return -ENOMEM; + + cmd = (struct wmi_set_antenna_cmd *) skb->data; + cmd->tx_ant = cpu_to_le32(tx_ant); + cmd->rx_ant = cpu_to_le32(rx_ant); + + return ath6kl_wmi_cmd_send(wmi, idx, skb, WMI_SET_ANTENNA_CMDID, + NO_SYNC_WMIFLAG); +} + int ath6kl_wmi_set_txe_notify(struct wmi *wmi, u8 idx, u32 rate, u32 pkts, u32 intvl) { diff --git a/drivers/net/wireless/ath/ath6kl/wmi.h b/drivers/net/wireless/ath/ath6kl/wmi.h index 3af464a..f2e65b3 100644 --- a/drivers/net/wireless/ath/ath6kl/wmi.h +++ b/drivers/net/wireless/ath/ath6kl/wmi.h @@ -642,6 +642,7 @@ enum wmi_cmd_id { WMI_SET_RECOVERY_TEST_PARAMETER_CMDID, /*0xf094*/ WMI_ENABLE_SCHED_SCAN_CMDID, + WMI_SET_ANTENNA_CMDID, }; enum wmi_mgmt_frame_type { @@ -2312,6 +2313,11 @@ struct wmi_ap_set_apsd_cmd { u8 enable; } __packed; +struct wmi_set_antenna_cmd { + __le32 tx_ant; + __le32 rx_ant; +} __packed; + enum wmi_ap_apsd_buffered_traffic_flags { WMI_AP_APSD_NO_DELIVERY_FRAMES = 0x1, }; -- 1.9.1
Re: [PATCH V8 7/9] acpi: Add generic MCFG table handling
On 08.06.2016 03:56, Bjorn Helgaas wrote: On Mon, May 30, 2016 at 05:14:20PM +0200, Tomasz Nowicki wrote: In order to handle PCI config space regions properly in ACPI, new MCFG interface is defined which does sanity checks on MCFG table and keeps its root pointer. The user is able to lookup MCFG regions based on host bridge root structure and domain:bus_start:bus_end touple. Use pci_mmcfg_late_init old prototype to avoid another function name. Signed-off-by: Tomasz Nowicki Signed-off-by: Jayachandran C --- drivers/acpi/Kconfig | 3 ++ drivers/acpi/Makefile| 1 + drivers/acpi/pci_mcfg.c | 94 include/linux/pci-acpi.h | 2 ++ include/linux/pci.h | 2 +- 5 files changed, 101 insertions(+), 1 deletion(-) create mode 100644 drivers/acpi/pci_mcfg.c diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index b7e2e77..f98c328 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -217,6 +217,9 @@ config ACPI_PROCESSOR_IDLE bool select CPU_IDLE +config ACPI_MCFG + bool + config ACPI_CPPC_LIB bool depends on ACPI_PROCESSOR diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index 251ce85..632e81f 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile @@ -40,6 +40,7 @@ acpi-$(CONFIG_ARCH_MIGHT_HAVE_ACPI_PDC) += processor_pdc.o acpi-y+= ec.o acpi-$(CONFIG_ACPI_DOCK) += dock.o acpi-y+= pci_root.o pci_link.o pci_irq.o +obj-$(CONFIG_ACPI_MCFG)+= pci_mcfg.o acpi-y+= acpi_lpss.o acpi_apd.o acpi-y+= acpi_platform.o acpi-y+= acpi_pnp.o diff --git a/drivers/acpi/pci_mcfg.c b/drivers/acpi/pci_mcfg.c new file mode 100644 index 000..1847f74 --- /dev/null +++ b/drivers/acpi/pci_mcfg.c @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2016 Broadcom + * Author: Jayachandran C + * Copyright (C) 2016 Semihalf + * Author: Tomasz Nowicki + * + * 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 + * published by the Free Software Foundation (the "GPL"). + * + * 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 version 2 (GPLv2) for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 (GPLv2) along with this source code. + */ + +#define pr_fmt(fmt) "ACPI: " fmt + +#include +#include +#include + +/* Root pointer to the mapped MCFG table */ +static struct acpi_table_mcfg *mcfg_table; +static int mcfg_entries; + +int pci_mcfg_lookup(struct acpi_pci_root *root) I think this would be better if we passed in the domain and a pointer to the bus range resource and returned the ECAM base address. I don't think we need to be connected to struct acpi_pci_root. I will use domain and bus range resource as you suggested. +{ + struct acpi_mcfg_allocation *mptr, *entry = NULL; + struct resource *bus_res = &root->secondary; + int i; + + if (mcfg_table) { + mptr = (struct acpi_mcfg_allocation *) &mcfg_table[1]; + for (i = 0; i < mcfg_entries && !entry; i++, mptr++) + if (mptr->pci_segment == root->segment && + mptr->start_bus_number == bus_res->start) + entry = mptr; + } + + /* not found, use _CBA if available, else error */ + if (!entry) { + if (root->mcfg_addr) + return root->mcfg_addr; + pr_err("%04x:%pR MCFG lookup failed\n", root->segment, bus_res); + return -ENOENT; + } else if (root->mcfg_addr && entry->address != root->mcfg_addr) { + pr_warn("%04x:%pR CBA %pa != MCFG %lx, using CBA\n", + root->segment, bus_res, &root->mcfg_addr, + (unsigned long)entry->address); + return 0; + } I keep looking at this code, trying to find where we "use _CBA", but I can't find it. Oh, I see, acpi_pci_root_add() calls acpi_pci_root_get_mcfg_addr() (which evaluates _CBA), and sets root->mcfg_addr to the result. "root->mcfg_addr" is sort of an unfortunate name because "MCFG" is the ACPI table name, we've used "ECAM" for the memory-mapped config space, and this address can come from either the MCFG table or the _CBA method. In the case where we have both _CBA and an MCFG entry, I think we should prefer _CBA, and I'm not sure it's even worth warning about it. So I think you could simplify this function if you made pci_acpi_setup_ecam_mapping() look like this: ... pci_acpi_setup_ecam_mapping(...) { ...
Re: [PATCH 0/2] *** r8723au: Replace semaphore lock with mutex ***
Binoy Jayan writes: > Hi, > > These are a set of patches which removes semaphores from: > > drivers/staging/rtl8723au > > These are part of a bigger effort to eliminate all semaphores > from the linux kernel. > > They build correctly (individually and as a whole). > NB: I have not tested this as I do not have the following hardware: > > R8723AU > "Realtek RTL8723AU Wireless LAN NIC driver" I am not against this, but please note this driver is already marked for deletion in a future kernel release. Cheers, Jes
Re: [PATCH] staging: rtl8712: Fixed multiple parenthesis alignment warnings in ieee80211.c
No mate, that aint just cutting it. I tried putting it, maybe i’m doing something wrong? Regards, Parth > On 08-Jun-2016, at 5:46 PM, Luis de Bethencourt > wrote: > > On 08/06/16 12:58, Parth Sane wrote: >> I’m trying to fix line 224 but its simply not happening. Can you help me >> with this? >> Regards, >> Parth >>> On 08-Jun-2016, at 5:19 PM, Luis de Bethencourt >>> wrote: >>> >>> On 08/06/16 12:37, Parth Sane wrote: > On 08-Jun-2016, at 5:01 PM, Luis de Bethencourt > wrote: > > On 08/06/16 12:27, Parth Sane wrote: >> Multiple parenthesis alignment warnings were thrown by checkpatch in >> ieee80211.c >> This patch effectively fixes that. >> >> Signed-off-by: Parth Sane >> >> --- >> drivers/staging/rtl8712/ieee80211.c | 25 - >> 1 file changed, 12 insertions(+), 13 deletions(-) > > Some of the lines you change are over 80 characters. You could fix those > as well in > a second patch :) > > Thanks, > Luis > You’re right on that regard. Maybe once this is accepted I can come back to other warnings. I will submit other patches meanwhile. I seriously want to see this driver in the next release! Regards, Parth >>> >>> You can resend this patch and the one fixing the 80 char limit with the >>> subject >>> prefix [RESEND PATCH v2 x/2]. >>> >>> AFAIK this driver is already in the release, check menuconfig under >>> "Device Drivers > Staging drivers > Realtek RTL8172" >>> >>> Thanks, >>> Luis >> > > Sure. > > You want something like this: > - if (memcmp((pbuf + 2), wpa_oui_type, > sizeof(wpa_oui_type))) > + if (memcmp((pbuf + 2), wpa_oui_type, > + sizeof(wpa_oui_type))) > > You could check for references of how other parts of the code have solved it > by doing: > git grep memcpy * | grep -v ";" > > I hope that helps. > Luis > > > > Reviewed-by: Luis de Bethencourt signature.asc Description: Message signed with OpenPGP using GPGMail
Re: [PATCH v8 2/3] CMDQ: Mediatek CMDQ driver
Hi Matthias, On Wed, 2016-06-08 at 12:45 +0200, Matthias Brugger wrote: > > On 08/06/16 07:40, Horng-Shyang Liao wrote: > > Hi Matthias, > > > > On Tue, 2016-06-07 at 18:59 +0200, Matthias Brugger wrote: > >> > >> On 03/06/16 15:11, Matthias Brugger wrote: > >>> > >>> > >> [...] > >> > + > +smp_mb(); /* modify jump before enable thread */ > +} > + > +cmdq_thread_writel(thread, task->pa_base + > task->command_size, > + CMDQ_THR_END_ADDR); > +cmdq_thread_resume(thread); > +} > +list_move_tail(&task->list_entry, &thread->task_busy_list); > +spin_unlock_irqrestore(&cmdq->exec_lock, flags); > +} > + > +static void cmdq_handle_error_done(struct cmdq *cmdq, > + struct cmdq_thread *thread, u32 irq_flag) > +{ > +struct cmdq_task *task, *tmp, *curr_task = NULL; > +u32 curr_pa; > +struct cmdq_cb_data cmdq_cb_data; > +bool err; > + > +if (irq_flag & CMDQ_THR_IRQ_ERROR) > +err = true; > +else if (irq_flag & CMDQ_THR_IRQ_DONE) > +err = false; > +else > +return; > + > +curr_pa = cmdq_thread_readl(thread, CMDQ_THR_CURR_ADDR); > + > +list_for_each_entry_safe(task, tmp, &thread->task_busy_list, > + list_entry) { > +if (curr_pa >= task->pa_base && > +curr_pa < (task->pa_base + task->command_size)) > >>> > >>> What are you checking here? It seems as if you make some implcit > >>> assumptions about pa_base and the order of execution of > >>> commands in the > >>> thread. Is it save to do so? Does dma_alloc_coherent give any > >>> guarantees > >>> about dma_handle? > >> > >> 1. Check what is the current running task in this GCE thread. > >> 2. Yes. > >> 3. Yes, CMDQ doesn't use iommu, so physical address is continuous. > >> > > > > Yes, physical addresses might be continous, but AFAIK there is no > > guarantee that the dma_handle address is steadily growing, when > > calling > > dma_alloc_coherent. And if I understand the code correctly, you > > use this > > assumption to decide if the task picked from task_busy_list is > > currently > > executing. So I think this mecanism is not working. > > I don't use dma_handle address, and just use physical addresses. > From CPU's point of view, tasks are linked by the busy list. > From GCE's point of view, tasks are linked by the JUMP command. > > > In which cases does the HW thread raise an interrupt. > > In case of error. When does CMDQ_THR_IRQ_DONE get raised? > > GCE will raise interrupt if any task is done or error. > However, GCE is fast, so CPU may get multiple done tasks > when it is running ISR. > > In case of error, that GCE thread will pause and raise interrupt. > So, CPU may get multiple done tasks and one error task. > > >>> > >>> I think we should reimplement the ISR mechanism. Can't we just read > >>> CURR_IRQ_STATUS and THR_IRQ_STATUS in the handler and leave > >>> cmdq_handle_error_done to the thread_fn? You will need to pass > >>> information from the handler to thread_fn, but that shouldn't be an > >>> issue. AFAIK interrupts are disabled in the handler, so we should stay > >>> there as short as possible. Traversing task_busy_list is expensive, so > >>> we need to do it in a thread context. > >> > >> Actually, our initial implementation is similar to your suggestion, > >> but display needs CMDQ to return callback function very precisely, > >> else display will drop frame. > >> For display, CMDQ interrupt will be raised every 16 ~ 17 ms, > >> and CMDQ needs to call callback function in ISR. > >> If we defer callback to workqueue, the time interval may be larger than > >> 32 ms.sometimes. > >> > > > > I think the problem is, that you implemented the workqueue as a ordered > > workqueue, so there is no parallel processing. I'm still not sure why > > you need the workqueue to be ordered. Can you please explain. > > The order should be kept. > Let me use mouse cursor as an example. > If task 1 means move mouse cursor to point A, task 2 means point B, > and task 3 means point C, our expected result is A -> B -> C. > If the order is not kept, the res
Re: [PATCH v3] mailbox: pcc: Support HW-Reduced Communication Subspace type 2
+ Prashanth (Can you please have a look as well?) On 31 May 2016 at 15:35, Hoan Tran wrote: > Hi Ashwin, Hi, Sorry about the delay. I'm in the middle of switching jobs and locations, so its been a bit crazy lately. I dont have any major concerns with this code, although there could be subtle issues with this IRQ thing. In this patchset, your intent is to add support for PCC subspace type 2. But you're also adding support for tx command completion which is not specific to Type 2. We could support that even in Type 1. Hence I wanted to separate the two, not just for review, but also the async IRQ completion has subtle issues esp. in the case of async platform notification, where you could have a PCC client in the OS writing to the cmd bit and the platform sending an async notification by writing to some bits in the same 8byte address as the cmd bit. So we need some mutual exclusivity there, otherwise the OS and platform could step on each other. Perhaps Prashanth has better insight into this. > > On Tue, May 31, 2016 at 12:05 PM, Ashwin Chaugule > wrote: >> On 19 May 2016 at 20:32, Hoan Tran wrote: >>> ACPI 6.1 has a PCC HW-Reduced Communication Subspace type 2 intended for >>> use on HW-Reduce ACPI Platform, which requires read-modify-write sequence >>> to acknowledge doorbell interrupt. This patch provides the implementation >>> for the Communication Subspace Type 2. >>> >>> v3 >>> * Remove 2 global structures >>> * Correct parsing subspace type 1 and subspace type 2 >>> >>> v2 >>> * Remove changes inside "actbl3.h". This file is taken care by ACPICA. >>> * Parse both subspace type 1 and subspace type 2 >>> * Remove unnecessary variable initialization >>> * ISR returns IRQ_NONE in case of error >>> >>> v1 >>> * Initial >>> >>> Signed-off-by: Hoan Tran >>> --- >>> drivers/mailbox/pcc.c | 316 >>> ++ >>> 1 file changed, 245 insertions(+), 71 deletions(-) >>> >>> diff --git a/drivers/mailbox/pcc.c b/drivers/mailbox/pcc.c >>> index 043828d..c98bd94 100644 >>> --- a/drivers/mailbox/pcc.c >>> +++ b/drivers/mailbox/pcc.c >>> @@ -59,6 +59,7 @@ >>> #include >>> #include >>> #include >>> +#include >>> #include >>> #include >>> #include >>> @@ -68,11 +69,16 @@ >>> #include "mailbox.h" >>> >>> #define MAX_PCC_SUBSPACES 256 >>> +#define MBOX_IRQ_NAME "pcc-mbox" >>> >>> static struct mbox_chan *pcc_mbox_channels; >>> >>> /* Array of cached virtual address for doorbell registers */ >>> static void __iomem **pcc_doorbell_vaddr; >>> +/* Array of cached virtual address for doorbell ack registers */ >>> +static void __iomem **pcc_doorbell_ack_vaddr; >>> +/* Array of doorbell interrupts */ >>> +static int *pcc_doorbell_irq; >>> >>> static struct mbox_controller pcc_mbox_ctrl = {}; >>> /** >>> @@ -91,6 +97,132 @@ static struct mbox_chan *get_pcc_channel(int id) >>> return &pcc_mbox_channels[id]; >>> } >>> >>> +/* >>> + * PCC can be used with perf critical drivers such as CPPC >>> + * So it makes sense to locally cache the virtual address and >>> + * use it to read/write to PCC registers such as doorbell register >>> + * >>> + * The below read_register and write_registers are used to read and >>> + * write from perf critical registers such as PCC doorbell register >>> + */ >>> +static int read_register(void __iomem *vaddr, u64 *val, unsigned int >>> bit_width) >>> +{ >>> + int ret_val = 0; >>> + >>> + switch (bit_width) { >>> + case 8: >>> + *val = readb(vaddr); >>> + break; >>> + case 16: >>> + *val = readw(vaddr); >>> + break; >>> + case 32: >>> + *val = readl(vaddr); >>> + break; >>> + case 64: >>> + *val = readq(vaddr); >>> + break; >>> + default: >>> + pr_debug("Error: Cannot read register of %u bit width", >>> + bit_width); >>> + ret_val = -EFAULT; >>> + break; >>> + } >>> + return ret_val; >>> +} >>> + >>> +static int write_register(void __iomem *vaddr, u64 val, unsigned int >>> bit_width) >>> +{ >>> + int ret_val = 0; >>> + >>> + switch (bit_width) { >>> + case 8: >>> + writeb(val, vaddr); >>> + break; >>> + case 16: >>> + writew(val, vaddr); >>> + break; >>> + case 32: >>> + writel(val, vaddr); >>> + break; >>> + case 64: >>> + writeq(val, vaddr); >>> + break; >>> + default: >>> + pr_debug("Error: Cannot write register of %u bit width", >>> + bit_width); >>> + ret_val = -EFAULT; >>> + break; >>> + } >>> + return ret_val; >>> +} >>> + >> >> Isn't this just reordering of function locations? I don't mean to be >> nitpicky, but your cosmetic changes in this file m
Re: [PATCH] spi: rockchip: Signal unfinished DMA transfers
Am Mittwoch, 8. Juni 2016, 09:32:51 schrieb Tomeu Vizoso: > When using DMA, the transfer_one callback should return 1 because the > transfer hasn't finished yet. > > A previous commit changed the function to return 0 when the DMA channels > were correctly prepared. > > This manifested in Veyron boards with this message: > > [ 1.983605] cros-ec-spi spi0.0: EC failed to respond in time > > Signed-off-by: Tomeu Vizoso > Fixes: ea9849113343 ("spi: rockchip: check return value of > dmaengine_prep_slave_sg") > Cc: Shawn Lin > Cc: Heiko Stuebner > Cc: Javier Martinez Canillas looks like Mark already applied it, but nevertheless I was able to verify that this patch fixes the issue on my veyron jerry chromebook as well, so Tested-by: Heiko Stuebner
[PATCH] arm64: defconfig: enable CONFIG_LOCALVERSION_AUTO
When CONFIG_LOCALVERSION_AUTO is disabled, the version string is just a tag name (or with a '+' appended if HEAD is not a tagged commit). During the development (and especially when git-bisecting), longer version string would be helpful to identify the commit we are running. This is a default y option, so drop the unset to enable it. Signed-off-by: Masahiro Yamada --- arch/arm64/configs/defconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index c8f287f..1e76fc2 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -1,4 +1,3 @@ -# CONFIG_LOCALVERSION_AUTO is not set CONFIG_SYSVIPC=y CONFIG_POSIX_MQUEUE=y CONFIG_AUDIT=y -- 1.9.1
Re: [PATCH 06/10] mm: remove unnecessary use-once cache bias from LRU balancing
On Mon 06-06-16 15:48:32, Johannes Weiner wrote: > When the splitlru patches divided page cache and swap-backed pages > into separate LRU lists, the pressure balance between the lists was > biased to account for the fact that streaming IO can cause memory > pressure with a flood of pages that are used only once. New page cache > additions would tip the balance toward the file LRU, and repeat access > would neutralize that bias again. This ensured that page reclaim would > always go for used-once cache first. > > Since e9868505987a ("mm,vmscan: only evict file pages when we have > plenty"), page reclaim generally skips over swap-backed memory > entirely as long as there is used-once cache present, and will apply > the LRU balancing when only repeatedly accessed cache pages are left - > at which point the previous use-once bias will have been neutralized. > > This makes the use-once cache balancing bias unnecessary. Remove it. > > Signed-off-by: Johannes Weiner Acked-by: Michal Hocko > --- > mm/swap.c | 11 --- > 1 file changed, 11 deletions(-) > > diff --git a/mm/swap.c b/mm/swap.c > index 576c721f210b..814e3a2e54b4 100644 > --- a/mm/swap.c > +++ b/mm/swap.c > @@ -264,7 +264,6 @@ static void __activate_page(struct page *page, struct > lruvec *lruvec, > void *arg) > { > if (PageLRU(page) && !PageActive(page) && !PageUnevictable(page)) { > - int file = page_is_file_cache(page); > int lru = page_lru_base_type(page); > > del_page_from_lru_list(page, lruvec, lru); > @@ -274,7 +273,6 @@ static void __activate_page(struct page *page, struct > lruvec *lruvec, > trace_mm_lru_activate(page); > > __count_vm_event(PGACTIVATE); > - update_page_reclaim_stat(lruvec, file, 1, hpage_nr_pages(page)); > } > } > > @@ -797,8 +795,6 @@ EXPORT_SYMBOL(__pagevec_release); > void lru_add_page_tail(struct page *page, struct page *page_tail, > struct lruvec *lruvec, struct list_head *list) > { > - const int file = 0; > - > VM_BUG_ON_PAGE(!PageHead(page), page); > VM_BUG_ON_PAGE(PageCompound(page_tail), page); > VM_BUG_ON_PAGE(PageLRU(page_tail), page); > @@ -833,20 +829,13 @@ void lru_add_page_tail(struct page *page, struct page > *page_tail, > static void __pagevec_lru_add_fn(struct page *page, struct lruvec *lruvec, >void *arg) > { > - int file = page_is_file_cache(page); > - int active = PageActive(page); > enum lru_list lru = page_lru(page); > - bool new = (bool)arg; > > VM_BUG_ON_PAGE(PageLRU(page), page); > > SetPageLRU(page); > add_page_to_lru_list(page, lruvec, lru); > > - if (new) > - update_page_reclaim_stat(lruvec, file, active, > - hpage_nr_pages(page)); > - > trace_mm_lru_insertion(page, lru); > } > > -- > 2.8.3 -- Michal Hocko SUSE Labs
Re: Nokia N900: musb is in wrong state after boot
On 6/8/2016 3:18 PM, joerg Reisenweber wrote: Tony, what do you think about that patch? Tony, PING Yeah I don't know, AFAIK we don't have a generic way to force MUSB to change mode without ID pin. If you have figured something generic for that which does not actually tinker with the PHY registers directly, that should be the generic musb_set_mode() that we've been wondering about for years. #define MUSB_TEST_FORCE_HOST0x80 Can someone confirm on MUSB's docs (and actual running system) that this does what's supposed to do? The MUSB programmer's guide says the CID (sic) input is ignored when the Force_Host bit is set. The host mode is entered when the Session bit is set. But I don't have a MUSB hardware readily available to confirm. MBR, Sergei also says: While the FORCE_HOST bit remains set, the core will enter Host mode when the Session bit is set and **remain in Host mode until the Session bit is cleared even if a connected device is disconnected during the session.** The operating speed while in this mode **is determined for the setting of the FORCE_HS and FORCE_FS bits of the Testmode register** in Section 23.1.4.11. Yeah, the MUSB PG says the same. [...] /j MBR, Sergei
Re: [PATCH 1/2] x86/entry: Avoid interrupt flag save and restore
On 08/06/2016 14:16, Ingo Molnar wrote: > > The guest ones are not quite as consistent. I can fix that later, > > there's no reason also to have guest context tracking split between > > include/linux/context_tracking.h and include/linux/kvm_host.h. > > Could we please first do the cleanups before complicating the code and > applying > more substantial changes? The further cleanups wouldn't complicate the code. It's just that guest_enter/guest_exit require IRQs off but don't have __. I'm thinking of something like this (untested): diff --git a/include/linux/context_tracking.h b/include/linux/context_tracking.h index d259274238db..c2dc581ddb0e 100644 --- a/include/linux/context_tracking.h +++ b/include/linux/context_tracking.h @@ -84,7 +84,7 @@ static inline void context_tracking_init(void) { } #ifdef CONFIG_VIRT_CPU_ACCOUNTING_GEN -static inline void guest_enter(void) +static inline void __guest_enter(void) { if (vtime_accounting_cpu_enabled()) vtime_guest_enter(current); @@ -93,9 +93,19 @@ static inline void guest_enter(void) if (context_tracking_is_enabled()) __context_tracking_enter(CONTEXT_GUEST); + + /* KVM does not hold any references to rcu protected data when it +* switches CPU into a guest mode. In fact switching to a guest mode +* is very similar to exiting to userspace from rcu point of view. In +* addition CPU may stay in a guest mode for quite a long time (up to +* one time slice). Lets treat guest mode as quiescent state, just like +* we do with user-mode execution. +*/ + if (!context_tracking_cpu_is_enabled()) + rcu_virt_note_context_switch(smp_processor_id()); } -static inline void guest_exit(void) +static inline void __guest_exit(void) { if (context_tracking_is_enabled()) __context_tracking_exit(CONTEXT_GUEST); @@ -107,7 +117,7 @@ static inline void guest_exit(void) } #else -static inline void guest_enter(void) +static inline void __guest_enter(void) { /* * This is running in ioctl context so its safe @@ -118,7 +128,7 @@ static inline void guest_enter(void) current->flags |= PF_VCPU; } -static inline void guest_exit(void) +static inline void __guest_exit(void) { /* Flush the guest cputime we spent on the guest */ vtime_account_system(current); @@ -126,4 +136,23 @@ static inline void guest_exit(void) } #endif /* CONFIG_VIRT_CPU_ACCOUNTING_GEN */ +static inline void guest_enter(void) +{ + unsigned long flags; + + local_irq_save(flags); + __guest_enter(); + local_irq_restore(flags); +} + +/* must be called with irqs disabled */ +static inline void guest_exit(void) +{ + unsigned long flags; + + local_irq_save(flags); + __guest_exit(); + local_irq_restore(flags); +} + #endif diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h index 5276fe0916fc..d00fdaa8da15 100644 --- a/include/linux/kvm_host.h +++ b/include/linux/kvm_host.h @@ -861,40 +861,23 @@ static inline void kvm_iommu_unmap_pages(struct kvm *kvm, /* must be called with irqs disabled */ static inline void __kvm_guest_enter(void) { - guest_enter(); - /* KVM does not hold any references to rcu protected data when it -* switches CPU into a guest mode. In fact switching to a guest mode -* is very similar to exiting to userspace from rcu point of view. In -* addition CPU may stay in a guest mode for quite a long time (up to -* one time slice). Lets treat guest mode as quiescent state, just like -* we do with user-mode execution. -*/ - if (!context_tracking_cpu_is_enabled()) - rcu_virt_note_context_switch(smp_processor_id()); + __guest_enter(); } /* must be called with irqs disabled */ static inline void __kvm_guest_exit(void) { - guest_exit(); + __guest_exit(); } static inline void kvm_guest_enter(void) { - unsigned long flags; - - local_irq_save(flags); - __kvm_guest_enter(); - local_irq_restore(flags); + guest_enter(); } static inline void kvm_guest_exit(void) { - unsigned long flags; - - local_irq_save(flags); - __kvm_guest_exit(); - local_irq_restore(flags); + guest_exit(); } /* and then removing the kvm_-prefixed functions. It's little more than code movement. Paolo
Re: [PATCH v3] powerpc: spinlock: Fix spin_unlock_wait()
On Wed, Jun 08, 2016 at 09:20:45PM +1000, Michael Ellerman wrote: > On Mon, 2016-06-06 at 16:46 +0200, Peter Zijlstra wrote: > > On Mon, Jun 06, 2016 at 10:17:25PM +1000, Michael Ellerman wrote: > > > On Mon, 2016-06-06 at 13:56 +0200, Peter Zijlstra wrote: > > > > On Mon, Jun 06, 2016 at 09:42:20PM +1000, Michael Ellerman wrote: > > > > > > > > Why the move to in-line this implementation? It looks like a fairly big > > > > function. > > > > > > I agree it's not pretty. > > > > > I'm not beholden to v3 though if you hate it. > > > > I don't mind; its just that I am in a similar boat with qspinlock and > > chose the other option. So I just figured I'd ask :-) > > OK. I'll go with inline and we'll see which version gets "cleaned-up" by a > janitor first ;) Ok; what tree does this go in? I have this dependent series which I'd like to get sorted and merged somewhere.
Re: [PATCH] x86/efi: Auto enable EFI memmap on SGI UV systems
(Cc'ing people familiar with e820 map woes) On Thu, 02 Jun, at 03:50:35PM, Joseph Thelen wrote: > Currently, the EFI memory map entries are disabled by default and must > be enabled by passing the kernel boot option: > > add_efi_memmap > > The EFI memory map entries should be enabled on systems with more > than 128 E820 entries, which includes many UV systems. Check if > we're on a UV system by chekcing the uv system table. > Enable the EFI memory map entries if we're on a UV system. > > This change is backward compatible because the EFI memory map entries are > still disabled by default on non-UV systems, and it maintains the previous > behavior of the kernel boot option. In addition, it allows the EFI memory > map entries to be explicitly disabled (will not be automatically enabled) > by setting the add_efi_memmap boot option to anything that kstringtobool > will determine to be false. > > Signed-off-by: Joseph Thelen > Cc: Alex Thorlton > Cc: Matt Fleming > Cc: Thomas Gleixner > Cc: Ingo Molnar > Cc: "H. Peter Anvin" > Cc: x...@kernel.org > Cc: linux-...@vger.kernel.org > --- > arch/x86/platform/efi/efi.c | 43 +++ > 1 file changed, 39 insertions(+), 4 deletions(-) What's the ultimate goal here? To not require that users specify the add_efi_memmap kernel parameter in the future? Presumably they do today? FYI, a lot of non-UV systems have more than 128 entries and the way we handle it is by using the SETUP_E820_EXT setup_data entry in boot_params in the EFI boot stub (I don't think boot loaders use it because they largely go via the stub anyhow). So if you've got control over your boot loader, and assuming SGI UV systems don't boot using the EFI boot stub, you could look at adding boot loader support for SETUP_E820_EXT to force enable > 128 entries automatically without any new kernel code.
[BUGFIX][PATCH v8 1/5] perf config: Handle the error about NULL at perf_config_set__delete()
perf_config_set__delete() purge and free the config set that contains all config key-value pairs. But if the config set (i.e. 'set' variable at the function) is NULL, this is wrong so handle it. Cc: Alexander Shishkin Cc: Jiri Olsa Cc: Masami Hiramatsu Cc: Namhyung Kim Cc: Wang Nan Signed-off-by: Taeung Song --- tools/perf/util/config.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tools/perf/util/config.c b/tools/perf/util/config.c index 8749eca..31e09a4 100644 --- a/tools/perf/util/config.c +++ b/tools/perf/util/config.c @@ -742,6 +742,9 @@ static void perf_config_set__purge(struct perf_config_set *set) void perf_config_set__delete(struct perf_config_set *set) { + if (set == NULL) + return; + perf_config_set__purge(set); free(set); } -- 2.5.0
[PATCH v8 3/5] perf config: Reimplement perf_config() using perf_config_set__iter()
Many sub-commands use perf_config() so everytime perf_config() is called, perf_config() always read config files. (i.e. user config '~/.perfconfig' and system config '$(sysconfdir)/perfconfig') But we need to use the config set that already contains all config key-value pairs to avoid this repetitive work reading the config files in perf_config(). (the config set mean a global variable 'config_set') In other words, if new perf_config() is called, only first time 'config_set' is initialized collecting all configs from the config files and it work with perf_config_set__iter(). And free the config set after a sub-command work at run_builtin(). If we do, 'config_set' can be reused wherever using perf_config() and a feature of old perf_config() is the same as new perf_config() work without the repetitive work that read the config files. Cc: Namhyung Kim Cc: Jiri Olsa Cc: Wang Nan Cc: Peter Zijlstra Cc: Ingo Molnar Cc: Masami Hiramatsu Cc: Alexander Shishkin Signed-off-by: Taeung Song --- tools/perf/builtin-config.c | 4 +++ tools/perf/perf.c | 1 + tools/perf/util/config.c| 87 ++--- tools/perf/util/config.h| 1 + 4 files changed, 48 insertions(+), 45 deletions(-) diff --git a/tools/perf/builtin-config.c b/tools/perf/builtin-config.c index fe1b77f..cfd1036 100644 --- a/tools/perf/builtin-config.c +++ b/tools/perf/builtin-config.c @@ -80,6 +80,10 @@ int cmd_config(int argc, const char **argv, const char *prefix __maybe_unused) else if (use_user_config) config_exclusive_filename = user_config; + /* +* At only 'config' sub-command, individually use the config set +* because of reinitializing with options config file location. +*/ set = perf_config_set__new(); if (!set) { ret = -1; diff --git a/tools/perf/perf.c b/tools/perf/perf.c index 15982ce..fe2ab7c 100644 --- a/tools/perf/perf.c +++ b/tools/perf/perf.c @@ -391,6 +391,7 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv) perf_env__set_cmdline(&perf_env, argc, argv); status = p->fn(argc, argv, prefix); + perf_config_set__delete(config_set); exit_browser(status); perf_env__exit(&perf_env); bpf__clear(); diff --git a/tools/perf/util/config.c b/tools/perf/util/config.c index 31e09a4..72db134 100644 --- a/tools/perf/util/config.c +++ b/tools/perf/util/config.c @@ -28,6 +28,7 @@ static int config_linenr; static int config_file_eof; const char *config_exclusive_filename; +struct perf_config_set *config_set; static int get_next_char(void) { @@ -478,51 +479,6 @@ static int perf_config_global(void) return !perf_env_bool("PERF_CONFIG_NOGLOBAL", 0); } -int perf_config(config_fn_t fn, void *data) -{ - int ret = -1; - const char *home = NULL; - - /* Setting $PERF_CONFIG makes perf read _only_ the given config file. */ - if (config_exclusive_filename) - return perf_config_from_file(fn, config_exclusive_filename, data); - if (perf_config_system() && !access(perf_etc_perfconfig(), R_OK)) { - if (perf_config_from_file(fn, perf_etc_perfconfig(), data) < 0) - goto out; - } - - home = getenv("HOME"); - if (perf_config_global() && home) { - char *user_config = strdup(mkpath("%s/.perfconfig", home)); - struct stat st; - - if (user_config == NULL) { - warning("Not enough memory to process %s/.perfconfig, " - "ignoring it.", home); - goto out; - } - - if (stat(user_config, &st) < 0) - goto out_free; - - if (st.st_uid && (st.st_uid != geteuid())) { - warning("File %s not owned by current user or root, " - "ignoring it.", user_config); - goto out_free; - } - - if (!st.st_size) - goto out_free; - - ret = perf_config_from_file(fn, user_config, data); - -out_free: - free(user_config); - } -out: - return ret; -} - static struct perf_config_section *find_section(struct list_head *sections, const char *section_name) { @@ -706,6 +662,47 @@ struct perf_config_set *perf_config_set__new(void) return set; } +static int perf_config_set__iter(struct perf_config_set *set, config_fn_t fn, void *data) +{ + struct perf_config_section *section; + struct perf_config_item *item; + struct list_head *sections; + char key[BUFSIZ]; + + if (set == NULL) + return -1; + + sections = &set->sections; + if (list_empty(sections)) + return -1; + + list_for_each_entry(section, sections, node) { +
[PATCH v8 2/5] perf config: Bring declarations about config from util/cache.h to util/config.h
Lately util/config.h has been added but util/cache.h has declarations of functions and extern variable for config features. To manage codes about configuration at one spot, move them to util/config.h and util/cache.h include util/config.h Cc: Alexander Shishkin Cc: Jiri Olsa Cc: Masami Hiramatsu Cc: Namhyung Kim Cc: Wang Nan Signed-off-by: Taeung Song --- tools/perf/util/cache.h | 13 + tools/perf/util/config.h | 12 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/tools/perf/util/cache.h b/tools/perf/util/cache.h index 0d814bb..cd8cd4d 100644 --- a/tools/perf/util/cache.h +++ b/tools/perf/util/cache.h @@ -7,6 +7,7 @@ #include #include "../perf.h" #include "../ui/ui.h" +#include "config.h" #include @@ -23,18 +24,6 @@ #define PERF_TRACEFS_ENVIRONMENT "PERF_TRACEFS_DIR" #define PERF_PAGER_ENVIRONMENT "PERF_PAGER" -extern const char *config_exclusive_filename; - -typedef int (*config_fn_t)(const char *, const char *, void *); -int perf_default_config(const char *, const char *, void *); -int perf_config(config_fn_t fn, void *); -int perf_config_int(const char *, const char *); -u64 perf_config_u64(const char *, const char *); -int perf_config_bool(const char *, const char *); -int config_error_nonbool(const char *); -const char *perf_config_dirname(const char *, const char *); -const char *perf_etc_perfconfig(void); - char *alias_lookup(const char *alias); int split_cmdline(char *cmdline, const char ***argv); diff --git a/tools/perf/util/config.h b/tools/perf/util/config.h index 22ec626..35ccddb 100644 --- a/tools/perf/util/config.h +++ b/tools/perf/util/config.h @@ -20,6 +20,18 @@ struct perf_config_set { struct list_head sections; }; +extern const char *config_exclusive_filename; + +typedef int (*config_fn_t)(const char *, const char *, void *); +int perf_default_config(const char *, const char *, void *); +int perf_config(config_fn_t fn, void *); +int perf_config_int(const char *, const char *); +u64 perf_config_u64(const char *, const char *); +int perf_config_bool(const char *, const char *); +int config_error_nonbool(const char *); +const char *perf_config_dirname(const char *, const char *); +const char *perf_etc_perfconfig(void); + struct perf_config_set *perf_config_set__new(void); void perf_config_set__delete(struct perf_config_set *set); -- 2.5.0
[PATCH v8 5/5] perf config: Reimplement show_config() using perf_config_set__iter()
Old show_config() directly use config set so there are many duplicated code with perf_config_set__iter(). So reimplement show_config() using perf_config() that use perf_config_set__iter() with config set that already contains all configs. Cc: Namhyung Kim Cc: Jiri Olsa Cc: Masami Hiramatsu Cc: Alexander Shishkin Cc: Wang Nan Signed-off-by: Taeung Song --- tools/perf/builtin-config.c | 29 +++-- tools/perf/util/config.c| 2 +- tools/perf/util/config.h| 1 + 3 files changed, 9 insertions(+), 23 deletions(-) diff --git a/tools/perf/builtin-config.c b/tools/perf/builtin-config.c index c07f744..9c654f9 100644 --- a/tools/perf/builtin-config.c +++ b/tools/perf/builtin-config.c @@ -33,28 +33,13 @@ static struct option config_options[] = { OPT_END() }; -static int show_config(struct perf_config_set *set) +static int show_config(const char *key, const char *value, + void *cb __maybe_unused) { - struct perf_config_section *section; - struct perf_config_item *item; - struct list_head *sections; - - if (set == NULL) - return -1; - - sections = &set->sections; - if (list_empty(sections)) - return -1; - - list_for_each_entry(section, sections, node) { - list_for_each_entry(item, §ion->items, node) { - char *value = item->value; - - if (value) - printf("%s.%s=%s\n", section->name, - item->name, value); - } - } + if (value) + printf("%s=%s\n", key, value); + else + printf("%s\n", key); return 0; } @@ -96,7 +81,7 @@ int cmd_config(int argc, const char **argv, const char *prefix __maybe_unused) pr_err("Error: takes no arguments\n"); parse_options_usage(config_usage, config_options, "l", 1); } else { - ret = show_config(set); + ret = perf_config_set__iter(set, show_config, NULL); if (ret < 0) { const char * config_filename = config_exclusive_filename; if (!config_exclusive_filename) diff --git a/tools/perf/util/config.c b/tools/perf/util/config.c index 23fb8e4..4775d18 100644 --- a/tools/perf/util/config.c +++ b/tools/perf/util/config.c @@ -662,7 +662,7 @@ struct perf_config_set *perf_config_set__new(void) return set; } -static int perf_config_set__iter(struct perf_config_set *set, config_fn_t fn, void *data) +int perf_config_set__iter(struct perf_config_set *set, config_fn_t fn, void *data) { struct perf_config_section *section; struct perf_config_item *item; diff --git a/tools/perf/util/config.h b/tools/perf/util/config.h index fafba86..3526bb7 100644 --- a/tools/perf/util/config.h +++ b/tools/perf/util/config.h @@ -35,5 +35,6 @@ const char *perf_etc_perfconfig(void); struct perf_config_set *perf_config_set__new(void); void perf_config_set__delete(struct perf_config_set **set); +int perf_config_set__iter(struct perf_config_set *set, config_fn_t fn, void *data); #endif /* __PERF_CONFIG_H */ -- 2.5.0
[PATCH v8 4/5] perf config: Use zfree() instead of free() at perf_config_set__delete()
perf_config_set__delete() delete allocated the config set but the global variable 'config_set' is used all around. So purge and zfree by an address of the global variable , i.e. 'struct perf_config_set **' type instead of using local variable 'set' of which type is 'struct perf_config_set *'. Cc: Namhyung Kim Cc: Jiri Olsa Cc: Masami Hiramatsu Cc: Alexander Shishkin Cc: Wang Nan Signed-off-by: Taeung Song --- tools/perf/builtin-config.c | 2 +- tools/perf/perf.c | 2 +- tools/perf/util/config.c| 10 +- tools/perf/util/config.h| 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/tools/perf/builtin-config.c b/tools/perf/builtin-config.c index cfd1036..c07f744 100644 --- a/tools/perf/builtin-config.c +++ b/tools/perf/builtin-config.c @@ -110,7 +110,7 @@ int cmd_config(int argc, const char **argv, const char *prefix __maybe_unused) usage_with_options(config_usage, config_options); } - perf_config_set__delete(set); + perf_config_set__delete(&set); out_err: return ret; } diff --git a/tools/perf/perf.c b/tools/perf/perf.c index fe2ab7c..058d5dc 100644 --- a/tools/perf/perf.c +++ b/tools/perf/perf.c @@ -391,7 +391,7 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv) perf_env__set_cmdline(&perf_env, argc, argv); status = p->fn(argc, argv, prefix); - perf_config_set__delete(config_set); + perf_config_set__delete(&config_set); exit_browser(status); perf_env__exit(&perf_env); bpf__clear(); diff --git a/tools/perf/util/config.c b/tools/perf/util/config.c index 72db134..23fb8e4 100644 --- a/tools/perf/util/config.c +++ b/tools/perf/util/config.c @@ -654,7 +654,7 @@ struct perf_config_set *perf_config_set__new(void) if (set) { INIT_LIST_HEAD(&set->sections); if (perf_config_set__init(set) < 0) { - perf_config_set__delete(set); + perf_config_set__delete(&set); set = NULL; } } @@ -737,13 +737,13 @@ static void perf_config_set__purge(struct perf_config_set *set) } } -void perf_config_set__delete(struct perf_config_set *set) +void perf_config_set__delete(struct perf_config_set **set) { - if (set == NULL) + if (*set == NULL) return; - perf_config_set__purge(set); - free(set); + perf_config_set__purge(*set); + zfree(set); } /* diff --git a/tools/perf/util/config.h b/tools/perf/util/config.h index 7cc4fea..fafba86 100644 --- a/tools/perf/util/config.h +++ b/tools/perf/util/config.h @@ -34,6 +34,6 @@ const char *perf_config_dirname(const char *, const char *); const char *perf_etc_perfconfig(void); struct perf_config_set *perf_config_set__new(void); -void perf_config_set__delete(struct perf_config_set *set); +void perf_config_set__delete(struct perf_config_set **set); #endif /* __PERF_CONFIG_H */ -- 2.5.0
[RFC][PATCH v8 0/5] perf config: Reimplement perf_config() using perf_config_set__inter()
Hello, :) This patchset is to reimplement perf_config() for efficient config management. Everytime perf_config() is called, perf_config() always read config files. (i.e. user config '~/.perfconfig' and system config '$(sysconfdir)/perfconfig') But we need to use 'struct perf_config_set config_set' variable that already contains all config key-value pairs to avoid this repetitive work in perf_config(). In other words, if new perf_config() is called, only first time 'config_set' is initialized collecting all configs from config files and it work with perf_config_set__iter(). If we do, 'config_set' can be reused wherever using perf_config() and a feature of old perf_config() is the same as new perf_config() work without the repetitive work that read the config files. IMHO, I think this patchset is needed because not only the repetitive work should be avoided but also in near future, it would be smooth to manage perf configs. If you give me any feedback, I'd apprecicated it. :) Thanks, Taeung v8: - handle the error about NULL at perf_config_set__delete() - bring declarations about config from util/config.h to util/config.h - reimplement show_config() using perf_config_set__iter() instead of perf_config() - rebased onto perf-core-for-mingo-20160607 - applied ([PATCH v7 1/7] 25d8f48, [PATCH v7 2/7] 8beeb00) v7: - fill a missing crumb that assign NULL to 'set' variable in perf_config_set__new() (Arnaldo) - two patches applied ([PATCH v6 1/9] 78f71c9, [PATCH v6 3/9] 7db91f2) v6: - add printing error message when perf_config_set__iter() is failed - modify commit messages for bugfix 1~3 (PATCH 1/9 ~ 3/9) to help reviewers easily understand why them is needed v5: - solve the leak when perf_config_set__init() failed (Arnaldo) (to clear the problem it is needed to apply the bottom bugfix 1~3 patches) - bugfix 1) fix the problem of abnormal terminaltion at perf_parse_file() called by perf_config() - bugfix 2) if failed at collect_config(), finally free a config set after it is done instead of freeing the config set in the function - bugfix 3) handle NULL pointer exception of 'set' at collect_config() v4: - Keep perf_config_set__delete() as it is (Arnaldo) - Remove perf_config_set__check() (Arnaldo) - Keep the existing code about the config set at cmd_config() (Arnaldo) v3: - add freeing config set after sub-command work at run_builtin() (Namhyung) - remove needless code about the config set at cmd_config() - add a patch about a global variable 'config_set' v2: - split a patch into several patches - reimplement show_config() using new perf_config() - modify perf_config_set__delete using global variable 'config_set' - reset config set when only 'config' sub-commaned work because of options for config file location Taeung Song (5): perf config: Handle the error about NULL at perf_config_set__delete() perf config: Bring declarations about config from util/cache.h to util/config.h perf config: Reimplement perf_config() using perf_config_set__iter() perf config: Use zfree() instead of free() at perf_config_set__delete() perf config: Reimplement show_config() using perf_config_set__iter() tools/perf/builtin-config.c | 35 ++-- tools/perf/perf.c | 1 + tools/perf/util/cache.h | 13 +- tools/perf/util/config.c| 98 ++--- tools/perf/util/config.h| 16 +++- 5 files changed, 78 insertions(+), 85 deletions(-) -- 2.5.0
Re: [PATCH v7 3/7] perf config: Add global variable 'config_set'
My answer was too long.. To be short, many sub-commands use perf_config() so wherever new perf_config() is called, the config set that already contains all configs from config files should be shared. And when a sub-command is done, we need to free the config set at run_builtin() as below. So, IMHO we need to use 'config_set' as a global variable. Anyway I sent v8 recasting this patchset with other way. (But 'config_set' is still a global variable.) Please, reconsider it again. Thanks, Taeung On 06/08/2016 12:14 AM, Taeung Song wrote: Good afternoon :) On 06/07/2016 11:05 PM, Arnaldo Carvalho de Melo wrote: Em Tue, Jun 07, 2016 at 06:26:13PM +0900, Taeung Song escreveu: The config set is prepared by collecting all configs from config files (i.e. user config ~/.perfconfig and system config $(sysconfdir)/perfconfig) so the config set contains all config key-value pairs. We need to use it as global variable to share it. We should generally avoid global variables, and in this case, from looking just at this patch, I'm not convinced we need to introduce more global variables, isn't this object instantiated and deleted at the cmd_config() function? So, can't we just pass it to any function needing to access it? The reason why I added global variable 'config_set' that all config key-value pairs from config files is because of upcoming perf_config_set__delete() and perf_config(). This variable can be used not only at cmd_config() but also at new perf_config() and future perf_config_set__delete(). Wherever new perf_config() is called, this function check whether the global variable 'config_set' is initialized or not. And this function use the variable 'config_set' like below. (One of intended purposes of new perf_config() is to avoid the repetitive work that read config files, every time it is called and to reuse the global variable 'config_set' that already contains all config info.) +int perf_config(config_fn_t fn, void *data) +{ + if (config_set == NULL) + config_set = perf_config_set__new(); + + return perf_config_set__iter(config_set, fn, data); +} Finally, after sub-command finished, called perf_config_set__delete() use the global variable as argument to free it as below. diff --git a/tools/perf/perf.c b/tools/perf/perf.c index 15982ce..058d5dc 100644 --- a/tools/perf/perf.c +++ b/tools/perf/perf.c @@ -391,6 +391,7 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv) perf_env__set_cmdline(&perf_env, argc, argv); status = p->fn(argc, argv, prefix); + perf_config_set__delete(&config_set); exit_browser(status); perf_env__exit(&perf_env); bpf__clear(); Sure, we can avoid 'extern' for the global variable 'config_set'. But IMHO, we may need to use a global variable 'config_set' at only util/config.c at least. (If perf_config_set__delete() don't take arguments) (But it seems natural that we should pair between destructor and constructor as you said. http://marc.info/?l=linux-kernel&m=146463657721848&w=2 ) And of course, there are other way e.g. modifying arguments of perf_config(), using perf_config_set__new() at the very beginning at main() or etc... Nevertheless, if we haven't to use the global variable, I'd find other way. I applied the first two patches. Thank you! Taeung And in near future, the variable will be handled in perf_config() and other functions at util/config.c Cc: Namhyung Kim Cc: Jiri Olsa Cc: Masami Hiramatsu Cc: Alexander Shishkin Signed-off-by: Taeung Song --- tools/perf/builtin-config.c | 9 - tools/perf/util/config.c| 1 + tools/perf/util/config.h| 2 ++ 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/tools/perf/builtin-config.c b/tools/perf/builtin-config.c index fe1b77f..b3bc01a 100644 --- a/tools/perf/builtin-config.c +++ b/tools/perf/builtin-config.c @@ -62,7 +62,6 @@ static int show_config(struct perf_config_set *set) int cmd_config(int argc, const char **argv, const char *prefix __maybe_unused) { int ret = 0; -struct perf_config_set *set; char *user_config = mkpath("%s/.perfconfig", getenv("HOME")); argc = parse_options(argc, argv, config_options, config_usage, @@ -80,8 +79,8 @@ int cmd_config(int argc, const char **argv, const char *prefix __maybe_unused) else if (use_user_config) config_exclusive_filename = user_config; -set = perf_config_set__new(); -if (!set) { +config_set = perf_config_set__new(); +if (!config_set) { ret = -1; goto out_err; } @@ -92,7 +91,7 @@ int cmd_config(int argc, const char **argv, const char *prefix __maybe_unused) pr_err("Error: takes no arguments\n"); parse_options_usage(config_usage, config_options, "l", 1); } else { -ret = show_config(set); +ret = show_config(config_set); if (ret < 0) { const char *
Re: [PATCH] x86/efi: remove unused variable efi
On Mon, 06 Jun, at 03:32:11PM, Colin Ian King wrote: > From: Colin Ian King > > Remove unused variable efi, it is never used. Fixes clang build > warning: > > arch/x86/boot/compressed/eboot.c:803:2: warning: Value stored to > 'efi' is never read > > Signed-off-by: Colin Ian King > --- > arch/x86/boot/compressed/eboot.c | 2 -- > 1 file changed, 2 deletions(-) Thanks Colin, applied to 'next'.
Re: [PATCH] [efifb] Fix 16 color palette entry calculation
On Tue, 07 Jun, at 01:23:05PM, Peter Jones wrote: > > Looks right to me. > > Acked-By: Peter Jones Tomi, are you OK to take this one or would you like me to take it through the EFI tree?
Re: [PATCH -v2 00/33] implement atomic_fetch_$op
On Thu, Jun 02, 2016 at 11:33:04AM +0200, Peter Zijlstra wrote: > On Thu, Jun 02, 2016 at 09:27:36AM +, Vineet Gupta wrote: > > What's ur merge plan - are u going to rebase/respin once more so I can push > > those > > updates to Linus for 4.7-rc2. Or you could carry those ARC patches in ur > > tree - > > ahead of ur series. I'd much rather prefer the revert / cleanup before > > adding new > > code which extends the back off code only to be deleted later. > > I was hoping to get these into tip for v4.8, I can rebase on whatever > changes you make in v4.7 no problem. -rc2 seems to have happened and I cannot seem to find changes to arc/atomic.h, will you still be pushing those patches this window or should I queue my patches?
Re: [PATCH v9 08/14] usb: otg: add OTG/dual-role core
On Wed, Jun 08, 2016 at 01:12:10PM +0300, Roger Quadros wrote: > Hi, > > On 08/06/16 12:53, Peter Chen wrote: > > On Wed, Jun 08, 2016 at 12:03:40PM +0300, Roger Quadros wrote: > >> +int usb_otg_unregister(struct device *dev) > >> +{ > >> + struct usb_otg *otg; > >> + > >> + mutex_lock(&otg_list_mutex); > >> + otg = usb_otg_get_data(dev); > >> + if (!otg) { > >> + dev_err(dev, "otg: %s: device not in otg list\n", > >> + __func__); > >> + mutex_unlock(&otg_list_mutex); > >> + return -EINVAL; > >> + } > >> + > >> + /* prevent unregister till both host & gadget have unregistered */ > >> + if (otg->host || otg->gadget) { > >> + dev_err(dev, "otg: %s: host/gadget still registered\n", > >> + __func__); > > > > You need to call mutex_unlock here > > Indeed. good catch. > > > >> + > >> +int usb_otg_gadget_ready(struct usb_gadget *gadget, bool ready) > >> +{ > > > > What this API is for? Why need it in this version? > > we moved gadget to otg registration from udc_bind_to_driver() to > usb_add_gadget_udc_release(). > This means there is a window when gadget function driver (e.g. g_zero) is not > loaded. > We don't want to start the gadget controller in that window. > > usb_otg_gadget_ready() is used by gadget core to notify the otg core when the > function driver > is ready or not-ready. > Why you need to move this from gadget's probe to udc's probe? Currently, the sequence of gadget and udc's probe is random, but udc_bind_to_driver is called when udc is ready. -- Best Regards, Peter Chen
Re: [RFC][PATCH 2/5] driver core: Functional dependencies tracking support
On Thu, Jan 14, 2016 at 02:54:17AM +0100, Rafael J. Wysocki wrote: > + * A side effect of the link creation is re-ordering of dpm_list and the > + * devices_kset list by moving the consumer device and all devices depending > + * on it to the ends of those lists. How does this work in the scenario where a device instantiates a child device then uses services that child provides to complete the initializiation? We do have that scenario currently for on chip regulators to allow external regulators to be used. signature.asc Description: PGP signature
Re: [PATCH 07/10] mm: base LRU balancing on an explicit cost model
On Mon 06-06-16 15:48:33, Johannes Weiner wrote: > Currently, scan pressure between the anon and file LRU lists is > balanced based on a mixture of reclaim efficiency and a somewhat vague > notion of "value" of having certain pages in memory over others. That > concept of value is problematic, because it has caused us to count any > event that remotely makes one LRU list more or less preferrable for > reclaim, even when these events are not directly comparable to each > other and impose very different costs on the system - such as a > referenced file page that we still deactivate and a referenced > anonymous page that we actually rotate back to the head of the list. > > There is also conceptual overlap with the LRU algorithm itself. By > rotating recently used pages instead of reclaiming them, the algorithm > already biases the applied scan pressure based on page value. Thus, > when rebalancing scan pressure due to rotations, we should think of > reclaim cost, and leave assessing the page value to the LRU algorithm. > > Lastly, considering both value-increasing as well as value-decreasing > events can sometimes cause the same type of event to be counted twice, > i.e. how rotating a page increases the LRU value, while reclaiming it > succesfully decreases the value. In itself this will balance out fine, > but it quietly skews the impact of events that are only recorded once. > > The abstract metric of "value", the murky relationship with the LRU > algorithm, and accounting both negative and positive events make the > current pressure balancing model hard to reason about and modify. > > In preparation for thrashing-based LRU balancing, this patch switches > to a balancing model of accounting the concrete, actually observed > cost of reclaiming one LRU over another. For now, that cost includes > pages that are scanned but rotated back to the list head. This makes a lot of sense to me > Subsequent > patches will add consideration for IO caused by refaulting recently > evicted pages. The idea is to primarily scan the LRU that thrashes the > least, and secondarily scan the LRU that needs the least amount of > work to free memory. > > Rename struct zone_reclaim_stat to struct lru_cost, and move from two > separate value ratios for the LRU lists to a relative LRU cost metric > with a shared denominator. I just do not like the too generic `number'. I guess cost or price would fit better and look better in the code as well. Up you though... > Then make everything that affects the cost go through a new > lru_note_cost() function. Just curious, have you tried to measure just the effect of this change without the rest of the series? I do not expect it would show large differences because we are not doing SCAN_FRACT most of the time... > Signed-off-by: Johannes Weiner Acked-by: Michal Hocko Thanks! > --- > include/linux/mmzone.h | 23 +++ > include/linux/swap.h | 2 ++ > mm/swap.c | 15 +-- > mm/vmscan.c| 35 +++ > 4 files changed, 33 insertions(+), 42 deletions(-) > > diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h > index 02069c23486d..4d257d00fbf5 100644 > --- a/include/linux/mmzone.h > +++ b/include/linux/mmzone.h > @@ -191,22 +191,21 @@ static inline int is_active_lru(enum lru_list lru) > return (lru == LRU_ACTIVE_ANON || lru == LRU_ACTIVE_FILE); > } > > -struct zone_reclaim_stat { > - /* > - * The pageout code in vmscan.c keeps track of how many of the > - * mem/swap backed and file backed pages are referenced. > - * The higher the rotated/scanned ratio, the more valuable > - * that cache is. > - * > - * The anon LRU stats live in [0], file LRU stats in [1] > - */ > - unsigned long recent_rotated[2]; > - unsigned long recent_scanned[2]; > +/* > + * This tracks cost of reclaiming one LRU type - file or anon - over > + * the other. As the observed cost of pressure on one type increases, > + * the scan balance in vmscan.c tips toward the other type. > + * > + * The recorded cost for anon is in numer[0], file in numer[1]. > + */ > +struct lru_cost { > + unsigned long numer[2]; > + unsigned long denom; > }; > > struct lruvec { > struct list_headlists[NR_LRU_LISTS]; > - struct zone_reclaim_statreclaim_stat; > + struct lru_cost balance; > /* Evictions & activations on the inactive file list */ > atomic_long_t inactive_age; > #ifdef CONFIG_MEMCG > diff --git a/include/linux/swap.h b/include/linux/swap.h > index 178f084365c2..c461ce0533da 100644 > --- a/include/linux/swap.h > +++ b/include/linux/swap.h > @@ -295,6 +295,8 @@ extern unsigned long nr_free_pagecache_pages(void); > > > /* linux/mm/swap.c */ > +extern void lru_note_cost(struct lruvec *lruvec, bool file, > + unsigned int nr_pa
Re: linux-4.6/drivers/crypto/ux500/hash/hash_core.c: 2 * possible bad size ?
On Wed, May 18, 2016 at 9:46 AM, Herbert Xu wrote: > On Mon, May 16, 2016 at 07:13:12PM +0100, David Binderman wrote: >> Hello there, >> >> 1. >> >> linux-4.6/drivers/crypto/ux500/hash/hash_core.c:784]: (warning) Division by >> result of sizeof(). memmove() expects a size in bytes, did you intend to >> multiply instead? >> >> Source code is >> >> memmove(req_ctx->state.buffer, >> device_data->state.buffer, >> HASH_BLOCK_SIZE / sizeof(u32)); >> >> Maybe better code >> >> memmove(req_ctx->state.buffer, >> device_data->state.buffer, >> HASH_BLOCK_SIZE); Yeah obviously the latter as in hash_alg.h: struct hash_state { (...) u32buffer[HASH_BLOCK_SIZE / sizeof(u32)]; That could just as well be an u8 of HASH_BLOCK_SIZE. Sending a patch for this. >> linux-4.6/drivers/crypto/ux500/hash/hash_core.c:835]: (warning) Division by >> result of sizeof(). memmove() expects a size in bytes, did you intend to >> multiply instead? >> >> Duplicate. > > Thanks for noticing these bugs. This driver hasn't been maintained > since 2012, so unless someone steps up I'm going to just delete it. I'm trying to take a look at it because I'm using this platform for tests and it's nice to have all features enabled. And it has some problems (I added prints to also print successful tests): [3.864746] alg: hash: Test 1 SUCCEEDED for sha1-ux500 [3.870147] alg: hash: Test 2 SUCCEEDED for sha1-ux500 [3.875610] alg: hash: Test 3 SUCCEEDED for sha1-ux500 [3.881408] alg: hash: Test 4 SUCCEEDED for sha1-ux500 [3.886596] alg: hash: Chunking test 1 SUCCEEDED for sha1-ux500 [3.892639] alg: hash: Chunking test 2 FAILED for sha1-ux500 [3.898284] result: [3.900421] : 76 b4 ed 2f d7 11 1d c8 64 4c 38 b0 f8 27 19 89 [3.906860] 0010: 58 1e bb 3a [3.915588] expected: [3.917846] : 97 01 11 c4 e7 7b cc 88 cc 20 45 9c 02 b6 9b 4a [3.928314] 0010: a8 f5 82 17 [3.937255] alg: hash: Test 1 SUCCEEDED for sha256-ux500 [3.948089] alg: hash: Test 2 SUCCEEDED for sha256-ux500 [3.961944] alg: hash: Test 3 SUCCEEDED for sha256-ux500 [3.967590] alg: hash: Test 4 SUCCEEDED for sha256-ux500 [3.973083] alg: hash: Chunking test 1 SUCCEEDED for sha256-ux500 [3.979248] alt: hash: Failed to export() for sha256-ux500 [3.984802] hash: partial update failed on test 1 for sha256-ux500: ret=38 [3.992004] alg: hash: Test 1 SUCCEEDED for hmac-sha1-ux500 [3.997650] alg: hash: Test 2 SUCCEEDED for hmac-sha1-ux500 [4.003356] alg: hash: Test 3 SUCCEEDED for hmac-sha1-ux500 [4.009002] alg: hash: Test 4 SUCCEEDED for hmac-sha1-ux500 [4.014678] alg: hash: Test 5 SUCCEEDED for hmac-sha1-ux500 [4.020385] alg: hash: Test 6 SUCCEEDED for hmac-sha1-ux500 [4.026062] alg: hash: Chunking test 1 SUCCEEDED for hmac-sha1-ux500 [4.032470] alt: hash: Failed to export() for hmac-sha1-ux500 [4.038208] hash: partial update failed on test 1 for hmac-sha1-ux500: ret=38 [4.045623] alg: hash: Test 1 SUCCEEDED for hmac-sha256-ux500 [4.051483] alg: hash: Test 2 SUCCEEDED for hmac-sha256-ux500 [4.057342] alg: hash: Test 3 SUCCEEDED for hmac-sha256-ux500 [4.063201] alg: hash: Test 4 SUCCEEDED for hmac-sha256-ux500 [4.069030] alg: hash: Test 5 SUCCEEDED for hmac-sha256-ux500 [4.074890] alg: hash: Test 6 SUCCEEDED for hmac-sha256-ux500 [4.080780] alg: hash: Test 7 SUCCEEDED for hmac-sha256-ux500 [4.086608] alg: hash: Test 8 SUCCEEDED for hmac-sha256-ux500 [4.092468] alg: hash: Test 9 SUCCEEDED for hmac-sha256-ux500 [4.098297] alg: hash: Chunking test 1 SUCCEEDED for hmac-sha256-ux500 [4.104888] alt: hash: Failed to export() for hmac-sha256-ux500 [4.110809] hash: partial update failed on test 1 for hmac-sha256-ux500: ret=38 [4.118164] hash1 hash1: successfully registered [4.123687] alg: No test for aes (aes-ux500) [4.132354] alg: No test for des (des-ux500) [4.136749] alg: No test for des3_ede (des3_ede-ux500) [4.151306] alg: skcipher: Test 1 failed (invalid result) on encryption for cbc-des-ux500 [4.159484] : 03 91 6b cc 4a f6 3a 53 9c 4d 2e 2b 91 83 44 f6 [4.165954] 0010: aa 6a 15 6a dc b5 e0 3d [4.170501] cryp1 cryp1: successfully registered The simple tests always work, it's those stressful ones that create problems. Joakim: did you have a memory of this code working? Should I check the vendor tree for fixes? Yours, Linus Walleij
Re: [PATCH 1/2] x86/entry: Avoid interrupt flag save and restore
* Paolo Bonzini wrote: > > > On 08/06/2016 14:16, Ingo Molnar wrote: > > > The guest ones are not quite as consistent. I can fix that later, > > > there's no reason also to have guest context tracking split between > > > include/linux/context_tracking.h and include/linux/kvm_host.h. > > > > Could we please first do the cleanups before complicating the code and > > applying > > more substantial changes? > > The further cleanups wouldn't complicate the code. It's just that > guest_enter/guest_exit require IRQs off but don't have __. > > I'm thinking of something like this (untested): > > diff --git a/include/linux/context_tracking.h > b/include/linux/context_tracking.h > index d259274238db..c2dc581ddb0e 100644 > --- a/include/linux/context_tracking.h > +++ b/include/linux/context_tracking.h > @@ -84,7 +84,7 @@ static inline void context_tracking_init(void) { } > > > #ifdef CONFIG_VIRT_CPU_ACCOUNTING_GEN > -static inline void guest_enter(void) > +static inline void __guest_enter(void) > { > if (vtime_accounting_cpu_enabled()) > vtime_guest_enter(current); > @@ -93,9 +93,19 @@ static inline void guest_enter(void) > > if (context_tracking_is_enabled()) > __context_tracking_enter(CONTEXT_GUEST); > + > + /* KVM does not hold any references to rcu protected data when it > + * switches CPU into a guest mode. In fact switching to a guest mode Nit, please use the customary (multi-line) comment style: /* * Comment . * .. goes here. */ > + * is very similar to exiting to userspace from rcu point of view. In s/RCU > + * addition CPU may stay in a guest mode for quite a long time (up to > + * one time slice). Lets treat guest mode as quiescent state, just like > + * we do with user-mode execution. > + */ > + if (!context_tracking_cpu_is_enabled()) > + rcu_virt_note_context_switch(smp_processor_id()); > } > > -static inline void guest_exit(void) > +static inline void __guest_exit(void) > +static inline void guest_enter(void) > +{ > + unsigned long flags; > + > + local_irq_save(flags); > + __guest_enter(); > + local_irq_restore(flags); So I believe it would be cleaner to name the irqs-off code paths explicitly: __guest_enter_irqsoff(), and propagate that naming into other parts as well? > /* must be called with irqs disabled */ > static inline void __kvm_guest_exit(void) This way all these random comments about irqs-off requirements would become unnecessary - the code becomes self-documenting. Thanks, Ingo
Re: [PATCH -v2 00/33] implement atomic_fetch_$op
* Peter Zijlstra wrote: > On Thu, Jun 02, 2016 at 11:33:04AM +0200, Peter Zijlstra wrote: > > On Thu, Jun 02, 2016 at 09:27:36AM +, Vineet Gupta wrote: > > > > What's ur merge plan - are u going to rebase/respin once more so I can > > > push those > > > updates to Linus for 4.7-rc2. Or you could carry those ARC patches in ur > > > tree - > > > ahead of ur series. I'd much rather prefer the revert / cleanup before > > > adding new > > > code which extends the back off code only to be deleted later. > > > > I was hoping to get these into tip for v4.8, I can rebase on whatever > > changes you make in v4.7 no problem. > > -rc2 seems to have happened and I cannot seem to find changes to > arc/atomic.h, will you still be pushing those patches this window or > should I queue my patches? I'd much prefer to have all of these in the locking tree (i.e. tip:locking/core), to make it less painful all around. Thanks, Ingo
Re: [PATCH 08/10] mm: deactivations shouldn't bias the LRU balance
On Mon 06-06-16 15:48:34, Johannes Weiner wrote: > Operations like MADV_FREE, FADV_DONTNEED etc. currently move any > affected active pages to the inactive list to accelerate their reclaim > (good) but also steer page reclaim toward that LRU type, or away from > the other (bad). > > The reason why this is undesirable is that such operations are not > part of the regular page aging cycle, and rather a fluke that doesn't > say much about the remaining pages on that list. They might all be in > heavy use. But once the chunk of easy victims has been purged, the VM > continues to apply elevated pressure on the remaining hot pages. The > other LRU, meanwhile, might have easily reclaimable pages, and there > was never a need to steer away from it in the first place. > > As the previous patch outlined, we should focus on recording actually > observed cost to steer the balance rather than speculating about the > potential value of one LRU list over the other. In that spirit, leave > explicitely deactivated pages to the LRU algorithm to pick up, and let > rotations decide which list is the easiest to reclaim. > > Signed-off-by: Johannes Weiner Acked-by: Michal Hocko > --- > mm/swap.c | 3 --- > 1 file changed, 3 deletions(-) > > diff --git a/mm/swap.c b/mm/swap.c > index 645d21242324..ae07b469ddca 100644 > --- a/mm/swap.c > +++ b/mm/swap.c > @@ -538,7 +538,6 @@ static void lru_deactivate_file_fn(struct page *page, > struct lruvec *lruvec, > > if (active) > __count_vm_event(PGDEACTIVATE); > - lru_note_cost(lruvec, !file, hpage_nr_pages(page)); > } > > > @@ -546,7 +545,6 @@ static void lru_deactivate_fn(struct page *page, struct > lruvec *lruvec, > void *arg) > { > if (PageLRU(page) && PageActive(page) && !PageUnevictable(page)) { > - int file = page_is_file_cache(page); > int lru = page_lru_base_type(page); > > del_page_from_lru_list(page, lruvec, lru + LRU_ACTIVE); > @@ -555,7 +553,6 @@ static void lru_deactivate_fn(struct page *page, struct > lruvec *lruvec, > add_page_to_lru_list(page, lruvec, lru); > > __count_vm_event(PGDEACTIVATE); > - lru_note_cost(lruvec, !file, hpage_nr_pages(page)); > } > } > > -- > 2.8.3 -- Michal Hocko SUSE Labs
Re: [PATCH v3 1/6] watchdog: add set_pretimeout interface
Hi Wolfram, On 08.06.2016 09:34, Wolfram Sang wrote: > On Tue, Jun 07, 2016 at 08:38:42PM +0300, Vladimir Zapolskiy wrote: >> From: Robin Gong >> >> Add set_pretimeout since our watchdog driver has those interfaces and >> obviously, the new common watchdog framework didn't implement this >> interface. >> >> Signed-off-by: Robin Gong >> [vzapolskiy: rebased, added an inline comment to describe new interface] >> Signed-off-by: Vladimir Zapolskiy > > Why didn't you just take my patch and worked on it? This would have > added the documentation Guenter explicitly requested when reviewing > Robin's patch. And it would have get rid of the bug you have in the > *_invalid function. I also don't think the split-up into three patches > is necessary here, but that might just be me. > I agree, your version is obviously more advanced, I will take it for v4. Best wishes, Vladimir
Re: [RFC][PATCH 3/5] PM core: Make async suspend/resume of devices use device links
On Thu, Jan 14, 2016 at 02:55:25AM +0100, Rafael J. Wysocki wrote: > From: Rafael J. Wysocki > > Make the device suspend/resume part of the core system > suspend/resume code use device links to ensure that supplier > and consumer devices will be suspended and resumed in the right > order in case of async suspend/resume. > > The idea, roughly, is to use dpm_wait() to wait for all consumers > before a supplier device suspend and to wait for all suppliers > before a consumer device resume. Same question with parents using their child - I'm thinking that perhaps we can arrange for the struct device of the parent to get used and ignore the child device outside of the MFD. signature.asc Description: PGP signature
Re: [PATCHv9 2/2] selftest/x86: add mremap vdso test
On 05/21/2016 11:27 PM, Ingo Molnar wrote: Will look at applying this after the merge window. Ping? Thanks, Dmitry Safonov
[PATCH v2 04/15] mtd: nand: rename nand_get_flash_type() into nand_detect()
The only caller of nand_get_flash_type() (nand_scan_ident()) actually don't use the returned nand_flash_dev pointer except for converting it to to an error code. Rename this function nand_detect() and make it return an integer. Signed-off-by: Boris Brezillon --- drivers/mtd/nand/nand_base.c | 19 --- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index 1e865c0..95e9a8e 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -3811,8 +3811,7 @@ static bool find_full_id_nand(struct nand_chip *chip, /* * Get the flash and manufacturer id and lookup if the type is supported. */ -static struct nand_flash_dev *nand_get_flash_type(struct nand_chip *chip, - struct nand_flash_dev *type) +static int nand_detect(struct nand_chip *chip, struct nand_flash_dev *type) { struct mtd_info *mtd = nand_to_mtd(chip); int busw; @@ -3852,7 +3851,7 @@ static struct nand_flash_dev *nand_get_flash_type(struct nand_chip *chip, if (id_data[0] != maf_id || id_data[1] != dev_id) { pr_info("second ID read did not match %02x,%02x against %02x,%02x\n", maf_id, dev_id, id_data[0], id_data[1]); - return ERR_PTR(-ENODEV); + return -ENODEV; } chip->id.len = nand_id_len(id_data, 8); @@ -3896,7 +3895,7 @@ static struct nand_flash_dev *nand_get_flash_type(struct nand_chip *chip, } if (!type->name) - return ERR_PTR(-ENODEV); + return -ENODEV; if (!mtd->name) mtd->name = type->name; @@ -3939,7 +3938,7 @@ ident_done: pr_info("%s %s\n", nand_manuf_ids[maf_idx].name, mtd->name); pr_warn("bus width %d instead %d bit\n", busw ? 16 : 8, (chip->options & NAND_BUSWIDTH_16) ? 16 : 8); - return ERR_PTR(-EINVAL); + return -EINVAL; } nand_decode_bbm_options(chip); @@ -3981,7 +3980,7 @@ ident_done: pr_info("%d MiB, %s, erase size: %d KiB, page size: %d, OOB size: %d\n", (int)(chip->chipsize >> 20), nand_is_slc(chip) ? "SLC" : "MLC", mtd->erasesize >> 10, mtd->writesize, mtd->oobsize); - return type; + return 0; } static const char * const nand_ecc_modes[] = { @@ -4139,7 +4138,6 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips, { int i, nand_maf_id, nand_dev_id; struct nand_chip *chip = mtd_to_nand(mtd); - struct nand_flash_dev *type; int ret; ret = nand_dt_init(chip); @@ -4153,13 +4151,12 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips, nand_set_defaults(chip); /* Read the flash type */ - type = nand_get_flash_type(chip, table); - - if (IS_ERR(type)) { + ret = nand_detect(chip, table); + if (ret) { if (!(chip->options & NAND_SCAN_SILENT_NODEV)) pr_warn("No NAND device found\n"); chip->select_chip(mtd, -1); - return PTR_ERR(type); + return ret; } nand_maf_id = chip->id.data[0]; -- 2.7.4
[PATCH v2 13/15] mtd: nand: samsung: retrieve ECC requirements from extended ID
From: Hans de Goede On some nand controllers with hw-ecc the controller code wants to know the ecc strength and size and having these as 0, 0 is not accepted. Specifying these in devicetree is possible but undesirable as the nand may be different in different production runs of the same board, so it is better to get this info from the nand id where possible. This commit adds code to read the ecc strength and size from the nand for Samsung extended-id nands. This code is based on the info for the 5th id byte in the datasheets for the following Samsung nands: K9GAG08U0E, K9GAG08U0F, K9GAG08X0D, K9GBG08U0A, K9GBG08U0B. These all use these bits in the exact same way. Signed-off-by: Hans de Goede Signed-off-by: Boris Brezillon --- drivers/mtd/nand/nand_samsung.c | 20 1 file changed, 20 insertions(+) diff --git a/drivers/mtd/nand/nand_samsung.c b/drivers/mtd/nand/nand_samsung.c index 863be01..5d973d4 100644 --- a/drivers/mtd/nand/nand_samsung.c +++ b/drivers/mtd/nand/nand_samsung.c @@ -63,6 +63,26 @@ static void samsung_nand_decode_id(struct nand_chip *chip) extid >>= 2; mtd->erasesize = (128 * 1024) << (((extid >> 1) & 0x04) | (extid & 0x03)); + + /* Extract ECC requirements from 5th id byte*/ + extid = (chip->id.data[4] >> 4) & 0x07; + if (extid < 5) { + chip->ecc_step_ds = 512; + chip->ecc_strength_ds = 1 << extid; + } else { + chip->ecc_step_ds = 1024; + switch (extid) { + case 5: + chip->ecc_strength_ds = 24; + break; + case 6: + chip->ecc_strength_ds = 40; + break; + case 7: + chip->ecc_strength_ds = 60; + break; + } + } } else { nand_decode_ext_id(chip); } -- 2.7.4
[PATCH v2 00/15] mtd: nand: allow vendor specific detection/initialization
Hello, This patch series is a step forward in supporting vendor-specific functionalities. This series is mainly moving vendor-specific initialization or detection code out of the core, but also introduces an infrastructure allowing support for vendor-specific features. While those features might seem useless to most users, some of them are actually required on modern MLC/TLC NANDs (this is the case of read-retry support, which AFAICT has not been standardized by the JEDEC consortium). Now, let's detail what's inside this patch-set. Patches 1 to 4 are simple reworks simplifying auto-detection function prototypes, and clarifying their purpose. Patch 5 is introducing the vendor-specific initialization infrastructure. Patch 6 is removing the MTD_NAND_IDS Kconfig option to avoid creating a nand_ids.ko module when MTD_NAND is enabled as a module. This prevents a future cross-dependency between nand.ko where all vendor specific code will rely and nand_ids.ko which will reference vendor-specific ops in its manufacturer table, which in turn is referenced by the core code linked in nand.ko. Patches 7 to 12 are moving vendor-specific code into their respective nand_.c files. Patch 13 is taking a patch proposed by Hans and adding support for ECC requirements extraction from the samsung extended IDs. It seems to apply to all Samsung MLCs, but even if it's not the case, the detection code should be improved to support the new formats. Patch 14 is adding support for advanced NAND ID decoding to the Hynix driver (OOB size, ECC and scrambling requirements extraction). Again this detection code might be incomplete, but I'd like people to extend it if required rather than adding new full-id entries in the nand_ids table. And finally, patch 15 is showing how useful this vendor-specific stuff can be by implementing read-retry support for Hynix 1x nm MLCs. And trust me, you don't want to try using such a NAND without read-retry support ;). As always, I'm open to any suggestion to improve this vendor-specific infrastructure, so please review the code :). Thanks, Boris Changes since v1: - split detection and initialization steps to avoid keeping information retrieved by nand_decode_ext_id() if it's not appropriate (Aleksei reported a bug where NAND_BUSWIDTH_16 was set by nand_decode_ext_id() and not cleared by the samsung ->init() function). The new approach is to call ->detect() if it's provided and fallback to nand_decode_ext_id() if it's not. ->detect() implementation should can call nand_decode_ext_id() if needed. Boris Brezillon (14): mtd: nand: get rid of the mtd parameter in all auto-detection functions mtd: nand: store nand ID in struct nand_chip mtd: nand: get rid of busw parameter mtd: nand: rename nand_get_flash_type() into nand_detect() mtd: nand: add manufacturer specific initialization/detection steps mtd: nand: kill the MTD_NAND_IDS Kconfig option mtd: nand: move Samsung specific init/detection logic in nand_samsung.c mtd: nand: move Hynix specific init/detection logic in nand_hynix.c mtd: nand: move Toshiba specific init/detection logic in nand_toshiba.c mtd: nand: move Micron specific init logic in nand_micron.c mtd: nand: move AMD/Spansion specific init/detection logic in nand_amd.c mtd: nand: move Macronix specific initialization in nand_macronix.c mtd: nand: hynix: rework NAND ID decoding to extract more information mtd: nand: hynix: add read-retry support for 1x nm MLC NANDs Hans de Goede (1): mtd: nand: samsung: retrieve ECC requirements from extended ID arch/cris/arch-v32/drivers/Kconfig | 1 - drivers/mtd/nand/Kconfig | 4 - drivers/mtd/nand/Makefile | 9 +- drivers/mtd/nand/nand_amd.c| 48 +++ drivers/mtd/nand/nand_base.c | 372 +++--- drivers/mtd/nand/nand_hynix.c | 629 + drivers/mtd/nand/nand_ids.c| 21 +- drivers/mtd/nand/nand_macronix.c | 27 ++ drivers/mtd/nand/nand_micron.c | 84 + drivers/mtd/nand/nand_samsung.c| 109 +++ drivers/mtd/nand/nand_toshiba.c| 48 +++ include/linux/mtd/nand.h | 69 ++-- 12 files changed, 1132 insertions(+), 289 deletions(-) create mode 100644 drivers/mtd/nand/nand_amd.c create mode 100644 drivers/mtd/nand/nand_hynix.c create mode 100644 drivers/mtd/nand/nand_macronix.c create mode 100644 drivers/mtd/nand/nand_micron.c create mode 100644 drivers/mtd/nand/nand_samsung.c create mode 100644 drivers/mtd/nand/nand_toshiba.c -- 2.7.4
[PATCH v2 05/15] mtd: nand: add manufacturer specific initialization/detection steps
A lot of NANDs are implementing generic features in a non-generic way, or are providing advanced auto-detection logic where the NAND ID bytes meaning changes with the NAND generation. Providing this vendor specific initialization step will allow us to get rid of the full ids in the nand_ids table or all the vendor specific cases added over the time in the generic NAND ID decoding logic. Signed-off-by: Boris Brezillon --- drivers/mtd/nand/nand_base.c | 42 -- include/linux/mtd/nand.h | 36 2 files changed, 68 insertions(+), 10 deletions(-) diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index 95e9a8e..0a7d1c6 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -3580,7 +3580,7 @@ static int nand_get_bits_per_cell(u8 cellinfo) * chip. The rest of the parameters must be decoded according to generic or * manufacturer-specific "extended ID" decoding patterns. */ -static void nand_decode_ext_id(struct nand_chip *chip) +void nand_decode_ext_id(struct nand_chip *chip) { struct mtd_info *mtd = nand_to_mtd(chip); int extid, id_len = chip->id.len; @@ -3705,6 +3705,7 @@ static void nand_decode_ext_id(struct nand_chip *chip) } } +EXPORT_SYMBOL_GPL(nand_decode_ext_id); /* * Old devices have chip data hardcoded in the device ID table. nand_decode_id @@ -3815,7 +3816,7 @@ static int nand_detect(struct nand_chip *chip, struct nand_flash_dev *type) { struct mtd_info *mtd = nand_to_mtd(chip); int busw; - int i, maf_idx; + int i, maf_idx, ret; u8 *id_data = chip->id.data; u8 maf_id, dev_id; @@ -3856,6 +3857,14 @@ static int nand_detect(struct nand_chip *chip, struct nand_flash_dev *type) chip->id.len = nand_id_len(id_data, 8); + /* Try to identify manufacturer */ + for (maf_idx = 0; nand_manuf_ids[maf_idx].id != 0x0; maf_idx++) { + if (nand_manuf_ids[maf_idx].id == maf_id) + break; + } + + chip->manufacturer.ops = nand_manuf_ids[maf_idx].ops; + if (!type) type = nand_flash_ids; @@ -3903,8 +3912,14 @@ static int nand_detect(struct nand_chip *chip, struct nand_flash_dev *type) chip->chipsize = (uint64_t)type->chipsize << 20; if (!type->pagesize) { - /* Decode parameters from extended ID */ - nand_decode_ext_id(chip); + /* +* Try manufacturer detection if available and use +* nand_decode_ext_id() otherwise. +*/ + if (chip->manufacturer.ops->detect) + chip->manufacturer.ops->detect(chip); + else + nand_decode_ext_id(chip); } else { nand_decode_id(chip, type); } @@ -3919,12 +3934,6 @@ static int nand_detect(struct nand_chip *chip, struct nand_flash_dev *type) chip->options &= ~NAND_SAMSUNG_LP_OPTIONS; ident_done: - /* Try to identify manufacturer */ - for (maf_idx = 0; nand_manuf_ids[maf_idx].id != 0x0; maf_idx++) { - if (nand_manuf_ids[maf_idx].id == maf_id) - break; - } - if (chip->options & NAND_BUSWIDTH_AUTO) { WARN_ON(busw & NAND_BUSWIDTH_16); nand_set_defaults(chip); @@ -3964,6 +3973,15 @@ ident_done: if (mtd->writesize > 512 && chip->cmdfunc == nand_command) chip->cmdfunc = nand_command_lp; + /* +* Manufacturer specific initialization. +*/ + if (chip->manufacturer.ops && chip->manufacturer.ops->init) { + ret = chip->manufacturer.ops->init(chip); + if (ret) + return ret; + } + pr_info("device found, Manufacturer ID: 0x%02x, Chip ID: 0x%02x\n", maf_id, dev_id); @@ -4623,6 +4641,10 @@ void nand_release(struct mtd_info *mtd) if (chip->badblock_pattern && chip->badblock_pattern->options & NAND_BBT_DYNAMICSTRUCT) kfree(chip->badblock_pattern); + + /* Release manufacturer private data */ + if (chip->manufacturer.ops && chip->manufacturer.ops->cleanup) + chip->manufacturer.ops->cleanup(chip); } EXPORT_SYMBOL_GPL(nand_release); diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h index 3072f5e..c0a1e36 100644 --- a/include/linux/mtd/nand.h +++ b/include/linux/mtd/nand.h @@ -577,6 +577,20 @@ struct nand_buffers { }; /** + * 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 speci
[PATCH v2 02/15] mtd: nand: store nand ID in struct nand_chip
Store the NAND ID in struct nand_chip to avoid passing id_data and id_len as function parameters. Signed-off-by: Boris Brezillon --- drivers/mtd/nand/nand_base.c | 55 include/linux/mtd/nand.h | 13 +++ 2 files changed, 43 insertions(+), 25 deletions(-) diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index c0d8c43..4959263 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -3582,18 +3582,16 @@ static int nand_get_bits_per_cell(u8 cellinfo) * chip. The rest of the parameters must be decoded according to generic or * manufacturer-specific "extended ID" decoding patterns. */ -static void nand_decode_ext_id(struct nand_chip *chip, u8 id_data[8], - int *busw) +static void nand_decode_ext_id(struct nand_chip *chip, int *busw) { struct mtd_info *mtd = nand_to_mtd(chip); - int extid, id_len; + int extid, id_len = chip->id.len; + u8 *id_data = chip->id.data; /* The 3rd id byte holds MLC / multichip data */ chip->bits_per_cell = nand_get_bits_per_cell(id_data[2]); /* The 4th id byte is the important one */ extid = id_data[3]; - id_len = nand_id_len(id_data, 8); - /* * Field definitions are in the following datasheets: * Old style (4,5 byte ID): Samsung K9GAG08U0M (p.32) @@ -3717,9 +3715,10 @@ static void nand_decode_ext_id(struct nand_chip *chip, u8 id_data[8], * the chip. */ static void nand_decode_id(struct nand_chip *chip, struct nand_flash_dev *type, - u8 id_data[8], int *busw) + int *busw) { struct mtd_info *mtd = nand_to_mtd(chip); + u8 *id_data = chip->id.data; int maf_id = id_data[0]; mtd->erasesize = type->erasesize; @@ -3749,9 +3748,10 @@ static void nand_decode_id(struct nand_chip *chip, struct nand_flash_dev *type, * heuristic patterns using various detected parameters (e.g., manufacturer, * page size, cell-type information). */ -static void nand_decode_bbm_options(struct nand_chip *chip, u8 id_data[8]) +static void nand_decode_bbm_options(struct nand_chip *chip) { struct mtd_info *mtd = nand_to_mtd(chip); + u8 *id_data = chip->id.data; int maf_id = id_data[0]; /* Set the bad block position */ @@ -3787,10 +3787,10 @@ static inline bool is_full_id_nand(struct nand_flash_dev *type) } static bool find_full_id_nand(struct nand_chip *chip, - struct nand_flash_dev *type, u8 *id_data, - int *busw) + struct nand_flash_dev *type, int *busw) { struct mtd_info *mtd = nand_to_mtd(chip); + u8 *id_data = chip->id.data; if (!strncmp(type->id, id_data, type->id_len)) { mtd->writesize = type->pagesize; @@ -3819,13 +3819,13 @@ static bool find_full_id_nand(struct nand_chip *chip, * Get the flash and manufacturer id and lookup if the type is supported. */ static struct nand_flash_dev *nand_get_flash_type(struct nand_chip *chip, - int *maf_id, int *dev_id, struct nand_flash_dev *type) { struct mtd_info *mtd = nand_to_mtd(chip); int busw; int i, maf_idx; - u8 id_data[8]; + u8 *id_data = chip->id.data; + u8 maf_id, dev_id; /* Select the device */ chip->select_chip(mtd, 0); @@ -3840,8 +3840,8 @@ static struct nand_flash_dev *nand_get_flash_type(struct nand_chip *chip, chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1); /* Read manufacturer and device IDs */ - *maf_id = chip->read_byte(mtd); - *dev_id = chip->read_byte(mtd); + maf_id = chip->read_byte(mtd); + dev_id = chip->read_byte(mtd); /* * Try again to make sure, as some systems the bus-hold or other @@ -3856,20 +3856,22 @@ static struct nand_flash_dev *nand_get_flash_type(struct nand_chip *chip, for (i = 0; i < 8; i++) id_data[i] = chip->read_byte(mtd); - if (id_data[0] != *maf_id || id_data[1] != *dev_id) { + if (id_data[0] != maf_id || id_data[1] != dev_id) { pr_info("second ID read did not match %02x,%02x against %02x,%02x\n", - *maf_id, *dev_id, id_data[0], id_data[1]); + maf_id, dev_id, id_data[0], id_data[1]); return ERR_PTR(-ENODEV); } + chip->id.len = nand_id_len(id_data, 8); + if (!type) type = nand_flash_ids; for (; type->name != NULL; type++) { if (is_full_id_nand(type)) { - if (find_full_id_nand(chip, type, id_data, &busw)) + if (find_full_id_nand(chip, type, &busw)) goto ident_done; -
[PATCH v2 01/15] mtd: nand: get rid of the mtd parameter in all auto-detection functions
Now that struct nand_chip embeds an mtd_info object we can get rid of the mtd parameter and extract it from the chip parameter with the nand_to_mtd() helper. Signed-off-by: Boris Brezillon --- drivers/mtd/nand/nand_base.c | 56 1 file changed, 30 insertions(+), 26 deletions(-) diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index 7bc37b4..c0d8c43 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -3228,9 +3228,10 @@ static u16 onfi_crc16(u16 crc, u8 const *p, size_t len) } /* Parse the Extended Parameter Page. */ -static int nand_flash_detect_ext_param_page(struct mtd_info *mtd, - struct nand_chip *chip, struct nand_onfi_params *p) +static int nand_flash_detect_ext_param_page(struct nand_chip *chip, + struct nand_onfi_params *p) { + struct mtd_info *mtd = nand_to_mtd(chip); struct onfi_ext_param_page *ep; struct onfi_ext_section *s; struct onfi_ext_ecc_info *ecc; @@ -3325,9 +3326,9 @@ static void nand_onfi_detect_micron(struct nand_chip *chip, /* * Check if the NAND chip is ONFI compliant, returns 1 if it is, 0 otherwise. */ -static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip, - int *busw) +static int nand_flash_detect_onfi(struct nand_chip *chip, int *busw) { + struct mtd_info *mtd = nand_to_mtd(chip); struct nand_onfi_params *p = &chip->onfi_params; int i, j; int val; @@ -3414,7 +3415,7 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip, chip->cmdfunc = nand_command_lp; /* The Extended Parameter Page is supported since ONFI 2.1. */ - if (nand_flash_detect_ext_param_page(mtd, chip, p)) + 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"); @@ -3429,9 +3430,9 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip, /* * Check if the NAND chip is JEDEC compliant, returns 1 if it is, 0 otherwise. */ -static int nand_flash_detect_jedec(struct mtd_info *mtd, struct nand_chip *chip, - int *busw) +static int nand_flash_detect_jedec(struct nand_chip *chip, int *busw) { + struct mtd_info *mtd = nand_to_mtd(chip); struct nand_jedec_params *p = &chip->jedec_params; struct jedec_ecc_info *ecc; int val; @@ -3581,9 +3582,10 @@ static int nand_get_bits_per_cell(u8 cellinfo) * chip. The rest of the parameters must be decoded according to generic or * manufacturer-specific "extended ID" decoding patterns. */ -static void nand_decode_ext_id(struct mtd_info *mtd, struct nand_chip *chip, - u8 id_data[8], int *busw) +static void nand_decode_ext_id(struct nand_chip *chip, u8 id_data[8], + int *busw) { + struct mtd_info *mtd = nand_to_mtd(chip); int extid, id_len; /* The 3rd id byte holds MLC / multichip data */ chip->bits_per_cell = nand_get_bits_per_cell(id_data[2]); @@ -3714,10 +3716,10 @@ static void nand_decode_ext_id(struct mtd_info *mtd, struct nand_chip *chip, * decodes a matching ID table entry and assigns the MTD size parameters for * the chip. */ -static void nand_decode_id(struct mtd_info *mtd, struct nand_chip *chip, - struct nand_flash_dev *type, u8 id_data[8], - int *busw) +static void nand_decode_id(struct nand_chip *chip, struct nand_flash_dev *type, + u8 id_data[8], int *busw) { + struct mtd_info *mtd = nand_to_mtd(chip); int maf_id = id_data[0]; mtd->erasesize = type->erasesize; @@ -3747,9 +3749,9 @@ static void nand_decode_id(struct mtd_info *mtd, struct nand_chip *chip, * heuristic patterns using various detected parameters (e.g., manufacturer, * page size, cell-type information). */ -static void nand_decode_bbm_options(struct mtd_info *mtd, - struct nand_chip *chip, u8 id_data[8]) +static void nand_decode_bbm_options(struct nand_chip *chip, u8 id_data[8]) { + struct mtd_info *mtd = nand_to_mtd(chip); int maf_id = id_data[0]; /* Set the bad block position */ @@ -3784,9 +3786,12 @@ static inline bool is_full_id_nand(struct nand_flash_dev *type) return type->id_len; } -static bool find_full_id_nand(struct mtd_info *mtd, struct nand_chip *chip, - struct nand_flash_dev *type, u8 *id_data, int *busw) +static bool find_full_id_nand(struct nand_chip *chip, + struct nand_flash_dev *type, u8 *id_data, + int *
[PATCH v2 08/15] mtd: nand: move Hynix specific init/detection logic in nand_hynix.c
Move Hynix specific initialization and detection logic into nand_hynix.c. This is part of the "separate vendor specific code from core" cleanup process. Signed-off-by: Boris Brezillon --- drivers/mtd/nand/Makefile | 1 + drivers/mtd/nand/nand_base.c | 108 ++ drivers/mtd/nand/nand_hynix.c | 81 +++ drivers/mtd/nand/nand_ids.c | 3 +- 4 files changed, 110 insertions(+), 83 deletions(-) create mode 100644 drivers/mtd/nand/nand_hynix.c diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile index 55a55d3..d79338f 100644 --- a/drivers/mtd/nand/Makefile +++ b/drivers/mtd/nand/Makefile @@ -58,4 +58,5 @@ obj-$(CONFIG_MTD_NAND_BRCMNAND) += brcmnand/ obj-$(CONFIG_MTD_NAND_QCOM)+= qcom_nandc.o nand-objs := nand_base.o nand_bbt.o nand_timings.o nand_ids.o +nand-objs += nand_hynix.o nand-objs += nand_samsung.o diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index a7c7ef3..69812fd 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -3590,85 +3590,32 @@ void nand_decode_ext_id(struct nand_chip *chip) /* The 4th id byte is the important one */ extid = id_data[3]; + /* Calc pagesize */ + mtd->writesize = 1024 << (extid & 0x03); + extid >>= 2; + /* Calc oobsize */ + mtd->oobsize = (8 << (extid & 0x01)) * (mtd->writesize >> 9); + extid >>= 2; + /* Calc blocksize. Blocksize is multiples of 64KiB */ + mtd->erasesize = (64 * 1024) << (extid & 0x03); + extid >>= 2; + /* Get buswidth information */ + if (extid & 0x1) + chip->options |= NAND_BUSWIDTH_16; + /* -* Field definitions are in the following datasheets: -* Old style (4,5 byte ID): Samsung K9GAG08U0M (p.32) -* Hynix MLC (6 byte ID): Hynix H27UBG8T2B (p.22) -* -* Check for ID length, non-zero 6th byte, cell type, and Hynix/Samsung -* ID to decide what to do. +* Toshiba 24nm raw SLC (i.e., not BENAND) have 32B OOB per +* 512B page. For Toshiba SLC, we decode the 5th/6th byte as +* follows: +* - ID byte 6, bits[2:0]: 100b -> 43nm, 101b -> 32nm, +* 110b -> 24nm +* - ID byte 5, bit[7]:1 -> BENAND, 0 -> raw SLC */ - if (id_len == 6 && id_data[0] == NAND_MFR_HYNIX && - !nand_is_slc(chip)) { - unsigned int tmp; - - /* Calc pagesize */ - mtd->writesize = 2048 << (extid & 0x03); - extid >>= 2; - /* Calc oobsize */ - switch (((extid >> 2) & 0x04) | (extid & 0x03)) { - case 0: - mtd->oobsize = 128; - break; - case 1: - mtd->oobsize = 224; - break; - case 2: - mtd->oobsize = 448; - break; - case 3: - mtd->oobsize = 64; - break; - case 4: - mtd->oobsize = 32; - break; - case 5: - mtd->oobsize = 16; - break; - default: - mtd->oobsize = 640; - break; - } - extid >>= 2; - /* Calc blocksize */ - tmp = ((extid >> 1) & 0x04) | (extid & 0x03); - if (tmp < 0x03) - mtd->erasesize = (128 * 1024) << tmp; - else if (tmp == 0x03) - mtd->erasesize = 768 * 1024; - else - mtd->erasesize = (64 * 1024) << tmp; - } else { - /* Calc pagesize */ - mtd->writesize = 1024 << (extid & 0x03); - extid >>= 2; - /* Calc oobsize */ - mtd->oobsize = (8 << (extid & 0x01)) * - (mtd->writesize >> 9); - extid >>= 2; - /* Calc blocksize. Blocksize is multiples of 64KiB */ - mtd->erasesize = (64 * 1024) << (extid & 0x03); - extid >>= 2; - /* Get buswidth information */ - if (extid & 0x1) - chip->options |= NAND_BUSWIDTH_16; - - /* -* Toshiba 24nm raw SLC (i.e., not BENAND) have 32B OOB per -* 512B page. For Toshiba SLC, we decode the 5th/6th byte as -* follows: -* - ID byte 6, bits[2:0]: 100b -> 43nm, 101b -> 32nm, -* 110b -> 24nm -* - ID byte 5, bit[7]:1 -> BENAND, 0 -> raw SLC -*/ - if (id_len >= 6 && id_data[0] == NAND_MFR_TOSHIBA && - nand_is_slc(chip) &
[PATCH v2 15/15] mtd: nand: hynix: add read-retry support for 1x nm MLC NANDs
All Hynix MLC NANDs using the produced with the 1X nm process support read-retry. This read retry implementation should also be reusable for other Hynix NANDs, but the method to retrieve the read-retry parameters from the read-retry OTP area might change a bit (some NANDs are even using a fixed set of values instead of retrieving those information from the OTP area). Signed-off-by: Boris Brezillon --- drivers/mtd/nand/nand_hynix.c | 361 +- 1 file changed, 360 insertions(+), 1 deletion(-) diff --git a/drivers/mtd/nand/nand_hynix.c b/drivers/mtd/nand/nand_hynix.c index f73b99f..7f5b446 100644 --- a/drivers/mtd/nand/nand_hynix.c +++ b/drivers/mtd/nand/nand_hynix.c @@ -13,6 +13,53 @@ */ #include +#include + +#define NAND_HYNIX_CMD_SET_PARAMS 0x36 +#define NAND_HYNIX_CMD_APPLY_PARAMS0x16 + +#define NAND_HYNIX_1XNM_RR_REPEAT 8 + +/** + * struct hynix_read_retry - read-retry data + * @nregs: number of register to set when applying a new read-retry mode + * @regs: register offsets (NAND chip dependent) + * @values: array of values to set in registers. The array size is equal to + * (nregs * nmodes) + */ +struct hynix_read_retry { + int nregs; + const u8 *regs; + u8 values[0]; +}; + +/** + * struct hynix_nand - private Hynix NAND struct + * @nand_technology: manufacturing process expressed in picometer + * @read_retry: read-retry information + */ +struct hynix_nand { + const struct hynix_read_retry *read_retry; +}; + +/** + * struct hynix_read_retry_otp - structure describing how the read-retry OTP + * area + * @nregs: number of hynix private registers to set before reading the reading + *the OTP area + * @regs: registers that should be configured + * @values: values that should be set in regs + * @page: the address to pass to the READ_PAGE command. Depends on the NAND + * chip + * @size: size of the read-retry OTP section + */ +struct hynix_read_retry_otp { + int nregs; + const u8 *regs; + const u8 *values; + int page; + int size; +}; static bool hynix_nand_has_valid_jedecid(struct nand_chip *chip) { @@ -27,6 +74,292 @@ static bool hynix_nand_has_valid_jedecid(struct nand_chip *chip) return !strcmp("JEDEC", jedecid); } +static int hynix_nand_setup_read_retry(struct mtd_info *mtd, int retry_mode) +{ + struct nand_chip *chip = mtd_to_nand(mtd); + struct hynix_nand *hynix = nand_get_manufacturer_data(chip); + const u8 *values; + int status; + int i; + + values = hynix->read_retry->values + +(retry_mode * hynix->read_retry->nregs); + + /* Enter 'Set Hynix Parameters' mode */ + chip->cmdfunc(mtd, NAND_HYNIX_CMD_SET_PARAMS, -1, -1); + + /* +* Configure the NAND in the requested read-retry mode. +* This is done by setting pre-defined values in internal NAND +* registers. +* +* The set of registers is NAND specific, and the values are either +* predefined or extracted from an OTP area on the NAND (values are +* probably tweaked at production in this case). +*/ + for (i = 0; i < hynix->read_retry->nregs; i++) { + int column = hynix->read_retry->regs[i]; + + column |= column << 8; + chip->cmdfunc(mtd, NAND_CMD_NONE, column, -1); + chip->write_byte(mtd, values[i]); + } + + /* Apply the new settings. */ + chip->cmdfunc(mtd, NAND_HYNIX_CMD_APPLY_PARAMS, -1, -1); + + status = chip->waitfunc(mtd, chip); + if (status & NAND_STATUS_FAIL) + return -EIO; + + return 0; +} + +/** + * hynix_get_majority - get the value that is occurring the most in a given + * set of values + * @in: the array of values to test + * @repeat: the size of the in array + * @out: pointer used to store the output value + * + * This function implements the 'majority check' logic that is supposed to + * overcome the unreliability of MLC NANDs when reading the OTP area storing + * the read-retry parameters. + * + * It's based on a pretty simple assumption: if we repeat the same value + * several times and then take the one that is occurring the most, we should + * find the correct value. + * Let's hope this dummy algorithm prevents us from losing the read-retry + * parameters. + */ +static int hynix_get_majority(const u8 *in, int repeat, u8 *out) +{ + int i, j, half = repeat / 2; + + /* +* We only test the first half of the in array because we must ensure +* that the value is at least occurring repeat / 2 times. +* +* This loop is suboptimal since we may count the occurrences of the +* same value several time, but we are doing that on small sets, which +* makes it acceptable. +*/ + for (i = 0; i < half; i++) { + int cnt = 0; +
[PATCH v2 12/15] mtd: nand: move Macronix specific initialization in nand_macronix.c
Move Macronix specific initialization into nand_macronix.c. This is part of the "separate vendor specific code from core" cleanup process. Signed-off-by: Boris Brezillon --- drivers/mtd/nand/Makefile| 1 + drivers/mtd/nand/nand_base.c | 11 --- drivers/mtd/nand/nand_ids.c | 3 ++- drivers/mtd/nand/nand_macronix.c | 27 +++ 4 files changed, 30 insertions(+), 12 deletions(-) create mode 100644 drivers/mtd/nand/nand_macronix.c diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile index 19d0cb8..19150d3 100644 --- a/drivers/mtd/nand/Makefile +++ b/drivers/mtd/nand/Makefile @@ -60,6 +60,7 @@ obj-$(CONFIG_MTD_NAND_QCOM) += qcom_nandc.o nand-objs := nand_base.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 nand-objs += nand_micron.o nand-objs += nand_samsung.o nand-objs += nand_toshiba.o diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index 5fd8487..06b5abf 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -3603,23 +3603,12 @@ static void nand_decode_id(struct nand_chip *chip, struct nand_flash_dev *type) static void nand_decode_bbm_options(struct nand_chip *chip) { struct mtd_info *mtd = nand_to_mtd(chip); - u8 *id_data = chip->id.data; - int maf_id = id_data[0]; /* Set the bad block position */ if (mtd->writesize > 512 || (chip->options & NAND_BUSWIDTH_16)) chip->badblockpos = NAND_LARGE_BADBLOCK_POS; else chip->badblockpos = NAND_SMALL_BADBLOCK_POS; - - /* -* Bad block marker is stored in the last page of each block on Samsung -* and Hynix MLC devices; stored in first two pages of each block on -* Micron devices with 2KiB pages and on SLC Samsung, Hynix, Toshiba, -* AMD/Spansion, and Macronix. All others scan only the first page. -*/ - if (nand_is_slc(chip) && maf_id == NAND_MFR_MACRONIX) - chip->bbt_options |= NAND_BBT_SCAN2NDPAGE; } static inline bool is_full_id_nand(struct nand_flash_dev *type) diff --git a/drivers/mtd/nand/nand_ids.c b/drivers/mtd/nand/nand_ids.c index 299b2b1..5bc347c 100644 --- a/drivers/mtd/nand/nand_ids.c +++ b/drivers/mtd/nand/nand_ids.c @@ -171,6 +171,7 @@ 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; struct nand_manufacturers nand_manuf_ids[] = { {NAND_MFR_TOSHIBA, "Toshiba", &toshiba_nand_manuf_ops}, @@ -182,7 +183,7 @@ struct nand_manufacturers nand_manuf_ids[] = { {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"}, + {NAND_MFR_MACRONIX, "Macronix", ¯onix_nand_manuf_ops}, {NAND_MFR_EON, "Eon"}, {NAND_MFR_SANDISK, "SanDisk"}, {NAND_MFR_INTEL, "Intel"}, diff --git a/drivers/mtd/nand/nand_macronix.c b/drivers/mtd/nand/nand_macronix.c new file mode 100644 index 000..960ddc0 --- /dev/null +++ b/drivers/mtd/nand/nand_macronix.c @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2013 Boris Brezillon + * + * 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. + * + * 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 + +static int macronix_nand_init(struct nand_chip *chip) +{ + if (nand_is_slc(chip)) + chip->bbt_options |= NAND_BBT_SCAN2NDPAGE; + + return 0; +} + +const struct nand_manufacturer_ops macronix_nand_manuf_ops = { + .init = macronix_nand_init, +}; -- 2.7.4
[PATCH v2 10/15] mtd: nand: move Micron specific init logic in nand_micron.c
Move Micron specific initialization logic into nand_micron.c. This is part of the "separate vendor specific code from core" cleanup process. Signed-off-by: Boris Brezillon --- drivers/mtd/nand/Makefile | 1 + drivers/mtd/nand/nand_base.c | 31 +--- drivers/mtd/nand/nand_ids.c| 3 +- drivers/mtd/nand/nand_micron.c | 84 ++ include/linux/mtd/nand.h | 20 -- 5 files changed, 88 insertions(+), 51 deletions(-) create mode 100644 drivers/mtd/nand/nand_micron.c diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile index 403e9a7..f1bd008 100644 --- a/drivers/mtd/nand/Makefile +++ b/drivers/mtd/nand/Makefile @@ -59,5 +59,6 @@ obj-$(CONFIG_MTD_NAND_QCOM) += qcom_nandc.o nand-objs := nand_base.o nand_bbt.o nand_timings.o nand_ids.o nand-objs += nand_hynix.o +nand-objs += nand_micron.o nand-objs += nand_samsung.o nand-objs += nand_toshiba.o diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index 931aafb..17fb6f6 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -3301,30 +3301,6 @@ ext_out: return ret; } -static int nand_setup_read_retry_micron(struct mtd_info *mtd, int retry_mode) -{ - struct nand_chip *chip = mtd_to_nand(mtd); - uint8_t feature[ONFI_SUBFEATURE_PARAM_LEN] = {retry_mode}; - - return chip->onfi_set_features(mtd, chip, ONFI_FEATURE_ADDR_READ_RETRY, - feature); -} - -/* - * Configure chip properties from Micron vendor-specific ONFI table - */ -static void nand_onfi_detect_micron(struct nand_chip *chip, - struct nand_onfi_params *p) -{ - struct nand_onfi_vendor_micron *micron = (void *)p->vendor; - - if (le16_to_cpu(p->vendor_revision) < 1) - return; - - chip->read_retries = micron->read_retry_options; - chip->setup_read_retry = nand_setup_read_retry_micron; -} - /* * Check if the NAND chip is ONFI compliant, returns 1 if it is, 0 otherwise. */ @@ -3421,9 +3397,6 @@ static int nand_flash_detect_onfi(struct nand_chip *chip) pr_warn("Could not retrieve ONFI ECC requirements\n"); } - if (p->jedec_id == NAND_MFR_MICRON) - nand_onfi_detect_micron(chip, p); - return 1; } @@ -3662,9 +3635,7 @@ static void nand_decode_bbm_options(struct nand_chip *chip) */ if ((nand_is_slc(chip) && (maf_id == NAND_MFR_AMD || -maf_id == NAND_MFR_MACRONIX)) || - (mtd->writesize == 2048 && -maf_id == NAND_MFR_MICRON)) +maf_id == NAND_MFR_MACRONIX))) chip->bbt_options |= NAND_BBT_SCAN2NDPAGE; } diff --git a/drivers/mtd/nand/nand_ids.c b/drivers/mtd/nand/nand_ids.c index 2cc9d32..5d02787 100644 --- a/drivers/mtd/nand/nand_ids.c +++ b/drivers/mtd/nand/nand_ids.c @@ -169,6 +169,7 @@ 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; struct nand_manufacturers nand_manuf_ids[] = { {NAND_MFR_TOSHIBA, "Toshiba", &toshiba_nand_manuf_ops}, @@ -178,7 +179,7 @@ struct nand_manufacturers nand_manuf_ids[] = { {NAND_MFR_RENESAS, "Renesas"}, {NAND_MFR_STMICRO, "ST Micro"}, {NAND_MFR_HYNIX, "Hynix", &hynix_nand_manuf_ops}, - {NAND_MFR_MICRON, "Micron"}, + {NAND_MFR_MICRON, "Micron", µn_nand_manuf_ops}, {NAND_MFR_AMD, "AMD/Spansion"}, {NAND_MFR_MACRONIX, "Macronix"}, {NAND_MFR_EON, "Eon"}, diff --git a/drivers/mtd/nand/nand_micron.c b/drivers/mtd/nand/nand_micron.c new file mode 100644 index 000..2303e45 --- /dev/null +++ b/drivers/mtd/nand/nand_micron.c @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2013 Boris Brezillon + * + * 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. + * + * 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 + +struct nand_onfi_vendor_micron { + u8 two_plane_read; + u8 read_cache; + u8 read_unique_id; + u8 dq_imped; + u8 dq_imped_num_settings; + u8 dq_imped_feat_addr; + u8 rb_pulldown_strength; + u8 rb_pulldown_strength_feat_addr; + u8 rb_pulldown_strength_num_settings; + u8 otp_mode; + u8 otp_page_start; + u8 otp_data_prot_add
[PATCH v2 11/15] mtd: nand: move AMD/Spansion specific init/detection logic in nand_amd.c
Moving AMD/Spansion specific initialization/detection into nand_amd.c. This is part of the "separate vendor specific code from core" cleanup process. Signed-off-by: Boris Brezillon --- drivers/mtd/nand/Makefile| 1 + drivers/mtd/nand/nand_amd.c | 48 drivers/mtd/nand/nand_base.c | 19 +- drivers/mtd/nand/nand_ids.c | 3 ++- 4 files changed, 52 insertions(+), 19 deletions(-) create mode 100644 drivers/mtd/nand/nand_amd.c diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile index f1bd008..19d0cb8 100644 --- a/drivers/mtd/nand/Makefile +++ b/drivers/mtd/nand/Makefile @@ -58,6 +58,7 @@ obj-$(CONFIG_MTD_NAND_BRCMNAND) += brcmnand/ obj-$(CONFIG_MTD_NAND_QCOM)+= qcom_nandc.o nand-objs := nand_base.o nand_bbt.o nand_timings.o nand_ids.o +nand-objs += nand_amd.o nand-objs += nand_hynix.o nand-objs += nand_micron.o nand-objs += nand_samsung.o diff --git a/drivers/mtd/nand/nand_amd.c b/drivers/mtd/nand/nand_amd.c new file mode 100644 index 000..3d7cc36 --- /dev/null +++ b/drivers/mtd/nand/nand_amd.c @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2013 Boris Brezillon + * + * 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. + * + * 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 + +static void amd_nand_decode_id(struct nand_chip *chip) +{ + struct mtd_info *mtd = nand_to_mtd(chip); + + nand_decode_ext_id(chip); + + /* +* Check for Spansion/AMD ID + repeating 5th, 6th byte since +* some Spansion chips have erasesize that conflicts with size +* listed in nand_ids table. +* Data sheet (5 byte ID): Spansion S30ML-P ORNAND (p.39) +*/ +if (chip->id.data[4] != 0x00 && chip->id.data[5] == 0x00 && +chip->id.data[6] == 0x00 && chip->id.data[7] == 0x00 && +mtd->writesize == 512) { + mtd->erasesize = 128 * 1024; + mtd->erasesize <<= ((chip->id.data[3] & 0x03) << 1); + } +} + +static int amd_nand_init(struct nand_chip *chip) +{ + if (nand_is_slc(chip)) + chip->bbt_options |= NAND_BBT_SCAN2NDPAGE; + + return 0; +} + +const struct nand_manufacturer_ops amd_nand_manuf_ops = { + .detect = amd_nand_decode_id, + .init = amd_nand_init, +}; diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index 17fb6f6..5fd8487 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -3586,8 +3586,6 @@ EXPORT_SYMBOL_GPL(nand_decode_ext_id); static void nand_decode_id(struct nand_chip *chip, struct nand_flash_dev *type) { struct mtd_info *mtd = nand_to_mtd(chip); - u8 *id_data = chip->id.data; - int maf_id = id_data[0]; mtd->erasesize = type->erasesize; mtd->writesize = type->pagesize; @@ -3595,19 +3593,6 @@ static void nand_decode_id(struct nand_chip *chip, struct nand_flash_dev *type) /* All legacy ID NAND are small-page, SLC */ chip->bits_per_cell = 1; - - /* -* Check for Spansion/AMD ID + repeating 5th, 6th byte since -* some Spansion chips have erasesize that conflicts with size -* listed in nand_ids table. -* Data sheet (5 byte ID): Spansion S30ML-P ORNAND (p.39) -*/ - if (maf_id == NAND_MFR_AMD && id_data[4] != 0x00 && id_data[5] == 0x00 - && id_data[6] == 0x00 && id_data[7] == 0x00 - && mtd->writesize == 512) { - mtd->erasesize = 128 * 1024; - mtd->erasesize <<= ((id_data[3] & 0x03) << 1); - } } /* @@ -3633,9 +3618,7 @@ static void nand_decode_bbm_options(struct nand_chip *chip) * Micron devices with 2KiB pages and on SLC Samsung, Hynix, Toshiba, * AMD/Spansion, and Macronix. All others scan only the first page. */ - if ((nand_is_slc(chip) && - (maf_id == NAND_MFR_AMD || -maf_id == NAND_MFR_MACRONIX))) + if (nand_is_slc(chip) && maf_id == NAND_MFR_MACRONIX) chip->bbt_options |= NAND_BBT_SCAN2NDPAGE; } diff --git a/drivers/mtd/nand/nand_ids.c b/drivers/mtd/nand/nand_ids.c index 5d02787..299b2b1 100644 --- a/drivers/mtd/nand/nand_ids.c +++ b/drivers/mtd/nand/nand_ids.c @@ -170,6 +170,7 @@ 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_m
Re: [RFC][PATCH 1/6] staging: android: ion: return error value for ion_device_add_heap
On Mon, Jun 06, 2016 at 11:23:28AM -0700, Laura Abbott wrote: > From: Laura Abbott > > > ion_device_add_heap doesn't return an error value. Change it to return > information to callers. > > Signed-off-by: Laura Abbott Reviewed-by: Liviu Dudau > --- > drivers/staging/android/ion/ion.c | 7 +-- > drivers/staging/android/ion/ion_priv.h | 2 +- > 2 files changed, 6 insertions(+), 3 deletions(-) > > diff --git a/drivers/staging/android/ion/ion.c > b/drivers/staging/android/ion/ion.c > index a2cf93b..306340a 100644 > --- a/drivers/staging/android/ion/ion.c > +++ b/drivers/staging/android/ion/ion.c > @@ -1584,14 +1584,16 @@ static int debug_shrink_get(void *data, u64 *val) > DEFINE_SIMPLE_ATTRIBUTE(debug_shrink_fops, debug_shrink_get, > debug_shrink_set, "%llu\n"); > > -void ion_device_add_heap(struct ion_device *dev, struct ion_heap *heap) > +int ion_device_add_heap(struct ion_device *dev, struct ion_heap *heap) > { > struct dentry *debug_file; > > if (!heap->ops->allocate || !heap->ops->free || !heap->ops->map_dma || > - !heap->ops->unmap_dma) > + !heap->ops->unmap_dma) { > pr_err("%s: can not add heap with invalid ops struct.\n", > __func__); > + return -EINVAL; > + } > > spin_lock_init(&heap->free_lock); > heap->free_list_size = 0; > @@ -1639,6 +1641,7 @@ void ion_device_add_heap(struct ion_device *dev, struct > ion_heap *heap) > } > > up_write(&dev->lock); > + return 0; > } > EXPORT_SYMBOL(ion_device_add_heap); > > diff --git a/drivers/staging/android/ion/ion_priv.h > b/drivers/staging/android/ion/ion_priv.h > index 0239883..35726ae 100644 > --- a/drivers/staging/android/ion/ion_priv.h > +++ b/drivers/staging/android/ion/ion_priv.h > @@ -221,7 +221,7 @@ void ion_device_destroy(struct ion_device *dev); > * @dev: the device > * @heap:the heap to add > */ > -void ion_device_add_heap(struct ion_device *dev, struct ion_heap *heap); > +int ion_device_add_heap(struct ion_device *dev, struct ion_heap *heap); > > /** > * some helpers for common operations on buffers using the sg_table > -- > 2.5.5 > -- | I would like to | | fix the world, | | but they're not | | giving me the | \ source code! / --- ¯\_(ツ)_/¯
[PATCH v2 14/15] mtd: nand: hynix: rework NAND ID decoding to extract more information
The current NAND ID detection in nand_hynix.c is not handling the different scheme used by Hynix, thus forcing developers to add new entries in the nand_ids table each time they want to support a new MLC NAND. Enhance the detection logic to handle all known formats. This does not necessarily mean we are handling all the cases, but if new formats are discovered, the code should evolve to take them into account instead of adding more full-id entries in the nand_ids table. Signed-off-by: Boris Brezillon --- drivers/mtd/nand/nand_hynix.c | 227 ++ 1 file changed, 208 insertions(+), 19 deletions(-) diff --git a/drivers/mtd/nand/nand_hynix.c b/drivers/mtd/nand/nand_hynix.c index 06c8e8b..f73b99f 100644 --- a/drivers/mtd/nand/nand_hynix.c +++ b/drivers/mtd/nand/nand_hynix.c @@ -14,20 +14,54 @@ #include -static void hynix_nand_decode_id(struct nand_chip *chip) +static bool hynix_nand_has_valid_jedecid(struct nand_chip *chip) { struct mtd_info *mtd = nand_to_mtd(chip); + u8 jedecid[6] = { }; + int i = 0; + + chip->cmdfunc(mtd, NAND_CMD_READID, 0x40, -1); + for (i = 0; i < 5; i++) + jedecid[i] = chip->read_byte(mtd); - /* Hynix MLC (6 byte ID): Hynix H27UBG8T2B (p.22) */ - if (chip->id.len == 6 && !nand_is_slc(chip)) { - u8 tmp, extid = chip->id.data[3]; + return !strcmp("JEDEC", jedecid); +} - /* Extract pagesize */ - mtd->writesize = 2048 << (extid & 0x03); - extid >>= 2; +static void hynix_nand_extract_oobsize(struct nand_chip *chip, + bool valid_jedecid) +{ + struct mtd_info *mtd = nand_to_mtd(chip); + u8 oobsize; - /* Extract oobsize */ - switch (((extid >> 2) & 0x4) | (extid & 0x3)) { + oobsize = ((chip->id.data[3] >> 2) & 0x3) | + ((chip->id.data[3] >> 4) & 0x4); + + if (valid_jedecid) { + switch (oobsize) { + case 0: + mtd->oobsize = 2048; + break; + case 1: + mtd->oobsize = 1664; + break; + case 2: + mtd->oobsize = 1024; + break; + case 3: + mtd->oobsize = 640; + break; + default: + /* +* We should never reach this case, but if that +* happens, this probably means Samsung decided to use +* a different extended ID format, and we should find +* a way to support it. +*/ + WARN(1, "Invalid OOB size"); + break; + } + } else { + switch (oobsize) { case 0: mtd->oobsize = 128; break; @@ -46,23 +80,178 @@ static void hynix_nand_decode_id(struct nand_chip *chip) case 5: mtd->oobsize = 16; break; - default: + case 6: mtd->oobsize = 640; break; + default: + /* +* We should never reach this case, but if that +* happens, this probably means Samsung decided to use +* a different extended ID format, and we should find +* a way to support it. +*/ + WARN(1, "Invalid OOB size"); + break; } + } +} + +static void hynix_nand_extract_ecc_requirements(struct nand_chip *chip, + bool valid_jedecid) +{ + u8 ecc_level = (chip->id.data[4] >> 4) & 0x7; + + if (valid_jedecid) { + /* Reference: H27UCG8T2E datasheet */ + chip->ecc_step_ds = 1024; - /* Extract blocksize */ - extid >>= 2; - tmp = ((extid >> 1) & 0x04) | (extid & 0x03); - if (tmp < 0x03) - mtd->erasesize = (128 * 1024) << tmp; - else if (tmp == 0x03) - mtd->erasesize = 768 * 1024; - else - mtd->erasesize = (64 * 1024) << tmp; + switch (ecc_level) { + case 0: + chip->ecc_step_ds = 0; + chip->ecc_strength_ds = 0; + break; + case 1: + chip->ecc_strength_ds = 4; + break; + case 2: + chip->ecc_strength_ds = 24; + break; + case 3: + chip->
[PATCH v2 07/15] mtd: nand: move Samsung specific init/detection logic in nand_samsung.c
Move Samsung specific initialization and detection logic into nand_samsung.c. This is part of the "separate vendor specific code from core" cleanup process. Signed-off-by: Boris Brezillon --- drivers/mtd/nand/Makefile | 1 + drivers/mtd/nand/nand_base.c| 52 ++-- drivers/mtd/nand/nand_ids.c | 6 ++- drivers/mtd/nand/nand_samsung.c | 89 + 4 files changed, 98 insertions(+), 50 deletions(-) create mode 100644 drivers/mtd/nand/nand_samsung.c diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile index d303dee..55a55d3 100644 --- a/drivers/mtd/nand/Makefile +++ b/drivers/mtd/nand/Makefile @@ -58,3 +58,4 @@ obj-$(CONFIG_MTD_NAND_BRCMNAND) += brcmnand/ obj-$(CONFIG_MTD_NAND_QCOM)+= qcom_nandc.o nand-objs := nand_base.o nand_bbt.o nand_timings.o nand_ids.o +nand-objs += nand_samsung.o diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index 0a7d1c6..a7c7ef3 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -3593,48 +3593,13 @@ void nand_decode_ext_id(struct nand_chip *chip) /* * Field definitions are in the following datasheets: * Old style (4,5 byte ID): Samsung K9GAG08U0M (p.32) -* New Samsung (6 byte ID): Samsung K9GAG08U0F (p.44) * Hynix MLC (6 byte ID): Hynix H27UBG8T2B (p.22) * * Check for ID length, non-zero 6th byte, cell type, and Hynix/Samsung * ID to decide what to do. */ - if (id_len == 6 && id_data[0] == NAND_MFR_SAMSUNG && - !nand_is_slc(chip) && id_data[5] != 0x00) { - /* Calc pagesize */ - mtd->writesize = 2048 << (extid & 0x03); - extid >>= 2; - /* Calc oobsize */ - switch (((extid >> 2) & 0x04) | (extid & 0x03)) { - case 1: - mtd->oobsize = 128; - break; - case 2: - mtd->oobsize = 218; - break; - case 3: - mtd->oobsize = 400; - break; - case 4: - mtd->oobsize = 436; - break; - case 5: - mtd->oobsize = 512; - break; - case 6: - mtd->oobsize = 640; - break; - case 7: - default: /* Other cases are "reserved" (unknown) */ - mtd->oobsize = 1024; - break; - } - extid >>= 2; - /* Calc blocksize */ - mtd->erasesize = (128 * 1024) << - (((extid >> 1) & 0x04) | (extid & 0x03)); - } else if (id_len == 6 && id_data[0] == NAND_MFR_HYNIX && - !nand_is_slc(chip)) { + if (id_len == 6 && id_data[0] == NAND_MFR_HYNIX && + !nand_is_slc(chip)) { unsigned int tmp; /* Calc pagesize */ @@ -3762,13 +3727,10 @@ static void nand_decode_bbm_options(struct nand_chip *chip) * Micron devices with 2KiB pages and on SLC Samsung, Hynix, Toshiba, * AMD/Spansion, and Macronix. All others scan only the first page. */ - if (!nand_is_slc(chip) && - (maf_id == NAND_MFR_SAMSUNG || -maf_id == NAND_MFR_HYNIX)) + if (!nand_is_slc(chip) && maf_id == NAND_MFR_HYNIX) chip->bbt_options |= NAND_BBT_SCANLASTPAGE; else if ((nand_is_slc(chip) && - (maf_id == NAND_MFR_SAMSUNG || -maf_id == NAND_MFR_HYNIX || + (maf_id == NAND_MFR_HYNIX || maf_id == NAND_MFR_TOSHIBA || maf_id == NAND_MFR_AMD || maf_id == NAND_MFR_MACRONIX)) || @@ -3926,12 +3888,6 @@ static int nand_detect(struct nand_chip *chip, struct nand_flash_dev *type) /* Get chip options */ chip->options |= type->options; - /* -* Check if chip is not a Samsung device. Do not clear the -* options for chips which do not have an extended id. -*/ - if (maf_id != NAND_MFR_SAMSUNG && !type->pagesize) - chip->options &= ~NAND_SAMSUNG_LP_OPTIONS; ident_done: if (chip->options & NAND_BUSWIDTH_AUTO) { diff --git a/drivers/mtd/nand/nand_ids.c b/drivers/mtd/nand/nand_ids.c index ccc05f5..5d2bef5 100644 --- a/drivers/mtd/nand/nand_ids.c +++ b/drivers/mtd/nand/nand_ids.c @@ -10,7 +10,7 @@ #include #include -#define LP_OPTIONS NAND_SAMSUNG_LP_OPTIONS +#define LP_OPTIONS 0 #define LP_OPTIONS16 (LP_OPTIONS | NAND_BUSWIDTH_16) #define SP_OPTIONS NAND_NEED_READRDY @@ -166,9 +166,11 @@ struct nand_flash_dev nand_fla
[PATCH v2 06/15] mtd: nand: kill the MTD_NAND_IDS Kconfig option
MTD_NAND_IDS is selected by MTD_NAND, which makes it useless. Remove the Kconfig option and link nand_ids.o into the nand.o object file. Doing that also prevents adding an extra nand_ids.ko module when MTD_NAND is activated as a module. Signed-off-by: Boris Brezillon --- arch/cris/arch-v32/drivers/Kconfig | 1 - drivers/mtd/nand/Kconfig | 4 drivers/mtd/nand/Makefile | 3 +-- 3 files changed, 1 insertion(+), 7 deletions(-) diff --git a/arch/cris/arch-v32/drivers/Kconfig b/arch/cris/arch-v32/drivers/Kconfig index 2735eb7..b7cd6b9 100644 --- a/arch/cris/arch-v32/drivers/Kconfig +++ b/arch/cris/arch-v32/drivers/Kconfig @@ -136,7 +136,6 @@ config ETRAX_NANDFLASH bool "NAND flash support" depends on ETRAX_ARCH_V32 select MTD_NAND - select MTD_NAND_IDS help This option enables MTD mapping of NAND flash devices. Needed to use NAND flash memories. If unsure, say Y. diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig index f05e0e9..16d7dff 100644 --- a/drivers/mtd/nand/Kconfig +++ b/drivers/mtd/nand/Kconfig @@ -13,7 +13,6 @@ config MTD_NAND_ECC_SMC menuconfig MTD_NAND tristate "NAND Device Support" depends on MTD - select MTD_NAND_IDS select MTD_NAND_ECC help This enables support for accessing all type of NAND flash @@ -109,9 +108,6 @@ config MTD_NAND_OMAP_BCH config MTD_NAND_OMAP_BCH_BUILD def_tristate MTD_NAND_OMAP2 && MTD_NAND_OMAP_BCH -config MTD_NAND_IDS - tristate - config MTD_NAND_RICOH tristate "Ricoh xD card reader" default n diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile index f553353..d303dee 100644 --- a/drivers/mtd/nand/Makefile +++ b/drivers/mtd/nand/Makefile @@ -5,7 +5,6 @@ obj-$(CONFIG_MTD_NAND) += nand.o obj-$(CONFIG_MTD_NAND_ECC) += nand_ecc.o obj-$(CONFIG_MTD_NAND_BCH) += nand_bch.o -obj-$(CONFIG_MTD_NAND_IDS) += nand_ids.o obj-$(CONFIG_MTD_SM_COMMON)+= sm_common.o obj-$(CONFIG_MTD_NAND_CAFE)+= cafe_nand.o @@ -58,4 +57,4 @@ obj-$(CONFIG_MTD_NAND_HISI504)+= hisi504_nand.o obj-$(CONFIG_MTD_NAND_BRCMNAND)+= brcmnand/ obj-$(CONFIG_MTD_NAND_QCOM)+= qcom_nandc.o -nand-objs := nand_base.o nand_bbt.o nand_timings.o +nand-objs := nand_base.o nand_bbt.o nand_timings.o nand_ids.o -- 2.7.4
[PATCH v2 03/15] mtd: nand: get rid of busw parameter
Auto-detection functions are passed a busw parameter to retrieve the actual NAND bus width and eventually set the correct value in chip->options. Rework the nand_get_flash_type() function to get rid of this extra parameter and let detection code directly set the NAND_BUSWIDTH_16 flag in chip->options if needed. Signed-off-by: Boris Brezillon --- drivers/mtd/nand/nand_base.c | 68 1 file changed, 37 insertions(+), 31 deletions(-) diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index 4959263..1e865c0 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -3148,8 +3148,10 @@ static void nand_shutdown(struct mtd_info *mtd) } /* Set default functions */ -static void nand_set_defaults(struct nand_chip *chip, int busw) +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; @@ -3326,7 +3328,7 @@ static void nand_onfi_detect_micron(struct nand_chip *chip, /* * 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, int *busw) +static int nand_flash_detect_onfi(struct nand_chip *chip) { struct mtd_info *mtd = nand_to_mtd(chip); struct nand_onfi_params *p = &chip->onfi_params; @@ -3395,9 +3397,7 @@ static int nand_flash_detect_onfi(struct nand_chip *chip, int *busw) chip->bits_per_cell = p->bits_per_cell; if (onfi_feature(chip) & ONFI_FEATURE_16_BIT_BUS) - *busw = NAND_BUSWIDTH_16; - else - *busw = 0; + chip->options |= NAND_BUSWIDTH_16; if (p->ecc_bits != 0xff) { chip->ecc_strength_ds = p->ecc_bits; @@ -3430,7 +3430,7 @@ static int nand_flash_detect_onfi(struct nand_chip *chip, int *busw) /* * 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, int *busw) +static int nand_flash_detect_jedec(struct nand_chip *chip) { struct mtd_info *mtd = nand_to_mtd(chip); struct nand_jedec_params *p = &chip->jedec_params; @@ -3491,9 +3491,7 @@ static int nand_flash_detect_jedec(struct nand_chip *chip, int *busw) chip->bits_per_cell = p->bits_per_cell; if (jedec_feature(chip) & JEDEC_FEATURE_16_BIT_BUS) - *busw = NAND_BUSWIDTH_16; - else - *busw = 0; + chip->options |= NAND_BUSWIDTH_16; /* ECC info */ ecc = &p->ecc_info[0]; @@ -3582,7 +3580,7 @@ static int nand_get_bits_per_cell(u8 cellinfo) * chip. The rest of the parameters must be decoded according to generic or * manufacturer-specific "extended ID" decoding patterns. */ -static void nand_decode_ext_id(struct nand_chip *chip, int *busw) +static void nand_decode_ext_id(struct nand_chip *chip) { struct mtd_info *mtd = nand_to_mtd(chip); int extid, id_len = chip->id.len; @@ -3635,7 +3633,6 @@ static void nand_decode_ext_id(struct nand_chip *chip, int *busw) /* Calc blocksize */ mtd->erasesize = (128 * 1024) << (((extid >> 1) & 0x04) | (extid & 0x03)); - *busw = 0; } else if (id_len == 6 && id_data[0] == NAND_MFR_HYNIX && !nand_is_slc(chip)) { unsigned int tmp; @@ -3676,7 +3673,6 @@ static void nand_decode_ext_id(struct nand_chip *chip, int *busw) mtd->erasesize = 768 * 1024; else mtd->erasesize = (64 * 1024) << tmp; - *busw = 0; } else { /* Calc pagesize */ mtd->writesize = 1024 << (extid & 0x03); @@ -3689,7 +3685,8 @@ static void nand_decode_ext_id(struct nand_chip *chip, int *busw) mtd->erasesize = (64 * 1024) << (extid & 0x03); extid >>= 2; /* Get buswidth information */ - *busw = (extid & 0x01) ? NAND_BUSWIDTH_16 : 0; + if (extid & 0x1) + chip->options |= NAND_BUSWIDTH_16; /* * Toshiba 24nm raw SLC (i.e., not BENAND) have 32B OOB per @@ -3714,8 +3711,7 @@ static void nand_decode_ext_id(struct nand_chip *chip, int *busw) * decodes a matching ID table entry and assigns the MTD size parameters for * the chip. */ -static void nand_decode_id(struct nand_chip *chip, struct nand_flash_dev *type, - int *busw) +static void nand_decode_id(struct nand_chip *chip, struct nand_flash_dev *type) { struct mtd_info *mtd = nand_to_mtd(chip); u8 *id_data = chip->id.data; @@ -3724,7 +3720,6 @@ static void nand_decode_id(struct nand_chip *chip, struct nand_flash_dev *type,
[PATCH v2 09/15] mtd: nand: move Toshiba specific init/detection logic in nand_toshiba.c
Move Toshiba specific initialization and detection logic into nand_toshiba.c. This is part of the "separate vendor specific code from core" cleanup process. Signed-off-by: Boris Brezillon --- drivers/mtd/nand/Makefile | 1 + drivers/mtd/nand/nand_base.c| 19 ++-- drivers/mtd/nand/nand_ids.c | 3 ++- drivers/mtd/nand/nand_toshiba.c | 48 + 4 files changed, 53 insertions(+), 18 deletions(-) create mode 100644 drivers/mtd/nand/nand_toshiba.c diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile index d79338f..403e9a7 100644 --- a/drivers/mtd/nand/Makefile +++ b/drivers/mtd/nand/Makefile @@ -60,3 +60,4 @@ obj-$(CONFIG_MTD_NAND_QCOM) += qcom_nandc.o nand-objs := nand_base.o nand_bbt.o nand_timings.o nand_ids.o nand-objs += nand_hynix.o nand-objs += nand_samsung.o +nand-objs += nand_toshiba.o diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index 69812fd..931aafb 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -3583,7 +3583,7 @@ static int nand_get_bits_per_cell(u8 cellinfo) void nand_decode_ext_id(struct nand_chip *chip) { struct mtd_info *mtd = nand_to_mtd(chip); - int extid, id_len = chip->id.len; + int extid; u8 *id_data = chip->id.data; /* The 3rd id byte holds MLC / multichip data */ chip->bits_per_cell = nand_get_bits_per_cell(id_data[2]); @@ -3602,20 +3602,6 @@ void nand_decode_ext_id(struct nand_chip *chip) /* Get buswidth information */ if (extid & 0x1) chip->options |= NAND_BUSWIDTH_16; - - /* -* Toshiba 24nm raw SLC (i.e., not BENAND) have 32B OOB per -* 512B page. For Toshiba SLC, we decode the 5th/6th byte as -* follows: -* - ID byte 6, bits[2:0]: 100b -> 43nm, 101b -> 32nm, -* 110b -> 24nm -* - ID byte 5, bit[7]:1 -> BENAND, 0 -> raw SLC -*/ - if (id_len >= 6 && id_data[0] == NAND_MFR_TOSHIBA && - nand_is_slc(chip) && - (id_data[5] & 0x7) == 0x6 /* 24nm */ && -!(id_data[4] & 0x80) /* !BENAND */) - mtd->oobsize = 32 * mtd->writesize >> 9; } EXPORT_SYMBOL_GPL(nand_decode_ext_id); @@ -3675,8 +3661,7 @@ static void nand_decode_bbm_options(struct nand_chip *chip) * AMD/Spansion, and Macronix. All others scan only the first page. */ if ((nand_is_slc(chip) && - (maf_id == NAND_MFR_TOSHIBA || -maf_id == NAND_MFR_AMD || + (maf_id == NAND_MFR_AMD || maf_id == NAND_MFR_MACRONIX)) || (mtd->writesize == 2048 && maf_id == NAND_MFR_MICRON)) diff --git a/drivers/mtd/nand/nand_ids.c b/drivers/mtd/nand/nand_ids.c index 7bf93b8..2cc9d32 100644 --- a/drivers/mtd/nand/nand_ids.c +++ b/drivers/mtd/nand/nand_ids.c @@ -166,11 +166,12 @@ struct nand_flash_dev nand_flash_ids[] = { }; /* Manufacturer 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; struct nand_manufacturers nand_manuf_ids[] = { - {NAND_MFR_TOSHIBA, "Toshiba"}, + {NAND_MFR_TOSHIBA, "Toshiba", &toshiba_nand_manuf_ops}, {NAND_MFR_SAMSUNG, "Samsung", &samsung_nand_manuf_ops}, {NAND_MFR_FUJITSU, "Fujitsu"}, {NAND_MFR_NATIONAL, "National"}, diff --git a/drivers/mtd/nand/nand_toshiba.c b/drivers/mtd/nand/nand_toshiba.c new file mode 100644 index 000..0e19f9d --- /dev/null +++ b/drivers/mtd/nand/nand_toshiba.c @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2013 Boris Brezillon + * + * 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. + * + * 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 + +static void toshiba_nand_decode_id(struct nand_chip *chip) +{ + struct mtd_info *mtd = nand_to_mtd(chip); + + nand_decode_ext_id(chip); + + /* +* Toshiba 24nm raw SLC (i.e., not BENAND) have 32B OOB per +* 512B page. For Toshiba SLC, we decode the 5th/6th byte as +* follows: +* - ID byte 6, bits[2:0]: 100b -> 43nm, 101b -> 32nm, +* 110b -> 24nm +* - ID byte 5, bit[7]:1 -> BENAND, 0 -> raw SLC +*/ + if (chip->id.len >= 6 && nand_is_slc(chip) && + (chip->id.data[5] & 0x7) == 0x6 /* 24nm */ &
Re: [PATCH] futex: Calculate the futex key based on a tail page for file-based futexes
On Tue, 07 Jun 2016, Mel Gorman wrote: Mike Galbraith reported that the LTP test case futex_wake04 was broken by commit 65d8fc777f6d ("futex: Remove requirement for lock_page() in get_futex_key()"). This test case uses futexes backed by hugetlbfs pages and so there is an associated inode with a futex stored on such pages. The problem is that the key is being calculated based on the head page index of the hugetlbfs page and not the tail page. Prior to the optimisation, the page lock was used to stabilise mappings and pin the inode is file-backed which is overkill. If the page was a compound page, the head page was automatically looked up as part of the page lock operation but the tail page index was used to calculate the futex key. After the optimisation, the compound head is looked up early and the page lock is only relied upon to identify truncated pages, special pages or a shmem page moving to swapcache. The head page is looked up because without the page lock, special care has to be taken to pin the inode correctly. However, the tail page is still required to calculate the futex key so this patch records the tail page. On vanilla 4.6, the output of the test case is; futex_wake040 TINFO : Hugepagesize 2097152 futex_wake041 TFAIL : futex_wake04.c:126: Bug: wait_thread2 did not wake after 30 secs. With the patch applied futex_wake040 TINFO : Hugepagesize 2097152 futex_wake041 TPASS : Hi hydra, thread2 awake! Reported-by: Mike Galbraith Signed-off-by: Mel Gorman Reviewed-by: Davidlohr Bueso (and yay for maintaining performance)
Re: [Intel-gfx] 4.7-rc0: redshift stopped working on intel display
Hi! > Could you try to apply the following patch [1], hopefully this fixes > the issue for you. > > [1] https://patchwork.freedesktop.org/patch/89111/ I updated the kernel, applied the patch and yes, that helped. Thanks! Pavel -- (english) http://www.livejournal.com/~pavelmachek (cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
Re: [PATCH 1/2] mfd: sm-usb-dig: Add support for the TI SM-USB-DIG
On Tue, 31 May 2016, Andrew F. Davis wrote: > The TI SM-USB-DIG is a USB to SPI/I2C/1Wire/GPIO adapter. > Add MFD core support. > > Signed-off-by: Andrew F. Davis > --- > The SPI, GPIO, and 1Wire drivers are WIP. > > drivers/mfd/Kconfig| 8 +++ > drivers/mfd/Makefile | 2 + > drivers/mfd/sm-usb-dig.c | 138 > + > include/linux/mfd/sm-usb-dig.h | 73 ++ > 4 files changed, 221 insertions(+) > create mode 100644 drivers/mfd/sm-usb-dig.c > create mode 100644 include/linux/mfd/sm-usb-dig.h > > diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig > index 1bcf601..455219a 100644 > --- a/drivers/mfd/Kconfig > +++ b/drivers/mfd/Kconfig > @@ -1373,6 +1373,14 @@ config MFD_LM3533 > additional drivers must be enabled in order to use the LED, > backlight or ambient-light-sensor functionality of the device. > > +config MFD_SM_USB_DIG > + tristate "Texas Instruments SM-USB-DIG interface adapter" If it is decided that MFD is truly the best place for this driver, you are still going to need a USB Ack for it. > + select MFD_CORE > + help > + Support for the TI SM-USB-DIG USB to SPI/I2C/1Wire/GPIO adapter. > + Additional drivers such as SPI_SM_USB_DIG, I2C_SM_USB_DIG, etc. must > + be enabled in order to use the functionality of the device. > + > config MFD_TIMBERDALE > tristate "Timberdale FPGA" > select MFD_CORE > diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile > index 42a66e1..376013e 100644 > --- a/drivers/mfd/Makefile > +++ b/drivers/mfd/Makefile > @@ -68,6 +68,8 @@ obj-$(CONFIG_MFD_WM8350_I2C)+= wm8350-i2c.o > wm8994-objs := wm8994-core.o wm8994-irq.o wm8994-regmap.o > obj-$(CONFIG_MFD_WM8994) += wm8994.o > > +obj-$(CONFIG_MFD_SM_USB_DIG)+= sm-usb-dig.o > + > obj-$(CONFIG_TPS6105X) += tps6105x.o > obj-$(CONFIG_TPS65010) += tps65010.o > obj-$(CONFIG_TPS6507X) += tps6507x.o > diff --git a/drivers/mfd/sm-usb-dig.c b/drivers/mfd/sm-usb-dig.c > new file mode 100644 > index 000..cf7ccab > --- /dev/null > +++ b/drivers/mfd/sm-usb-dig.c This should probably be ti-sm-usb-dig.c > @@ -0,0 +1,138 @@ > +/* > + * MFD Core driver for TI SM-USB-DIG > + * > + * Copyright (C) 2016 Texas Instruments Incorporated - http://www.ti.com/ > + * Andrew F. Davis > + * > + * 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 > + * published by the Free Software Foundation. > + * > + * This program is distributed "as is" WITHOUT ANY WARRANTY of any > + * kind, whether expressed or implied; without even the implied warranty > + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License version 2 for more details. > + */ > + > +#include > +#include > +#include > + > +#include All alphabetical. > +#define USB_VENDOR_ID_TI0x0451 > +#define USB_DEVICE_ID_TI_SM_USB_DIG 0x2f90 TI at the beginning. > +#define SMUSBDIG_USB_TIMEOUT 1000/* in ms */ Rename to SMUSBDIG_USB_TIMEOUT_MS > +struct smusbdig_device { > + struct usb_device *usb_dev; > + struct usb_interface *interface; > +}; s/smusbdig/ti_smusbdig/ ... throughout. > +int smusbdig_xfer(struct smusbdig_device *smusbdig, u8 *buffer, int size) > +{ > + struct device *dev = &smusbdig->interface->dev; > + int actual_length, ret; > + > + if (!smusbdig || !buffer || size <= 0) > + return -EINVAL; > + > + ret = usb_interrupt_msg(smusbdig->usb_dev, > + usb_sndctrlpipe(smusbdig->usb_dev, 1), > + buffer, size, &actual_length, > + SMUSBDIG_USB_TIMEOUT); > + if (ret) { > + dev_err(dev, "USB transaction failed\n"); > + return ret; > + } > + > + ret = usb_interrupt_msg(smusbdig->usb_dev, > + usb_rcvctrlpipe(smusbdig->usb_dev, 1), > + buffer, SMUSBDIG_PACKET_SIZE, &actual_length, > + SMUSBDIG_USB_TIMEOUT); > + if (ret) { > + dev_err(dev, "USB transaction failed\n"); > + return ret; > + } > + > + return 0; > +} > +EXPORT_SYMBOL_GPL(smusbdig_xfer); > + > +static const struct mfd_cell smusbdig_mfd_cells[] = { > + { .name = "sm-usb-dig-gpio", }, > + { .name = "sm-usb-dig-i2c", }, > + { .name = "sm-usb-dig-spi", }, > + { .name = "sm-usb-dig-w1", }, > +}; > + > +static int smusbdig_probe(struct usb_interface *interface, > + const struct usb_device_id *usb_id) > +{ > + struct usb_host_interface *hostif = interface->cur_altsetting; > + struct device *dev = &interface->dev; > + struct smusbdig_device *smusbdig; > + u8 buffer[SMUSBDIG_PACKET_SIZE]; > + int ret; > + >
Re: [PATCH v3 04/30] staging: unisys: visorbus: remove unused module parameters
On Wed, Jun 08, 2016 at 02:13:47AM +, Binder, David Anthony wrote: > > -Original Message- > > From: Neil Horman [mailto:nhor...@redhat.com] > > Sent: Tuesday, June 07, 2016 9:23 AM > > To: Kershner, David A > > Cc: cor...@lwn.net; t...@linutronix.de; mi...@redhat.com; > > h...@zytor.com; gre...@linuxfoundation.org; Arfvidson, Erik > > ; Sell, Timothy C ; > > hof...@osadl.org; dzic...@redhat.com; jes.soren...@redhat.com; Curtin, > > Alexander Paul ; > > janani.rvchn...@gmail.com; sudipm.mukher...@gmail.com; > > pra...@redhat.com; Binder, David Anthony ; > > dan.j.willi...@intel.com; linux-kernel@vger.kernel.org; linux- > > d...@vger.kernel.org; driverdev-de...@linuxdriverproject.org; *S-Par- > > Maintainer > > Subject: Re: [PATCH v3 04/30] staging: unisys: visorbus: remove unused > > module parameters > > > > On Sat, Jun 04, 2016 at 01:27:04PM -0400, David Kershner wrote: > > > From: David Binder > > > > > > Removes unused module parameters from visorbus_main.c, in response to > > > findings by SonarQube. > > > > > > Signed-off-by: David Binder > > > Signed-off-by: David Kershner > > > Reviewed-by: Tim Sell > > > --- > > > drivers/staging/unisys/visorbus/visorbus_main.c | 9 + > > > 1 file changed, 1 insertion(+), 8 deletions(-) > > > > > > diff --git a/drivers/staging/unisys/visorbus/visorbus_main.c > > b/drivers/staging/unisys/visorbus/visorbus_main.c > > > index 2ed9628..71bff07 100644 > > > --- a/drivers/staging/unisys/visorbus/visorbus_main.c > > > +++ b/drivers/staging/unisys/visorbus/visorbus_main.c > > > @@ -27,10 +27,9 @@ > > > #define MYDRVNAME "visorbus" > > > > > > /* module parameters */ > > > -static int visorbus_debug; > > > static int visorbus_forcematch; > > > static int visorbus_forcenomatch; > > > -static int visorbus_debugref; > > > + > > > #define SERIALLOOPBACKCHANADDR (100 * 1024 * 1024) > > > > > > /* Display string that is guaranteed to be no longer the 99 characters*/ > > > @@ -1332,9 +1331,6 @@ visorbus_exit(void) > > > remove_bus_type(); > > > } > > > > > > -module_param_named(debug, visorbus_debug, int, S_IRUGO); > > > -MODULE_PARM_DESC(visorbus_debug, "1 to debug"); > > > - > > > module_param_named(forcematch, visorbus_forcematch, int, S_IRUGO); > > > MODULE_PARM_DESC(visorbus_forcematch, > > >"1 to force a successful dev <--> drv match"); > > > @@ -1342,6 +1338,3 @@ MODULE_PARM_DESC(visorbus_forcematch, > > > module_param_named(forcenomatch, visorbus_forcenomatch, int, > > S_IRUGO); > > > MODULE_PARM_DESC(visorbus_forcenomatch, > > >"1 to force an UNsuccessful dev <--> drv match"); > > > - > > > -module_param_named(debugref, visorbus_debugref, int, S_IRUGO); > > > -MODULE_PARM_DESC(visorbus_debugref, "1 to debug reference > > counting"); > > > > visorbus_forcematch and visorbus_forcenomatch appear to be referenced in > > visorbus_match (at least in the HEAD of linus' tree). If you're going to > > remove > > the module parameters, why not also remove those references and the > > force[no]match variables themselves? > > > > Neil > > We presently use visorbus_forcematch and visorbus_forcenomatch for > debugging purposes, and therefore decided to keep the variables in > the driver. > Ok, thats fine, but this seems like a half measure then. This patch removes the module option for those features, which means that for you to use them, you have to rebuild the module. If you have intentions to use it, why not just leave the module option in place? If you don't, remove it all the way. Neil > David Binder
[PATCH 1/6] virtio_net: add _UAPI prefix to virtio_net header guards
This gives better namespacing and prevents conflicts with no-uapi version of virtio_net header that will be introduced in the following patch. Signed-off-by: Mike Rapoport --- include/uapi/linux/virtio_net.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/uapi/linux/virtio_net.h b/include/uapi/linux/virtio_net.h index ec32293..75cf581 100644 --- a/include/uapi/linux/virtio_net.h +++ b/include/uapi/linux/virtio_net.h @@ -1,5 +1,5 @@ -#ifndef _LINUX_VIRTIO_NET_H -#define _LINUX_VIRTIO_NET_H +#ifndef _UAPI_LINUX_VIRTIO_NET_H +#define _UAPI_LINUX_VIRTIO_NET_H /* This header is BSD licensed so anyone can use the definitions to implement * compatible drivers/servers. * @@ -242,4 +242,4 @@ struct virtio_net_ctrl_mq { #define VIRTIO_NET_CTRL_GUEST_OFFLOADS 5 #define VIRTIO_NET_CTRL_GUEST_OFFLOADS_SET0 -#endif /* _LINUX_VIRTIO_NET_H */ +#endif /* _UAPI_LINUX_VIRTIO_NET_H */ -- 1.9.1
[PATCH 4/6] tuntap: use common code for virtio_net_hdr and skb GSO conversion
Replace open coded conversion between virtio_net_hdr to skb GSO info with virtio_net_hdr_{from,to}_skb Signed-off-by: Mike Rapoport --- drivers/net/tun.c | 97 --- 1 file changed, 21 insertions(+), 76 deletions(-) diff --git a/drivers/net/tun.c b/drivers/net/tun.c index e16487c..8cc6bf4 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -1254,15 +1254,6 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile, return -EFAULT; } - if (gso.flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) { - if (!skb_partial_csum_set(skb, tun16_to_cpu(tun, gso.csum_start), - tun16_to_cpu(tun, gso.csum_offset))) { - this_cpu_inc(tun->pcpu_stats->rx_frame_errors); - kfree_skb(skb); - return -EINVAL; - } - } - switch (tun->flags & TUN_TYPE_MASK) { case IFF_TUN: if (tun->flags & IFF_NO_PI) { @@ -1289,37 +1280,11 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile, break; } - if (gso.gso_type != VIRTIO_NET_HDR_GSO_NONE) { - pr_debug("GSO!\n"); - switch (gso.gso_type & ~VIRTIO_NET_HDR_GSO_ECN) { - case VIRTIO_NET_HDR_GSO_TCPV4: - skb_shinfo(skb)->gso_type = SKB_GSO_TCPV4; - break; - case VIRTIO_NET_HDR_GSO_TCPV6: - skb_shinfo(skb)->gso_type = SKB_GSO_TCPV6; - break; - case VIRTIO_NET_HDR_GSO_UDP: - skb_shinfo(skb)->gso_type = SKB_GSO_UDP; - break; - default: - this_cpu_inc(tun->pcpu_stats->rx_frame_errors); - kfree_skb(skb); - return -EINVAL; - } - - if (gso.gso_type & VIRTIO_NET_HDR_GSO_ECN) - skb_shinfo(skb)->gso_type |= SKB_GSO_TCP_ECN; - - skb_shinfo(skb)->gso_size = tun16_to_cpu(tun, gso.gso_size); - if (skb_shinfo(skb)->gso_size == 0) { - this_cpu_inc(tun->pcpu_stats->rx_frame_errors); - kfree_skb(skb); - return -EINVAL; - } - - /* Header must be checked, and gso_segs computed. */ - skb_shinfo(skb)->gso_type |= SKB_GSO_DODGY; - skb_shinfo(skb)->gso_segs = 0; + err = virtio_net_hdr_to_skb(skb, &gso, tun_is_little_endian(tun)); + if (err) { + this_cpu_inc(tun->pcpu_stats->rx_frame_errors); + kfree_skb(skb); + return -EINVAL; } /* copy skb_ubuf_info for callback when skb has no error */ @@ -1399,46 +1364,26 @@ static ssize_t tun_put_user(struct tun_struct *tun, if (vnet_hdr_sz) { struct virtio_net_hdr gso = { 0 }; /* no info leak */ + int ret; + if (iov_iter_count(iter) < vnet_hdr_sz) return -EINVAL; - if (skb_is_gso(skb)) { + ret = virtio_net_hdr_from_skb(skb, &gso, + tun_is_little_endian(tun)); + if (ret) { struct skb_shared_info *sinfo = skb_shinfo(skb); - - /* This is a hint as to how much should be linear. */ - gso.hdr_len = cpu_to_tun16(tun, skb_headlen(skb)); - gso.gso_size = cpu_to_tun16(tun, sinfo->gso_size); - if (sinfo->gso_type & SKB_GSO_TCPV4) - gso.gso_type = VIRTIO_NET_HDR_GSO_TCPV4; - else if (sinfo->gso_type & SKB_GSO_TCPV6) - gso.gso_type = VIRTIO_NET_HDR_GSO_TCPV6; - else if (sinfo->gso_type & SKB_GSO_UDP) - gso.gso_type = VIRTIO_NET_HDR_GSO_UDP; - else { - pr_err("unexpected GSO type: " - "0x%x, gso_size %d, hdr_len %d\n", - sinfo->gso_type, tun16_to_cpu(tun, gso.gso_size), - tun16_to_cpu(tun, gso.hdr_len)); - print_hex_dump(KERN_ERR, "tun: ", - DUMP_PREFIX_NONE, - 16, 1, skb->head, - min((int)tun16_to_cpu(tun, gso.hdr_len), 64), true); - WARN_ON_ONCE(1); - return -EINVAL; - } - if (sinfo->gso_type & SKB_GSO_TCP_ECN) - gso.gso_type |= VIRTIO_NET_HDR_GSO_ECN; -
[PATCH 5/6] virtio_net: use common code for virtio_net_hdr and skb GSO conversion
Replace open coded conversion between virtio_net_hdr to skb GSO info with virtio_net_hdr_{from,to}_skb Signed-off-by: Mike Rapoport --- drivers/net/virtio_net.c | 78 +++- 1 file changed, 10 insertions(+), 68 deletions(-) diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index e0638e5..9af0a98 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -479,51 +479,19 @@ static void receive_buf(struct virtnet_info *vi, struct receive_queue *rq, stats->rx_packets++; u64_stats_update_end(&stats->rx_syncp); - if (hdr->hdr.flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) { - pr_debug("Needs csum!\n"); - if (!skb_partial_csum_set(skb, - virtio16_to_cpu(vi->vdev, hdr->hdr.csum_start), - virtio16_to_cpu(vi->vdev, hdr->hdr.csum_offset))) - goto frame_err; - } else if (hdr->hdr.flags & VIRTIO_NET_HDR_F_DATA_VALID) { + if (hdr->hdr.flags & VIRTIO_NET_HDR_F_DATA_VALID) skb->ip_summed = CHECKSUM_UNNECESSARY; - } skb->protocol = eth_type_trans(skb, dev); pr_debug("Receiving skb proto 0x%04x len %i type %i\n", ntohs(skb->protocol), skb->len, skb->pkt_type); - if (hdr->hdr.gso_type != VIRTIO_NET_HDR_GSO_NONE) { - pr_debug("GSO!\n"); - switch (hdr->hdr.gso_type & ~VIRTIO_NET_HDR_GSO_ECN) { - case VIRTIO_NET_HDR_GSO_TCPV4: - skb_shinfo(skb)->gso_type = SKB_GSO_TCPV4; - break; - case VIRTIO_NET_HDR_GSO_UDP: - skb_shinfo(skb)->gso_type = SKB_GSO_UDP; - break; - case VIRTIO_NET_HDR_GSO_TCPV6: - skb_shinfo(skb)->gso_type = SKB_GSO_TCPV6; - break; - default: - net_warn_ratelimited("%s: bad gso type %u.\n", -dev->name, hdr->hdr.gso_type); - goto frame_err; - } - - if (hdr->hdr.gso_type & VIRTIO_NET_HDR_GSO_ECN) - skb_shinfo(skb)->gso_type |= SKB_GSO_TCP_ECN; - - skb_shinfo(skb)->gso_size = virtio16_to_cpu(vi->vdev, - hdr->hdr.gso_size); - if (skb_shinfo(skb)->gso_size == 0) { - net_warn_ratelimited("%s: zero gso size.\n", dev->name); - goto frame_err; - } - - /* Header must be checked, and gso_segs computed. */ - skb_shinfo(skb)->gso_type |= SKB_GSO_DODGY; - skb_shinfo(skb)->gso_segs = 0; + if (virtio_net_hdr_to_skb(skb, &hdr->hdr, + virtio_is_little_endian(vi->vdev))) { + net_warn_ratelimited("%s: bad gso: type: %u, size: %u\n", +dev->name, hdr->hdr.gso_type, +hdr->hdr.gso_size); + goto frame_err; } napi_gro_receive(&rq->napi, skb); @@ -868,35 +836,9 @@ static int xmit_skb(struct send_queue *sq, struct sk_buff *skb) else hdr = skb_vnet_hdr(skb); - if (skb->ip_summed == CHECKSUM_PARTIAL) { - hdr->hdr.flags = VIRTIO_NET_HDR_F_NEEDS_CSUM; - hdr->hdr.csum_start = cpu_to_virtio16(vi->vdev, - skb_checksum_start_offset(skb)); - hdr->hdr.csum_offset = cpu_to_virtio16(vi->vdev, -skb->csum_offset); - } else { - hdr->hdr.flags = 0; - hdr->hdr.csum_offset = hdr->hdr.csum_start = 0; - } - - if (skb_is_gso(skb)) { - hdr->hdr.hdr_len = cpu_to_virtio16(vi->vdev, skb_headlen(skb)); - hdr->hdr.gso_size = cpu_to_virtio16(vi->vdev, - skb_shinfo(skb)->gso_size); - if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV4) - hdr->hdr.gso_type = VIRTIO_NET_HDR_GSO_TCPV4; - else if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6) - hdr->hdr.gso_type = VIRTIO_NET_HDR_GSO_TCPV6; - else if (skb_shinfo(skb)->gso_type & SKB_GSO_UDP) - hdr->hdr.gso_type = VIRTIO_NET_HDR_GSO_UDP; - else - BUG(); - if (skb_shinfo(skb)->gso_type & SKB_GSO_TCP_ECN) - hdr->hdr.gso_type |= VIRTIO_NET_HDR_GSO_ECN; - } else { - hdr->hdr.gso_type = VIRTIO_NET_HDR_GSO_NONE; - hdr->hdr.gso_size = hdr->hdr.hdr_len = 0; - } + if (virtio_net_hdr_from_skb(skb, &hdr->hdr, + virtio_is_little_endian(vi->vdev))) +
Re: [GIT PULL 00/24] perf/core improvements and fixes
Em Wed, Jun 08, 2016 at 08:10:50AM +0900, Taeung Song escreveu: > I found something weird about perf/core branch on your repository. > (I don't know whether it is just my illusion or not) > > I can't pull new commits on top of perf-core-for-mingo-20160606 > by normal way as below I forgot to push perf/core, having pushed just perf-core-for-mingo-20160607, which is enough for Ingo to pull what I sent to him, but not for you to get if you use perf/core, as usual, instead of perf-core-for-mingo-20160607. I pushed perf/core now, please update your local repo and all should be ok now. - Arnaldo
[PATCH 3/6] macvtap: use common code for virtio_net_hdr and skb GSO conversion
Replace open coded conversion between virtio_net_hdr to skb GSO info with virtio_net_hdr_{from,to}_skb Signed-off-by: Mike Rapoport --- drivers/net/macvtap.c | 95 --- 1 file changed, 6 insertions(+), 89 deletions(-) diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c index bd67209..95a1332 100644 --- a/drivers/net/macvtap.c +++ b/drivers/net/macvtap.c @@ -627,93 +627,6 @@ static inline struct sk_buff *macvtap_alloc_skb(struct sock *sk, size_t prepad, return skb; } -/* - * macvtap_skb_from_vnet_hdr and macvtap_skb_to_vnet_hdr should - * be shared with the tun/tap driver. - */ -static int macvtap_skb_from_vnet_hdr(struct macvtap_queue *q, -struct sk_buff *skb, -struct virtio_net_hdr *vnet_hdr) -{ - unsigned short gso_type = 0; - if (vnet_hdr->gso_type != VIRTIO_NET_HDR_GSO_NONE) { - switch (vnet_hdr->gso_type & ~VIRTIO_NET_HDR_GSO_ECN) { - case VIRTIO_NET_HDR_GSO_TCPV4: - gso_type = SKB_GSO_TCPV4; - break; - case VIRTIO_NET_HDR_GSO_TCPV6: - gso_type = SKB_GSO_TCPV6; - break; - case VIRTIO_NET_HDR_GSO_UDP: - gso_type = SKB_GSO_UDP; - break; - default: - return -EINVAL; - } - - if (vnet_hdr->gso_type & VIRTIO_NET_HDR_GSO_ECN) - gso_type |= SKB_GSO_TCP_ECN; - - if (vnet_hdr->gso_size == 0) - return -EINVAL; - } - - if (vnet_hdr->flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) { - if (!skb_partial_csum_set(skb, macvtap16_to_cpu(q, vnet_hdr->csum_start), - macvtap16_to_cpu(q, vnet_hdr->csum_offset))) - return -EINVAL; - } - - if (vnet_hdr->gso_type != VIRTIO_NET_HDR_GSO_NONE) { - skb_shinfo(skb)->gso_size = macvtap16_to_cpu(q, vnet_hdr->gso_size); - skb_shinfo(skb)->gso_type = gso_type; - - /* Header must be checked, and gso_segs computed. */ - skb_shinfo(skb)->gso_type |= SKB_GSO_DODGY; - skb_shinfo(skb)->gso_segs = 0; - } - return 0; -} - -static void macvtap_skb_to_vnet_hdr(struct macvtap_queue *q, - const struct sk_buff *skb, - struct virtio_net_hdr *vnet_hdr) -{ - memset(vnet_hdr, 0, sizeof(*vnet_hdr)); - - if (skb_is_gso(skb)) { - struct skb_shared_info *sinfo = skb_shinfo(skb); - - /* This is a hint as to how much should be linear. */ - vnet_hdr->hdr_len = cpu_to_macvtap16(q, skb_headlen(skb)); - vnet_hdr->gso_size = cpu_to_macvtap16(q, sinfo->gso_size); - if (sinfo->gso_type & SKB_GSO_TCPV4) - vnet_hdr->gso_type = VIRTIO_NET_HDR_GSO_TCPV4; - else if (sinfo->gso_type & SKB_GSO_TCPV6) - vnet_hdr->gso_type = VIRTIO_NET_HDR_GSO_TCPV6; - else if (sinfo->gso_type & SKB_GSO_UDP) - vnet_hdr->gso_type = VIRTIO_NET_HDR_GSO_UDP; - else - BUG(); - if (sinfo->gso_type & SKB_GSO_TCP_ECN) - vnet_hdr->gso_type |= VIRTIO_NET_HDR_GSO_ECN; - } else - vnet_hdr->gso_type = VIRTIO_NET_HDR_GSO_NONE; - - if (skb->ip_summed == CHECKSUM_PARTIAL) { - vnet_hdr->flags = VIRTIO_NET_HDR_F_NEEDS_CSUM; - if (skb_vlan_tag_present(skb)) - vnet_hdr->csum_start = cpu_to_macvtap16(q, - skb_checksum_start_offset(skb) + VLAN_HLEN); - else - vnet_hdr->csum_start = cpu_to_macvtap16(q, - skb_checksum_start_offset(skb)); - vnet_hdr->csum_offset = cpu_to_macvtap16(q, skb->csum_offset); - } else if (skb->ip_summed == CHECKSUM_UNNECESSARY) { - vnet_hdr->flags = VIRTIO_NET_HDR_F_DATA_VALID; - } /* else everything is zero */ -} - /* Neighbour code has some assumptions on HH_DATA_MOD alignment */ #define MACVTAP_RESERVE HH_DATA_OFF(ETH_HLEN) @@ -812,7 +725,8 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m, skb->protocol = eth_hdr(skb)->h_proto; if (vnet_hdr_len) { - err = macvtap_skb_from_vnet_hdr(q, skb, &vnet_hdr); + err = virtio_net_hdr_to_skb(skb, &vnet_hdr, + macvtap_is_little_endian(q)); if (err) goto err_kfree; } @@ -880,7 +794,10 @@ static ssize_t macvtap_put_user(struct macvtap_queue *q, if (iov_iter_count(iter) < vne
[PATCH 6/6] packet: use common code for virtio_net_hdr and skb GSO conversion
Replace open coded conversion between virtio_net_hdr to skb GSO info with virtio_net_hdr_from_skb Signed-off-by: Mike Rapoport --- net/packet/af_packet.c | 36 ++-- 1 file changed, 2 insertions(+), 34 deletions(-) diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 4040eb9..ec35aa9 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -1978,40 +1978,8 @@ static int __packet_rcv_vnet(const struct sk_buff *skb, { *vnet_hdr = (const struct virtio_net_hdr) { 0 }; - if (skb_is_gso(skb)) { - struct skb_shared_info *sinfo = skb_shinfo(skb); - - /* This is a hint as to how much should be linear. */ - vnet_hdr->hdr_len = - __cpu_to_virtio16(vio_le(), skb_headlen(skb)); - vnet_hdr->gso_size = - __cpu_to_virtio16(vio_le(), sinfo->gso_size); - - if (sinfo->gso_type & SKB_GSO_TCPV4) - vnet_hdr->gso_type = VIRTIO_NET_HDR_GSO_TCPV4; - else if (sinfo->gso_type & SKB_GSO_TCPV6) - vnet_hdr->gso_type = VIRTIO_NET_HDR_GSO_TCPV6; - else if (sinfo->gso_type & SKB_GSO_UDP) - vnet_hdr->gso_type = VIRTIO_NET_HDR_GSO_UDP; - else if (sinfo->gso_type & SKB_GSO_FCOE) - return -EINVAL; - else - BUG(); - - if (sinfo->gso_type & SKB_GSO_TCP_ECN) - vnet_hdr->gso_type |= VIRTIO_NET_HDR_GSO_ECN; - } else - vnet_hdr->gso_type = VIRTIO_NET_HDR_GSO_NONE; - - if (skb->ip_summed == CHECKSUM_PARTIAL) { - vnet_hdr->flags = VIRTIO_NET_HDR_F_NEEDS_CSUM; - vnet_hdr->csum_start = __cpu_to_virtio16(vio_le(), - skb_checksum_start_offset(skb)); - vnet_hdr->csum_offset = __cpu_to_virtio16(vio_le(), -skb->csum_offset); - } else if (skb->ip_summed == CHECKSUM_UNNECESSARY) { - vnet_hdr->flags = VIRTIO_NET_HDR_F_DATA_VALID; - } /* else everything is zero */ + if (virtio_net_hdr_from_skb(skb, vnet_hdr, vio_le())) + BUG(); return 0; } -- 1.9.1
[PATCH 0/6] virtio_net: use common code for virtio_net_hdr and skb GSO conversion
Hi, This patches introduce virtio_net_hdr_{from,to}_skb functions for conversion of GSO information between skb and virtio_net_hdr. Mike Rapoport (6): virtio_net: add _UAPI prefix to virtio_net header guards virtio_net: introduce virtio_net_hdr_{from,to}_skb macvtap: use common code for virtio_net_hdr and skb GSO conversion tuntap: use common code for virtio_net_hdr and skb GSO conversion virtio_net: use common code for virtio_net_hdr and skb GSO conversion packet: use common code for virtio_net_hdr and skb GSO conversion drivers/net/macvtap.c | 95 +++-- drivers/net/tun.c | 97 +- drivers/net/virtio_net.c| 78 --- include/linux/virtio_net.h | 101 include/uapi/linux/virtio_net.h | 6 +-- net/packet/af_packet.c | 36 +- 6 files changed, 143 insertions(+), 270 deletions(-) create mode 100644 include/linux/virtio_net.h -- 1.9.1
Re: [PATCH] kernel/sysrq: reset watchdog on all CPUs while processing sysrq-w
* Andrey Ryabinin wrote: > Lengthy output of sysrq-w may take a lot of time on slow serial console. > Currently we reset NMI-watchdog on the current CPU to avoid softlockup. > Sometimes this doesn't work since watchdog might trigger on the other > CPU which is waiting for an IPI to proceed. > > Reset watchdog on all CPUs to prevent spurious softlockup messages. > > Signed-off-by: Andrey Ryabinin > --- > kernel/sched/core.c | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/kernel/sched/core.c b/kernel/sched/core.c > index 7f2cae4..c135eee 100644 > --- a/kernel/sched/core.c > +++ b/kernel/sched/core.c > @@ -5134,7 +5134,7 @@ void show_state_filter(unsigned long state_filter) >* reset the NMI-timeout, listing all files on a slow >* console might take a lot of time: >*/ > - touch_nmi_watchdog(); > + touch_all_softlockup_watchdogs(); So don't we want both? Thanks, Ingo
Re: NVMe over Fabrics target implementation
*) Extensible to multiple types of backend drivers. nvme-target needs a way to absorb new backend drivers, that does not effect existing configfs group layout or attributes. Looking at the nvmet/configfs layout as-is, there are no multiple backend types defined, nor a way to control backend feature bits exposed to nvme namespaces at runtime. Hey Nic, As for different type of backends, I still don't see a big justification for adding the LIO backends pscsi (as it doesn't make sense), ramdisk (we have brd), or file (losetup). What kind of feature bits would you want to expose at runtime? And that's very much intentional. We have a very well working block layer which we're going to use, no need to reivent it. The block layer supports NVMe pass through just fine in case we'll need it, as I spent the last year preparing it for that. Why does it ever make sense for $SUBSYSTEM_NQN_0 with $PORT_DRIVER_FOO to block operation of $SUBSYSTEM_NQN_1 with $PORT_DRIVER_BAR..? Because it keeps the code simple. If you had actually participated on our development list you might have seen that until not too long ago we have very fine grainded locks here. In the end Armen convinced me that it's easier to maintain if we don't bother with fine grained locking outside the fast path, especially as it significantly simplifies the discovery implementation. If if it ever turns out to be an issue we can change it easily as the implementation is well encapsulated. We did change that, and Nic is raising a valid point in terms of having a global mutex around all the ports. If the requirement of nvme subsystems and ports configuration is that it should happen fast enough and scale to the numbers that Nic is referring to, we'll need to change that back. Having said that, I'm not sure this is a real hard requirement for RDMA and FC in the mid-term, because from what I've seen, the workloads Nic is referring to are more typical for iscsi/tcp where connections are cheaper and you need more to saturate a high-speed interconnects, so we'll probably see this when we have nvme over tcp working.
[PATCH 2/6] virtio_net: introduce virtio_net_hdr_{from,to}_skb
The code for conversion between virtio_net_hdr and skb GSO info is duplicated at several places. Let's put it to a common place to allow reuse. Signed-off-by: Mike Rapoport --- include/linux/virtio_net.h | 101 + 1 file changed, 101 insertions(+) create mode 100644 include/linux/virtio_net.h diff --git a/include/linux/virtio_net.h b/include/linux/virtio_net.h new file mode 100644 index 000..1c912f8 --- /dev/null +++ b/include/linux/virtio_net.h @@ -0,0 +1,101 @@ +#ifndef _LINUX_VIRTIO_NET_H +#define _LINUX_VIRTIO_NET_H + +#include +#include + +static inline int virtio_net_hdr_to_skb(struct sk_buff *skb, + const struct virtio_net_hdr *hdr, + bool little_endian) +{ + unsigned short gso_type = 0; + + if (hdr->gso_type != VIRTIO_NET_HDR_GSO_NONE) { + switch (hdr->gso_type & ~VIRTIO_NET_HDR_GSO_ECN) { + case VIRTIO_NET_HDR_GSO_TCPV4: + gso_type = SKB_GSO_TCPV4; + break; + case VIRTIO_NET_HDR_GSO_TCPV6: + gso_type = SKB_GSO_TCPV6; + break; + case VIRTIO_NET_HDR_GSO_UDP: + gso_type = SKB_GSO_UDP; + break; + default: + return -EINVAL; + } + + if (hdr->gso_type & VIRTIO_NET_HDR_GSO_ECN) + gso_type |= SKB_GSO_TCP_ECN; + + if (hdr->gso_size == 0) + return -EINVAL; + } + + if (hdr->flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) { + u16 start = __virtio16_to_cpu(little_endian, hdr->csum_start); + u16 off = __virtio16_to_cpu(little_endian, hdr->csum_offset); + + if (!skb_partial_csum_set(skb, start, off)) + return -EINVAL; + } + + if (hdr->gso_type != VIRTIO_NET_HDR_GSO_NONE) { + u16 gso_size = __virtio16_to_cpu(little_endian, hdr->gso_size); + + skb_shinfo(skb)->gso_size = gso_size; + skb_shinfo(skb)->gso_type = gso_type; + + /* Header must be checked, and gso_segs computed. */ + skb_shinfo(skb)->gso_type |= SKB_GSO_DODGY; + skb_shinfo(skb)->gso_segs = 0; + } + + return 0; +} + +static inline int virtio_net_hdr_from_skb(const struct sk_buff *skb, + struct virtio_net_hdr *hdr, + bool little_endian) +{ + memset(hdr, 0, sizeof(*hdr)); + + if (skb_is_gso(skb)) { + struct skb_shared_info *sinfo = skb_shinfo(skb); + + /* This is a hint as to how much should be linear. */ + hdr->hdr_len = __cpu_to_virtio16(little_endian, +skb_headlen(skb)); + hdr->gso_size = __cpu_to_virtio16(little_endian, + sinfo->gso_size); + if (sinfo->gso_type & SKB_GSO_TCPV4) + hdr->gso_type = VIRTIO_NET_HDR_GSO_TCPV4; + else if (sinfo->gso_type & SKB_GSO_TCPV6) + hdr->gso_type = VIRTIO_NET_HDR_GSO_TCPV6; + else if (sinfo->gso_type & SKB_GSO_UDP) + hdr->gso_type = VIRTIO_NET_HDR_GSO_UDP; + else + return -EINVAL; + if (sinfo->gso_type & SKB_GSO_TCP_ECN) + hdr->gso_type |= VIRTIO_NET_HDR_GSO_ECN; + } else + hdr->gso_type = VIRTIO_NET_HDR_GSO_NONE; + + if (skb->ip_summed == CHECKSUM_PARTIAL) { + hdr->flags = VIRTIO_NET_HDR_F_NEEDS_CSUM; + if (skb_vlan_tag_present(skb)) + hdr->csum_start = __cpu_to_virtio16(little_endian, + skb_checksum_start_offset(skb) + VLAN_HLEN); + else + hdr->csum_start = __cpu_to_virtio16(little_endian, + skb_checksum_start_offset(skb)); + hdr->csum_offset = __cpu_to_virtio16(little_endian, + skb->csum_offset); + } else if (skb->ip_summed == CHECKSUM_UNNECESSARY) { + hdr->flags = VIRTIO_NET_HDR_F_DATA_VALID; + } /* else everything is zero */ + + return 0; +} + +#endif /* _LINUX_VIRTIO_BYTEORDER */ -- 1.9.1
Re: [RFC][PATCH 2/6] staging: android: ion: Switch to using an idr to manage heaps
On Mon, Jun 06, 2016 at 11:23:29AM -0700, Laura Abbott wrote: > From: Laura Abbott > > > In anticipation of dynamic registration of heaps, switch to using > an idr for heaps. The idr makes it easier to control the assignment > and management + lookup of heap numbers. > > Signed-off-by: Laura Abbott > --- > drivers/staging/android/ion/ion.c | 83 > +-- > 1 file changed, 53 insertions(+), 30 deletions(-) > > diff --git a/drivers/staging/android/ion/ion.c > b/drivers/staging/android/ion/ion.c > index 306340a..739060f 100644 > --- a/drivers/staging/android/ion/ion.c > +++ b/drivers/staging/android/ion/ion.c > @@ -55,13 +55,14 @@ struct ion_device { > struct rb_root buffers; > struct mutex buffer_lock; > struct rw_semaphore lock; > - struct plist_head heaps; > long (*custom_ioctl)(struct ion_client *client, unsigned int cmd, >unsigned long arg); > struct rb_root clients; > struct dentry *debug_root; > struct dentry *heaps_debug_root; > struct dentry *clients_debug_root; > + struct idr idr; > + int heap_cnt; > }; > > /** > @@ -488,39 +489,22 @@ static int ion_handle_add(struct ion_client *client, > struct ion_handle *handle) > return 0; > } > > -struct ion_handle *ion_alloc(struct ion_client *client, size_t len, > - size_t align, unsigned int heap_id_mask, > +static struct ion_handle *__ion_alloc(struct ion_client *client, size_t len, > + size_t align, struct ion_heap *heap, >unsigned int flags) > { > struct ion_handle *handle; > struct ion_device *dev = client->dev; > struct ion_buffer *buffer = NULL; > - struct ion_heap *heap; > int ret; > > - pr_debug("%s: len %zu align %zu heap_id_mask %u flags %x\n", __func__, > - len, align, heap_id_mask, flags); > - /* > - * traverse the list of heaps available in this system in priority > - * order. If the heap type is supported by the client, and matches the > - * request of the caller allocate from it. Repeat until allocate has > - * succeeded or all heaps have been tried > - */ > + Drop the (second) empty line here. > len = PAGE_ALIGN(len); > > if (!len) > return ERR_PTR(-EINVAL); > > - down_read(&dev->lock); > - plist_for_each_entry(heap, &dev->heaps, node) { > - /* if the caller didn't specify this heap id */ > - if (!((1 << heap->id) & heap_id_mask)) > - continue; > - buffer = ion_buffer_create(heap, dev, len, align, flags); > - if (!IS_ERR(buffer)) > - break; > - } > - up_read(&dev->lock); > + buffer = ion_buffer_create(heap, dev, len, align, flags); > > if (buffer == NULL) > return ERR_PTR(-ENODEV); > @@ -549,6 +533,41 @@ struct ion_handle *ion_alloc(struct ion_client *client, > size_t len, > > return handle; > } > + > +struct ion_handle *ion_alloc(struct ion_client *client, size_t len, > + size_t align, unsigned int heap_mask, > + unsigned int flags) > +{ > + int bit; > + struct ion_handle *handle = ERR_PTR(-ENODEV); > + > + pr_debug("%s: len %zu align %zu heap_id_mask %u flags %x\n", __func__, > + len, align, heap_mask, flags); > + > + down_read(&client->dev->lock); > + /* > + * traverse the list of heaps available in this system in priority > + * order. If the heap type is supported by the client, and matches the > + * request of the caller allocate from it. Repeat until allocate has > + * succeeded or all heaps have been tried > + */ > + for_each_set_bit(bit, (unsigned long *)&heap_mask, 32) { > + struct ion_heap *heap; > + > + heap = idr_find(&client->dev->idr, bit); > + if (!heap) > + continue; > + > + handle = __ion_alloc(client, len, align, heap, flags); > + if (IS_ERR(handle)) > + continue; > + else > + break; > + } > + > + up_read(&client->dev->lock); > + return handle; > +} > EXPORT_SYMBOL(ion_alloc); > > static void ion_free_nolock(struct ion_client *client, struct ion_handle > *handle) > @@ -1587,6 +1606,7 @@ DEFINE_SIMPLE_ATTRIBUTE(debug_shrink_fops, > debug_shrink_get, > int ion_device_add_heap(struct ion_device *dev, struct ion_heap *heap) > { > struct dentry *debug_file; > + int ret; > > if (!heap->ops->allocate || !heap->ops->free || !heap->ops->map_dma || > !heap->ops->unmap_dma) { > @@ -1606,12 +1626,15 @@ int ion_device_add_heap(struct ion_device *dev, > struct ion_heap *heap) > > heap->dev = dev; > down_write(&dev->lock); > - /* > - * use negative heap->id
Re: [PATCH 2/2] sched/debug: fix deadlock when enabling sched events
On Wed, Jun 08, 2016 at 09:56:12AM +0200, Ingo Molnar wrote: > > * Josh Poimboeuf wrote: > > > --- a/kernel/sched/fair.c > > +++ b/kernel/sched/fair.c > > @@ -789,6 +789,13 @@ static void update_curr_fair(struct rq *rq) > > update_curr(cfs_rq_of(&rq->curr->se)); > > } > > > > +void trace_sched_stat_register(void) > > +{ > > +#ifdef CONFIG_SCHEDSTATS > > + force_schedstat_enabled(); > > +#endif > > +} > > I think it would be cleaner to provide an empty force_schedstat_enabled() > definition in sched.h, on !CONFIG_SCHEDSTATS. Yes, agreed. > But it might make sense to further decouple schedstats from tracing? Looking at how we could do that: - The sched_stat_wait tracepoint is dependent on the wait_start schedstat. - The sched_stat_sleep tracepoint is dependent on the sleep_start schedstat. - The sched_stat_iowait and sched_stat_blocked tracepoints are dependent on the block_start schedstat. We could move those three schedstats values out of sched_statistics and into sched_entity, and then always update them regardless of CONFIG_SCHEDSTATS. That would ensure these tracepoints always work. But then again it would add a little bit of runtime overhead. I don't have a strong opinion either way. Thoughts? -- Josh
Re: [PATCH 2/2] sched/debug: fix deadlock when enabling sched events
* Josh Poimboeuf wrote: > On Wed, Jun 08, 2016 at 09:56:12AM +0200, Ingo Molnar wrote: > > > > * Josh Poimboeuf wrote: > > > > > --- a/kernel/sched/fair.c > > > +++ b/kernel/sched/fair.c > > > @@ -789,6 +789,13 @@ static void update_curr_fair(struct rq *rq) > > > update_curr(cfs_rq_of(&rq->curr->se)); > > > } > > > > > > +void trace_sched_stat_register(void) > > > +{ > > > +#ifdef CONFIG_SCHEDSTATS > > > + force_schedstat_enabled(); > > > +#endif > > > +} > > > > I think it would be cleaner to provide an empty force_schedstat_enabled() > > definition in sched.h, on !CONFIG_SCHEDSTATS. > > Yes, agreed. > > > But it might make sense to further decouple schedstats from tracing? > > Looking at how we could do that: > > - The sched_stat_wait tracepoint is dependent on the wait_start schedstat. Can we maintain wait_start unconditionally? Having config dependent tracepoints sucks. > - The sched_stat_sleep tracepoint is dependent on the sleep_start > schedstat. Ditto. > - The sched_stat_iowait and sched_stat_blocked tracepoints are dependent > on the block_start schedstat. Ditto. > We could move those three schedstats values out of sched_statistics and > into sched_entity, and then always update them regardless of > CONFIG_SCHEDSTATS. > > That would ensure these tracepoints always work. But then again it > would add a little bit of runtime overhead. > > I don't have a strong opinion either way. Thoughts? Please do a before/after 'size vmlinux' dump of a defconfig build with tracing disabled. I.e. how much code overhead does the updating of those variables add? Thanks, Ingo
Re: [PATCH] watchdog: max77620: Add support for watchdog timer
On 06/08/2016 01:58 AM, Laxman Dewangan wrote: Hi Guenter, Thanks for quick review. I will take care of most of comment. I have one query fr following comment. Thanks, Laxman On Tuesday 07 June 2016 11:26 PM, Guenter Roeck wrote: Hi, On Mon, Jun 06, 2016 at 05:22:44PM +0530, Laxman Dewangan wrote: +/* Stop watchodog */ +ret = regmap_update_bits(wdt->rmap, MAX77620_REG_CNFGGLBL2, + MAX77620_WDTEN, 0); +if (ret < 0) { +dev_err(wdt->dev, "Failed to reset WDTEN: %d\n", ret); +return ret; +} Alternatively, you could set WDOG_HW_RUNNING to tell the watchdog core that the watchdog is already running. The watchdog core would then ping the watchdog until the watchdog device is opened. That would also require to tell the watchdog core about the current (or default) timeout, which doesn't seem to be set anywhere. That means it won't be set at all unless user space updates it explicitly. This is quite unusual. Is it on purpose or an oversight ? If it is on purpose, please explain. OK, we have use cases where we have enabled the WDT in BL also. and keep runnign till kernel up. Instead of stopping WDT, I can say that WDOG_HW_RUNING and current timeout can be read from the register. Now, the WDT need to be ping periodically. Is there any flag which enabled the worker thread from core which will keep pinging till user space alive and activate the WDT? The watchdog core will start the worker if WDOG_HW_RUNNING is set. Guenter
Re: [PATCH V8 7/9] acpi: Add generic MCFG table handling
On Wed, Jun 08, 2016 at 02:21:30PM +0200, Tomasz Nowicki wrote: > On 08.06.2016 03:56, Bjorn Helgaas wrote: > >On Mon, May 30, 2016 at 05:14:20PM +0200, Tomasz Nowicki wrote: > >>In order to handle PCI config space regions properly in ACPI, new MCFG > >>interface is defined which does sanity checks on MCFG table and keeps its > >>root pointer. The user is able to lookup MCFG regions based on > >>host bridge root structure and domain:bus_start:bus_end touple. > >>Use pci_mmcfg_late_init old prototype to avoid another function name. > >>+ /* found matching entry, bus range check */ > >>+ if (entry->end_bus_number != bus_res->end) { > >>+ resource_size_t bus_end = min_t(resource_size_t, > >>+ entry->end_bus_number, bus_res->end); > >>+ pr_warn("%04x:%pR bus end mismatch, using %02lx\n", > >>+ root->segment, bus_res, (unsigned long)bus_end); > >>+ bus_res->end = bus_end; > >>+ } > > What about bus end mismatch case? Should we trim the host bridge bus > range or expect MCFG entry covers that range? Sometimes we get > _BBN-0xFF bus range, not from _CRS. Lack of a bus range in _CRS is a firmware defect. There's a comment about this in acpi_pci_root_add(). On x86, we probably had to live with firmware in the field that had this defect. I think we should expect all ARM64 systems to provide a bus number range in _CRS, and fail the attach if it's not there. I don't think we should warn about an MCFG entry that covers more than the _CRS bus range. On x86, it's common to have something like: ACPI: PCI Root Bridge [PCI0] (domain [bus 00-7f]) ACPI: PCI Root Bridge [PCI1] (domain [bus 80-ff]) with a single MCFG entry that covers [bus 00-ff]. That seems reasonable and I don't think it's worth warning about it. If the MCFG entry doesn't cover all of a _CRS bus range, we should just fail so we can find and fix broken firmware. > >>+/* Interface called by ACPI - parse and save MCFG table */ > > > >I think we save a *pointer* to the MCFG table, not the table itself. > > Right, the comment is broken. > > >And acpi_table_parse() calls early_acpi_os_unmap_memory() immediately > >after it calls pci_mcfg_parse(), so I'm doubtful that the pointer > >remains valid. > > At this stage early_acpi_os_unmap_memory() is doing nothing since > acpi_early_init() set acpi_gbl_permanent_mmap to 1 way before. The > pointer is fine then. Hmmm... I see your argument, but this is a problem waiting to happen. We should not depend on the internal implementation of early_acpi_os_unmap_memory(). The pattern of: y = x; unmap(x); z = *y; is just broken and we shouldn't expect readers to recognize that "oh, unmap() isn't really unmapping anything in this special case, so this looks wrong but is really fine." Bjorn
Re: [PATCH 09/10] mm: only count actual rotations as LRU reclaim cost
On Mon 06-06-16 15:48:35, Johannes Weiner wrote: > Noting a reference on an active file page but still deactivating it > represents a smaller cost of reclaim than noting a referenced > anonymous page and actually physically rotating it back to the head. > The file page *might* refault later on, but it's definite progress > toward freeing pages, whereas rotating the anonymous page costs us > real time without making progress toward the reclaim goal. > > Don't treat both events as equal. The following patch will hook up LRU > balancing to cache and swap refaults, which are a much more concrete > cost signal for reclaiming one list over the other. Remove the > maybe-IO cost bias from page references, and only note the CPU cost > for actual rotations that prevent the pages from getting reclaimed. The changelog was quite hard to digest for me but I guess I got your point. The change itself makes sense to me because noting the LRU cost for pages which we intentionally keep on the active list because they are really precious is reasonable. Which is not the case for referenced pages in general because we only find out whether they are really needed when we encounter them on the inactive list. > Signed-off-by: Johannes Weiner Acked-by: Michal Hocko > --- > mm/vmscan.c | 8 +++- > 1 file changed, 3 insertions(+), 5 deletions(-) > > diff --git a/mm/vmscan.c b/mm/vmscan.c > index 06e381e1004c..acbd212eab6e 100644 > --- a/mm/vmscan.c > +++ b/mm/vmscan.c > @@ -1821,7 +1821,6 @@ static void shrink_active_list(unsigned long nr_to_scan, > > if (page_referenced(page, 0, sc->target_mem_cgroup, > &vm_flags)) { > - nr_rotated += hpage_nr_pages(page); > /* >* Identify referenced, file-backed active pages and >* give them one more trip around the active list. So > @@ -1832,6 +1831,7 @@ static void shrink_active_list(unsigned long nr_to_scan, >* so we ignore them here. >*/ > if ((vm_flags & VM_EXEC) && page_is_file_cache(page)) { > + nr_rotated += hpage_nr_pages(page); > list_add(&page->lru, &l_active); > continue; > } > @@ -1846,10 +1846,8 @@ static void shrink_active_list(unsigned long > nr_to_scan, >*/ > spin_lock_irq(&zone->lru_lock); > /* > - * Count referenced pages from currently used mappings as rotated, > - * even though only some of them are actually re-activated. This > - * helps balance scan pressure between file and anonymous pages in > - * get_scan_count. > + * Rotating pages costs CPU without actually > + * progressing toward the reclaim goal. >*/ > lru_note_cost(lruvec, file, nr_rotated); > > -- > 2.8.3 -- Michal Hocko SUSE Labs
Re: [RFC][PATCH 4/6] staging: android: ion: Pull out ion ioctls to a separate file
On Mon, Jun 06, 2016 at 11:23:31AM -0700, Laura Abbott wrote: > > The number of Ion ioctls may continue to grow along with necessary > validation. Pull it out into a separate file for easier management > and review. > > Signed-off-by: Laura Abbott Reviewed-by: Liviu Dudau > --- > drivers/staging/android/ion/Makefile| 3 +- > drivers/staging/android/ion/ion-ioctl.c | 144 ++ > drivers/staging/android/ion/ion.c | 208 > +--- > drivers/staging/android/ion/ion_priv.h | 92 ++ > 4 files changed, 244 insertions(+), 203 deletions(-) > create mode 100644 drivers/staging/android/ion/ion-ioctl.c > > diff --git a/drivers/staging/android/ion/Makefile > b/drivers/staging/android/ion/Makefile > index 18cc2aa..376c2b2 100644 > --- a/drivers/staging/android/ion/Makefile > +++ b/drivers/staging/android/ion/Makefile > @@ -1,4 +1,5 @@ > -obj-$(CONFIG_ION) += ion.o ion_heap.o ion_page_pool.o ion_system_heap.o \ > +obj-$(CONFIG_ION) += ion.o ion-ioctl.o ion_heap.o \ > + ion_page_pool.o ion_system_heap.o \ > ion_carveout_heap.o ion_chunk_heap.o ion_cma_heap.o > obj-$(CONFIG_ION_TEST) += ion_test.o > ifdef CONFIG_COMPAT > diff --git a/drivers/staging/android/ion/ion-ioctl.c > b/drivers/staging/android/ion/ion-ioctl.c > new file mode 100644 > index 000..341ba7d > --- /dev/null > +++ b/drivers/staging/android/ion/ion-ioctl.c > @@ -0,0 +1,144 @@ > +/* > + * > + * Copyright (C) 2011 Google, Inc. > + * > + * This software is licensed under the terms of the GNU General Public > + * License version 2, as published by the Free Software Foundation, and > + * may be copied, distributed, and modified under those terms. > + * > + * 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 > +#include > +#include > + > +#include "ion.h" > +#include "ion_priv.h" > +#include "compat_ion.h" > + > +/* fix up the cases where the ioctl direction bits are incorrect */ > +static unsigned int ion_ioctl_dir(unsigned int cmd) > +{ > + switch (cmd) { > + case ION_IOC_SYNC: > + case ION_IOC_FREE: > + case ION_IOC_CUSTOM: > + return _IOC_WRITE; > + default: > + return _IOC_DIR(cmd); > + } > +} > + > +long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) > +{ > + struct ion_client *client = filp->private_data; > + struct ion_device *dev = client->dev; > + struct ion_handle *cleanup_handle = NULL; > + int ret = 0; > + unsigned int dir; > + > + union { > + struct ion_fd_data fd; > + struct ion_allocation_data allocation; > + struct ion_handle_data handle; > + struct ion_custom_data custom; > + } data; > + > + dir = ion_ioctl_dir(cmd); > + > + if (_IOC_SIZE(cmd) > sizeof(data)) > + return -EINVAL; > + > + if (dir & _IOC_WRITE) > + if (copy_from_user(&data, (void __user *)arg, _IOC_SIZE(cmd))) > + return -EFAULT; > + > + switch (cmd) { > + case ION_IOC_ALLOC: > + { > + struct ion_handle *handle; > + > + handle = ion_alloc(client, data.allocation.len, > + data.allocation.align, > + data.allocation.heap_id_mask, > + data.allocation.flags); > + if (IS_ERR(handle)) > + return PTR_ERR(handle); > + > + data.allocation.handle = handle->id; > + > + cleanup_handle = handle; > + break; > + } > + case ION_IOC_FREE: > + { > + struct ion_handle *handle; > + > + mutex_lock(&client->lock); > + handle = ion_handle_get_by_id_nolock(client, > data.handle.handle); > + if (IS_ERR(handle)) { > + mutex_unlock(&client->lock); > + return PTR_ERR(handle); > + } > + ion_free_nolock(client, handle); > + ion_handle_put_nolock(handle); > + mutex_unlock(&client->lock); > + break; > + } > + case ION_IOC_SHARE: > + case ION_IOC_MAP: > + { > + struct ion_handle *handle; > + > + handle = ion_handle_get_by_id(client, data.handle.handle); > + if (IS_ERR(handle)) > + return PTR_ERR(handle); > + data.fd.fd = ion_share_dma_buf_fd(client, handle); > + ion_handle_put(handle); > + if (data.fd.fd < 0) > + ret = data.fd.fd; > + break; > + } > + case ION_IOC_IMPORT: > + { > + struct ion_handle *
Re: [PATCH V8 5/9] pci, acpi: add acpi hook to assign domain number.
On Wed, Jun 08, 2016 at 12:21:19PM +0200, Tomasz Nowicki wrote: > On 08.06.2016 02:15, Bjorn Helgaas wrote: > >On Mon, May 30, 2016 at 05:14:18PM +0200, Tomasz Nowicki wrote: > >>PCI core code provides a config option (CONFIG_PCI_DOMAINS_GENERIC) > >>that allows assigning the PCI bus domain number generically by > >>relying on device tree bindings, and falling back to a simple counter > >>when the respective DT properties (ie "linux,pci-domain") are not > >>specified in the host bridge device tree node. > >> > >>In a similar way, when a system is booted through ACPI, architectures > >>that are selecting CONFIG_PCI_DOMAINS_GENERIC (ie ARM64) require kernel > >>hooks to retrieve the domain number so that the PCI bus domain number > >>set-up can be handled seamlessly with DT and ACPI in generic core code > >>when CONFIG_PCI_DOMAINS_GENERIC is selected. > >> > >>Since currently it is not possible to retrieve a pointer to the PCI > >>host bridge ACPI device backing the host bridge from core PCI code > >>(which would allow retrieving the domain number in an arch agnostic > >>way through the ACPI _SEG method), an arch specific ACPI hook has to > >>be declared and implemented by all arches that rely on > >>CONFIG_PCI_DOMAINS_GENERIC to retrieve the domain number and set it > >>up in core PCI code. > >> > >>For the aforementioned reasons, this patch introduces a dummy > >>acpi_pci_bus_domain_nr() hook in preparation for per-arch implementation > >>of the same to retrieve the domain number on a per-arch basis when > >>the system boots through ACPI. > >> > >>For the sake of code clarity the current code implementing generic > >>domain number assignment (ie pci_bus_assign_domain_nr(), selected by > >>CONFIG_PCI_DOMAINS_GENERIC) is reshuffled so that the code implementing > >>the DT domain assignment function is stubbed out into a corresponding > >>helper, so that DT and ACPI functions are clearly separated in > >>preparation for arches acpi_pci_bus_domain_nr() implementations. > >> > >>Signed-off-by: Tomasz Nowicki > >>Signed-off-by: Lorenzo Pieralisi > >>--- > >> drivers/pci/pci.c | 11 +-- > >> include/linux/pci.h | 1 + > >> 2 files changed, 10 insertions(+), 2 deletions(-) > >> > >>diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c > >>index eb431b5..2b52178 100644 > >>--- a/drivers/pci/pci.c > >>+++ b/drivers/pci/pci.c > >>@@ -7,6 +7,7 @@ > >> *Copyright 1997 -- 2000 Martin Mares > >> */ > >> > >>+#include > >> #include > >> #include > >> #include > >>@@ -4941,7 +4942,7 @@ int pci_get_new_domain_nr(void) > >> } > >> > >> #ifdef CONFIG_PCI_DOMAINS_GENERIC > >>-void pci_bus_assign_domain_nr(struct pci_bus *bus, struct device *parent) > >>+static int of_pci_bus_domain_nr(struct device *parent) > > > >Can we do a little cleanup before this patch? > > > > - pci_bus_assign_domain_nr() is only used inside drivers/pci, so > > maybe we move the prototype to drivers/pci/pci.h? > > pci_bus_assign_domain_nr() goes with pci_domain_nr() as an option > for CONFIG_PCI_DOMAINS_GENERIC. pci_domain_nr() is used commonly > outside drivers/pci so we would need to split these calls then, thus > personally I think it would be better to keep both in > inclue/linux/pci.h OK. > > - I don't really like the style of calling a function that > > internally assigns bus->domain_nr. Could we do something like > > this instead? > > > > int pci_bus_domain_nr(...) > > { > > ... > > return domain; > > } > > > > ... pci_create_root_bus(...) > > { > > ... > > b->domain_nr = pci_bus_domain_nr(...); > > > We can. I do not see much difference between pci_bus_domain_nr() and > pci_domain_nr() which we already have so how about calling it > pci_bus_find_domain_nr instead? Lorenzo, any strong preference for > it? I suggested that to make them all parallel: pci_bus_domain_nr() of_pci_bus_domain_nr() acpi_pci_bus_domain_nr() If you want to make them all *pci_bus_find_domain_nr() that would be OK with me, but I think it is worth keeping them the same except for the prefix (none/"of_"/"acpi_"). I think that's what you suggested below. > >That would be two new patches, if this makes sense. > > > >And this patch would only rename pci_bus_assign_domain_nr() to > >of_pci_bus_domain_nr() and add the pci_bus_domain_nr() wrapper. > > Giving that we would keep prototypes in inclue/linux/pci.h > > 1. First patch would rename pci_bus_assign_domain_nr() to > pci_bus_find_domain_nr() and it would return domain number so that > we could do: > ... pci_create_root_bus(...) > { >... >b->domain_nr = pci_bus_domain_nr(...); >... > } > > 2. Second patch would transform pci_bus_find_domain_nr() to be the > wrapper for of_pci_bus_domain_nr() > > 3. Third patch would add stub definition, the ARM64 definition and > the new call acpi_pci_bus_domain_nr() in pci_bus_find_domain_nr() > wrapper. > > Does this plan sound reasonable? S
Re: dell-smm-hwmon: security problems
On 06/08/2016 02:57 AM, Pali Rohár wrote: Hello! Mario wrote me about two I think security problems in dell-smm-hwmon driver and I would like to ask you, how to fix them. 1) File /proc/i8k (exists only when kernel is compiled with CONFIG_I8K) exports DMI_PRODUCT_SERIAL and it can be read by ordinary user, without root permission. Normally DMI_PRODUCT_SERIAL can be read from sysfs file /sys/class/dmi/id/product_serial but only by root user. 2) Via /proc/i8k ordinary user can set fan speed. This is because how "restricted" parameter and variable works. Setting fan speed by normal non-root user can be dangerous, e.g. malicious application under user "nobody" could take control of fans. Do you have idea how to fix these problems? Just to note that /proc/i8k has stable kernel ABI and changing it will break all existing i8k* applications. But /proc/i8k is there only for old legacy laptops (year 2000). There is module parameter "restricted" with default value false and description: "Allow fan control if SYS_ADMIN capability set". Current code do: case I8K_SET_FAN: if (restricted && !capable(CAP_SYS_ADMIN)) return -EPERM; For me description is a bit ambiguous. What about setting "restricted" by default to true and updating description to something like this? "Disallow fan control when SYS_ADMIN capability is not set (default: 1)" Sure. I am sure that someone will complain (we learned just recently that people still use the old commands, after all), but then the old behavior can be restored by setting the flag to 0. I would not use a double negative to describe it. Why not just something like "Allow fan control only if SYS_ADMIN capability set (default 1)" ? Guenter
[PATCH v2] futex: Calculate the futex key based on a tail page for file-based futexes
Mike Galbraith reported that the LTP test case futex_wake04 was broken by commit 65d8fc777f6d ("futex: Remove requirement for lock_page() in get_futex_key()"). This test case uses futexes backed by hugetlbfs pages and so there is an associated inode with a futex stored on such pages. The problem is that the key is being calculated based on the head page index of the hugetlbfs page and not the tail page. Prior to the optimisation, the page lock was used to stabilise mappings and pin the inode is file-backed which is overkill. If the page was a compound page, the head page was automatically looked up as part of the page lock operation but the tail page index was used to calculate the futex key. After the optimisation, the compound head is looked up early and the page lock is only relied upon to identify truncated pages, special pages or a shmem page moving to swapcache. The head page is looked up because without the page lock, special care has to be taken to pin the inode correctly. However, the tail page is still required to calculate the futex key so this patch records the tail page. On vanilla 4.6, the output of the test case is; futex_wake040 TINFO : Hugepagesize 2097152 futex_wake041 TFAIL : futex_wake04.c:126: Bug: wait_thread2 did not wake after 30 secs. With the patch applied futex_wake040 TINFO : Hugepagesize 2097152 futex_wake041 TPASS : Hi hydra, thread2 awake! Cc: sta...@vger.kernel.org # 4.6+ Reported-and-tested-by: Mike Galbraith Signed-off-by: Mel Gorman Acked-by: Peter Zijlstra (Intel) Reviewed-by: Davidlohr Bueso --- kernel/futex.c | 14 +++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/kernel/futex.c b/kernel/futex.c index c20f06f38ef3..6555d5459e98 100644 --- a/kernel/futex.c +++ b/kernel/futex.c @@ -469,7 +469,7 @@ get_futex_key(u32 __user *uaddr, int fshared, union futex_key *key, int rw) { unsigned long address = (unsigned long)uaddr; struct mm_struct *mm = current->mm; - struct page *page; + struct page *page, *tail; struct address_space *mapping; int err, ro = 0; @@ -530,7 +530,15 @@ get_futex_key(u32 __user *uaddr, int fshared, union futex_key *key, int rw) * considered here and page lock forces unnecessarily serialization * From this point on, mapping will be re-verified if necessary and * page lock will be acquired only if it is unavoidable -*/ +* +* Mapping checks require the head page for any compound page so the +* head page and mapping is looked up now. For anonymous pages, it +* does not matter if the page splits in the future as the key is +* based on the address. For filesystem-backed pages, the tail is +* required as the index of the page determines the key. For +* base pages, there is no tail page and tail == page. +*/ + tail = page; page = compound_head(page); mapping = READ_ONCE(page->mapping); @@ -654,7 +662,7 @@ get_futex_key(u32 __user *uaddr, int fshared, union futex_key *key, int rw) key->both.offset |= FUT_OFF_INODE; /* inode-based key */ key->shared.inode = inode; - key->shared.pgoff = basepage_index(page); + key->shared.pgoff = basepage_index(tail); rcu_read_unlock(); }
Re: 274ad65c9d02 ("drm/radeon: hard reset r600 and newer GPU when hibernating.")
On Wed, Jun 08, 2016 at 01:50:28PM +0200, Christian König wrote: > What's the output of mplayer? Mplayer usually uses video acceleration when > it is available. Something like this? libavformat version 56.23.105 (internal) libavformat file format detected. [lavf] stream 0: video (h264), -vid 0 [lavf] stream 1: audio (aac), -aid 0, -alang eng VIDEO: [H264] 1280x720 24bpp 23.976 fps 1702.9 kbps (207.9 kbyte/s) Clip info: major_brand: mp42 minor_version: 0 compatible_brands: isommp42 creation_time: 2015-09-24 14:54:07 Load subtitles in ./ == Opening video decoder: [ffmpeg] FFmpeg's libavcodec codec family libavcodec version 56.26.100 (internal) Selected video codec: [ffh264] vfm: ffmpeg (FFmpeg H.264) == == Opening audio decoder: [ffmpeg] FFmpeg/libavcodec audio decoders AUDIO: 44100 Hz, 2 ch, floatle, 192.0 kbit/6.80% (ratio: 23999->352800) Selected audio codec: [ffaac] afm: ffmpeg (FFmpeg AAC (MPEG-2/MPEG-4 Audio)) == AO: [alsa] 48000Hz 2ch floatle (4 bytes per sample) Starting playback... Movie-Aspect is 1.78:1 - prescaling to correct movie aspect. VO: [xv] 1280x720 => 1280x720 Planar YV12 A: 1.5 V: 1.5 A-V: 0.001 ct: 0.041 0/ 0 8% 2% 1.3% 0 0 -- Regards/Gruss, Boris. ECO tip #101: Trim your mails when you reply.
[PATCH v2 0/7] fix bugs; enable iommu for ARM64
This series patches mainly for ARM64 supporting. To do this, it first add virtual iommu slave device which DRM can attach to, convert DRM driver to use common iommu API instead of the ARM32 functions, and then use DMA API in iommu driver to map, to flush cache. The v2 patches make a lot changes vs v1, so please forget the v1. Shunqian Zheng (4): iommu/rockchip: support virtual iommu slave device ARM: dts: rockchip: add virtual iommu for display drm: rockchip: use common iommu api to attach iommu iommu/rockchip: use DMA API to map, to flush cache Simon Xue (3): iommu/rockchip: fix devm_{request,free}_irq parameter iommu/rockchip: add map_sg callback for rk_iommu_ops iommu/rockchip: enable rockchip iommu on ARM64 platform arch/arm/boot/dts/rk3288.dtsi | 6 ++ drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 130 drivers/gpu/drm/rockchip/rockchip_drm_drv.h | 1 + drivers/iommu/Kconfig | 2 +- drivers/iommu/rockchip-iommu.c | 151 ++-- 5 files changed, 193 insertions(+), 97 deletions(-) -- 1.9.1
[PATCH v2 1/7] iommu/rockchip: fix devm_{request,free}_irq parameter
From: Simon Xue Even though the iommu shares irq with its master, using the *dev of iommu instead of master's *dev for devm_{request,free}_irq makes things clear. Signed-off-by: Simon Xue Signed-off-by: Shunqian Zheng --- drivers/iommu/rockchip-iommu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c index c7d6156..ec0ce62 100644 --- a/drivers/iommu/rockchip-iommu.c +++ b/drivers/iommu/rockchip-iommu.c @@ -807,7 +807,7 @@ static int rk_iommu_attach_device(struct iommu_domain *domain, iommu->domain = domain; - ret = devm_request_irq(dev, iommu->irq, rk_iommu_irq, + ret = devm_request_irq(iommu->dev, iommu->irq, rk_iommu_irq, IRQF_SHARED, dev_name(dev), iommu); if (ret) return ret; @@ -860,7 +860,7 @@ static void rk_iommu_detach_device(struct iommu_domain *domain, } rk_iommu_disable_stall(iommu); - devm_free_irq(dev, iommu->irq, iommu); + devm_free_irq(iommu->dev, iommu->irq, iommu); iommu->domain = NULL; -- 1.9.1
[PATCH v2 6/7] iommu/rockchip: use DMA API to map, to flush cache
Use DMA API instead of architecture internal functions like __cpuc_flush_dcache_area() etc. To support the virtual device like DRM the virtual slave iommu added in the previous patch, attaching to which the DRM can use it own domain->dev for dma_map_*(), dma_sync_*() even VOP is disabled. With this patch, this driver is available for ARM64 like RK3399. Signed-off-by: Shunqian Zheng --- drivers/iommu/rockchip-iommu.c | 113 ++--- 1 file changed, 71 insertions(+), 42 deletions(-) diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c index d6c3051..aafea6e 100644 --- a/drivers/iommu/rockchip-iommu.c +++ b/drivers/iommu/rockchip-iommu.c @@ -4,8 +4,6 @@ * published by the Free Software Foundation. */ -#include -#include #include #include #include @@ -61,8 +59,7 @@ #define RK_MMU_IRQ_BUS_ERROR 0x02 /* bus read error */ #define RK_MMU_IRQ_MASK (RK_MMU_IRQ_PAGE_FAULT | RK_MMU_IRQ_BUS_ERROR) -#define NUM_DT_ENTRIES 1024 -#define NUM_PT_ENTRIES 1024 +#define NUM_TLB_ENTRIES 1024 /* for both DT and PT */ #define SPAGE_ORDER 12 #define SPAGE_SIZE (1 << SPAGE_ORDER) @@ -82,7 +79,9 @@ struct rk_iommu_domain { struct list_head iommus; + struct device *dev; u32 *dt; /* page directory table */ + dma_addr_t dt_dma; spinlock_t iommus_lock; /* lock for iommus list */ spinlock_t dt_lock; /* lock for modifying page directory table */ @@ -98,14 +97,12 @@ struct rk_iommu { struct iommu_domain *domain; /* domain to which iommu is attached */ }; -static inline void rk_table_flush(u32 *va, unsigned int count) +static inline void rk_table_flush(struct device *dev, dma_addr_t dma, + unsigned int count) { - phys_addr_t pa_start = virt_to_phys(va); - phys_addr_t pa_end = virt_to_phys(va + count); - size_t size = pa_end - pa_start; + size_t size = count * 4; - __cpuc_flush_dcache_area(va, size); - outer_flush_range(pa_start, pa_end); + dma_sync_single_range_for_device(dev, dma, 0, size, DMA_TO_DEVICE); } static struct rk_iommu_domain *to_rk_domain(struct iommu_domain *dom) @@ -188,10 +185,9 @@ static inline bool rk_dte_is_pt_valid(u32 dte) return dte & RK_DTE_PT_VALID; } -static u32 rk_mk_dte(u32 *pt) +static inline u32 rk_mk_dte(dma_addr_t pt_dma) { - phys_addr_t pt_phys = virt_to_phys(pt); - return (pt_phys & RK_DTE_PT_ADDRESS_MASK) | RK_DTE_PT_VALID; + return (pt_dma & RK_DTE_PT_ADDRESS_MASK) | RK_DTE_PT_VALID; } /* @@ -609,12 +605,14 @@ static u32 *rk_dte_get_page_table(struct rk_iommu_domain *rk_domain, dma_addr_t iova) { u32 *page_table, *dte_addr; + u32 dte_index = rk_iova_dte_index(iova); u32 dte; phys_addr_t pt_phys; + dma_addr_t pt_dma; assert_spin_locked(&rk_domain->dt_lock); - dte_addr = &rk_domain->dt[rk_iova_dte_index(iova)]; + dte_addr = &rk_domain->dt[dte_index]; dte = *dte_addr; if (rk_dte_is_pt_valid(dte)) goto done; @@ -623,19 +621,27 @@ static u32 *rk_dte_get_page_table(struct rk_iommu_domain *rk_domain, if (!page_table) return ERR_PTR(-ENOMEM); - dte = rk_mk_dte(page_table); - *dte_addr = dte; + pt_dma = dma_map_single(rk_domain->dev, page_table, + SPAGE_SIZE, DMA_TO_DEVICE); + if (dma_mapping_error(rk_domain->dev, pt_dma)) { + dev_err(rk_domain->dev, "dma mapping error\n"); + free_page((unsigned long)page_table); + return ERR_PTR(-ENOMEM); + } - rk_table_flush(page_table, NUM_PT_ENTRIES); - rk_table_flush(dte_addr, 1); + dte = rk_mk_dte(pt_dma); + *dte_addr = dte; + rk_table_flush(rk_domain->dev, pt_dma, NUM_TLB_ENTRIES); + rk_table_flush(rk_domain->dev, rk_domain->dt_dma + dte_index * 4, 1); done: pt_phys = rk_dte_pt_address(dte); return (u32 *)phys_to_virt(pt_phys); } static size_t rk_iommu_unmap_iova(struct rk_iommu_domain *rk_domain, - u32 *pte_addr, dma_addr_t iova, size_t size) + u32 *pte_addr, dma_addr_t pte_dma, + size_t size) { unsigned int pte_count; unsigned int pte_total = size / SPAGE_SIZE; @@ -650,14 +656,14 @@ static size_t rk_iommu_unmap_iova(struct rk_iommu_domain *rk_domain, pte_addr[pte_count] = rk_mk_pte_invalid(pte); } - rk_table_flush(pte_addr, pte_count); + rk_table_flush(rk_domain->dev, pte_dma, pte_count); return pte_count * SPAGE_SIZE; } static int rk_iommu_map_iova(struct rk_iommu_domain *rk_domain, u32 *pte_addr, -dma_addr_t iova, phys_addr_t paddr, size_t size, -int prot) +
[PATCH v2 7/7] iommu/rockchip: enable rockchip iommu on ARM64 platform
From: Simon Xue Signed-off-by: Simon Xue Signed-off-by: Shunqian Zheng --- drivers/iommu/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig index ad08603..5572621 100644 --- a/drivers/iommu/Kconfig +++ b/drivers/iommu/Kconfig @@ -218,7 +218,7 @@ config OMAP_IOMMU_DEBUG config ROCKCHIP_IOMMU bool "Rockchip IOMMU Support" - depends on ARM + depends on ARM || ARM64 depends on ARCH_ROCKCHIP || COMPILE_TEST select IOMMU_API select ARM_DMA_USE_IOMMU -- 1.9.1
[PATCH v2 2/7] iommu/rockchip: add map_sg callback for rk_iommu_ops
From: Simon Xue The iommu_dma_alloc() in iommu/dma-iommu.c calls iommu_map_sg() that requires the callback iommu_ops .map_sg(). Adding the default_iommu_map_sg() to rockchip iommu accordingly. Signed-off-by: Simon Xue Signed-off-by: Shunqian Zheng --- drivers/iommu/rockchip-iommu.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c index ec0ce62..3c16ec3 100644 --- a/drivers/iommu/rockchip-iommu.c +++ b/drivers/iommu/rockchip-iommu.c @@ -1022,6 +1022,7 @@ static const struct iommu_ops rk_iommu_ops = { .detach_dev = rk_iommu_detach_device, .map = rk_iommu_map, .unmap = rk_iommu_unmap, + .map_sg = default_iommu_map_sg, .add_device = rk_iommu_add_device, .remove_device = rk_iommu_remove_device, .iova_to_phys = rk_iommu_iova_to_phys, -- 1.9.1
[PATCH v2 3/7] iommu/rockchip: support virtual iommu slave device
An virtual master device like DRM need to attach to iommu domain to share the domain with VOP(the one with actual iommu slave). We currently check the group is NULL to indicate a virtual master, which is not true since we decide to use the common iommu api to attach device in DRM. With this patch, we can probe a virtual iommu device and allow the DRM attaching to it. The virtual iommu is needed also because we want convert to use DMA API for map/unmap, cache flush, so that DRM buffer alloc still work even VOP is disabled. Signed-off-by: Shunqian Zheng --- drivers/iommu/rockchip-iommu.c | 37 + 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c index 3c16ec3..d6c3051 100644 --- a/drivers/iommu/rockchip-iommu.c +++ b/drivers/iommu/rockchip-iommu.c @@ -75,6 +75,11 @@ #define IOMMU_REG_POLL_COUNT_FAST 1000 +/* A virtual iommu in device-tree registered without reg or + * interrupts, so the num_mmu is zero. + */ +#define RK_IOMMU_IS_VIRTUAL(iommu) (iommu->num_mmu == 0) + struct rk_iommu_domain { struct list_head iommus; u32 *dt; /* page directory table */ @@ -789,13 +794,13 @@ static int rk_iommu_attach_device(struct iommu_domain *domain, int ret, i; phys_addr_t dte_addr; - /* -* Allow 'virtual devices' (e.g., drm) to attach to domain. -* Such a device does not belong to an iommu group. -*/ iommu = rk_iommu_from_dev(dev); - if (!iommu) + + iommu->domain = domain; + if (RK_IOMMU_IS_VIRTUAL(iommu)) { + dev_dbg(dev, "Attach virtual device to iommu domain\n"); return 0; + } ret = rk_iommu_enable_stall(iommu); if (ret) @@ -805,7 +810,6 @@ static int rk_iommu_attach_device(struct iommu_domain *domain, if (ret) return ret; - iommu->domain = domain; ret = devm_request_irq(iommu->dev, iommu->irq, rk_iommu_irq, IRQF_SHARED, dev_name(dev), iommu); @@ -842,10 +846,13 @@ static void rk_iommu_detach_device(struct iommu_domain *domain, unsigned long flags; int i; - /* Allow 'virtual devices' (eg drm) to detach from domain */ iommu = rk_iommu_from_dev(dev); - if (!iommu) + + iommu->domain = NULL; + if (RK_IOMMU_IS_VIRTUAL(iommu)) { + dev_dbg(dev, "Master with virtual iommu detached from domain\n"); return; + } spin_lock_irqsave(&rk_domain->iommus_lock, flags); list_del_init(&iommu->node); @@ -862,8 +869,6 @@ static void rk_iommu_detach_device(struct iommu_domain *domain, devm_free_irq(iommu->dev, iommu->irq, iommu); - iommu->domain = NULL; - dev_dbg(dev, "Detached from iommu domain\n"); } @@ -1034,6 +1039,7 @@ static int rk_iommu_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct rk_iommu *iommu; struct resource *res; + int num_res = pdev->num_resources; int i; iommu = devm_kzalloc(dev, sizeof(*iommu), GFP_KERNEL); @@ -1043,12 +1049,19 @@ static int rk_iommu_probe(struct platform_device *pdev) platform_set_drvdata(pdev, iommu); iommu->dev = dev; iommu->num_mmu = 0; - iommu->bases = devm_kzalloc(dev, sizeof(*iommu->bases) * iommu->num_mmu, + + if (!num_res) { + iommu->bases = NULL; + dev_info(dev, "this is a virtual iommu\n"); + return 0; + } + + iommu->bases = devm_kzalloc(dev, sizeof(*iommu->bases) * num_res, GFP_KERNEL); if (!iommu->bases) return -ENOMEM; - for (i = 0; i < pdev->num_resources; i++) { + for (i = 0; i < num_res; i++) { res = platform_get_resource(pdev, IORESOURCE_MEM, i); if (!res) continue; -- 1.9.1
[PATCH v2 4/7] ARM: dts: rockchip: add virtual iommu for display
An virtual iommu without reg or interrupts for display. Adding this according to iommu driver changes. Signed-off-by: Shunqian Zheng --- arch/arm/boot/dts/rk3288.dtsi | 6 ++ 1 file changed, 6 insertions(+) diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi index 7fa932f..4cd535f 100644 --- a/arch/arm/boot/dts/rk3288.dtsi +++ b/arch/arm/boot/dts/rk3288.dtsi @@ -219,9 +219,15 @@ clock-names = "timer", "pclk"; }; + display_mmu: virtual-iommu { + compatible = "rockchip,iommu"; + #iommu-cells = <0>; + }; + display-subsystem { compatible = "rockchip,display-subsystem"; ports = <&vopl_out>, <&vopb_out>; + iommus = <&display_mmu>; }; sdmmc: dwmmc@ff0c { -- 1.9.1
[PATCH v2 5/7] drm: rockchip: use common iommu api to attach iommu
Rockchip DRM used the arm special API, arm_iommu_*(), to attach iommu for ARM32 SoCs. This patch convert to common iommu API so it would support ARM64 like RK3399. The general idea is domain_alloc(), attach_device() and arch_setup_dma_ops() to set dma_ops manually for DRM at the last. Signed-off-by: Shunqian Zheng --- drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 130 +++- drivers/gpu/drm/rockchip/rockchip_drm_drv.h | 1 + 2 files changed, 89 insertions(+), 42 deletions(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c index f5a68fc..7965a66 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c @@ -14,8 +14,6 @@ * GNU General Public License for more details. */ -#include - #include #include #include @@ -24,6 +22,8 @@ #include #include #include +#include +#include #include "rockchip_drm_drv.h" #include "rockchip_drm_fb.h" @@ -46,7 +46,8 @@ static bool is_support_iommu = true; int rockchip_drm_dma_attach_device(struct drm_device *drm_dev, struct device *dev) { - struct dma_iommu_mapping *mapping = drm_dev->dev->archdata.mapping; + struct rockchip_drm_private *private = drm_dev->dev_private; + struct iommu_domain *domain = private->domain; int ret; if (!is_support_iommu) @@ -58,16 +59,25 @@ int rockchip_drm_dma_attach_device(struct drm_device *drm_dev, dma_set_max_seg_size(dev, DMA_BIT_MASK(32)); - return arm_iommu_attach_device(dev, mapping); + ret = iommu_attach_device(domain, dev); + + if (ret) { + dev_err(dev, "Failed to attach iommu device\n"); + return ret; + } + arch_setup_dma_ops(dev, 0x, SZ_2G, + (struct iommu_ops *)dev->bus->iommu_ops, false); + return 0; } void rockchip_drm_dma_detach_device(struct drm_device *drm_dev, struct device *dev) { - if (!is_support_iommu) - return; + struct rockchip_drm_private *private = drm_dev->dev_private; + struct iommu_domain *domain = private->domain; - arm_iommu_detach_device(dev); + if (is_support_iommu) + iommu_detach_device(domain, dev); } int rockchip_register_crtc_funcs(struct drm_crtc *crtc, @@ -132,10 +142,70 @@ static void rockchip_drm_crtc_disable_vblank(struct drm_device *dev, priv->crtc_funcs[pipe]->disable_vblank(crtc); } +static int rockchip_drm_init_iommu(struct drm_device *drm_dev) +{ + struct rockchip_drm_private *private = drm_dev->dev_private; + struct device *dev = drm_dev->dev; + int ret; + + dev->dma_parms = devm_kzalloc(dev, sizeof(*dev->dma_parms), + GFP_KERNEL); + if (!dev->dma_parms) { + ret = -ENOMEM; + return ret; + } + + ret = dma_set_coherent_mask(dev, DMA_BIT_MASK(32)); + if (ret) { + dev_err(dev, "Failed to set coherent mask\n"); + return ret; + } + + dma_set_max_seg_size(dev, DMA_BIT_MASK(32)); + + private->domain = iommu_domain_alloc(&platform_bus_type); + if (!private->domain) + return -ENOMEM; + + ret = iommu_get_dma_cookie(private->domain); + if (ret) { + dev_err(dev, "Failed to get dma cookie\n"); + goto err_free_domain; + } + + ret = iommu_dma_init_domain(private->domain, 0x, SZ_2G); + if (ret) { + dev_err(dev, "Failed to init domain\n"); + goto err_put_cookie; + } + + ret = rockchip_drm_dma_attach_device(drm_dev, dev); + if (ret) { + dev_err(dev, "Failed to attach device\n"); + goto err_put_cookie; + } + + return 0; + +err_put_cookie: + iommu_put_dma_cookie(private->domain); +err_free_domain: + iommu_domain_free(private->domain); + + return ret; +} + +static void rockchip_iommu_cleanup(struct drm_device *drm_dev) +{ + struct rockchip_drm_private *private = drm_dev->dev_private; + + iommu_put_dma_cookie(private->domain); + iommu_domain_free(private->domain); +} + static int rockchip_drm_load(struct drm_device *drm_dev, unsigned long flags) { struct rockchip_drm_private *private; - struct dma_iommu_mapping *mapping = NULL; struct device *dev = drm_dev->dev; struct drm_connector *connector; int ret; @@ -153,38 +223,18 @@ static int rockchip_drm_load(struct drm_device *drm_dev, unsigned long flags) rockchip_drm_mode_config_init(drm_dev); - dev->dma_parms = devm_kzalloc(dev, sizeof(*dev->dma_parms), - GFP_KERNEL); - if (!dev->dma_parms) { - ret = -ENOMEM; - goto err_config_cleanup
Re: [PATCH 3/3] x86, mpx, selftests: add MPX self test
These patches look good to me, but it would be nice to get rid of uglies like: > +/* > + * Written by Dave Hansen > + * > + * run like this: > + pid=31390; BDIR="$(cat /proc/$pid/smaps | grep -B1 2097152 | head -1 | awk > -F- '{print $1}')"; ./mpx-dig $pid 0x$BDIR > + > +NOTE: > + assumes that the only 2097152-kb VMA is the bounds dir > + */ (weird vertical alignment) > +long nr_incore(void *ptr, unsigned long size_bytes) > +{ > + int i; > + long ret = 0; > + long vec_len = size_bytes / PAGE_SIZE; > + unsigned char *vec = malloc(vec_len); > + if (!vec) (missing newline) > + mpx_dig_abort(); > + > + int incore_ret = mincore(ptr, size_bytes, vec); (weird non-kernel-style definition.) > +char buf[100]; > +int open_proc(int pid, char *file) (missing newline) > +{ > + int fd; > + sprintf(&buf[0], "/proc/%d/%s", pid, file); (ditto, also unsafe looking sprintf()) > +void __dave_abort(int line) > +{ > + perror("abort"); > + printf("abort @ %d\n", line); > + mpx_dig_abort(); > +} > +#define dave_mpx_dig_abort() __dave_abort(__LINE__); maybe s/dave// ? ;-) > +//This mincore stuff works, but the bounds tables are not > +//sparse enough to make it worthwhile bad comment style. > + unsigned char incore_vec[MPX_BOUNDS_TABLE_SIZE_BYTES/ PAGE_SIZE]; > + int incore_ret = mincore(bt_buf, MPX_BOUNDS_TABLE_SIZE_BYTES, > &incore_vec[0]); stray whitespace. > + //if (!incore_vec[page_nr]) > + // continue; ugly. > + if (this_bt_entry_for_vaddr > 0x7fffUL) { > + this_bt_entry_for_vaddr |= 0x8000; > + } unnecessary curly braces. > + // Each bounds directory entry controls 1MB of > + // virtual address space. This variable is the > + // virtual address in the process of the > + // beginning of the area controlled by this > + // bounds_dir. ugly. > + unsigned long bd_for_vaddr = bd_index * (1UL<<20); > + //printf("%s() at bd index: %lx for vaddr: %lx\n", __func__, > bd_index, bd_for_vaddr); > + //printf("dir entry[%4ld @ %p]\n", bd_index, > bounds_dir_global+i); Ditto. > + int nr_entries = dump_table(bounds_dir_entry, bd_for_vaddr, > bounds_dir_global+bd_offset_bytes+i); > + total_entries += nr_entries; > + continue; > + printf("dir entry[%4ld @ %p]: 0x%lx %6d entries total this buf: > %7d bd_for_vaddrs: 0x%lx -> 0x%lx\n", > + bd_index, buf+i, > + bounds_dir_entry, nr_entries, total_entries, > bd_for_vaddr, bd_for_vaddr + (1UL<<20)); hm? > + // there shouldn't practically be short reads of /proc/$pid/mem > + > + incore_ret = mincore(dig_bounds_dir_ptr, buffer_size_bytes, &vec[0]); stray space. > + //if (this_entries) > + // printf("entries this loop: %d total: %d (bufs skipped: > %d)\n", this_entries, total_entries, bufs_skipped); You know the drill! > +#ifdef MPX_DIG_REMOTE > +int main(int argc, char **argv) > +{ > + int err; > +char *c; hm... etc. - ad nauseum. Would be nice to tidy this all up a bit. Thanks, Ingo
Re: [PATCH 4/6] x86/coredump: use core regs, rather that TIF_IA32 flag
On 06/07/2016 01:43 AM, Oleg Nesterov wrote: On 06/06, Oleg Nesterov wrote: On 06/01, Dmitry Safonov wrote: static int fill_thread_core_info(struct elf_thread_core_info *t, const struct user_regset_view *view, -long signr, size_t *total) +long signr, size_t *total, +struct pt_regs *regs __maybe_unused) { unsigned int i; @@ -1652,11 +1653,11 @@ static int fill_thread_core_info(struct elf_thread_core_info *t, */ fill_prstatus(&t->prstatus, t->task, signr); (void) view->regsets[0].get(t->task, &view->regsets[0], - 0, PR_REG_SIZE(t->prstatus.pr_reg), + 0, PR_REG_SIZE(t->prstatus.pr_reg, regs), Hmm. I don't understand this... Note that this "regs" argument has nothing to do with t->task if the process is multithreaded, @@ -1772,7 +1773,8 @@ static int fill_note_info(struct elfhdr *elf, int phdrs, * Now fill in each thread's information. */ for (t = info->thread; t != NULL; t = t->next) - if (!fill_thread_core_info(t, view, siginfo->si_signo, &info->size)) + if (!fill_thread_core_info(t, view, siginfo->si_signo, + &info->size, regs)) fill_note_info(..., args) is called with args = task_pt_regs(dumper_thread). forgot to mention... yes, this matches the fact we use a single "view" for all threads, and we get it via task_user_regset_view(dump_task). But this change (imo) adds even more confusion, and without the next patch the logic looks "obviously wrong", becauase PR_REG_SIZE/etc look at dumper_thread->cs while task_user_regset_view() checks thread flags. Anyway I fail to understand these macros... Say, PR_REG_SIZE(S). Can't we kill it and use regsets[0].n * regsets[0].size instead ? These numbers should match whatever we do, if we call ->get(). Thanks, the idea of dropping PR_REG_SIZE looks better than my patch! I'll try to drop those macros for the next revision. -- Regards, Dmitry Safonov
Re: 274ad65c9d02 ("drm/radeon: hard reset r600 and newer GPU when hibernating.")
Yes, exactly. VO: [xv] 1280x720 => 1280x720 Planar YV12 Mplayer is using xv without any acceleration (except for color space conversion). Try forcing mplayer to use VDPAU with "mplayer -vo vdpau $file". Regards, Christian. Am 08.06.2016 um 15:26 schrieb Borislav Petkov: On Wed, Jun 08, 2016 at 01:50:28PM +0200, Christian König wrote: What's the output of mplayer? Mplayer usually uses video acceleration when it is available. Something like this? libavformat version 56.23.105 (internal) libavformat file format detected. [lavf] stream 0: video (h264), -vid 0 [lavf] stream 1: audio (aac), -aid 0, -alang eng VIDEO: [H264] 1280x720 24bpp 23.976 fps 1702.9 kbps (207.9 kbyte/s) Clip info: major_brand: mp42 minor_version: 0 compatible_brands: isommp42 creation_time: 2015-09-24 14:54:07 Load subtitles in ./ == Opening video decoder: [ffmpeg] FFmpeg's libavcodec codec family libavcodec version 56.26.100 (internal) Selected video codec: [ffh264] vfm: ffmpeg (FFmpeg H.264) == == Opening audio decoder: [ffmpeg] FFmpeg/libavcodec audio decoders AUDIO: 44100 Hz, 2 ch, floatle, 192.0 kbit/6.80% (ratio: 23999->352800) Selected audio codec: [ffaac] afm: ffmpeg (FFmpeg AAC (MPEG-2/MPEG-4 Audio)) == AO: [alsa] 48000Hz 2ch floatle (4 bytes per sample) Starting playback... Movie-Aspect is 1.78:1 - prescaling to correct movie aspect. VO: [xv] 1280x720 => 1280x720 Planar YV12 A: 1.5 V: 1.5 A-V: 0.001 ct: 0.041 0/ 0 8% 2% 1.3% 0 0
Re: [PATCH] vme: Update documentation to match api
On 05/06/16 21:35, Martyn Welch wrote: > The vme_register_driver() api changed in commit 5d6abf379d73 ("staging: > vme: make match() driver specific to improve non-VME64x support") but the > documentation wasn't updated. Update the documentation to match the API. > > Signed-off-by: Martyn Welch > --- Nice catch :) Thanks Martyn
Re: [PATCH -v2 00/33] implement atomic_fetch_$op
On Wed, Jun 08, 2016 at 02:55:30PM +0200, Ingo Molnar wrote: > I'd much prefer to have all of these in the locking tree (i.e. > tip:locking/core), > to make it less painful all around. All the fetch_op stuff, yes certainly. But Vineet wanted to munge arch/arc/include/asm/atomic.h a bit in 4.7, which would make applying the arc fetch_op patch tricky.
Re: [GIT PULL arm] Use _rcuidle tracepoints to allow tracing from idle
* Paul E. McKenney wrote: > On Thu, May 26, 2016 at 09:26:06AM -0700, Paul E. McKenney wrote: > > Hello, Ingo, > > > > This series changes a number of event tracepoints to their _rcuidle() form > > to allow use from idle without lockdep-RCU complaints, a straightforward > > modification that has been successfully applied many times. These splats > > were found in testing by Guenter Roeck and Tony Lindgren, who have > > both successfully tested the full series. Tony asked that I carry these > > in -rcu: > > > > http://lkml.kernel.org/g/20160426213630.gv5...@atomide.com > > > > These have been posted to LKML, CCing relevant maintainers, who have > > not objected to the proposed changes: > > > > http://lkml.kernel.org/g/20160516184844.ga20...@linux.vnet.ibm.com > > > > These maintainers are also CCed on this pull request. > > > > They have also been subjected to 0day Test Robot and -next testing. > > And this time actually including the pull request... :-/ > > Thanx, Paul > > These changes are available in the git repository at: > > git://git.kernel.org/pub/scm/linux/kernel/git/paulmck/linux-rcu.git > for-mingo > > for you to fetch changes up to e7c38dda94b23965a3eb46ef4656bb8cb921933d: > > arm: Use _rcuidle suffix to allow clk_core_enable() to used from idle > (2016-05-18 11:55:29 -0700) > > > Paul E. McKenney (6): > arm: Use _rcuidle tracepoint to allow use from idle > arm: Use _rcuidle for suspend/resume tracepoints > arm: Add _rcuidle tracepoints to allow clk_core_disable() use from idle > arm: Add _rcuidle suffix to allow rpm_idle() use from idle > arm: Add _rcuidle suffix to allow rpm_resume() to be called from idle > arm: Use _rcuidle suffix to allow clk_core_enable() to used from idle > > arch/arm/kernel/smp.c | 2 +- > arch/arm/mach-omap2/powerdomain.c | 9 + > drivers/base/power/runtime.c | 14 +++--- > drivers/clk/clk.c | 8 > 4 files changed, 17 insertions(+), 16 deletions(-) Just wondering, wouldn't it be better for Russell to pull/apply, as it appears to be a mostly ARM patch-set? Thanks, Ingo
Re: [PATCH] watchdog: max77620: Add support for watchdog timer
On Wednesday 08 June 2016 06:45 PM, Guenter Roeck wrote: On 06/08/2016 01:58 AM, Laxman Dewangan wrote: Hi Guenter, Thanks for quick review. I will take care of most of comment. I have one query fr following comment. Thanks, Laxman On Tuesday 07 June 2016 11:26 PM, Guenter Roeck wrote: Hi, On Mon, Jun 06, 2016 at 05:22:44PM +0530, Laxman Dewangan wrote: +/* Stop watchodog */ +ret = regmap_update_bits(wdt->rmap, MAX77620_REG_CNFGGLBL2, + MAX77620_WDTEN, 0); +if (ret < 0) { +dev_err(wdt->dev, "Failed to reset WDTEN: %d\n", ret); +return ret; +} Alternatively, you could set WDOG_HW_RUNNING to tell the watchdog core that the watchdog is already running. The watchdog core would then ping the watchdog until the watchdog device is opened. That would also require to tell the watchdog core about the current (or default) timeout, which doesn't seem to be set anywhere. That means it won't be set at all unless user space updates it explicitly. This is quite unusual. Is it on purpose or an oversight ? If it is on purpose, please explain. OK, we have use cases where we have enabled the WDT in BL also. and keep runnign till kernel up. Instead of stopping WDT, I can say that WDOG_HW_RUNING and current timeout can be read from the register. Now, the WDT need to be ping periodically. Is there any flag which enabled the worker thread from core which will keep pinging till user space alive and activate the WDT? The watchdog core will start the worker if WDOG_HW_RUNNING is set. Thanks, found that I also need to set max_hw_heartbeat_ms for periodic ping if user space is not active. I tested this path and it works perfectly. This is also great that all work thread is moved to core. It simplify the drivers very much. I sent the v2 patch with fixing all this. Thanks, Laxman
Re: [PATCH V2] watchdog: max77620: Add support for watchdog timer
Hi, On 06/08/2016 03:17 AM, Laxman Dewangan wrote: Maxim PMIC MAX77620 is Power management IC which have multiple sub blocks like regulators (DCDC/LDOs), GPIO, RTC, Clock, Watchdog timer etc. Add the driver for watchdog timer under watchdog framework. The driver implements the watchdog callbacks to start, stop, ping and set timeout for watchodg framework. Almost good. One more comment below. Signed-off-by: Laxman Dewangan --- Changes from V1: - Remove the error prints from start/stop/ping to simplify the function. - Instead of stopping running WDT, inform HW RUNNING and update the required param accordingly. - Resequence the param sets for wdt device to avoid race condition, move all wdt device setting before registration. [ ... ] +static int max77620_wdt_probe(struct platform_device *pdev) +{ + struct max77620_wdt *wdt; + struct watchdog_device *wdt_dev; + unsigned int regval; + int ret; + + wdt = devm_kzalloc(&pdev->dev, sizeof(*wdt), GFP_KERNEL); + if (!wdt) + return -ENOMEM; + + wdt->dev = &pdev->dev; + wdt->rmap = dev_get_regmap(pdev->dev.parent, NULL); + if (!wdt->rmap) { + dev_err(wdt->dev, "Failed to get parent regmap\n"); + return -ENODEV; + } + + wdt_dev = &wdt->wdt_dev; + wdt_dev->info = &max77620_wdt_info; + wdt_dev->ops = &max77620_wdt_ops; + wdt_dev->min_timeout = 2; + wdt_dev->max_timeout = 128; + wdt_dev->max_hw_heartbeat_ms = 128 * 1000; + + platform_set_drvdata(pdev, wdt); + + /* Enable WD_RST_WK - WDT expire results in a restart */ + ret = regmap_update_bits(wdt->rmap, MAX77620_REG_ONOFFCNFG2, +MAX77620_ONOFFCNFG2_WD_RST_WK, +MAX77620_ONOFFCNFG2_WD_RST_WK); + if (ret < 0) { + dev_err(wdt->dev, "Failed to set WD_RST_WK: %d\n", ret); + return ret; + } + + /* Set WDT clear in OFF and sleep mode */ + ret = regmap_update_bits(wdt->rmap, MAX77620_REG_CNFGGLBL2, +MAX77620_WDTOFFC | MAX77620_WDTSLPC, +MAX77620_WDTOFFC | MAX77620_WDTSLPC); + if (ret < 0) { + dev_err(wdt->dev, "Failed to set WDT OFF mode: %d\n", ret); + return ret; + } + + /* Check if WDT running and ig yes then set flags properly */ + ret = regmap_read(wdt->rmap, MAX77620_REG_CNFGGLBL2, ®val); + if (ret < 0) { + dev_err(wdt->dev, "Failed to read WDT CFG register: %d\n", ret); + return ret; + } + + if (regval & MAX77620_WDTEN) { + regval = regval & MAX77620_TWD_MASK; + if (regval == MAX77620_TWD_2s) + wdt_dev->timeout = 2; + else if (regval == MAX77620_TWD_16s) + wdt_dev->timeout = 16; + else if (regval == MAX77620_TWD_64s) + wdt_dev->timeout = 64; + else + wdt_dev->timeout = 128; + set_bit(WDOG_HW_RUNNING, &wdt_dev->status); + } Please also set a default timeout if the watchdog is not running (and remember to write it to the chip). Otherwise the core won't know the timeout and can not report it to user space when the watchdog device is opened. Thanks, Guenter
Re: [PATCH 2/2] gpio: Support cascaded GPIO chip lookup for OF
Hi Rob, > On Jun 8, 2016, at 00:00 , Rob Herring wrote: > > +Mark R > > On Fri, Jun 3, 2016 at 3:26 PM, Pantelis Antoniou > wrote: >> In certain cases it makes sense to create cascaded GPIO which >> are not real GPIOs, merely point to the real backend GPIO chip. > > In what cases? Make it clear what this is for. Connectors of course, > but are there any other use cases you have in mind. > Connectors is one obvious use-case. In fact even when there is no connector but there is an obvious interface abstraction point you might want to use it. For instance a SoC package may have a number of different GPIO controllers (that may or may not use the same IP block). You could abstract all the gpio controllers away in a single GPIO controller block. >> In order to support this, cascaded of_xlate lookup need to be >> performed. >> >> For example let's take a connector that we want to abstract >> having two GPIO pins from different GPIO controllers, connector >> pin #0 connected to gpioA controller with offset 10 and gpioB >> with 4. > > A connector's GPIO number may or may not be related to connector pins. > Obviously, this is just an example. >> In pseudo DT form this is analogous to: >> >>gpioA: gpioa@8 { >>compatible = "foocorp,gpio"; >>... >>}; >> >>gpioB: gpiob@80800 { >>compatible = "foocorp,gpio"; >> >>}; >> >>gpioC: controller_gpio { >>compatible = "cascaded-gpio"; > > This compatible is kind of meaningless. I'd expect this to be a > connector compatible. > No, because this gpio patch is completely independent of the existence of a connector. >>gpios = <&gpioA 10>, <&gpioB 5>; > > As we discussed at ELC, I think this should be modeled after > interrupt-map property like this: > > gpio-map = <0 0 &soc_gpio 10 0>, <1 0 &soc_gpio 5 0>; > gpio-map-mask = <0xff 0>; > > This is more flexible, a known pattern, and allows remapping of flag cells. > It’s just syntactic sugar. It can work either way. > Also, we will likely have interrupt capable GPIOs, so they are going > to need interrupt-map anyway. > Devices that use interrupts usually convert the GPIO to an interrupt and use it. Since the xlat op will return the real GPIO spec the interrupt conversion will work. Bare interrupt lines are sort-of out of fashion nowadays I think. I’m eager to be proven wrong though with a recent portable expansion board that uses them. > Rob Regards — Pantelis
Re: [PATCH 1/2] x86/entry: Avoid interrupt flag save and restore
> So I believe it would be cleaner to name the irqs-off code paths explicitly: > __guest_enter_irqsoff(), and propagate that naming into other parts as well? Ok, I'll send v2 with both the KVM cleanups and the entry optimizations. It should be four patches putting all things together. Thanks for the review! Paolo
Re: [PATCH net v2] sfc: report supported link speeds on SFP connections
On Tue, Jun 07, 2016 at 05:20:16PM -0400, Jarod Wilson wrote: > On Mon, Jun 06, 2016 at 02:55:29PM -0400, Jarod Wilson wrote: > > On Mon, Jun 06, 2016 at 05:29:30PM +0100, Bert Kenward wrote: > > > 7000-series SFC NICs connected with an SFP+ module currently fail to > > > report any supported link speeds. > > > > > > Reported-by: Jarod Wilson > > > Signed-off-by: Bert Kenward > > > > Had a feeling my cut might not have been quite right. Looks good to me. > > > > Reviewed-by: Jarod Wilson > > ...however, upon testing, there's a gotcha. This results in my 10Gbps sfc > nic reporting that it supports 40Gbps: > > $ ethtool ens4f0 > Settings for ens4f0: > Supported ports: [ FIBRE ] > Supported link modes: 1000baseT/Full > 1baseT/Full > 4baseKR4/Full This turned out to be a flub on my part. My local tree wasn't clean, had some lingering test/debug crap in it that I thought I'd removed, but clearly, hadn't. With that removed, we're all good here. Tested-by: Jarod Wilson -- Jarod Wilson ja...@redhat.com
Re: [PATCH v10 1/7] regulator: fixed: add support for ACPI interface
On Tue, Jun 07, 2016 at 09:42:48PM -0700, Greg Kroah-Hartman wrote: > On Thu, Jun 02, 2016 at 09:37:23AM +0800, Lu Baolu wrote: > > Add support to retrieve fixed voltage configure information through > > ACPI interface. This is needed for Intel Bay Trail devices, where a > > GPIO is used to control the USB vbus. > Can't do anything with this until I get an ack from the "owners" of this > file. Please allow a reasonable time for review, it's been under a week since this was posted. I would *not* expect this to be applied to another tree, please don't do that. signature.asc Description: PGP signature
[PATCH] staging: slicoss: replacement of goto statements
From: Jaime Arrocha Replaced deprecated goto statements. Signed-off-by: Jaime Arrocha --- drivers/staging/slicoss/slicoss.c | 22 +++--- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/staging/slicoss/slicoss.c b/drivers/staging/slicoss/slicoss.c index ac126d4..cc45f4c 100644 --- a/drivers/staging/slicoss/slicoss.c +++ b/drivers/staging/slicoss/slicoss.c @@ -1457,30 +1457,30 @@ static struct slic_hostcmd *slic_cmdq_getfree(struct adapter *adapter) struct slic_hostcmd *cmd = NULL; unsigned long flags; -lock_and_retry: spin_lock_irqsave(&cmdq->lock, flags); -retry: cmd = cmdq->head; - if (cmd) { - cmdq->head = cmd->next; - cmdq->count--; - spin_unlock_irqrestore(&cmdq->lock, flags); - } else { + while (!cmd) { slic_cmdq_getdone(adapter); cmd = cmdq->head; - if (cmd) { - goto retry; - } else { + if (cmd) + continue; + else { u32 *pageaddr; spin_unlock_irqrestore(&cmdq->lock, flags); pageaddr = slic_cmdqmem_addpage(adapter); if (pageaddr) { slic_cmdq_addcmdpage(adapter, pageaddr); - goto lock_and_retry; + spin_lock_irqsave(&cmdq->lock, flags); + cmd = cmdq->head; + continue; } + return cmd; } } + cmdq->head = cmd->next; + cmdq->count--; + spin_unlock_irqrestore(&cmdq->lock, flags); return cmd; } -- 2.1.4