[PATCH 1/2] mm/page_ref: use page_ref helper instead of direct modification of _count
From: Joonsoo Kimpage_reference manipulation functions are introduced to track down reference count change of the page. Use it instead of direct modification of _count. Signed-off-by: Joonsoo Kim --- drivers/net/ethernet/cavium/thunder/nicvf_queues.c | 2 +- drivers/net/ethernet/qlogic/qede/qede_main.c | 2 +- mm/filemap.c | 2 +- net/wireless/util.c| 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_queues.c b/drivers/net/ethernet/cavium/thunder/nicvf_queues.c index fa05e34..8acd7c0 100644 --- a/drivers/net/ethernet/cavium/thunder/nicvf_queues.c +++ b/drivers/net/ethernet/cavium/thunder/nicvf_queues.c @@ -23,7 +23,7 @@ static void nicvf_get_page(struct nicvf *nic) if (!nic->rb_pageref || !nic->rb_page) return; - atomic_add(nic->rb_pageref, >rb_page->_count); + page_ref_add(nic->rb_page, nic->rb_pageref); nic->rb_pageref = 0; } diff --git a/drivers/net/ethernet/qlogic/qede/qede_main.c b/drivers/net/ethernet/qlogic/qede/qede_main.c index 518af32..394c97ff 100644 --- a/drivers/net/ethernet/qlogic/qede/qede_main.c +++ b/drivers/net/ethernet/qlogic/qede/qede_main.c @@ -791,7 +791,7 @@ static inline int qede_realloc_rx_buffer(struct qede_dev *edev, * network stack to take the ownership of the page * which can be recycled multiple times by the driver. */ - atomic_inc(_cons->data->_count); + page_ref_inc(curr_cons->data); qede_reuse_page(edev, rxq, curr_cons); } diff --git a/mm/filemap.c b/mm/filemap.c index a8c69c8..0ebd326 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -213,7 +213,7 @@ void __delete_from_page_cache(struct page *page, void *shadow) * some other bad page check should catch it later. */ page_mapcount_reset(page); - atomic_sub(mapcount, >_count); + page_ref_sub(page, mapcount); } } diff --git a/net/wireless/util.c b/net/wireless/util.c index 9f440a9..e22432a 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c @@ -651,7 +651,7 @@ __frame_add_frag(struct sk_buff *skb, struct page *page, struct skb_shared_info *sh = skb_shinfo(skb); int page_offset; - atomic_inc(>_count); + page_ref_inc(page); page_offset = ptr - page_address(page); skb_add_rx_frag(skb, sh->nr_frags, page, page_offset, len, size); } -- 1.9.1
[PATCH 1/2] mm/page_ref: use page_ref helper instead of direct modification of _count
From: Joonsoo Kim page_reference manipulation functions are introduced to track down reference count change of the page. Use it instead of direct modification of _count. Signed-off-by: Joonsoo Kim --- drivers/net/ethernet/cavium/thunder/nicvf_queues.c | 2 +- drivers/net/ethernet/qlogic/qede/qede_main.c | 2 +- mm/filemap.c | 2 +- net/wireless/util.c| 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_queues.c b/drivers/net/ethernet/cavium/thunder/nicvf_queues.c index fa05e34..8acd7c0 100644 --- a/drivers/net/ethernet/cavium/thunder/nicvf_queues.c +++ b/drivers/net/ethernet/cavium/thunder/nicvf_queues.c @@ -23,7 +23,7 @@ static void nicvf_get_page(struct nicvf *nic) if (!nic->rb_pageref || !nic->rb_page) return; - atomic_add(nic->rb_pageref, >rb_page->_count); + page_ref_add(nic->rb_page, nic->rb_pageref); nic->rb_pageref = 0; } diff --git a/drivers/net/ethernet/qlogic/qede/qede_main.c b/drivers/net/ethernet/qlogic/qede/qede_main.c index 518af32..394c97ff 100644 --- a/drivers/net/ethernet/qlogic/qede/qede_main.c +++ b/drivers/net/ethernet/qlogic/qede/qede_main.c @@ -791,7 +791,7 @@ static inline int qede_realloc_rx_buffer(struct qede_dev *edev, * network stack to take the ownership of the page * which can be recycled multiple times by the driver. */ - atomic_inc(_cons->data->_count); + page_ref_inc(curr_cons->data); qede_reuse_page(edev, rxq, curr_cons); } diff --git a/mm/filemap.c b/mm/filemap.c index a8c69c8..0ebd326 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -213,7 +213,7 @@ void __delete_from_page_cache(struct page *page, void *shadow) * some other bad page check should catch it later. */ page_mapcount_reset(page); - atomic_sub(mapcount, >_count); + page_ref_sub(page, mapcount); } } diff --git a/net/wireless/util.c b/net/wireless/util.c index 9f440a9..e22432a 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c @@ -651,7 +651,7 @@ __frame_add_frag(struct sk_buff *skb, struct page *page, struct skb_shared_info *sh = skb_shinfo(skb); int page_offset; - atomic_inc(>_count); + page_ref_inc(page); page_offset = ptr - page_address(page); skb_add_rx_frag(skb, sh->nr_frags, page, page_offset, len, size); } -- 1.9.1
Re: [PATCH v2] mmc: Provide tracepoints for request processing
On 25 March 2016 at 22:10, Jens Axboewrote: > On 03/25/2016 02:19 AM, Baolin Wang wrote: >> >> diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c >> index fe207e5..d372a2d 100644 >> --- a/drivers/mmc/card/block.c >> +++ b/drivers/mmc/card/block.c >> @@ -46,6 +46,9 @@ >> >> #include "queue.h" >> >> +#define CREATE_TRACE_POINTS >> +#include >> + >> MODULE_ALIAS("mmc:block"); >> #ifdef MODULE_PARAM_PREFIX >> #undef MODULE_PARAM_PREFIX >> @@ -1709,6 +1712,7 @@ static u8 mmc_blk_prep_packed_list(struct mmc_queue >> *mq, struct request *req) >> if (phys_segments > max_phys_segs) >> break; >> >> + trace_mmc_block_packed_req(next); >> list_add_tail(>queuelist, >packed->list); >> cur = next; >> reqs++; > > > This looks like the only valid trace point in the block part. OK. > >> @@ -1870,6 +1874,7 @@ static int mmc_blk_end_packed_req(struct >> mmc_queue_req *mq_rq) >> } >> list_del_init(>queuelist); >> blk_end_request(prq, 0, blk_rq_bytes(prq)); >> + trace_mmc_block_req_done(prq); > > > We just logged a complete event through blk_end_request() here. I'll remove this repeated tracepoint. >> >> @@ -1985,6 +1990,7 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, >> struct request *rqc) >> } else { >> ret = blk_end_request(req, 0, >> brq->data.bytes_xfered); >> + trace_mmc_block_req_done(req); >> } > > > Ditto Will remove it too. > >> diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c >> index 6f4323c..d0388cf 100644 >> --- a/drivers/mmc/card/queue.c >> +++ b/drivers/mmc/card/queue.c >> @@ -16,6 +16,7 @@ >> #include >> #include >> #include >> +#include >> >> #include >> #include >> @@ -64,6 +65,9 @@ static int mmc_queue_thread(void *d) >> mq->mqrq_cur->req = req; >> spin_unlock_irq(q->queue_lock); >> >> + if (req) >> + trace_mmc_queue_fetch(req); > > > Issue event was just logged here, if req != NULL. So also redundant. Make sense. > > Basically only your core mmc events would potentially have merit, the rest > are all dupes. So nak. I'll remove the redundant tracepoints. Thanks for your comments. > > -- > Jens Axboe > -- Baolin.wang Best Regards
Re: [PATCH v2] mmc: Provide tracepoints for request processing
On 25 March 2016 at 22:10, Jens Axboe wrote: > On 03/25/2016 02:19 AM, Baolin Wang wrote: >> >> diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c >> index fe207e5..d372a2d 100644 >> --- a/drivers/mmc/card/block.c >> +++ b/drivers/mmc/card/block.c >> @@ -46,6 +46,9 @@ >> >> #include "queue.h" >> >> +#define CREATE_TRACE_POINTS >> +#include >> + >> MODULE_ALIAS("mmc:block"); >> #ifdef MODULE_PARAM_PREFIX >> #undef MODULE_PARAM_PREFIX >> @@ -1709,6 +1712,7 @@ static u8 mmc_blk_prep_packed_list(struct mmc_queue >> *mq, struct request *req) >> if (phys_segments > max_phys_segs) >> break; >> >> + trace_mmc_block_packed_req(next); >> list_add_tail(>queuelist, >packed->list); >> cur = next; >> reqs++; > > > This looks like the only valid trace point in the block part. OK. > >> @@ -1870,6 +1874,7 @@ static int mmc_blk_end_packed_req(struct >> mmc_queue_req *mq_rq) >> } >> list_del_init(>queuelist); >> blk_end_request(prq, 0, blk_rq_bytes(prq)); >> + trace_mmc_block_req_done(prq); > > > We just logged a complete event through blk_end_request() here. I'll remove this repeated tracepoint. >> >> @@ -1985,6 +1990,7 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, >> struct request *rqc) >> } else { >> ret = blk_end_request(req, 0, >> brq->data.bytes_xfered); >> + trace_mmc_block_req_done(req); >> } > > > Ditto Will remove it too. > >> diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c >> index 6f4323c..d0388cf 100644 >> --- a/drivers/mmc/card/queue.c >> +++ b/drivers/mmc/card/queue.c >> @@ -16,6 +16,7 @@ >> #include >> #include >> #include >> +#include >> >> #include >> #include >> @@ -64,6 +65,9 @@ static int mmc_queue_thread(void *d) >> mq->mqrq_cur->req = req; >> spin_unlock_irq(q->queue_lock); >> >> + if (req) >> + trace_mmc_queue_fetch(req); > > > Issue event was just logged here, if req != NULL. So also redundant. Make sense. > > Basically only your core mmc events would potentially have merit, the rest > are all dupes. So nak. I'll remove the redundant tracepoints. Thanks for your comments. > > -- > Jens Axboe > -- Baolin.wang Best Regards
Re: [PATCH 10/31] Add sparc-specific parity functions
在 2016年03月28日 10:43, David Miller 写道: From: "zhaoxiu.zeng"Date: Sun, 27 Mar 2016 14:43:10 +0800 + +/* + * parityN: returns the parity of a N-bit word, + * i.e. the number of 1-bits in x modulo 2. + */ + +#define __arch_parity4(w) (__arch_hweight8((w) & 0xf) & 1) +#define __arch_parity8(w) (__arch_hweight8(w) & 1) +#define __arch_parity16(w) (__arch_hweight16(w) & 1) +#define __arch_parity32(w) (__arch_hweight32(w) & 1) +#define __arch_parity64(w) ((unsigned int)__arch_hweight64(w) & 1) This looks like asm-generic/ material to me. This is generic for the architectures which have popcount instruction, but more higher costs than asm-generic/ for others.
Re: [PATCH 10/31] Add sparc-specific parity functions
在 2016年03月28日 10:43, David Miller 写道: From: "zhaoxiu.zeng" Date: Sun, 27 Mar 2016 14:43:10 +0800 + +/* + * parityN: returns the parity of a N-bit word, + * i.e. the number of 1-bits in x modulo 2. + */ + +#define __arch_parity4(w) (__arch_hweight8((w) & 0xf) & 1) +#define __arch_parity8(w) (__arch_hweight8(w) & 1) +#define __arch_parity16(w) (__arch_hweight16(w) & 1) +#define __arch_parity32(w) (__arch_hweight32(w) & 1) +#define __arch_parity64(w) ((unsigned int)__arch_hweight64(w) & 1) This looks like asm-generic/ material to me. This is generic for the architectures which have popcount instruction, but more higher costs than asm-generic/ for others.
Re: [PATCH v1 0/4] Implement SoC bus driver for Vybrid
Hello, Ping. - Sanchayan. On 16-03-11 14:29:27, Sanchayan Maity wrote: > Hello, > > This patchset implements SoC bus support for Freescale Vybrid platform, > implementing the following > https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-devices-soc > > This a reworked version of an older patchset series posted in June 2015 > which was at v5 then [1]. Since the NVMEM framework was then getting > introduced, we decided that first a NVMEM driver for OCOTP peripheral > being in place would be better. > > Compared to the older revisions, this driver now relies on NVMEM > consumer API using the NVMEM based vf610_ocotp driver which has > already been in mainline for a while now. Also now a new syscon > abstraction "syscon_regmap_read_from_offset" is implemented and > exported from syscon allowing accessing a register from a syscon > reference like this > > ocotp-cfg1 = < 0x20>; > > avoiding code repetition in the driver. > > One point on which we were not sure here is whether we really should > introduce a new Kconfig symbol as being introduced here. While we > could just enable it when SOC_VF610 is selected, this however would > introduce circular dependencies. > > This patch series is based on top of shawn's for-next branch and > tested on Colibri Vybrid VF50 and VF61 modules. > > Feedback is most welcome. > > [1] Older v5: > http://lkml.iu.edu/hypermail/linux/kernel/1506.0/03787.html > Even earlier versions: > Version 4 of the patchset can be found here > https://lkml.org/lkml/2015/5/26/199 > Version 3 of the patchset can be found here > http://www.spinics.net/lists/arm-kernel/msg420847.html > Version 2 of the patchset can be found here > http://www.spinics.net/lists/devicetree/msg80654.html > Version 1 of the patchset can be found here > http://www.spinics.net/lists/devicetree/msg80257.html > The RFC version can be found here > https://lkml.org/lkml/2015/5/11/13 > > Regards, > Sanchayan. > > Sanchayan Maity (4): > mfd: syscon: Introduce syscon_regmap_read_from_offset > ARM: dts: vfxxx: Add device tree node for OCOTP > ARM: dts: vfxxx: Add OCROM and phandle entries for Vybrid SoC bus driver > soc: Add SoC bus driver for Freescale Vybrid Platform > > arch/arm/boot/dts/vfxxx.dtsi | 28 +++- > drivers/mfd/syscon.c | 30 > drivers/soc/Kconfig | 1 + > drivers/soc/fsl/Kconfig | 10 +++ > drivers/soc/fsl/Makefile | 1 + > drivers/soc/fsl/soc-vf610.c | 160 > +++ > include/linux/mfd/syscon.h | 10 +++ > 7 files changed, 239 insertions(+), 1 deletion(-) > create mode 100644 drivers/soc/fsl/Kconfig > create mode 100644 drivers/soc/fsl/soc-vf610.c > > -- > 2.7.2 >
Re: [PATCH v1 0/4] Implement SoC bus driver for Vybrid
Hello, Ping. - Sanchayan. On 16-03-11 14:29:27, Sanchayan Maity wrote: > Hello, > > This patchset implements SoC bus support for Freescale Vybrid platform, > implementing the following > https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-devices-soc > > This a reworked version of an older patchset series posted in June 2015 > which was at v5 then [1]. Since the NVMEM framework was then getting > introduced, we decided that first a NVMEM driver for OCOTP peripheral > being in place would be better. > > Compared to the older revisions, this driver now relies on NVMEM > consumer API using the NVMEM based vf610_ocotp driver which has > already been in mainline for a while now. Also now a new syscon > abstraction "syscon_regmap_read_from_offset" is implemented and > exported from syscon allowing accessing a register from a syscon > reference like this > > ocotp-cfg1 = < 0x20>; > > avoiding code repetition in the driver. > > One point on which we were not sure here is whether we really should > introduce a new Kconfig symbol as being introduced here. While we > could just enable it when SOC_VF610 is selected, this however would > introduce circular dependencies. > > This patch series is based on top of shawn's for-next branch and > tested on Colibri Vybrid VF50 and VF61 modules. > > Feedback is most welcome. > > [1] Older v5: > http://lkml.iu.edu/hypermail/linux/kernel/1506.0/03787.html > Even earlier versions: > Version 4 of the patchset can be found here > https://lkml.org/lkml/2015/5/26/199 > Version 3 of the patchset can be found here > http://www.spinics.net/lists/arm-kernel/msg420847.html > Version 2 of the patchset can be found here > http://www.spinics.net/lists/devicetree/msg80654.html > Version 1 of the patchset can be found here > http://www.spinics.net/lists/devicetree/msg80257.html > The RFC version can be found here > https://lkml.org/lkml/2015/5/11/13 > > Regards, > Sanchayan. > > Sanchayan Maity (4): > mfd: syscon: Introduce syscon_regmap_read_from_offset > ARM: dts: vfxxx: Add device tree node for OCOTP > ARM: dts: vfxxx: Add OCROM and phandle entries for Vybrid SoC bus driver > soc: Add SoC bus driver for Freescale Vybrid Platform > > arch/arm/boot/dts/vfxxx.dtsi | 28 +++- > drivers/mfd/syscon.c | 30 > drivers/soc/Kconfig | 1 + > drivers/soc/fsl/Kconfig | 10 +++ > drivers/soc/fsl/Makefile | 1 + > drivers/soc/fsl/soc-vf610.c | 160 > +++ > include/linux/mfd/syscon.h | 10 +++ > 7 files changed, 239 insertions(+), 1 deletion(-) > create mode 100644 drivers/soc/fsl/Kconfig > create mode 100644 drivers/soc/fsl/soc-vf610.c > > -- > 2.7.2 >
Re: [PATCH] regulator: s2mps11: Fix invalid minimal selector for buck9 supplying SD card
On 28.03.2016 14:35, Anand Moon wrote: > Should their be a fix in the u-boot for HK for this issue ? It depends whether U-Boot S2MPS11 driver has this bug or has not. I did not observe any issues with U-Boot at this matter. > mmc card detection logic is pretty old in HK u-boot. This is not related to MMC card detection logic. Best regards, Krzysztof
Re: [PATCH] regulator: s2mps11: Fix invalid minimal selector for buck9 supplying SD card
On 28.03.2016 14:35, Anand Moon wrote: > Should their be a fix in the u-boot for HK for this issue ? It depends whether U-Boot S2MPS11 driver has this bug or has not. I did not observe any issues with U-Boot at this matter. > mmc card detection logic is pretty old in HK u-boot. This is not related to MMC card detection logic. Best regards, Krzysztof
Re: [PATCH] regulator: s2mps11: Fix invalid minimal selector for buck9 supplying SD card
Hi Krzysztof On 28 March 2016 at 09:02, Krzysztof Kozlowskiwrote: > On 28.03.2016 10:59, Javier Martinez Canillas wrote: >> Hello Krzysztof, >> >> On 03/27/2016 08:54 PM, Krzysztof Kozlowski wrote: >>> The buck9 regulator of S2MPS11 PMIC lacked minimal selector for linear >>> mapping. The mapping starts from 0x40 (3 V). >>> >> >> This patch is a real fix since the the SD error goes away and the regulator >> driver probes correctly now. >> >>> This buck9 provides power to other regulators, including LDO13 and LDO19 >>> which supply the MMC2 (SD card). >>> >> >> I think it's worth mentioning that this is the case for the Exynos5422 Odroid >> XU{3,4} boards. I mean, the regulators can be used for anything but are those >> boards that use LDO19 as the SD card supply. > > Yes, indeed. I forgot to add that details. > >> >> In fact, I wonder if the subject line shouldn't be changed to something like: >> >> "regulator: s2mps11: Fix invalid min selector and voltages num for buck9" >> >> since the real problem is that the .linear_min_sel and .n_voltages are wrong. >> The fact that the SD was failing on Odroids is just a consequence of that >> (although I agree that this information should be part of the commit >> message). > > Okay, seems more accurate. > >> >>> Bootloader initializes the regulator with value of 0xff (5 V) which is >>> outside of supported voltage range. When (during boot) constraints to >>> buck9 were applied, the driver wrote value counting from 0x00, not 0x40. >>> Effectively driver set lower voltage than required leading to SD card >>> detection errors on Odroid XU3/XU4: >>> mmc1: card never left busy state >>> mmc1: error -110 whilst initialising SD card >>> >>> Fixes: cb74685ecb39 ("regulator: s2mps11: Add samsung s2mps11 regulator >>> driver") >>> Cc: >>> Signed-off-by: Krzysztof Kozlowski >>> >>> --- >>> >>> The issue can be reproduced on next-20160324 with >>> bae4fdc88d7f7dda1 (regulator: core: Ensure we are at least in bounds >>> for our constraints). >>> --- >>> drivers/regulator/s2mps11.c | 19 ++- >>> include/linux/mfd/samsung/s2mps11.h | 9 + >>> 2 files changed, 27 insertions(+), 1 deletion(-) >>> >>> diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c >>> index d24e2c783dc5..caeefc38ac47 100644 >>> --- a/drivers/regulator/s2mps11.c >>> +++ b/drivers/regulator/s2mps11.c >>> @@ -324,6 +324,23 @@ static struct regulator_ops s2mps11_buck_ops = { >>> .enable_mask= S2MPS11_ENABLE_MASK \ >>> } >>> >>> +#define regulator_desc_s2mps11_buck9 { \ >>> +.name = "BUCK9", \ >>> +.id = S2MPS11_BUCK9,\ >>> +.ops= _buck_ops,\ >>> +.type = REGULATOR_VOLTAGE,\ >>> +.owner = THIS_MODULE, \ >>> +.min_uV = MIN_3000_MV, \ >>> +.uV_step= STEP_25_MV, \ >>> +.linear_min_sel = S2MPS11_BUCK9_MIN_VSEL, \ >> >> I don't have a datasheet for this PMIC but I wonder if buck9 is the only >> buck regulator whose minimal register value is != 0. If that's not the >> case, it would be good to fix the descriptions for all other regulators. > > Some of them are broken, some not. :) Buck 1-4 and 6 also should have > minimal selector. Also number of selectors and masks seems to be > invalid. I already have a plan to fix this up but it is not an urgent > task because the driver works so far. > >> >>> +.n_voltages = S2MPS11_BUCK9_N_VOLTAGES, \ >>> +.ramp_delay = S2MPS11_RAMP_DELAY, \ >>> +.vsel_reg = S2MPS11_REG_B9CTRL2, \ >>> +.vsel_mask = S2MPS11_BUCK_VSEL_MASK, \ >>> +.enable_reg = S2MPS11_REG_B9CTRL1, \ >>> +.enable_mask= S2MPS11_ENABLE_MASK \ >>> +} >>> + >>> static const struct regulator_desc s2mps11_regulators[] = { >>> regulator_desc_s2mps11_ldo(1, STEP_25_MV), >>> regulator_desc_s2mps11_ldo(2, STEP_50_MV), >>> @@ -371,7 +388,7 @@ static const struct regulator_desc s2mps11_regulators[] >>> = { >>> regulator_desc_s2mps11_buck6_10(6, MIN_600_MV, STEP_6_25_MV), >>> regulator_desc_s2mps11_buck6_10(7, MIN_600_MV, STEP_6_25_MV), >>> regulator_desc_s2mps11_buck6_10(8, MIN_600_MV, STEP_6_25_MV), >>> -regulator_desc_s2mps11_buck6_10(9, MIN_3000_MV, STEP_25_MV), >> >> Maybe the regulator_desc_s2mps11_buck6_10() define should be renamed? >> Since it's no longer true that can be used for buck6-10, so the name >> is misleading now. > > Sure. > >> >> Patch looks good to me though and as I said it fixes the issue so: >> >> Reviewed-by: Javier Martinez Canillas
Re: [PATCH] regulator: s2mps11: Fix invalid minimal selector for buck9 supplying SD card
Hi Krzysztof On 28 March 2016 at 09:02, Krzysztof Kozlowski wrote: > On 28.03.2016 10:59, Javier Martinez Canillas wrote: >> Hello Krzysztof, >> >> On 03/27/2016 08:54 PM, Krzysztof Kozlowski wrote: >>> The buck9 regulator of S2MPS11 PMIC lacked minimal selector for linear >>> mapping. The mapping starts from 0x40 (3 V). >>> >> >> This patch is a real fix since the the SD error goes away and the regulator >> driver probes correctly now. >> >>> This buck9 provides power to other regulators, including LDO13 and LDO19 >>> which supply the MMC2 (SD card). >>> >> >> I think it's worth mentioning that this is the case for the Exynos5422 Odroid >> XU{3,4} boards. I mean, the regulators can be used for anything but are those >> boards that use LDO19 as the SD card supply. > > Yes, indeed. I forgot to add that details. > >> >> In fact, I wonder if the subject line shouldn't be changed to something like: >> >> "regulator: s2mps11: Fix invalid min selector and voltages num for buck9" >> >> since the real problem is that the .linear_min_sel and .n_voltages are wrong. >> The fact that the SD was failing on Odroids is just a consequence of that >> (although I agree that this information should be part of the commit >> message). > > Okay, seems more accurate. > >> >>> Bootloader initializes the regulator with value of 0xff (5 V) which is >>> outside of supported voltage range. When (during boot) constraints to >>> buck9 were applied, the driver wrote value counting from 0x00, not 0x40. >>> Effectively driver set lower voltage than required leading to SD card >>> detection errors on Odroid XU3/XU4: >>> mmc1: card never left busy state >>> mmc1: error -110 whilst initialising SD card >>> >>> Fixes: cb74685ecb39 ("regulator: s2mps11: Add samsung s2mps11 regulator >>> driver") >>> Cc: >>> Signed-off-by: Krzysztof Kozlowski >>> >>> --- >>> >>> The issue can be reproduced on next-20160324 with >>> bae4fdc88d7f7dda1 (regulator: core: Ensure we are at least in bounds >>> for our constraints). >>> --- >>> drivers/regulator/s2mps11.c | 19 ++- >>> include/linux/mfd/samsung/s2mps11.h | 9 + >>> 2 files changed, 27 insertions(+), 1 deletion(-) >>> >>> diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c >>> index d24e2c783dc5..caeefc38ac47 100644 >>> --- a/drivers/regulator/s2mps11.c >>> +++ b/drivers/regulator/s2mps11.c >>> @@ -324,6 +324,23 @@ static struct regulator_ops s2mps11_buck_ops = { >>> .enable_mask= S2MPS11_ENABLE_MASK \ >>> } >>> >>> +#define regulator_desc_s2mps11_buck9 { \ >>> +.name = "BUCK9", \ >>> +.id = S2MPS11_BUCK9,\ >>> +.ops= _buck_ops,\ >>> +.type = REGULATOR_VOLTAGE,\ >>> +.owner = THIS_MODULE, \ >>> +.min_uV = MIN_3000_MV, \ >>> +.uV_step= STEP_25_MV, \ >>> +.linear_min_sel = S2MPS11_BUCK9_MIN_VSEL, \ >> >> I don't have a datasheet for this PMIC but I wonder if buck9 is the only >> buck regulator whose minimal register value is != 0. If that's not the >> case, it would be good to fix the descriptions for all other regulators. > > Some of them are broken, some not. :) Buck 1-4 and 6 also should have > minimal selector. Also number of selectors and masks seems to be > invalid. I already have a plan to fix this up but it is not an urgent > task because the driver works so far. > >> >>> +.n_voltages = S2MPS11_BUCK9_N_VOLTAGES, \ >>> +.ramp_delay = S2MPS11_RAMP_DELAY, \ >>> +.vsel_reg = S2MPS11_REG_B9CTRL2, \ >>> +.vsel_mask = S2MPS11_BUCK_VSEL_MASK, \ >>> +.enable_reg = S2MPS11_REG_B9CTRL1, \ >>> +.enable_mask= S2MPS11_ENABLE_MASK \ >>> +} >>> + >>> static const struct regulator_desc s2mps11_regulators[] = { >>> regulator_desc_s2mps11_ldo(1, STEP_25_MV), >>> regulator_desc_s2mps11_ldo(2, STEP_50_MV), >>> @@ -371,7 +388,7 @@ static const struct regulator_desc s2mps11_regulators[] >>> = { >>> regulator_desc_s2mps11_buck6_10(6, MIN_600_MV, STEP_6_25_MV), >>> regulator_desc_s2mps11_buck6_10(7, MIN_600_MV, STEP_6_25_MV), >>> regulator_desc_s2mps11_buck6_10(8, MIN_600_MV, STEP_6_25_MV), >>> -regulator_desc_s2mps11_buck6_10(9, MIN_3000_MV, STEP_25_MV), >> >> Maybe the regulator_desc_s2mps11_buck6_10() define should be renamed? >> Since it's no longer true that can be used for buck6-10, so the name >> is misleading now. > > Sure. > >> >> Patch looks good to me though and as I said it fixes the issue so: >> >> Reviewed-by: Javier Martinez Canillas >> Tested-by: Javier Martinez Canillas > > Thanks! > > I'll update patch as you suggested and
Re: [PATCH v6 5/7][Resend] cpufreq: Move governor symbols to cpufreq.h
On 22-03-16, 02:51, Rafael J. Wysocki wrote: > From: Rafael J. Wysocki> > Move definitions of symbols related to transition latency and > sampling rate to include/linux/cpufreq.h so they can be used by > (future) goverernors located outside of drivers/cpufreq/. s/goverernors/governors > > No functional changes. > > Signed-off-by: Rafael J. Wysocki > --- > > This patch was new in v4, no changes since then. > > --- > drivers/cpufreq/cpufreq_governor.h | 14 -- > include/linux/cpufreq.h| 14 ++ > 2 files changed, 14 insertions(+), 14 deletions(-) Acked-by: Viresh Kumar -- viresh
Re: [PATCH v6 5/7][Resend] cpufreq: Move governor symbols to cpufreq.h
On 22-03-16, 02:51, Rafael J. Wysocki wrote: > From: Rafael J. Wysocki > > Move definitions of symbols related to transition latency and > sampling rate to include/linux/cpufreq.h so they can be used by > (future) goverernors located outside of drivers/cpufreq/. s/goverernors/governors > > No functional changes. > > Signed-off-by: Rafael J. Wysocki > --- > > This patch was new in v4, no changes since then. > > --- > drivers/cpufreq/cpufreq_governor.h | 14 -- > include/linux/cpufreq.h| 14 ++ > 2 files changed, 14 insertions(+), 14 deletions(-) Acked-by: Viresh Kumar -- viresh
Re: Warnings for invalid VDD (sdhci-s3c)
On 27.03.2016 16:41, Anand Moon wrote: > > On My Odroid U3 with debug flags enable I am observing bellow deadlock. There is a sleep in atomic context and possible deadlock, but: 1. Are you sure it does not happen without the patch? 2. Are you sure it is not the same as already known issue on sdhci-s3c? For example reported here: http://www.spinics.net/lists/linux-samsung-soc/msg42398.html What is reproducibility rate? Best regards, Krzysztof > - > [ 202.519524] BUG: sleeping function called from invalid context at > kernel/locking/mutex.c:617 > [ 202.522364] in_atomic(): 1, irqs_disabled(): 128, pid: 100, name: mmcqd/0 > [ 202.529129] 1 lock held by mmcqd/0/100: > [ 202.529150] #0: (&(>lock)->rlock#2){-.-...}, at: > [] sdhci_do_set_ios+0x1c/0x484 > [ 202.529271] irq event stamp: 703530 > [ 202.529291] hardirqs last enabled at (703529): [] > _raw_spin_unlock_irqrestore+0x6c/0x74 > [ 202.529343] hardirqs last disabled at (703530): [] > _raw_spin_lock_irqsave+0x1c/0x84 > [ 202.529384] softirqs last enabled at (703456): [] > __do_softirq+0x244/0x2c0 > [ 202.529438] softirqs last disabled at (703445): [] > irq_exit+0xec/0x128 > [ 202.529472] Preemption disabled at:[< (null)>] (null) > [ 202.534415] > [ 202.534449] CPU: 0 PID: 100 Comm: mmcqd/0 Not tainted 4.6.0-rc1-u3s #38 > [ 202.534473] Hardware name: SAMSUNG EXYNOS (Flattened Device Tree) > [ 202.534544] [] (unwind_backtrace) from [] > (show_stack+0x10/0x14) > [ 202.534594] [] (show_stack) from [] > (dump_stack+0x98/0xc4) > [ 202.534639] [] (dump_stack) from [] > (mutex_lock_nested+0x2c/0x4dc) > [ 202.534685] [] (mutex_lock_nested) from [] > (clk_prepare_lock+0x50/0xf8) > [ 202.534726] [] (clk_prepare_lock) from [] > (clk_round_rate+0x1c/0x58) > [ 202.534773] [] (clk_round_rate) from [] > (sdhci_s3c_set_clock+0x18c/0x1b0) > [ 202.534819] [] (sdhci_s3c_set_clock) from [] > (sdhci_cmu_set_clock+0x24/0x17c) > [ 202.534860] [] (sdhci_cmu_set_clock) from [] > (sdhci_do_set_ios+0x78/0x484) > [ 202.534904] [] (sdhci_do_set_ios) from [] > (sdhci_runtime_resume_host+0x60/0x114) > [ 202.534957] [] (sdhci_runtime_resume_host) from > [] (__rpm_callback+0x2c/0x60) > [ 202.535000] [] (__rpm_callback) from [] > (rpm_callback+0x54/0x80) > [ 202.535041] [] (rpm_callback) from [] > (rpm_resume+0x364/0x558) > [ 202.535081] [] (rpm_resume) from [] > (__pm_runtime_resume+0x60/0x8c) > [ 202.535125] [] (__pm_runtime_resume) from [] > (__mmc_claim_host+0x1b4/0x1f8) > [ 202.535176] [] (__mmc_claim_host) from [] > (mmc_sd_runtime_resume+0x20/0xac) > [ 202.535220] [] (mmc_sd_runtime_resume) from [] > (__rpm_callback+0x2c/0x60) > [ 202.535259] [] (__rpm_callback) from [] > (rpm_callback+0x54/0x80) > [ 202.535299] [] (rpm_callback) from [] > (rpm_resume+0x364/0x558) > [ 202.535340] [] (rpm_resume) from [] > (__pm_runtime_resume+0x60/0x8c) > [ 202.535379] [] (__pm_runtime_resume) from [] > (mmc_get_card+0x14/0x24) > [ 202.535420] [] (mmc_get_card) from [] > (mmc_blk_issue_rq+0x258/0x4f0) > [ 202.535461] [] (mmc_blk_issue_rq) from [] > (mmc_queue_thread+0xd0/0x1d8) > [ 202.535513] [] (mmc_queue_thread) from [] > (kthread+0xf4/0x10c) > [ 202.535561] [] (kthread) from [] > (ret_from_fork+0x14/0x24) > [ 202.535624] > [ 202.535893] == > [ 202.542059] [ INFO: HARDIRQ-safe -> HARDIRQ-unsafe lock order detected ] > [ 202.548742] 4.6.0-rc1-u3s #38 Not tainted > [ 202.552732] -- > [ 202.558902] mmcqd/0/100 [HC0[0]:SC0[0]:HE0:SE1] is trying to acquire: > [ 202.565317] (prepare_lock){+.+...}, at: [] > clk_prepare_lock+0x50/0xf8 > [ 202.572695] > [ 202.572695] and this task is already holding: > [ 202.578510] (&(>lock)->rlock#2){-.-...}, at: [] > sdhci_do_set_ios+0x1c/0x484 > [ 202.586930] which would create a new lock dependency: > [ 202.591964] (&(>lock)->rlock#2){-.-...} -> (prepare_lock){+.+...} > [ 202.598650] > [ 202.598650] but this new dependency connects a HARDIRQ-irq-safe lock: > [ 202.606546] (&(>lock)->rlock#2){-.-...} > [ 202.606546] ... which became HARDIRQ-irq-safe at: > [ 202.614359] [] _raw_spin_lock+0x3c/0x74 > [ 202.619219] [] sdhci_irq+0x1c/0x814 > [ 202.623732] [] handle_irq_event_percpu+0x9c/0x150 > [ 202.629461] [] handle_irq_event+0x38/0x5c > [ 202.634495] [] handle_fasteoi_irq+0xd0/0x1a8 > [ 202.639790] [] generic_handle_irq+0x24/0x34 > [ 202.644998] [] __handle_domain_irq+0x7c/0xec > [ 202.650293] [] gic_handle_irq+0x54/0x94 > [ 202.655154] [] __irq_svc+0x58/0x98 > [ 202.659581] [] arch_cpu_idle+0x24/0x3c > [ 202.664354] [] arch_cpu_idle+0x24/0x3c > [ 202.669128] [] cpu_startup_entry+0x1c8/0x24c > [ 202.674423] [] start_kernel+0x39c/0x3a8 > [ 202.679284] [<4000807c>] 0x4000807c > [ 202.682933] > [ 202.682933] to a HARDIRQ-irq-unsafe lock: > [ 202.688399]
Re: Warnings for invalid VDD (sdhci-s3c)
On 27.03.2016 16:41, Anand Moon wrote: > > On My Odroid U3 with debug flags enable I am observing bellow deadlock. There is a sleep in atomic context and possible deadlock, but: 1. Are you sure it does not happen without the patch? 2. Are you sure it is not the same as already known issue on sdhci-s3c? For example reported here: http://www.spinics.net/lists/linux-samsung-soc/msg42398.html What is reproducibility rate? Best regards, Krzysztof > - > [ 202.519524] BUG: sleeping function called from invalid context at > kernel/locking/mutex.c:617 > [ 202.522364] in_atomic(): 1, irqs_disabled(): 128, pid: 100, name: mmcqd/0 > [ 202.529129] 1 lock held by mmcqd/0/100: > [ 202.529150] #0: (&(>lock)->rlock#2){-.-...}, at: > [] sdhci_do_set_ios+0x1c/0x484 > [ 202.529271] irq event stamp: 703530 > [ 202.529291] hardirqs last enabled at (703529): [] > _raw_spin_unlock_irqrestore+0x6c/0x74 > [ 202.529343] hardirqs last disabled at (703530): [] > _raw_spin_lock_irqsave+0x1c/0x84 > [ 202.529384] softirqs last enabled at (703456): [] > __do_softirq+0x244/0x2c0 > [ 202.529438] softirqs last disabled at (703445): [] > irq_exit+0xec/0x128 > [ 202.529472] Preemption disabled at:[< (null)>] (null) > [ 202.534415] > [ 202.534449] CPU: 0 PID: 100 Comm: mmcqd/0 Not tainted 4.6.0-rc1-u3s #38 > [ 202.534473] Hardware name: SAMSUNG EXYNOS (Flattened Device Tree) > [ 202.534544] [] (unwind_backtrace) from [] > (show_stack+0x10/0x14) > [ 202.534594] [] (show_stack) from [] > (dump_stack+0x98/0xc4) > [ 202.534639] [] (dump_stack) from [] > (mutex_lock_nested+0x2c/0x4dc) > [ 202.534685] [] (mutex_lock_nested) from [] > (clk_prepare_lock+0x50/0xf8) > [ 202.534726] [] (clk_prepare_lock) from [] > (clk_round_rate+0x1c/0x58) > [ 202.534773] [] (clk_round_rate) from [] > (sdhci_s3c_set_clock+0x18c/0x1b0) > [ 202.534819] [] (sdhci_s3c_set_clock) from [] > (sdhci_cmu_set_clock+0x24/0x17c) > [ 202.534860] [] (sdhci_cmu_set_clock) from [] > (sdhci_do_set_ios+0x78/0x484) > [ 202.534904] [] (sdhci_do_set_ios) from [] > (sdhci_runtime_resume_host+0x60/0x114) > [ 202.534957] [] (sdhci_runtime_resume_host) from > [] (__rpm_callback+0x2c/0x60) > [ 202.535000] [] (__rpm_callback) from [] > (rpm_callback+0x54/0x80) > [ 202.535041] [] (rpm_callback) from [] > (rpm_resume+0x364/0x558) > [ 202.535081] [] (rpm_resume) from [] > (__pm_runtime_resume+0x60/0x8c) > [ 202.535125] [] (__pm_runtime_resume) from [] > (__mmc_claim_host+0x1b4/0x1f8) > [ 202.535176] [] (__mmc_claim_host) from [] > (mmc_sd_runtime_resume+0x20/0xac) > [ 202.535220] [] (mmc_sd_runtime_resume) from [] > (__rpm_callback+0x2c/0x60) > [ 202.535259] [] (__rpm_callback) from [] > (rpm_callback+0x54/0x80) > [ 202.535299] [] (rpm_callback) from [] > (rpm_resume+0x364/0x558) > [ 202.535340] [] (rpm_resume) from [] > (__pm_runtime_resume+0x60/0x8c) > [ 202.535379] [] (__pm_runtime_resume) from [] > (mmc_get_card+0x14/0x24) > [ 202.535420] [] (mmc_get_card) from [] > (mmc_blk_issue_rq+0x258/0x4f0) > [ 202.535461] [] (mmc_blk_issue_rq) from [] > (mmc_queue_thread+0xd0/0x1d8) > [ 202.535513] [] (mmc_queue_thread) from [] > (kthread+0xf4/0x10c) > [ 202.535561] [] (kthread) from [] > (ret_from_fork+0x14/0x24) > [ 202.535624] > [ 202.535893] == > [ 202.542059] [ INFO: HARDIRQ-safe -> HARDIRQ-unsafe lock order detected ] > [ 202.548742] 4.6.0-rc1-u3s #38 Not tainted > [ 202.552732] -- > [ 202.558902] mmcqd/0/100 [HC0[0]:SC0[0]:HE0:SE1] is trying to acquire: > [ 202.565317] (prepare_lock){+.+...}, at: [] > clk_prepare_lock+0x50/0xf8 > [ 202.572695] > [ 202.572695] and this task is already holding: > [ 202.578510] (&(>lock)->rlock#2){-.-...}, at: [] > sdhci_do_set_ios+0x1c/0x484 > [ 202.586930] which would create a new lock dependency: > [ 202.591964] (&(>lock)->rlock#2){-.-...} -> (prepare_lock){+.+...} > [ 202.598650] > [ 202.598650] but this new dependency connects a HARDIRQ-irq-safe lock: > [ 202.606546] (&(>lock)->rlock#2){-.-...} > [ 202.606546] ... which became HARDIRQ-irq-safe at: > [ 202.614359] [] _raw_spin_lock+0x3c/0x74 > [ 202.619219] [] sdhci_irq+0x1c/0x814 > [ 202.623732] [] handle_irq_event_percpu+0x9c/0x150 > [ 202.629461] [] handle_irq_event+0x38/0x5c > [ 202.634495] [] handle_fasteoi_irq+0xd0/0x1a8 > [ 202.639790] [] generic_handle_irq+0x24/0x34 > [ 202.644998] [] __handle_domain_irq+0x7c/0xec > [ 202.650293] [] gic_handle_irq+0x54/0x94 > [ 202.655154] [] __irq_svc+0x58/0x98 > [ 202.659581] [] arch_cpu_idle+0x24/0x3c > [ 202.664354] [] arch_cpu_idle+0x24/0x3c > [ 202.669128] [] cpu_startup_entry+0x1c8/0x24c > [ 202.674423] [] start_kernel+0x39c/0x3a8 > [ 202.679284] [<4000807c>] 0x4000807c > [ 202.682933] > [ 202.682933] to a HARDIRQ-irq-unsafe lock: > [ 202.688399]
Re: [PATCH 0/2] scsi: remove orphaned modular code from non-modular drivers
On Sun, 2016-03-27 at 13:00 -0400, Paul Gortmaker wrote: > In the ongoing audit/cleanup of non-modular code needlessly using > modular infrastructure, the SCSI subsystem fortunately only contains > two instances that I detected. Both are for legacy drivers that > predate the git epoch, so cleary there is no demand for converting > these drivers to be tristate. > > For anyone new to the underlying goal of this cleanup, we are trying > to not use module support for code that isn't buildable as a module > since: > > (1) it is easy to accidentally write unused module_exit and remove > code > (2) it can be misleading when reading the source, thinking it can be > modular when the Makefile and/or Kconfig prohibit it > (3) it requires the include of the module.h header file which in > turn > includes nearly everything else, thus adding to CPP overhead. > (4) it gets copied/replicated into other code and spreads like > weeds. I don't really buy any of these as being credible issues for the ancient drivers, so there doesn't appear to be an real benefit to this conversion; however, besides the danger of touching old stuff, there are some down sides: > -MODULE_DESCRIPTION("Sun3x ESP SCSI driver"); > -MODULE_AUTHOR("Thomas Bogendoerfer (tsbog...@alpha.franken.de)"); > -MODULE_LICENSE("GPL"); > -MODULE_VERSION(DRV_VERSION); These tags are usefully greppable for drivers, regardless of whether they generate actual kernel side information. > We explicitly disallow a driver unbind, since that doesn't have a > sensible use case anyway, and it allows us to drop the ".remove" > code for non-modular drivers. That's bogus. I use bind and unbind a lot for testing built in drivers but the usual user use case is for resetting the devices. > Build tested for mips (jazz) and m68k (sun3x) on 4.6-rc1 to ensure no > silly typos crept in. For trivial changes, build testing is not really sufficient: a significant fraction of them break something that isn't spotted by the reviewers. For the older drivers, this isn't discovered for months to years and then someone has to go digging back through all the so called trivial changes to find which one it was. James
[PATCH v5 5/6] hwmon: (fam15h_power) Add documentation for TDP and accumulated power algorithm
This patch adds the description to explain the TDP reporting mechanism and accumulated power algorithm. Signed-off-by: Huang RuiCc: Borislav Petkov --- Documentation/hwmon/fam15h_power | 57 +++- drivers/hwmon/fam15h_power.c | 2 +- 2 files changed, 57 insertions(+), 2 deletions(-) diff --git a/Documentation/hwmon/fam15h_power b/Documentation/hwmon/fam15h_power index e2b1b69..2c4fbee 100644 --- a/Documentation/hwmon/fam15h_power +++ b/Documentation/hwmon/fam15h_power @@ -10,14 +10,22 @@ Supported chips: Datasheets: BIOS and Kernel Developer's Guide (BKDG) For AMD Family 15h Processors BIOS and Kernel Developer's Guide (BKDG) For AMD Family 16h Processors + AMD64 Architecture Programmer's Manual Volume 2: System Programming Author: Andreas Herrmann Description --- +1) Processor TDP (Thermal design power) + +Given a fixed frequency and voltage, the power consumption of a +processor varies based on the workload being executed. Derated power +is the power consumed when running a specific application. Thermal +design power (TDP) is an example of derated power. + This driver permits reading of registers providing power information -of AMD Family 15h and 16h processors. +of AMD Family 15h and 16h processors via TDP algorithm. For AMD Family 15h and 16h processors the following power values can be calculated using different processor northbridge function @@ -37,3 +45,50 @@ This driver provides ProcessorPwrWatts and CurrPwrWatts: On multi-node processors the calculated value is for the entire package and not for a single node. Thus the driver creates sysfs attributes only for internal node0 of a multi-node processor. + +2) Accumulated Power Mechanism + +This driver also introduces an algorithm that should be used to +calculate the average power consumed by a processor during a +measurement interval Tm. The feature of accumulated power mechanism is +indicated by CPUID Fn8000_0007_EDX[12]. + +* Tsample: compute unit power accumulator sample period +* Tref: the PTSC counter period +* PTSC: performance timestamp counter +* N: the ratio of compute unit power accumulator sample period to the + PTSC period +* Jmax: max compute unit accumulated power which is indicated by + MaxCpuSwPwrAcc MSR C001007b +* Jx/Jy: compute unit accumulated power which is indicated by + CpuSwPwrAcc MSR C001007a +* Tx/Ty: the value of performance timestamp counter which is indicated + by CU_PTSC MSR C0010280 +* PwrCPUave: CPU average power + +i. Determine the ratio of Tsample to Tref by executing CPUID Fn8000_0007. + N = value of CPUID Fn8000_0007_ECX[CpuPwrSampleTimeRatio[15:0]]. + +ii. Read the full range of the cumulative energy value from the new +MSR MaxCpuSwPwrAcc. + Jmax = value returned. +iii. At time x, SW reads CpuSwPwrAcc MSR and samples the PTSC. + Jx = value read from CpuSwPwrAcc and Tx = value read from +PTSC. + +iv. At time y, SW reads CpuSwPwrAcc MSR and samples the PTSC. + Jy = value read from CpuSwPwrAcc and Ty = value read from +PTSC. + +v. Calculate the average power consumption for a compute unit over +time period (y-x). Unit of result is uWatt. + if (Jy < Jx) // Rollover has occurred + Jdelta = (Jy + Jmax) - Jx + else + Jdelta = Jy - Jx + PwrCPUave = N * Jdelta * 1000 / (Ty - Tx) + +This driver provides PwrCPUave and interval(default is 10 millisecond +and maximum is 1 second): +* power1_average (PwrCPUave) +* power1_average_interval (Interval) diff --git a/drivers/hwmon/fam15h_power.c b/drivers/hwmon/fam15h_power.c index 003564b..c1cad26 100644 --- a/drivers/hwmon/fam15h_power.c +++ b/drivers/hwmon/fam15h_power.c @@ -1,7 +1,7 @@ /* * fam15h_power.c - AMD Family 15h processor power monitoring * - * Copyright (c) 2011 Advanced Micro Devices, Inc. + * Copyright (c) 2011-2016 Advanced Micro Devices, Inc. * Author: Andreas Herrmann * * -- 1.9.1
Re: [PATCH 0/2] scsi: remove orphaned modular code from non-modular drivers
On Sun, 2016-03-27 at 13:00 -0400, Paul Gortmaker wrote: > In the ongoing audit/cleanup of non-modular code needlessly using > modular infrastructure, the SCSI subsystem fortunately only contains > two instances that I detected. Both are for legacy drivers that > predate the git epoch, so cleary there is no demand for converting > these drivers to be tristate. > > For anyone new to the underlying goal of this cleanup, we are trying > to not use module support for code that isn't buildable as a module > since: > > (1) it is easy to accidentally write unused module_exit and remove > code > (2) it can be misleading when reading the source, thinking it can be > modular when the Makefile and/or Kconfig prohibit it > (3) it requires the include of the module.h header file which in > turn > includes nearly everything else, thus adding to CPP overhead. > (4) it gets copied/replicated into other code and spreads like > weeds. I don't really buy any of these as being credible issues for the ancient drivers, so there doesn't appear to be an real benefit to this conversion; however, besides the danger of touching old stuff, there are some down sides: > -MODULE_DESCRIPTION("Sun3x ESP SCSI driver"); > -MODULE_AUTHOR("Thomas Bogendoerfer (tsbog...@alpha.franken.de)"); > -MODULE_LICENSE("GPL"); > -MODULE_VERSION(DRV_VERSION); These tags are usefully greppable for drivers, regardless of whether they generate actual kernel side information. > We explicitly disallow a driver unbind, since that doesn't have a > sensible use case anyway, and it allows us to drop the ".remove" > code for non-modular drivers. That's bogus. I use bind and unbind a lot for testing built in drivers but the usual user use case is for resetting the devices. > Build tested for mips (jazz) and m68k (sun3x) on 4.6-rc1 to ensure no > silly typos crept in. For trivial changes, build testing is not really sufficient: a significant fraction of them break something that isn't spotted by the reviewers. For the older drivers, this isn't discovered for months to years and then someone has to go digging back through all the so called trivial changes to find which one it was. James
[PATCH v5 5/6] hwmon: (fam15h_power) Add documentation for TDP and accumulated power algorithm
This patch adds the description to explain the TDP reporting mechanism and accumulated power algorithm. Signed-off-by: Huang Rui Cc: Borislav Petkov --- Documentation/hwmon/fam15h_power | 57 +++- drivers/hwmon/fam15h_power.c | 2 +- 2 files changed, 57 insertions(+), 2 deletions(-) diff --git a/Documentation/hwmon/fam15h_power b/Documentation/hwmon/fam15h_power index e2b1b69..2c4fbee 100644 --- a/Documentation/hwmon/fam15h_power +++ b/Documentation/hwmon/fam15h_power @@ -10,14 +10,22 @@ Supported chips: Datasheets: BIOS and Kernel Developer's Guide (BKDG) For AMD Family 15h Processors BIOS and Kernel Developer's Guide (BKDG) For AMD Family 16h Processors + AMD64 Architecture Programmer's Manual Volume 2: System Programming Author: Andreas Herrmann Description --- +1) Processor TDP (Thermal design power) + +Given a fixed frequency and voltage, the power consumption of a +processor varies based on the workload being executed. Derated power +is the power consumed when running a specific application. Thermal +design power (TDP) is an example of derated power. + This driver permits reading of registers providing power information -of AMD Family 15h and 16h processors. +of AMD Family 15h and 16h processors via TDP algorithm. For AMD Family 15h and 16h processors the following power values can be calculated using different processor northbridge function @@ -37,3 +45,50 @@ This driver provides ProcessorPwrWatts and CurrPwrWatts: On multi-node processors the calculated value is for the entire package and not for a single node. Thus the driver creates sysfs attributes only for internal node0 of a multi-node processor. + +2) Accumulated Power Mechanism + +This driver also introduces an algorithm that should be used to +calculate the average power consumed by a processor during a +measurement interval Tm. The feature of accumulated power mechanism is +indicated by CPUID Fn8000_0007_EDX[12]. + +* Tsample: compute unit power accumulator sample period +* Tref: the PTSC counter period +* PTSC: performance timestamp counter +* N: the ratio of compute unit power accumulator sample period to the + PTSC period +* Jmax: max compute unit accumulated power which is indicated by + MaxCpuSwPwrAcc MSR C001007b +* Jx/Jy: compute unit accumulated power which is indicated by + CpuSwPwrAcc MSR C001007a +* Tx/Ty: the value of performance timestamp counter which is indicated + by CU_PTSC MSR C0010280 +* PwrCPUave: CPU average power + +i. Determine the ratio of Tsample to Tref by executing CPUID Fn8000_0007. + N = value of CPUID Fn8000_0007_ECX[CpuPwrSampleTimeRatio[15:0]]. + +ii. Read the full range of the cumulative energy value from the new +MSR MaxCpuSwPwrAcc. + Jmax = value returned. +iii. At time x, SW reads CpuSwPwrAcc MSR and samples the PTSC. + Jx = value read from CpuSwPwrAcc and Tx = value read from +PTSC. + +iv. At time y, SW reads CpuSwPwrAcc MSR and samples the PTSC. + Jy = value read from CpuSwPwrAcc and Ty = value read from +PTSC. + +v. Calculate the average power consumption for a compute unit over +time period (y-x). Unit of result is uWatt. + if (Jy < Jx) // Rollover has occurred + Jdelta = (Jy + Jmax) - Jx + else + Jdelta = Jy - Jx + PwrCPUave = N * Jdelta * 1000 / (Ty - Tx) + +This driver provides PwrCPUave and interval(default is 10 millisecond +and maximum is 1 second): +* power1_average (PwrCPUave) +* power1_average_interval (Interval) diff --git a/drivers/hwmon/fam15h_power.c b/drivers/hwmon/fam15h_power.c index 003564b..c1cad26 100644 --- a/drivers/hwmon/fam15h_power.c +++ b/drivers/hwmon/fam15h_power.c @@ -1,7 +1,7 @@ /* * fam15h_power.c - AMD Family 15h processor power monitoring * - * Copyright (c) 2011 Advanced Micro Devices, Inc. + * Copyright (c) 2011-2016 Advanced Micro Devices, Inc. * Author: Andreas Herrmann * * -- 1.9.1
[PATCH v5 6/6] hwmon: (fam15h_power) Add platform check function
This patch adds a platform check function to make code more readable. Signed-off-by: Huang Rui--- drivers/hwmon/fam15h_power.c | 9 +++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/hwmon/fam15h_power.c b/drivers/hwmon/fam15h_power.c index c1cad26..622c646 100644 --- a/drivers/hwmon/fam15h_power.c +++ b/drivers/hwmon/fam15h_power.c @@ -78,6 +78,11 @@ struct fam15h_power_data { unsigned long power_period; }; +static bool is_carrizo_or_later(void) +{ + return boot_cpu_data.x86 == 0x15 && boot_cpu_data.x86_model >= 0x60; +} + static ssize_t show_power(struct device *dev, struct device_attribute *attr, char *buf) { @@ -94,7 +99,7 @@ static ssize_t show_power(struct device *dev, * On Carrizo and later platforms, TdpRunAvgAccCap bit field * is extended to 4:31 from 4:25. */ - if (boot_cpu_data.x86 == 0x15 && boot_cpu_data.x86_model >= 0x60) { + if (is_carrizo_or_later()) { running_avg_capture = val >> 4; running_avg_capture = sign_extend32(running_avg_capture, 27); } else { @@ -111,7 +116,7 @@ static ssize_t show_power(struct device *dev, * On Carrizo and later platforms, ApmTdpLimit bit field * is extended to 16:31 from 16:28. */ - if (boot_cpu_data.x86 == 0x15 && boot_cpu_data.x86_model >= 0x60) + if (is_carrizo_or_later()) tdp_limit = val >> 16; else tdp_limit = (val >> 16) & 0x1fff; -- 1.9.1
[PATCH v5 4/6] hwmon: (fam15h_power) Introduce a cpu accumulated power reporting algorithm
This patch introduces an algorithm that computes the average power by reading a delta value of “core power accumulator” register during measurement interval, and then dividing delta value by the length of the time interval. User is able to use power1_average entry to measure the processor power consumption and power1_average_interval entry to set the interval. A simple example: ray@hr-ub:~/tip$ sensors fam15h_power-pci-00c4 Adapter: PCI adapter power1: 19.58 mW (avg = 2.55 mW, interval = 0.01 s) (crit = 15.00 W) ... The result is current average processor power consumption in 10 millisecond. The unit of the result is uWatt. Suggested-by: Guenter RoeckSigned-off-by: Huang Rui Cc: Borislav Petkov --- drivers/hwmon/fam15h_power.c | 119 +++ 1 file changed, 119 insertions(+) diff --git a/drivers/hwmon/fam15h_power.c b/drivers/hwmon/fam15h_power.c index de6f52b..003564b 100644 --- a/drivers/hwmon/fam15h_power.c +++ b/drivers/hwmon/fam15h_power.c @@ -27,6 +27,8 @@ #include #include #include +#include +#include #include #include @@ -48,6 +50,9 @@ MODULE_LICENSE("GPL"); #define FAM15H_NUM_GROUPS 2 #define MAX_CUS8 +/* set maximum interval as 1 second */ +#define MAX_INTERVAL 1000 + #define MSR_F15H_CU_PWR_ACCUMULATOR0xc001007a #define MSR_F15H_CU_MAX_PWR_ACCUMULATOR0xc001007b #define MSR_F15H_PTSC 0xc0010280 @@ -68,6 +73,9 @@ struct fam15h_power_data { u64 cu_acc_power[MAX_CUS]; /* performance timestamp counter */ u64 cpu_sw_pwr_ptsc[MAX_CUS]; + /* online/offline status of current compute unit */ + int cu_on[MAX_CUS]; + unsigned long power_period; }; static ssize_t show_power(struct device *dev, @@ -149,6 +157,8 @@ static void do_read_registers_on_cu(void *_data) rdmsrl_safe(MSR_F15H_CU_PWR_ACCUMULATOR, >cu_acc_power[cu]); rdmsrl_safe(MSR_F15H_PTSC, >cpu_sw_pwr_ptsc[cu]); + + data->cu_on[cu] = 1; } /* @@ -165,6 +175,8 @@ static int read_registers(struct fam15h_power_data *data) if (!ret) return -ENOMEM; + memset(data->cu_on, 0, sizeof(int) * MAX_CUS); + get_online_cpus(); this_cpu = get_cpu(); @@ -192,18 +204,117 @@ static int read_registers(struct fam15h_power_data *data) return 0; } +static ssize_t acc_show_power(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct fam15h_power_data *data = dev_get_drvdata(dev); + u64 prev_cu_acc_power[MAX_CUS], prev_ptsc[MAX_CUS], + jdelta[MAX_CUS]; + u64 tdelta, avg_acc; + int cu, cu_num, ret; + signed long leftover; + + /* +* With the new x86 topology modelling, x86_max_cores is the +* compute unit number. +*/ + cu_num = boot_cpu_data.x86_max_cores; + + ret = read_registers(data); + if (ret) + return 0; + + for (cu = 0; cu < cu_num; cu++) { + prev_cu_acc_power[cu] = data->cu_acc_power[cu]; + prev_ptsc[cu] = data->cpu_sw_pwr_ptsc[cu]; + } + + leftover = schedule_timeout_interruptible(msecs_to_jiffies(data->power_period)); + if (leftover) + return 0; + + ret = read_registers(data); + if (ret) + return 0; + + for (cu = 0, avg_acc = 0; cu < cu_num; cu++) { + /* check if current compute unit is online */ + if (data->cu_on[cu] == 0) + continue; + + if (data->cu_acc_power[cu] < prev_cu_acc_power[cu]) { + jdelta[cu] = data->max_cu_acc_power + data->cu_acc_power[cu]; + jdelta[cu] -= prev_cu_acc_power[cu]; + } else { + jdelta[cu] = data->cu_acc_power[cu] - prev_cu_acc_power[cu]; + } + tdelta = data->cpu_sw_pwr_ptsc[cu] - prev_ptsc[cu]; + jdelta[cu] *= data->cpu_pwr_sample_ratio * 1000; + do_div(jdelta[cu], tdelta); + + /* the unit is microWatt */ + avg_acc += jdelta[cu]; + } + + return sprintf(buf, "%llu\n", (unsigned long long)avg_acc); +} +static DEVICE_ATTR(power1_average, S_IRUGO, acc_show_power, NULL); + +static ssize_t acc_show_power_period(struct device *dev, +struct device_attribute *attr, +char *buf) +{ + struct fam15h_power_data *data = dev_get_drvdata(dev); + + return sprintf(buf, "%lu\n", data->power_period); +} + +static ssize_t acc_set_power_period(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t
[PATCH v5 6/6] hwmon: (fam15h_power) Add platform check function
This patch adds a platform check function to make code more readable. Signed-off-by: Huang Rui --- drivers/hwmon/fam15h_power.c | 9 +++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/hwmon/fam15h_power.c b/drivers/hwmon/fam15h_power.c index c1cad26..622c646 100644 --- a/drivers/hwmon/fam15h_power.c +++ b/drivers/hwmon/fam15h_power.c @@ -78,6 +78,11 @@ struct fam15h_power_data { unsigned long power_period; }; +static bool is_carrizo_or_later(void) +{ + return boot_cpu_data.x86 == 0x15 && boot_cpu_data.x86_model >= 0x60; +} + static ssize_t show_power(struct device *dev, struct device_attribute *attr, char *buf) { @@ -94,7 +99,7 @@ static ssize_t show_power(struct device *dev, * On Carrizo and later platforms, TdpRunAvgAccCap bit field * is extended to 4:31 from 4:25. */ - if (boot_cpu_data.x86 == 0x15 && boot_cpu_data.x86_model >= 0x60) { + if (is_carrizo_or_later()) { running_avg_capture = val >> 4; running_avg_capture = sign_extend32(running_avg_capture, 27); } else { @@ -111,7 +116,7 @@ static ssize_t show_power(struct device *dev, * On Carrizo and later platforms, ApmTdpLimit bit field * is extended to 16:31 from 16:28. */ - if (boot_cpu_data.x86 == 0x15 && boot_cpu_data.x86_model >= 0x60) + if (is_carrizo_or_later()) tdp_limit = val >> 16; else tdp_limit = (val >> 16) & 0x1fff; -- 1.9.1
[PATCH v5 4/6] hwmon: (fam15h_power) Introduce a cpu accumulated power reporting algorithm
This patch introduces an algorithm that computes the average power by reading a delta value of “core power accumulator” register during measurement interval, and then dividing delta value by the length of the time interval. User is able to use power1_average entry to measure the processor power consumption and power1_average_interval entry to set the interval. A simple example: ray@hr-ub:~/tip$ sensors fam15h_power-pci-00c4 Adapter: PCI adapter power1: 19.58 mW (avg = 2.55 mW, interval = 0.01 s) (crit = 15.00 W) ... The result is current average processor power consumption in 10 millisecond. The unit of the result is uWatt. Suggested-by: Guenter Roeck Signed-off-by: Huang Rui Cc: Borislav Petkov --- drivers/hwmon/fam15h_power.c | 119 +++ 1 file changed, 119 insertions(+) diff --git a/drivers/hwmon/fam15h_power.c b/drivers/hwmon/fam15h_power.c index de6f52b..003564b 100644 --- a/drivers/hwmon/fam15h_power.c +++ b/drivers/hwmon/fam15h_power.c @@ -27,6 +27,8 @@ #include #include #include +#include +#include #include #include @@ -48,6 +50,9 @@ MODULE_LICENSE("GPL"); #define FAM15H_NUM_GROUPS 2 #define MAX_CUS8 +/* set maximum interval as 1 second */ +#define MAX_INTERVAL 1000 + #define MSR_F15H_CU_PWR_ACCUMULATOR0xc001007a #define MSR_F15H_CU_MAX_PWR_ACCUMULATOR0xc001007b #define MSR_F15H_PTSC 0xc0010280 @@ -68,6 +73,9 @@ struct fam15h_power_data { u64 cu_acc_power[MAX_CUS]; /* performance timestamp counter */ u64 cpu_sw_pwr_ptsc[MAX_CUS]; + /* online/offline status of current compute unit */ + int cu_on[MAX_CUS]; + unsigned long power_period; }; static ssize_t show_power(struct device *dev, @@ -149,6 +157,8 @@ static void do_read_registers_on_cu(void *_data) rdmsrl_safe(MSR_F15H_CU_PWR_ACCUMULATOR, >cu_acc_power[cu]); rdmsrl_safe(MSR_F15H_PTSC, >cpu_sw_pwr_ptsc[cu]); + + data->cu_on[cu] = 1; } /* @@ -165,6 +175,8 @@ static int read_registers(struct fam15h_power_data *data) if (!ret) return -ENOMEM; + memset(data->cu_on, 0, sizeof(int) * MAX_CUS); + get_online_cpus(); this_cpu = get_cpu(); @@ -192,18 +204,117 @@ static int read_registers(struct fam15h_power_data *data) return 0; } +static ssize_t acc_show_power(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct fam15h_power_data *data = dev_get_drvdata(dev); + u64 prev_cu_acc_power[MAX_CUS], prev_ptsc[MAX_CUS], + jdelta[MAX_CUS]; + u64 tdelta, avg_acc; + int cu, cu_num, ret; + signed long leftover; + + /* +* With the new x86 topology modelling, x86_max_cores is the +* compute unit number. +*/ + cu_num = boot_cpu_data.x86_max_cores; + + ret = read_registers(data); + if (ret) + return 0; + + for (cu = 0; cu < cu_num; cu++) { + prev_cu_acc_power[cu] = data->cu_acc_power[cu]; + prev_ptsc[cu] = data->cpu_sw_pwr_ptsc[cu]; + } + + leftover = schedule_timeout_interruptible(msecs_to_jiffies(data->power_period)); + if (leftover) + return 0; + + ret = read_registers(data); + if (ret) + return 0; + + for (cu = 0, avg_acc = 0; cu < cu_num; cu++) { + /* check if current compute unit is online */ + if (data->cu_on[cu] == 0) + continue; + + if (data->cu_acc_power[cu] < prev_cu_acc_power[cu]) { + jdelta[cu] = data->max_cu_acc_power + data->cu_acc_power[cu]; + jdelta[cu] -= prev_cu_acc_power[cu]; + } else { + jdelta[cu] = data->cu_acc_power[cu] - prev_cu_acc_power[cu]; + } + tdelta = data->cpu_sw_pwr_ptsc[cu] - prev_ptsc[cu]; + jdelta[cu] *= data->cpu_pwr_sample_ratio * 1000; + do_div(jdelta[cu], tdelta); + + /* the unit is microWatt */ + avg_acc += jdelta[cu]; + } + + return sprintf(buf, "%llu\n", (unsigned long long)avg_acc); +} +static DEVICE_ATTR(power1_average, S_IRUGO, acc_show_power, NULL); + +static ssize_t acc_show_power_period(struct device *dev, +struct device_attribute *attr, +char *buf) +{ + struct fam15h_power_data *data = dev_get_drvdata(dev); + + return sprintf(buf, "%lu\n", data->power_period); +} + +static ssize_t acc_set_power_period(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct fam15h_power_data *data =
Re: [PATCH v6 1/7][Resend] cpufreq: sched: Helpers to add and remove update_util hooks
On 22-03-16, 02:46, Rafael J. Wysocki wrote: > From: Rafael J. Wysocki> > Replace the single helper for adding and removing cpufreq utilization > update hooks, cpufreq_set_update_util_data(), with a pair of helpers, > cpufreq_add_update_util_hook() and cpufreq_remove_update_util_hook(), > and modify the users of cpufreq_set_update_util_data() accordingly. > > With the new helpers, the code using them doesn't need to worry > about the internals of struct update_util_data and in particular > it doesn't need to worry about populating the func field in it > properly upfront. > > Signed-off-by: Rafael J. Wysocki > --- Acked-by: Viresh Kumar -- viresh
[PATCH v5 0/6] hwmon: (fam15h_power) Introduce an accumulated power reporting algorithm
Hi Guenter, This serial of patches introduces an accumulated power reporting algorithm. It will calculate the average power consumption for the processor. The cpu feature flag is CPUID.8000_0007H:EDX[12]. This algorithm is used to test the comparison of processor power consumption with between MWAITX delay and TSC delay on AMD Carrizo platforms. Reference: https://lkml.kernel.org/r/1438744732-1459-1-git-send-email-ray.hu...@amd.com Commit f96756 at tip ("x86/asm: Add MONITORX/MWAITX instruction support") Commit b466bd at tip ("x86/asm/delay: Introduce an MWAITX-based delay with a configurable timer") V1: https://lkml.kernel.org/r/1440662866-28716-1-git-send-email-ray.hu...@amd.com V2: https://lkml.kernel.org/r/1445308109-17970-1-git-send-email-ray.hu...@amd.com V3: https://lkml.kernel.org/r/1446199024-1896-1-git-send-email-ray.hu...@amd.com V4: https://lkml.kernel.org/r/1457662670-3354-1-git-send-email-ray.hu...@amd.com On V5, I used the new x86 topology with compute unit id (cpu_core_id) and compute unit numbers (x86_max_cores) for AMD processors. The change and documentation will go to master soon as below link. And This way is better to use smp_num_siblings which is un-defined variable out of CONFIG_SMP. Refer: https://git.kernel.org/cgit/linux/kernel/git/bp/bp.git/commit/?h=tip-urgent=f6ce1851fa2eec2c332255fc25a544658dbfbfe4 Changes from v1 -> v2: - Move fam15h_power_groups and fam15h_power_group into fam15h_power_data to avoid overwrite on multi-CPU system. - Rename FAM15H_MIN_NUM_ATTRS macro and fix return error code. - Remove unnecessary warning print. - Adds do_read_registers_on_cu to do all the read to all MSRs and run it on one of the online cores on each compute unit with smp_call_function_many(). - Use power1_average and power1_average_interval standard entry instread of power1_acc - Fix the CPU-hotplug case. Changes from v2 -> v3: - As Guenter's suggestion, remove typecast, use >groups[0]. - Remove all "fam15_power_*" prefix at data. - Remove unnecessary ( ). - Fix the issue that is reported by build test robot, and add CPU_SUP_AMD as the dependence of fam15h_power - Remove the WARN_ON at do_read_registers_on_cu, because it must be behind CPUID check. The MSR must be available since CPUID.8000_0007H:EDX[12] is set - Add get_online_cpus()/put_online_cpus() functions. - Refine commments and the method which generate cpumask for cu. - Add the interval scope to make the value suitable for user experience - Remove the useless mutex. Changes from v3 -> v4: - Rebase the patches to latest groeck/hwmon-next. - Use smp_num_siblings instead of cores_per_cu accessor. - Refine the cpumask method which is inspired by perf solution. - Fix some typo and errors. Changes from v4 -> v5: - Rebase patches to v4.6-rc1. - Use new x86 topology with compute id (cpu_core_id) and compute unit number (x86_max_cores) instead of smp_num_siblings. A simple example: ray@hr-ub:~/tip$ sensors fam15h_power-pci-00c4 Adapter: PCI adapter power1: 19.58 mW (avg = 2.55 mW, interval = 0.01 s) (crit = 15.00 W) ... These patches are rebased on v4.6-rc1. Thanks, Rui Huang Rui (6): hwmon: (fam15h_power) Add CPU_SUP_AMD as the dependence hwmon: (fam15h_power) Add compute unit accumulated power hwmon: (fam15h_power) Add ptsc counter value for accumulated power hwmon: (fam15h_power) Introduce a cpu accumulated power reporting algorithm hwmon: (fam15h_power) Add documentation for TDP and accumulated power algorithm hwmon: (fam15h_power) Add platform check function Documentation/hwmon/fam15h_power | 57 ++- drivers/hwmon/Kconfig| 2 +- drivers/hwmon/fam15h_power.c | 199 ++- 3 files changed, 252 insertions(+), 6 deletions(-) -- 1.9.1
Re: [PATCH v6 1/7][Resend] cpufreq: sched: Helpers to add and remove update_util hooks
On 22-03-16, 02:46, Rafael J. Wysocki wrote: > From: Rafael J. Wysocki > > Replace the single helper for adding and removing cpufreq utilization > update hooks, cpufreq_set_update_util_data(), with a pair of helpers, > cpufreq_add_update_util_hook() and cpufreq_remove_update_util_hook(), > and modify the users of cpufreq_set_update_util_data() accordingly. > > With the new helpers, the code using them doesn't need to worry > about the internals of struct update_util_data and in particular > it doesn't need to worry about populating the func field in it > properly upfront. > > Signed-off-by: Rafael J. Wysocki > --- Acked-by: Viresh Kumar -- viresh
[PATCH v5 0/6] hwmon: (fam15h_power) Introduce an accumulated power reporting algorithm
Hi Guenter, This serial of patches introduces an accumulated power reporting algorithm. It will calculate the average power consumption for the processor. The cpu feature flag is CPUID.8000_0007H:EDX[12]. This algorithm is used to test the comparison of processor power consumption with between MWAITX delay and TSC delay on AMD Carrizo platforms. Reference: https://lkml.kernel.org/r/1438744732-1459-1-git-send-email-ray.hu...@amd.com Commit f96756 at tip ("x86/asm: Add MONITORX/MWAITX instruction support") Commit b466bd at tip ("x86/asm/delay: Introduce an MWAITX-based delay with a configurable timer") V1: https://lkml.kernel.org/r/1440662866-28716-1-git-send-email-ray.hu...@amd.com V2: https://lkml.kernel.org/r/1445308109-17970-1-git-send-email-ray.hu...@amd.com V3: https://lkml.kernel.org/r/1446199024-1896-1-git-send-email-ray.hu...@amd.com V4: https://lkml.kernel.org/r/1457662670-3354-1-git-send-email-ray.hu...@amd.com On V5, I used the new x86 topology with compute unit id (cpu_core_id) and compute unit numbers (x86_max_cores) for AMD processors. The change and documentation will go to master soon as below link. And This way is better to use smp_num_siblings which is un-defined variable out of CONFIG_SMP. Refer: https://git.kernel.org/cgit/linux/kernel/git/bp/bp.git/commit/?h=tip-urgent=f6ce1851fa2eec2c332255fc25a544658dbfbfe4 Changes from v1 -> v2: - Move fam15h_power_groups and fam15h_power_group into fam15h_power_data to avoid overwrite on multi-CPU system. - Rename FAM15H_MIN_NUM_ATTRS macro and fix return error code. - Remove unnecessary warning print. - Adds do_read_registers_on_cu to do all the read to all MSRs and run it on one of the online cores on each compute unit with smp_call_function_many(). - Use power1_average and power1_average_interval standard entry instread of power1_acc - Fix the CPU-hotplug case. Changes from v2 -> v3: - As Guenter's suggestion, remove typecast, use >groups[0]. - Remove all "fam15_power_*" prefix at data. - Remove unnecessary ( ). - Fix the issue that is reported by build test robot, and add CPU_SUP_AMD as the dependence of fam15h_power - Remove the WARN_ON at do_read_registers_on_cu, because it must be behind CPUID check. The MSR must be available since CPUID.8000_0007H:EDX[12] is set - Add get_online_cpus()/put_online_cpus() functions. - Refine commments and the method which generate cpumask for cu. - Add the interval scope to make the value suitable for user experience - Remove the useless mutex. Changes from v3 -> v4: - Rebase the patches to latest groeck/hwmon-next. - Use smp_num_siblings instead of cores_per_cu accessor. - Refine the cpumask method which is inspired by perf solution. - Fix some typo and errors. Changes from v4 -> v5: - Rebase patches to v4.6-rc1. - Use new x86 topology with compute id (cpu_core_id) and compute unit number (x86_max_cores) instead of smp_num_siblings. A simple example: ray@hr-ub:~/tip$ sensors fam15h_power-pci-00c4 Adapter: PCI adapter power1: 19.58 mW (avg = 2.55 mW, interval = 0.01 s) (crit = 15.00 W) ... These patches are rebased on v4.6-rc1. Thanks, Rui Huang Rui (6): hwmon: (fam15h_power) Add CPU_SUP_AMD as the dependence hwmon: (fam15h_power) Add compute unit accumulated power hwmon: (fam15h_power) Add ptsc counter value for accumulated power hwmon: (fam15h_power) Introduce a cpu accumulated power reporting algorithm hwmon: (fam15h_power) Add documentation for TDP and accumulated power algorithm hwmon: (fam15h_power) Add platform check function Documentation/hwmon/fam15h_power | 57 ++- drivers/hwmon/Kconfig| 2 +- drivers/hwmon/fam15h_power.c | 199 ++- 3 files changed, 252 insertions(+), 6 deletions(-) -- 1.9.1
[PATCH v5 1/6] hwmon: (fam15h_power) Add CPU_SUP_AMD as the dependence
This patch adds CONFIG_CPU_SUP_AMD as the dependence of fam15h_power driver. Because the following patch will use the interface from x86/kernel/cpu/amd.c. Otherwise, the below error might be encountered: All errors (new ones prefixed by >>): drivers/built-in.o: In function `fam15h_power_probe': >> fam15h_power.c:(.text+0x26e3a3): undefined reference to >> `amd_get_cores_per_cu' fam15h_power.c:(.text+0x26e41e): undefined reference to `amd_get_cores_per_cu' Reported-by: build test robotSigned-off-by: Huang Rui --- drivers/hwmon/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 5c2d13a..4be3792 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -288,7 +288,7 @@ config SENSORS_K10TEMP config SENSORS_FAM15H_POWER tristate "AMD Family 15h processor power" - depends on X86 && PCI + depends on X86 && PCI && CPU_SUP_AMD help If you say yes here you get support for processor power information of your AMD family 15h CPU. -- 1.9.1
[PATCH v5 3/6] hwmon: (fam15h_power) Add ptsc counter value for accumulated power
PTSC is the performance timestamp counter value in a cpu core and the cores in one compute unit have the fixed frequency. So it picks up the performance timestamp counter value of the first core per compute unit to measure the interval for average power per compute unit. Signed-off-by: Huang RuiCc: Borislav Petkov --- drivers/hwmon/fam15h_power.c | 4 1 file changed, 4 insertions(+) diff --git a/drivers/hwmon/fam15h_power.c b/drivers/hwmon/fam15h_power.c index ccbc944..de6f52b 100644 --- a/drivers/hwmon/fam15h_power.c +++ b/drivers/hwmon/fam15h_power.c @@ -50,6 +50,7 @@ MODULE_LICENSE("GPL"); #define MSR_F15H_CU_PWR_ACCUMULATOR0xc001007a #define MSR_F15H_CU_MAX_PWR_ACCUMULATOR0xc001007b +#define MSR_F15H_PTSC 0xc0010280 #define PCI_DEVICE_ID_AMD_15H_M70H_NB_F4 0x15b4 @@ -65,6 +66,8 @@ struct fam15h_power_data { u64 max_cu_acc_power; /* accumulated power of the compute units */ u64 cu_acc_power[MAX_CUS]; + /* performance timestamp counter */ + u64 cpu_sw_pwr_ptsc[MAX_CUS]; }; static ssize_t show_power(struct device *dev, @@ -145,6 +148,7 @@ static void do_read_registers_on_cu(void *_data) cu = cpu_data(cpu).cpu_core_id; rdmsrl_safe(MSR_F15H_CU_PWR_ACCUMULATOR, >cu_acc_power[cu]); + rdmsrl_safe(MSR_F15H_PTSC, >cpu_sw_pwr_ptsc[cu]); } /* -- 1.9.1
[PATCH v5 1/6] hwmon: (fam15h_power) Add CPU_SUP_AMD as the dependence
This patch adds CONFIG_CPU_SUP_AMD as the dependence of fam15h_power driver. Because the following patch will use the interface from x86/kernel/cpu/amd.c. Otherwise, the below error might be encountered: All errors (new ones prefixed by >>): drivers/built-in.o: In function `fam15h_power_probe': >> fam15h_power.c:(.text+0x26e3a3): undefined reference to >> `amd_get_cores_per_cu' fam15h_power.c:(.text+0x26e41e): undefined reference to `amd_get_cores_per_cu' Reported-by: build test robot Signed-off-by: Huang Rui --- drivers/hwmon/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 5c2d13a..4be3792 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -288,7 +288,7 @@ config SENSORS_K10TEMP config SENSORS_FAM15H_POWER tristate "AMD Family 15h processor power" - depends on X86 && PCI + depends on X86 && PCI && CPU_SUP_AMD help If you say yes here you get support for processor power information of your AMD family 15h CPU. -- 1.9.1
[PATCH v5 3/6] hwmon: (fam15h_power) Add ptsc counter value for accumulated power
PTSC is the performance timestamp counter value in a cpu core and the cores in one compute unit have the fixed frequency. So it picks up the performance timestamp counter value of the first core per compute unit to measure the interval for average power per compute unit. Signed-off-by: Huang Rui Cc: Borislav Petkov --- drivers/hwmon/fam15h_power.c | 4 1 file changed, 4 insertions(+) diff --git a/drivers/hwmon/fam15h_power.c b/drivers/hwmon/fam15h_power.c index ccbc944..de6f52b 100644 --- a/drivers/hwmon/fam15h_power.c +++ b/drivers/hwmon/fam15h_power.c @@ -50,6 +50,7 @@ MODULE_LICENSE("GPL"); #define MSR_F15H_CU_PWR_ACCUMULATOR0xc001007a #define MSR_F15H_CU_MAX_PWR_ACCUMULATOR0xc001007b +#define MSR_F15H_PTSC 0xc0010280 #define PCI_DEVICE_ID_AMD_15H_M70H_NB_F4 0x15b4 @@ -65,6 +66,8 @@ struct fam15h_power_data { u64 max_cu_acc_power; /* accumulated power of the compute units */ u64 cu_acc_power[MAX_CUS]; + /* performance timestamp counter */ + u64 cpu_sw_pwr_ptsc[MAX_CUS]; }; static ssize_t show_power(struct device *dev, @@ -145,6 +148,7 @@ static void do_read_registers_on_cu(void *_data) cu = cpu_data(cpu).cpu_core_id; rdmsrl_safe(MSR_F15H_CU_PWR_ACCUMULATOR, >cu_acc_power[cu]); + rdmsrl_safe(MSR_F15H_PTSC, >cpu_sw_pwr_ptsc[cu]); } /* -- 1.9.1
[PATCH v5 2/6] hwmon: (fam15h_power) Add compute unit accumulated power
This patch adds a member in fam15h_power_data which specifies the compute unit accumulated power. It adds do_read_registers_on_cu to do all the read to all MSRs and run it on one of the online cores on each compute unit with smp_call_function_many(). This behavior can decrease IPI numbers. Suggested-by: Borislav PetkovSigned-off-by: Huang Rui --- drivers/hwmon/fam15h_power.c | 65 +++- 1 file changed, 64 insertions(+), 1 deletion(-) diff --git a/drivers/hwmon/fam15h_power.c b/drivers/hwmon/fam15h_power.c index 4f695d8..ccbc944 100644 --- a/drivers/hwmon/fam15h_power.c +++ b/drivers/hwmon/fam15h_power.c @@ -25,6 +25,8 @@ #include #include #include +#include +#include #include #include @@ -44,7 +46,9 @@ MODULE_LICENSE("GPL"); #define FAM15H_MIN_NUM_ATTRS 2 #define FAM15H_NUM_GROUPS 2 +#define MAX_CUS8 +#define MSR_F15H_CU_PWR_ACCUMULATOR0xc001007a #define MSR_F15H_CU_MAX_PWR_ACCUMULATOR0xc001007b #define PCI_DEVICE_ID_AMD_15H_M70H_NB_F4 0x15b4 @@ -59,6 +63,8 @@ struct fam15h_power_data { struct attribute_group group; /* maximum accumulated power of a compute unit */ u64 max_cu_acc_power; + /* accumulated power of the compute units */ + u64 cu_acc_power[MAX_CUS]; }; static ssize_t show_power(struct device *dev, @@ -125,6 +131,63 @@ static ssize_t show_power_crit(struct device *dev, } static DEVICE_ATTR(power1_crit, S_IRUGO, show_power_crit, NULL); +static void do_read_registers_on_cu(void *_data) +{ + struct fam15h_power_data *data = _data; + int cpu, cu; + + cpu = smp_processor_id(); + + /* +* With the new x86 topology modelling, cpu core id actually +* is compute unit id. +*/ + cu = cpu_data(cpu).cpu_core_id; + + rdmsrl_safe(MSR_F15H_CU_PWR_ACCUMULATOR, >cu_acc_power[cu]); +} + +/* + * This function is only able to be called when CPUID + * Fn8000_0007:EDX[12] is set. + */ +static int read_registers(struct fam15h_power_data *data) +{ + int this_cpu, ret, cpu; + int target; + cpumask_var_t mask; + + ret = zalloc_cpumask_var(, GFP_KERNEL); + if (!ret) + return -ENOMEM; + + get_online_cpus(); + this_cpu = get_cpu(); + + /* +* Choose the first online core of each compute unit, and then +* read their MSR value of power and ptsc in a single IPI, +* because the MSR value of CPU core represent the compute +* unit's. +*/ + for_each_online_cpu(cpu) { + target = cpumask_first(topology_sibling_cpumask(cpu)); + if (!cpumask_test_cpu(target, mask)) + cpumask_set_cpu(target, mask); + } + + if (cpumask_test_cpu(this_cpu, mask)) + do_read_registers_on_cu(data); + + smp_call_function_many(mask, do_read_registers_on_cu, data, true); + put_cpu(); + put_online_cpus(); + + free_cpumask_var(mask); + + return 0; +} + static int fam15h_power_init_attrs(struct pci_dev *pdev, struct fam15h_power_data *data) { @@ -263,7 +326,7 @@ static int fam15h_power_init_data(struct pci_dev *f4, data->max_cu_acc_power = tmp; - return 0; + return read_registers(data); } static int fam15h_power_probe(struct pci_dev *pdev, -- 1.9.1
[PATCH v5 2/6] hwmon: (fam15h_power) Add compute unit accumulated power
This patch adds a member in fam15h_power_data which specifies the compute unit accumulated power. It adds do_read_registers_on_cu to do all the read to all MSRs and run it on one of the online cores on each compute unit with smp_call_function_many(). This behavior can decrease IPI numbers. Suggested-by: Borislav Petkov Signed-off-by: Huang Rui --- drivers/hwmon/fam15h_power.c | 65 +++- 1 file changed, 64 insertions(+), 1 deletion(-) diff --git a/drivers/hwmon/fam15h_power.c b/drivers/hwmon/fam15h_power.c index 4f695d8..ccbc944 100644 --- a/drivers/hwmon/fam15h_power.c +++ b/drivers/hwmon/fam15h_power.c @@ -25,6 +25,8 @@ #include #include #include +#include +#include #include #include @@ -44,7 +46,9 @@ MODULE_LICENSE("GPL"); #define FAM15H_MIN_NUM_ATTRS 2 #define FAM15H_NUM_GROUPS 2 +#define MAX_CUS8 +#define MSR_F15H_CU_PWR_ACCUMULATOR0xc001007a #define MSR_F15H_CU_MAX_PWR_ACCUMULATOR0xc001007b #define PCI_DEVICE_ID_AMD_15H_M70H_NB_F4 0x15b4 @@ -59,6 +63,8 @@ struct fam15h_power_data { struct attribute_group group; /* maximum accumulated power of a compute unit */ u64 max_cu_acc_power; + /* accumulated power of the compute units */ + u64 cu_acc_power[MAX_CUS]; }; static ssize_t show_power(struct device *dev, @@ -125,6 +131,63 @@ static ssize_t show_power_crit(struct device *dev, } static DEVICE_ATTR(power1_crit, S_IRUGO, show_power_crit, NULL); +static void do_read_registers_on_cu(void *_data) +{ + struct fam15h_power_data *data = _data; + int cpu, cu; + + cpu = smp_processor_id(); + + /* +* With the new x86 topology modelling, cpu core id actually +* is compute unit id. +*/ + cu = cpu_data(cpu).cpu_core_id; + + rdmsrl_safe(MSR_F15H_CU_PWR_ACCUMULATOR, >cu_acc_power[cu]); +} + +/* + * This function is only able to be called when CPUID + * Fn8000_0007:EDX[12] is set. + */ +static int read_registers(struct fam15h_power_data *data) +{ + int this_cpu, ret, cpu; + int target; + cpumask_var_t mask; + + ret = zalloc_cpumask_var(, GFP_KERNEL); + if (!ret) + return -ENOMEM; + + get_online_cpus(); + this_cpu = get_cpu(); + + /* +* Choose the first online core of each compute unit, and then +* read their MSR value of power and ptsc in a single IPI, +* because the MSR value of CPU core represent the compute +* unit's. +*/ + for_each_online_cpu(cpu) { + target = cpumask_first(topology_sibling_cpumask(cpu)); + if (!cpumask_test_cpu(target, mask)) + cpumask_set_cpu(target, mask); + } + + if (cpumask_test_cpu(this_cpu, mask)) + do_read_registers_on_cu(data); + + smp_call_function_many(mask, do_read_registers_on_cu, data, true); + put_cpu(); + put_online_cpus(); + + free_cpumask_var(mask); + + return 0; +} + static int fam15h_power_init_attrs(struct pci_dev *pdev, struct fam15h_power_data *data) { @@ -263,7 +326,7 @@ static int fam15h_power_init_data(struct pci_dev *f4, data->max_cu_acc_power = tmp; - return 0; + return read_registers(data); } static int fam15h_power_probe(struct pci_dev *pdev, -- 1.9.1
RE: [PATCH v2 3/6] Documentation: DT: vdma: update binding doc for AXI DMA
Hi Soren, > -Original Message- > From: Sören Brinkmann [mailto:soren.brinkm...@xilinx.com] > Sent: Monday, March 28, 2016 12:56 AM > To: Appana Durga Kedareswara Rao > Cc: robh...@kernel.org; pawel.m...@arm.com; mark.rutl...@arm.com; > ijc+devicet...@hellion.org.uk; ga...@codeaurora.org; Michal Simek; > vinod.k...@intel.com; dan.j.willi...@intel.com; Anurag Kumar Vulisha; Appana > Durga Kedareswara Rao; moritz.fisc...@ettus.com; > laurent.pinch...@ideasonboard.com; l...@debethencourt.com; Srikanth > Vemula; Anirudha Sarangi; devicet...@vger.kernel.org; linux-arm- > ker...@lists.infradead.org; linux-kernel@vger.kernel.org; > dmaeng...@vger.kernel.org > Subject: Re: [PATCH v2 3/6] Documentation: DT: vdma: update binding doc for > AXI DMA > > On Sun, 2016-03-27 at 23:36:05 +0530, Kedareswara rao Appana wrote: > > This patch updates the device-tree binding doc for adding support for > > AXI DMA. > > > > Signed-off-by: Kedareswara rao Appana> > --- > > Changes for v2: > > ---> Modified commit message as suggested by Vinod. > > ---> Moved the patch to forward in the series as suggested by vinod. > > > > .../devicetree/bindings/dma/xilinx/xilinx_vdma.txt | 22 > > +- > > 1 file changed, 21 insertions(+), 1 deletion(-) > > > > diff --git > > a/Documentation/devicetree/bindings/dma/xilinx/xilinx_vdma.txt > > b/Documentation/devicetree/bindings/dma/xilinx/xilinx_vdma.txt > > index a86737c..5841421 100644 > > --- a/Documentation/devicetree/bindings/dma/xilinx/xilinx_vdma.txt > > +++ b/Documentation/devicetree/bindings/dma/xilinx/xilinx_vdma.txt > > @@ -3,8 +3,13 @@ It can be configured to have one channel or two > > channels. If configured as two channels, one is to transmit to the > > video device and another is to receive from the video device. > > > > +Xilinx AXI DMA engine, it does transfers between memory and AXI4 > > +stream target devices. It can be configured to have one channel or two > channels. > > +If configured as two channels, one is to transmit to the device and > > +another is to receive from the device. > > + > > Required properties: > > -- compatible: Should be "xlnx,axi-vdma-1.00.a" > > +- compatible: Should be "xlnx,axi-vdma-1.00.a" or "xlnx,axi-dma-1.00.a" > > - #dma-cells: Should be <1>, see "dmas" property below > > - reg: Should contain VDMA registers location and length. > > - xlnx,num-fstores: Should be the number of framebuffers as configured in > h/w. > > @@ -59,6 +64,21 @@ axi_vdma_0: axivdma@4003 { > > } ; > > } ; > > > > +axi_dma_0: axidma@4040 { > > The node names should follow the generic names, hence 'dma-controller@...'. Ok will fix in next version... > > > + compatible = "xlnx,axi-dma-1.00.a"; > > + #dma-cells = <1>; > > + reg = < 0x4040 0x1 >; > > + dma-channel@4040 { > > + compatible = "xlnx,axi-dma-mm2s-channel"; > > + interrupts = < 0 59 4 >; > > + xlnx,datawidth = <0x40>; > > + } ; > > + dma-channel@40400030 { > > + compatible = "xlnx,axi-dma-s2mm-channel"; > > + interrupts = < 0 58 4 >; > > + xlnx,datawidth = <0x40>; > > Nit: The spacing around the '<' '>' is inconsistent. I'd just remove all > redundant > spaces. Ok will fix in next version... Regards, Kedar. > > Sören
RE: [PATCH v2 3/6] Documentation: DT: vdma: update binding doc for AXI DMA
Hi Soren, > -Original Message- > From: Sören Brinkmann [mailto:soren.brinkm...@xilinx.com] > Sent: Monday, March 28, 2016 12:56 AM > To: Appana Durga Kedareswara Rao > Cc: robh...@kernel.org; pawel.m...@arm.com; mark.rutl...@arm.com; > ijc+devicet...@hellion.org.uk; ga...@codeaurora.org; Michal Simek; > vinod.k...@intel.com; dan.j.willi...@intel.com; Anurag Kumar Vulisha; Appana > Durga Kedareswara Rao; moritz.fisc...@ettus.com; > laurent.pinch...@ideasonboard.com; l...@debethencourt.com; Srikanth > Vemula; Anirudha Sarangi; devicet...@vger.kernel.org; linux-arm- > ker...@lists.infradead.org; linux-kernel@vger.kernel.org; > dmaeng...@vger.kernel.org > Subject: Re: [PATCH v2 3/6] Documentation: DT: vdma: update binding doc for > AXI DMA > > On Sun, 2016-03-27 at 23:36:05 +0530, Kedareswara rao Appana wrote: > > This patch updates the device-tree binding doc for adding support for > > AXI DMA. > > > > Signed-off-by: Kedareswara rao Appana > > --- > > Changes for v2: > > ---> Modified commit message as suggested by Vinod. > > ---> Moved the patch to forward in the series as suggested by vinod. > > > > .../devicetree/bindings/dma/xilinx/xilinx_vdma.txt | 22 > > +- > > 1 file changed, 21 insertions(+), 1 deletion(-) > > > > diff --git > > a/Documentation/devicetree/bindings/dma/xilinx/xilinx_vdma.txt > > b/Documentation/devicetree/bindings/dma/xilinx/xilinx_vdma.txt > > index a86737c..5841421 100644 > > --- a/Documentation/devicetree/bindings/dma/xilinx/xilinx_vdma.txt > > +++ b/Documentation/devicetree/bindings/dma/xilinx/xilinx_vdma.txt > > @@ -3,8 +3,13 @@ It can be configured to have one channel or two > > channels. If configured as two channels, one is to transmit to the > > video device and another is to receive from the video device. > > > > +Xilinx AXI DMA engine, it does transfers between memory and AXI4 > > +stream target devices. It can be configured to have one channel or two > channels. > > +If configured as two channels, one is to transmit to the device and > > +another is to receive from the device. > > + > > Required properties: > > -- compatible: Should be "xlnx,axi-vdma-1.00.a" > > +- compatible: Should be "xlnx,axi-vdma-1.00.a" or "xlnx,axi-dma-1.00.a" > > - #dma-cells: Should be <1>, see "dmas" property below > > - reg: Should contain VDMA registers location and length. > > - xlnx,num-fstores: Should be the number of framebuffers as configured in > h/w. > > @@ -59,6 +64,21 @@ axi_vdma_0: axivdma@4003 { > > } ; > > } ; > > > > +axi_dma_0: axidma@4040 { > > The node names should follow the generic names, hence 'dma-controller@...'. Ok will fix in next version... > > > + compatible = "xlnx,axi-dma-1.00.a"; > > + #dma-cells = <1>; > > + reg = < 0x4040 0x1 >; > > + dma-channel@4040 { > > + compatible = "xlnx,axi-dma-mm2s-channel"; > > + interrupts = < 0 59 4 >; > > + xlnx,datawidth = <0x40>; > > + } ; > > + dma-channel@40400030 { > > + compatible = "xlnx,axi-dma-s2mm-channel"; > > + interrupts = < 0 58 4 >; > > + xlnx,datawidth = <0x40>; > > Nit: The spacing around the '<' '>' is inconsistent. I'd just remove all > redundant > spaces. Ok will fix in next version... Regards, Kedar. > > Sören
[PATCH 05/11] mm/slab: clean-up kmem_cache_node setup
From: Joonsoo KimThere are mostly same code for setting up kmem_cache_node either in cpuup_prepare() or alloc_kmem_cache_node(). Factor out and clean-up them. Signed-off-by: Joonsoo Kim --- mm/slab.c | 167 +- 1 file changed, 67 insertions(+), 100 deletions(-) diff --git a/mm/slab.c b/mm/slab.c index 569d7db..b96f381 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -898,6 +898,62 @@ static int init_cache_node_node(int node) return 0; } +static int setup_kmem_cache_node(struct kmem_cache *cachep, + int node, gfp_t gfp, bool force_change) +{ + int ret = -ENOMEM; + struct kmem_cache_node *n; + struct array_cache *old_shared = NULL; + struct array_cache *new_shared = NULL; + struct alien_cache **new_alien = NULL; + LIST_HEAD(list); + + if (use_alien_caches) { + new_alien = alloc_alien_cache(node, cachep->limit, gfp); + if (!new_alien) + goto fail; + } + + if (cachep->shared) { + new_shared = alloc_arraycache(node, + cachep->shared * cachep->batchcount, 0xbaadf00d, gfp); + if (!new_shared) + goto fail; + } + + ret = init_cache_node(cachep, node, gfp); + if (ret) + goto fail; + + n = get_node(cachep, node); + spin_lock_irq(>list_lock); + if (n->shared) { + free_block(cachep, n->shared->entry, + n->shared->avail, node, ); + } + + if (!n->shared || force_change) { + old_shared = n->shared; + n->shared = new_shared; + new_shared = NULL; + } + + if (!n->alien) { + n->alien = new_alien; + new_alien = NULL; + } + + spin_unlock_irq(>list_lock); + slabs_destroy(cachep, ); + +fail: + kfree(old_shared); + kfree(new_shared); + free_alien_cache(new_alien); + + return ret; +} + static void cpuup_canceled(long cpu) { struct kmem_cache *cachep; @@ -969,7 +1025,6 @@ free_slab: static int cpuup_prepare(long cpu) { struct kmem_cache *cachep; - struct kmem_cache_node *n = NULL; int node = cpu_to_mem(cpu); int err; @@ -988,44 +1043,9 @@ static int cpuup_prepare(long cpu) * array caches */ list_for_each_entry(cachep, _caches, list) { - struct array_cache *shared = NULL; - struct alien_cache **alien = NULL; - - if (cachep->shared) { - shared = alloc_arraycache(node, - cachep->shared * cachep->batchcount, - 0xbaadf00d, GFP_KERNEL); - if (!shared) - goto bad; - } - if (use_alien_caches) { - alien = alloc_alien_cache(node, cachep->limit, GFP_KERNEL); - if (!alien) { - kfree(shared); - goto bad; - } - } - n = get_node(cachep, node); - BUG_ON(!n); - - spin_lock_irq(>list_lock); - if (!n->shared) { - /* -* We are serialised from CPU_DEAD or -* CPU_UP_CANCELLED by the cpucontrol lock -*/ - n->shared = shared; - shared = NULL; - } -#ifdef CONFIG_NUMA - if (!n->alien) { - n->alien = alien; - alien = NULL; - } -#endif - spin_unlock_irq(>list_lock); - kfree(shared); - free_alien_cache(alien); + err = setup_kmem_cache_node(cachep, node, GFP_KERNEL, false); + if (err) + goto bad; } return 0; @@ -3652,72 +3672,19 @@ EXPORT_SYMBOL(kfree); /* * This initializes kmem_cache_node or resizes various caches for all nodes. */ -static int alloc_kmem_cache_node(struct kmem_cache *cachep, gfp_t gfp) +static int setup_kmem_cache_node_node(struct kmem_cache *cachep, gfp_t gfp) { + int ret; int node; struct kmem_cache_node *n; - struct array_cache *new_shared; - struct alien_cache **new_alien = NULL; for_each_online_node(node) { - - if (use_alien_caches) { - new_alien = alloc_alien_cache(node, cachep->limit, gfp); - if (!new_alien) - goto fail; - } - - new_shared = NULL; - if (cachep->shared) { - new_shared =
[PATCH] arm: dts: mt2701: Add clock controller device nodes
Add clock controller nodes for MT2701, include topckgen, infracfg, pericfg, apmixedsys, mmsys, imgsys, vdecsys, hifsys, ethsys and bdpsys. This patch also add two oscillators that provide clocks for MT2701. Signed-off-by: James Liao--- This patch is based on v4.6-rc1 and MT2701 clock patches [1]. This patch adds all clock provider nodes which are supported in [1]. [1] http://lists.infradead.org/pipermail/linux-mediatek/2016-February/004030.html arch/arm/boot/dts/mt2701.dtsi | 78 +++ 1 file changed, 78 insertions(+) diff --git a/arch/arm/boot/dts/mt2701.dtsi b/arch/arm/boot/dts/mt2701.dtsi index 8343768..c8fee33 100644 --- a/arch/arm/boot/dts/mt2701.dtsi +++ b/arch/arm/boot/dts/mt2701.dtsi @@ -12,6 +12,7 @@ * GNU General Public License for more details. */ +#include #include #include #include "skeleton64.dtsi" @@ -76,6 +77,20 @@ #clock-cells = <0>; }; + clk26m: oscillator@0 { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <2600>; + clock-output-names = "clk26m"; + }; + + rtc32k: oscillator@1 { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <32000>; + clock-output-names = "rtc32k"; + }; + timer { compatible = "arm,armv7-timer"; interrupt-parent = <>; @@ -85,6 +100,26 @@ ; }; + topckgen: syscon@1000 { + compatible = "mediatek,mt2701-topckgen", "syscon"; + reg = <0 0x1000 0 0x1000>; + #clock-cells = <1>; + }; + + infracfg: syscon@10001000 { + compatible = "mediatek,mt2701-infracfg", "syscon"; + reg = <0 0x10001000 0 0x1000>; + #clock-cells = <1>; + #reset-cells = <1>; + }; + + pericfg: syscon@10003000 { + compatible = "mediatek,mt2701-pericfg", "syscon"; + reg = <0 0x10003000 0 0x1000>; + #clock-cells = <1>; + #reset-cells = <1>; + }; + watchdog: watchdog@10007000 { compatible = "mediatek,mt2701-wdt", "mediatek,mt6589-wdt"; @@ -109,6 +144,13 @@ reg = <0 0x10200100 0 0x1c>; }; + apmixedsys: syscon@10209000 { + compatible = "mediatek,mt2701-apmixedsys", "syscon"; + reg = <0 0x10209000 0 0x1000>; + mediatek,hdmi-ibias = <0xa>; + #clock-cells = <1>; + }; + gic: interrupt-controller@10211000 { compatible = "arm,cortex-a7-gic"; interrupt-controller; @@ -155,4 +197,40 @@ clocks = <_clk>; status = "disabled"; }; + + mmsys: syscon@1400 { + compatible = "mediatek,mt2701-mmsys", "syscon"; + reg = <0 0x1400 0 0x1000>; + #clock-cells = <1>; + }; + + imgsys: syscon@1500 { + compatible = "mediatek,mt2701-imgsys", "syscon"; + reg = <0 0x1500 0 0x1000>; + #clock-cells = <1>; + }; + + vdecsys: syscon@1600 { + compatible = "mediatek,mt2701-vdecsys", "syscon"; + reg = <0 0x1600 0 0x1000>; + #clock-cells = <1>; + }; + + hifsys: syscon@1a00 { + compatible = "mediatek,mt2701-hifsys", "syscon"; + reg = <0 0x1a00 0 0x1000>; + #clock-cells = <1>; + }; + + ethsys: syscon@1b00 { + compatible = "mediatek,mt2701-ethsys", "syscon"; + reg = <0 0x1b00 0 0x1000>; + #clock-cells = <1>; + }; + + bdpsys: syscon@1c00 { + compatible = "mediatek,mt2701-bdpsys", "syscon"; + reg = <0 0x1c00 0 0x1000>; + #clock-cells = <1>; + }; }; -- 1.9.1
[PATCH 05/11] mm/slab: clean-up kmem_cache_node setup
From: Joonsoo Kim There are mostly same code for setting up kmem_cache_node either in cpuup_prepare() or alloc_kmem_cache_node(). Factor out and clean-up them. Signed-off-by: Joonsoo Kim --- mm/slab.c | 167 +- 1 file changed, 67 insertions(+), 100 deletions(-) diff --git a/mm/slab.c b/mm/slab.c index 569d7db..b96f381 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -898,6 +898,62 @@ static int init_cache_node_node(int node) return 0; } +static int setup_kmem_cache_node(struct kmem_cache *cachep, + int node, gfp_t gfp, bool force_change) +{ + int ret = -ENOMEM; + struct kmem_cache_node *n; + struct array_cache *old_shared = NULL; + struct array_cache *new_shared = NULL; + struct alien_cache **new_alien = NULL; + LIST_HEAD(list); + + if (use_alien_caches) { + new_alien = alloc_alien_cache(node, cachep->limit, gfp); + if (!new_alien) + goto fail; + } + + if (cachep->shared) { + new_shared = alloc_arraycache(node, + cachep->shared * cachep->batchcount, 0xbaadf00d, gfp); + if (!new_shared) + goto fail; + } + + ret = init_cache_node(cachep, node, gfp); + if (ret) + goto fail; + + n = get_node(cachep, node); + spin_lock_irq(>list_lock); + if (n->shared) { + free_block(cachep, n->shared->entry, + n->shared->avail, node, ); + } + + if (!n->shared || force_change) { + old_shared = n->shared; + n->shared = new_shared; + new_shared = NULL; + } + + if (!n->alien) { + n->alien = new_alien; + new_alien = NULL; + } + + spin_unlock_irq(>list_lock); + slabs_destroy(cachep, ); + +fail: + kfree(old_shared); + kfree(new_shared); + free_alien_cache(new_alien); + + return ret; +} + static void cpuup_canceled(long cpu) { struct kmem_cache *cachep; @@ -969,7 +1025,6 @@ free_slab: static int cpuup_prepare(long cpu) { struct kmem_cache *cachep; - struct kmem_cache_node *n = NULL; int node = cpu_to_mem(cpu); int err; @@ -988,44 +1043,9 @@ static int cpuup_prepare(long cpu) * array caches */ list_for_each_entry(cachep, _caches, list) { - struct array_cache *shared = NULL; - struct alien_cache **alien = NULL; - - if (cachep->shared) { - shared = alloc_arraycache(node, - cachep->shared * cachep->batchcount, - 0xbaadf00d, GFP_KERNEL); - if (!shared) - goto bad; - } - if (use_alien_caches) { - alien = alloc_alien_cache(node, cachep->limit, GFP_KERNEL); - if (!alien) { - kfree(shared); - goto bad; - } - } - n = get_node(cachep, node); - BUG_ON(!n); - - spin_lock_irq(>list_lock); - if (!n->shared) { - /* -* We are serialised from CPU_DEAD or -* CPU_UP_CANCELLED by the cpucontrol lock -*/ - n->shared = shared; - shared = NULL; - } -#ifdef CONFIG_NUMA - if (!n->alien) { - n->alien = alien; - alien = NULL; - } -#endif - spin_unlock_irq(>list_lock); - kfree(shared); - free_alien_cache(alien); + err = setup_kmem_cache_node(cachep, node, GFP_KERNEL, false); + if (err) + goto bad; } return 0; @@ -3652,72 +3672,19 @@ EXPORT_SYMBOL(kfree); /* * This initializes kmem_cache_node or resizes various caches for all nodes. */ -static int alloc_kmem_cache_node(struct kmem_cache *cachep, gfp_t gfp) +static int setup_kmem_cache_node_node(struct kmem_cache *cachep, gfp_t gfp) { + int ret; int node; struct kmem_cache_node *n; - struct array_cache *new_shared; - struct alien_cache **new_alien = NULL; for_each_online_node(node) { - - if (use_alien_caches) { - new_alien = alloc_alien_cache(node, cachep->limit, gfp); - if (!new_alien) - goto fail; - } - - new_shared = NULL; - if (cachep->shared) { - new_shared = alloc_arraycache(node, -
[PATCH] arm: dts: mt2701: Add clock controller device nodes
Add clock controller nodes for MT2701, include topckgen, infracfg, pericfg, apmixedsys, mmsys, imgsys, vdecsys, hifsys, ethsys and bdpsys. This patch also add two oscillators that provide clocks for MT2701. Signed-off-by: James Liao --- This patch is based on v4.6-rc1 and MT2701 clock patches [1]. This patch adds all clock provider nodes which are supported in [1]. [1] http://lists.infradead.org/pipermail/linux-mediatek/2016-February/004030.html arch/arm/boot/dts/mt2701.dtsi | 78 +++ 1 file changed, 78 insertions(+) diff --git a/arch/arm/boot/dts/mt2701.dtsi b/arch/arm/boot/dts/mt2701.dtsi index 8343768..c8fee33 100644 --- a/arch/arm/boot/dts/mt2701.dtsi +++ b/arch/arm/boot/dts/mt2701.dtsi @@ -12,6 +12,7 @@ * GNU General Public License for more details. */ +#include #include #include #include "skeleton64.dtsi" @@ -76,6 +77,20 @@ #clock-cells = <0>; }; + clk26m: oscillator@0 { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <2600>; + clock-output-names = "clk26m"; + }; + + rtc32k: oscillator@1 { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <32000>; + clock-output-names = "rtc32k"; + }; + timer { compatible = "arm,armv7-timer"; interrupt-parent = <>; @@ -85,6 +100,26 @@ ; }; + topckgen: syscon@1000 { + compatible = "mediatek,mt2701-topckgen", "syscon"; + reg = <0 0x1000 0 0x1000>; + #clock-cells = <1>; + }; + + infracfg: syscon@10001000 { + compatible = "mediatek,mt2701-infracfg", "syscon"; + reg = <0 0x10001000 0 0x1000>; + #clock-cells = <1>; + #reset-cells = <1>; + }; + + pericfg: syscon@10003000 { + compatible = "mediatek,mt2701-pericfg", "syscon"; + reg = <0 0x10003000 0 0x1000>; + #clock-cells = <1>; + #reset-cells = <1>; + }; + watchdog: watchdog@10007000 { compatible = "mediatek,mt2701-wdt", "mediatek,mt6589-wdt"; @@ -109,6 +144,13 @@ reg = <0 0x10200100 0 0x1c>; }; + apmixedsys: syscon@10209000 { + compatible = "mediatek,mt2701-apmixedsys", "syscon"; + reg = <0 0x10209000 0 0x1000>; + mediatek,hdmi-ibias = <0xa>; + #clock-cells = <1>; + }; + gic: interrupt-controller@10211000 { compatible = "arm,cortex-a7-gic"; interrupt-controller; @@ -155,4 +197,40 @@ clocks = <_clk>; status = "disabled"; }; + + mmsys: syscon@1400 { + compatible = "mediatek,mt2701-mmsys", "syscon"; + reg = <0 0x1400 0 0x1000>; + #clock-cells = <1>; + }; + + imgsys: syscon@1500 { + compatible = "mediatek,mt2701-imgsys", "syscon"; + reg = <0 0x1500 0 0x1000>; + #clock-cells = <1>; + }; + + vdecsys: syscon@1600 { + compatible = "mediatek,mt2701-vdecsys", "syscon"; + reg = <0 0x1600 0 0x1000>; + #clock-cells = <1>; + }; + + hifsys: syscon@1a00 { + compatible = "mediatek,mt2701-hifsys", "syscon"; + reg = <0 0x1a00 0 0x1000>; + #clock-cells = <1>; + }; + + ethsys: syscon@1b00 { + compatible = "mediatek,mt2701-ethsys", "syscon"; + reg = <0 0x1b00 0 0x1000>; + #clock-cells = <1>; + }; + + bdpsys: syscon@1c00 { + compatible = "mediatek,mt2701-bdpsys", "syscon"; + reg = <0 0x1c00 0 0x1000>; + #clock-cells = <1>; + }; }; -- 1.9.1
[PATCH 06/11] mm/slab: don't keep free slabs if free_objects exceeds free_limit
From: Joonsoo KimCurrently, determination to free a slab is done whenever free object is put into the slab. This has a problem that free slabs are not freed even if we have free slabs and have more free_objects than free_limit when processed slab isn't a free slab. This would cause to keep too much memory in the slab subsystem. This patch try to fix it by checking number of free object after all free work is done. If there is free slab at that time, we can free it so we keep free slab as minimal as possible. Signed-off-by: Joonsoo Kim --- mm/slab.c | 23 ++- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/mm/slab.c b/mm/slab.c index b96f381..df11757 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -3258,6 +3258,9 @@ static void free_block(struct kmem_cache *cachep, void **objpp, { int i; struct kmem_cache_node *n = get_node(cachep, node); + struct page *page; + + n->free_objects += nr_objects; for (i = 0; i < nr_objects; i++) { void *objp; @@ -3270,17 +3273,11 @@ static void free_block(struct kmem_cache *cachep, void **objpp, check_spinlock_acquired_node(cachep, node); slab_put_obj(cachep, page, objp); STATS_DEC_ACTIVE(cachep); - n->free_objects++; /* fixup slab chains */ - if (page->active == 0) { - if (n->free_objects > n->free_limit) { - n->free_objects -= cachep->num; - list_add_tail(>lru, list); - } else { - list_add(>lru, >slabs_free); - } - } else { + if (page->active == 0) + list_add(>lru, >slabs_free); + else { /* Unconditionally move a slab to the end of the * partial list on free - maximum time for the * other objects to be freed, too. @@ -3288,6 +3285,14 @@ static void free_block(struct kmem_cache *cachep, void **objpp, list_add_tail(>lru, >slabs_partial); } } + + while (n->free_objects > n->free_limit && !list_empty(>slabs_free)) { + n->free_objects -= cachep->num; + + page = list_last_entry(>slabs_free, struct page, lru); + list_del(>lru); + list_add(>lru, list); + } } static void cache_flusharray(struct kmem_cache *cachep, struct array_cache *ac) -- 1.9.1
[PATCH 07/11] mm/slab: racy access/modify the slab color
From: Joonsoo KimSlab color isn't needed to be changed strictly. Because locking for changing slab color could cause more lock contention so this patch implements racy access/modify the slab color. This is a preparation step to implement lockless allocation path when there is no free objects in the kmem_cache. Below is the result of concurrent allocation/free in slab allocation benchmark made by Christoph a long time ago. I make the output simpler. The number shows cycle count during alloc/free respectively so less is better. * Before Kmalloc N*alloc N*free(32): Average=365/806 Kmalloc N*alloc N*free(64): Average=452/690 Kmalloc N*alloc N*free(128): Average=736/886 Kmalloc N*alloc N*free(256): Average=1167/985 Kmalloc N*alloc N*free(512): Average=2088/1125 Kmalloc N*alloc N*free(1024): Average=4115/1184 Kmalloc N*alloc N*free(2048): Average=8451/1748 Kmalloc N*alloc N*free(4096): Average=16024/2048 * After Kmalloc N*alloc N*free(32): Average=355/750 Kmalloc N*alloc N*free(64): Average=452/812 Kmalloc N*alloc N*free(128): Average=559/1070 Kmalloc N*alloc N*free(256): Average=1176/980 Kmalloc N*alloc N*free(512): Average=1939/1189 Kmalloc N*alloc N*free(1024): Average=3521/1278 Kmalloc N*alloc N*free(2048): Average=7152/1838 Kmalloc N*alloc N*free(4096): Average=13438/2013 It shows that contention is reduced for object size >= 1024 and performance increases by roughly 15%. Signed-off-by: Joonsoo Kim --- mm/slab.c | 26 +- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/mm/slab.c b/mm/slab.c index df11757..52fc5e3 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -2536,20 +2536,7 @@ static int cache_grow(struct kmem_cache *cachep, } local_flags = flags & (GFP_CONSTRAINT_MASK|GFP_RECLAIM_MASK); - /* Take the node list lock to change the colour_next on this node */ check_irq_off(); - n = get_node(cachep, nodeid); - spin_lock(>list_lock); - - /* Get colour for the slab, and cal the next value. */ - offset = n->colour_next; - n->colour_next++; - if (n->colour_next >= cachep->colour) - n->colour_next = 0; - spin_unlock(>list_lock); - - offset *= cachep->colour_off; - if (gfpflags_allow_blocking(local_flags)) local_irq_enable(); @@ -2570,6 +2557,19 @@ static int cache_grow(struct kmem_cache *cachep, if (!page) goto failed; + n = get_node(cachep, nodeid); + + /* Get colour for the slab, and cal the next value. */ + n->colour_next++; + if (n->colour_next >= cachep->colour) + n->colour_next = 0; + + offset = n->colour_next; + if (offset >= cachep->colour) + offset = 0; + + offset *= cachep->colour_off; + /* Get slab management. */ freelist = alloc_slabmgmt(cachep, page, offset, local_flags & ~GFP_CONSTRAINT_MASK, nodeid); -- 1.9.1
[PATCH 06/11] mm/slab: don't keep free slabs if free_objects exceeds free_limit
From: Joonsoo Kim Currently, determination to free a slab is done whenever free object is put into the slab. This has a problem that free slabs are not freed even if we have free slabs and have more free_objects than free_limit when processed slab isn't a free slab. This would cause to keep too much memory in the slab subsystem. This patch try to fix it by checking number of free object after all free work is done. If there is free slab at that time, we can free it so we keep free slab as minimal as possible. Signed-off-by: Joonsoo Kim --- mm/slab.c | 23 ++- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/mm/slab.c b/mm/slab.c index b96f381..df11757 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -3258,6 +3258,9 @@ static void free_block(struct kmem_cache *cachep, void **objpp, { int i; struct kmem_cache_node *n = get_node(cachep, node); + struct page *page; + + n->free_objects += nr_objects; for (i = 0; i < nr_objects; i++) { void *objp; @@ -3270,17 +3273,11 @@ static void free_block(struct kmem_cache *cachep, void **objpp, check_spinlock_acquired_node(cachep, node); slab_put_obj(cachep, page, objp); STATS_DEC_ACTIVE(cachep); - n->free_objects++; /* fixup slab chains */ - if (page->active == 0) { - if (n->free_objects > n->free_limit) { - n->free_objects -= cachep->num; - list_add_tail(>lru, list); - } else { - list_add(>lru, >slabs_free); - } - } else { + if (page->active == 0) + list_add(>lru, >slabs_free); + else { /* Unconditionally move a slab to the end of the * partial list on free - maximum time for the * other objects to be freed, too. @@ -3288,6 +3285,14 @@ static void free_block(struct kmem_cache *cachep, void **objpp, list_add_tail(>lru, >slabs_partial); } } + + while (n->free_objects > n->free_limit && !list_empty(>slabs_free)) { + n->free_objects -= cachep->num; + + page = list_last_entry(>slabs_free, struct page, lru); + list_del(>lru); + list_add(>lru, list); + } } static void cache_flusharray(struct kmem_cache *cachep, struct array_cache *ac) -- 1.9.1
[PATCH 07/11] mm/slab: racy access/modify the slab color
From: Joonsoo Kim Slab color isn't needed to be changed strictly. Because locking for changing slab color could cause more lock contention so this patch implements racy access/modify the slab color. This is a preparation step to implement lockless allocation path when there is no free objects in the kmem_cache. Below is the result of concurrent allocation/free in slab allocation benchmark made by Christoph a long time ago. I make the output simpler. The number shows cycle count during alloc/free respectively so less is better. * Before Kmalloc N*alloc N*free(32): Average=365/806 Kmalloc N*alloc N*free(64): Average=452/690 Kmalloc N*alloc N*free(128): Average=736/886 Kmalloc N*alloc N*free(256): Average=1167/985 Kmalloc N*alloc N*free(512): Average=2088/1125 Kmalloc N*alloc N*free(1024): Average=4115/1184 Kmalloc N*alloc N*free(2048): Average=8451/1748 Kmalloc N*alloc N*free(4096): Average=16024/2048 * After Kmalloc N*alloc N*free(32): Average=355/750 Kmalloc N*alloc N*free(64): Average=452/812 Kmalloc N*alloc N*free(128): Average=559/1070 Kmalloc N*alloc N*free(256): Average=1176/980 Kmalloc N*alloc N*free(512): Average=1939/1189 Kmalloc N*alloc N*free(1024): Average=3521/1278 Kmalloc N*alloc N*free(2048): Average=7152/1838 Kmalloc N*alloc N*free(4096): Average=13438/2013 It shows that contention is reduced for object size >= 1024 and performance increases by roughly 15%. Signed-off-by: Joonsoo Kim --- mm/slab.c | 26 +- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/mm/slab.c b/mm/slab.c index df11757..52fc5e3 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -2536,20 +2536,7 @@ static int cache_grow(struct kmem_cache *cachep, } local_flags = flags & (GFP_CONSTRAINT_MASK|GFP_RECLAIM_MASK); - /* Take the node list lock to change the colour_next on this node */ check_irq_off(); - n = get_node(cachep, nodeid); - spin_lock(>list_lock); - - /* Get colour for the slab, and cal the next value. */ - offset = n->colour_next; - n->colour_next++; - if (n->colour_next >= cachep->colour) - n->colour_next = 0; - spin_unlock(>list_lock); - - offset *= cachep->colour_off; - if (gfpflags_allow_blocking(local_flags)) local_irq_enable(); @@ -2570,6 +2557,19 @@ static int cache_grow(struct kmem_cache *cachep, if (!page) goto failed; + n = get_node(cachep, nodeid); + + /* Get colour for the slab, and cal the next value. */ + n->colour_next++; + if (n->colour_next >= cachep->colour) + n->colour_next = 0; + + offset = n->colour_next; + if (offset >= cachep->colour) + offset = 0; + + offset *= cachep->colour_off; + /* Get slab management. */ freelist = alloc_slabmgmt(cachep, page, offset, local_flags & ~GFP_CONSTRAINT_MASK, nodeid); -- 1.9.1
[PATCH 09/11] mm/slab: separate cache_grow() to two parts
From: Joonsoo KimThis is a preparation step to implement lockless allocation path when there is no free objects in kmem_cache. What we'd like to do here is to refill cpu cache without holding a node lock. To accomplish this purpose, refill should be done after new slab allocation but before attaching the slab to the management list. So, this patch separates cache_grow() to two parts, allocation and attaching to the list in order to add some code inbetween them in the following patch. Signed-off-by: Joonsoo Kim --- mm/slab.c | 74 --- 1 file changed, 52 insertions(+), 22 deletions(-) diff --git a/mm/slab.c b/mm/slab.c index ce8ed65..401e60c 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -213,6 +213,11 @@ static void slabs_destroy(struct kmem_cache *cachep, struct list_head *list); static int enable_cpucache(struct kmem_cache *cachep, gfp_t gfp); static void cache_reap(struct work_struct *unused); +static inline void fixup_objfreelist_debug(struct kmem_cache *cachep, + void **list); +static inline void fixup_slab_list(struct kmem_cache *cachep, + struct kmem_cache_node *n, struct page *page, + void **list); static int slab_early_init = 1; #define INDEX_NODE kmalloc_index(sizeof(struct kmem_cache_node)) @@ -1796,7 +1801,7 @@ static size_t calculate_slab_order(struct kmem_cache *cachep, /* * Needed to avoid possible looping condition -* in cache_grow() +* in cache_grow_begin() */ if (OFF_SLAB(freelist_cache)) continue; @@ -2518,7 +2523,8 @@ static void slab_map_pages(struct kmem_cache *cache, struct page *page, * Grow (by 1) the number of slabs within a cache. This is called by * kmem_cache_alloc() when there are no active objs left in a cache. */ -static int cache_grow(struct kmem_cache *cachep, gfp_t flags, int nodeid) +static struct page *cache_grow_begin(struct kmem_cache *cachep, + gfp_t flags, int nodeid) { void *freelist; size_t offset; @@ -2584,21 +2590,40 @@ static int cache_grow(struct kmem_cache *cachep, gfp_t flags, int nodeid) if (gfpflags_allow_blocking(local_flags)) local_irq_disable(); - check_irq_off(); - spin_lock(>list_lock); - /* Make slab active. */ - list_add_tail(>lru, &(n->slabs_free)); - STATS_INC_GROWN(cachep); - n->free_objects += cachep->num; - spin_unlock(>list_lock); - return page_node; + return page; + opps1: kmem_freepages(cachep, page); failed: if (gfpflags_allow_blocking(local_flags)) local_irq_disable(); - return -1; + return NULL; +} + +static void cache_grow_end(struct kmem_cache *cachep, struct page *page) +{ + struct kmem_cache_node *n; + void *list = NULL; + + check_irq_off(); + + if (!page) + return; + + INIT_LIST_HEAD(>lru); + n = get_node(cachep, page_to_nid(page)); + + spin_lock(>list_lock); + if (!page->active) + list_add_tail(>lru, &(n->slabs_free)); + else + fixup_slab_list(cachep, n, page, ); + STATS_INC_GROWN(cachep); + n->free_objects += cachep->num - page->active; + spin_unlock(>list_lock); + + fixup_objfreelist_debug(cachep, ); } #if DEBUG @@ -2809,6 +2834,7 @@ static void *cache_alloc_refill(struct kmem_cache *cachep, gfp_t flags) struct array_cache *ac; int node; void *list = NULL; + struct page *page; check_irq_off(); node = numa_mem_id(); @@ -2836,7 +2862,6 @@ retry: } while (batchcount > 0) { - struct page *page; /* Get slab alloc is to come from. */ page = get_first_slab(n, false); if (!page) @@ -2869,8 +2894,6 @@ alloc_done: fixup_objfreelist_debug(cachep, ); if (unlikely(!ac->avail)) { - int x; - /* Check if we can use obj in pfmemalloc slab */ if (sk_memalloc_socks()) { void *obj = cache_alloc_pfmemalloc(cachep, n, flags); @@ -2879,14 +2902,18 @@ alloc_done: return obj; } - x = cache_grow(cachep, gfp_exact_node(flags), node); + page = cache_grow_begin(cachep, gfp_exact_node(flags), node); + cache_grow_end(cachep, page); - /* cache_grow can reenable interrupts, then ac could change. */ + /* +* cache_grow_begin() can reenable interrupts, +* then ac could change. +*/
[PATCH 08/11] mm/slab: make cache_grow() handle the page allocated on arbitrary node
From: Joonsoo KimCurrently, cache_grow() assumes that allocated page's nodeid would be same with parameter nodeid which is used for allocation request. If we discard this assumption, we can handle fallback_alloc() case gracefully. So, this patch makes cache_grow() handle the page allocated on arbitrary node and clean-up relevant code. Signed-off-by: Joonsoo Kim --- mm/slab.c | 60 +--- 1 file changed, 21 insertions(+), 39 deletions(-) diff --git a/mm/slab.c b/mm/slab.c index 52fc5e3..ce8ed65 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -2518,13 +2518,14 @@ static void slab_map_pages(struct kmem_cache *cache, struct page *page, * Grow (by 1) the number of slabs within a cache. This is called by * kmem_cache_alloc() when there are no active objs left in a cache. */ -static int cache_grow(struct kmem_cache *cachep, - gfp_t flags, int nodeid, struct page *page) +static int cache_grow(struct kmem_cache *cachep, gfp_t flags, int nodeid) { void *freelist; size_t offset; gfp_t local_flags; + int page_node; struct kmem_cache_node *n; + struct page *page; /* * Be lazy and only check for valid flags here, keeping it out of the @@ -2552,12 +2553,12 @@ static int cache_grow(struct kmem_cache *cachep, * Get mem for the objs. Attempt to allocate a physical page from * 'nodeid'. */ - if (!page) - page = kmem_getpages(cachep, local_flags, nodeid); + page = kmem_getpages(cachep, local_flags, nodeid); if (!page) goto failed; - n = get_node(cachep, nodeid); + page_node = page_to_nid(page); + n = get_node(cachep, page_node); /* Get colour for the slab, and cal the next value. */ n->colour_next++; @@ -2572,7 +2573,7 @@ static int cache_grow(struct kmem_cache *cachep, /* Get slab management. */ freelist = alloc_slabmgmt(cachep, page, offset, - local_flags & ~GFP_CONSTRAINT_MASK, nodeid); + local_flags & ~GFP_CONSTRAINT_MASK, page_node); if (OFF_SLAB(cachep) && !freelist) goto opps1; @@ -2591,13 +2592,13 @@ static int cache_grow(struct kmem_cache *cachep, STATS_INC_GROWN(cachep); n->free_objects += cachep->num; spin_unlock(>list_lock); - return 1; + return page_node; opps1: kmem_freepages(cachep, page); failed: if (gfpflags_allow_blocking(local_flags)) local_irq_disable(); - return 0; + return -1; } #if DEBUG @@ -2878,14 +2879,14 @@ alloc_done: return obj; } - x = cache_grow(cachep, gfp_exact_node(flags), node, NULL); + x = cache_grow(cachep, gfp_exact_node(flags), node); /* cache_grow can reenable interrupts, then ac could change. */ ac = cpu_cache_get(cachep); node = numa_mem_id(); /* no objects in sight? abort */ - if (!x && ac->avail == 0) + if (x < 0 && ac->avail == 0) return NULL; if (!ac->avail) /* objects refilled by interrupt? */ @@ -3014,7 +3015,6 @@ static void *alternate_node_alloc(struct kmem_cache *cachep, gfp_t flags) static void *fallback_alloc(struct kmem_cache *cache, gfp_t flags) { struct zonelist *zonelist; - gfp_t local_flags; struct zoneref *z; struct zone *zone; enum zone_type high_zoneidx = gfp_zone(flags); @@ -3025,8 +3025,6 @@ static void *fallback_alloc(struct kmem_cache *cache, gfp_t flags) if (flags & __GFP_THISNODE) return NULL; - local_flags = flags & (GFP_CONSTRAINT_MASK|GFP_RECLAIM_MASK); - retry_cpuset: cpuset_mems_cookie = read_mems_allowed_begin(); zonelist = node_zonelist(mempolicy_slab_node(), flags); @@ -3056,33 +3054,17 @@ retry: * We may trigger various forms of reclaim on the allowed * set and go into memory reserves if necessary. */ - struct page *page; + nid = cache_grow(cache, flags, numa_mem_id()); + if (nid >= 0) { + obj = cache_alloc_node(cache, + gfp_exact_node(flags), nid); - if (gfpflags_allow_blocking(local_flags)) - local_irq_enable(); - kmem_flagcheck(cache, flags); - page = kmem_getpages(cache, local_flags, numa_mem_id()); - if (gfpflags_allow_blocking(local_flags)) - local_irq_disable(); - if (page) { /* -* Insert into the appropriate per node queues +*
[PATCH 11/11] mm/slab: lockless decision to grow cache
From: Joonsoo KimTo check whther free objects exist or not precisely, we need to grab a lock. But, accuracy isn't that important because race window would be even small and if there is too much free object, cache reaper would reap it. So, this patch makes the check for free object exisistence not to hold a lock. This will reduce lock contention in heavily allocation case. Note that until now, n->shared can be freed during the processing by writing slabinfo, but, with some trick in this patch, we can access it freely within interrupt disabled period. Below is the result of concurrent allocation/free in slab allocation benchmark made by Christoph a long time ago. I make the output simpler. The number shows cycle count during alloc/free respectively so less is better. * Before Kmalloc N*alloc N*free(32): Average=248/966 Kmalloc N*alloc N*free(64): Average=261/949 Kmalloc N*alloc N*free(128): Average=314/1016 Kmalloc N*alloc N*free(256): Average=741/1061 Kmalloc N*alloc N*free(512): Average=1246/1152 Kmalloc N*alloc N*free(1024): Average=2437/1259 Kmalloc N*alloc N*free(2048): Average=4980/1800 Kmalloc N*alloc N*free(4096): Average=9000/2078 * After Kmalloc N*alloc N*free(32): Average=344/792 Kmalloc N*alloc N*free(64): Average=347/882 Kmalloc N*alloc N*free(128): Average=390/959 Kmalloc N*alloc N*free(256): Average=393/1067 Kmalloc N*alloc N*free(512): Average=683/1229 Kmalloc N*alloc N*free(1024): Average=1295/1325 Kmalloc N*alloc N*free(2048): Average=2513/1664 Kmalloc N*alloc N*free(4096): Average=4742/2172 It shows that allocation performance decreases for the object size up to 128 and it may be due to extra checks in cache_alloc_refill(). But, with considering improvement of free performance, net result looks the same. Result for other size class looks very promising, roughly, 50% performance improvement. Signed-off-by: Joonsoo Kim --- mm/slab.c | 21 ++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/mm/slab.c b/mm/slab.c index 029d6b3..b70aabf 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -951,6 +951,15 @@ static int setup_kmem_cache_node(struct kmem_cache *cachep, spin_unlock_irq(>list_lock); slabs_destroy(cachep, ); + /* +* To protect lockless access to n->shared during irq disabled context. +* If n->shared isn't NULL in irq disabled context, accessing to it is +* guaranteed to be valid until irq is re-enabled, because it will be +* freed after kick_all_cpus_sync(). +*/ + if (force_change) + kick_all_cpus_sync(); + fail: kfree(old_shared); kfree(new_shared); @@ -2855,7 +2864,7 @@ static void *cache_alloc_refill(struct kmem_cache *cachep, gfp_t flags) { int batchcount; struct kmem_cache_node *n; - struct array_cache *ac; + struct array_cache *ac, *shared; int node; void *list = NULL; struct page *page; @@ -2876,11 +2885,16 @@ static void *cache_alloc_refill(struct kmem_cache *cachep, gfp_t flags) n = get_node(cachep, node); BUG_ON(ac->avail > 0 || !n); + shared = READ_ONCE(n->shared); + if (!n->free_objects && (!shared || !shared->avail)) + goto direct_grow; + spin_lock(>list_lock); + shared = READ_ONCE(n->shared); /* See if we can refill from the shared array */ - if (n->shared && transfer_objects(ac, n->shared, batchcount)) { - n->shared->touched = 1; + if (shared && transfer_objects(ac, shared, batchcount)) { + shared->touched = 1; goto alloc_done; } @@ -2902,6 +2916,7 @@ alloc_done: spin_unlock(>list_lock); fixup_objfreelist_debug(cachep, ); +direct_grow: if (unlikely(!ac->avail)) { /* Check if we can use obj in pfmemalloc slab */ if (sk_memalloc_socks()) { -- 1.9.1
[PATCH 09/11] mm/slab: separate cache_grow() to two parts
From: Joonsoo Kim This is a preparation step to implement lockless allocation path when there is no free objects in kmem_cache. What we'd like to do here is to refill cpu cache without holding a node lock. To accomplish this purpose, refill should be done after new slab allocation but before attaching the slab to the management list. So, this patch separates cache_grow() to two parts, allocation and attaching to the list in order to add some code inbetween them in the following patch. Signed-off-by: Joonsoo Kim --- mm/slab.c | 74 --- 1 file changed, 52 insertions(+), 22 deletions(-) diff --git a/mm/slab.c b/mm/slab.c index ce8ed65..401e60c 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -213,6 +213,11 @@ static void slabs_destroy(struct kmem_cache *cachep, struct list_head *list); static int enable_cpucache(struct kmem_cache *cachep, gfp_t gfp); static void cache_reap(struct work_struct *unused); +static inline void fixup_objfreelist_debug(struct kmem_cache *cachep, + void **list); +static inline void fixup_slab_list(struct kmem_cache *cachep, + struct kmem_cache_node *n, struct page *page, + void **list); static int slab_early_init = 1; #define INDEX_NODE kmalloc_index(sizeof(struct kmem_cache_node)) @@ -1796,7 +1801,7 @@ static size_t calculate_slab_order(struct kmem_cache *cachep, /* * Needed to avoid possible looping condition -* in cache_grow() +* in cache_grow_begin() */ if (OFF_SLAB(freelist_cache)) continue; @@ -2518,7 +2523,8 @@ static void slab_map_pages(struct kmem_cache *cache, struct page *page, * Grow (by 1) the number of slabs within a cache. This is called by * kmem_cache_alloc() when there are no active objs left in a cache. */ -static int cache_grow(struct kmem_cache *cachep, gfp_t flags, int nodeid) +static struct page *cache_grow_begin(struct kmem_cache *cachep, + gfp_t flags, int nodeid) { void *freelist; size_t offset; @@ -2584,21 +2590,40 @@ static int cache_grow(struct kmem_cache *cachep, gfp_t flags, int nodeid) if (gfpflags_allow_blocking(local_flags)) local_irq_disable(); - check_irq_off(); - spin_lock(>list_lock); - /* Make slab active. */ - list_add_tail(>lru, &(n->slabs_free)); - STATS_INC_GROWN(cachep); - n->free_objects += cachep->num; - spin_unlock(>list_lock); - return page_node; + return page; + opps1: kmem_freepages(cachep, page); failed: if (gfpflags_allow_blocking(local_flags)) local_irq_disable(); - return -1; + return NULL; +} + +static void cache_grow_end(struct kmem_cache *cachep, struct page *page) +{ + struct kmem_cache_node *n; + void *list = NULL; + + check_irq_off(); + + if (!page) + return; + + INIT_LIST_HEAD(>lru); + n = get_node(cachep, page_to_nid(page)); + + spin_lock(>list_lock); + if (!page->active) + list_add_tail(>lru, &(n->slabs_free)); + else + fixup_slab_list(cachep, n, page, ); + STATS_INC_GROWN(cachep); + n->free_objects += cachep->num - page->active; + spin_unlock(>list_lock); + + fixup_objfreelist_debug(cachep, ); } #if DEBUG @@ -2809,6 +2834,7 @@ static void *cache_alloc_refill(struct kmem_cache *cachep, gfp_t flags) struct array_cache *ac; int node; void *list = NULL; + struct page *page; check_irq_off(); node = numa_mem_id(); @@ -2836,7 +2862,6 @@ retry: } while (batchcount > 0) { - struct page *page; /* Get slab alloc is to come from. */ page = get_first_slab(n, false); if (!page) @@ -2869,8 +2894,6 @@ alloc_done: fixup_objfreelist_debug(cachep, ); if (unlikely(!ac->avail)) { - int x; - /* Check if we can use obj in pfmemalloc slab */ if (sk_memalloc_socks()) { void *obj = cache_alloc_pfmemalloc(cachep, n, flags); @@ -2879,14 +2902,18 @@ alloc_done: return obj; } - x = cache_grow(cachep, gfp_exact_node(flags), node); + page = cache_grow_begin(cachep, gfp_exact_node(flags), node); + cache_grow_end(cachep, page); - /* cache_grow can reenable interrupts, then ac could change. */ + /* +* cache_grow_begin() can reenable interrupts, +* then ac could change. +*/ ac = cpu_cache_get(cachep);
[PATCH 08/11] mm/slab: make cache_grow() handle the page allocated on arbitrary node
From: Joonsoo Kim Currently, cache_grow() assumes that allocated page's nodeid would be same with parameter nodeid which is used for allocation request. If we discard this assumption, we can handle fallback_alloc() case gracefully. So, this patch makes cache_grow() handle the page allocated on arbitrary node and clean-up relevant code. Signed-off-by: Joonsoo Kim --- mm/slab.c | 60 +--- 1 file changed, 21 insertions(+), 39 deletions(-) diff --git a/mm/slab.c b/mm/slab.c index 52fc5e3..ce8ed65 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -2518,13 +2518,14 @@ static void slab_map_pages(struct kmem_cache *cache, struct page *page, * Grow (by 1) the number of slabs within a cache. This is called by * kmem_cache_alloc() when there are no active objs left in a cache. */ -static int cache_grow(struct kmem_cache *cachep, - gfp_t flags, int nodeid, struct page *page) +static int cache_grow(struct kmem_cache *cachep, gfp_t flags, int nodeid) { void *freelist; size_t offset; gfp_t local_flags; + int page_node; struct kmem_cache_node *n; + struct page *page; /* * Be lazy and only check for valid flags here, keeping it out of the @@ -2552,12 +2553,12 @@ static int cache_grow(struct kmem_cache *cachep, * Get mem for the objs. Attempt to allocate a physical page from * 'nodeid'. */ - if (!page) - page = kmem_getpages(cachep, local_flags, nodeid); + page = kmem_getpages(cachep, local_flags, nodeid); if (!page) goto failed; - n = get_node(cachep, nodeid); + page_node = page_to_nid(page); + n = get_node(cachep, page_node); /* Get colour for the slab, and cal the next value. */ n->colour_next++; @@ -2572,7 +2573,7 @@ static int cache_grow(struct kmem_cache *cachep, /* Get slab management. */ freelist = alloc_slabmgmt(cachep, page, offset, - local_flags & ~GFP_CONSTRAINT_MASK, nodeid); + local_flags & ~GFP_CONSTRAINT_MASK, page_node); if (OFF_SLAB(cachep) && !freelist) goto opps1; @@ -2591,13 +2592,13 @@ static int cache_grow(struct kmem_cache *cachep, STATS_INC_GROWN(cachep); n->free_objects += cachep->num; spin_unlock(>list_lock); - return 1; + return page_node; opps1: kmem_freepages(cachep, page); failed: if (gfpflags_allow_blocking(local_flags)) local_irq_disable(); - return 0; + return -1; } #if DEBUG @@ -2878,14 +2879,14 @@ alloc_done: return obj; } - x = cache_grow(cachep, gfp_exact_node(flags), node, NULL); + x = cache_grow(cachep, gfp_exact_node(flags), node); /* cache_grow can reenable interrupts, then ac could change. */ ac = cpu_cache_get(cachep); node = numa_mem_id(); /* no objects in sight? abort */ - if (!x && ac->avail == 0) + if (x < 0 && ac->avail == 0) return NULL; if (!ac->avail) /* objects refilled by interrupt? */ @@ -3014,7 +3015,6 @@ static void *alternate_node_alloc(struct kmem_cache *cachep, gfp_t flags) static void *fallback_alloc(struct kmem_cache *cache, gfp_t flags) { struct zonelist *zonelist; - gfp_t local_flags; struct zoneref *z; struct zone *zone; enum zone_type high_zoneidx = gfp_zone(flags); @@ -3025,8 +3025,6 @@ static void *fallback_alloc(struct kmem_cache *cache, gfp_t flags) if (flags & __GFP_THISNODE) return NULL; - local_flags = flags & (GFP_CONSTRAINT_MASK|GFP_RECLAIM_MASK); - retry_cpuset: cpuset_mems_cookie = read_mems_allowed_begin(); zonelist = node_zonelist(mempolicy_slab_node(), flags); @@ -3056,33 +3054,17 @@ retry: * We may trigger various forms of reclaim on the allowed * set and go into memory reserves if necessary. */ - struct page *page; + nid = cache_grow(cache, flags, numa_mem_id()); + if (nid >= 0) { + obj = cache_alloc_node(cache, + gfp_exact_node(flags), nid); - if (gfpflags_allow_blocking(local_flags)) - local_irq_enable(); - kmem_flagcheck(cache, flags); - page = kmem_getpages(cache, local_flags, numa_mem_id()); - if (gfpflags_allow_blocking(local_flags)) - local_irq_disable(); - if (page) { /* -* Insert into the appropriate per node queues +* Another processor may allocate the objects in +
[PATCH 11/11] mm/slab: lockless decision to grow cache
From: Joonsoo Kim To check whther free objects exist or not precisely, we need to grab a lock. But, accuracy isn't that important because race window would be even small and if there is too much free object, cache reaper would reap it. So, this patch makes the check for free object exisistence not to hold a lock. This will reduce lock contention in heavily allocation case. Note that until now, n->shared can be freed during the processing by writing slabinfo, but, with some trick in this patch, we can access it freely within interrupt disabled period. Below is the result of concurrent allocation/free in slab allocation benchmark made by Christoph a long time ago. I make the output simpler. The number shows cycle count during alloc/free respectively so less is better. * Before Kmalloc N*alloc N*free(32): Average=248/966 Kmalloc N*alloc N*free(64): Average=261/949 Kmalloc N*alloc N*free(128): Average=314/1016 Kmalloc N*alloc N*free(256): Average=741/1061 Kmalloc N*alloc N*free(512): Average=1246/1152 Kmalloc N*alloc N*free(1024): Average=2437/1259 Kmalloc N*alloc N*free(2048): Average=4980/1800 Kmalloc N*alloc N*free(4096): Average=9000/2078 * After Kmalloc N*alloc N*free(32): Average=344/792 Kmalloc N*alloc N*free(64): Average=347/882 Kmalloc N*alloc N*free(128): Average=390/959 Kmalloc N*alloc N*free(256): Average=393/1067 Kmalloc N*alloc N*free(512): Average=683/1229 Kmalloc N*alloc N*free(1024): Average=1295/1325 Kmalloc N*alloc N*free(2048): Average=2513/1664 Kmalloc N*alloc N*free(4096): Average=4742/2172 It shows that allocation performance decreases for the object size up to 128 and it may be due to extra checks in cache_alloc_refill(). But, with considering improvement of free performance, net result looks the same. Result for other size class looks very promising, roughly, 50% performance improvement. Signed-off-by: Joonsoo Kim --- mm/slab.c | 21 ++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/mm/slab.c b/mm/slab.c index 029d6b3..b70aabf 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -951,6 +951,15 @@ static int setup_kmem_cache_node(struct kmem_cache *cachep, spin_unlock_irq(>list_lock); slabs_destroy(cachep, ); + /* +* To protect lockless access to n->shared during irq disabled context. +* If n->shared isn't NULL in irq disabled context, accessing to it is +* guaranteed to be valid until irq is re-enabled, because it will be +* freed after kick_all_cpus_sync(). +*/ + if (force_change) + kick_all_cpus_sync(); + fail: kfree(old_shared); kfree(new_shared); @@ -2855,7 +2864,7 @@ static void *cache_alloc_refill(struct kmem_cache *cachep, gfp_t flags) { int batchcount; struct kmem_cache_node *n; - struct array_cache *ac; + struct array_cache *ac, *shared; int node; void *list = NULL; struct page *page; @@ -2876,11 +2885,16 @@ static void *cache_alloc_refill(struct kmem_cache *cachep, gfp_t flags) n = get_node(cachep, node); BUG_ON(ac->avail > 0 || !n); + shared = READ_ONCE(n->shared); + if (!n->free_objects && (!shared || !shared->avail)) + goto direct_grow; + spin_lock(>list_lock); + shared = READ_ONCE(n->shared); /* See if we can refill from the shared array */ - if (n->shared && transfer_objects(ac, n->shared, batchcount)) { - n->shared->touched = 1; + if (shared && transfer_objects(ac, shared, batchcount)) { + shared->touched = 1; goto alloc_done; } @@ -2902,6 +2916,7 @@ alloc_done: spin_unlock(>list_lock); fixup_objfreelist_debug(cachep, ); +direct_grow: if (unlikely(!ac->avail)) { /* Check if we can use obj in pfmemalloc slab */ if (sk_memalloc_socks()) { -- 1.9.1
[PATCH 01/11] mm/slab: hold a slab_mutex when calling __kmem_cache_shrink()
From: Joonsoo KimMajor kmem_cache metadata in slab subsystem is synchronized with the slab_mutex. In SLAB, if some of them is changed, node's shared array cache would be freed and re-populated. If __kmem_cache_shrink() is called at the same time, it will call drain_array() with n->shared without holding node lock so problem can happen. We can fix this small theoretical race condition by holding node lock in drain_array(), but, holding a slab_mutex in kmem_cache_shrink() looks more appropriate solution because stable state would make things less error-prone and this is not performance critical path. In addtion, annotate on SLAB functions. Signed-off-by: Joonsoo Kim --- mm/slab.c| 2 ++ mm/slab_common.c | 4 2 files changed, 6 insertions(+) diff --git a/mm/slab.c b/mm/slab.c index a53a0f6..043606a 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -2218,6 +2218,7 @@ static void do_drain(void *arg) ac->avail = 0; } +/* Should be called with slab_mutex to prevent from freeing shared array */ static void drain_cpu_caches(struct kmem_cache *cachep) { struct kmem_cache_node *n; @@ -3871,6 +3872,7 @@ skip_setup: * Drain an array if it contains any elements taking the node lock only if * necessary. Note that the node listlock also protects the array_cache * if drain_array() is used on the shared array. + * Should be called with slab_mutex to prevent from freeing shared array. */ static void drain_array(struct kmem_cache *cachep, struct kmem_cache_node *n, struct array_cache *ac, int force, int node) diff --git a/mm/slab_common.c b/mm/slab_common.c index a65dad7..5bed565 100644 --- a/mm/slab_common.c +++ b/mm/slab_common.c @@ -755,7 +755,11 @@ int kmem_cache_shrink(struct kmem_cache *cachep) get_online_cpus(); get_online_mems(); kasan_cache_shrink(cachep); + + mutex_lock(_mutex); ret = __kmem_cache_shrink(cachep, false); + mutex_unlock(_mutex); + put_online_mems(); put_online_cpus(); return ret; -- 1.9.1
[PATCH 10/11] mm/slab: refill cpu cache through a new slab without holding a node lock
From: Joonsoo KimUntil now, cache growing makes a free slab on node's slab list and then we can allocate free objects from it. This necessarily requires to hold a node lock which is very contended. If we refill cpu cache before attaching it to node's slab list, we can avoid holding a node lock as much as possible because this newly allocated slab is only visible to the current task. This will reduce lock contention. Below is the result of concurrent allocation/free in slab allocation benchmark made by Christoph a long time ago. I make the output simpler. The number shows cycle count during alloc/free respectively so less is better. * Before Kmalloc N*alloc N*free(32): Average=355/750 Kmalloc N*alloc N*free(64): Average=452/812 Kmalloc N*alloc N*free(128): Average=559/1070 Kmalloc N*alloc N*free(256): Average=1176/980 Kmalloc N*alloc N*free(512): Average=1939/1189 Kmalloc N*alloc N*free(1024): Average=3521/1278 Kmalloc N*alloc N*free(2048): Average=7152/1838 Kmalloc N*alloc N*free(4096): Average=13438/2013 * After Kmalloc N*alloc N*free(32): Average=248/966 Kmalloc N*alloc N*free(64): Average=261/949 Kmalloc N*alloc N*free(128): Average=314/1016 Kmalloc N*alloc N*free(256): Average=741/1061 Kmalloc N*alloc N*free(512): Average=1246/1152 Kmalloc N*alloc N*free(1024): Average=2437/1259 Kmalloc N*alloc N*free(2048): Average=4980/1800 Kmalloc N*alloc N*free(4096): Average=9000/2078 It shows that contention is reduced for all the object sizes and performance increases by 30 ~ 40%. Signed-off-by: Joonsoo Kim --- mm/slab.c | 68 +-- 1 file changed, 36 insertions(+), 32 deletions(-) diff --git a/mm/slab.c b/mm/slab.c index 401e60c..029d6b3 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -2827,6 +2827,30 @@ static noinline void *cache_alloc_pfmemalloc(struct kmem_cache *cachep, return obj; } +/* + * Slab list should be fixed up by fixup_slab_list() for existing slab + * or cache_grow_end() for new slab + */ +static __always_inline int alloc_block(struct kmem_cache *cachep, + struct array_cache *ac, struct page *page, int batchcount) +{ + /* +* There must be at least one object available for +* allocation. +*/ + BUG_ON(page->active >= cachep->num); + + while (page->active < cachep->num && batchcount--) { + STATS_INC_ALLOCED(cachep); + STATS_INC_ACTIVE(cachep); + STATS_SET_HIGH(cachep); + + ac->entry[ac->avail++] = slab_get_obj(cachep, page); + } + + return batchcount; +} + static void *cache_alloc_refill(struct kmem_cache *cachep, gfp_t flags) { int batchcount; @@ -2839,7 +2863,6 @@ static void *cache_alloc_refill(struct kmem_cache *cachep, gfp_t flags) check_irq_off(); node = numa_mem_id(); -retry: ac = cpu_cache_get(cachep); batchcount = ac->batchcount; if (!ac->touched && batchcount > BATCHREFILL_LIMIT) { @@ -2869,21 +2892,7 @@ retry: check_spinlock_acquired(cachep); - /* -* The slab was either on partial or free list so -* there must be at least one object available for -* allocation. -*/ - BUG_ON(page->active >= cachep->num); - - while (page->active < cachep->num && batchcount--) { - STATS_INC_ALLOCED(cachep); - STATS_INC_ACTIVE(cachep); - STATS_SET_HIGH(cachep); - - ac->entry[ac->avail++] = slab_get_obj(cachep, page); - } - + batchcount = alloc_block(cachep, ac, page, batchcount); fixup_slab_list(cachep, n, page, ); } @@ -2903,21 +2912,18 @@ alloc_done: } page = cache_grow_begin(cachep, gfp_exact_node(flags), node); - cache_grow_end(cachep, page); /* * cache_grow_begin() can reenable interrupts, * then ac could change. */ ac = cpu_cache_get(cachep); - node = numa_mem_id(); + if (!ac->avail && page) + alloc_block(cachep, ac, page, batchcount); + cache_grow_end(cachep, page); - /* no objects in sight? abort */ - if (!page && ac->avail == 0) + if (!ac->avail) return NULL; - - if (!ac->avail) /* objects refilled by interrupt? */ - goto retry; } ac->touched = 1; @@ -3111,14 +3117,13 @@ static void *cache_alloc_node(struct kmem_cache *cachep, gfp_t flags, { struct page *page; struct kmem_cache_node *n; - void *obj; + void *obj = NULL; void *list = NULL; VM_BUG_ON(nodeid < 0 || nodeid
[PATCH 10/11] mm/slab: refill cpu cache through a new slab without holding a node lock
From: Joonsoo Kim Until now, cache growing makes a free slab on node's slab list and then we can allocate free objects from it. This necessarily requires to hold a node lock which is very contended. If we refill cpu cache before attaching it to node's slab list, we can avoid holding a node lock as much as possible because this newly allocated slab is only visible to the current task. This will reduce lock contention. Below is the result of concurrent allocation/free in slab allocation benchmark made by Christoph a long time ago. I make the output simpler. The number shows cycle count during alloc/free respectively so less is better. * Before Kmalloc N*alloc N*free(32): Average=355/750 Kmalloc N*alloc N*free(64): Average=452/812 Kmalloc N*alloc N*free(128): Average=559/1070 Kmalloc N*alloc N*free(256): Average=1176/980 Kmalloc N*alloc N*free(512): Average=1939/1189 Kmalloc N*alloc N*free(1024): Average=3521/1278 Kmalloc N*alloc N*free(2048): Average=7152/1838 Kmalloc N*alloc N*free(4096): Average=13438/2013 * After Kmalloc N*alloc N*free(32): Average=248/966 Kmalloc N*alloc N*free(64): Average=261/949 Kmalloc N*alloc N*free(128): Average=314/1016 Kmalloc N*alloc N*free(256): Average=741/1061 Kmalloc N*alloc N*free(512): Average=1246/1152 Kmalloc N*alloc N*free(1024): Average=2437/1259 Kmalloc N*alloc N*free(2048): Average=4980/1800 Kmalloc N*alloc N*free(4096): Average=9000/2078 It shows that contention is reduced for all the object sizes and performance increases by 30 ~ 40%. Signed-off-by: Joonsoo Kim --- mm/slab.c | 68 +-- 1 file changed, 36 insertions(+), 32 deletions(-) diff --git a/mm/slab.c b/mm/slab.c index 401e60c..029d6b3 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -2827,6 +2827,30 @@ static noinline void *cache_alloc_pfmemalloc(struct kmem_cache *cachep, return obj; } +/* + * Slab list should be fixed up by fixup_slab_list() for existing slab + * or cache_grow_end() for new slab + */ +static __always_inline int alloc_block(struct kmem_cache *cachep, + struct array_cache *ac, struct page *page, int batchcount) +{ + /* +* There must be at least one object available for +* allocation. +*/ + BUG_ON(page->active >= cachep->num); + + while (page->active < cachep->num && batchcount--) { + STATS_INC_ALLOCED(cachep); + STATS_INC_ACTIVE(cachep); + STATS_SET_HIGH(cachep); + + ac->entry[ac->avail++] = slab_get_obj(cachep, page); + } + + return batchcount; +} + static void *cache_alloc_refill(struct kmem_cache *cachep, gfp_t flags) { int batchcount; @@ -2839,7 +2863,6 @@ static void *cache_alloc_refill(struct kmem_cache *cachep, gfp_t flags) check_irq_off(); node = numa_mem_id(); -retry: ac = cpu_cache_get(cachep); batchcount = ac->batchcount; if (!ac->touched && batchcount > BATCHREFILL_LIMIT) { @@ -2869,21 +2892,7 @@ retry: check_spinlock_acquired(cachep); - /* -* The slab was either on partial or free list so -* there must be at least one object available for -* allocation. -*/ - BUG_ON(page->active >= cachep->num); - - while (page->active < cachep->num && batchcount--) { - STATS_INC_ALLOCED(cachep); - STATS_INC_ACTIVE(cachep); - STATS_SET_HIGH(cachep); - - ac->entry[ac->avail++] = slab_get_obj(cachep, page); - } - + batchcount = alloc_block(cachep, ac, page, batchcount); fixup_slab_list(cachep, n, page, ); } @@ -2903,21 +2912,18 @@ alloc_done: } page = cache_grow_begin(cachep, gfp_exact_node(flags), node); - cache_grow_end(cachep, page); /* * cache_grow_begin() can reenable interrupts, * then ac could change. */ ac = cpu_cache_get(cachep); - node = numa_mem_id(); + if (!ac->avail && page) + alloc_block(cachep, ac, page, batchcount); + cache_grow_end(cachep, page); - /* no objects in sight? abort */ - if (!page && ac->avail == 0) + if (!ac->avail) return NULL; - - if (!ac->avail) /* objects refilled by interrupt? */ - goto retry; } ac->touched = 1; @@ -3111,14 +3117,13 @@ static void *cache_alloc_node(struct kmem_cache *cachep, gfp_t flags, { struct page *page; struct kmem_cache_node *n; - void *obj; + void *obj = NULL; void *list = NULL; VM_BUG_ON(nodeid < 0 || nodeid >= MAX_NUMNODES); n = get_node(cachep,
[PATCH 01/11] mm/slab: hold a slab_mutex when calling __kmem_cache_shrink()
From: Joonsoo Kim Major kmem_cache metadata in slab subsystem is synchronized with the slab_mutex. In SLAB, if some of them is changed, node's shared array cache would be freed and re-populated. If __kmem_cache_shrink() is called at the same time, it will call drain_array() with n->shared without holding node lock so problem can happen. We can fix this small theoretical race condition by holding node lock in drain_array(), but, holding a slab_mutex in kmem_cache_shrink() looks more appropriate solution because stable state would make things less error-prone and this is not performance critical path. In addtion, annotate on SLAB functions. Signed-off-by: Joonsoo Kim --- mm/slab.c| 2 ++ mm/slab_common.c | 4 2 files changed, 6 insertions(+) diff --git a/mm/slab.c b/mm/slab.c index a53a0f6..043606a 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -2218,6 +2218,7 @@ static void do_drain(void *arg) ac->avail = 0; } +/* Should be called with slab_mutex to prevent from freeing shared array */ static void drain_cpu_caches(struct kmem_cache *cachep) { struct kmem_cache_node *n; @@ -3871,6 +3872,7 @@ skip_setup: * Drain an array if it contains any elements taking the node lock only if * necessary. Note that the node listlock also protects the array_cache * if drain_array() is used on the shared array. + * Should be called with slab_mutex to prevent from freeing shared array. */ static void drain_array(struct kmem_cache *cachep, struct kmem_cache_node *n, struct array_cache *ac, int force, int node) diff --git a/mm/slab_common.c b/mm/slab_common.c index a65dad7..5bed565 100644 --- a/mm/slab_common.c +++ b/mm/slab_common.c @@ -755,7 +755,11 @@ int kmem_cache_shrink(struct kmem_cache *cachep) get_online_cpus(); get_online_mems(); kasan_cache_shrink(cachep); + + mutex_lock(_mutex); ret = __kmem_cache_shrink(cachep, false); + mutex_unlock(_mutex); + put_online_mems(); put_online_cpus(); return ret; -- 1.9.1
[PATCH 02/11] mm/slab: remove BAD_ALIEN_MAGIC again
From: Joonsoo KimInitial attemp to remove BAD_ALIEN_MAGIC is once reverted by 'commit edcad2509550 ("Revert "slab: remove BAD_ALIEN_MAGIC"")' because it causes a problem on m68k which has many node but !CONFIG_NUMA. In this case, although alien cache isn't used at all but to cope with some initialization path, garbage value is used and that is BAD_ALIEN_MAGIC. Now, this patch set use_alien_caches to 0 when !CONFIG_NUMA, there is no initialization path problem so we don't need BAD_ALIEN_MAGIC at all. So remove it. Signed-off-by: Joonsoo Kim --- mm/slab.c | 6 ++ 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/mm/slab.c b/mm/slab.c index 043606a..a5a205b 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -421,8 +421,6 @@ static struct kmem_cache kmem_cache_boot = { .name = "kmem_cache", }; -#define BAD_ALIEN_MAGIC 0x01020304ul - static DEFINE_PER_CPU(struct delayed_work, slab_reap_work); static inline struct array_cache *cpu_cache_get(struct kmem_cache *cachep) @@ -637,7 +635,7 @@ static int transfer_objects(struct array_cache *to, static inline struct alien_cache **alloc_alien_cache(int node, int limit, gfp_t gfp) { - return (struct alien_cache **)BAD_ALIEN_MAGIC; + return NULL; } static inline void free_alien_cache(struct alien_cache **ac_ptr) @@ -1205,7 +1203,7 @@ void __init kmem_cache_init(void) sizeof(struct rcu_head)); kmem_cache = _cache_boot; - if (num_possible_nodes() == 1) + if (!IS_ENABLED(CONFIG_NUMA) || num_possible_nodes() == 1) use_alien_caches = 0; for (i = 0; i < NUM_INIT_LISTS; i++) -- 1.9.1
[PATCH 02/11] mm/slab: remove BAD_ALIEN_MAGIC again
From: Joonsoo Kim Initial attemp to remove BAD_ALIEN_MAGIC is once reverted by 'commit edcad2509550 ("Revert "slab: remove BAD_ALIEN_MAGIC"")' because it causes a problem on m68k which has many node but !CONFIG_NUMA. In this case, although alien cache isn't used at all but to cope with some initialization path, garbage value is used and that is BAD_ALIEN_MAGIC. Now, this patch set use_alien_caches to 0 when !CONFIG_NUMA, there is no initialization path problem so we don't need BAD_ALIEN_MAGIC at all. So remove it. Signed-off-by: Joonsoo Kim --- mm/slab.c | 6 ++ 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/mm/slab.c b/mm/slab.c index 043606a..a5a205b 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -421,8 +421,6 @@ static struct kmem_cache kmem_cache_boot = { .name = "kmem_cache", }; -#define BAD_ALIEN_MAGIC 0x01020304ul - static DEFINE_PER_CPU(struct delayed_work, slab_reap_work); static inline struct array_cache *cpu_cache_get(struct kmem_cache *cachep) @@ -637,7 +635,7 @@ static int transfer_objects(struct array_cache *to, static inline struct alien_cache **alloc_alien_cache(int node, int limit, gfp_t gfp) { - return (struct alien_cache **)BAD_ALIEN_MAGIC; + return NULL; } static inline void free_alien_cache(struct alien_cache **ac_ptr) @@ -1205,7 +1203,7 @@ void __init kmem_cache_init(void) sizeof(struct rcu_head)); kmem_cache = _cache_boot; - if (num_possible_nodes() == 1) + if (!IS_ENABLED(CONFIG_NUMA) || num_possible_nodes() == 1) use_alien_caches = 0; for (i = 0; i < NUM_INIT_LISTS; i++) -- 1.9.1
[PATCH 03/11] mm/slab: drain the free slab as much as possible
From: Joonsoo Kimslabs_tofree() implies freeing all free slab. We can do it with just providing INT_MAX. Signed-off-by: Joonsoo Kim --- mm/slab.c | 12 +++- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/mm/slab.c b/mm/slab.c index a5a205b..ba2eacf 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -888,12 +888,6 @@ static int init_cache_node_node(int node) return 0; } -static inline int slabs_tofree(struct kmem_cache *cachep, - struct kmem_cache_node *n) -{ - return (n->free_objects + cachep->num - 1) / cachep->num; -} - static void cpuup_canceled(long cpu) { struct kmem_cache *cachep; @@ -958,7 +952,7 @@ free_slab: n = get_node(cachep, node); if (!n) continue; - drain_freelist(cachep, n, slabs_tofree(cachep, n)); + drain_freelist(cachep, n, INT_MAX); } } @@ -1110,7 +1104,7 @@ static int __meminit drain_cache_node_node(int node) if (!n) continue; - drain_freelist(cachep, n, slabs_tofree(cachep, n)); + drain_freelist(cachep, n, INT_MAX); if (!list_empty(>slabs_full) || !list_empty(>slabs_partial)) { @@ -2280,7 +2274,7 @@ int __kmem_cache_shrink(struct kmem_cache *cachep, bool deactivate) check_irq_on(); for_each_kmem_cache_node(cachep, node, n) { - drain_freelist(cachep, n, slabs_tofree(cachep, n)); + drain_freelist(cachep, n, INT_MAX); ret += !list_empty(>slabs_full) || !list_empty(>slabs_partial); -- 1.9.1
RE: [PATCH v2 5/6] Documentation: DT: vdma: update binding doc for AXI CDMA
Hi Soren, > -Original Message- > From: Sören Brinkmann [mailto:soren.brinkm...@xilinx.com] > Sent: Monday, March 28, 2016 12:58 AM > To: Appana Durga Kedareswara Rao > Cc: robh...@kernel.org; pawel.m...@arm.com; mark.rutl...@arm.com; > ijc+devicet...@hellion.org.uk; ga...@codeaurora.org; Michal Simek; > vinod.k...@intel.com; dan.j.willi...@intel.com; Anurag Kumar Vulisha; Appana > Durga Kedareswara Rao; moritz.fisc...@ettus.com; > laurent.pinch...@ideasonboard.com; l...@debethencourt.com; Srikanth > Vemula; Anirudha Sarangi; devicet...@vger.kernel.org; linux-arm- > ker...@lists.infradead.org; linux-kernel@vger.kernel.org; > dmaeng...@vger.kernel.org > Subject: Re: [PATCH v2 5/6] Documentation: DT: vdma: update binding doc for > AXI CDMA > > On Sun, 2016-03-27 at 23:36:06 +0530, Kedareswara rao Appana wrote: > > This patch updates the device-tree binding doc for adding support for > > AXI CDMA. > > > > Signed-off-by: Kedareswara rao Appana> > --- > > ---> Modified commit message as suggested by Vinod. > > ---> Moved the patch to forward in the series as suggested by vinod. > > > > .../devicetree/bindings/dma/xilinx/xilinx_vdma.txt | 18 > +- > > 1 file changed, 17 insertions(+), 1 deletion(-) > > > > diff --git > > a/Documentation/devicetree/bindings/dma/xilinx/xilinx_vdma.txt > > b/Documentation/devicetree/bindings/dma/xilinx/xilinx_vdma.txt > > index 5841421..2b0c12b 100644 > > --- a/Documentation/devicetree/bindings/dma/xilinx/xilinx_vdma.txt > > +++ b/Documentation/devicetree/bindings/dma/xilinx/xilinx_vdma.txt > > @@ -8,8 +8,12 @@ target devices. It can be configured to have one channel > or two channels. > > If configured as two channels, one is to transmit to the device and > > another is to receive from the device. > > > > +Xilinx AXI CDMA engine, it does transfers between memory-mapped > > +source address and a memory-mapped destination address. > > + > > Required properties: > > -- compatible: Should be "xlnx,axi-vdma-1.00.a" or "xlnx,axi-dma-1.00.a" > > +- compatible: Should be "xlnx,axi-vdma-1.00.a" or "xlnx,axi-dma-1.00.a" or > > + "xlnx,axi-cdma-1.00.a"" > > - #dma-cells: Should be <1>, see "dmas" property below > > - reg: Should contain VDMA registers location and length. > > - xlnx,num-fstores: Should be the number of framebuffers as configured in > h/w. > > @@ -80,6 +84,18 @@ axi_dma_0: axidma@4040 { > > } ; > > } ; > > > > +axi_cdma_0: axicdma@7e20 { > > + compatible = "xlnx,axi-cdma-1.00.a"; > > + #dma-cells = <1>; > > + reg = < 0x7e20 0x1 >; > > + xlnx,addrwidth = <0x20>; > > + dma-channel@7e20 { > > + compatible = "xlnx,axi-dma-mm2s-channel"; > > + interrupts = < 0 55 4 >; > > + xlnx,datawidth = <0x40>; > > + } ; > > +} ; > > As in the other patch, the node name should be 'dma-controller@...' and the > inconsistend spacing could be fixed. Ok will fix... > > Also, it seems this adds pretty much identical examples that just differ in > the > compat string. Is that really needed? Most of the properties are same across the three DMA's For AXI VDMA there are few required properties that are not required for AXI DMA/CDMA. That's why added example for the other IP's as well I mean for AXI DMA and CDMA. Regards, Kedar. > > Sören
mm/slab: reduce lock contention in alloc path
From: Joonsoo KimWhile processing concurrent allocation, SLAB could be contended a lot because it did a lots of work with holding a lock. This patchset try to reduce the number of critical section to reduce lock contention. Major changes are lockless decision to allocate more slab and lockless cpu cache refill from the newly allocated slab. Below is the result of concurrent allocation/free in slab allocation benchmark made by Christoph a long time ago. I make the output simpler. The number shows cycle count during alloc/free respectively so less is better. * Before Kmalloc N*alloc N*free(32): Average=365/806 Kmalloc N*alloc N*free(64): Average=452/690 Kmalloc N*alloc N*free(128): Average=736/886 Kmalloc N*alloc N*free(256): Average=1167/985 Kmalloc N*alloc N*free(512): Average=2088/1125 Kmalloc N*alloc N*free(1024): Average=4115/1184 Kmalloc N*alloc N*free(2048): Average=8451/1748 Kmalloc N*alloc N*free(4096): Average=16024/2048 * After Kmalloc N*alloc N*free(32): Average=344/792 Kmalloc N*alloc N*free(64): Average=347/882 Kmalloc N*alloc N*free(128): Average=390/959 Kmalloc N*alloc N*free(256): Average=393/1067 Kmalloc N*alloc N*free(512): Average=683/1229 Kmalloc N*alloc N*free(1024): Average=1295/1325 Kmalloc N*alloc N*free(2048): Average=2513/1664 Kmalloc N*alloc N*free(4096): Average=4742/2172 It shows that performance improves greatly (roughly more than 50%) for the object class whose size is more than 128 bytes. Thanks. Joonsoo Kim (11): mm/slab: hold a slab_mutex when calling __kmem_cache_shrink() mm/slab: remove BAD_ALIEN_MAGIC again mm/slab: drain the free slab as much as possible mm/slab: factor out kmem_cache_node initialization code mm/slab: clean-up kmem_cache_node setup mm/slab: don't keep free slabs if free_objects exceeds free_limit mm/slab: racy access/modify the slab color mm/slab: make cache_grow() handle the page allocated on arbitrary node mm/slab: separate cache_grow() to two parts mm/slab: refill cpu cache through a new slab without holding a node lock mm/slab: lockless decision to grow cache mm/slab.c| 495 --- mm/slab_common.c | 4 + 2 files changed, 255 insertions(+), 244 deletions(-) -- 1.9.1
mm/slab: reduce lock contention in alloc path
From: Joonsoo Kim While processing concurrent allocation, SLAB could be contended a lot because it did a lots of work with holding a lock. This patchset try to reduce the number of critical section to reduce lock contention. Major changes are lockless decision to allocate more slab and lockless cpu cache refill from the newly allocated slab. Below is the result of concurrent allocation/free in slab allocation benchmark made by Christoph a long time ago. I make the output simpler. The number shows cycle count during alloc/free respectively so less is better. * Before Kmalloc N*alloc N*free(32): Average=365/806 Kmalloc N*alloc N*free(64): Average=452/690 Kmalloc N*alloc N*free(128): Average=736/886 Kmalloc N*alloc N*free(256): Average=1167/985 Kmalloc N*alloc N*free(512): Average=2088/1125 Kmalloc N*alloc N*free(1024): Average=4115/1184 Kmalloc N*alloc N*free(2048): Average=8451/1748 Kmalloc N*alloc N*free(4096): Average=16024/2048 * After Kmalloc N*alloc N*free(32): Average=344/792 Kmalloc N*alloc N*free(64): Average=347/882 Kmalloc N*alloc N*free(128): Average=390/959 Kmalloc N*alloc N*free(256): Average=393/1067 Kmalloc N*alloc N*free(512): Average=683/1229 Kmalloc N*alloc N*free(1024): Average=1295/1325 Kmalloc N*alloc N*free(2048): Average=2513/1664 Kmalloc N*alloc N*free(4096): Average=4742/2172 It shows that performance improves greatly (roughly more than 50%) for the object class whose size is more than 128 bytes. Thanks. Joonsoo Kim (11): mm/slab: hold a slab_mutex when calling __kmem_cache_shrink() mm/slab: remove BAD_ALIEN_MAGIC again mm/slab: drain the free slab as much as possible mm/slab: factor out kmem_cache_node initialization code mm/slab: clean-up kmem_cache_node setup mm/slab: don't keep free slabs if free_objects exceeds free_limit mm/slab: racy access/modify the slab color mm/slab: make cache_grow() handle the page allocated on arbitrary node mm/slab: separate cache_grow() to two parts mm/slab: refill cpu cache through a new slab without holding a node lock mm/slab: lockless decision to grow cache mm/slab.c| 495 --- mm/slab_common.c | 4 + 2 files changed, 255 insertions(+), 244 deletions(-) -- 1.9.1
RE: [PATCH v2 5/6] Documentation: DT: vdma: update binding doc for AXI CDMA
Hi Soren, > -Original Message- > From: Sören Brinkmann [mailto:soren.brinkm...@xilinx.com] > Sent: Monday, March 28, 2016 12:58 AM > To: Appana Durga Kedareswara Rao > Cc: robh...@kernel.org; pawel.m...@arm.com; mark.rutl...@arm.com; > ijc+devicet...@hellion.org.uk; ga...@codeaurora.org; Michal Simek; > vinod.k...@intel.com; dan.j.willi...@intel.com; Anurag Kumar Vulisha; Appana > Durga Kedareswara Rao; moritz.fisc...@ettus.com; > laurent.pinch...@ideasonboard.com; l...@debethencourt.com; Srikanth > Vemula; Anirudha Sarangi; devicet...@vger.kernel.org; linux-arm- > ker...@lists.infradead.org; linux-kernel@vger.kernel.org; > dmaeng...@vger.kernel.org > Subject: Re: [PATCH v2 5/6] Documentation: DT: vdma: update binding doc for > AXI CDMA > > On Sun, 2016-03-27 at 23:36:06 +0530, Kedareswara rao Appana wrote: > > This patch updates the device-tree binding doc for adding support for > > AXI CDMA. > > > > Signed-off-by: Kedareswara rao Appana > > --- > > ---> Modified commit message as suggested by Vinod. > > ---> Moved the patch to forward in the series as suggested by vinod. > > > > .../devicetree/bindings/dma/xilinx/xilinx_vdma.txt | 18 > +- > > 1 file changed, 17 insertions(+), 1 deletion(-) > > > > diff --git > > a/Documentation/devicetree/bindings/dma/xilinx/xilinx_vdma.txt > > b/Documentation/devicetree/bindings/dma/xilinx/xilinx_vdma.txt > > index 5841421..2b0c12b 100644 > > --- a/Documentation/devicetree/bindings/dma/xilinx/xilinx_vdma.txt > > +++ b/Documentation/devicetree/bindings/dma/xilinx/xilinx_vdma.txt > > @@ -8,8 +8,12 @@ target devices. It can be configured to have one channel > or two channels. > > If configured as two channels, one is to transmit to the device and > > another is to receive from the device. > > > > +Xilinx AXI CDMA engine, it does transfers between memory-mapped > > +source address and a memory-mapped destination address. > > + > > Required properties: > > -- compatible: Should be "xlnx,axi-vdma-1.00.a" or "xlnx,axi-dma-1.00.a" > > +- compatible: Should be "xlnx,axi-vdma-1.00.a" or "xlnx,axi-dma-1.00.a" or > > + "xlnx,axi-cdma-1.00.a"" > > - #dma-cells: Should be <1>, see "dmas" property below > > - reg: Should contain VDMA registers location and length. > > - xlnx,num-fstores: Should be the number of framebuffers as configured in > h/w. > > @@ -80,6 +84,18 @@ axi_dma_0: axidma@4040 { > > } ; > > } ; > > > > +axi_cdma_0: axicdma@7e20 { > > + compatible = "xlnx,axi-cdma-1.00.a"; > > + #dma-cells = <1>; > > + reg = < 0x7e20 0x1 >; > > + xlnx,addrwidth = <0x20>; > > + dma-channel@7e20 { > > + compatible = "xlnx,axi-dma-mm2s-channel"; > > + interrupts = < 0 55 4 >; > > + xlnx,datawidth = <0x40>; > > + } ; > > +} ; > > As in the other patch, the node name should be 'dma-controller@...' and the > inconsistend spacing could be fixed. Ok will fix... > > Also, it seems this adds pretty much identical examples that just differ in > the > compat string. Is that really needed? Most of the properties are same across the three DMA's For AXI VDMA there are few required properties that are not required for AXI DMA/CDMA. That's why added example for the other IP's as well I mean for AXI DMA and CDMA. Regards, Kedar. > > Sören
[PATCH 03/11] mm/slab: drain the free slab as much as possible
From: Joonsoo Kim slabs_tofree() implies freeing all free slab. We can do it with just providing INT_MAX. Signed-off-by: Joonsoo Kim --- mm/slab.c | 12 +++- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/mm/slab.c b/mm/slab.c index a5a205b..ba2eacf 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -888,12 +888,6 @@ static int init_cache_node_node(int node) return 0; } -static inline int slabs_tofree(struct kmem_cache *cachep, - struct kmem_cache_node *n) -{ - return (n->free_objects + cachep->num - 1) / cachep->num; -} - static void cpuup_canceled(long cpu) { struct kmem_cache *cachep; @@ -958,7 +952,7 @@ free_slab: n = get_node(cachep, node); if (!n) continue; - drain_freelist(cachep, n, slabs_tofree(cachep, n)); + drain_freelist(cachep, n, INT_MAX); } } @@ -1110,7 +1104,7 @@ static int __meminit drain_cache_node_node(int node) if (!n) continue; - drain_freelist(cachep, n, slabs_tofree(cachep, n)); + drain_freelist(cachep, n, INT_MAX); if (!list_empty(>slabs_full) || !list_empty(>slabs_partial)) { @@ -2280,7 +2274,7 @@ int __kmem_cache_shrink(struct kmem_cache *cachep, bool deactivate) check_irq_on(); for_each_kmem_cache_node(cachep, node, n) { - drain_freelist(cachep, n, slabs_tofree(cachep, n)); + drain_freelist(cachep, n, INT_MAX); ret += !list_empty(>slabs_full) || !list_empty(>slabs_partial); -- 1.9.1
[PATCH 04/11] mm/slab: factor out kmem_cache_node initialization code
From: Joonsoo KimIt can be reused on other place, so factor out it. Following patch will use it. Signed-off-by: Joonsoo Kim --- mm/slab.c | 68 --- 1 file changed, 39 insertions(+), 29 deletions(-) diff --git a/mm/slab.c b/mm/slab.c index ba2eacf..569d7db 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -841,6 +841,40 @@ static inline gfp_t gfp_exact_node(gfp_t flags) } #endif +static int init_cache_node(struct kmem_cache *cachep, int node, gfp_t gfp) +{ + struct kmem_cache_node *n; + + /* +* Set up the kmem_cache_node for cpu before we can +* begin anything. Make sure some other cpu on this +* node has not already allocated this +*/ + n = get_node(cachep, node); + if (n) + return 0; + + n = kmalloc_node(sizeof(struct kmem_cache_node), gfp, node); + if (!n) + return -ENOMEM; + + kmem_cache_node_init(n); + n->next_reap = jiffies + REAPTIMEOUT_NODE + + ((unsigned long)cachep) % REAPTIMEOUT_NODE; + + n->free_limit = + (1 + nr_cpus_node(node)) * cachep->batchcount + cachep->num; + + /* +* The kmem_cache_nodes don't come and go as CPUs +* come and go. slab_mutex is sufficient +* protection here. +*/ + cachep->node[node] = n; + + return 0; +} + /* * Allocates and initializes node for a node on each slab cache, used for * either memory or cpu hotplug. If memory is being hot-added, the kmem_cache_node @@ -852,39 +886,15 @@ static inline gfp_t gfp_exact_node(gfp_t flags) */ static int init_cache_node_node(int node) { + int ret; struct kmem_cache *cachep; - struct kmem_cache_node *n; - const size_t memsize = sizeof(struct kmem_cache_node); list_for_each_entry(cachep, _caches, list) { - /* -* Set up the kmem_cache_node for cpu before we can -* begin anything. Make sure some other cpu on this -* node has not already allocated this -*/ - n = get_node(cachep, node); - if (!n) { - n = kmalloc_node(memsize, GFP_KERNEL, node); - if (!n) - return -ENOMEM; - kmem_cache_node_init(n); - n->next_reap = jiffies + REAPTIMEOUT_NODE + - ((unsigned long)cachep) % REAPTIMEOUT_NODE; - - /* -* The kmem_cache_nodes don't come and go as CPUs -* come and go. slab_mutex is sufficient -* protection here. -*/ - cachep->node[node] = n; - } - - spin_lock_irq(>list_lock); - n->free_limit = - (1 + nr_cpus_node(node)) * - cachep->batchcount + cachep->num; - spin_unlock_irq(>list_lock); + ret = init_cache_node(cachep, node, GFP_KERNEL); + if (ret) + return ret; } + return 0; } -- 1.9.1
[PATCH 04/11] mm/slab: factor out kmem_cache_node initialization code
From: Joonsoo Kim It can be reused on other place, so factor out it. Following patch will use it. Signed-off-by: Joonsoo Kim --- mm/slab.c | 68 --- 1 file changed, 39 insertions(+), 29 deletions(-) diff --git a/mm/slab.c b/mm/slab.c index ba2eacf..569d7db 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -841,6 +841,40 @@ static inline gfp_t gfp_exact_node(gfp_t flags) } #endif +static int init_cache_node(struct kmem_cache *cachep, int node, gfp_t gfp) +{ + struct kmem_cache_node *n; + + /* +* Set up the kmem_cache_node for cpu before we can +* begin anything. Make sure some other cpu on this +* node has not already allocated this +*/ + n = get_node(cachep, node); + if (n) + return 0; + + n = kmalloc_node(sizeof(struct kmem_cache_node), gfp, node); + if (!n) + return -ENOMEM; + + kmem_cache_node_init(n); + n->next_reap = jiffies + REAPTIMEOUT_NODE + + ((unsigned long)cachep) % REAPTIMEOUT_NODE; + + n->free_limit = + (1 + nr_cpus_node(node)) * cachep->batchcount + cachep->num; + + /* +* The kmem_cache_nodes don't come and go as CPUs +* come and go. slab_mutex is sufficient +* protection here. +*/ + cachep->node[node] = n; + + return 0; +} + /* * Allocates and initializes node for a node on each slab cache, used for * either memory or cpu hotplug. If memory is being hot-added, the kmem_cache_node @@ -852,39 +886,15 @@ static inline gfp_t gfp_exact_node(gfp_t flags) */ static int init_cache_node_node(int node) { + int ret; struct kmem_cache *cachep; - struct kmem_cache_node *n; - const size_t memsize = sizeof(struct kmem_cache_node); list_for_each_entry(cachep, _caches, list) { - /* -* Set up the kmem_cache_node for cpu before we can -* begin anything. Make sure some other cpu on this -* node has not already allocated this -*/ - n = get_node(cachep, node); - if (!n) { - n = kmalloc_node(memsize, GFP_KERNEL, node); - if (!n) - return -ENOMEM; - kmem_cache_node_init(n); - n->next_reap = jiffies + REAPTIMEOUT_NODE + - ((unsigned long)cachep) % REAPTIMEOUT_NODE; - - /* -* The kmem_cache_nodes don't come and go as CPUs -* come and go. slab_mutex is sufficient -* protection here. -*/ - cachep->node[node] = n; - } - - spin_lock_irq(>list_lock); - n->free_limit = - (1 + nr_cpus_node(node)) * - cachep->batchcount + cachep->num; - spin_unlock_irq(>list_lock); + ret = init_cache_node(cachep, node, GFP_KERNEL); + if (ret) + return ret; } + return 0; } -- 1.9.1
Re: [PATCH v2] ARM: exynos_defconfig: Enable Samsung media platform drivers as modules
Hello Krzysztof, On 03/28/2016 12:28 AM, Krzysztof Kozlowski wrote: > On 25.03.2016 12:15, Javier Martinez Canillas wrote: >>> >>> How about doing the same for multi_v7? >>> >> >> I didn't consider multi_v7 because media drivers aren't necessary for booting >> the boards and so it could increase build times for not real benefits in most >> machines. But I can enable it in multi_v7 as a follow-up if you think that it >> makes sense there too. > > I consider use cases of multi_v7 the same as exynos (except the > difference in policy: use always modules). This means that if it makes > sense to enable some media drivers on exynos (for build coverage, boot > testing and real usage) then it makes sense to do the same for multi_v7. > Ok, thanks a lot for your suggestion. I'll post a patch for multi_v7 then. > In ideal future we would move entirely from exynos-specific image to one > common image for testing: the multi_v7. It would make things simpler. > > Best regards, > Krzysztof > Best regards, -- Javier Martinez Canillas Open Source Group Samsung Research America
Re: [PATCH v2] ARM: exynos_defconfig: Enable Samsung media platform drivers as modules
Hello Krzysztof, On 03/28/2016 12:28 AM, Krzysztof Kozlowski wrote: > On 25.03.2016 12:15, Javier Martinez Canillas wrote: >>> >>> How about doing the same for multi_v7? >>> >> >> I didn't consider multi_v7 because media drivers aren't necessary for booting >> the boards and so it could increase build times for not real benefits in most >> machines. But I can enable it in multi_v7 as a follow-up if you think that it >> makes sense there too. > > I consider use cases of multi_v7 the same as exynos (except the > difference in policy: use always modules). This means that if it makes > sense to enable some media drivers on exynos (for build coverage, boot > testing and real usage) then it makes sense to do the same for multi_v7. > Ok, thanks a lot for your suggestion. I'll post a patch for multi_v7 then. > In ideal future we would move entirely from exynos-specific image to one > common image for testing: the multi_v7. It would make things simpler. > > Best regards, > Krzysztof > Best regards, -- Javier Martinez Canillas Open Source Group Samsung Research America
Re: [PATCH v2 00/18] Support non-lru page migration
Hello Andrew, On Mon, Mar 21, 2016 at 03:30:49PM +0900, Minchan Kim wrote: > Recently, I got many reports about perfermance degradation > in embedded system(Android mobile phone, webOS TV and so on) > and failed to fork easily. > > The problem was fragmentation caused by zram and GPU driver > pages. Their pages cannot be migrated so compaction cannot > work well, either so reclaimer ends up shrinking all of working > set pages. It made system very slow and even to fail to fork > easily. > > Other pain point is that they cannot work with CMA. > Most of CMA memory space could be idle(ie, it could be used > for movable pages unless driver is using) but if driver(i.e., > zram) cannot migrate his page, that memory space could be > wasted. In our product which has big CMA memory, it reclaims > zones too exccessively although there are lots of free space > in CMA so system was very slow easily. > > To solve these problem, this patch try to add facility to > migrate non-lru pages via introducing new friend functions > of migratepage in address_space_operation and new page flags. > > (isolate_page, putback_page) > (PG_movable, PG_isolated) > > For details, please read description in > "mm/compaction: support non-lru movable page migration". > > Originally, Gioh Kim tried to support this feature but he moved > so I took over the work. But I took many code from his work and > changed a little bit. > Thanks, Gioh! > > And I should mention Konstantin Khlebnikov. He really heped Gioh > at that time so he should deserve to have many credit, too. > Thanks, Konstantin! > > This patchset consists of five parts > > 1. clean up migration > mm: use put_page to free page instead of putback_lru_page > > 2. zsmalloc clean-up for preparing page migration > zsmalloc: use first_page rather than page > zsmalloc: clean up many BUG_ON > zsmalloc: reordering function parameter > zsmalloc: remove unused pool param in obj_free > zsmalloc: keep max_object in size_class > zsmalloc: squeeze inuse into page->mapping > zsmalloc: squeeze freelist into page->mapping > zsmalloc: move struct zs_meta from mapping to freelist > zsmalloc: factor page chain functionality out > zsmalloc: separate free_zspage from putback_zspage > zsmalloc: zs_compact refactoring In this series, [2-5] are clean up regardless of goal of the patchset so it could be merged independently. I want to reduce patchset size in next post. If anyone are not against, could you merge cleanup patchset? zsmalloc: use first_page rather than page zsmalloc: clean up many BUG_ON zsmalloc: reordering function parameter zsmalloc: remove unused pool param in obj_free Thanks.
Re: [PATCH v2 00/18] Support non-lru page migration
Hello Andrew, On Mon, Mar 21, 2016 at 03:30:49PM +0900, Minchan Kim wrote: > Recently, I got many reports about perfermance degradation > in embedded system(Android mobile phone, webOS TV and so on) > and failed to fork easily. > > The problem was fragmentation caused by zram and GPU driver > pages. Their pages cannot be migrated so compaction cannot > work well, either so reclaimer ends up shrinking all of working > set pages. It made system very slow and even to fail to fork > easily. > > Other pain point is that they cannot work with CMA. > Most of CMA memory space could be idle(ie, it could be used > for movable pages unless driver is using) but if driver(i.e., > zram) cannot migrate his page, that memory space could be > wasted. In our product which has big CMA memory, it reclaims > zones too exccessively although there are lots of free space > in CMA so system was very slow easily. > > To solve these problem, this patch try to add facility to > migrate non-lru pages via introducing new friend functions > of migratepage in address_space_operation and new page flags. > > (isolate_page, putback_page) > (PG_movable, PG_isolated) > > For details, please read description in > "mm/compaction: support non-lru movable page migration". > > Originally, Gioh Kim tried to support this feature but he moved > so I took over the work. But I took many code from his work and > changed a little bit. > Thanks, Gioh! > > And I should mention Konstantin Khlebnikov. He really heped Gioh > at that time so he should deserve to have many credit, too. > Thanks, Konstantin! > > This patchset consists of five parts > > 1. clean up migration > mm: use put_page to free page instead of putback_lru_page > > 2. zsmalloc clean-up for preparing page migration > zsmalloc: use first_page rather than page > zsmalloc: clean up many BUG_ON > zsmalloc: reordering function parameter > zsmalloc: remove unused pool param in obj_free > zsmalloc: keep max_object in size_class > zsmalloc: squeeze inuse into page->mapping > zsmalloc: squeeze freelist into page->mapping > zsmalloc: move struct zs_meta from mapping to freelist > zsmalloc: factor page chain functionality out > zsmalloc: separate free_zspage from putback_zspage > zsmalloc: zs_compact refactoring In this series, [2-5] are clean up regardless of goal of the patchset so it could be merged independently. I want to reduce patchset size in next post. If anyone are not against, could you merge cleanup patchset? zsmalloc: use first_page rather than page zsmalloc: clean up many BUG_ON zsmalloc: reordering function parameter zsmalloc: remove unused pool param in obj_free Thanks.
arm:collie_defconfig broken since commit ff2b135922 ("gpio: make the gpiochip a real device")
Hi, arm:collie_defconfig is broken since commit ff2b135922 ("gpio: make the gpiochip a real device"). Test is quite simple: Build arm:collie_defconfig, run with qemu-system-arm -M collie -kernel arch/arm/boot/zImage --append "console=ttySA1" -monitor null -nographic Prior to the above commit, there is console output (the image crashes because it doesn't have a root file system, but that is irrelevant). After the commit, the console is silent. Let me know if I can do anything to help tracking down the problem. Thanks, Guenter --- Bisect log: # bad: [f55532a0c0b8bb6148f4e07853b876ef73bc69ca] Linux 4.6-rc1 # good: [b562e44f507e863c6792946e4e1b1449fbbac85d] Linux 4.5 git bisect start 'HEAD' 'v4.5' # bad: [6b5f04b6cf8ebab9a65d9c0026c650bb2538fd0f] Merge branch 'for-4.6' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup git bisect bad 6b5f04b6cf8ebab9a65d9c0026c650bb2538fd0f # good: [96b9b1c95660d4bc5510c5d798d3817ae9f0b391] Merge tag 'tty-4.6-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty git bisect good 96b9b1c95660d4bc5510c5d798d3817ae9f0b391 # good: [18f038e6bfb715310526ac05e4f20e55683471de] staging: dgnc: cleanup properly git bisect good 18f038e6bfb715310526ac05e4f20e55683471de # bad: [10fdfee7f7fd8d4a6a8455ac4c9fbbc51d79b9f7] Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input git bisect bad 10fdfee7f7fd8d4a6a8455ac4c9fbbc51d79b9f7 # good: [3d15cfdb1b77536c205d8e49c0312219ddf162ec] Merge tag 'linux-kselftest-4.6-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest git bisect good 3d15cfdb1b77536c205d8e49c0312219ddf162ec # bad: [ccbd805aa934dd1b863ef115a9c55f119b2388cf] Revert "Share upstreaming patches" git bisect bad ccbd805aa934dd1b863ef115a9c55f119b2388cf # bad: [db303a9053c8a81717cb6497f4cf63b773b21ca8] gpio: arizona: Use devm_gpiochip_add_data() for gpio registration git bisect bad db303a9053c8a81717cb6497f4cf63b773b21ca8 # bad: [ed07247dbf5b0a23b0289c9e8e4a2ceb9b8f2e9d] gpio: Remove unused asm/gpio.h files git bisect bad ed07247dbf5b0a23b0289c9e8e4a2ceb9b8f2e9d # bad: [2f890cf0dfe421ecd2095d8cabb89e7207b499ee] gpio: ath79: Make the driver removable git bisect bad 2f890cf0dfe421ecd2095d8cabb89e7207b499ee # good: [daec0beda6fd7a741e4381741b3f7ff15970fdf6] Merge branch 'error-return-from-get' into devel git bisect good daec0beda6fd7a741e4381741b3f7ff15970fdf6 # bad: [40c159b776f882f2e2cbe20c9e29832841e5c0f9] gpio: add a userspace character device ABI git bisect bad 40c159b776f882f2e2cbe20c9e29832841e5c0f9 # bad: [34ffd85d9c46cde3dc987cac82bff370a937ac4b] gpio: refer to gpio device in prints and debugfs git bisect bad 34ffd85d9c46cde3dc987cac82bff370a937ac4b # bad: [ff2b1359229927563addbf2f5ad480660c350903] gpio: make the gpiochip a real device git bisect bad ff2b1359229927563addbf2f5ad480660c350903 # first bad commit: [ff2b1359229927563addbf2f5ad480660c350903] gpio: make the gpiochip a real device
arm:collie_defconfig broken since commit ff2b135922 ("gpio: make the gpiochip a real device")
Hi, arm:collie_defconfig is broken since commit ff2b135922 ("gpio: make the gpiochip a real device"). Test is quite simple: Build arm:collie_defconfig, run with qemu-system-arm -M collie -kernel arch/arm/boot/zImage --append "console=ttySA1" -monitor null -nographic Prior to the above commit, there is console output (the image crashes because it doesn't have a root file system, but that is irrelevant). After the commit, the console is silent. Let me know if I can do anything to help tracking down the problem. Thanks, Guenter --- Bisect log: # bad: [f55532a0c0b8bb6148f4e07853b876ef73bc69ca] Linux 4.6-rc1 # good: [b562e44f507e863c6792946e4e1b1449fbbac85d] Linux 4.5 git bisect start 'HEAD' 'v4.5' # bad: [6b5f04b6cf8ebab9a65d9c0026c650bb2538fd0f] Merge branch 'for-4.6' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup git bisect bad 6b5f04b6cf8ebab9a65d9c0026c650bb2538fd0f # good: [96b9b1c95660d4bc5510c5d798d3817ae9f0b391] Merge tag 'tty-4.6-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty git bisect good 96b9b1c95660d4bc5510c5d798d3817ae9f0b391 # good: [18f038e6bfb715310526ac05e4f20e55683471de] staging: dgnc: cleanup properly git bisect good 18f038e6bfb715310526ac05e4f20e55683471de # bad: [10fdfee7f7fd8d4a6a8455ac4c9fbbc51d79b9f7] Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input git bisect bad 10fdfee7f7fd8d4a6a8455ac4c9fbbc51d79b9f7 # good: [3d15cfdb1b77536c205d8e49c0312219ddf162ec] Merge tag 'linux-kselftest-4.6-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest git bisect good 3d15cfdb1b77536c205d8e49c0312219ddf162ec # bad: [ccbd805aa934dd1b863ef115a9c55f119b2388cf] Revert "Share upstreaming patches" git bisect bad ccbd805aa934dd1b863ef115a9c55f119b2388cf # bad: [db303a9053c8a81717cb6497f4cf63b773b21ca8] gpio: arizona: Use devm_gpiochip_add_data() for gpio registration git bisect bad db303a9053c8a81717cb6497f4cf63b773b21ca8 # bad: [ed07247dbf5b0a23b0289c9e8e4a2ceb9b8f2e9d] gpio: Remove unused asm/gpio.h files git bisect bad ed07247dbf5b0a23b0289c9e8e4a2ceb9b8f2e9d # bad: [2f890cf0dfe421ecd2095d8cabb89e7207b499ee] gpio: ath79: Make the driver removable git bisect bad 2f890cf0dfe421ecd2095d8cabb89e7207b499ee # good: [daec0beda6fd7a741e4381741b3f7ff15970fdf6] Merge branch 'error-return-from-get' into devel git bisect good daec0beda6fd7a741e4381741b3f7ff15970fdf6 # bad: [40c159b776f882f2e2cbe20c9e29832841e5c0f9] gpio: add a userspace character device ABI git bisect bad 40c159b776f882f2e2cbe20c9e29832841e5c0f9 # bad: [34ffd85d9c46cde3dc987cac82bff370a937ac4b] gpio: refer to gpio device in prints and debugfs git bisect bad 34ffd85d9c46cde3dc987cac82bff370a937ac4b # bad: [ff2b1359229927563addbf2f5ad480660c350903] gpio: make the gpiochip a real device git bisect bad ff2b1359229927563addbf2f5ad480660c350903 # first bad commit: [ff2b1359229927563addbf2f5ad480660c350903] gpio: make the gpiochip a real device
[PATCH v2 2/5] phy: Add support for NS2 SATA3 PHY in Broadcom SATA3 PHY driver
This patch adds support for Broadcom NS2 SATA3 PHY in existing Broadcom SATA3 PHY driver. Signed-off-by: Anup Patel--- drivers/phy/phy-brcm-sata.c | 238 +--- 1 file changed, 200 insertions(+), 38 deletions(-) diff --git a/drivers/phy/phy-brcm-sata.c b/drivers/phy/phy-brcm-sata.c index c97b9d6..6c4c5cb 100644 --- a/drivers/phy/phy-brcm-sata.c +++ b/drivers/phy/phy-brcm-sata.c @@ -14,6 +14,7 @@ * GNU General Public License for more details. */ +#include #include #include #include @@ -24,22 +25,26 @@ #include #include -#define SATA_MDIO_BANK_OFFSET 0x23c -#define SATA_MDIO_REG_OFFSET(ofs) ((ofs) * 4) +#define SATA_PCB_BANK_OFFSET 0x23c +#define SATA_PCB_REG_OFFSET(ofs) ((ofs) * 4) #define MAX_PORTS 2 /* Register offset between PHYs in PCB space */ -#define SATA_MDIO_REG_28NM_SPACE_SIZE 0x1000 +#define SATA_PCB_REG_28NM_SPACE_SIZE 0x1000 /* The older SATA PHY registers duplicated per port registers within the map, * rather than having a separate map per port. */ -#define SATA_MDIO_REG_40NM_SPACE_SIZE 0x10 +#define SATA_PCB_REG_40NM_SPACE_SIZE 0x10 + +/* Register offset between PHYs in PHY control space */ +#define SATA_PHY_CTRL_REG_28NM_SPACE_SIZE 0x8 enum brcm_sata_phy_version { - BRCM_SATA_PHY_28NM, - BRCM_SATA_PHY_40NM, + BRCM_SATA_PHY_STB_28NM, + BRCM_SATA_PHY_STB_40NM, + BRCM_SATA_PHY_IPROC_NS2, }; struct brcm_sata_port { @@ -52,15 +57,48 @@ struct brcm_sata_port { struct brcm_sata_phy { struct device *dev; void __iomem *phy_base; + void __iomem *ctrl_base; enum brcm_sata_phy_version version; struct brcm_sata_port phys[MAX_PORTS]; }; -enum sata_mdio_phy_regs { - PLL_REG_BANK_0 = 0x50, +enum sata_phy_regs { + BLOCK0_REG_BANK = 0x000, + BLOCK0_XGXSSTATUS = 0x81, + BLOCK0_XGXSSTATUS_PLL_LOCK = BIT(12), + BLOCK0_SPARE= 0x8d, + BLOCK0_SPARE_OOB_CLK_SEL_MASK = 0x3, + BLOCK0_SPARE_OOB_CLK_SEL_REFBY2 = 0x1, + + PLL_REG_BANK_0 = 0x050, PLL_REG_BANK_0_PLLCONTROL_0 = 0x81, + PLL1_REG_BANK = 0x060, + PLL1_ACTRL2 = 0x82, + PLL1_ACTRL3 = 0x83, + PLL1_ACTRL4 = 0x84, + + OOB_REG_BANK= 0x150, + OOB_CTRL1 = 0x80, + OOB_CTRL1_BURST_MAX_MASK= 0xf, + OOB_CTRL1_BURST_MAX_SHIFT = 12, + OOB_CTRL1_BURST_MIN_MASK= 0xf, + OOB_CTRL1_BURST_MIN_SHIFT = 8, + OOB_CTRL1_WAKE_IDLE_MAX_MASK= 0xf, + OOB_CTRL1_WAKE_IDLE_MAX_SHIFT = 4, + OOB_CTRL1_WAKE_IDLE_MIN_MASK= 0xf, + OOB_CTRL1_WAKE_IDLE_MIN_SHIFT = 0, + OOB_CTRL2 = 0x81, + OOB_CTRL2_SEL_ENA_SHIFT = 15, + OOB_CTRL2_SEL_ENA_RC_SHIFT = 14, + OOB_CTRL2_RESET_IDLE_MAX_MASK = 0x3f, + OOB_CTRL2_RESET_IDLE_MAX_SHIFT = 8, + OOB_CTRL2_BURST_CNT_MASK= 0x3, + OOB_CTRL2_BURST_CNT_SHIFT = 6, + OOB_CTRL2_RESET_IDLE_MIN_MASK = 0x3f, + OOB_CTRL2_RESET_IDLE_MIN_SHIFT = 0, + TXPMD_REG_BANK = 0x1a0, TXPMD_CONTROL1 = 0x81, TXPMD_CONTROL1_TX_SSC_EN_FRC= BIT(0), @@ -72,69 +110,183 @@ enum sata_mdio_phy_regs { TXPMD_TX_FREQ_CTRL_CONTROL3_FMAX_MASK = 0x3ff, }; -static inline void __iomem *brcm_sata_phy_base(struct brcm_sata_port *port) +enum sata_phy_ctrl_regs { + PHY_CTRL_1 = 0x0, + PHY_CTRL_1_RESET= BIT(0), +}; + +static inline void __iomem *brcm_sata_pcb_base(struct brcm_sata_port *port) { struct brcm_sata_phy *priv = port->phy_priv; - u32 offset = 0; + u32 size = 0; + + switch (priv->version) { + case BRCM_SATA_PHY_STB_28NM: + case BRCM_SATA_PHY_IPROC_NS2: + size = SATA_PCB_REG_28NM_SPACE_SIZE; + break; + case BRCM_SATA_PHY_STB_40NM: + size = SATA_PCB_REG_40NM_SPACE_SIZE; + break; + default: + dev_err(priv->dev, "invalid phy version\n"); + break; + }; - if (priv->version == BRCM_SATA_PHY_28NM) - offset = SATA_MDIO_REG_28NM_SPACE_SIZE; - else
[PATCH v2 2/5] phy: Add support for NS2 SATA3 PHY in Broadcom SATA3 PHY driver
This patch adds support for Broadcom NS2 SATA3 PHY in existing Broadcom SATA3 PHY driver. Signed-off-by: Anup Patel --- drivers/phy/phy-brcm-sata.c | 238 +--- 1 file changed, 200 insertions(+), 38 deletions(-) diff --git a/drivers/phy/phy-brcm-sata.c b/drivers/phy/phy-brcm-sata.c index c97b9d6..6c4c5cb 100644 --- a/drivers/phy/phy-brcm-sata.c +++ b/drivers/phy/phy-brcm-sata.c @@ -14,6 +14,7 @@ * GNU General Public License for more details. */ +#include #include #include #include @@ -24,22 +25,26 @@ #include #include -#define SATA_MDIO_BANK_OFFSET 0x23c -#define SATA_MDIO_REG_OFFSET(ofs) ((ofs) * 4) +#define SATA_PCB_BANK_OFFSET 0x23c +#define SATA_PCB_REG_OFFSET(ofs) ((ofs) * 4) #define MAX_PORTS 2 /* Register offset between PHYs in PCB space */ -#define SATA_MDIO_REG_28NM_SPACE_SIZE 0x1000 +#define SATA_PCB_REG_28NM_SPACE_SIZE 0x1000 /* The older SATA PHY registers duplicated per port registers within the map, * rather than having a separate map per port. */ -#define SATA_MDIO_REG_40NM_SPACE_SIZE 0x10 +#define SATA_PCB_REG_40NM_SPACE_SIZE 0x10 + +/* Register offset between PHYs in PHY control space */ +#define SATA_PHY_CTRL_REG_28NM_SPACE_SIZE 0x8 enum brcm_sata_phy_version { - BRCM_SATA_PHY_28NM, - BRCM_SATA_PHY_40NM, + BRCM_SATA_PHY_STB_28NM, + BRCM_SATA_PHY_STB_40NM, + BRCM_SATA_PHY_IPROC_NS2, }; struct brcm_sata_port { @@ -52,15 +57,48 @@ struct brcm_sata_port { struct brcm_sata_phy { struct device *dev; void __iomem *phy_base; + void __iomem *ctrl_base; enum brcm_sata_phy_version version; struct brcm_sata_port phys[MAX_PORTS]; }; -enum sata_mdio_phy_regs { - PLL_REG_BANK_0 = 0x50, +enum sata_phy_regs { + BLOCK0_REG_BANK = 0x000, + BLOCK0_XGXSSTATUS = 0x81, + BLOCK0_XGXSSTATUS_PLL_LOCK = BIT(12), + BLOCK0_SPARE= 0x8d, + BLOCK0_SPARE_OOB_CLK_SEL_MASK = 0x3, + BLOCK0_SPARE_OOB_CLK_SEL_REFBY2 = 0x1, + + PLL_REG_BANK_0 = 0x050, PLL_REG_BANK_0_PLLCONTROL_0 = 0x81, + PLL1_REG_BANK = 0x060, + PLL1_ACTRL2 = 0x82, + PLL1_ACTRL3 = 0x83, + PLL1_ACTRL4 = 0x84, + + OOB_REG_BANK= 0x150, + OOB_CTRL1 = 0x80, + OOB_CTRL1_BURST_MAX_MASK= 0xf, + OOB_CTRL1_BURST_MAX_SHIFT = 12, + OOB_CTRL1_BURST_MIN_MASK= 0xf, + OOB_CTRL1_BURST_MIN_SHIFT = 8, + OOB_CTRL1_WAKE_IDLE_MAX_MASK= 0xf, + OOB_CTRL1_WAKE_IDLE_MAX_SHIFT = 4, + OOB_CTRL1_WAKE_IDLE_MIN_MASK= 0xf, + OOB_CTRL1_WAKE_IDLE_MIN_SHIFT = 0, + OOB_CTRL2 = 0x81, + OOB_CTRL2_SEL_ENA_SHIFT = 15, + OOB_CTRL2_SEL_ENA_RC_SHIFT = 14, + OOB_CTRL2_RESET_IDLE_MAX_MASK = 0x3f, + OOB_CTRL2_RESET_IDLE_MAX_SHIFT = 8, + OOB_CTRL2_BURST_CNT_MASK= 0x3, + OOB_CTRL2_BURST_CNT_SHIFT = 6, + OOB_CTRL2_RESET_IDLE_MIN_MASK = 0x3f, + OOB_CTRL2_RESET_IDLE_MIN_SHIFT = 0, + TXPMD_REG_BANK = 0x1a0, TXPMD_CONTROL1 = 0x81, TXPMD_CONTROL1_TX_SSC_EN_FRC= BIT(0), @@ -72,69 +110,183 @@ enum sata_mdio_phy_regs { TXPMD_TX_FREQ_CTRL_CONTROL3_FMAX_MASK = 0x3ff, }; -static inline void __iomem *brcm_sata_phy_base(struct brcm_sata_port *port) +enum sata_phy_ctrl_regs { + PHY_CTRL_1 = 0x0, + PHY_CTRL_1_RESET= BIT(0), +}; + +static inline void __iomem *brcm_sata_pcb_base(struct brcm_sata_port *port) { struct brcm_sata_phy *priv = port->phy_priv; - u32 offset = 0; + u32 size = 0; + + switch (priv->version) { + case BRCM_SATA_PHY_STB_28NM: + case BRCM_SATA_PHY_IPROC_NS2: + size = SATA_PCB_REG_28NM_SPACE_SIZE; + break; + case BRCM_SATA_PHY_STB_40NM: + size = SATA_PCB_REG_40NM_SPACE_SIZE; + break; + default: + dev_err(priv->dev, "invalid phy version\n"); + break; + }; - if (priv->version == BRCM_SATA_PHY_28NM) - offset = SATA_MDIO_REG_28NM_SPACE_SIZE; - else if (priv->version ==
[PATCH v2 1/5] phy: Rename phy-brcmstb-sata driver to phy-brcm-sata driver
Currently, we have a common SATA3 PHY driver for all Broadcom STB SoCs. This driver can be extended and re-used for Broadcom iProc SoCs having same SATA3 PHY. This patch renames existing Broadcom STB SATA3 PHY driver to common Broadcom SATA3 PHY driver to share this PHY driver across Broadcom SoCs. Signed-off-by: Anup Patel--- drivers/phy/Kconfig | 18 +- drivers/phy/Makefile| 2 +- drivers/phy/{phy-brcmstb-sata.c => phy-brcm-sata.c} | 8 3 files changed, 14 insertions(+), 14 deletions(-) rename drivers/phy/{phy-brcmstb-sata.c => phy-brcm-sata.c} (97%) diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig index 26566db..c0187a7 100644 --- a/drivers/phy/Kconfig +++ b/drivers/phy/Kconfig @@ -403,15 +403,6 @@ config PHY_TUSB1210 help Support for TI TUSB1210 USB ULPI PHY. -config PHY_BRCMSTB_SATA - tristate "Broadcom STB SATA PHY driver" - depends on ARCH_BRCMSTB || BMIPS_GENERIC - depends on OF - select GENERIC_PHY - help - Enable this to support the SATA3 PHY on 28nm or 40nm Broadcom STB SoCs. - Likely useful only with CONFIG_SATA_BRCMSTB enabled. - config PHY_CYGNUS_PCIE tristate "Broadcom Cygnus PCIe PHY driver" depends on OF && (ARCH_BCM_CYGNUS || COMPILE_TEST) @@ -421,4 +412,13 @@ config PHY_CYGNUS_PCIE Enable this to support the Broadcom Cygnus PCIe PHY. If unsure, say N. +config PHY_BRCM_SATA + tristate "Broadcom SATA PHY driver" + depends on ARCH_BRCMSTB || ARCH_BCM_IPROC || BMIPS_GENERIC || COMPILE_TEST + depends on OF + select GENERIC_PHY + default ARCH_BCM_IPROC + help + Enable this to support the Broadcom SATA PHY. + If unsure, say N. endmenu diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile index 24596a9..596fae9 100644 --- a/drivers/phy/Makefile +++ b/drivers/phy/Makefile @@ -49,6 +49,6 @@ obj-$(CONFIG_PHY_QCOM_UFS)+= phy-qcom-ufs.o obj-$(CONFIG_PHY_QCOM_UFS) += phy-qcom-ufs-qmp-20nm.o obj-$(CONFIG_PHY_QCOM_UFS) += phy-qcom-ufs-qmp-14nm.o obj-$(CONFIG_PHY_TUSB1210) += phy-tusb1210.o -obj-$(CONFIG_PHY_BRCMSTB_SATA) += phy-brcmstb-sata.o obj-$(CONFIG_PHY_PISTACHIO_USB)+= phy-pistachio-usb.o obj-$(CONFIG_PHY_CYGNUS_PCIE) += phy-bcm-cygnus-pcie.o +obj-$(CONFIG_PHY_BRCM_SATA)+= phy-brcm-sata.o diff --git a/drivers/phy/phy-brcmstb-sata.c b/drivers/phy/phy-brcm-sata.c similarity index 97% rename from drivers/phy/phy-brcmstb-sata.c rename to drivers/phy/phy-brcm-sata.c index a23172f..c97b9d6 100644 --- a/drivers/phy/phy-brcmstb-sata.c +++ b/drivers/phy/phy-brcm-sata.c @@ -1,7 +1,7 @@ /* * Broadcom SATA3 AHCI Controller PHY Driver * - * Copyright © 2009-2015 Broadcom Corporation + * Copyright (C) 2016 Broadcom * * 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 @@ -238,13 +238,13 @@ static struct platform_driver brcm_sata_phy_driver = { .probe = brcm_sata_phy_probe, .driver = { .of_match_table = brcm_sata_phy_of_match, - .name = "brcmstb-sata-phy", + .name = "brcm-sata-phy", } }; module_platform_driver(brcm_sata_phy_driver); -MODULE_DESCRIPTION("Broadcom STB SATA PHY driver"); +MODULE_DESCRIPTION("Broadcom SATA PHY driver"); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Marc Carino"); MODULE_AUTHOR("Brian Norris"); -MODULE_ALIAS("platform:phy-brcmstb-sata"); +MODULE_ALIAS("platform:phy-brcm-sata"); -- 1.9.1
[PATCH v2 3/5] dt-bindings: phy: bindings document for common Broadcom SATA3 PHY driver
This patch: 1. Renames DT bindings document of Broadcom STB SATA3 PHY driver to common Broadcom SATA3 PHY driver bindings document 2. Adds bindings info for NS2 SATA3 PHY Signed-off-by: Anup PatelAcked-by: Rob Herring --- .../phy/{brcm,brcmstb-sata-phy.txt => brcm-sata-phy.txt} | 15 +-- 1 file changed, 9 insertions(+), 6 deletions(-) rename Documentation/devicetree/bindings/phy/{brcm,brcmstb-sata-phy.txt => brcm-sata-phy.txt} (69%) diff --git a/Documentation/devicetree/bindings/phy/brcm,brcmstb-sata-phy.txt b/Documentation/devicetree/bindings/phy/brcm-sata-phy.txt similarity index 69% rename from Documentation/devicetree/bindings/phy/brcm,brcmstb-sata-phy.txt rename to Documentation/devicetree/bindings/phy/brcm-sata-phy.txt index d87ab7c..d023120 100644 --- a/Documentation/devicetree/bindings/phy/brcm,brcmstb-sata-phy.txt +++ b/Documentation/devicetree/bindings/phy/brcm-sata-phy.txt @@ -1,14 +1,17 @@ -* Broadcom SATA3 PHY for STB +* Broadcom SATA3 PHY Required properties: - compatible: should be one or more of "brcm,bcm7425-sata-phy" "brcm,bcm7445-sata-phy" + "brcm,iproc-ns2-sata-phy" "brcm,phy-sata3" - address-cells: should be 1 - size-cells: should be 0 -- reg: register range for the PHY PCB interface -- reg-names: should be "phy" +- reg: register ranges for the PHY PCB interface +- reg-names: should be "phy" and "phy-ctrl" + The "phy-ctrl" registers are only required for + "brcm,iproc-ns2-sata-phy". Sub-nodes: Each port's PHY should be represented as a sub-node. @@ -16,12 +19,12 @@ Sub-nodes: Sub-nodes required properties: - reg: the PHY number - phy-cells: generic PHY binding; must be 0 -Optional: -- brcm,enable-ssc: use spread spectrum clocking (SSC) on this port +Sub-nodes optional properties: +- brcm,enable-ssc: use spread spectrum clocking (SSC) on this port + This property is not applicable for "brcm,iproc-ns2-sata-phy". Example: - sata-phy@f0458100 { compatible = "brcm,bcm7445-sata-phy", "brcm,phy-sata3"; reg = <0xf0458100 0x1e00>, <0xf045804c 0x10>; -- 1.9.1
[PATCH v2 4/5] dt-bindings: ata: add compatible string for iProc AHCI controller
The Broadcom iProc SoCs have AHCI compliant SATA controller. This patch adds common compatible string for AHCI SATA controller on iProc SoCs. Signed-off-by: Anup PatelAcked-by: Rob Herring --- Documentation/devicetree/bindings/ata/ahci-platform.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/ata/ahci-platform.txt b/Documentation/devicetree/bindings/ata/ahci-platform.txt index 30df832..3990348 100644 --- a/Documentation/devicetree/bindings/ata/ahci-platform.txt +++ b/Documentation/devicetree/bindings/ata/ahci-platform.txt @@ -10,6 +10,7 @@ PHYs. Required properties: - compatible: compatible string, one of: - "allwinner,sun4i-a10-ahci" + - "brcm,iproc-ahci" - "hisilicon,hisi-ahci" - "cavium,octeon-7130-ahci" - "ibm,476gtr-ahci" -- 1.9.1
[PATCH v2 5/5] arm64: dts: Add SATA3 AHCI and SATA3 PHY DT nodes for NS2
We have one dual-port SATA3 AHCI controller present in NS2 SoC. This patch enables SATA3 AHCI controller and SATA3 PHY for NS2 SoC in NS2 DT. Signed-off-by: Anup PatelReviewed-by: Ray Jui Reviewed-by: Scott Branden --- arch/arm64/boot/dts/broadcom/ns2-svk.dts | 12 + arch/arm64/boot/dts/broadcom/ns2.dtsi| 43 2 files changed, 55 insertions(+) diff --git a/arch/arm64/boot/dts/broadcom/ns2-svk.dts b/arch/arm64/boot/dts/broadcom/ns2-svk.dts index ce0ab84..06cf9c5 100644 --- a/arch/arm64/boot/dts/broadcom/ns2-svk.dts +++ b/arch/arm64/boot/dts/broadcom/ns2-svk.dts @@ -72,6 +72,18 @@ status = "ok"; }; +_phy0 { + status = "ok"; +}; + +_phy1 { + status = "ok"; +}; + + { + status = "ok"; +}; + { status = "ok"; }; diff --git a/arch/arm64/boot/dts/broadcom/ns2.dtsi b/arch/arm64/boot/dts/broadcom/ns2.dtsi index 6f81c9d..c8dccf8 100644 --- a/arch/arm64/boot/dts/broadcom/ns2.dtsi +++ b/arch/arm64/boot/dts/broadcom/ns2.dtsi @@ -413,6 +413,49 @@ reg = <0x6622 0x28>; }; + sata_phy: sata_phy@663f0100 { + compatible = "brcm,iproc-ns2-sata-phy"; + reg = <0x663f0100 0x1f00>, + <0x663f004c 0x10>; + reg-names = "phy", "phy-ctrl"; + #address-cells = <1>; + #size-cells = <0>; + + sata_phy0: sata-phy@0 { + reg = <0>; + #phy-cells = <0>; + status = "disabled"; + }; + + sata_phy1: sata-phy@1 { + reg = <1>; + #phy-cells = <0>; + status = "disabled"; + }; + }; + + sata: ahci@663f2000 { + compatible = "brcm,iproc-ahci", "generic-ahci"; + reg = <0x663f2000 0x1000>; + reg-names = "ahci"; + interrupts = ; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + + sata0: sata-port@0 { + reg = <0>; + phys = <_phy0>; + phy-names = "sata-phy"; + }; + + sata1: sata-port@1 { + reg = <1>; + phys = <_phy1>; + phy-names = "sata-phy"; + }; + }; + sdio0: sdhci@6642 { compatible = "brcm,sdhci-iproc-cygnus"; reg = <0x6642 0x100>; -- 1.9.1
[PATCH v2 4/5] dt-bindings: ata: add compatible string for iProc AHCI controller
The Broadcom iProc SoCs have AHCI compliant SATA controller. This patch adds common compatible string for AHCI SATA controller on iProc SoCs. Signed-off-by: Anup Patel Acked-by: Rob Herring --- Documentation/devicetree/bindings/ata/ahci-platform.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/ata/ahci-platform.txt b/Documentation/devicetree/bindings/ata/ahci-platform.txt index 30df832..3990348 100644 --- a/Documentation/devicetree/bindings/ata/ahci-platform.txt +++ b/Documentation/devicetree/bindings/ata/ahci-platform.txt @@ -10,6 +10,7 @@ PHYs. Required properties: - compatible: compatible string, one of: - "allwinner,sun4i-a10-ahci" + - "brcm,iproc-ahci" - "hisilicon,hisi-ahci" - "cavium,octeon-7130-ahci" - "ibm,476gtr-ahci" -- 1.9.1
[PATCH v2 5/5] arm64: dts: Add SATA3 AHCI and SATA3 PHY DT nodes for NS2
We have one dual-port SATA3 AHCI controller present in NS2 SoC. This patch enables SATA3 AHCI controller and SATA3 PHY for NS2 SoC in NS2 DT. Signed-off-by: Anup Patel Reviewed-by: Ray Jui Reviewed-by: Scott Branden --- arch/arm64/boot/dts/broadcom/ns2-svk.dts | 12 + arch/arm64/boot/dts/broadcom/ns2.dtsi| 43 2 files changed, 55 insertions(+) diff --git a/arch/arm64/boot/dts/broadcom/ns2-svk.dts b/arch/arm64/boot/dts/broadcom/ns2-svk.dts index ce0ab84..06cf9c5 100644 --- a/arch/arm64/boot/dts/broadcom/ns2-svk.dts +++ b/arch/arm64/boot/dts/broadcom/ns2-svk.dts @@ -72,6 +72,18 @@ status = "ok"; }; +_phy0 { + status = "ok"; +}; + +_phy1 { + status = "ok"; +}; + + { + status = "ok"; +}; + { status = "ok"; }; diff --git a/arch/arm64/boot/dts/broadcom/ns2.dtsi b/arch/arm64/boot/dts/broadcom/ns2.dtsi index 6f81c9d..c8dccf8 100644 --- a/arch/arm64/boot/dts/broadcom/ns2.dtsi +++ b/arch/arm64/boot/dts/broadcom/ns2.dtsi @@ -413,6 +413,49 @@ reg = <0x6622 0x28>; }; + sata_phy: sata_phy@663f0100 { + compatible = "brcm,iproc-ns2-sata-phy"; + reg = <0x663f0100 0x1f00>, + <0x663f004c 0x10>; + reg-names = "phy", "phy-ctrl"; + #address-cells = <1>; + #size-cells = <0>; + + sata_phy0: sata-phy@0 { + reg = <0>; + #phy-cells = <0>; + status = "disabled"; + }; + + sata_phy1: sata-phy@1 { + reg = <1>; + #phy-cells = <0>; + status = "disabled"; + }; + }; + + sata: ahci@663f2000 { + compatible = "brcm,iproc-ahci", "generic-ahci"; + reg = <0x663f2000 0x1000>; + reg-names = "ahci"; + interrupts = ; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + + sata0: sata-port@0 { + reg = <0>; + phys = <_phy0>; + phy-names = "sata-phy"; + }; + + sata1: sata-port@1 { + reg = <1>; + phys = <_phy1>; + phy-names = "sata-phy"; + }; + }; + sdio0: sdhci@6642 { compatible = "brcm,sdhci-iproc-cygnus"; reg = <0x6642 0x100>; -- 1.9.1
[PATCH v2 1/5] phy: Rename phy-brcmstb-sata driver to phy-brcm-sata driver
Currently, we have a common SATA3 PHY driver for all Broadcom STB SoCs. This driver can be extended and re-used for Broadcom iProc SoCs having same SATA3 PHY. This patch renames existing Broadcom STB SATA3 PHY driver to common Broadcom SATA3 PHY driver to share this PHY driver across Broadcom SoCs. Signed-off-by: Anup Patel --- drivers/phy/Kconfig | 18 +- drivers/phy/Makefile| 2 +- drivers/phy/{phy-brcmstb-sata.c => phy-brcm-sata.c} | 8 3 files changed, 14 insertions(+), 14 deletions(-) rename drivers/phy/{phy-brcmstb-sata.c => phy-brcm-sata.c} (97%) diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig index 26566db..c0187a7 100644 --- a/drivers/phy/Kconfig +++ b/drivers/phy/Kconfig @@ -403,15 +403,6 @@ config PHY_TUSB1210 help Support for TI TUSB1210 USB ULPI PHY. -config PHY_BRCMSTB_SATA - tristate "Broadcom STB SATA PHY driver" - depends on ARCH_BRCMSTB || BMIPS_GENERIC - depends on OF - select GENERIC_PHY - help - Enable this to support the SATA3 PHY on 28nm or 40nm Broadcom STB SoCs. - Likely useful only with CONFIG_SATA_BRCMSTB enabled. - config PHY_CYGNUS_PCIE tristate "Broadcom Cygnus PCIe PHY driver" depends on OF && (ARCH_BCM_CYGNUS || COMPILE_TEST) @@ -421,4 +412,13 @@ config PHY_CYGNUS_PCIE Enable this to support the Broadcom Cygnus PCIe PHY. If unsure, say N. +config PHY_BRCM_SATA + tristate "Broadcom SATA PHY driver" + depends on ARCH_BRCMSTB || ARCH_BCM_IPROC || BMIPS_GENERIC || COMPILE_TEST + depends on OF + select GENERIC_PHY + default ARCH_BCM_IPROC + help + Enable this to support the Broadcom SATA PHY. + If unsure, say N. endmenu diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile index 24596a9..596fae9 100644 --- a/drivers/phy/Makefile +++ b/drivers/phy/Makefile @@ -49,6 +49,6 @@ obj-$(CONFIG_PHY_QCOM_UFS)+= phy-qcom-ufs.o obj-$(CONFIG_PHY_QCOM_UFS) += phy-qcom-ufs-qmp-20nm.o obj-$(CONFIG_PHY_QCOM_UFS) += phy-qcom-ufs-qmp-14nm.o obj-$(CONFIG_PHY_TUSB1210) += phy-tusb1210.o -obj-$(CONFIG_PHY_BRCMSTB_SATA) += phy-brcmstb-sata.o obj-$(CONFIG_PHY_PISTACHIO_USB)+= phy-pistachio-usb.o obj-$(CONFIG_PHY_CYGNUS_PCIE) += phy-bcm-cygnus-pcie.o +obj-$(CONFIG_PHY_BRCM_SATA)+= phy-brcm-sata.o diff --git a/drivers/phy/phy-brcmstb-sata.c b/drivers/phy/phy-brcm-sata.c similarity index 97% rename from drivers/phy/phy-brcmstb-sata.c rename to drivers/phy/phy-brcm-sata.c index a23172f..c97b9d6 100644 --- a/drivers/phy/phy-brcmstb-sata.c +++ b/drivers/phy/phy-brcm-sata.c @@ -1,7 +1,7 @@ /* * Broadcom SATA3 AHCI Controller PHY Driver * - * Copyright © 2009-2015 Broadcom Corporation + * Copyright (C) 2016 Broadcom * * 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 @@ -238,13 +238,13 @@ static struct platform_driver brcm_sata_phy_driver = { .probe = brcm_sata_phy_probe, .driver = { .of_match_table = brcm_sata_phy_of_match, - .name = "brcmstb-sata-phy", + .name = "brcm-sata-phy", } }; module_platform_driver(brcm_sata_phy_driver); -MODULE_DESCRIPTION("Broadcom STB SATA PHY driver"); +MODULE_DESCRIPTION("Broadcom SATA PHY driver"); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Marc Carino"); MODULE_AUTHOR("Brian Norris"); -MODULE_ALIAS("platform:phy-brcmstb-sata"); +MODULE_ALIAS("platform:phy-brcm-sata"); -- 1.9.1
[PATCH v2 3/5] dt-bindings: phy: bindings document for common Broadcom SATA3 PHY driver
This patch: 1. Renames DT bindings document of Broadcom STB SATA3 PHY driver to common Broadcom SATA3 PHY driver bindings document 2. Adds bindings info for NS2 SATA3 PHY Signed-off-by: Anup Patel Acked-by: Rob Herring --- .../phy/{brcm,brcmstb-sata-phy.txt => brcm-sata-phy.txt} | 15 +-- 1 file changed, 9 insertions(+), 6 deletions(-) rename Documentation/devicetree/bindings/phy/{brcm,brcmstb-sata-phy.txt => brcm-sata-phy.txt} (69%) diff --git a/Documentation/devicetree/bindings/phy/brcm,brcmstb-sata-phy.txt b/Documentation/devicetree/bindings/phy/brcm-sata-phy.txt similarity index 69% rename from Documentation/devicetree/bindings/phy/brcm,brcmstb-sata-phy.txt rename to Documentation/devicetree/bindings/phy/brcm-sata-phy.txt index d87ab7c..d023120 100644 --- a/Documentation/devicetree/bindings/phy/brcm,brcmstb-sata-phy.txt +++ b/Documentation/devicetree/bindings/phy/brcm-sata-phy.txt @@ -1,14 +1,17 @@ -* Broadcom SATA3 PHY for STB +* Broadcom SATA3 PHY Required properties: - compatible: should be one or more of "brcm,bcm7425-sata-phy" "brcm,bcm7445-sata-phy" + "brcm,iproc-ns2-sata-phy" "brcm,phy-sata3" - address-cells: should be 1 - size-cells: should be 0 -- reg: register range for the PHY PCB interface -- reg-names: should be "phy" +- reg: register ranges for the PHY PCB interface +- reg-names: should be "phy" and "phy-ctrl" + The "phy-ctrl" registers are only required for + "brcm,iproc-ns2-sata-phy". Sub-nodes: Each port's PHY should be represented as a sub-node. @@ -16,12 +19,12 @@ Sub-nodes: Sub-nodes required properties: - reg: the PHY number - phy-cells: generic PHY binding; must be 0 -Optional: -- brcm,enable-ssc: use spread spectrum clocking (SSC) on this port +Sub-nodes optional properties: +- brcm,enable-ssc: use spread spectrum clocking (SSC) on this port + This property is not applicable for "brcm,iproc-ns2-sata-phy". Example: - sata-phy@f0458100 { compatible = "brcm,bcm7445-sata-phy", "brcm,phy-sata3"; reg = <0xf0458100 0x1e00>, <0xf045804c 0x10>; -- 1.9.1
[PATCH v2 0/5] Add SATA3 support for Broadcom NS2 SVK
The Broadcom NS2 SoC has a AHCI compliant SATA3 controller with two ports. This patchset adds common Broadcom SATA3 PHY driver and related DT bindings document. It also adds appropriate DT nodes in NS2 DT. The patchset is based on v4.6-rc1 tag and is available in branch ns2_sata3_v2 of https://github.com/Broadcom/arm64-linux.git All patches have been tested on Broadcom NS2 SVK. Changes since v1: - Added ACKed by Rob for DT bindings related patches Anup Patel (5): phy: Rename phy-brcmstb-sata driver to phy-brcm-sata driver phy: Add support for NS2 SATA3 PHY in Broadcom SATA3 PHY driver dt-bindings: phy: bindings document for common Broadcom SATA3 PHY driver dt-bindings: ata: add compatible string for iProc AHCI controller arm64: dts: Add SATA3 AHCI and SATA3 PHY DT nodes for NS2 .../devicetree/bindings/ata/ahci-platform.txt | 1 + ...brcm,brcmstb-sata-phy.txt => brcm-sata-phy.txt} | 15 +- arch/arm64/boot/dts/broadcom/ns2-svk.dts | 12 + arch/arm64/boot/dts/broadcom/ns2.dtsi | 43 +++ drivers/phy/Kconfig| 18 +- drivers/phy/Makefile | 2 +- drivers/phy/phy-brcm-sata.c| 412 + drivers/phy/phy-brcmstb-sata.c | 250 - 8 files changed, 487 insertions(+), 266 deletions(-) rename Documentation/devicetree/bindings/phy/{brcm,brcmstb-sata-phy.txt => brcm-sata-phy.txt} (69%) create mode 100644 drivers/phy/phy-brcm-sata.c delete mode 100644 drivers/phy/phy-brcmstb-sata.c -- 1.9.1
[PATCH v2 0/5] Add SATA3 support for Broadcom NS2 SVK
The Broadcom NS2 SoC has a AHCI compliant SATA3 controller with two ports. This patchset adds common Broadcom SATA3 PHY driver and related DT bindings document. It also adds appropriate DT nodes in NS2 DT. The patchset is based on v4.6-rc1 tag and is available in branch ns2_sata3_v2 of https://github.com/Broadcom/arm64-linux.git All patches have been tested on Broadcom NS2 SVK. Changes since v1: - Added ACKed by Rob for DT bindings related patches Anup Patel (5): phy: Rename phy-brcmstb-sata driver to phy-brcm-sata driver phy: Add support for NS2 SATA3 PHY in Broadcom SATA3 PHY driver dt-bindings: phy: bindings document for common Broadcom SATA3 PHY driver dt-bindings: ata: add compatible string for iProc AHCI controller arm64: dts: Add SATA3 AHCI and SATA3 PHY DT nodes for NS2 .../devicetree/bindings/ata/ahci-platform.txt | 1 + ...brcm,brcmstb-sata-phy.txt => brcm-sata-phy.txt} | 15 +- arch/arm64/boot/dts/broadcom/ns2-svk.dts | 12 + arch/arm64/boot/dts/broadcom/ns2.dtsi | 43 +++ drivers/phy/Kconfig| 18 +- drivers/phy/Makefile | 2 +- drivers/phy/phy-brcm-sata.c| 412 + drivers/phy/phy-brcmstb-sata.c | 250 - 8 files changed, 487 insertions(+), 266 deletions(-) rename Documentation/devicetree/bindings/phy/{brcm,brcmstb-sata-phy.txt => brcm-sata-phy.txt} (69%) create mode 100644 drivers/phy/phy-brcm-sata.c delete mode 100644 drivers/phy/phy-brcmstb-sata.c -- 1.9.1
Re: [PATCH] zram: revive swap_slot_free_notify
On Wed, Mar 23, 2016 at 01:45:34PM +0900, Joonsoo Kim wrote: > On Tue, Mar 22, 2016 at 11:06:29PM +0900, Minchan Kim wrote: > > On Tue, Mar 22, 2016 at 05:20:08PM +0900, Joonsoo Kim wrote: > > > 2016-03-22 17:00 GMT+09:00 Minchan Kim: > > > > On Tue, Mar 22, 2016 at 02:08:59PM +0900, Joonsoo Kim wrote: > > > >> On Fri, Mar 18, 2016 at 04:58:31PM +0900, Minchan Kim wrote: > > > >> > "remove compressed copy from zram in-memory" > > > >> > applied swap_slot_free_notify call in *end_swap_bio_read* to > > > >> > remove duplicated memory between zram and memory. > > > >> > > > > >> > However, with introducing rw_page in zram <8c7f01025f7b> > > > >> > "zram: implement rw_page operation of zram", it became void > > > >> > because rw_page doesn't need bio. > > > >> > > > > >> > This patch restores the function for rw_page. > > > >> > > > > >> > Signed-off-by: Minchan Kim > > > >> > --- > > > >> > mm/page_io.c | 93 > > > >> > > > > >> > 1 file changed, 50 insertions(+), 43 deletions(-) > > > >> > > > > >> > diff --git a/mm/page_io.c b/mm/page_io.c > > > >> > index ff74e512f029..18aac7819cc9 100644 > > > >> > --- a/mm/page_io.c > > > >> > +++ b/mm/page_io.c > > > >> > @@ -66,6 +66,54 @@ void end_swap_bio_write(struct bio *bio) > > > >> > bio_put(bio); > > > >> > } > > > >> > > > > >> > +static void swap_slot_free_notify(struct page *page) > > > >> > +{ > > > >> > + struct swap_info_struct *sis; > > > >> > + struct gendisk *disk; > > > >> > + > > > >> > + /* > > > >> > +* There is no guarantee that the page is in swap cache - the > > > >> > software > > > >> > +* suspend code (at least) uses end_swap_bio_read() against a > > > >> > non- > > > >> > +* swapcache page. So we must check PG_swapcache before > > > >> > proceeding with > > > >> > +* this optimization. > > > >> > +*/ > > > >> > + if (unlikely(!PageSwapCache(page))) > > > >> > + return; > > > >> > + > > > >> > + sis = page_swap_info(page); > > > >> > + if (!(sis->flags & SWP_BLKDEV)) > > > >> > + return; > > > >> > + > > > >> > + /* > > > >> > +* The swap subsystem performs lazy swap slot freeing, > > > >> > +* expecting that the page will be swapped out again. > > > >> > +* So we can avoid an unnecessary write if the page > > > >> > +* isn't redirtied. > > > >> > +* This is good for real swap storage because we can > > > >> > +* reduce unnecessary I/O and enhance wear-leveling > > > >> > +* if an SSD is used as the as swap device. > > > >> > +* But if in-memory swap device (eg zram) is used, > > > >> > +* this causes a duplicated copy between uncompressed > > > >> > +* data in VM-owned memory and compressed data in > > > >> > +* zram-owned memory. So let's free zram-owned memory > > > >> > +* and make the VM-owned decompressed page *dirty*, > > > >> > +* so the page should be swapped out somewhere again if > > > >> > +* we again wish to reclaim it. > > > >> > +*/ > > > >> > + disk = sis->bdev->bd_disk; > > > >> > + if (disk->fops->swap_slot_free_notify) { > > > >> > + swp_entry_t entry; > > > >> > + unsigned long offset; > > > >> > + > > > >> > + entry.val = page_private(page); > > > >> > + offset = swp_offset(entry); > > > >> > + > > > >> > + SetPageDirty(page); > > > >> > + disk->fops->swap_slot_free_notify(sis->bdev, > > > >> > + offset); > > > >> > + } > > > >> > +} > > > >> > + > > > >> > static void end_swap_bio_read(struct bio *bio) > > > >> > { > > > >> > struct page *page = bio->bi_io_vec[0].bv_page; > > > >> > @@ -81,49 +129,7 @@ static void end_swap_bio_read(struct bio *bio) > > > >> > } > > > >> > > > > >> > SetPageUptodate(page); > > > >> > - > > > >> > - /* > > > >> > -* There is no guarantee that the page is in swap cache - the > > > >> > software > > > >> > -* suspend code (at least) uses end_swap_bio_read() against a > > > >> > non- > > > >> > -* swapcache page. So we must check PG_swapcache before > > > >> > proceeding with > > > >> > -* this optimization. > > > >> > -*/ > > > >> > - if (likely(PageSwapCache(page))) { > > > >> > - struct swap_info_struct *sis; > > > >> > - > > > >> > - sis = page_swap_info(page); > > > >> > - if (sis->flags & SWP_BLKDEV) { > > > >> > - /* > > > >> > -* The swap subsystem performs lazy swap slot > > > >> > freeing, > > > >> > -* expecting that the page will be swapped out > > > >> > again. > > > >> > -* So we can avoid an unnecessary write if the > > > >> > page > > > >> > -* isn't redirtied. > > > >> > -* This is good for real swap storage because we > > > >> > can > > > >> > -*
Re: [PATCH] zram: revive swap_slot_free_notify
On Wed, Mar 23, 2016 at 01:45:34PM +0900, Joonsoo Kim wrote: > On Tue, Mar 22, 2016 at 11:06:29PM +0900, Minchan Kim wrote: > > On Tue, Mar 22, 2016 at 05:20:08PM +0900, Joonsoo Kim wrote: > > > 2016-03-22 17:00 GMT+09:00 Minchan Kim : > > > > On Tue, Mar 22, 2016 at 02:08:59PM +0900, Joonsoo Kim wrote: > > > >> On Fri, Mar 18, 2016 at 04:58:31PM +0900, Minchan Kim wrote: > > > >> > "remove compressed copy from zram in-memory" > > > >> > applied swap_slot_free_notify call in *end_swap_bio_read* to > > > >> > remove duplicated memory between zram and memory. > > > >> > > > > >> > However, with introducing rw_page in zram <8c7f01025f7b> > > > >> > "zram: implement rw_page operation of zram", it became void > > > >> > because rw_page doesn't need bio. > > > >> > > > > >> > This patch restores the function for rw_page. > > > >> > > > > >> > Signed-off-by: Minchan Kim > > > >> > --- > > > >> > mm/page_io.c | 93 > > > >> > > > > >> > 1 file changed, 50 insertions(+), 43 deletions(-) > > > >> > > > > >> > diff --git a/mm/page_io.c b/mm/page_io.c > > > >> > index ff74e512f029..18aac7819cc9 100644 > > > >> > --- a/mm/page_io.c > > > >> > +++ b/mm/page_io.c > > > >> > @@ -66,6 +66,54 @@ void end_swap_bio_write(struct bio *bio) > > > >> > bio_put(bio); > > > >> > } > > > >> > > > > >> > +static void swap_slot_free_notify(struct page *page) > > > >> > +{ > > > >> > + struct swap_info_struct *sis; > > > >> > + struct gendisk *disk; > > > >> > + > > > >> > + /* > > > >> > +* There is no guarantee that the page is in swap cache - the > > > >> > software > > > >> > +* suspend code (at least) uses end_swap_bio_read() against a > > > >> > non- > > > >> > +* swapcache page. So we must check PG_swapcache before > > > >> > proceeding with > > > >> > +* this optimization. > > > >> > +*/ > > > >> > + if (unlikely(!PageSwapCache(page))) > > > >> > + return; > > > >> > + > > > >> > + sis = page_swap_info(page); > > > >> > + if (!(sis->flags & SWP_BLKDEV)) > > > >> > + return; > > > >> > + > > > >> > + /* > > > >> > +* The swap subsystem performs lazy swap slot freeing, > > > >> > +* expecting that the page will be swapped out again. > > > >> > +* So we can avoid an unnecessary write if the page > > > >> > +* isn't redirtied. > > > >> > +* This is good for real swap storage because we can > > > >> > +* reduce unnecessary I/O and enhance wear-leveling > > > >> > +* if an SSD is used as the as swap device. > > > >> > +* But if in-memory swap device (eg zram) is used, > > > >> > +* this causes a duplicated copy between uncompressed > > > >> > +* data in VM-owned memory and compressed data in > > > >> > +* zram-owned memory. So let's free zram-owned memory > > > >> > +* and make the VM-owned decompressed page *dirty*, > > > >> > +* so the page should be swapped out somewhere again if > > > >> > +* we again wish to reclaim it. > > > >> > +*/ > > > >> > + disk = sis->bdev->bd_disk; > > > >> > + if (disk->fops->swap_slot_free_notify) { > > > >> > + swp_entry_t entry; > > > >> > + unsigned long offset; > > > >> > + > > > >> > + entry.val = page_private(page); > > > >> > + offset = swp_offset(entry); > > > >> > + > > > >> > + SetPageDirty(page); > > > >> > + disk->fops->swap_slot_free_notify(sis->bdev, > > > >> > + offset); > > > >> > + } > > > >> > +} > > > >> > + > > > >> > static void end_swap_bio_read(struct bio *bio) > > > >> > { > > > >> > struct page *page = bio->bi_io_vec[0].bv_page; > > > >> > @@ -81,49 +129,7 @@ static void end_swap_bio_read(struct bio *bio) > > > >> > } > > > >> > > > > >> > SetPageUptodate(page); > > > >> > - > > > >> > - /* > > > >> > -* There is no guarantee that the page is in swap cache - the > > > >> > software > > > >> > -* suspend code (at least) uses end_swap_bio_read() against a > > > >> > non- > > > >> > -* swapcache page. So we must check PG_swapcache before > > > >> > proceeding with > > > >> > -* this optimization. > > > >> > -*/ > > > >> > - if (likely(PageSwapCache(page))) { > > > >> > - struct swap_info_struct *sis; > > > >> > - > > > >> > - sis = page_swap_info(page); > > > >> > - if (sis->flags & SWP_BLKDEV) { > > > >> > - /* > > > >> > -* The swap subsystem performs lazy swap slot > > > >> > freeing, > > > >> > -* expecting that the page will be swapped out > > > >> > again. > > > >> > -* So we can avoid an unnecessary write if the > > > >> > page > > > >> > -* isn't redirtied. > > > >> > -* This is good for real swap storage because we > > > >> > can > > > >> > -* reduce unnecessary I/O and enhance > > >
Re: [PATCH] mmc: Provide tracepoints for request processing
On 25 March 2016 at 22:07, Jens Axboewrote: > On 03/25/2016 01:32 AM, Baolin Wang wrote: >> >> On 24 March 2016 at 22:08, Jens Axboe wrote: >>> >>> On 03/24/2016 05:54 AM, Baolin Wang wrote: This patch provides some tracepoints for the lifecycle of a request from fetching to completion to help with performance analysis of MMC subsystem. >>> >>> >>> >>> Most of these already exist as block layer trace points, why do we need >>> mmc >>> specific ones? >> >> >> Currently the MMC core does not have any tracepoints for use with >> ftrace. These are very useful as they provide a very low overhead >> runtime controllable way of getting diagnostics from the system which >> is capable of recording a great deal of information without impacting >> system performance. We have tracepoints in the block layer so we can >> do some trace of MMC but none in MMC itself so adding some where >> appropriate would help people follow the activity of subsystem. > > > But more than half of the trace points you added, those are DIRECTLY related > to the block event. So what you are saying makes little sense. I see you > resend it with the same trace points, I'll comment on that mail. OK. I'll address your comments on that new mail. Thanks. > > -- > Jens Axboe > -- Baolin.wang Best Regards
Re: [PATCH] mmc: Provide tracepoints for request processing
On 25 March 2016 at 22:07, Jens Axboe wrote: > On 03/25/2016 01:32 AM, Baolin Wang wrote: >> >> On 24 March 2016 at 22:08, Jens Axboe wrote: >>> >>> On 03/24/2016 05:54 AM, Baolin Wang wrote: This patch provides some tracepoints for the lifecycle of a request from fetching to completion to help with performance analysis of MMC subsystem. >>> >>> >>> >>> Most of these already exist as block layer trace points, why do we need >>> mmc >>> specific ones? >> >> >> Currently the MMC core does not have any tracepoints for use with >> ftrace. These are very useful as they provide a very low overhead >> runtime controllable way of getting diagnostics from the system which >> is capable of recording a great deal of information without impacting >> system performance. We have tracepoints in the block layer so we can >> do some trace of MMC but none in MMC itself so adding some where >> appropriate would help people follow the activity of subsystem. > > > But more than half of the trace points you added, those are DIRECTLY related > to the block event. So what you are saying makes little sense. I see you > resend it with the same trace points, I'll comment on that mail. OK. I'll address your comments on that new mail. Thanks. > > -- > Jens Axboe > -- Baolin.wang Best Regards
[PATCH V2] staging: dgnc: replace dgnc_offset_table with bit shift.
the dgnc_offset_table has a same value with (1 << port). So I tried to replace dgnc_offset_table array with 1 << port. And also there are redundant assignments(tmp and current_port) inside while loop for checking uart port, and remove them. Signed-off-by: Daeseok Youn--- V2: clean up useless variables and increasing port value is just for traversing all port with uart_poll. So It need to replace 'continue' with 'break' in switch statement and last of this function, move onto next port. drivers/staging/dgnc/dgnc_neo.c | 44 +++-- 1 file changed, 12 insertions(+), 32 deletions(-) diff --git a/drivers/staging/dgnc/dgnc_neo.c b/drivers/staging/dgnc/dgnc_neo.c index d732e6e..6b57c44 100644 --- a/drivers/staging/dgnc/dgnc_neo.c +++ b/drivers/staging/dgnc/dgnc_neo.c @@ -77,9 +77,6 @@ struct board_ops dgnc_neo_ops = { .send_immediate_char = neo_send_immediate_char }; -static uint dgnc_offset_table[8] = { 0x01, 0x02, 0x04, 0x08, -0x10, 0x20, 0x40, 0x80 }; - /* * This function allows calls to ensure that all outstanding * PCI writes have been completed, by doing a PCI read against @@ -923,9 +920,7 @@ static irqreturn_t neo_intr(int irq, void *voidbrd) struct dgnc_board *brd = voidbrd; struct channel_t *ch; int port = 0; - int type = 0; - int current_port; - u32 tmp; + int type; u32 uart_poll; unsigned long flags; unsigned long flags2; @@ -960,29 +955,12 @@ static irqreturn_t neo_intr(int irq, void *voidbrd) /* At this point, we have at least SOMETHING to service, dig further... */ - current_port = 0; - /* Loop on each port */ while ((uart_poll & 0xff) != 0) { - tmp = uart_poll; - - /* Check current port to see if it has interrupt pending */ - if ((tmp & dgnc_offset_table[current_port]) != 0) { - port = current_port; - type = tmp >> (8 + (port * 3)); - type &= 0x7; - } else { - current_port++; - continue; - } - - /* Remove this port + type from uart_poll */ - uart_poll &= ~(dgnc_offset_table[port]); + type = uart_poll >> (8 + (port * 3)); + type &= 0x7; - if (!type) { - /* If no type, just ignore it, and move onto next port */ - continue; - } + uart_poll &= ~(0x01 << port); /* Switch on type of interrupt we have */ switch (type) { @@ -994,7 +972,7 @@ static irqreturn_t neo_intr(int irq, void *voidbrd) /* Verify the port is in range. */ if (port >= brd->nasync) - continue; + break; ch = brd->channels[port]; neo_copy_data_from_uart_to_queue(ch); @@ -1004,14 +982,14 @@ static irqreturn_t neo_intr(int irq, void *voidbrd) dgnc_check_queue_flow_control(ch); spin_unlock_irqrestore(>ch_lock, flags2); - continue; + break; case UART_17158_RX_LINE_STATUS: /* * RXRDY and RX LINE Status (logic OR of LSR[4:1]) */ neo_parse_lsr(brd, port); - continue; + break; case UART_17158_TXRDY: /* @@ -1027,14 +1005,14 @@ static irqreturn_t neo_intr(int irq, void *voidbrd) * it should be, I was getting things like RXDY too. Weird. */ neo_parse_isr(brd, port); - continue; + break; case UART_17158_MSR: /* * MSR or flow control was seen. */ neo_parse_isr(brd, port); - continue; + break; default: /* @@ -1043,8 +1021,10 @@ static irqreturn_t neo_intr(int irq, void *voidbrd) * these once and awhile. * Its harmless, just ignore it and move on. */ - continue; + break; } + + port++; } /* -- 1.9.1
[PATCH V2] staging: dgnc: replace dgnc_offset_table with bit shift.
the dgnc_offset_table has a same value with (1 << port). So I tried to replace dgnc_offset_table array with 1 << port. And also there are redundant assignments(tmp and current_port) inside while loop for checking uart port, and remove them. Signed-off-by: Daeseok Youn --- V2: clean up useless variables and increasing port value is just for traversing all port with uart_poll. So It need to replace 'continue' with 'break' in switch statement and last of this function, move onto next port. drivers/staging/dgnc/dgnc_neo.c | 44 +++-- 1 file changed, 12 insertions(+), 32 deletions(-) diff --git a/drivers/staging/dgnc/dgnc_neo.c b/drivers/staging/dgnc/dgnc_neo.c index d732e6e..6b57c44 100644 --- a/drivers/staging/dgnc/dgnc_neo.c +++ b/drivers/staging/dgnc/dgnc_neo.c @@ -77,9 +77,6 @@ struct board_ops dgnc_neo_ops = { .send_immediate_char = neo_send_immediate_char }; -static uint dgnc_offset_table[8] = { 0x01, 0x02, 0x04, 0x08, -0x10, 0x20, 0x40, 0x80 }; - /* * This function allows calls to ensure that all outstanding * PCI writes have been completed, by doing a PCI read against @@ -923,9 +920,7 @@ static irqreturn_t neo_intr(int irq, void *voidbrd) struct dgnc_board *brd = voidbrd; struct channel_t *ch; int port = 0; - int type = 0; - int current_port; - u32 tmp; + int type; u32 uart_poll; unsigned long flags; unsigned long flags2; @@ -960,29 +955,12 @@ static irqreturn_t neo_intr(int irq, void *voidbrd) /* At this point, we have at least SOMETHING to service, dig further... */ - current_port = 0; - /* Loop on each port */ while ((uart_poll & 0xff) != 0) { - tmp = uart_poll; - - /* Check current port to see if it has interrupt pending */ - if ((tmp & dgnc_offset_table[current_port]) != 0) { - port = current_port; - type = tmp >> (8 + (port * 3)); - type &= 0x7; - } else { - current_port++; - continue; - } - - /* Remove this port + type from uart_poll */ - uart_poll &= ~(dgnc_offset_table[port]); + type = uart_poll >> (8 + (port * 3)); + type &= 0x7; - if (!type) { - /* If no type, just ignore it, and move onto next port */ - continue; - } + uart_poll &= ~(0x01 << port); /* Switch on type of interrupt we have */ switch (type) { @@ -994,7 +972,7 @@ static irqreturn_t neo_intr(int irq, void *voidbrd) /* Verify the port is in range. */ if (port >= brd->nasync) - continue; + break; ch = brd->channels[port]; neo_copy_data_from_uart_to_queue(ch); @@ -1004,14 +982,14 @@ static irqreturn_t neo_intr(int irq, void *voidbrd) dgnc_check_queue_flow_control(ch); spin_unlock_irqrestore(>ch_lock, flags2); - continue; + break; case UART_17158_RX_LINE_STATUS: /* * RXRDY and RX LINE Status (logic OR of LSR[4:1]) */ neo_parse_lsr(brd, port); - continue; + break; case UART_17158_TXRDY: /* @@ -1027,14 +1005,14 @@ static irqreturn_t neo_intr(int irq, void *voidbrd) * it should be, I was getting things like RXDY too. Weird. */ neo_parse_isr(brd, port); - continue; + break; case UART_17158_MSR: /* * MSR or flow control was seen. */ neo_parse_isr(brd, port); - continue; + break; default: /* @@ -1043,8 +1021,10 @@ static irqreturn_t neo_intr(int irq, void *voidbrd) * these once and awhile. * Its harmless, just ignore it and move on. */ - continue; + break; } + + port++; } /* -- 1.9.1
Re: [PATCH HACK 1/6] livepatch-test: Add more cases
* Balbir Singh[2016-03-26 18:11:22]: > On Fri, Mar 25, 2016 at 3:37 AM, Kamalesh Babulal > wrote: > > * Michael Ellerman [2016-03-24 22:04:00]: > > > >> Not for merging. > >> > > > > Hi Michael, > > > > Loading the livepatch sample module, trigger following warning > > > > The #if IS_MODULE(CONFIG_SCSI) code is buggy, you probably have > CONFIG_SCSI=y, make it M or you can fix the code yourself. I had the > same issue while testing > > BTW, the tests worked fine with the changes proposed by Michael. > Thanks, It helped. I was able to load the sample livepatch module with proposed changes. Thanks, Kamalesh.
Re: [PATCH HACK 1/6] livepatch-test: Add more cases
* Balbir Singh [2016-03-26 18:11:22]: > On Fri, Mar 25, 2016 at 3:37 AM, Kamalesh Babulal > wrote: > > * Michael Ellerman [2016-03-24 22:04:00]: > > > >> Not for merging. > >> > > > > Hi Michael, > > > > Loading the livepatch sample module, trigger following warning > > > > The #if IS_MODULE(CONFIG_SCSI) code is buggy, you probably have > CONFIG_SCSI=y, make it M or you can fix the code yourself. I had the > same issue while testing > > BTW, the tests worked fine with the changes proposed by Michael. > Thanks, It helped. I was able to load the sample livepatch module with proposed changes. Thanks, Kamalesh.
Re: [PATCH v2] ARM: exynos_defconfig: Enable Samsung media platform drivers as modules
On 25.03.2016 12:15, Javier Martinez Canillas wrote: >> >> How about doing the same for multi_v7? >> > > I didn't consider multi_v7 because media drivers aren't necessary for booting > the boards and so it could increase build times for not real benefits in most > machines. But I can enable it in multi_v7 as a follow-up if you think that it > makes sense there too. I consider use cases of multi_v7 the same as exynos (except the difference in policy: use always modules). This means that if it makes sense to enable some media drivers on exynos (for build coverage, boot testing and real usage) then it makes sense to do the same for multi_v7. In ideal future we would move entirely from exynos-specific image to one common image for testing: the multi_v7. It would make things simpler. Best regards, Krzysztof
Re: [PATCH v2] ARM: exynos_defconfig: Enable Samsung media platform drivers as modules
On 25.03.2016 12:15, Javier Martinez Canillas wrote: >> >> How about doing the same for multi_v7? >> > > I didn't consider multi_v7 because media drivers aren't necessary for booting > the boards and so it could increase build times for not real benefits in most > machines. But I can enable it in multi_v7 as a follow-up if you think that it > makes sense there too. I consider use cases of multi_v7 the same as exynos (except the difference in policy: use always modules). This means that if it makes sense to enable some media drivers on exynos (for build coverage, boot testing and real usage) then it makes sense to do the same for multi_v7. In ideal future we would move entirely from exynos-specific image to one common image for testing: the multi_v7. It would make things simpler. Best regards, Krzysztof
Re: [PATCH] brcmfmac: sdio: remove unused variable retry_limit
Hi All, On Mon, Mar 21, 2016 at 4:34 AM, Colin Kingwrote: > From: Colin Ian King > > retry_limit has never been used during the life of this driver, so > we may as well remove it as it is redundant. > > Signed-off-by: Colin Ian King Looks right to me. Reviewed-by: Julian Calaby > --- > drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c | 3 --- > 1 file changed, 3 deletions(-) > > diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c > b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c > index 43fd3f4..cd92ba7 100644 > --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c > +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c > @@ -535,9 +535,6 @@ static int qcount[NUMPRIO]; > > #define RETRYCHAN(chan) ((chan) == SDPCM_EVENT_CHANNEL) > > -/* Retry count for register access failures */ > -static const uint retry_limit = 2; > - > /* Limit on rounding up frames */ > static const uint max_roundup = 512; > > -- > 2.7.3 > > -- > To unsubscribe from this list: send the line "unsubscribe linux-wireless" in > the body of a message to majord...@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html -- Julian Calaby Email: julian.cal...@gmail.com Profile: http://www.google.com/profiles/julian.calaby/
Re: [PATCH] brcmfmac: sdio: remove unused variable retry_limit
Hi All, On Mon, Mar 21, 2016 at 4:34 AM, Colin King wrote: > From: Colin Ian King > > retry_limit has never been used during the life of this driver, so > we may as well remove it as it is redundant. > > Signed-off-by: Colin Ian King Looks right to me. Reviewed-by: Julian Calaby > --- > drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c | 3 --- > 1 file changed, 3 deletions(-) > > diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c > b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c > index 43fd3f4..cd92ba7 100644 > --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c > +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c > @@ -535,9 +535,6 @@ static int qcount[NUMPRIO]; > > #define RETRYCHAN(chan) ((chan) == SDPCM_EVENT_CHANNEL) > > -/* Retry count for register access failures */ > -static const uint retry_limit = 2; > - > /* Limit on rounding up frames */ > static const uint max_roundup = 512; > > -- > 2.7.3 > > -- > To unsubscribe from this list: send the line "unsubscribe linux-wireless" in > the body of a message to majord...@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html -- Julian Calaby Email: julian.cal...@gmail.com Profile: http://www.google.com/profiles/julian.calaby/
Re: [PATCH] Staging: rtl8723au: Remove function rtw_enqueue_{recvbuf23a/recvbuf23a_to_head}
Hi All, On Sat, Mar 26, 2016 at 5:24 PM, Bhumika Goyalwrote: > The functions rtw_enqueue_recvbuf23a and rtw_enqueue_recvbuf23a_to_head > are never used anywhere in the kernel. So, remove their definition and > prototype. > Grepped to find occurences. > > Signed-off-by: Bhumika Goyal Looks right to me. Reviewed-by: Julian Calaby > --- > drivers/staging/rtl8723au/core/rtw_recv.c| 25 - > drivers/staging/rtl8723au/include/rtw_recv.h | 2 -- > 2 files changed, 27 deletions(-) > > diff --git a/drivers/staging/rtl8723au/core/rtw_recv.c > b/drivers/staging/rtl8723au/core/rtw_recv.c > index 989ed07..150dabc 100644 > --- a/drivers/staging/rtl8723au/core/rtw_recv.c > +++ b/drivers/staging/rtl8723au/core/rtw_recv.c > @@ -211,31 +211,6 @@ u32 rtw_free_uc_swdec_pending_queue23a(struct > rtw_adapter *adapter) > return cnt; > } > > -int rtw_enqueue_recvbuf23a_to_head(struct recv_buf *precvbuf, struct > rtw_queue *queue) > -{ > - spin_lock_bh(>lock); > - > - list_del_init(>list); > - list_add(>list, get_list_head(queue)); > - > - spin_unlock_bh(>lock); > - > - return _SUCCESS; > -} > - > -int rtw_enqueue_recvbuf23a(struct recv_buf *precvbuf, struct rtw_queue > *queue) > -{ > - unsigned long irqL; > - > - spin_lock_irqsave(>lock, irqL); > - > - list_del_init(>list); > - > - list_add_tail(>list, get_list_head(queue)); > - spin_unlock_irqrestore(>lock, irqL); > - return _SUCCESS; > -} > - > struct recv_buf *rtw_dequeue_recvbuf23a (struct rtw_queue *queue) > { > unsigned long irqL; > diff --git a/drivers/staging/rtl8723au/include/rtw_recv.h > b/drivers/staging/rtl8723au/include/rtw_recv.h > index dc784be..85a5edb 100644 > --- a/drivers/staging/rtl8723au/include/rtw_recv.h > +++ b/drivers/staging/rtl8723au/include/rtw_recv.h > @@ -279,8 +279,6 @@ int rtw_enqueue_recvframe23a(struct recv_frame > *precvframe, struct rtw_queue *qu > > u32 rtw_free_uc_swdec_pending_queue23a(struct rtw_adapter *adapter); > > -int rtw_enqueue_recvbuf23a_to_head(struct recv_buf *precvbuf, struct > rtw_queue *queue); > -int rtw_enqueue_recvbuf23a(struct recv_buf *precvbuf, struct rtw_queue > *queue); > struct recv_buf *rtw_dequeue_recvbuf23a(struct rtw_queue *queue); > > void rtw_reordering_ctrl_timeout_handler23a(unsigned long pcontext); > -- > 1.9.1 > > -- > To unsubscribe from this list: send the line "unsubscribe linux-wireless" in > the body of a message to majord...@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html -- Julian Calaby Email: julian.cal...@gmail.com Profile: http://www.google.com/profiles/julian.calaby/
[PATCH v2] regulator: s2mps11: Fix invalid selector mask and voltages for buck9
The buck9 regulator of S2MPS11 PMIC had incorrect vsel_mask (0xff instead of 0x1f) thus reading entire register as buck9's voltage. This effectively caused regulator core to interpret values as higher voltages than they were and then to set real voltage much lower than intended. The buck9 provides power to other regulators, including LDO13 and LDO19 which supply the MMC2 (SD card). On Odroid XU3/XU4 the lower voltage caused SD card detection errors on Odroid XU3/XU4: mmc1: card never left busy state mmc1: error -110 whilst initialising SD card During driver probe the regulator core was checking whether initial voltage matches the constraints. With incorrect vsel_mask of 0xff and default value of 0x50, the core interpreted this as 5 V which is outside of constraints (3-3.775 V). Then the regulator core was adjusting the voltage to match the constraints. With incorrect vsel_mask this new voltage mapped to a vere low voltage in the driver. Fixes: cb74685ecb39 ("regulator: s2mps11: Add samsung s2mps11 regulator driver") Cc:Signed-off-by: Krzysztof Kozlowski Reviewed-by: Javier Martinez Canillas Tested-by: Javier Martinez Canillas --- Changes since v1: 1. The driver did not lack minimal linear selector but the selector mask was wrong. The effect was exactly the same - writing values corresponding to a lower voltage in reality. Instead of setting '.linear_min_sel', set the '.vsel_mask' to a proper value. 2. Rewrite title/commit. 3. Minor changes after Javier's review. 4. Add Javier's review/tested by. The issue can be reproduced on next-20160324 with bae4fdc88d7f7dda1 (regulator: core: Ensure we are at least in bounds for our constraints). --- drivers/regulator/s2mps11.c | 28 ++-- include/linux/mfd/samsung/s2mps11.h | 2 ++ 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c index d24e2c783dc5..6dfa3502e1f1 100644 --- a/drivers/regulator/s2mps11.c +++ b/drivers/regulator/s2mps11.c @@ -308,7 +308,7 @@ static struct regulator_ops s2mps11_buck_ops = { .enable_mask= S2MPS11_ENABLE_MASK \ } -#define regulator_desc_s2mps11_buck6_10(num, min, step) { \ +#define regulator_desc_s2mps11_buck67810(num, min, step) { \ .name = "BUCK"#num, \ .id = S2MPS11_BUCK##num,\ .ops= _buck_ops,\ @@ -324,6 +324,22 @@ static struct regulator_ops s2mps11_buck_ops = { .enable_mask= S2MPS11_ENABLE_MASK \ } +#define regulator_desc_s2mps11_buck9 { \ + .name = "BUCK9", \ + .id = S2MPS11_BUCK9,\ + .ops= _buck_ops,\ + .type = REGULATOR_VOLTAGE,\ + .owner = THIS_MODULE, \ + .min_uV = MIN_3000_MV, \ + .uV_step= STEP_25_MV, \ + .n_voltages = S2MPS11_BUCK9_N_VOLTAGES, \ + .ramp_delay = S2MPS11_RAMP_DELAY, \ + .vsel_reg = S2MPS11_REG_B9CTRL2, \ + .vsel_mask = S2MPS11_BUCK9_VSEL_MASK, \ + .enable_reg = S2MPS11_REG_B9CTRL1, \ + .enable_mask= S2MPS11_ENABLE_MASK \ +} + static const struct regulator_desc s2mps11_regulators[] = { regulator_desc_s2mps11_ldo(1, STEP_25_MV), regulator_desc_s2mps11_ldo(2, STEP_50_MV), @@ -368,11 +384,11 @@ static const struct regulator_desc s2mps11_regulators[] = { regulator_desc_s2mps11_buck1_4(3), regulator_desc_s2mps11_buck1_4(4), regulator_desc_s2mps11_buck5, - regulator_desc_s2mps11_buck6_10(6, MIN_600_MV, STEP_6_25_MV), - regulator_desc_s2mps11_buck6_10(7, MIN_600_MV, STEP_6_25_MV), - regulator_desc_s2mps11_buck6_10(8, MIN_600_MV, STEP_6_25_MV), - regulator_desc_s2mps11_buck6_10(9, MIN_3000_MV, STEP_25_MV), - regulator_desc_s2mps11_buck6_10(10, MIN_750_MV, STEP_12_5_MV), + regulator_desc_s2mps11_buck67810(6, MIN_600_MV, STEP_6_25_MV), + regulator_desc_s2mps11_buck67810(7, MIN_600_MV, STEP_6_25_MV), + regulator_desc_s2mps11_buck67810(8, MIN_600_MV, STEP_6_25_MV), + regulator_desc_s2mps11_buck9, + regulator_desc_s2mps11_buck67810(10, MIN_750_MV, STEP_12_5_MV), }; static struct regulator_ops s2mps14_reg_ops; diff --git a/include/linux/mfd/samsung/s2mps11.h b/include/linux/mfd/samsung/s2mps11.h index b288965e8101..2c14eeca46f0 100644 --- a/include/linux/mfd/samsung/s2mps11.h +++ b/include/linux/mfd/samsung/s2mps11.h @@ -173,10 +173,12
Re: [PATCH] Staging: rtl8723au: Remove function rtw_enqueue_{recvbuf23a/recvbuf23a_to_head}
Hi All, On Sat, Mar 26, 2016 at 5:24 PM, Bhumika Goyal wrote: > The functions rtw_enqueue_recvbuf23a and rtw_enqueue_recvbuf23a_to_head > are never used anywhere in the kernel. So, remove their definition and > prototype. > Grepped to find occurences. > > Signed-off-by: Bhumika Goyal Looks right to me. Reviewed-by: Julian Calaby > --- > drivers/staging/rtl8723au/core/rtw_recv.c| 25 - > drivers/staging/rtl8723au/include/rtw_recv.h | 2 -- > 2 files changed, 27 deletions(-) > > diff --git a/drivers/staging/rtl8723au/core/rtw_recv.c > b/drivers/staging/rtl8723au/core/rtw_recv.c > index 989ed07..150dabc 100644 > --- a/drivers/staging/rtl8723au/core/rtw_recv.c > +++ b/drivers/staging/rtl8723au/core/rtw_recv.c > @@ -211,31 +211,6 @@ u32 rtw_free_uc_swdec_pending_queue23a(struct > rtw_adapter *adapter) > return cnt; > } > > -int rtw_enqueue_recvbuf23a_to_head(struct recv_buf *precvbuf, struct > rtw_queue *queue) > -{ > - spin_lock_bh(>lock); > - > - list_del_init(>list); > - list_add(>list, get_list_head(queue)); > - > - spin_unlock_bh(>lock); > - > - return _SUCCESS; > -} > - > -int rtw_enqueue_recvbuf23a(struct recv_buf *precvbuf, struct rtw_queue > *queue) > -{ > - unsigned long irqL; > - > - spin_lock_irqsave(>lock, irqL); > - > - list_del_init(>list); > - > - list_add_tail(>list, get_list_head(queue)); > - spin_unlock_irqrestore(>lock, irqL); > - return _SUCCESS; > -} > - > struct recv_buf *rtw_dequeue_recvbuf23a (struct rtw_queue *queue) > { > unsigned long irqL; > diff --git a/drivers/staging/rtl8723au/include/rtw_recv.h > b/drivers/staging/rtl8723au/include/rtw_recv.h > index dc784be..85a5edb 100644 > --- a/drivers/staging/rtl8723au/include/rtw_recv.h > +++ b/drivers/staging/rtl8723au/include/rtw_recv.h > @@ -279,8 +279,6 @@ int rtw_enqueue_recvframe23a(struct recv_frame > *precvframe, struct rtw_queue *qu > > u32 rtw_free_uc_swdec_pending_queue23a(struct rtw_adapter *adapter); > > -int rtw_enqueue_recvbuf23a_to_head(struct recv_buf *precvbuf, struct > rtw_queue *queue); > -int rtw_enqueue_recvbuf23a(struct recv_buf *precvbuf, struct rtw_queue > *queue); > struct recv_buf *rtw_dequeue_recvbuf23a(struct rtw_queue *queue); > > void rtw_reordering_ctrl_timeout_handler23a(unsigned long pcontext); > -- > 1.9.1 > > -- > To unsubscribe from this list: send the line "unsubscribe linux-wireless" in > the body of a message to majord...@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html -- Julian Calaby Email: julian.cal...@gmail.com Profile: http://www.google.com/profiles/julian.calaby/
[PATCH v2] regulator: s2mps11: Fix invalid selector mask and voltages for buck9
The buck9 regulator of S2MPS11 PMIC had incorrect vsel_mask (0xff instead of 0x1f) thus reading entire register as buck9's voltage. This effectively caused regulator core to interpret values as higher voltages than they were and then to set real voltage much lower than intended. The buck9 provides power to other regulators, including LDO13 and LDO19 which supply the MMC2 (SD card). On Odroid XU3/XU4 the lower voltage caused SD card detection errors on Odroid XU3/XU4: mmc1: card never left busy state mmc1: error -110 whilst initialising SD card During driver probe the regulator core was checking whether initial voltage matches the constraints. With incorrect vsel_mask of 0xff and default value of 0x50, the core interpreted this as 5 V which is outside of constraints (3-3.775 V). Then the regulator core was adjusting the voltage to match the constraints. With incorrect vsel_mask this new voltage mapped to a vere low voltage in the driver. Fixes: cb74685ecb39 ("regulator: s2mps11: Add samsung s2mps11 regulator driver") Cc: Signed-off-by: Krzysztof Kozlowski Reviewed-by: Javier Martinez Canillas Tested-by: Javier Martinez Canillas --- Changes since v1: 1. The driver did not lack minimal linear selector but the selector mask was wrong. The effect was exactly the same - writing values corresponding to a lower voltage in reality. Instead of setting '.linear_min_sel', set the '.vsel_mask' to a proper value. 2. Rewrite title/commit. 3. Minor changes after Javier's review. 4. Add Javier's review/tested by. The issue can be reproduced on next-20160324 with bae4fdc88d7f7dda1 (regulator: core: Ensure we are at least in bounds for our constraints). --- drivers/regulator/s2mps11.c | 28 ++-- include/linux/mfd/samsung/s2mps11.h | 2 ++ 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c index d24e2c783dc5..6dfa3502e1f1 100644 --- a/drivers/regulator/s2mps11.c +++ b/drivers/regulator/s2mps11.c @@ -308,7 +308,7 @@ static struct regulator_ops s2mps11_buck_ops = { .enable_mask= S2MPS11_ENABLE_MASK \ } -#define regulator_desc_s2mps11_buck6_10(num, min, step) { \ +#define regulator_desc_s2mps11_buck67810(num, min, step) { \ .name = "BUCK"#num, \ .id = S2MPS11_BUCK##num,\ .ops= _buck_ops,\ @@ -324,6 +324,22 @@ static struct regulator_ops s2mps11_buck_ops = { .enable_mask= S2MPS11_ENABLE_MASK \ } +#define regulator_desc_s2mps11_buck9 { \ + .name = "BUCK9", \ + .id = S2MPS11_BUCK9,\ + .ops= _buck_ops,\ + .type = REGULATOR_VOLTAGE,\ + .owner = THIS_MODULE, \ + .min_uV = MIN_3000_MV, \ + .uV_step= STEP_25_MV, \ + .n_voltages = S2MPS11_BUCK9_N_VOLTAGES, \ + .ramp_delay = S2MPS11_RAMP_DELAY, \ + .vsel_reg = S2MPS11_REG_B9CTRL2, \ + .vsel_mask = S2MPS11_BUCK9_VSEL_MASK, \ + .enable_reg = S2MPS11_REG_B9CTRL1, \ + .enable_mask= S2MPS11_ENABLE_MASK \ +} + static const struct regulator_desc s2mps11_regulators[] = { regulator_desc_s2mps11_ldo(1, STEP_25_MV), regulator_desc_s2mps11_ldo(2, STEP_50_MV), @@ -368,11 +384,11 @@ static const struct regulator_desc s2mps11_regulators[] = { regulator_desc_s2mps11_buck1_4(3), regulator_desc_s2mps11_buck1_4(4), regulator_desc_s2mps11_buck5, - regulator_desc_s2mps11_buck6_10(6, MIN_600_MV, STEP_6_25_MV), - regulator_desc_s2mps11_buck6_10(7, MIN_600_MV, STEP_6_25_MV), - regulator_desc_s2mps11_buck6_10(8, MIN_600_MV, STEP_6_25_MV), - regulator_desc_s2mps11_buck6_10(9, MIN_3000_MV, STEP_25_MV), - regulator_desc_s2mps11_buck6_10(10, MIN_750_MV, STEP_12_5_MV), + regulator_desc_s2mps11_buck67810(6, MIN_600_MV, STEP_6_25_MV), + regulator_desc_s2mps11_buck67810(7, MIN_600_MV, STEP_6_25_MV), + regulator_desc_s2mps11_buck67810(8, MIN_600_MV, STEP_6_25_MV), + regulator_desc_s2mps11_buck9, + regulator_desc_s2mps11_buck67810(10, MIN_750_MV, STEP_12_5_MV), }; static struct regulator_ops s2mps14_reg_ops; diff --git a/include/linux/mfd/samsung/s2mps11.h b/include/linux/mfd/samsung/s2mps11.h index b288965e8101..2c14eeca46f0 100644 --- a/include/linux/mfd/samsung/s2mps11.h +++ b/include/linux/mfd/samsung/s2mps11.h @@ -173,10 +173,12 @@ enum s2mps11_regulators { #define S2MPS11_LDO_VSEL_MASK 0x3F #define
Re: [PATCH] Staging: rtl8723au: Remove unused functions
Hi All, On Sat, Mar 26, 2016 at 5:14 PM, Bhumika Goyalwrote: > The functions rtw_get_oper_bw23a and rtw_get_oper_ch23aoffset are never > used anywhere in the kernel. So, remove their definition and prototype. > Grepped to find occurences. > > Signed-off-by: Bhumika Goyal Looks right to me. Reviewed-by: Julian Calaby > --- > drivers/staging/rtl8723au/core/rtw_wlan_util.c | 10 -- > drivers/staging/rtl8723au/include/rtw_mlme_ext.h | 2 -- > 2 files changed, 12 deletions(-) > > diff --git a/drivers/staging/rtl8723au/core/rtw_wlan_util.c > b/drivers/staging/rtl8723au/core/rtw_wlan_util.c > index cc2b84b..694cf17 100644 > --- a/drivers/staging/rtl8723au/core/rtw_wlan_util.c > +++ b/drivers/staging/rtl8723au/core/rtw_wlan_util.c > @@ -304,21 +304,11 @@ inline void rtw_set_oper_ch23a(struct rtw_adapter > *adapter, u8 ch) > adapter_to_dvobj(adapter)->oper_channel = ch; > } > > -inline u8 rtw_get_oper_bw23a(struct rtw_adapter *adapter) > -{ > - return adapter_to_dvobj(adapter)->oper_bwmode; > -} > - > inline void rtw_set_oper_bw23a(struct rtw_adapter *adapter, u8 bw) > { > adapter_to_dvobj(adapter)->oper_bwmode = bw; > } > > -inline u8 rtw_get_oper_ch23aoffset(struct rtw_adapter *adapter) > -{ > - return adapter_to_dvobj(adapter)->oper_ch_offset; > -} > - > inline void rtw_set_oper_ch23aoffset23a(struct rtw_adapter *adapter, u8 > offset) > { > adapter_to_dvobj(adapter)->oper_ch_offset = offset; > diff --git a/drivers/staging/rtl8723au/include/rtw_mlme_ext.h > b/drivers/staging/rtl8723au/include/rtw_mlme_ext.h > index ea2a6c9..0e7d3da 100644 > --- a/drivers/staging/rtl8723au/include/rtw_mlme_ext.h > +++ b/drivers/staging/rtl8723au/include/rtw_mlme_ext.h > @@ -461,9 +461,7 @@ void Update23aTblForSoftAP(u8 *bssrateset, u32 > bssratelen); > > u8 rtw_get_oper_ch23a(struct rtw_adapter *adapter); > void rtw_set_oper_ch23a(struct rtw_adapter *adapter, u8 ch); > -u8 rtw_get_oper_bw23a(struct rtw_adapter *adapter); > void rtw_set_oper_bw23a(struct rtw_adapter *adapter, u8 bw); > -u8 rtw_get_oper_ch23aoffset(struct rtw_adapter *adapter); > void rtw_set_oper_ch23aoffset23a(struct rtw_adapter *adapter, u8 offset); > > void set_channel_bwmode23a(struct rtw_adapter *padapter, unsigned char > channel, > -- > 1.9.1 > > -- > To unsubscribe from this list: send the line "unsubscribe linux-wireless" in > the body of a message to majord...@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html -- Julian Calaby Email: julian.cal...@gmail.com Profile: http://www.google.com/profiles/julian.calaby/
Re: [PATCH] Staging: rtl8723au: Remove unused functions
Hi All, On Sat, Mar 26, 2016 at 5:14 PM, Bhumika Goyal wrote: > The functions rtw_get_oper_bw23a and rtw_get_oper_ch23aoffset are never > used anywhere in the kernel. So, remove their definition and prototype. > Grepped to find occurences. > > Signed-off-by: Bhumika Goyal Looks right to me. Reviewed-by: Julian Calaby > --- > drivers/staging/rtl8723au/core/rtw_wlan_util.c | 10 -- > drivers/staging/rtl8723au/include/rtw_mlme_ext.h | 2 -- > 2 files changed, 12 deletions(-) > > diff --git a/drivers/staging/rtl8723au/core/rtw_wlan_util.c > b/drivers/staging/rtl8723au/core/rtw_wlan_util.c > index cc2b84b..694cf17 100644 > --- a/drivers/staging/rtl8723au/core/rtw_wlan_util.c > +++ b/drivers/staging/rtl8723au/core/rtw_wlan_util.c > @@ -304,21 +304,11 @@ inline void rtw_set_oper_ch23a(struct rtw_adapter > *adapter, u8 ch) > adapter_to_dvobj(adapter)->oper_channel = ch; > } > > -inline u8 rtw_get_oper_bw23a(struct rtw_adapter *adapter) > -{ > - return adapter_to_dvobj(adapter)->oper_bwmode; > -} > - > inline void rtw_set_oper_bw23a(struct rtw_adapter *adapter, u8 bw) > { > adapter_to_dvobj(adapter)->oper_bwmode = bw; > } > > -inline u8 rtw_get_oper_ch23aoffset(struct rtw_adapter *adapter) > -{ > - return adapter_to_dvobj(adapter)->oper_ch_offset; > -} > - > inline void rtw_set_oper_ch23aoffset23a(struct rtw_adapter *adapter, u8 > offset) > { > adapter_to_dvobj(adapter)->oper_ch_offset = offset; > diff --git a/drivers/staging/rtl8723au/include/rtw_mlme_ext.h > b/drivers/staging/rtl8723au/include/rtw_mlme_ext.h > index ea2a6c9..0e7d3da 100644 > --- a/drivers/staging/rtl8723au/include/rtw_mlme_ext.h > +++ b/drivers/staging/rtl8723au/include/rtw_mlme_ext.h > @@ -461,9 +461,7 @@ void Update23aTblForSoftAP(u8 *bssrateset, u32 > bssratelen); > > u8 rtw_get_oper_ch23a(struct rtw_adapter *adapter); > void rtw_set_oper_ch23a(struct rtw_adapter *adapter, u8 ch); > -u8 rtw_get_oper_bw23a(struct rtw_adapter *adapter); > void rtw_set_oper_bw23a(struct rtw_adapter *adapter, u8 bw); > -u8 rtw_get_oper_ch23aoffset(struct rtw_adapter *adapter); > void rtw_set_oper_ch23aoffset23a(struct rtw_adapter *adapter, u8 offset); > > void set_channel_bwmode23a(struct rtw_adapter *padapter, unsigned char > channel, > -- > 1.9.1 > > -- > To unsubscribe from this list: send the line "unsubscribe linux-wireless" in > the body of a message to majord...@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html -- Julian Calaby Email: julian.cal...@gmail.com Profile: http://www.google.com/profiles/julian.calaby/